本帖最后由 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
|