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.
This commit is contained in:
parent
5ce2ece134
commit
9169ff6a15
@ -1050,10 +1050,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;
|
uint32_t cr;
|
||||||
|
|
||||||
@ -1074,12 +1074,31 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie)
|
|||||||
up_serialout(priv, STM32_USART_CR3_OFFSET, cr);
|
up_serialout(priv, STM32_USART_CR3_OFFSET, cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* 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
|
* 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)
|
if (ie)
|
||||||
{
|
{
|
||||||
uint32_t cr1;
|
uint32_t cr1;
|
||||||
@ -1116,7 +1135,9 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
|
|||||||
|
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
|
|
||||||
up_restoreusartint(priv, 0);
|
up_setusartint(priv, 0);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -769,10 +769,10 @@ static inline void stm32f0serial_putreg(FAR struct stm32f0_serial_s *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32f0serial_restoreusartint
|
* Name: stm32f0serial_setusartint
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void stm32f0serial_restoreusartint(FAR struct stm32f0_serial_s *priv,
|
static void stm32f0serial_setusartint(FAR struct stm32f0_serial_s *priv,
|
||||||
uint16_t ie)
|
uint16_t ie)
|
||||||
{
|
{
|
||||||
uint32_t cr;
|
uint32_t cr;
|
||||||
@ -794,13 +794,33 @@ static void stm32f0serial_restoreusartint(FAR struct stm32f0_serial_s *priv,
|
|||||||
stm32f0serial_putreg(priv, STM32F0_USART_CR3_OFFSET, cr);
|
stm32f0serial_putreg(priv, STM32F0_USART_CR3_OFFSET, cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32f0serial_restoreusartint
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void stm32f0serial_restoreusartint(FAR struct stm32f0_serial_s *priv,
|
||||||
|
uint16_t ie)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
stm32f0serial_setusartint(priv, ie);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32f0serial_disableusartint
|
* Name: stm32f0serial_disableusartint
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void stm32f0serial_disableusartint(FAR struct stm32f0_serial_s *priv,
|
static void stm32f0serial_disableusartint(FAR struct stm32f0_serial_s *priv,
|
||||||
FAR uint16_t *ie)
|
FAR uint16_t *ie)
|
||||||
{
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
if (ie)
|
if (ie)
|
||||||
{
|
{
|
||||||
uint32_t cr1;
|
uint32_t cr1;
|
||||||
@ -837,7 +857,9 @@ static inline void stm32f0serial_disableusartint(FAR struct stm32f0_serial_s *pr
|
|||||||
|
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
|
|
||||||
stm32f0serial_restoreusartint(priv, 0);
|
stm32f0serial_setusartint(priv, 0);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -1096,10 +1096,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;
|
uint32_t cr;
|
||||||
|
|
||||||
@ -1120,12 +1120,31 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie)
|
|||||||
up_serialout(priv, STM32_USART_CR3_OFFSET, cr);
|
up_serialout(priv, STM32_USART_CR3_OFFSET, cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* 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
|
* 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)
|
if (ie)
|
||||||
{
|
{
|
||||||
uint32_t cr1;
|
uint32_t cr1;
|
||||||
@ -1162,7 +1181,9 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie)
|
|||||||
|
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
|
|
||||||
up_restoreusartint(priv, 0);
|
up_setusartint(priv, 0);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -2868,6 +2889,7 @@ int up_putc(int ch)
|
|||||||
|
|
||||||
up_lowputc(ch);
|
up_lowputc(ch);
|
||||||
up_restoreusartint(priv, ie);
|
up_restoreusartint(priv, ie);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
@ -765,11 +765,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,
|
static inline void stm32l4serial_setusartint(FAR struct stm32l4_serial_s *priv,
|
||||||
uint16_t ie)
|
uint16_t ie)
|
||||||
{
|
{
|
||||||
uint32_t cr;
|
uint32_t cr;
|
||||||
|
|
||||||
@ -790,13 +790,33 @@ static void stm32l4serial_restoreusartint(FAR struct stm32l4_serial_s *priv,
|
|||||||
stm32l4serial_putreg(priv, STM32L4_USART_CR3_OFFSET, cr);
|
stm32l4serial_putreg(priv, STM32L4_USART_CR3_OFFSET, cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* 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
|
* Name: stm32l4serial_disableusartint
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *priv,
|
static void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *priv,
|
||||||
FAR uint16_t *ie)
|
FAR uint16_t *ie)
|
||||||
{
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
if (ie)
|
if (ie)
|
||||||
{
|
{
|
||||||
uint32_t cr1;
|
uint32_t cr1;
|
||||||
@ -833,7 +853,9 @@ static inline void stm32l4serial_disableusartint(FAR struct stm32l4_serial_s *pr
|
|||||||
|
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
|
|
||||||
stm32l4serial_restoreusartint(priv, 0);
|
stm32l4serial_setusartint(priv, 0);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
Loading…
Reference in New Issue
Block a user