VSF中的通用USB设备协议栈:应用部分

VSF中实现了一个相对通用的USB设备端协议栈,可以通过移植芯片的USB SIE驱动,来支持不同的MCU。USB设备端协议栈的实现只用到了最基本的事件驱动机制,并且,USB的各个中断响应,没有实时性要求。VSF的USB代码都位于vsf/component/usb目录下,core目录下的vsfusbd.c是协议栈主体、dcd(device controller driver设备控制器驱动)目录下是USB设备控制芯片的驱动、class/device目录下是USB设备类的驱动。

先从应用角度来看,使用USB设备端协议栈只需要定义一个vsfusbd_device_t数据结构,然后调用vsfusbd_device_init即可,以下是典型的USBD应用代码:

static void usrapp_usbd_conn(void *p)
{
    struct usrapp_t *app = (struct usrapp_t *)p;

    vsfusbd_device_init(&app->usbd.device);
    app->usbd.device.drv->connect();
    if (app->hwcfg->usbd.pullup.port != VSFHAL_DUMMY_PORT)
        vsfhal_gpio_set(app->hwcfg->usbd.pullup.port, 1 << app->hwcfg->usbd.pullup.pin);
}

void usrapp_srt_init(struct usrapp_t *app)
{
    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);
    }
    app->usbd.device.drv->disconnect();

    vsftimer_create_cb(200, 1, usrapp_usbd_conn, app);
}

应用层定义好app->usbd.device数据结构后,代码上就非常简单和固化了,在软实时初始化里,断开USB上拉,建立一个200ms的定时器,超时后执行usrapp_usbd_conn,调用vsfusbd_device_init、连接USB并且使能上拉。所以应用部分的关键就是在这个vsfusbd_device_t数据结构的定义,这个决定了USB实现的功能。

这里,以mscboot的应用代码作为示例,截取USB设备端数据结构的定义:

    .usbd.msc.param.ep_in                   = 1,
    .usbd.msc.param.ep_out                  = 1,
    .usbd.msc.param.scsi_dev                = &usrapp.mal.scsi_dev,
    .usbd.ifaces[0].class_protocol          = (struct vsfusbd_class_protocol_t *)&vsfusbd_MSCBOT_class,
    .usbd.ifaces[0].protocol_param          = &usrapp.usbd.msc.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,

device.drv指向一个vsfhal_usbd_t结构的数据,指定底层的USB设备驱动。常用的底层设备驱动有vsfhal_usbd(芯片内置的USB设备接口驱动)、vsfsdcd_usbd(GPIO模拟低速USB的接口驱动)、vbususbd_drv(虚拟vbus总线上实现的USB设备接口驱动)等等。device.int_priority定义驱动使用到的中断的优先级。这些的定义是和硬件有关的。

其他定义都和硬件无关,只是指定了实现什么样的USB设备。了解USB的人应该都知道,USB是由configuration、interface、endpoint组成的。一个设备可以有多个configuration,由device.num_of_configuration和device.config指定。上述代码里,只有一个configuration:

    .usbd.config[0].num_of_ifaces           = dimof(usrapp.usbd.ifaces),
    .usbd.config[0].iface                   = usrapp.usbd.ifaces,

然后,每个configuration可以包含多个interface,上述代码里,也只有一个interface:

    .usbd.ifaces[0].class_protocol          = (struct vsfusbd_class_protocol_t *)&vsfusbd_MSCBOT_class,
    .usbd.ifaces[0].protocol_param          = &usrapp.usbd.msc.param,

这里的interface是vsfusbd_MSCBOT_class类的,也就是U盘的设备类。这里class_protocol指定了类协议,protocol_param指定了参数:

    .usbd.msc.param.ep_in                   = 1,
    .usbd.msc.param.ep_out                  = 1,
    .usbd.msc.param.scsi_dev                = &usrapp.mal.scsi_dev,

这个就是MSC类需要设置的参数。指定了输入输出的ep端口号,并且指定了一个scsi设备。

所以,总的来说,vsfusbd_device_t里定义了和硬件相关的设置、定义了描述符的设置、定义了从configuration到interface的结构、然后再定义各个interface的参数。有了这些信息,USB设备端协议栈就可以运行起来了。

你可能感兴趣的:(VSF中的通用USB设备协议栈:应用部分)