-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
During a call to “stdio_set_chars_available_callback()” when a receive character is already pending in the UART the system locks up. It continuously re-enters the low-level "on_uart_rx()" function because the callback pointer has not yet been saved before enabling the interrupt.
Note the order of the highlighted lines in file "pico-sdk/src/rp2_common/pico_stdio_uart /stdio_uart.c":
static void stdio_uart_set_chars_available_callback(void (fn)(void), void *param) {
uint irq_num = UART_IRQ_NUM(uart_instance);
if (fn && !chars_available_callback) {
irq_set_exclusive_handler(irq_num, on_uart_rx);
irq_set_enabled(irq_num, true);
uart_set_irqs_enabled(uart_instance, true, false);
} else if (!fn && chars_available_callback) {
uart_set_irqs_enabled(uart_instance, false, false);
irq_set_enabled(irq_num, false);
irq_remove_handler(irq_num, on_uart_rx);
}
chars_available_callback = fn;
chars_available_param = param;
}
Clearly the "chars_available_callback" pointer is set after the RX interrupt has been enabled. I suggest to change the function to look like this:
static void stdio_uart_set_chars_available_callback(void (fn)(void), void *param) {
uint irq_num = UART_IRQ_NUM(uart_instance);
if (fn && !chars_available_callback) {
chars_available_callback = fn;
chars_available_param = param;
irq_set_exclusive_handler(irq_num, on_uart_rx);
irq_set_enabled(irq_num, true);
uart_set_irqs_enabled(uart_instance, true, false);
} else if (!fn && chars_available_callback) {
uart_set_irqs_enabled(uart_instance, false, false);
irq_set_enabled(irq_num, false);
irq_remove_handler(irq_num, on_uart_rx);
chars_available_callback = fn;
chars_available_param = param;
}
}
Note that the order is critical both in the callback installation and de-installation context. You want the callback pointers saved before enabling the interrupt. You also want to clear the callback pointer only after the interrupt is disabled.
There are many scenarios where a UART is connected to a device which spontaneously and regularly sends serial data (e.g. telemetry). If the Pico is powering up while such a data burst is happening, the “stdio_set_chars_available_callback()” will hang unless my suggested fix is implemented.
Please let me know if you need further information.