diff --git a/arch/arm/src/samv7/hardware/sam_uart.h b/arch/arm/src/samv7/hardware/sam_uart.h index 7c3e9cdc9e7..dde3c84af32 100644 --- a/arch/arm/src/samv7/hardware/sam_uart.h +++ b/arch/arm/src/samv7/hardware/sam_uart.h @@ -248,7 +248,7 @@ #define UART_CR_STTBRK (1 << 9) /* Bit 9: Start Break (USART, UART mode only) */ #define UART_CR_STPBRK (1 << 10) /* Bit 10: Stop Break (USART, UART mode only) */ #define UART_CR_STTTO (1 << 11) /* Bit 11: Start Time-out (USART, UART mode only) */ -#define UART_CR_REQCLR (1 << 12) /* Bit 12:Request Clear (UART only) */ +#define UART_CR_REQCLR (1 << 12) /* Bit 12: Request Clear (UART only) */ #define UART_CR_SENDA (1 << 12) /* Bit 12: Send Address (USART, UART mode only) */ #define UART_CR_RETTO (1 << 15) /* Bit 15: Rearm Time-out (USART, UART mode only) */ #define UART_CR_RTSEN (1 << 18) /* Bit 18: Request to Send Enable (USART, UART mode only) */ @@ -266,6 +266,8 @@ # define UART_MR_MODE_RS485 (1 << UART_MR_MODE_SHIFT) /* RS485 */ # define UART_MR_MODE_HWHS (2 << UART_MR_MODE_SHIFT) /* Hardware Handshaking */ # define UART_MR_MODE_LON (9 << UART_MR_MODE_SHIFT) /* LON */ +# define UART_MR_MODE_LINMSTR (10 << UART_MR_MODE_SHIFT) /* LIN Master */ +# define UART_MR_MODE_LINSLV (11 << UART_MR_MODE_SHIFT) /* LIN Slave */ # define UART_MR_MODE_SPIMSTR (14 << UART_MR_MODE_SHIFT) /* SPI Master (SPI mode only) */ # define UART_MR_MODE_SPISLV (15 << UART_MR_MODE_SHIFT) /* SPI Slave (SPI mode only) */ diff --git a/arch/arm/src/samv7/sam_serial.c b/arch/arm/src/samv7/sam_serial.c index a8be404699e..798f36e7192 100644 --- a/arch/arm/src/samv7/sam_serial.c +++ b/arch/arm/src/samv7/sam_serial.c @@ -1040,11 +1040,9 @@ static int sam_interrupt(int irq, void *context, FAR void *arg) static int sam_ioctl(struct file *filep, int cmd, unsigned long arg) { -#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_SERIAL_TIOCSERGSTRUCT) struct inode *inode = filep->f_inode; struct uart_dev_s *dev = inode->i_private; -#endif - int ret = OK; + int ret = OK; switch (cmd) { @@ -1223,6 +1221,62 @@ static int sam_ioctl(struct file *filep, int cmd, unsigned long arg) break; #endif /* CONFIG_SERIAL_TERMIOS */ + case TIOCSLINID: + { + /* Switch USART to LIN mode -> Set identifier register -> This will + * issue a LIN header -> Restore USART mode + */ + + struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv; + uint32_t regvalsave = 0; + uint32_t regval = 0; + + /* Save actual configuration */ + + regvalsave = sam_serialin(priv, SAM_UART_MR_OFFSET); + + /* Issue a LIN header (Master mode only) */ + + regval = regvalsave & ~UART_MR_MODE_MASK; + regval |= UART_MR_MODE_LINMSTR; + sam_serialout(priv, SAM_UART_MR_OFFSET, regval); + + /* Reset transaction status bits */ + + sam_serialout(priv, SAM_UART_CR_OFFSET, UART_CR_RSTSTA); + + /* Write LIN ID to trigger header transmission */ + + regval = UART_LINIR_MASK & (uint8_t)arg; + sam_serialout(priv, SAM_UART_LINIR_OFFSET, regval); + + /* Wait until the header is on the wire */ + + do + { + /* Header takes 34 bits to transmit so poll with 34 / 4 = 8 bits + * cycle time + * + * TODO: Interrupt + semaphore can be used instead of busy + * waiting to improve CPU utilization + */ + + usleep((8 * 1000 * 1000) / priv->baud); + + regval = sam_serialin(priv, SAM_UART_SR_OFFSET); + } + while ((regval & UART_INT_LINID) == 0); + + /* Reset transaction status bits */ + + sam_serialout(priv, SAM_UART_CR_OFFSET, UART_CR_RSTSTA); + + /* Restore USART mode */ + + sam_serialout(priv, SAM_UART_MR_OFFSET, regvalsave); + } + break; + default: ret = -ENOTTY; break; diff --git a/include/nuttx/serial/tioctl.h b/include/nuttx/serial/tioctl.h index 436585eda83..ca82e927d55 100644 --- a/include/nuttx/serial/tioctl.h +++ b/include/nuttx/serial/tioctl.h @@ -197,6 +197,10 @@ #define SER_SWAP_ENABLED (1 << 0) /* Enable/disable RX/TX swap */ +/* LIN Protocol Support */ + +#define TIOCSLINID _TIOC(0x0037) /* Master send one LIN header with specified LIN identifier: uint8_t */ + /**************************************************************************** * Public Type Definitions ****************************************************************************/