本帖最后由 vsf 于 2018-4-18 13:43 编辑
首先,要启动USB,实现CDC协议,模拟一个串口。USB设备协议栈应用部分参考这里:https://bbs.21ic.com/icview-2496928-1-1.html。
usrapp.h
struct usrapp_t
{
struct
{
struct
{
struct vsfusbd_CDCACM_param_t param;
struct vsf_fifostream_t stream_tx;
struct vsf_fifostream_t stream_rx;
uint8_t txbuff[8 * 1024];
uint8_t rxbuff[512 + 1];
} cdc;
struct vsfusbd_iface_t ifaces[2];
struct vsfusbd_config_t config[1];
struct vsfusbd_device_t device;
} usbd;
};
这里,定义了USBD的数据结构,定义了CDC的相关参数,定义了CDC的数据流和缓冲。由于USB使用高速,所以一个USB报文是512字节。VSF中的fifo的实现方式需要实际数组长度+1,因为513字节缓冲中,实际能够写入的只有512字节。
usrapp.c
struct usrapp_t usrapp =
{
.usbd.cdc.param.CDC.ep_notify = 1,
.usbd.cdc.param.CDC.ep_out = 2,
.usbd.cdc.param.CDC.ep_in = 2,
.usbd.cdc.param.CDC.stream_tx = (struct vsf_stream_t *)&usrapp.usbd.cdc.stream_tx,
.usbd.cdc.param.CDC.stream_rx = (struct vsf_stream_t *)&usrapp.usbd.cdc.stream_rx,
.usbd.cdc.param.line_coding.bitrate = 115200,
.usbd.cdc.param.line_coding.stopbittype = 0,
.usbd.cdc.param.line_coding.paritytype = 0,
.usbd.cdc.param.line_coding.datatype = 8,
.usbd.cdc.stream_tx.stream.op = &fifostream_op,
.usbd.cdc.stream_tx.mem.buffer.buffer = (uint8_t *)&usrapp.usbd.cdc.txbuff,
.usbd.cdc.stream_tx.mem.buffer.size = sizeof(usrapp.usbd.cdc.txbuff),
.usbd.cdc.stream_rx.stream.op = &fifostream_op,
.usbd.cdc.stream_rx.mem.buffer.buffer = (uint8_t *)&usrapp.usbd.cdc.rxbuff,
.usbd.cdc.stream_rx.mem.buffer.size = sizeof(usrapp.usbd.cdc.rxbuff),
.usbd.ifaces[0].class_protocol = (struct vsfusbd_class_protocol_t *)&vsfusbd_CDCACMControl_class,
.usbd.ifaces[0].protocol_param = &usrapp.usbd.cdc.param,
.usbd.ifaces[1].class_protocol = (struct vsfusbd_class_protocol_t *)&vsfusbd_CDCACMData_class,
.usbd.ifaces[1].protocol_param = &usrapp.usbd.cdc.param,
.usbd.config[0].num_of_ifaces = dimof(usrapp.usbd.ifaces),
.usbd.config[0].iface = usrapp.usbd.ifaces,
.usbd.device.num_of_configuration = dimof(usrapp.usbd.config),
.usbd.device.config = usrapp.usbd.config,
.usbd.device.desc_filter = (struct vsfusbd_desc_filter_t *)usrapp_param.usbd.StdDesc,
.usbd.device.device_class_iface = 0,
.usbd.device.drv = (struct vsfhal_usbd_t *)&vsfhal_usbd,
.usbd.device.int_priority = 0xFF,
};
static void usrapp_heart_beat(void *p)
{
vsfdbg_printf("heartbeat: %d" VSFCFG_DEBUG_LINEEND, vsfhal_tickclk_get_ms());
}
static void usrapp_usbd_conn(void *p)
{
struct usrapp_t *app = (struct usrapp_t *)p;
vsfusbd_device_init(&app->usbd.device);
vsfusbd_connect(&app->usbd.device);
if (app_hwcfg.usbd.pullup.port != VSFHAL_DUMMY_PORT)
vsfhal_gpio_set(app_hwcfg.usbd.pullup.port, 1 << app_hwcfg.usbd.pullup.pin);
vsftimer_create_cb(1000, -1, usrapp_heart_beat, app);
}
void usrapp_srt_init(struct usrapp_t *app)
{
STREAM_INIT(&app->usbd.cdc.stream_rx);
STREAM_INIT(&app->usbd.cdc.stream_tx);
vsfdbg_init((struct vsf_stream_t *)&app->usbd.cdc.stream_tx);
if (app_hwcfg.usbd.pullup.port != VSFHAL_DUMMY_PORT)
{
vsfhal_gpio_init(app_hwcfg.usbd.pullup.port);
vsfhal_gpio_clear(app_hwcfg.usbd.pullup.port, 1 << app_hwcfg.usbd.pullup.pin);
vsfhal_gpio_config(app_hwcfg.usbd.pullup.port, app_hwcfg.usbd.pullup.pin, VSFHAL_GPIO_OUTPP);
}
vsfusbd_disconnect(&app->usbd.device);
vsftimer_create_cb(200, 1, usrapp_usbd_conn, app);
}
void usrapp_initial_init(struct usrapp_t *app){}
这里,USB描述符就不贴上来了。初始化了usrapp的数据结构,设置了CDC的参数和数据流的参数。
usrapp_srt_init(软实时初始化函数)中,初始化了CDC的输入和输出流、初始化了vsfdbg调试模块、关闭了USB设备口的上拉,并且延时200ms(超时后,调用usrapp_usbd_conn)。
usrapp_usbd_conn(200ms超时后执行这个函数)中,初始化usb设备协议栈,使能USB上拉,使能1000ms心跳定时器(每隔1000ms调用usrapp_heart_beat)。
usrapp_heart_beat中,简单调用vsfdbg_printf输出调试信息,由于usrapp_srt_init中,vsfdbg模块是连接到CDC的数据流的,那么实际调试信息就是从CDC接口发送给PC的。
运行效果如下(PC上使用putty):
代码位于:github.com/versaloon/vsf_open/tree/master/vsf/example/vsfaio/usrapp/stepbystep/step0_printf |