sumsky的专栏

我挥一挥衣袖,带走的不只有思想,还有云彩

用户操作
[留言]  [发消息]  [加为好友] 
订阅我的博客
XML聚合    FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
abc19842008的公告
<IFRAME ID='ifm2' WIDTH='189' HEIGHT='190' ALIGN='CENTER' MARGINWIDTH='0' MARGINHEIGHT='0' HSPACE='0' VSPACE='0' FRAMEBORDER='0' SCROLLING='NO' SRC='http://weather.qq.com/inc/ss296.htm'></IFRAME> <EMBED src="http://www.clocklink.com/Clocks/0001P-Orange.swf?Place=Beijing China&TimeZone=GMT0800" width=200 height=200 type=application/x-shockwave-flash wmode="transparent">
文章分类
存档

原创  DFU分析 收藏

最近因为项目的原因看了下DFU的资料,也下个Demo来研究了下,其实也就是在USB驱动中嵌入DFU驱动而已,弄明白了DFU的协议,就很容易了。DFU有个specification,全名叫USB Device Class Specification for Device Firmware Upgrade。可见其和USB之间的密切关系。

当把DFU嵌入USB后,系统运行状态一般就可以分为二种模式,一种是就是正常的USB运行模式,一种是DFU模式,二种模式不能共存。那如果确定是哪种模式呢,这就要通过寻找DFU class interface descriptor来判断设备是否具有DFU功能,也就是升级固件的功能。而这个DFU class interface descriptor和USB中interface中的interface descriptor结构是一样的,的在DFU Specification中提到其interface descriptor中的bInterfaceClass为EFh,而其bInterfaceSubClass为01h,这就是我们判断的依据。
if (intf->bInterfaceClass == 0xfe &&  intf->bInterfaceSubClass == 1)
{
             ......
}
这里需要注意的是,在正常的模式下,只有一个DFU Class interface descriptor.同时在bInterfaceProtocol为01的话就代表还是在正常模式,为02在处于DFU协议下了。

如果有多个设备具有DFU功能,这时就要注意了,因为在 DFU Specification中提到,其协议只支持一个具有DFU功能的设备,原因是在从正常模式下进入DFU模式前必须reset总线。具有DFU功能的设备地址将会改变。

发送dfu_detach后,还重新re-scan USB。这里的dfu_detach是DFU Specification中定义的请求,如果函数成功则可以在reset usb后进入DFU模式,下面是发送DFU的代码,利用usblib这个库,也就是我在上一篇提到的。

usb_control_msg( device,
        /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
        /* bRequest      */ DFU_DETACH,
        /* wValue        */ timeout,
        /* wIndex        */ interface,
        /* Data          */ NULL,
        /* wLength       */ 0,
                            dfu_timeout );

在DFU Specification中提到DFU有很多状态,在各个状态实现不同的功能,比如在 DFU_STATE_dfuERROR状态下只能调用dfu_clear_status才能回到dfuIdle模式下,Demo中的代码如下:

status_again:
               printf("Determining device status: ");
               if (dfu_get_status(dif->dev_handle, dif->interface, &status ) < 0) {
                        fprintf(stderr, "error get_status: %s\n", usb_strerror());
                       exit(1);
               } 
switch (status.bState) {
               case DFU_STATE_appIDLE:
               case DFU_STATE_appDETACH:
                        fprintf(stderr, "Device still in Runtime Mode!\n");
                        exit(1);
                        break;
               case DFU_STATE_dfuERROR:
                        printf("dfuERROR, clearing status\n");
                        if (dfu_clear_status(dif->dev_handle, dif->interface) < 0) {
                                 fprintf(stderr, "error clear_status: %s\n", usb_strerror());
                                 exit(1);
                        }
                       goto status_again;
                       break;
                case DFU_STATE_dfuDNLOAD_IDLE:
                case DFU_STATE_dfuUPLOAD_IDLE:
                       printf("aborting previous incomplete transfer\n");
                       if (dfu_abort(dif->dev_handle, dif->interface) < 0) {
                               fprintf(stderr, "can't send DFU_ABORT: %s\n", usb_strerror());
                               exit(1);
                        }
                       goto status_again;
                       break;
                case DFU_STATE_dfuIDLE:
                       printf("dfuIDLE, continuing\n");
                       break;

}

其中的dfu_get_status等都是调用usb_control_msg来实现的。

然后可以执行下载,上传的操作了。同样调用usb_control_msg来实现,比如对于更新固件,就可以
    status = usb_control_msg( device,
          /* bmRequestType */ USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
          /* bRequest      */ DFU_UPLOAD,
          /* wValue        */ transaction++,
          /* wIndex        */ interface,
          /* Data          */ data,
          /* wLength       */ length,
                              dfu_timeout );

发表于 @ 2008年03月17日 23:45:00 | 评论( loading... ) | 编辑| 举报| 收藏

旧一篇:libusb 介绍 | 新一篇:线程同步(信号量,互斥,条件变量)

  • 发表评论
  • 评论内容:
  •  
Copyright © abc19842008
Powered by CSDN Blog