Skip to content

bug in pico-sdk/src/rp2_common/pico_stdio_uart /stdio_uart.c causing lockups #2009

@thunter6600

Description

@thunter6600

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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions