Skip to content

Commit 410eef1

Browse files
committed
uart-bridge: expose both HW UARTs
With these changes, both HW UARTs will be exposed as two independent USB-UART bridge controllers. Signed-off-by: Álvaro Fernández Rojas <[email protected]>
1 parent 911bf03 commit 410eef1

File tree

4 files changed

+224
-107
lines changed

4 files changed

+224
-107
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ pico_sdk_init()
1111
add_executable(uart_bridge uart-bridge.c usb-descriptors.c)
1212

1313
target_include_directories(uart_bridge PUBLIC
14-
pico-sdk/lib/tinyusb/src
15-
pico-sdk/src/rp2_common/pico_stdio_usb/include)
14+
./
15+
pico-sdk/lib/tinyusb/src)
1616

1717
target_link_libraries(uart_bridge
1818
pico_multicore

tusb_config.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
5+
* Copyright (c) 2020 Damien P. George
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*
25+
*/
26+
27+
#ifndef _PICO_STDIO_USB_TUSB_CONFIG_H
28+
#define _PICO_STDIO_USB_TUSB_CONFIG_H
29+
30+
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE)
31+
32+
#define CFG_TUD_CDC (2)
33+
#define CFG_TUD_CDC_RX_BUFSIZE (256)
34+
#define CFG_TUD_CDC_TX_BUFSIZE (256)
35+
36+
#endif

uart-bridge.c

Lines changed: 164 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -7,42 +7,52 @@
77
#include <hardware/structs/sio.h>
88
#include <hardware/uart.h>
99
#include <pico/multicore.h>
10-
#include <pico/stdio_usb.h>
1110
#include <pico/stdlib.h>
1211
#include <tusb.h>
13-
#include <string.h>
1412

1513
#if !defined(MIN)
1614
#define MIN(a, b) ((a > b) ? b : a)
1715
#endif /* MIN */
1816

1917
#define LED_PIN 25
2018

21-
#define UART_ID uart0
22-
#define UART_TX_PIN 0
23-
#define UART_RX_PIN 1
24-
2519
#define BUFFER_SIZE 64
2620

2721
#define DEF_BIT_RATE 115200
2822
#define DEF_STOP_BITS 1
2923
#define DEF_PARITY 0
3024
#define DEF_DATA_BITS 8
3125

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+
}
3753
};
3854

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];
4656

4757
static inline uint databits_usb2uart(uint8_t data_bits)
4858
{
@@ -80,133 +90,186 @@ static inline uint stopbits_usb2uart(uint8_t stop_bits)
8090
}
8191
}
8292

83-
int update_uart_cfg(void)
93+
void update_uart_cfg(uint8_t itf)
8494
{
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];
9797

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;
105101
}
106102

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+
}
111114
}
112115

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);
117118

118-
tud_cdc_get_line_coding(&CDC_LC);
119+
if (len) {
120+
uart_data_t *ud = &UART_DATA[itf];
119121

120-
/* Read bytes from USB */
121-
if (tud_cdc_available()) {
122-
mutex_enter_blocking(&USB_MTX);
122+
mutex_enter_blocking(&ud->usb_mtx);
123123

124-
len = MIN(tud_cdc_available(), BUFFER_SIZE - USB_POS);
124+
len = MIN(len, BUFFER_SIZE - ud->usb_pos);
125125
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;
128130
}
129131

130-
mutex_exit(&USB_MTX);
132+
mutex_exit(&ud->usb_mtx);
131133
}
134+
}
132135

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];
136138

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);
138145
if (count) {
139-
UART_POS -= count;
140-
tud_cdc_write_flush();
146+
ud->uart_pos -= count;
147+
tud_cdc_n_write_flush(itf);
141148
}
142149

143-
mutex_exit(&UART_MTX);
150+
mutex_exit(&ud->uart_mtx);
144151
}
145152
}
146153

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+
147164
void core1_entry(void)
148165
{
149166
tusb_init();
150167

151168
while (1) {
152-
tud_task();
169+
int itf;
170+
int con = 0;
153171

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+
}
159179
}
180+
181+
gpio_put(LED_PIN, con);
160182
}
161183
}
162184

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];
167187

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];
170190

171-
gpio_init(LED_PIN);
172-
gpio_set_dir(LED_PIN, GPIO_OUT);
191+
mutex_enter_blocking(&ud->uart_mtx);
173192

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+
}
175198

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+
}
178202

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];
183205

184-
multicore_launch_core1(core1_entry);
206+
if (ud->usb_pos) {
207+
const uart_id_t *ui = &UART_ID[itf];
185208

186-
while (1) {
187-
update_uart_cfg();
209+
mutex_enter_blocking(&ud->usb_mtx);
188210

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;
192213

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+
}
198217

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+
}
201253

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;
205259

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);
208262

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);
210273
}
211274
}
212275

0 commit comments

Comments
 (0)