drivers: uart_sam0: add error support

Adds support for enabling and detecting errors to uart.

Signed-off-by: Arvin Farahmand <arvinf@ip-logix.com>
This commit is contained in:
Arvin Farahmand 2021-04-16 22:03:29 -04:00 committed by Anas Nashif
commit 008bfeb43e

View file

@ -19,6 +19,14 @@
#define SERCOM_USART_CTRLA_MODE_USART_INT_CLK SERCOM_USART_CTRLA_MODE(0x1) #define SERCOM_USART_CTRLA_MODE_USART_INT_CLK SERCOM_USART_CTRLA_MODE(0x1)
#endif #endif
/*
* Interrupt error flag is only supported in devices with
* SERCOM revision 0x500
*/
#if defined(SERCOM_U2201) && (REV_SERCOM == 0x500)
#define SERCOM_REV500
#endif
/* Device constant configuration parameters */ /* Device constant configuration parameters */
struct uart_sam0_dev_cfg { struct uart_sam0_dev_cfg {
SercomUsart *regs; SercomUsart *regs;
@ -718,7 +726,7 @@ static int uart_sam0_fifo_fill(const struct device *dev,
static void uart_sam0_irq_tx_enable(const struct device *dev) static void uart_sam0_irq_tx_enable(const struct device *dev)
{ {
SercomUsart *regs = DEV_CFG(dev)->regs; SercomUsart * const regs = DEV_CFG(dev)->regs;
regs->INTENSET.reg = SERCOM_USART_INTENCLR_DRE; regs->INTENSET.reg = SERCOM_USART_INTENCLR_DRE;
} }
@ -783,7 +791,74 @@ static int uart_sam0_irq_is_pending(const struct device *dev)
return (regs->INTENSET.reg & regs->INTFLAG.reg) != 0; return (regs->INTENSET.reg & regs->INTFLAG.reg) != 0;
} }
static int uart_sam0_irq_update(const struct device *dev) { return 1; } #if defined(SERCOM_REV500)
static void uart_sam0_irq_err_enable(const struct device *dev)
{
SercomUsart * const regs = DEV_CFG(dev)->regs;
regs->INTENSET.reg |= SERCOM_USART_INTENCLR_ERROR;
wait_synchronization(regs);
}
static void uart_sam0_irq_err_disable(const struct device *dev)
{
SercomUsart * const regs = DEV_CFG(dev)->regs;
regs->INTENCLR.reg |= SERCOM_USART_INTENSET_ERROR;
wait_synchronization(regs);
}
#endif
static int uart_sam0_irq_update(const struct device *dev)
{
/* Clear sticky interrupts */
SercomUsart * const regs = DEV_CFG(dev)->regs;
#if defined(SERCOM_REV500)
regs->INTFLAG.reg |= SERCOM_USART_INTENCLR_ERROR
| SERCOM_USART_INTENCLR_RXBRK
| SERCOM_USART_INTENCLR_CTSIC
| SERCOM_USART_INTENCLR_RXS;
#else
regs->INTFLAG.reg |= SERCOM_USART_INTENCLR_RXS;
#endif
return 1;
}
static int uart_sam0_err_check(const struct device *dev)
{
SercomUsart * const regs = DEV_CFG(dev)->regs;
uint32_t err = 0U;
if (regs->STATUS.reg & SERCOM_USART_STATUS_BUFOVF) {
err |= UART_ERROR_OVERRUN;
}
if (regs->STATUS.reg & SERCOM_USART_STATUS_FERR) {
err |= UART_ERROR_PARITY;
}
if (regs->STATUS.reg & SERCOM_USART_STATUS_PERR) {
err |= UART_ERROR_FRAMING;
}
#if defined(SERCOM_REV500)
if (regs->STATUS.reg & SERCOM_USART_STATUS_ISF) {
err |= UART_BREAK;
}
regs->STATUS.reg |= SERCOM_USART_STATUS_BUFOVF
| SERCOM_USART_STATUS_FERR
| SERCOM_USART_STATUS_PERR
| SERCOM_USART_STATUS_ISF;
#else
regs->STATUS.reg |= SERCOM_USART_STATUS_BUFOVF
| SERCOM_USART_STATUS_FERR
| SERCOM_USART_STATUS_PERR;
#endif
wait_synchronization(regs);
return err;
}
static void uart_sam0_irq_callback_set(const struct device *dev, static void uart_sam0_irq_callback_set(const struct device *dev,
uart_irq_callback_user_data_t cb, uart_irq_callback_user_data_t cb,
@ -1032,6 +1107,7 @@ static const struct uart_driver_api uart_sam0_driver_api = {
.poll_out = uart_sam0_poll_out, .poll_out = uart_sam0_poll_out,
.configure = uart_sam0_configure, .configure = uart_sam0_configure,
.config_get = uart_sam0_config_get, .config_get = uart_sam0_config_get,
.err_check = uart_sam0_err_check,
#if CONFIG_UART_INTERRUPT_DRIVEN #if CONFIG_UART_INTERRUPT_DRIVEN
.fifo_fill = uart_sam0_fifo_fill, .fifo_fill = uart_sam0_fifo_fill,
.fifo_read = uart_sam0_fifo_read, .fifo_read = uart_sam0_fifo_read,
@ -1042,6 +1118,10 @@ static const struct uart_driver_api uart_sam0_driver_api = {
.irq_rx_disable = uart_sam0_irq_rx_disable, .irq_rx_disable = uart_sam0_irq_rx_disable,
.irq_rx_ready = uart_sam0_irq_rx_ready, .irq_rx_ready = uart_sam0_irq_rx_ready,
.irq_is_pending = uart_sam0_irq_is_pending, .irq_is_pending = uart_sam0_irq_is_pending,
#if defined(SERCOM_REV500)
.irq_err_enable = uart_sam0_irq_err_enable,
.irq_err_disable = uart_sam0_irq_err_disable,
#endif
.irq_update = uart_sam0_irq_update, .irq_update = uart_sam0_irq_update,
.irq_callback_set = uart_sam0_irq_callback_set, .irq_callback_set = uart_sam0_irq_callback_set,
#endif #endif