samples: usb: get CDC ACM UART device from devicetree

Add app.overlay which contains cdc-acm-uart nodes.
Rework CDC ACM and HID samples to get CDC ACM UART device
from devicetree.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
This commit is contained in:
Johann Fischer 2021-07-22 14:42:16 +02:00 committed by Christopher Friedt
commit 020843f249
10 changed files with 145 additions and 112 deletions

View file

@ -0,0 +1,12 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
&zephyr_udc0 {
cdc_acm_uart0 {
compatible = "zephyr,cdc-acm-uart";
label = "CDC_ACM_0";
};
};

View file

@ -3,7 +3,6 @@ CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC ACM sample"
CONFIG_LOG=y
CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y
CONFIG_USB_CDC_ACM=y
CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y
CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y

View file

@ -78,9 +78,9 @@ void main(void)
uint32_t baudrate, dtr = 0U;
int ret;
dev = device_get_binding("CDC_ACM_0");
if (!dev) {
LOG_ERR("CDC ACM device not found");
dev = DEVICE_DT_GET_ONE(zephyr_cdc_acm_uart);
if (!device_is_ready(dev)) {
LOG_ERR("CDC ACM device not ready");
return;
}

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
&zephyr_udc0 {
cdc_acm_uart0 {
compatible = "zephyr,cdc-acm-uart";
label = "CDC_ACM_0";
};
cdc_acm_uart1 {
compatible = "zephyr,cdc-acm-uart";
label = "CDC_ACM_1";
};
};

View file

@ -7,8 +7,6 @@ CONFIG_UART_LINE_CTRL=y
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC ACM Composite sample"
CONFIG_USB_COMPOSITE_DEVICE=y
CONFIG_USB_CDC_ACM=y
CONFIG_USB_CDC_ACM_DEVICE_COUNT=2
CONFIG_USB_CDC_ACM_RINGBUF_SIZE=512
CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y

View file

@ -28,38 +28,42 @@ LOG_MODULE_REGISTER(cdc_acm_composite, LOG_LEVEL_INF);
uint8_t buffer0[RING_BUF_SIZE];
uint8_t buffer1[RING_BUF_SIZE];
static struct serial_data {
const struct device *peer;
struct serial_data *peer_data;
struct ring_buf ringbuf;
} peers[2];
struct serial_peer {
const struct device *dev;
struct serial_peer *data;
struct ring_buf rb;
};
#define DEFINE_SERIAL_PEER(node_id) { .dev = DEVICE_DT_GET(node_id), },
static struct serial_peer peers[] = {
DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEFINE_SERIAL_PEER)
};
BUILD_ASSERT(ARRAY_SIZE(peers) >= 2, "Not enough CDC ACM instances");
static void interrupt_handler(const struct device *dev, void *user_data)
{
struct serial_data *dev_data = user_data;
struct serial_peer *peer = user_data;
while (uart_irq_update(dev) && uart_irq_is_pending(dev)) {
const struct device *peer = dev_data->peer;
LOG_DBG("dev %p dev_data %p", dev, dev_data);
LOG_DBG("dev %p peer %p", dev, peer);
if (uart_irq_rx_ready(dev)) {
uint8_t buf[64];
size_t read, wrote;
struct ring_buf *ringbuf =
&dev_data->peer_data->ringbuf;
struct ring_buf *rb = &peer->data->rb;
read = uart_fifo_read(dev, buf, sizeof(buf));
if (read) {
wrote = ring_buf_put(ringbuf, buf, read);
wrote = ring_buf_put(rb, buf, read);
if (wrote < read) {
LOG_ERR("Drop %zu bytes", read - wrote);
}
uart_irq_tx_enable(dev_data->peer);
uart_irq_tx_enable(peer->dev);
LOG_DBG("dev %p -> dev %p send %zu bytes",
dev, peer, wrote);
dev, peer->dev, wrote);
}
}
@ -67,8 +71,7 @@ static void interrupt_handler(const struct device *dev, void *user_data)
uint8_t buf[64];
size_t wrote, len;
len = ring_buf_get(&dev_data->ringbuf, buf,
sizeof(buf));
len = ring_buf_get(&peer->rb, buf, sizeof(buf));
if (!len) {
LOG_DBG("dev %p TX buffer empty", dev);
uart_irq_tx_disable(dev);
@ -109,23 +112,15 @@ static void uart_line_set(const struct device *dev)
void main(void)
{
uint32_t dtr = 0U;
int ret;
struct serial_data *dev_data0 = &peers[0];
struct serial_data *dev_data1 = &peers[1];
const struct device *dev0, *dev1;
uint32_t dtr = 0U;
dev0 = device_get_binding("CDC_ACM_0");
if (!dev0) {
LOG_DBG("CDC_ACM_0 device not found");
for (int idx = 0; idx < ARRAY_SIZE(peers); idx++) {
if (!device_is_ready(peers[idx].dev)) {
LOG_ERR("CDC ACM device %s is not ready",
peers[idx].dev->name);
return;
}
dev1 = device_get_binding("CDC_ACM_1");
if (!dev1) {
LOG_DBG("CDC_ACM_1 device not found");
return;
}
ret = usb_enable(NULL);
@ -137,7 +132,7 @@ void main(void)
LOG_INF("Wait for DTR");
while (1) {
uart_line_ctrl_get(dev0, UART_LINE_CTRL_DTR, &dtr);
uart_line_ctrl_get(peers[0].dev, UART_LINE_CTRL_DTR, &dtr);
if (dtr) {
break;
}
@ -146,7 +141,7 @@ void main(void)
}
while (1) {
uart_line_ctrl_get(dev1, UART_LINE_CTRL_DTR, &dtr);
uart_line_ctrl_get(peers[1].dev, UART_LINE_CTRL_DTR, &dtr);
if (dtr) {
break;
}
@ -156,21 +151,19 @@ void main(void)
LOG_INF("DTR set, start test");
uart_line_set(dev0);
uart_line_set(dev1);
uart_line_set(peers[0].dev);
uart_line_set(peers[1].dev);
dev_data0->peer = dev1;
dev_data0->peer_data = dev_data1;
ring_buf_init(&dev_data0->ringbuf, sizeof(buffer0), buffer0);
peers[0].data = &peers[1];
peers[1].data = &peers[0];
dev_data1->peer = dev0;
dev_data1->peer_data = dev_data0;
ring_buf_init(&dev_data1->ringbuf, sizeof(buffer1), buffer1);
ring_buf_init(&peers[0].rb, sizeof(buffer0), buffer0);
ring_buf_init(&peers[1].rb, sizeof(buffer1), buffer1);
uart_irq_callback_user_data_set(dev0, interrupt_handler, dev_data0);
uart_irq_callback_user_data_set(dev1, interrupt_handler, dev_data1);
uart_irq_callback_user_data_set(peers[1].dev, interrupt_handler, &peers[0]);
uart_irq_callback_user_data_set(peers[0].dev, interrupt_handler, &peers[1]);
/* Enable rx interrupts */
uart_irq_rx_enable(dev0);
uart_irq_rx_enable(dev1);
uart_irq_rx_enable(peers[0].dev);
uart_irq_rx_enable(peers[1].dev);
}

View file

@ -79,7 +79,7 @@ After both ports have been connected to, messages explaining usage of each port
.. code-block:: console
Welcome to CDC ACM 0!
Welcome to CDC_ACM_0
Supported commands:
up - moves the mouse up
down - moves the mouse down
@ -88,7 +88,7 @@ After both ports have been connected to, messages explaining usage of each port
.. code-block:: console
Welcome to CDC ACM 1!
Welcome to CDC_ACM_1
Enter a string and terminate it with ENTER.
It will be sent via HID when BUTTON 2 is pressed.
You can modify it by sending a new one here.

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
&zephyr_udc0 {
cdc_acm_uart0 {
compatible = "zephyr,cdc-acm-uart";
label = "CDC_ACM_0";
};
cdc_acm_uart1 {
compatible = "zephyr,cdc-acm-uart";
label = "CDC_ACM_1";
};
};

View file

@ -11,11 +11,7 @@ CONFIG_LOG=y
CONFIG_USB_DRIVER_LOG_LEVEL_INF=y
CONFIG_USB_DEVICE_LOG_LEVEL_INF=y
CONFIG_USB_CDC_ACM=y
CONFIG_USB_CDC_ACM_DEVICE_COUNT=2
CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_UART_LINE_CTRL=y
CONFIG_GPIO=y

View file

@ -159,13 +159,14 @@ static uint8_t chr_ptr_mouse, chr_ptr_kbd, str_pointer;
#define MOUSE_BTN_RIGHT BIT(1)
#define MOUSE_BTN_MIDDLE BIT(2)
static const char *banner0 = "Welcome to CDC ACM 0!\r\n"
static const char *welcome = "Welcome to ";
static const char *banner0 = "\r\n"
"Supported commands:\r\n"
"up - moves the mouse up\r\n"
"down - moves the mouse down\r\n"
"right - moves the mouse to right\r\n"
"left - moves the mouse to left\r\n";
static const char *banner1 = "Welcome to CDC ACM 1!\r\n"
static const char *banner1 = "\r\n"
"Enter a string and terminate "
"it with ENTER.\r\n"
"It will be sent via HID "
@ -545,13 +546,18 @@ static void status_cb(enum usb_dc_status_code status, const uint8_t *param)
LOG_INF("Status %d", status);
}
#define DEVICE_AND_COMMA(node_id) DEVICE_DT_GET(node_id),
void main(void)
{
int ret;
const struct device *hid0_dev, *hid1_dev, *cdc0_dev, *cdc1_dev;
uint32_t dtr = 0U;
const struct device *cdc_dev[] = {
DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEVICE_AND_COMMA)
};
BUILD_ASSERT(ARRAY_SIZE(cdc_dev) >= 2, "Not enough CDC ACM instances");
const struct device *hid0_dev, *hid1_dev;
struct app_evt_t *ev;
uint32_t dtr = 0U;
int ret;
/* Configure devices */
@ -567,16 +573,12 @@ void main(void)
return;
}
cdc0_dev = device_get_binding("CDC_ACM_0");
if (cdc0_dev == NULL) {
LOG_ERR("Cannot get USB CDC 0 Device");
for (int idx = 0; idx < ARRAY_SIZE(cdc_dev); idx++) {
if (!device_is_ready(cdc_dev[idx])) {
LOG_ERR("CDC ACM device %s is not ready",
cdc_dev[idx]->name);
return;
}
cdc1_dev = device_get_binding("CDC_ACM_1");
if (cdc1_dev == NULL) {
LOG_ERR("Cannot get USB CDC 1 Device");
return;
}
if (callbacks_configure(device_get_binding(PORT0), PIN0, PIN0_FLAGS,
@ -627,36 +629,35 @@ void main(void)
}
/* Initialize CDC ACM */
LOG_INF("Wait for DTR on CDC ACM 0");
for (int idx = 0; idx < ARRAY_SIZE(cdc_dev); idx++) {
LOG_INF("Wait for DTR on %s", cdc_dev[idx]->name);
while (1) {
uart_line_ctrl_get(cdc0_dev, UART_LINE_CTRL_DTR, &dtr);
uart_line_ctrl_get(cdc_dev[idx],
UART_LINE_CTRL_DTR,
&dtr);
if (dtr) {
break;
}
}
LOG_INF("DTR on CDC ACM 0 set");
LOG_INF("Wait for DTR on CDC ACM 1");
while (1) {
uart_line_ctrl_get(cdc1_dev, UART_LINE_CTRL_DTR, &dtr);
if (dtr) {
break;
LOG_INF("DTR on device %s", cdc_dev[idx]->name);
}
}
LOG_INF("DTR on CDC ACM 1 set");
/* Wait 1 sec for the host to do all settings */
k_busy_wait(USEC_PER_SEC);
uart_irq_callback_set(cdc0_dev, cdc_mouse_int_handler);
uart_irq_callback_set(cdc1_dev, cdc_kbd_int_handler);
uart_irq_callback_set(cdc_dev[0], cdc_mouse_int_handler);
uart_irq_callback_set(cdc_dev[1], cdc_kbd_int_handler);
write_data(cdc0_dev, banner0, strlen(banner0));
write_data(cdc1_dev, banner1, strlen(banner1));
write_data(cdc_dev[0], welcome, strlen(welcome));
write_data(cdc_dev[0], cdc_dev[0]->name, strlen(cdc_dev[0]->name));
write_data(cdc_dev[0], banner0, strlen(banner0));
write_data(cdc_dev[1], welcome, strlen(welcome));
write_data(cdc_dev[1], cdc_dev[1]->name, strlen(cdc_dev[1]->name));
write_data(cdc_dev[1], banner1, strlen(banner1));
uart_irq_rx_enable(cdc0_dev);
uart_irq_rx_enable(cdc1_dev);
uart_irq_rx_enable(cdc_dev[0]);
uart_irq_rx_enable(cdc_dev[1]);
while (true) {
k_sem_take(&evt_sem, K_FOREVER);
@ -672,7 +673,7 @@ void main(void)
k_sem_take(&usb_sem, K_FOREVER);
hid_int_ep_write(hid0_dev, rep,
sizeof(rep), NULL);
write_data(cdc0_dev, gpio0, strlen(gpio0));
write_data(cdc_dev[0], gpio0, strlen(gpio0));
clear_mouse_report();
break;
}
@ -685,14 +686,14 @@ void main(void)
k_sem_take(&usb_sem, K_FOREVER);
hid_int_ep_write(hid0_dev, rep,
sizeof(rep), NULL);
write_data(cdc0_dev, gpio1, strlen(gpio1));
write_data(cdc_dev[0], gpio1, strlen(gpio1));
clear_mouse_report();
break;
}
case GPIO_BUTTON_2:
{
/* Send string on HID keyboard */
write_data(cdc1_dev, gpio2, strlen(gpio2));
write_data(cdc_dev[1], gpio2, strlen(gpio2));
if (strlen(string) > 0) {
struct app_evt_t *ev = app_evt_alloc();
@ -713,7 +714,7 @@ void main(void)
k_sem_take(&usb_sem, K_FOREVER);
hid_int_ep_write(hid1_dev, rep,
sizeof(rep), NULL);
write_data(cdc1_dev, gpio3, strlen(gpio3));
write_data(cdc_dev[1], gpio3, strlen(gpio3));
clear_kbd_report();
break;
}
@ -725,7 +726,7 @@ void main(void)
k_sem_take(&usb_sem, K_FOREVER);
hid_int_ep_write(hid0_dev, rep,
sizeof(rep), NULL);
write_data(cdc0_dev, up, strlen(up));
write_data(cdc_dev[0], up, strlen(up));
clear_mouse_report();
break;
}
@ -737,7 +738,7 @@ void main(void)
k_sem_take(&usb_sem, K_FOREVER);
hid_int_ep_write(hid0_dev, rep,
sizeof(rep), NULL);
write_data(cdc0_dev, down, strlen(down));
write_data(cdc_dev[0], down, strlen(down));
clear_mouse_report();
break;
}
@ -749,7 +750,7 @@ void main(void)
k_sem_take(&usb_sem, K_FOREVER);
hid_int_ep_write(hid0_dev, rep,
sizeof(rep), NULL);
write_data(cdc0_dev, right, strlen(right));
write_data(cdc_dev[0], right, strlen(right));
clear_mouse_report();
break;
}
@ -761,25 +762,25 @@ void main(void)
k_sem_take(&usb_sem, K_FOREVER);
hid_int_ep_write(hid0_dev, rep,
sizeof(rep), NULL);
write_data(cdc0_dev, left, strlen(left));
write_data(cdc_dev[0], left, strlen(left));
clear_mouse_report();
break;
}
case CDC_UNKNOWN:
{
write_data(cdc0_dev, unknown, strlen(unknown));
write_data(cdc1_dev, unknown, strlen(unknown));
write_data(cdc_dev[0], unknown, strlen(unknown));
write_data(cdc_dev[1], unknown, strlen(unknown));
break;
}
case CDC_STRING:
{
write_data(cdc0_dev, set_str, strlen(set_str));
write_data(cdc0_dev, string, strlen(string));
write_data(cdc0_dev, endl, strlen(endl));
write_data(cdc_dev[0], set_str, strlen(set_str));
write_data(cdc_dev[0], string, strlen(string));
write_data(cdc_dev[0], endl, strlen(endl));
write_data(cdc1_dev, set_str, strlen(set_str));
write_data(cdc1_dev, string, strlen(string));
write_data(cdc1_dev, endl, strlen(endl));
write_data(cdc_dev[1], set_str, strlen(set_str));
write_data(cdc_dev[1], string, strlen(string));
write_data(cdc_dev[1], endl, strlen(endl));
break;
}
case HID_MOUSE_CLEAR:
@ -841,9 +842,9 @@ void main(void)
default:
{
LOG_ERR("Unknown event to execute");
write_data(cdc0_dev, evt_fail,
write_data(cdc_dev[0], evt_fail,
strlen(evt_fail));
write_data(cdc1_dev, evt_fail,
write_data(cdc_dev[1], evt_fail,
strlen(evt_fail));
break;
}