Datasheet

Table Of Contents
60
61 good_stop: ; No delay before returning to start; a little slack is
62 push ; important in case the TX clock is slightly too fast.
The second example does not use autopush (Section 3.5.4), preferring instead to use an explicit push instruction, so that it
can condition the push on whether a correct stop bit is seen. The .pio file includes a helper function which configures the
state machine and connects it to a GPIO with the pullup enabled:
Pico Examples: https://github.com/raspberrypi/pico-examples/tree/pre_release/pio/uart_rx/uart_rx.pio Lines 66 - 84
66 static inline void uart_rx_program_init(PIO pio, uint sm, uint offset, uint pin, uint baud)
Ê {
67 pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
68 pio_gpio_select(pio, pin);
69 gpio_pull_up(pin);
70
71 pio_sm_config c = uart_rx_program_get_default_config(offset);
72 sm_config_set_in_pins(&c, pin); // for WAIT, IN
73 sm_config_set_jmp_pin(&c, pin); // for JMP
74 // Shift to right, autopull disabled
75 sm_config_set_in_shift(&c, true, false, 32);
76 // Deeper FIFO as we're not doing any TX
77 sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
78 // SM transmits 1 bit per 8 execution cycles.
79 float div = (float)clock_get_hz(clk_sys) / (8 * baud);
80 sm_config_set_clkdiv(&c, div);
81
82 pio_sm_init(pio, sm, offset, &c);
83 pio_sm_enable(pio, sm, true);
84 }
To correctly receive data which is sent LSB-first, the ISR is configured to shift to the right. After shifting in 8 bits, this
unfortunately leaves our 8 data bits in bits 31:24 of the ISR, with 24 zeroes in the LSBs. One option here is an in null, 24
instruction to shuffle the ISR contents down to 7:0. Another is to read from the FIFO at an offset of 3 bytes, with an 8 bit
read, so that the processor’s bus hardware (or the DMA’s) picks out the relevant byte for free:
Pico Examples: https://github.com/raspberrypi/pico-examples/tree/pre_release/pio/uart_rx/uart_rx.pio Lines 86 - 92
86 static inline char uart_rx_program_getc(PIO pio, uint sm) {
87 // 8-bit read from the uppermost byte of the FIFO, as data is left-justified
88 io_rw_8 *rxfifo_shift = (io_rw_8*)&pio->rxf[sm] + 3;
89 while (pio_sm_is_rx_empty(pio, sm))
90 tight_loop_contents();
91 return (char)*rxfifo_shift;
92 }
An example program shows how this UART RX program can be used to receive characters sent by one of the hardware
UARTs on RP2040. A wire must be connected from GPIO4 to GPIO3 for this program to function. To make the wrangling
of 3 different serial ports a little easier, this program uses core 1 to print out a string on the test UART (UART 1), and the
code running on core 0 will pull out characters from the PIO state machine, and pass them along to the UART used for the
debug console (UART 0). Another approach here would be interrupt-based IO, using PIO’s FIFO IRQs. If the SM0_RXNEMPTY bit
is set in the IRQ0_INTE register, then PIO will raise its first interrupt request line whenever there is a character in state
machine 0’s RX FIFO.
Pico Examples: https://github.com/raspberrypi/pico-examples/tree/pre_release/pio/uart_rx/uart_rx.c Lines 1 - 60
Ê1 /**
RP2040 Datasheet
3.6. Examples 353