summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-08-13 09:42:40 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-08-13 09:42:40 -0600
commit10d49e897e562c376fd053b7aaa44912bc32b771 (patch)
tree8054ee03b7b66806d1d741877ab602ac98adc01c
parentb10f9ac74ef20d0ff7f56f11e84e8f5d0fcecc2d (diff)
downloadnuttx-10d49e897e562c376fd053b7aaa44912bc32b771.tar.gz
nuttx-10d49e897e562c376fd053b7aaa44912bc32b771.tar.bz2
nuttx-10d49e897e562c376fd053b7aaa44912bc32b771.zip
Fix re-entry problem in SAMA5 up_putc
-rw-r--r--nuttx/ChangeLog5
-rw-r--r--nuttx/arch/arm/src/sama5/sam_serial.c31
2 files changed, 35 insertions, 1 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 2471c4c7f..fa6401252 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -5387,3 +5387,8 @@
is being disconnected (2013-8-12).
* nuttx/arch/arm/src/stm32/Kconfig, Make.defs, and /stm32f30xxx_i2c.c:
STM32 F3 I2C fixes from John Wharington (2013-8-13).
+ * nuttx/arch/arm/src/sama5/sam_serial.c: Fix a re-entrancy problem
+ in up_putc(). I think all architectures have this re-entrancy
+ than can result in serial interrupt being disabled, but I have only
+ seen the symptom on SAMA5 (2013-8-13).
+
diff --git a/nuttx/arch/arm/src/sama5/sam_serial.c b/nuttx/arch/arm/src/sama5/sam_serial.c
index ebf1e4166..19b2dcd1b 100644
--- a/nuttx/arch/arm/src/sama5/sam_serial.c
+++ b/nuttx/arch/arm/src/sama5/sam_serial.c
@@ -1194,7 +1194,10 @@ void up_serialinit(void)
* Name: up_putc
*
* Description:
- * Provide priority, low-level access to support OS debug writes
+ * Provide priority, low-level access to support OS debug writes. This
+ * function is intended only to support early boot-up logic and serial
+ * debug output from interrupt handlers. It is invasive and will effect
+ * your realtime performance!
*
****************************************************************************/
@@ -1202,9 +1205,26 @@ int up_putc(int ch)
{
#ifdef HAVE_CONSOLE
struct up_dev_s *priv = (struct up_dev_s*)CONSOLE_DEV.priv;
+
+ /* This logic does not work. Apparently re-entrancy problems cause the
+ * loss of serial interrupts (a bad, zero IMR gets set). My attempts to
+ * make this function fully re-entrant have not been successful but the
+ * following brute force approach works just fine.
+ */
+
+#if 0
uint32_t imr;
+ /* Disable serial interrupts */
+
up_disableallints(priv, &imr);
+#else
+ irqstate_t flags;
+
+ /* Disable all interrupts */
+
+ flags = irqsave();
+#endif
/* Check for LF */
@@ -1216,7 +1236,16 @@ int up_putc(int ch)
}
up_lowputc(ch);
+
+#if 0 /* See comments above */
+ /* Restore serial interrupts */
+
up_restoreusartint(priv, imr);
+#else
+ /* Restore all interrupts */
+
+ irqrestore(flags);
+#endif
#endif
return ch;
}