在一级bootloader执行进入USB启动方式之后,设备进行枚举。枚举过程中会通过PC端发送命令对连接的USB设备进行枚举。当枚举成功之后,在PC端可以看到设备的盘符。

当设备能够被PC正确识别之后。接下来就能够通过烧写工具完毕设备的扫描假设成功找到设备,则能够通过USB数据传输到SRAM中,这时候的数据主要包含2k infor文件。一级bootloader在成功的解析2kinfor 之后。PC端会将DFU文件传输到初始化好的DRAM中。而且PC指针跳转到DFU地址处运行,运行过程中会跳转到USB初始化程序过程中。

USB的初始化过程主要分为两个部分,一个部分是初始化UDC设备。第二部分是等待PC端发送的命令并响应。

这个过程的描写叙述例如以下:

在USB的初始化过程中会调用VIM_CLKRST_UotgExitRst();函数。

此函数中,

VOID VIM_CLKRST_UotgExitRst(VOID)

{

__CLKRST_UotgSWRst();//为了防止global rst之后。来不了中断导致挂死

__CLKRST_UotgExitRst();

//waitfor uotg swrstdone irq

while(!__CLKRST_CheckUotgSwrst())//poolling

{

//donothing

};

__CLKRST_ClearUotgSwrstIrq();

}

会首先设置0x604寄存器的bit25。UOTG_SW_RESET。

接着设置0x610寄存器的SW_CFG_UOTG_DONE,bit12。uotg software configuration done flag, high active

然后死等UOTG_RSTDONE_IRQ中断的到来。最后写清中断。

在初始化函数的最后,会调用

UDC_DFU_Init(VIM_USB_DataProcess,VIM_USB_ArmSpeedBinProcess);函数。函数中会将两个函数指针进行赋值给全局变量g_Usb_Process_Call以及g_Usb_SpeedBin_Call。函数指针的定义为typedef VIM_RESULT(* PFatCallBack)(UINT8 *, UINT32);

void UDC_DFU_Init(PFatCallBackp_data_process,PFatCallBack p_speedbin_process)

{

VIM_HAL_PrintStr("UDC_DFU_Init:\r\n");

g_Usb_Process_Call= p_data_process;//处理收到的512字节,就是一个sector

//当中g_Usb_Process_Call用于USB工具下载IMAGE时对一个sector的处理

g_Usb_SpeedBin_Call= p_speedbin_process;//装载speed sorting镜像

g_FatCtx.pcall= p_data_process;

//g_FatCtx.pcall用于U盘拷贝方式对一个sector的处理

g_FatCtx.fat_total_sec= ChkFatBoot(DFU_SIZE);

udc_mass_init(&g_DfuMedOp, 1);

udc_mass_start();

}

此函数中会对fat设备的cluster等变量值进行计算,而且初始化mass设备。初始化的过程主要是对设备操作过程中记录状态机等信息的全局变量this_usb_udc进行赋初始值。

void udc_mass_init(PUSB_MED_IF pMedIf,UINT8 lun_num)

{

VIM_HAL_Memset(&g_mass_ctx,0, sizeof(g_mass_ctx));

g_mass_ctx.maxlun= 0;

//     g_DataShared= (UINT8*)VIM_USB_DATA_BUF;

g_mass_ctx.lun[0].dma_addr[0]= (void *) (((UINT32)g_DmaNotMallocAddr+0x1000)&0xfffff000);

g_mass_ctx.lun[0].pUmdIf= pMedIf;

udc_init();

}

在udc_init()中会完毕对设备赋初值的操作。主要包含设备的初始状态值,DMA地址等信息以及例如以下结构体变量值。

USB_MED_IF g_DfuMedOp =

