From 6bf19d2a0657795f505a5b15250ea344ac845a6d Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Wed, 17 May 2017 09:14:12 -1000 Subject: [PATCH] BACKPORT of upstream NuttX stm32_serial: fix freezing serial port. Thanks to Jussi Kivilinna https://bitbucket.org/nuttx/nuttx/commits/9169ff6a15fe65ba4af134b470dbf89220274c19 stm32_serial: fix freezing serial port. Serial interrupt enable/disable functions do not disable interrupts and can freeze device when serial interrupt is received while execution is at those functions. Trivially triggered with two or more threads write to regular syslog stream and to emergency stream. In this case, freeze happens because of mismatch of priv->ie (TXEIE == 0) and actually enabled interrupts in USART registers (TXEIE == 1), which leads to unhandled TXE interrupt and causes interrupt storm for USART. --- ...BACKPORT-stm32fX-serial-fix-freezing.patch | 193 ++++++++++++++++++ nuttx-patches/CMakeLists.txt | 1 + 2 files changed, 194 insertions(+) create mode 100644 nuttx-patches/00026-BACKPORT-stm32fX-serial-fix-freezing.patch diff --git a/nuttx-patches/00026-BACKPORT-stm32fX-serial-fix-freezing.patch b/nuttx-patches/00026-BACKPORT-stm32fX-serial-fix-freezing.patch new file mode 100644 index 0000000000..67b5411750 --- /dev/null +++ b/nuttx-patches/00026-BACKPORT-stm32fX-serial-fix-freezing.patch @@ -0,0 +1,193 @@ +diff --git NuttX/nuttx/arch/arm/src/stm32/stm32_serial.c NuttX/nuttx/arch/arm/src/stm32/stm32_serial.c +index 644c810..b885440 100644 +--- NuttX/nuttx/arch/arm/src/stm32/stm32_serial.c ++++ NuttX/nuttx/arch/arm/src/stm32/stm32_serial.c +@@ -1088,10 +1088,10 @@ static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t valu + } + + /**************************************************************************** +- * Name: up_restoreusartint ++ * Name: up_setusartint + ****************************************************************************/ + +-static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) ++static inline void up_setusartint(struct up_dev_s *priv, uint16_t ie) + { + uint32_t cr; + +@@ -1113,11 +1113,30 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) + } + + /**************************************************************************** ++ * Name: up_restoreusartint ++ ****************************************************************************/ ++ ++static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) ++{ ++ irqstate_t flags; ++ ++ flags = enter_critical_section(); ++ ++ up_setusartint(priv, ie); ++ ++ leave_critical_section(flags); ++} ++ ++/**************************************************************************** + * Name: up_disableusartint + ****************************************************************************/ + +-static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) ++static void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) + { ++ irqstate_t flags; ++ ++ flags = enter_critical_section(); ++ + if (ie) + { + uint32_t cr1; +@@ -1154,7 +1173,9 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) + + /* Disable all interrupts */ + +- up_restoreusartint(priv, 0); ++ up_setusartint(priv, 0); ++ ++ leave_critical_section(flags); + } + + /**************************************************************************** +diff --git NuttX/nuttx/arch/arm/src/stm32f7/stm32_serial.c NuttX/nuttx/arch/arm/src/stm32f7/stm32_serial.c +index 1f5445a..faae72a 100644 +--- NuttX/nuttx/arch/arm/src/stm32f7/stm32_serial.c ++++ NuttX/nuttx/arch/arm/src/stm32f7/stm32_serial.c +@@ -1070,10 +1070,10 @@ static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t valu + } + + /**************************************************************************** +- * Name: up_restoreusartint ++ * Name: up_setusartint + ****************************************************************************/ + +-static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) ++static inline void up_setusartint(struct up_dev_s *priv, uint16_t ie) + { + uint32_t cr; + +@@ -1095,11 +1095,30 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) + } + + /**************************************************************************** ++ * Name: up_restoreusartint ++ ****************************************************************************/ ++ ++static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) ++{ ++ irqstate_t flags; ++ ++ flags = enter_critical_section(); ++ ++ up_setusartint(priv, ie); ++ ++ leave_critical_section(flags); ++} ++ ++/**************************************************************************** + * Name: up_disableusartint + ****************************************************************************/ + +-static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) ++static void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) + { ++ irqstate_t flags; ++ ++ flags = enter_critical_section(); ++ + if (ie) + { + uint32_t cr1; +@@ -1136,7 +1155,9 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) + + /* Disable all interrupts */ + +- up_restoreusartint(priv, 0); ++ up_setusartint(priv, 0); ++ ++ leave_critical_section(flags); + } + + /**************************************************************************** +@@ -2928,6 +2949,7 @@ int up_putc(int ch) + + up_lowputc(ch); + up_restoreusartint(priv, ie); ++ + #endif + return ch; + } +diff --git NuttX/nuttx/arch/arm/src/stm32l4/stm32l4_serial.c NuttX/nuttx/arch/arm/src/stm32l4/stm32l4_serial.c +index dfef76a..8f1fa77 100644 +--- NuttX/nuttx/arch/arm/src/stm32l4/stm32l4_serial.c ++++ NuttX/nuttx/arch/arm/src/stm32l4/stm32l4_serial.c +@@ -783,11 +783,11 @@ static inline void stm32l4serial_putreg(FAR struct stm32l4_serial_s *priv, + } + + /**************************************************************************** +- * Name: stm32l4serial_restoreusartint ++ * Name: stm32l4serial_setusartint + ****************************************************************************/ + +-static void stm32l4serial_restoreusartint(FAR struct stm32l4_serial_s *priv, +- uint16_t ie) ++static inline void stm32l4serial_setusartint(FAR struct stm32l4_serial_s *priv, ++ uint16_t ie) + { + uint32_t cr; + +@@ -809,12 +809,32 @@ static void stm32l4serial_restoreusartint(FAR struct stm32l4_serial_s *priv, + } + + /**************************************************************************** ++ * Name: up_restoreusartint ++ ****************************************************************************/ ++ ++static void stm32l4serial_restoreusartint(FAR struct stm32l4_serial_s *priv, ++ uint16_t ie) ++{ ++ irqstate_t flags; ++ ++ flags = enter_critical_section(); ++ ++ stm32l4serial_setusartint(priv, ie); ++ ++ leave_critical_section(flags); ++} ++ ++/**************************************************************************** + * Name: stm32l4serial_disableusartint + ****************************************************************************/ + +-static inline void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *priv, +- FAR uint16_t *ie) ++static void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *priv, ++ FAR uint16_t *ie) + { ++ irqstate_t flags; ++ ++ flags = enter_critical_section(); ++ + if (ie) + { + uint32_t cr1; +@@ -851,7 +871,9 @@ static inline void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *pr + + /* Disable all interrupts */ + +- stm32l4serial_restoreusartint(priv, 0); ++ stm32l4serial_setusartint(priv, 0); ++ ++ leave_critical_section(flags); + } + + /**************************************************************************** diff --git a/nuttx-patches/CMakeLists.txt b/nuttx-patches/CMakeLists.txt index ab8206335c..f7d335dba2 100644 --- a/nuttx-patches/CMakeLists.txt +++ b/nuttx-patches/CMakeLists.txt @@ -57,6 +57,7 @@ set(nuttx_patches 00023-BACKPORT-stm32f7-bkp-reference-fix.patch 00024-BACKPORT-stm32f7-serial-dma-hotfix.patch 00025-BACKPORT-add-set-ex-to-nsh.patch + 00026-BACKPORT-stm32fX-serial-fix-freezing.patch 90000-PENDING-wip-inflight-to-upstream.patch )