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 <noltari@gmail.com>
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy