diff --git a/arch/arm/src/sam34/chip/sam3u_uart.h b/arch/arm/src/sam34/chip/sam3u_uart.h index bf2dbff2d2..86f48639e2 100644 --- a/arch/arm/src/sam34/chip/sam3u_uart.h +++ b/arch/arm/src/sam34/chip/sam3u_uart.h @@ -319,6 +319,12 @@ #define UART_INT_MANE (1 << 24) /* Bit 24: Manchester Error Interrupt (USART only) */ +#if defined(CONFIG_ARCH_CHIP_SAM4S) +# define UART_INT_ALLINTS 0x010f3fff +#else +# define UART_INT_ALLINTS 0x01083fff +#endif + /* UART Receiver Holding Register */ #if 0 diff --git a/arch/arm/src/sam34/sam_serial.c b/arch/arm/src/sam34/sam_serial.c index 4d28227c63..13867d65b6 100644 --- a/arch/arm/src/sam34/sam_serial.c +++ b/arch/arm/src/sam34/sam_serial.c @@ -332,7 +332,6 @@ struct up_dev_s { uint32_t usartbase; /* Base address of USART registers */ uint32_t baud; /* Configured baud */ - uint32_t imr; /* Saved interrupt mask bits value */ uint32_t sr; /* Saved status bits */ uint8_t irq; /* IRQ associated with this USART */ uint8_t parity; /* 0=none, 1=odd, 2=even */ @@ -607,37 +606,15 @@ static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t valu putreg32(value, priv->usartbase + offset); } -/**************************************************************************** - * Name: up_enableint - ****************************************************************************/ - -static inline void up_enableint(struct up_dev_s *priv) -{ - up_serialout(priv, SAM_UART_IER_OFFSET, priv->imr); -} - -/**************************************************************************** - * Name: up_disableint - ****************************************************************************/ - -static inline void up_disableint(struct up_dev_s *priv) -{ - up_serialout(priv, SAM_UART_IDR_OFFSET, ~priv->imr); -} - /**************************************************************************** * Name: up_restoreusartint ****************************************************************************/ -static void up_restoreusartint(struct up_dev_s *priv, uint32_t imr) +static inline void up_restoreusartint(struct up_dev_s *priv, uint32_t imr) { - /* Save the interrupt mask */ + /* Restore the previous interrupt state */ - priv->imr = imr; - - /* And re-enable interrrupts previoulsy disabled by up_disableallints */ - - up_enableint(priv); + up_serialout(priv, SAM_UART_IMR_OFFSET, imr); } /**************************************************************************** @@ -646,17 +623,22 @@ static void up_restoreusartint(struct up_dev_s *priv, uint32_t imr) static void up_disableallints(struct up_dev_s *priv, uint32_t *imr) { + irqstate_t flags; + + /* The following must be atomic */ + + flags = irqsave(); if (imr) { /* Return the current interrupt mask */ - *imr = priv->imr; + *imr = up_serialin(priv, SAM_UART_IMR_OFFSET); } /* Disable all interrupts */ - priv->imr = 0; - up_disableint(priv); + up_serialout(priv, SAM_UART_IDR_OFFSET, UART_INT_ALLINTS); + irqrestore(flags); } /**************************************************************************** @@ -855,6 +837,7 @@ static int up_interrupt(int irq, void *context) struct uart_dev_s *dev = NULL; struct up_dev_s *priv; uint32_t pending; + uint32_t imr; int passes; bool handled; @@ -917,8 +900,9 @@ static int up_interrupt(int irq, void *context) /* Get the UART/USART status (we are only interested in the unmasked interrupts). */ - priv->sr = up_serialin(priv, SAM_UART_SR_OFFSET); /* Save for error reporting */ - pending = priv->sr & priv->imr; /* Mask out disabled interrupt sources */ + priv->sr = up_serialin(priv, SAM_UART_SR_OFFSET); /* Save for error reporting */ + imr = up_serialin(priv, SAM_UART_IMR_OFFSET); /* Interrupt mask */ + pending = priv->sr & imr; /* Mask out disabled interrupt sources */ /* Handle an incoming, receive byte. RXRDY: At least one complete character * has been received and US_RHR has not yet been read. @@ -1033,14 +1017,12 @@ static void up_rxint(struct uart_dev_s *dev, bool enable) */ #ifndef CONFIG_SUPPRESS_SERIAL_INTS - priv->imr |= UART_INT_RXRDY; - up_enableint(priv); + up_serialout(priv, SAM_UART_IER_OFFSET, UART_INT_RXRDY); #endif } else { - priv->imr &= ~UART_INT_RXRDY; - up_disableint(priv); + up_serialout(priv, SAM_UART_IDR_OFFSET, UART_INT_RXRDY); } } @@ -1093,22 +1075,22 @@ static void up_txint(struct uart_dev_s *dev, bool enable) */ #ifndef CONFIG_SUPPRESS_SERIAL_INTS - priv->imr |= UART_INT_TXRDY; - up_enableint(priv); + up_serialout(priv, SAM_UART_IER_OFFSET, UART_INT_TXRDY); +# if 0 /* Seems to be unnecessary */ /* Fake a TX interrupt here by just calling uart_xmitchars() with * interrupts disabled (note this may recurse). */ uart_xmitchars(dev); +# endif #endif } else { /* Disable the TX interrupt */ - priv->imr &= ~UART_INT_TXRDY; - up_disableint(priv); + up_serialout(priv, SAM_UART_IDR_OFFSET, UART_INT_TXRDY); } irqrestore(flags);