arch/arm/samv7: initial support for LIN bus communication

Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
Co-authored-by: Petro Karashchenko <petro.karashchenko@gmail.com>
This commit is contained in:
Simon Filgis 2021-12-20 18:16:37 +02:00 committed by Gustavo Henrique Nihei
parent 928426295f
commit 6cc48ff6ff
3 changed files with 64 additions and 4 deletions

View File

@ -248,7 +248,7 @@
#define UART_CR_STTBRK (1 << 9) /* Bit 9: Start Break (USART, UART mode only) */ #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_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_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_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_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) */ #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_RS485 (1 << UART_MR_MODE_SHIFT) /* RS485 */
# define UART_MR_MODE_HWHS (2 << UART_MR_MODE_SHIFT) /* Hardware Handshaking */ # 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_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_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) */ # define UART_MR_MODE_SPISLV (15 << UART_MR_MODE_SHIFT) /* SPI Slave (SPI mode only) */

View File

@ -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) 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 inode *inode = filep->f_inode;
struct uart_dev_s *dev = inode->i_private; struct uart_dev_s *dev = inode->i_private;
#endif int ret = OK;
int ret = OK;
switch (cmd) switch (cmd)
{ {
@ -1223,6 +1221,62 @@ static int sam_ioctl(struct file *filep, int cmd, unsigned long arg)
break; break;
#endif /* CONFIG_SERIAL_TERMIOS */ #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: default:
ret = -ENOTTY; ret = -ENOTTY;
break; break;

View File

@ -197,6 +197,10 @@
#define SER_SWAP_ENABLED (1 << 0) /* Enable/disable RX/TX swap */ #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 * Public Type Definitions
****************************************************************************/ ****************************************************************************/