1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
38
39
40
41
42
43
44
45
46
47
55
56
57
58
59
60
61
62
63
64
74
75
76
86
87
88
89
90
91
92
99
100
101
102
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
124
125
126
127
128
131
132
133
134
135
136
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/* ... */
#include <stdio.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "pico/util/queue.h"
#include "pico/async_context_threadsafe_background.h"
#include "hardware/pio.h"
#include "hardware/uart.h"
#include "uart_rx.pio.h"
9 includes
#define SERIAL_BAUD PICO_DEFAULT_UART_BAUD_RATE
#define HARD_UART_INST uart1
#define HARD_UART_TX_PIN 4
#define PIO_RX_PIN 3
#define FIFO_SIZE 64
#define MAX_COUNTER 10
6 defines
static PIO pio;
static uint sm;
static int8_t pio_irq;
static queue_t fifo;
static uint offset;
static uint32_t counter;
static bool work_done;
static void core1_main() {
while(counter < MAX_COUNTER) {
sleep_ms(1000 + (rand() % 1000));
static char text[64];
sprintf(text, "Hello, world from PIO with interrupts! %u\n", counter++);
uart_puts(HARD_UART_INST, text);
}while (counter < MAX_COUNTER) { ... }
}{ ... }
static void async_worker_func(async_context_t *async_context, async_when_pending_worker_t *worker);
static async_context_threadsafe_background_t async_context;
static async_when_pending_worker_t worker = { .do_work = async_worker_func };
static void pio_irq_func(void) {
while(!pio_sm_is_rx_fifo_empty(pio, sm)) {
char c = uart_rx_program_getc(pio, sm);
if (!queue_try_add(&fifo, &c)) {
panic("fifo full");
}if (!queue_try_add(&fifo, &c)) { ... }
}while (!pio_sm_is_rx_fifo_empty(pio, sm)) { ... }
async_context_set_work_pending(&async_context.core, &worker);
}{ ... }
static void async_worker_func(__unused async_context_t *async_context, __unused async_when_pending_worker_t *worker) {
work_done = true;
while(!queue_is_empty(&fifo)) {
char c;
if (!queue_try_remove(&fifo, &c)) {
panic("fifo empty");
}if (!queue_try_remove(&fifo, &c)) { ... }
putchar(c);
}while (!queue_is_empty(&fifo)) { ... }
}{ ... }
static bool init_pio(const pio_program_t *program, PIO *pio_hw, uint *sm, uint *offset) {
*pio_hw = pio1;
if (!pio_can_add_program(*pio_hw, program)) {
*pio_hw = pio0;
if (!pio_can_add_program(*pio_hw, program)) {
*offset = -1;
return false;
}if (!pio_can_add_program(*pio_hw, program)) { ... }
}if (!pio_can_add_program(*pio_hw, program)) { ... }
*offset = pio_add_program(*pio_hw, program);
*sm = (int8_t)pio_claim_unused_sm(*pio_hw, false);
if (*sm < 0) {
return false;
}if (*sm < 0) { ... }
return true;
}{ ... }
int main() {
setup_default_uart();
printf("Starting PIO UART RX interrupt example\n");
uart_init(HARD_UART_INST, SERIAL_BAUD);
gpio_set_function(HARD_UART_TX_PIN, GPIO_FUNC_UART);
queue_init(&fifo, 1, FIFO_SIZE);
if (!async_context_threadsafe_background_init_with_defaults(&async_context)) {
panic("failed to setup context");
}if (!async_context_threadsafe_background_init_with_defaults(&async_context)) { ... }
async_context_add_when_pending_worker(&async_context.core, &worker);
if (!init_pio(&uart_rx_program, &pio, &sm, &offset)) {
panic("failed to setup pio");
}if (!init_pio(&uart_rx_program, &pio, &sm, &offset)) { ... }
uart_rx_program_init(pio, sm, offset, PIO_RX_PIN, SERIAL_BAUD);
static_assert(PIO0_IRQ_1 == PIO0_IRQ_0 + 1 && PIO1_IRQ_1 == PIO1_IRQ_0 + 1, "");
pio_irq = (pio == pio0) ? PIO0_IRQ_0 : PIO1_IRQ_0;
if (irq_get_exclusive_handler(pio_irq)) {
pio_irq++;
if (irq_get_exclusive_handler(pio_irq)) {
panic("All IRQs are in use");
}if (irq_get_exclusive_handler(pio_irq)) { ... }
}if (irq_get_exclusive_handler(pio_irq)) { ... }
irq_add_shared_handler(pio_irq, pio_irq_func, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
irq_set_enabled(pio_irq, true);
const uint irq_index = pio_irq - ((pio == pio0) ? PIO0_IRQ_0 : PIO1_IRQ_0);
pio_set_irqn_source_enabled(pio, irq_index, pis_sm0_rx_fifo_not_empty + sm, true);
multicore_launch_core1(core1_main);
while (counter < MAX_COUNTER || work_done) {
work_done = false;
async_context_poll(&async_context.core);
async_context_wait_for_work_ms(&async_context.core, 2000);
}while (counter < MAX_COUNTER || work_done) { ... }
pio_set_irqn_source_enabled(pio, irq_index, pis_sm0_rx_fifo_not_empty + sm, false);
irq_set_enabled(pio_irq, false);
irq_remove_handler(pio_irq, pio_irq_func);
pio_sm_set_enabled(pio, sm, false);
pio_remove_program(pio, &uart_rx_program, offset);
pio_sm_unclaim(pio, sm);
async_context_remove_when_pending_worker(&async_context.core, &worker);
async_context_deinit(&async_context.core);
queue_free(&fifo);
uart_deinit(HARD_UART_INST);
printf("Test complete\n");
sleep_ms(100);
return 0;
}{ ... }