feat(usb_cdc): 添加USB CDC ACM控制台和日志后端支持

添加zephyr,console和zephyr,log-uart设备树配置,启用UART控制台和日志功能,
同时增加第二个CDC ACM UART实例用于控制台输出。在prj.conf中启用相关配置项。

refactor(protocol): 优化协议会话状态管理并增强日志记录

引入proto_session_set函数统一管理协议会话状态转换,添加详细的日志输出来跟踪
状态变化、消息处理和传输事件,提高系统的可调试性。

feat(usb_device): 增强USB设备模块状态跟踪和日志输出

为USB栈、总线和公共状态添加命名函数,实现详细的状态转换日志记录,包括USB
连接、断开、使能等关键事件的日志输出,便于系统调试和问题排查。
This commit is contained in:
2026-04-21 16:40:37 +08:00
parent 0a1357c62d
commit a11f4c0110
5 changed files with 265 additions and 6 deletions

View File

@@ -74,7 +74,7 @@ static struct usb_cdc_ctx ctx = {
.ops = &lifecycle_ops,
},
.business = USB_CDC_BUS_OFFLINE,
.cdc_dev = DEVICE_DT_GET_ONE(zephyr_cdc_acm_uart),
.cdc_dev = DEVICE_DT_GET(DT_NODELABEL(cdc_acm_uart0)),
.usb_active = false,
.proto_rx_len = 0U,
};
@@ -83,6 +83,32 @@ static struct usb_cdc_ctx ctx = {
static void validate_line_coding(void);
static const char *usb_cdc_business_state_name(enum usb_cdc_business_state state)
{
switch (state) {
case USB_CDC_BUS_OFFLINE:
return "BUS_OFFLINE";
case USB_CDC_WAIT_DTR:
return "WAIT_DTR";
case USB_CDC_SESSION_READY:
return "SESSION_READY";
default:
return "?";
}
}
static const char *proto_link_state_name(enum proto_transport_link_state state)
{
switch (state) {
case PROTO_TRANSPORT_LINK_DOWN:
return "DOWN";
case PROTO_TRANSPORT_LINK_READY:
return "READY";
default:
return "?";
}
}
static bool lifecycle_is_ready(void)
{
return module_lifecycle_is_running(&ctx.lc);
@@ -128,6 +154,7 @@ static void state_reconcile(enum module_lifecycle old_lifecycle,
if ((old_lifecycle == LC_RUNNING) &&
(old_business == USB_CDC_SESSION_READY) &&
(new_link == PROTO_TRANSPORT_LINK_DOWN)) {
LOG_INF("CDC reconcile: link READY -> DOWN, disable UART IO");
disable_uart_io();
}
@@ -135,6 +162,9 @@ static void state_reconcile(enum module_lifecycle old_lifecycle,
(new_link == PROTO_TRANSPORT_LINK_READY)) {
int err;
LOG_INF("CDC reconcile: link DOWN -> READY (business:%s usb_active:%u lc:%s)",
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
module_lifecycle_name(ctx.lc.state));
validate_line_coding();
err = uart_line_ctrl_set(ctx.cdc_dev, UART_LINE_CTRL_DCD, 1);
@@ -151,6 +181,11 @@ static void state_reconcile(enum module_lifecycle old_lifecycle,
}
if (old_link != new_link) {
LOG_INF("CDC link %s -> %s (business:%s usb_active:%u lc:%s)",
proto_link_state_name(old_link),
proto_link_state_name(new_link),
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
module_lifecycle_name(ctx.lc.state));
submit_proto_transport_state_event(PROTO_TRANSPORT_USB_CDC,
new_link);
}
@@ -166,11 +201,19 @@ static void business_state_set(enum usb_cdc_business_state new_state)
}
ctx.business = new_state;
LOG_INF("CDC business %s -> %s (usb_active:%u lc:%s)",
usb_cdc_business_state_name(old_business),
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
module_lifecycle_name(ctx.lc.state));
state_reconcile(old_lifecycle, old_business);
}
static void business_state_sync_from_usb(void)
{
LOG_INF("CDC sync from USB (usb_active:%u business:%s lc:%s)",
ctx.usb_active, usb_cdc_business_state_name(ctx.business),
module_lifecycle_name(ctx.lc.state));
if (!ctx.usb_active) {
business_state_set(USB_CDC_BUS_OFFLINE);
return;
@@ -188,9 +231,14 @@ static void business_state_sync_from_usb(void)
static void kick_tx(void)
{
if (transport_link_state_get() != PROTO_TRANSPORT_LINK_READY) {
LOG_INF("CDC kick_tx skipped: link=%s business:%s usb_active:%u tx_rb:%u",
proto_link_state_name(transport_link_state_get()),
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
ring_buf_size_get(&ctx.tx_ringbuf));
return;
}
LOG_INF("CDC kick_tx: enable TX IRQ (tx_rb:%u)", ring_buf_size_get(&ctx.tx_ringbuf));
uart_irq_tx_enable(ctx.cdc_dev);
}
@@ -249,6 +297,9 @@ static void rx_work_handler(struct k_work *work)
return;
}
LOG_INF("CDC rx_work pulled %u bytes from RX ring (proto_rx_len:%u)",
(unsigned int)len, (unsigned int)ctx.proto_rx_len);
if ((ctx.proto_rx_len + len) > sizeof(proto_rx_buf)) {
LOG_WRN("Drop oversized CDC protobuf message len:%u",
(uint32_t)(ctx.proto_rx_len + len));
@@ -269,9 +320,14 @@ static void rx_flush_work_handler(struct k_work *work)
if ((transport_link_state_get() != PROTO_TRANSPORT_LINK_READY) ||
(ctx.proto_rx_len == 0U)) {
LOG_INF("CDC rx_flush skipped: link=%s proto_rx_len:%u business:%s",
proto_link_state_name(transport_link_state_get()),
(unsigned int)ctx.proto_rx_len,
usb_cdc_business_state_name(ctx.business));
return;
}
LOG_INF("CDC rx_flush submit proto_rx len:%u", (unsigned int)ctx.proto_rx_len);
(void)submit_proto_rx_event(PROTO_TRANSPORT_USB_CDC, proto_rx_buf,
ctx.proto_rx_len);
ctx.proto_rx_len = 0U;
@@ -304,6 +360,10 @@ static void cdc_interrupt_handler(const struct device *dev, void *user_data)
recv_len - (int)written);
}
LOG_INF("CDC IRQ RX recv:%d written:%u rx_rb:%u",
recv_len, (unsigned int)written,
ring_buf_size_get(&ctx.rx_ringbuf));
k_work_submit(&ctx.rx_work);
}
}
@@ -318,6 +378,7 @@ static void cdc_interrupt_handler(const struct device *dev, void *user_data)
irq_unlock(key);
if (len == 0U) {
LOG_INF("CDC IRQ TX ready but no pending data, disable TX IRQ");
uart_irq_tx_disable(dev);
continue;
}
@@ -330,6 +391,10 @@ static void cdc_interrupt_handler(const struct device *dev, void *user_data)
LOG_WRN("Drop %u CDC TX bytes",
(unsigned int)(len - (uint32_t)sent_len));
}
LOG_INF("CDC IRQ TX requested:%u sent:%d tx_rb_remain:%u",
(unsigned int)len, sent_len,
ring_buf_size_get(&ctx.tx_ringbuf));
}
}
}
@@ -348,6 +413,9 @@ static int do_init(void)
ctx.business = USB_CDC_BUS_OFFLINE;
ctx.usb_active = false;
ctx.proto_rx_len = 0U;
LOG_INF("CDC init done (business:%s usb_active:%u lc:%s dev:%p)",
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
module_lifecycle_name(ctx.lc.state), ctx.cdc_dev);
return 0;
}
@@ -359,6 +427,9 @@ static int do_start(void)
static int do_stop(void)
{
LOG_INF("CDC stop requested (business:%s usb_active:%u lc:%s)",
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
module_lifecycle_name(ctx.lc.state));
ctx.business = USB_CDC_BUS_OFFLINE;
return 0;
}
@@ -379,6 +450,11 @@ static int apply_lifecycle(enum module_lifecycle target)
business_state_sync_from_usb();
}
LOG_INF("CDC lifecycle %s -> %s done (business:%s usb_active:%u link:%s)",
module_lifecycle_name(old_lifecycle), module_lifecycle_name(target),
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
proto_link_state_name(transport_link_state_get()));
return 0;
}
@@ -391,6 +467,10 @@ static bool handle_usb_state_event(const struct usb_state_event *event)
}
ctx.usb_active = new_usb_active;
LOG_INF("CDC usb_active -> %u from usb_state:%d (business:%s lc:%s)",
ctx.usb_active, event->state,
usb_cdc_business_state_name(ctx.business),
module_lifecycle_name(ctx.lc.state));
business_state_sync_from_usb();
return false;
@@ -404,7 +484,13 @@ static bool handle_usb_control_event(const struct usb_control_event *event)
switch (event->type) {
case USB_CONTROL_EVENT_CDC_LINE_STATE:
LOG_INF("CDC control event line_state dtr:%u usb_active:%u lc:%s business:%s",
event->data.cdc_line_state.dtr, ctx.usb_active,
module_lifecycle_name(ctx.lc.state),
usb_cdc_business_state_name(ctx.business));
if (!ctx.usb_active || !lifecycle_is_ready()) {
LOG_INF("CDC line_state ignored: usb_active:%u lc:%s",
ctx.usb_active, module_lifecycle_name(ctx.lc.state));
return false;
}
@@ -419,6 +505,13 @@ static bool handle_usb_control_event(const struct usb_control_event *event)
return false;
case USB_CONTROL_EVENT_CDC_LINE_CODING:
LOG_INF("CDC control event line_coding baud:%u data:%u stop:%u parity:%u flow:%u business:%s",
event->data.cdc_line_coding.baudrate,
event->data.cdc_line_coding.data_bits,
event->data.cdc_line_coding.stop_bits,
event->data.cdc_line_coding.parity,
event->data.cdc_line_coding.flow_ctrl,
usb_cdc_business_state_name(ctx.business));
if (event->data.cdc_line_coding.baudrate != 0U) {
LOG_INF("CDC baudrate %u",
event->data.cdc_line_coding.baudrate);
@@ -459,6 +552,10 @@ static bool handle_proto_tx_event(const struct proto_tx_event *event)
}
if (transport_link_state_get() != PROTO_TRANSPORT_LINK_READY) {
LOG_INF("CDC proto_tx ignored len:%u link:%s business:%s usb_active:%u",
(unsigned int)event->dyndata.size,
proto_link_state_name(transport_link_state_get()),
usb_cdc_business_state_name(ctx.business), ctx.usb_active);
return false;
}
@@ -467,6 +564,10 @@ static bool handle_proto_tx_event(const struct proto_tx_event *event)
(uint32_t)event->dyndata.size);
irq_unlock(key);
LOG_INF("CDC proto_tx queued len:%u written:%u tx_rb:%u",
(unsigned int)event->dyndata.size, (unsigned int)written,
ring_buf_size_get(&ctx.tx_ringbuf));
if (written < event->dyndata.size) {
LOG_WRN("Drop %zu CDC TX bytes", event->dyndata.size - written);
}