cmvr_head/board/ports/usb/usb_cdc_init.c

154 lines
4.1 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by Administrator on 2025/12/31.
//
#include "usb_cdc_char_device.h"
#include <board.h>
// 例如在 board init / main 里
int usb_init(void)
{
return rt_hw_usbd_cdc_char_init("cdc0", 0, USB_OTG_FS_PERIPH_BASE);
}
// INIT_APP_EXPORT(usb_init);
#include "usb_cdc_char_device.h" /* 为了 CDC_CTRL_GET_CONFIGURED */
/* 线程参数 */
#define CDC_ECHO_THREAD_NAME "cdc_echo"
#define CDC_ECHO_THREAD_STACK 4096
#define CDC_ECHO_THREAD_PRIO 20
#define CDC_ECHO_THREAD_TICK 10
/* 等待策略 */
#define CDC_WAIT_SEM_TIMEOUT_MS 500 /* 不要 FOREVER支持先启动后插线/断开重连 */
#define CDC_NOT_CFG_DELAY_MS 50
/* RX 等待信号量 */
static rt_sem_t s_cdc_rx_sem = RT_NULL;
/* 保存设备句柄 */
static rt_device_t s_cdc_dev = RT_NULL;
/* RX 回调:有数据到来时被驱动调用(或驱动事件里用 size=0 唤醒) */
static rt_err_t cdc_rx_ind(rt_device_t dev, rt_size_t size)
{
(void)dev;
(void)size;
if (s_cdc_rx_sem)
{
rt_sem_release(s_cdc_rx_sem);
}
return RT_EOK;
}
static int cdc_is_configured(rt_device_t dev)
{
uint8_t cfg = 0;
if (rt_device_control(dev, CDC_CTRL_GET_CONFIGURED, &cfg) == RT_EOK)
{
return cfg ? 1 : 0;
}
/* control 不支持时,保守认为未配置 */
return 0;
}
/* echo 线程:等待 -> 读 -> 立刻写回(支持断开重连) */
static void cdc_echo_thread(void *parameter)
{
(void)parameter;
s_cdc_dev = rt_device_find("cdc0");
if (!s_cdc_dev)
{
rt_kprintf("cdc_echo: cdc0 not found\n");
return;
}
if (rt_device_open(s_cdc_dev, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
{
rt_kprintf("cdc_echo: open cdc0 failed\n");
return;
}
s_cdc_rx_sem = rt_sem_create("cdc_rx", 0, RT_IPC_FLAG_FIFO);
if (!s_cdc_rx_sem)
{
rt_kprintf("cdc_echo: sem create failed\n");
rt_device_close(s_cdc_dev);
return;
}
rt_device_set_rx_indicate(s_cdc_dev, cdc_rx_ind);
rt_kprintf("cdc_echo: started, supports plug/unplug\n");
char buf[1024];
while (1)
{
/* 关键:不要 FOREVER避免未插线/断开时永远卡住 */
rt_sem_take(s_cdc_rx_sem, rt_tick_from_millisecond(CDC_WAIT_SEM_TIMEOUT_MS));
/* 没枚举好/断开:不读不写,稍等继续 */
if (!cdc_is_configured(s_cdc_dev))
{
rt_thread_mdelay(CDC_NOT_CFG_DELAY_MS);
continue;
}
/* 把 ringbuffer 里当前所有数据读光并回写 */
while (1)
{
rt_ssize_t rn = rt_device_read(s_cdc_dev, 0, buf, sizeof(buf));
if (rn > 0)
{
rt_ssize_t wn = rt_device_write(s_cdc_dev, 0, buf, (rt_size_t)rn);
if (wn < 0)
{
/* 典型:断开/未配置 => -RT_EIO */
rt_kprintf("cdc_echo: write err=%d\n", (int)wn);
break;
}
}
else if (rn == 0)
{
/* 暂时没数据 */
rt_kprintf("cdc_echo: read err=%d\n", (int)rn);
break;
}
else
{
/* rn < 0典型 -RT_EIO断开/未配置) */
rt_kprintf("cdc_echo: read err=%d\n", (int)rn);
break;
}
}
}
}
/* 创建并启动线程 */
int cdc_echo_start(void)
{
if (rt_thread_find(CDC_ECHO_THREAD_NAME))
{
rt_kprintf("cdc_echo: thread already running\n");
return -RT_EBUSY;
}
rt_thread_t tid = rt_thread_create(CDC_ECHO_THREAD_NAME,
cdc_echo_thread,
RT_NULL,
CDC_ECHO_THREAD_STACK,
CDC_ECHO_THREAD_PRIO,
CDC_ECHO_THREAD_TICK);
if (!tid)
{
rt_kprintf("cdc_echo: create thread failed\n");
return -RT_ENOMEM;
}
rt_thread_startup(tid);
return RT_EOK;
}
MSH_CMD_EXPORT(cdc_echo_start, start usb cdc echo thread);