{

NULL,

MedBoot_rd_sec,

MedBoot_wr_sec,

MedBoot_get_status,

MedBoot_get_sec_num,

NULL,

{

{'o','o', 'o', 'o', 'o', 'o', 'o', 0x20},//VID

{'S','U', 'P', 'E', 'R', 0x20, 'D', 'I', 'S', 'K', 0x20, 0x20, 0x20, 0x20, 0x20,0x20},//PID

{'1','.','0','0'}//VERSIIN

}

};

在整个初始化过程的最后会通过配置寄存器连接并使能设备为快速设备。

Udc_SetUsbPower(UDC_M_POWER_SOFTCONN|UDC_M_POWER_HSENAB);

至此设备的初始化过程完毕,接下来会进入循环等待设备与host端进行交互的操作过程。

在udc_mass_process函数中会注冊“查询处理usb传输数据状态。进行数据处理”的中断,接受中断并进行处理。

void udc_mass_process(void)

{

udc_int_usb();//查询处理usb传输数据状态。进行数据处理

if(g_mass_ctx.usb_state!= USB_STATE_CONFIGURED)

return;

if(g_mass_ctx.umb_state== UMB_IDLE)

{

req_cbw();

}

elseif(g_mass_ctx.umb_state == UMB_CBW_OK)

{

do_cbw();

}

}

在设备接收到的CBW状态为UMB_CBW_OK时,会通过do_cbw对数据进行分发和处理。这个过程中。主要是通过UmscProcess函数。

在case中会看到在PC端程序中传递下来的子命令。

static void do_cbw(void)

{

UINT32  reqlen = 0;

pCsw->Tag= pCbw->Tag;

reqlen= UdcGet32Lbuf( (UINT8*)(&pCbw->TransferLength) );

g_mass_ctx.umb_state= UMB_CBW_PROCESS;

UmscProcess(&g_mass_ctx.lun[pCbw->Resv_Lun], pCbw->CbOpt, pCbw->CbData,pCbw->Flags, reqlen );

}

依据上面的描写叙述大体上了解了USB设备注冊完毕之后设备的一些状态问题。在上面的描写叙述中可以看到打开了USB的中断。这时候设备会进行又一次枚举的过程,又一次枚举的过程是会首先发送reset命令。在DFU中等待设备reset的过程显得比較漫长。这个过程中须要注意是否可以进行优化。

此处还是没有查明究竟reset是从代码的那个位置传送下来,还是在udc_mass_process完毕注冊之后会一直扫描中断,可是后者看起来不像。

当接收到reset中断后。会对端点进行又一次设置,而且通过调用udc_nuke_req()函数完毕实际的操作。

/***************************************************************************************

总线RESET后运行的操作

****************************************************************************************/

static void udc_usbreset(void)

{

UINT32val;

UINT8 i;

VIM_DBG_Print(USB_MSG_DEVICE_RESET);

//Udc_SetIntUnmask(UDC_INT_USB|UDC_INT_DMA);

//usbint , all without sof

val= ~UDC_M_INTR_SOF;

Udc_SetUsbIrqEn(val);

Udc_SetInIrqEn((0x1<<EP_CTRL)|(0x1<<EP_BULK_IN)|(0x1<<EP_INTR_IN) );

Udc_SetOutIrqEn((0x1<<EP_CTRL)|(0x1<<EP_BULK_OUT)|(0x1<<EP_INTR_OUT) );//又一次使能对应的端点

this_usb_udc.state= USB_STATE_DEFAULT;

this_usb_udc.highspeed= 1;

//各个端点注冊的RESET函数,在udc_ttc.c和udc_bulkonly中定义了this_usb_udc.driver指向的实体结构体

//g_ttc_driver      and   g_mass_driver

if(this_usb_udc.driver != NULL )//在TTC中,将命令的各个管道的USBstate设置成usb_state =USB_STATE_DEFAULT

this_usb_udc.driver->reset();

udc_nuke_req();//??

????

??

?????????

?

???????

???

??

???

??

??

??

??

?

//OUT和中断端点设置BUSY位。为什么?

这个BUSY的用处是什么?

//这两位为1表示不能使能RX端点,即清除它的RXPKTRDY位。不能接收下笔数据

//这两位在第一次REQ_CBW时被清除。因为系统默认是能够接收数据的,这次就不必

//人工使能端点接收了

this_usb_udc.ep[EP_BULK_OUT].busy= 1;//此时g_ep_out=EP_IDX_1

this_usb_udc.ep[EP_INTR_OUT].busy= 1;//此时EP_INTR_OUT=EP_IDX_3

//清除端点的FIFO和TOG。释放停止状态标志

for(i=0;i<EP_GT_NUM; i++)

{

Udc_EpRst(i, USB_EP_RET_DIR_OUT);//out

Udc_EpRst(i,USB_EP_RET_DIR_IN); //in

this_usb_udc.ep[i].halt= 0;

}

}

