|
7 | 7 | #include <hardware/structs/sio.h>
|
8 | 8 | #include <hardware/uart.h>
|
9 | 9 | #include <pico/multicore.h>
|
10 |
| -#include <pico/stdio_usb.h> |
11 | 10 | #include <pico/stdlib.h>
|
12 | 11 | #include <tusb.h>
|
13 |
| -#include <string.h> |
14 | 12 |
|
15 | 13 | #if !defined(MIN)
|
16 | 14 | #define MIN(a, b) ((a > b) ? b : a)
|
17 | 15 | #endif /* MIN */
|
18 | 16 |
|
19 | 17 | #define LED_PIN 25
|
20 | 18 |
|
21 |
| -#define UART_ID uart0 |
22 |
| -#define UART_TX_PIN 0 |
23 |
| -#define UART_RX_PIN 1 |
24 |
| - |
25 | 19 | #define BUFFER_SIZE 64
|
26 | 20 |
|
27 | 21 | #define DEF_BIT_RATE 115200
|
28 | 22 | #define DEF_STOP_BITS 1
|
29 | 23 | #define DEF_PARITY 0
|
30 | 24 | #define DEF_DATA_BITS 8
|
31 | 25 |
|
32 |
| -static cdc_line_coding_t CDC_LC = { |
33 |
| - .bit_rate = DEF_BIT_RATE, |
34 |
| - .stop_bits = DEF_STOP_BITS, |
35 |
| - .parity = DEF_PARITY, |
36 |
| - .data_bits = DEF_DATA_BITS, |
| 26 | +typedef struct { |
| 27 | + uart_inst_t *const inst; |
| 28 | + uint8_t tx_pin; |
| 29 | + uint8_t rx_pin; |
| 30 | +} uart_id_t; |
| 31 | + |
| 32 | +typedef struct { |
| 33 | + cdc_line_coding_t usb_lc; |
| 34 | + cdc_line_coding_t uart_lc; |
| 35 | + uint8_t uart_buffer[BUFFER_SIZE]; |
| 36 | + uint32_t uart_pos; |
| 37 | + mutex_t uart_mtx; |
| 38 | + uint8_t usb_buffer[BUFFER_SIZE]; |
| 39 | + uint32_t usb_pos; |
| 40 | + mutex_t usb_mtx; |
| 41 | +} uart_data_t; |
| 42 | + |
| 43 | +const uart_id_t UART_ID[CFG_TUD_CDC] = { |
| 44 | + { |
| 45 | + .inst = uart0, |
| 46 | + .tx_pin = 0, |
| 47 | + .rx_pin = 1, |
| 48 | + }, { |
| 49 | + .inst = uart1, |
| 50 | + .tx_pin = 4, |
| 51 | + .rx_pin = 5, |
| 52 | + } |
37 | 53 | };
|
38 | 54 |
|
39 |
| -static uint8_t UART_BUFFER[BUFFER_SIZE]; |
40 |
| -static uint32_t UART_POS = 0; |
41 |
| -static mutex_t UART_MTX; |
42 |
| - |
43 |
| -static uint8_t USB_BUFFER[BUFFER_SIZE]; |
44 |
| -static uint32_t USB_POS = 0; |
45 |
| -static mutex_t USB_MTX; |
| 55 | +uart_data_t UART_DATA[CFG_TUD_CDC]; |
46 | 56 |
|
47 | 57 | static inline uint databits_usb2uart(uint8_t data_bits)
|
48 | 58 | {
|
@@ -80,133 +90,186 @@ static inline uint stopbits_usb2uart(uint8_t stop_bits)
|
80 | 90 | }
|
81 | 91 | }
|
82 | 92 |
|
83 |
| -int update_uart_cfg(void) |
| 93 | +void update_uart_cfg(uint8_t itf) |
84 | 94 | {
|
85 |
| - static cdc_line_coding_t last_cdc_lc = { |
86 |
| - .bit_rate = DEF_STOP_BITS, |
87 |
| - .stop_bits = DEF_STOP_BITS, |
88 |
| - .parity = DEF_PARITY, |
89 |
| - .data_bits = DEF_DATA_BITS, |
90 |
| - }; |
91 |
| - int updated = 0; |
92 |
| - |
93 |
| - if (last_cdc_lc.bit_rate != CDC_LC.bit_rate) { |
94 |
| - uart_set_baudrate(UART_ID, CDC_LC.bit_rate); |
95 |
| - updated = 1; |
96 |
| - } |
| 95 | + const uart_id_t *ui = &UART_ID[itf]; |
| 96 | + uart_data_t *ud = &UART_DATA[itf]; |
97 | 97 |
|
98 |
| - if ((last_cdc_lc.stop_bits != CDC_LC.stop_bits) || |
99 |
| - (last_cdc_lc.parity != CDC_LC.parity) || |
100 |
| - (last_cdc_lc.data_bits != CDC_LC.data_bits)) { |
101 |
| - uart_set_format(UART_ID, databits_usb2uart(CDC_LC.data_bits), |
102 |
| - stopbits_usb2uart(CDC_LC.stop_bits), |
103 |
| - parity_usb2uart(CDC_LC.parity)); |
104 |
| - updated = 1; |
| 98 | + if (ud->usb_lc.bit_rate != ud->uart_lc.bit_rate) { |
| 99 | + uart_set_baudrate(ui->inst, ud->usb_lc.bit_rate); |
| 100 | + ud->uart_lc.bit_rate = ud->usb_lc.bit_rate; |
105 | 101 | }
|
106 | 102 |
|
107 |
| - if (updated) |
108 |
| - memcpy(&last_cdc_lc, &CDC_LC, sizeof(cdc_line_coding_t)); |
109 |
| - |
110 |
| - return updated; |
| 103 | + if ((ud->usb_lc.stop_bits != ud->uart_lc.stop_bits) || |
| 104 | + (ud->usb_lc.parity != ud->uart_lc.parity) || |
| 105 | + (ud->usb_lc.data_bits != ud->uart_lc.data_bits)) { |
| 106 | + uart_set_format(ui->inst, |
| 107 | + databits_usb2uart(ud->usb_lc.data_bits), |
| 108 | + stopbits_usb2uart(ud->usb_lc.stop_bits), |
| 109 | + parity_usb2uart(ud->usb_lc.parity)); |
| 110 | + ud->uart_lc.data_bits = ud->usb_lc.data_bits; |
| 111 | + ud->uart_lc.parity = ud->usb_lc.parity; |
| 112 | + ud->uart_lc.stop_bits = ud->usb_lc.stop_bits; |
| 113 | + } |
111 | 114 | }
|
112 | 115 |
|
113 |
| -void usb_cdc_process(void) |
114 |
| -{ |
115 |
| - uint32_t count; |
116 |
| - uint32_t len; |
| 116 | +void usb_read_bytes(uint8_t itf) { |
| 117 | + uint32_t len = tud_cdc_n_available(itf); |
117 | 118 |
|
118 |
| - tud_cdc_get_line_coding(&CDC_LC); |
| 119 | + if (len) { |
| 120 | + uart_data_t *ud = &UART_DATA[itf]; |
119 | 121 |
|
120 |
| - /* Read bytes from USB */ |
121 |
| - if (tud_cdc_available()) { |
122 |
| - mutex_enter_blocking(&USB_MTX); |
| 122 | + mutex_enter_blocking(&ud->usb_mtx); |
123 | 123 |
|
124 |
| - len = MIN(tud_cdc_available(), BUFFER_SIZE - USB_POS); |
| 124 | + len = MIN(len, BUFFER_SIZE - ud->usb_pos); |
125 | 125 | if (len) {
|
126 |
| - count = tud_cdc_read(USB_BUFFER, len); |
127 |
| - USB_POS += count; |
| 126 | + uint32_t count; |
| 127 | + |
| 128 | + count = tud_cdc_n_read(itf, ud->usb_buffer, len); |
| 129 | + ud->usb_pos += count; |
128 | 130 | }
|
129 | 131 |
|
130 |
| - mutex_exit(&USB_MTX); |
| 132 | + mutex_exit(&ud->usb_mtx); |
131 | 133 | }
|
| 134 | +} |
132 | 135 |
|
133 |
| - /* Write bytes to USB */ |
134 |
| - if (UART_POS) { |
135 |
| - mutex_enter_blocking(&UART_MTX); |
| 136 | +void usb_write_bytes(uint8_t itf) { |
| 137 | + uart_data_t *ud = &UART_DATA[itf]; |
136 | 138 |
|
137 |
| - count = tud_cdc_write(UART_BUFFER, UART_POS); |
| 139 | + if (ud->uart_pos) { |
| 140 | + uint32_t count; |
| 141 | + |
| 142 | + mutex_enter_blocking(&ud->uart_mtx); |
| 143 | + |
| 144 | + count = tud_cdc_n_write(itf, ud->uart_buffer, ud->uart_pos); |
138 | 145 | if (count) {
|
139 |
| - UART_POS -= count; |
140 |
| - tud_cdc_write_flush(); |
| 146 | + ud->uart_pos -= count; |
| 147 | + tud_cdc_n_write_flush(itf); |
141 | 148 | }
|
142 | 149 |
|
143 |
| - mutex_exit(&UART_MTX); |
| 150 | + mutex_exit(&ud->uart_mtx); |
144 | 151 | }
|
145 | 152 | }
|
146 | 153 |
|
| 154 | +void usb_cdc_process(uint8_t itf) |
| 155 | +{ |
| 156 | + uart_data_t *ud = &UART_DATA[itf]; |
| 157 | + int con = tud_cdc_n_connected(itf); |
| 158 | + |
| 159 | + tud_cdc_n_get_line_coding(itf, &ud->usb_lc); |
| 160 | + usb_read_bytes(itf); |
| 161 | + usb_write_bytes(itf); |
| 162 | +} |
| 163 | + |
147 | 164 | void core1_entry(void)
|
148 | 165 | {
|
149 | 166 | tusb_init();
|
150 | 167 |
|
151 | 168 | while (1) {
|
152 |
| - tud_task(); |
| 169 | + int itf; |
| 170 | + int con = 0; |
153 | 171 |
|
154 |
| - if (tud_cdc_connected()) { |
155 |
| - usb_cdc_process(); |
156 |
| - gpio_put(LED_PIN, 1); |
157 |
| - } else { |
158 |
| - gpio_put(LED_PIN, 0); |
| 172 | + tud_task(); |
| 173 | + |
| 174 | + for (itf = 0; itf < CFG_TUD_CDC; itf++) { |
| 175 | + if (tud_cdc_n_connected(itf)) { |
| 176 | + con = 1; |
| 177 | + usb_cdc_process(itf); |
| 178 | + } |
159 | 179 | }
|
| 180 | + |
| 181 | + gpio_put(LED_PIN, con); |
160 | 182 | }
|
161 | 183 | }
|
162 | 184 |
|
163 |
| -int main(void) |
164 |
| -{ |
165 |
| - uint8_t ch; |
166 |
| - int rc; |
| 185 | +void uart_read_bytes(uint8_t itf) { |
| 186 | + const uart_id_t *ui = &UART_ID[itf]; |
167 | 187 |
|
168 |
| - mutex_init(&UART_MTX); |
169 |
| - mutex_init(&USB_MTX); |
| 188 | + if (uart_is_readable(ui->inst)) { |
| 189 | + uart_data_t *ud = &UART_DATA[itf]; |
170 | 190 |
|
171 |
| - gpio_init(LED_PIN); |
172 |
| - gpio_set_dir(LED_PIN, GPIO_OUT); |
| 191 | + mutex_enter_blocking(&ud->uart_mtx); |
173 | 192 |
|
174 |
| - uart_init(UART_ID, CDC_LC.bit_rate); |
| 193 | + while (uart_is_readable(ui->inst) && |
| 194 | + ud->uart_pos < BUFFER_SIZE) { |
| 195 | + ud->uart_buffer[ud->uart_pos] = uart_getc(ui->inst); |
| 196 | + ud->uart_pos++; |
| 197 | + } |
175 | 198 |
|
176 |
| - gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART); |
177 |
| - gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART); |
| 199 | + mutex_exit(&ud->uart_mtx); |
| 200 | + } |
| 201 | +} |
178 | 202 |
|
179 |
| - uart_set_hw_flow(UART_ID, false, false); |
180 |
| - uart_set_format(UART_ID, databits_usb2uart(CDC_LC.data_bits), |
181 |
| - stopbits_usb2uart(CDC_LC.stop_bits), |
182 |
| - parity_usb2uart(CDC_LC.parity)); |
| 203 | +void uart_write_bytes(uint8_t itf) { |
| 204 | + uart_data_t *ud = &UART_DATA[itf]; |
183 | 205 |
|
184 |
| - multicore_launch_core1(core1_entry); |
| 206 | + if (ud->usb_pos) { |
| 207 | + const uart_id_t *ui = &UART_ID[itf]; |
185 | 208 |
|
186 |
| - while (1) { |
187 |
| - update_uart_cfg(); |
| 209 | + mutex_enter_blocking(&ud->usb_mtx); |
188 | 210 |
|
189 |
| - /* Read bytes from UART */ |
190 |
| - if (uart_is_readable(UART_ID)) { |
191 |
| - mutex_enter_blocking(&UART_MTX); |
| 211 | + uart_write_blocking(ui->inst, ud->usb_buffer, ud->usb_pos); |
| 212 | + ud->usb_pos = 0; |
192 | 213 |
|
193 |
| - while (uart_is_readable(UART_ID) && |
194 |
| - UART_POS < BUFFER_SIZE) { |
195 |
| - UART_BUFFER[UART_POS] = uart_getc(UART_ID); |
196 |
| - UART_POS++; |
197 |
| - } |
| 214 | + mutex_exit(&ud->usb_mtx); |
| 215 | + } |
| 216 | +} |
198 | 217 |
|
199 |
| - mutex_exit(&UART_MTX); |
200 |
| - } |
| 218 | +void init_uart_data(uint8_t itf) { |
| 219 | + const uart_id_t *ui = &UART_ID[itf]; |
| 220 | + uart_data_t *ud = &UART_DATA[itf]; |
| 221 | + |
| 222 | + /* Pinmux */ |
| 223 | + gpio_set_function(ui->tx_pin, GPIO_FUNC_UART); |
| 224 | + gpio_set_function(ui->rx_pin, GPIO_FUNC_UART); |
| 225 | + |
| 226 | + /* USB CDC LC */ |
| 227 | + ud->usb_lc.bit_rate = DEF_BIT_RATE; |
| 228 | + ud->usb_lc.data_bits = DEF_DATA_BITS; |
| 229 | + ud->usb_lc.parity = DEF_PARITY; |
| 230 | + ud->usb_lc.stop_bits = DEF_STOP_BITS; |
| 231 | + |
| 232 | + /* UART LC */ |
| 233 | + ud->uart_lc.bit_rate = DEF_BIT_RATE; |
| 234 | + ud->uart_lc.data_bits = DEF_DATA_BITS; |
| 235 | + ud->uart_lc.parity = DEF_PARITY; |
| 236 | + ud->uart_lc.stop_bits = DEF_STOP_BITS; |
| 237 | + |
| 238 | + /* Buffer */ |
| 239 | + ud->uart_pos = 0; |
| 240 | + ud->usb_pos = 0; |
| 241 | + |
| 242 | + /* Mutex */ |
| 243 | + mutex_init(&ud->uart_mtx); |
| 244 | + mutex_init(&ud->usb_mtx); |
| 245 | + |
| 246 | + /* UART start */ |
| 247 | + uart_init(ui->inst, ud->usb_lc.bit_rate); |
| 248 | + uart_set_hw_flow(ui->inst, false, false); |
| 249 | + uart_set_format(ui->inst, databits_usb2uart(ud->usb_lc.data_bits), |
| 250 | + stopbits_usb2uart(ud->usb_lc.stop_bits), |
| 251 | + parity_usb2uart(ud->usb_lc.parity)); |
| 252 | +} |
201 | 253 |
|
202 |
| - /* Write bytes to UART */ |
203 |
| - if (USB_POS) { |
204 |
| - mutex_enter_blocking(&USB_MTX); |
| 254 | +int main(void) |
| 255 | +{ |
| 256 | + uint8_t ch; |
| 257 | + int rc; |
| 258 | + int itf; |
205 | 259 |
|
206 |
| - uart_write_blocking(UART_ID, USB_BUFFER, USB_POS); |
207 |
| - USB_POS = 0; |
| 260 | + for (itf = 0; itf < CFG_TUD_CDC; itf++) |
| 261 | + init_uart_data(itf); |
208 | 262 |
|
209 |
| - mutex_exit(&USB_MTX); |
| 263 | + gpio_init(LED_PIN); |
| 264 | + gpio_set_dir(LED_PIN, GPIO_OUT); |
| 265 | + |
| 266 | + multicore_launch_core1(core1_entry); |
| 267 | + |
| 268 | + while (1) { |
| 269 | + for (itf = 0; itf < CFG_TUD_CDC; itf++) { |
| 270 | + update_uart_cfg(itf); |
| 271 | + uart_read_bytes(itf); |
| 272 | + uart_write_bytes(itf); |
210 | 273 | }
|
211 | 274 | }
|
212 | 275 |
|
|
0 commit comments