uart: ns16550: add workaround to re-enable interrupts in ISR
In some configurations (e.g. edge interrupt triggers), an interruptible event occurs during ISR and the host interrupt controller does not see the new event due to IIR is constantly asserting interrupts. For example, the callback handles RX and then TX. If another character comes in before end of TX processing (TX interrupt still asserts while raising RX interrupt), the host interrupt controller may not see this new event. So if needed, the IER is being toggled to re-assert interrupts at the end of ISR to nudge the host interrupt controller to fire the ISR again. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
cf3dabedaf
commit
ef0d955758
|
@ -41,4 +41,22 @@ config UART_NS16550_ACCESS_WORD_ONLY
|
|||
16550 (DesignWare UART) only allows word access, byte access will raise
|
||||
exception.
|
||||
|
||||
menu "NS16550 Workarounds"
|
||||
|
||||
config UART_NS16550_WA_ISR_REENABLE_INTERRUPT
|
||||
bool "Re-enable interrupts by toggling IER at end of ISR"
|
||||
depends on UART_INTERRUPT_DRIVEN
|
||||
help
|
||||
In some configurations (e.g. edge interrupt triggers),
|
||||
an interruptible event occurs during ISR and the host interrupt
|
||||
controller does not see the new event due to IIR is constantly
|
||||
asserting interrupts. For example, the callback handles RX and
|
||||
then TX. If another character comes in before end of TX processing
|
||||
(TX interrupt still asserts while raising RX interrupt), the host
|
||||
interrupt controller may not see this new event. So if needed,
|
||||
the IER is being toggled to re-assert interrupts at the end of ISR
|
||||
to nudge the host interrupt controller to fire the ISR again.
|
||||
|
||||
endmenu
|
||||
|
||||
endif # UART_NS16550
|
||||
|
|
|
@ -871,6 +871,12 @@ static void uart_ns16550_isr(const struct device *dev)
|
|||
dev_data->cb(dev, dev_data->cb_data);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UART_NS16550_WA_ISR_REENABLE_INTERRUPT
|
||||
uint8_t cached_ier = INBYTE(IER(dev));
|
||||
|
||||
OUTBYTE(IER(dev), 0U);
|
||||
OUTBYTE(IER(dev), cached_ier);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
||||
|
|
Loading…
Reference in a new issue