arch/arm/gd32f4: fix missing CTL selector bits in up_disableusartint.

up_disableusartint() saves USART interrupt state from hardware CTL0-CTL3
registers but omits the CTL selector bits (bits 24-27) in the encoded
ie value. When up_restoreusartint() later restores interrupts, it uses
ie >> 24 to determine which CTL register to write. Without selector bits
this evaluates to 0, so no CTL register is updated and all interrupt
enables (including RBNEIE) are permanently lost.

This causes RX interrupts to never fire after any call to up_putc()
(e.g. via syslog), making the serial console unable to receive input.

Fix by adding the corresponding CTL selector bit (USART_CFG_CTLx_INT
<< USART_CFG_SHIFT) whenever a CTL register has active interrupt bits.

Signed-off-by: lccosy <1191294205@qq.com>
This commit is contained in:
lccosy
2026-06-24 12:19:17 +08:00
committed by Xiang Xiao
parent 186d1ca80f
commit d4f31f73aa
+26 -4
View File
@@ -1142,25 +1142,47 @@ static void up_disableusartint(struct up_dev_s *priv, uint32_t *ie)
{
uint32_t ctl;
ctl_ie = 0;
/* Save interrupt in CTL0 register */
ctl = up_serialin(priv, GD32_USART_CTL0_OFFSET);
ctl_ie = ((ctl & USART_CTL0_USED_INTS) >> USART_CFG_CTL0_INT_SHIFT);
if (ctl & USART_CTL0_USED_INTS)
{
ctl_ie |= ((ctl & USART_CTL0_USED_INTS) >>
USART_CFG_CTL0_INT_SHIFT);
ctl_ie |= (USART_CFG_CTL0_INT << USART_CFG_SHIFT);
}
/* Save interrupt in CTL1 register */
ctl = up_serialin(priv, GD32_USART_CTL1_OFFSET);
ctl_ie |= ((ctl & USART_CTL1_USED_INTS) >> USART_CFG_CTL1_INT_SHIFT);
if (ctl & USART_CTL1_USED_INTS)
{
ctl_ie |= ((ctl & USART_CTL1_USED_INTS) >>
USART_CFG_CTL1_INT_SHIFT);
ctl_ie |= (USART_CFG_CTL1_INT << USART_CFG_SHIFT);
}
/* Save interrupt in CTL2 register */
ctl = up_serialin(priv, GD32_USART_CTL2_OFFSET);
ctl_ie |= ((ctl & USART_CTL2_USED_INTS) << USART_CFG_CTL2_INT_SHIFT);
if (ctl & USART_CTL2_USED_INTS)
{
ctl_ie |= ((ctl & USART_CTL2_USED_INTS) <<
USART_CFG_CTL2_INT_SHIFT);
ctl_ie |= (USART_CFG_CTL2_INT << USART_CFG_SHIFT);
}
/* Save interrupt in CTL3 register */
ctl = up_serialin(priv, GD32_USART_CTL3_OFFSET);
ctl_ie |= ((ctl & USART_CTL3_USED_INTS) << USART_CFG_CTL3_INT_SHIFT);
if (ctl & USART_CTL3_USED_INTS)
{
ctl_ie |= ((ctl & USART_CTL3_USED_INTS) <<
USART_CFG_CTL3_INT_SHIFT);
ctl_ie |= (USART_CFG_CTL3_INT << USART_CFG_SHIFT);
}
*ie = ctl_ie;
}