Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug #20 (Cleanup of #24) #25

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 90 additions & 46 deletions uart-bridge.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: MIT
/*
* Copyright 2021 Álvaro Fernández Rojas <[email protected]>
* Cleanup/modifications Copyright 2023 Andrew J. Kroll <xxxajk at gmail>
*
*/

#include <hardware/irq.h>
Expand All @@ -19,6 +21,12 @@

#define BUFFER_SIZE 2560

#define UART0_TX 16
#define UART0_RX 17

#define UART1_TX 4
#define UART1_RX 5

#define DEF_BIT_RATE 115200
#define DEF_STOP_BITS 1
#define DEF_PARITY 0
Expand Down Expand Up @@ -52,18 +60,19 @@ const uart_id_t UART_ID[CFG_TUD_CDC] = {
.inst = uart0,
.irq = UART0_IRQ,
.irq_fn = &uart0_irq_fn,
.tx_pin = 16,
.rx_pin = 17,
.tx_pin = UART0_TX,
.rx_pin = UART0_RX,
}, {
.inst = uart1,
.irq = UART1_IRQ,
.irq_fn = &uart1_irq_fn,
.tx_pin = 4,
.rx_pin = 5,
.tx_pin = UART1_TX,
.rx_pin = UART1_RX,
}
};

uart_data_t UART_DATA[CFG_TUD_CDC];
volatile bool ready = false;