上面的代码中调用了this_usb_udc.driver->reset();这个函数的赋值是通过对结构体进行总体赋值完毕的,

struct usb_driver g_mass_driver =

{

UsbMassClsReq,

Usb_MassGetDescBuf,

UsbMassSetCfg,

UsbMassReset,

UsbMassSuspend,

UsbMassSetIntf

};

usb_driver结构体的定义为:

struct usb_driver {

void                                    (*udc_vendor_class_req)(structusb_fifo *);

UINT8*         (*get_desc)(UINT8 highspeed, UINT8type, UINT16* len, UINT8 strIdx);

void                                    (*set_cfg)(void);

void                                    (*reset)(void);

void                                    (*suspend)(void);

void                                    (*set_interface)(UINT16intface, UINT16 altset);

};

实际过程中UsbMassReset函数完毕的操作不过对g_mass_ctx.usb_state进行赋值为 USB_STATE_DEFAULT,设置这个状态会让设备。

眼下可以看到的在DFU中状态机的操作是在GetConfig的过程中作为控制端点是否可用的状态推断符,

if(this_usb_udc.state == USB_STATE_DEFAULT )

{

udc_CtrlCmdNotSupport();

return;

}

假设不支持这种控制命令那么就会stall endpoint为停止状态。

在udc_nuke_req()函数中。会依据选择的传输方式不同进行不同的控制。通常情况下,控制传输使用FIFO方式,而在须要大量传输数据的bulk传输过程中会使用DMA方式。

DFU工作过程中USB机制的更多相关文章

  1. 测试或运维工作过程中最常用的几个linux命令?

     大家在测试工作过程中,可能会遇到需要你去服务器修改一些配置文件,譬如说某个字段的值是1 则关联老版本,是0则关联新版本,这时候你可能就需要会下vi的命令操作:或者查看session设置的时长,可能需 ...

  2. 之前工作过程中自定义的代码生成器模版,codesimit

    动软代码生成器 和codesmith 5年前的东西,或许有些过时 动软的功能有限,改的也比较简单,已弃. codesmith可定制性强,当时自已改的,提高了团队的整体工作效率. codesmith代码 ...

  3. SVC 工作过程中出现的错误记录(SEO项目)

    1.同一のキーを含む項目が既に追加されています.追加的项目中含有重复主键) /seo' アプリケーションでサーバー エラーが発生しました. 同一のキーを含む項目が既に追加されています. 説明: 現在の ...

  4. java jvm概述及工作过程中的内存管理

    java jvm 有分层的思想.   java类..java文件,源文件,源代码,源程序   编译器不能把源代码直接编译成0101,除非是java语言写的操作系统.   windows认识的可执行文件 ...

  5. Nginx reopen reload作用及工作过程

    http://www.iigrowing.cn/nginx-reopen-reload-zuo-yong-ji-gong-zuo-guo-cheng.html Nginx reopen reload作 ...

  6. JVM加载类的过程,双亲委派机制中的方法

    JVM加载类的过程: 1)JVM中类的整个生命周期: 加载=>验证=>准备=>解析=>初始化=>使用=>卸载  1.1.加载 类的加载阶段,主要是获取定义此类的二进 ...

  7. RT3070 USB WIFI 在连接socket编程过程中问题总结

    最近耗时多天,成功的将RT3070驱动.并解决了socket的网络编程,成功的在BA9G10上面实现了USB wif.连上家里的无线路由器,通过ubuntu下面建立的服务端程序,将BA9G10中的数据 ...

  8. 阿里面试官:Android中binder机制的实现原理及过程?

    Binder 是 Android 系统中非常重要的组成部分.Android 系统中的许多功能建立在 Binder 机制之上.在这篇文章中,我们会对 Android 中的 Binder 在系统架构中的作 ...

  9. 将数据的初始化放到docker中的整个工作过程(问题记录)

    将数据的初始化放到docker中的整个工作过程 由于是打算作为个人博客,所以对于install这个步骤,我从一开始就打算删掉的,前面一个多星期一直在修bug,到前天才开始做这个事情. 过程中也是碰到了 ...

