Hi all,
I am currently trying to realize a USB to Uart bridge with the nRF52840 development kit.
I used an old sample as a starting point for this task namely the "usb_uart_bridge" which was present in the SDK version 1.4:
https://github.com/nrfconnect/sdk-nrf/tree/v1.4-branch/samples/usb/usb_uart_bridge
Unfortunately I am not able to port/ to adapt the sample to my needs and a newer version of the SSK(1.8).
The sample builds fine, but when sending something via USB I get a hard fault error.
Is there a reason why this sample was discontinued? Could somebody please help me to port this sample to a newer SDK version or point to a similar sample in a newer version of the SDK?
I am working in the Segger Studio and with the standard nRF52840 DK board here is my adapted code:
#include <zephyr.h> #include <stdio.h> #include <string.h> #include <device.h> #include <drivers/uart.h> #include <sys/ring_buffer.h> #include <usb/usb_device.h> #include <logging/log.h> #include <uart_communication.h> #include <sys/reboot.h> #define UART_BUF_SIZE 500 static K_FIFO_DEFINE(usb_0_tx_fifo); static K_FIFO_DEFINE(uart_1_tx_fifo); struct uart_data { void *fifo_reserved; uint8_t buffer[UART_BUF_SIZE]; uint16_t len; }uart_data_t; static struct serial_dev { const struct device *dev; void *peer; struct k_fifo *fifo; struct k_sem sem; struct uart_data *rx; } devs[2]; /* Frees data for incoming transmission on device blocked by full heap. */ static int oom_free(struct serial_dev *sd) { struct serial_dev *peer_sd = (struct serial_dev *)sd->peer; struct uart_data *buf; /* First, try to free from FIFO of peer device (blocked stream) */ buf = k_fifo_get(peer_sd->fifo, K_NO_WAIT); if (buf) { k_free(buf); return 0; } /* Then, try FIFO of the receiving device (reverse of blocked stream) */ buf = k_fifo_get(sd->fifo, K_NO_WAIT); if (buf) { k_free(buf); return 0; } /* Finally, try all of them */ for (int i = 0; i < ARRAY_SIZE(devs); i++) { buf = k_fifo_get(sd->fifo, K_NO_WAIT); if (buf) { k_free(buf); return 0; } } return -1; /* Was not able to free any heap memory */ } static void uart_interrupt_handler(void *user_data) { struct serial_dev *sd = user_data; struct device *dev = sd->dev; struct serial_dev *peer_sd = (struct serial_dev *)sd->peer; uart_irq_update(dev); while (uart_irq_rx_ready(dev)) { int data_length; while (!sd->rx) { sd->rx = k_malloc(sizeof(*sd->rx)); if (sd->rx) { sd->rx->len = 0; } else { int err = oom_free(sd); if (err) { printk("Could not free memory. Rebooting.\n"); sys_reboot(SYS_REBOOT_COLD); } } } data_length = uart_fifo_read(dev, &sd->rx->buffer[sd->rx->len], UART_BUF_SIZE - sd->rx->len); sd->rx->len += data_length; if (sd->rx->len > 0) { if ((sd->rx->len == UART_BUF_SIZE) || (sd->rx->buffer[sd->rx->len - 1] == '\n') || (sd->rx->buffer[sd->rx->len - 1] == '\r') || (sd->rx->buffer[sd->rx->len - 1] == '\0')) { k_fifo_put(peer_sd->fifo, sd->rx); k_sem_give(&peer_sd->sem); sd->rx = NULL; } } } if (uart_irq_tx_ready(dev)) { struct uart_data *buf = k_fifo_get(sd->fifo, K_NO_WAIT); uint16_t written = 0; /* Nothing in the FIFO, nothing to send */ if (!buf) { uart_irq_tx_disable(dev); return; } while (buf->len > written) { written += uart_fifo_fill(dev, &buf->buffer[written], buf->len - written); } while (!uart_irq_tx_complete(dev)) { /* Wait for the last byte to get * shifted out of the module */ } if (k_fifo_is_empty(sd->fifo)) { uart_irq_tx_disable(dev); } k_free(buf); } } void main(void) { int ret; struct serial_dev *usb_0_sd = &devs[0]; struct serial_dev *uart_1_sd =&devs[1]; const struct device *usb_0_dev; const struct device *uart_1_dev; usb_0_dev = device_get_binding("CDC_ACM_0"); if (!usb_0_dev) { printk("CDC ACM device not found\n"); return; } uart_1_dev = device_get_binding("UART_1"); if (!uart_1_dev) { printk("UART 1 init failed\n"); } usb_0_sd->dev = usb_0_dev; usb_0_sd->fifo = &usb_0_tx_fifo; usb_0_sd->peer = uart_1_sd; uart_1_sd->dev = uart_1_dev; uart_1_sd->fifo = &uart_1_tx_fifo; uart_1_sd->peer = usb_0_sd; k_sem_init(&usb_0_sd->sem, 0, 1); k_sem_init(&uart_1_sd->sem, 0, 1); uart_irq_callback_user_data_set(usb_0_dev, uart_interrupt_handler, usb_0_sd); uart_irq_callback_user_data_set(uart_1_dev, uart_interrupt_handler, uart_1_sd); ret = usb_enable(NULL); if (ret != 0) { printk("Failed to enable USB\n"); return; } uart_irq_rx_enable(usb_0_dev); uart_irq_rx_enable(uart_1_dev); printk("USB <--> UART bridge is now initialized\n"); struct k_poll_event events[2] = { K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, &usb_0_sd->sem, 0), K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, &uart_1_sd->sem, 0), }; while (1) { ret = k_poll(events, ARRAY_SIZE(events), K_FOREVER); if (ret != 0) { continue; } if (events[0].state == K_POLL_TYPE_SEM_AVAILABLE) { events[0].state = K_POLL_STATE_NOT_READY; k_sem_take(&usb_0_sd->sem, K_NO_WAIT); uart_irq_tx_enable(usb_0_dev); } else if (events[1].state == K_POLL_TYPE_SEM_AVAILABLE) { events[1].state = K_POLL_STATE_NOT_READY; k_sem_take(&uart_1_sd->sem, K_NO_WAIT); uart_irq_tx_enable(uart_1_dev); } } }
Regards,
Andreas