In this series, I design a programmable lab switch based on RP2040, that can turn a set of signals or supplies on or off. Over USB. SCPI compatible.
|
Understand RP2040 UART and Interrupts
The RP2040 FreeRTOS port doesn't include wrappers for the peripherals. It's not uncommon - a port is good if it supports running the RTOS. Making the peripherals RTOS aware isn't needed. We can do that ourselves.
A few things to consider:
- protect UART resources from multi-task access, where needed
- write tasks for receiving data and incoming traffic interrupt handling. Maybe for sending data?
To do this, I first need to understand how the UARTs of the RP2040 work. There's an excellent example: uart_advanced. The example uses interrupts for both receive and send, but I'm looking for receive only.
Review pico-examples UART interrupt example
Enable RX Interrupt
This is straightforward:
// Turn off FIFO's - we want to do this character by character uart_set_fifo_enabled(UART_ID, false); // Set up a RX interrupt // We need to set up the handler first // Select correct interrupt for the UART we are using int UART_IRQ = UART_ID == uart0 ? UART0_IRQ : UART1_IRQ; // And set up and enable the interrupt handlers irq_set_exclusive_handler(UART_IRQ, on_uart_rx); irq_set_enabled(UART_IRQ, true); // Now enable the UART to send interrupts - RX only uart_set_irq_enables(UART_ID, true, false); // OK, all set up.
Single-char is set, and that matches what I'll want to do: I want to shoot each character to the SCPI library later.
Then, the interrupt is registered and activated.
Handle RX Interrupt
Again simple:
// RX interrupt handler void on_uart_rx() { while (uart_is_readable(UART_ID)) { uint8_t ch = uart_getc(UART_ID); // TODO: handle } }
The handle retrieves any available character from the UART. I haven't reviewed RP2040 SDK in depth, but it seems you don't have to clear the interrupt ...
Port to FreeRTOS
This will not be hard to translate to RTOS:
- make the "UART read task" wait on a direct task message
- in the "UART RX interrupt handler", notify the read task, so that it wakes up.
- in the "UART read task", get the character from UART, send it to the business logic (SCPI parser),
- go back to start
In the next blog, I'll implement most of this. The business logic will not be there yet. I'll toggle the LED whenever you type a 'b' character ...