static inline uint databits_usb2uart(uint8_t data_bits)
{
Expand Down Expand Up @@ -151,21 +160,41 @@ void usb_write_bytes(uint8_t itf)
{
uart_data_t *ud = &UART_DATA[itf];

if (ud->uart_pos &&
mutex_try_enter(&ud->uart_mtx, NULL)) {
uint32_t count;
if (ud->uart_pos) {
if (mutex_try_enter(&ud->uart_mtx, NULL)) {
uint32_t count = tud_cdc_n_write(itf, ud->uart_buffer, ud->uart_pos);
// horrible! should use ring buffers!!
if (count < ud->uart_pos) {
memmove(ud->uart_buffer, &ud->uart_buffer[count], ud->uart_pos - count);
}
ud->uart_pos -= count;
mutex_exit(&ud->uart_mtx);

count = tud_cdc_n_write(itf, ud->uart_buffer, ud->uart_pos);
if (count < ud->uart_pos)
memmove(ud->uart_buffer, &ud->uart_buffer[count],
ud->uart_pos - count);
ud->uart_pos -= count;
if (count)
tud_cdc_n_write_flush(itf);
}
}
}

mutex_exit(&ud->uart_mtx);
void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms)
{
const uart_id_t *ui = &UART_ID[itf];
uart_data_t *ud = &UART_DATA[itf];

if (count)
tud_cdc_n_write_flush(itf);
// is mutex for tx even needed??
//mutex_enter_blocking(&ud->lc_mtx);

if (duration_ms == 0xffff) {
uart_set_break(ui->inst, true);
} else if (duration_ms == 0x0000) {
uart_set_break(ui->inst, false);
} else {
// should be correct for non-compliant stacks?
uart_set_break(ui->inst, true);
sleep_ms(duration_ms);
uart_set_break(ui->inst, false);
}
//mutex_exit(&ud->lc_mtx);
}

void usb_cdc_process(uint8_t itf)
Expand All @@ -183,17 +212,19 @@ void usb_cdc_process(uint8_t itf)
void core1_entry(void)
{
tusb_init();
ready = true;

while (1) {
int itf;
int con = 0;

tud_task();

for (itf = 0; itf < CFG_TUD_CDC; itf++) {
if (tud_cdc_n_connected(itf)) {
con = 1;
usb_cdc_process(itf);
if (tud_ready()) { // we need to ignore DTR on the CDC side
for (itf = 0; itf < CFG_TUD_CDC; itf++) {
if (tud_cdc_n_connected(itf)) {
con = 1;
usb_cdc_process(itf);
}
}
}

Expand All @@ -209,12 +240,12 @@ static inline void uart_read_bytes(uint8_t itf)
if (uart_is_readable(ui->inst)) {
mutex_enter_blocking(&ud->uart_mtx);

while (uart_is_readable(ui->inst) &&
(ud->uart_pos < BUFFER_SIZE)) {
if (ud->uart_pos < BUFFER_SIZE) {
ud->uart_buffer[ud->uart_pos] = uart_getc(ui->inst);
ud->uart_pos++;
} else {
uart_getc(ui->inst); // drop it on the floor
}

mutex_exit(&ud->uart_mtx);
}
}
Expand All @@ -233,22 +264,17 @@ void uart_write_bytes(uint8_t itf)
{
uart_data_t *ud = &UART_DATA[itf];

if (ud->usb_pos &&
mutex_try_enter(&ud->usb_mtx, NULL)) {
if (ud->usb_pos && mutex_try_enter(&ud->usb_mtx, NULL)) {
const uart_id_t *ui = &UART_ID[itf];
uint32_t count = 0;

while (uart_is_writable(ui->inst) &&
count < ud->usb_pos) {
uart_putc_raw(ui->inst, ud->usb_buffer[count]);
count++;
// horrible! should use ring buffers!!
if (uart_is_writable(ui->inst)) { // && count < ud->usb_pos) {
uart_putc_raw(ui->inst, ud->usb_buffer[0]);
if (ud->usb_pos > 1) {
memmove(ud->usb_buffer, &ud->usb_buffer[1], ud->usb_pos - 1);
}
ud->usb_pos--;
}

if (count < ud->usb_pos)
memmove(ud->usb_buffer, &ud->usb_buffer[count],
ud->usb_pos - count);
ud->usb_pos -= count;

mutex_exit(&ud->usb_mtx);
}
}
Expand All @@ -261,6 +287,7 @@ void init_uart_data(uint8_t itf)
/* Pinmux */
gpio_set_function(ui->tx_pin, GPIO_FUNC_UART);
gpio_set_function(ui->rx_pin, GPIO_FUNC_UART);
gpio_pull_up(ui->rx_pin); // important missed detail, prevents connection glitches

/* USB CDC LC */
ud->usb_lc.bit_rate = DEF_BIT_RATE;
Expand Down Expand Up @@ -290,31 +317,48 @@ void init_uart_data(uint8_t itf)
stopbits_usb2uart(ud->usb_lc.stop_bits),
parity_usb2uart(ud->usb_lc.parity));
uart_set_fifo_enabled(ui->inst, false);

uart_set_translate_crlf(ui->inst, false);
/* UART RX Interrupt */
irq_set_exclusive_handler(ui->irq, ui->irq_fn);
irq_set_enabled(ui->irq, true);
uart_set_irq_enables(ui->inst, true, false);
}

int main(void)
{
void start_uarts() {
uint8_t itf;
for (itf = 0; itf < CFG_TUD_CDC; itf++) {
init_uart_data(itf);
}

// enable ISRs
for (itf = 0; itf < CFG_TUD_CDC; itf++) {
const uart_id_t *ui = &UART_ID[itf];
irq_set_enabled(ui->irq, true);
uart_set_irq_enables(ui->inst, true, false);
}
}

int main(void) {
int itf;

multicore_reset_core1();

usbd_serial_init();

for (itf = 0; itf < CFG_TUD_CDC; itf++)
init_uart_data(itf);
start_uarts();

gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);

multicore_launch_core1(core1_entry);
do {
sleep_us(1);
} while (!ready);

while (1) {
for (itf = 0; itf < CFG_TUD_CDC; itf++) {
update_uart_cfg(itf);
uart_write_bytes(itf);
if (tud_ready()) {
for (itf = 0; itf < CFG_TUD_CDC; itf++) {
update_uart_cfg(itf);
uart_write_bytes(itf);
}
}
}

Expand Down
27 changes: 25 additions & 2 deletions usb-descriptors.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,29 @@
#include <hardware/flash.h>
#include <tusb.h>

#define TUD_CDC_BRK_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \
/* Interface Associate */\
8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, 0,\
/* CDC Control Interface */\
9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_NONE, _stridx,\
/* CDC Header */\
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\
/* CDC Call */\
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\
/* CDC ACM: support line request */\
4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 6,\
/* CDC Union */\
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\
/* Endpoint Notification */\
7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\
/* CDC Data Interface */\
9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\
/* Endpoint Out */\
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
/* Endpoint In */\
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0


#define DESC_STR_MAX 20

#define USBD_VID 0x2E8A /* Raspberry Pi */
Expand Down Expand Up @@ -64,11 +87,11 @@ static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = {
TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN,
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA),

TUD_CDC_DESCRIPTOR(USBD_ITF_CDC_0, USBD_STR_CDC, USBD_CDC_0_EP_CMD,
TUD_CDC_BRK_DESCRIPTOR(USBD_ITF_CDC_0, USBD_STR_CDC, USBD_CDC_0_EP_CMD,
USBD_CDC_CMD_MAX_SIZE, USBD_CDC_0_EP_OUT, USBD_CDC_0_EP_IN,
USBD_CDC_IN_OUT_MAX_SIZE),

TUD_CDC_DESCRIPTOR(USBD_ITF_CDC_1, USBD_STR_CDC, USBD_CDC_1_EP_CMD,
TUD_CDC_BRK_DESCRIPTOR(USBD_ITF_CDC_1, USBD_STR_CDC, USBD_CDC_1_EP_CMD,
USBD_CDC_CMD_MAX_SIZE, USBD_CDC_1_EP_OUT, USBD_CDC_1_EP_IN,
USBD_CDC_IN_OUT_MAX_SIZE),
};
Expand Down