summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-04-08 15:27:31 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-04-08 15:27:31 -0600
commit80839635abdc1c7cff0b3f5d2b31cc300f68fb7b (patch)
tree004491a1aeedc8a011a563aae24421fb605cd895
parent02c33f66c5a8be774034cd40e4125e9323c7b4d8 (diff)
downloadpx4-nuttx-80839635abdc1c7cff0b3f5d2b31cc300f68fb7b.tar.gz
px4-nuttx-80839635abdc1c7cff0b3f5d2b31cc300f68fb7b.tar.bz2
px4-nuttx-80839635abdc1c7cff0b3f5d2b31cc300f68fb7b.zip
SAMA5 Serial: Reading IMR and disabling interrupt must be atomic
-rwxr-xr-xnuttx/ChangeLog4
-rw-r--r--nuttx/arch/arm/src/sam34/sam_serial.c2
-rw-r--r--nuttx/arch/arm/src/sama5/sam_serial.c41
-rw-r--r--nuttx/arch/arm/src/samv7/sam_serial.c2
4 files changed, 35 insertions, 14 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index efa398960..e8383ba8f 100755
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -10122,3 +10122,7 @@
interrupts disabled (2015-04-08)
* arch/arm/src/sama5/sam_serial.c: Backport support for flowcontrol and
termios from SAM3/4 -- UNVERIFIED. (2015-04-08).
+ * arch/arm/src/sam34/sam_serial.c and samv7/sam_serial.c: The IMR
+ register is read-only. This means that sam_restoreints() did not
+ actually re-enable UART interrupts (2015-04-08).
+
diff --git a/nuttx/arch/arm/src/sam34/sam_serial.c b/nuttx/arch/arm/src/sam34/sam_serial.c
index b2f98a582..d264aa349 100644
--- a/nuttx/arch/arm/src/sam34/sam_serial.c
+++ b/nuttx/arch/arm/src/sam34/sam_serial.c
@@ -650,7 +650,7 @@ static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t valu
static inline void up_restoreusartint(struct up_dev_s *priv, uint32_t imr)
{
- /* Restore the previous interrupt state */
+ /* Restore the previous interrupt state (assuming all interrupts disabled) */
up_serialout(priv, SAM_UART_IER_OFFSET, imr);
}
diff --git a/nuttx/arch/arm/src/sama5/sam_serial.c b/nuttx/arch/arm/src/sama5/sam_serial.c
index 2f5f54870..935ee0e56 100644
--- a/nuttx/arch/arm/src/sama5/sam_serial.c
+++ b/nuttx/arch/arm/src/sama5/sam_serial.c
@@ -728,10 +728,21 @@ static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t valu
}
/****************************************************************************
+ * Name: up_restoreusartint
+ ****************************************************************************/
+
+static inline void up_restoreusartint(struct up_dev_s *priv, uint32_t imr)
+{
+ /* Restore the previous interrupt state (assuming all interrupts disabled) */
+
+ up_serialout(priv, SAM_UART_IER_OFFSET, imr);
+}
+
+/****************************************************************************
* Name: up_disableallints
****************************************************************************/
-static void up_disableallints(struct up_dev_s *priv)
+static void up_disableallints(struct up_dev_s *priv, uint32_t *imr)
{
irqstate_t flags;
@@ -739,6 +750,13 @@ static void up_disableallints(struct up_dev_s *priv)
flags = irqsave();
+ /* Return the current interrupt state */
+
+ if (imr)
+ {
+ *imr = up_serialin(priv, SAM_UART_IMR_OFFSET);
+ }
+
/* Disable all interrupts */
up_serialout(priv, SAM_UART_IDR_OFFSET, UART_INT_ALLINTS);
@@ -887,7 +905,7 @@ static void up_shutdown(struct uart_dev_s *dev)
/* Disable all interrupts */
- up_disableallints(priv);
+ up_disableallints(priv, NULL);
}
/****************************************************************************
@@ -1243,13 +1261,12 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
* implement TCSADRAIN / TCSAFLUSH
*/
- imr = up_serialin(priv, SAM_UART_IMR_OFFSET);
- up_disableallints(priv);
+ up_disableallints(priv, &imr);
ret = up_setup(dev);
/* Restore the interrupt state */
- up_serialout(priv, SAM_UART_IER_OFFSET, imr);
+ up_restoreusartint(priv, imr);
}
}
break;
@@ -1437,25 +1454,25 @@ void sam_earlyserialinit(void)
/* Disable all USARTS */
#ifdef TTYS0_DEV
- up_disableallints(TTYS0_DEV.priv);
+ up_disableallints(TTYS0_DEV.priv, NULL);
#endif
#ifdef TTYS1_DEV
- up_disableallints(TTYS1_DEV.priv);
+ up_disableallints(TTYS1_DEV.priv, NULL);
#endif
#ifdef TTYS2_DEV
- up_disableallints(TTYS2_DEV.priv);
+ up_disableallints(TTYS2_DEV.priv, NULL);
#endif
#ifdef TTYS3_DEV
- up_disableallints(TTYS3_DEV.priv);
+ up_disableallints(TTYS3_DEV.priv, NULL);
#endif
#ifdef TTYS4_DEV
- up_disableallints(TTYS4_DEV.priv);
+ up_disableallints(TTYS4_DEV.priv, NULL);
#endif
#ifdef TTYS5_DEV
- up_disableallints(TTYS5_DEV.priv);
+ up_disableallints(TTYS5_DEV.priv, NULL);
#endif
#ifdef TTYS6_DEV
- up_disableallints(TTYS6_DEV.priv);
+ up_disableallints(TTYS6_DEV.priv, NULL);
#endif
/* Configuration whichever one is the console */
diff --git a/nuttx/arch/arm/src/samv7/sam_serial.c b/nuttx/arch/arm/src/samv7/sam_serial.c
index 896fcd405..1ffa8539b 100644
--- a/nuttx/arch/arm/src/samv7/sam_serial.c
+++ b/nuttx/arch/arm/src/samv7/sam_serial.c
@@ -710,7 +710,7 @@ static inline void sam_serialout(struct sam_dev_s *priv, int offset, uint32_t va
static inline void sam_restoreusartint(struct sam_dev_s *priv, uint32_t imr)
{
- /* Restore the previous interrupt state */
+ /* Restore the previous interrupt state (assuming all interrupts disabled) */
sam_serialout(priv, SAM_UART_IER_OFFSET, imr);
}