VSF中實現(xiàn)了一個相對通用的USB設備端協(xié)議棧,可以通過移植芯片的USB SIE驅(qū)動,來支持不同的MCU。USB設備端協(xié)議棧的實現(xiàn)只用到了最基本的事件驅(qū)動機制,并且,USB的各個中斷響應,沒有實時性要求。VSF的USB代碼都位于vsf/component/usb目錄下,core目錄下的vsfusbd.c是協(xié)議棧主體、dcd(device controller driver設備控制器驅(qū)動)目錄下是USB設備控制芯片的驅(qū)動、class/device目錄下是USB設備類的驅(qū)動。
先從應用角度來看,使用USB設備端協(xié)議棧只需要定義一個vsfusbd_device_t數(shù)據(jù)結(jié)構(gòu),然后調(diào)用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數(shù)據(jù)結(jié)構(gòu)后,代碼上就非常簡單和固化了,在軟實時初始化里,斷開USB上拉,建立一個200ms的定時器,超時后執(zhí)行usrapp_usbd_conn,調(diào)用vsfusbd_device_init、連接USB并且使能上拉。所以應用部分的關(guān)鍵就是在這個vsfusbd_device_t數(shù)據(jù)結(jié)構(gòu)的定義,這個決定了USB實現(xiàn)的功能。
這里,以mscboot的應用代碼作為示例,截取USB設備端數(shù)據(jù)結(jié)構(gòu)的定義:
.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結(jié)構(gòu)的數(shù)據(jù),指定底層的USB設備驅(qū)動。常用的底層設備驅(qū)動有vsfhal_usbd(芯片內(nèi)置的USB設備接口驅(qū)動)、vsfsdcd_usbd(GPIO模擬低速USB的接口驅(qū)動)、vbususbd_drv(虛擬vbus總線上實現(xiàn)的USB設備接口驅(qū)動)等等。device.int_priority定義驅(qū)動使用到的中斷的優(yōu)先級。這些的定義是和硬件有關(guān)的。
其他定義都和硬件無關(guān),只是指定了實現(xiàn)什么樣的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指定了類協(xié)議,protocol_param指定了參數(shù):
.usbd.msc.param.ep_in = 1,
.usbd.msc.param.ep_out = 1,
.usbd.msc.param.scsi_dev = &usrapp.mal.scsi_dev,
這個就是MSC類需要設置的參數(shù)。指定了輸入輸出的ep端口號,并且指定了一個scsi設備。
所以,總的來說,vsfusbd_device_t里定義了和硬件相關(guān)的設置、定義了描述符的設置、定義了從configuration到interface的結(jié)構(gòu)、然后再定義各個interface的參數(shù)。有了這些信息,USB設備端協(xié)議棧就可以運行起來了。