随机推荐

  1. SGU 114.Telecasting station

    题意: 百慕大的每一座城市都坐落在一维直线上.这个国家的政府决定建造一个新的广播电视台.经过了许多次试验后,百慕大的科学家们提出了一个结论,在每座城市的不满意度等于这座城市的市民数与这座城市与广播电视 ...

  2. SGU 159.Self-Replicating Numbers

    时间限制:0.5s 空间限制:6M 题意:         在b(2<b<36)进制中,找到所有长度为n(0<n<2000)的自守数k,满足k^2%b^n=k,字典序输出.   ...

  3. 常见的iis日志代码!

    2xx  成功 200  正常:请求已完成. 201  正常:紧接 POST 命令. 202  正常:已接受用于处理,但处理尚未完成. 203  正常:部分信息 — 返回的信息只是一部分. 204   ...

  4. 控制寄存器 CR*

    控制寄存器(CR0-CR3)用于控制和确定处理器的操作模式以及当前执行任务的特性,如图4-3所示.CR0中含有控制处理器操作模式和状态的系统控制标志:CR1保留不用:CR2含有导致页错误的线性地址:C ...

  5. qt环境问题导致的编译错误

    /usr/include/qt5/QtCore/qprocess.h:245:24: error: missing binary operator before token "(" ...

  6. 在MAC下 Python+Django+mysql配置

    今天在搭建Django+mysql环境的时候遇到了一点问题,记录下来. 安装环境:OS X 10.10操作系统,Python 2.7. MySQLdb其实包含在MySQL-python包中,因此无论下 ...

  7. python Hbase Thrift pycharm 及引入包

    cp -r hbase/ /usr/lib/python2.7/site-packages/ 官方示例子http://code.google.com/p/hbase-thrift/source/bro ...

  8. [BZOJ 2326] [HNOI2011] 数学作业 【矩阵乘法】

    题目链接:BZOJ - 2326 题目分析 数据范围达到了 10^18 ,显然需要矩阵乘法了! 可以发现,向数字尾部添加一个数字 x 的过程就是 Num = Num * 10^k + x .其中 k ...

  9. [Mon Feb 10 15:21:06 2014] [notice] child pid 7101 exit signal File size limit exceeded (25)

    今天遇到的问题: LAMP的LOG里报如下错误. 然后IE和FIREFOX里显示连接被重置或是无法访问. 但自己建一个正常的PHP测试探针倒可以. 原来是PHP错误日志太多,无法写入LOG导致. [r ...

  10. 【Linux】鸟哥的Linux私房菜基础学习篇整理(七)

    1. test命令的测试功能.测试的标志:(1)关于文件类型的检测 test [-efdbcSpL] filename-e:该文件名是否存在:-f:该文件名是否为文件:-d:该文件名是否为目录:-b: ...