历史上的今天
返回首页

历史上的今天

今天是:2024年11月10日(星期日)

正在发生

2020年11月10日 | 深入解析STM32_USB-FS-Device_Lib库V0.2

2020-11-10 来源:eefocus

图1 展示了一个典型的USB应用与USB-FS-Device library的关系图。我们可以看出图中由3个层构成分别是:外围硬件(hardware)、STM32_USB-FS_Device_Lib和用户层(User application)。我们从下到上来分析:

 

 图1 典型的USB应用与USB-FS-Device library的关系图

 

1.外围硬件(hardware)

     就是我们的购买的芯片STM32F10XXX和开发板

2  STM32_USB-FS_Device_Lib

就是STM提供给我们的The USB-FS-Device library固件库,它由STM32_USB FS_Device_ Driver和Application Interface layer两个部分组成。

其中STM32_USB-FS_Device_Driver这层管理USB的硬件设备和USB标准协议的直接交互,它又由Low Layer 和 Medium Layer两个层组成;Application Interface layer-High Layer这层又叫High Layer层,它在固件库核和应用提供给用户一个完整的接口。

图2 是我给出的STM32_USB-FS-Device_Lib_V3.1.0 结构图,下面我们将对这个整个结构的运行机理分析,然后结构逐层给出具体含义。

 

 

 


 


 图2 STM32_USB-FS-Device_Lib_V3.1.0 结构图


 

    和其他的接口一样,当受到USB的中断后,进入stm32f10x_it.c中的USB_LP_CAN1_RX0

_IRQHandler()和USB_HP_CAN1_TX_IRQHandler()中断服务子程序。其中优先级高的由USB_HP_CAN1_TX_IRQHandler处理,优先级低的由USB_LP_CAN1_RX0_ IRQHandler处理。

    对于USB_HP_CAN1_TX_IRQHandler函数,它直接调用usb_int (.h , .c)中的CTR_HP(),然后根据发送和接受数据,它调用usb_endp(.c)中的EPX_IN_Callback()或EPX_OUT_ Callback()函数。对于EPX_IN_Callback和EPX_OUT_Callback()这14个函数(X=1,2...7)它们在usb_conf(.h)中通过

#define  EPX_IN_Callback   NOP_Process

#define  EPX_OUT_Callback   NOP_Process

的形式,来由用户决定是否提供具体的实现并调用。而将它们和CTR_HP联系在一起的操作,在usb_istr(.h,.c)中以下面的形式给出:

void (*pEpInt_IN[7])(void) ={

    EP1_IN_Callback,

    ...

    EP7_IN_Callback,};

void (*pEpInt_OUT[7])(void) ={

    EP1_OUT_Callback,

    ...

EP7_OUT_Callback,};

对于USB_HP_CAN1_TX_IRQHandler函数,它直接调用usb_istr(.h,.c)中的USB_Istr(),USB_Istr()根据具体的请求决定是调用usb_istr(.h,.c)中下面函数

void CTR_Callback(void);

void DOVR_Callback(void);

void ERR_Callback(void);

void WKUP_Callback(void);

void SUSP_Callback(void);

void RESET_Callback(void);

void SOF_Callback(void);

void ESOF_Callback(void);

还是调用usb_int(.h,.c)中的void CTR_LP(void)。对于上面的这个函数是否给出定义,是由用户在usb_conf(.h)中,通过下面的宏决定的

/*#define CTR_CALLBACK*/

/*#define DOVR_CALLBACK*/

/*#define ERR_CALLBACK*/

/*#define WKUP_CALLBACK*/

/*#define SUSP_CALLBACK*/

/*#define RESET_CALLBACK*/

#define SOF_CALLBACK

/*#define ESOF_CALLBACK*/

如果调用了 CTR_LP()函数,CTR_LP()函数中如果不是端点0的请求,则和CTR_LP一样的顺序处理;如果是端点0,它调用usb_core(.h,.c)中的

uint8_t Setup0_Process(void);

uint8_t Post0_Process(void);

uint8_t Out0_Process(void);

uInt8_t In0_Process(void);

如果是标准的请求,便调用usb_core(.h,.c)中的下面的函数

RESULT Standard_SetEndPointFeature(void);

RESULT Standard_SetDeviceFeature(void);

uint8_t *Standard_GetConfiguration(uint16_t Length);

RESULT Standard_SetConfiguration(void);

uint8_t *Standard_GetInterface(uint16_t Length);

RESULT Standard_SetInterface(void);

Uint8_t *Standard_GetDescriptorData(uint16_t ...);

uint8_t *Standard_GetStatus(uint16_t Length);

RESULT Standard_ClearFeature(void);

void SetDeviceAddress(uint8_t);

这些函数,又调用USER_STANDARD_REQUESTS结构指定的中,用户在usb_prop(.h,.c)中定义的函数。如果不是标准请求,则调用DEVICE_PROP结构指定的中,用户在usb_prop(.h,.c)中定义的函数其他一些函数。

 

 


 下面我再按文件分析一次:

 

 

usb_conf.h

usb_conf.h中的#define IMR_MSK (CNTR_CTRM  | CNTR_SOFM  | CNTR_RESETM )来决定USB_CNTR寄存器中的那个USB相关中断启动还是屏蔽。

 

usb_istr.c

进入USB_Istr()后,首先检测是否是CTR位中断,即完成一次数据的正处传输,如果是,并且相应IMR_MSK没有屏蔽,就调用usb_int,c中的CTR_LP()函数,如果定义了CTR_CALLBACK,则调用本文件中定义的CTR_Callback()函数。

然后检测是否是RESET位中断,如果是,并且相应的中断没有屏蔽,则首先清楚USB_ISTR寄存中相应的中断位,然后调用用户在usb_prop.c的Device_Property结构体中填充的相应的函数;如果定义了宏RESET_CALLBACK还将调用本文件中定义的RESET_Callback()函数。

其他的类似。

 

注意:值得我们注意的是如果缓冲区的数据溢出,则不会调用 CTR_LP()和CTR_Callback(),这样的话,我们也就没有机会来处理这些数据,所以,如果你想处理缓冲区溢出时的数据你必须定义DOVR_CALLBACK,并提供DOVR_Callback()函数。

 

usb_int.h

    进入CTR_LP()函数后,首先检测发生中断断点的ID如果是端点0,则根据是输入还是输出调用。如果是IN,则调用usb_core(.h,.c)中的In0_Process()函数;否则检测是否是SETUP,是的话调用usb_core(.c)中的Setup0_Process()函数,不是的话调用usb_core(c)中的Out0_Process()函数。如果不是端点0则调用usb_endp(.c)中 EPX_IN_Callback()和EPX_OUT_Callback()。

进入CTR_HP()后,因为它只接受同步传输和双缓冲区的批量传输中的,所以它直接检测是IN还是OUT,并调用usb_endp(.c)中 EPX_IN_Callback()和EPX_OUT_Callback()。

 

usb_core(.h,.c)

Setup0_Process()

    进入Setup0_Process()函数后,如果现在的CONTROL_STATE状态不是PAUSE则,填充pInformation指向的DEVICE_INFO结构体,然后设置CONTROL_STATE现在状态为SETTING_UP,然后根据数据的长度是否为0调用NoData_Setup0()或者 Data_Setup0()函数,最后调用Post0_Process()????????。

 

NoData_Setup0()

进入NoData_Setup0()后,首先判断是否接收者是设备并且是标准请求,如果是根据请求的类型SET_CONFIGURATION、SET_ADDRESS、SET_FEATURE和CLEAR_FEATURE来调用该文件中的相应函数;然后判断是否接收者是接口并且是标准请求,如果是根据是否是SET_INTERFACE来调用文件中相应的函数;其次判断是否接收者是端点并且是标准请求,如果是则根据CLEAR_FEATURE和SET_FEATURE来调用相应的本文件中函数。否则结果设置成USB_UNSUPPORT。

    接下来,如果结果是USB_UNSUPPORT,则调用usb_prop(.h,.c)中DEVICE_PROP结构体中填充的RESULT (*Class_NoData_Setup)(uint8_t RequestNo)函数,我们就在该函数中处理不是类库中已经实现的请求。

 

Data_Setup0()

进入Data_Setup0()后,首先检测请求代码是否是GET_DESCRIPTOR,如果是根据描述符的请求,分别调用usb_prop(.h,.c)中DEVICE_PROP结构体中填充的设备描述符、配置描述符和字符串描述符的函数;然后检测请求代码是否是GET STATUS,如果是则调用Standard_GetStatus函数;其次检测是否是GET_CONFIGURATION和GET_INTERFACE,如果是调用相关函数。

如果不满足上面条件则调用调用usb_prop(.h,.c)中DEVICE_PROP结构体中填充的RESULT (*Class_Data_Setup)(uint8_t RequestNo)函数,我们就在该函数中处理不是类库中已经实现的请求。

最后根据请求设置相应状态,用于下次通信。


推荐阅读

史海拾趣

Chemtronics公司的发展小趣事

为满足电子行业对无铅应用的需求,Chemtronics专门设计了完整的无铅产品线,并成为业内第一个向市场提供此类产品的公司。这一创新不仅满足了市场对环保和高效产品的需求,也进一步巩固了Chemtronics在电子行业的领先地位。

AMS公司的发展小趣事

1999年,Chemtronics迎来了一个重要的转折点,成为Illinois Tool Works Inc的全资子公司。这一变化为Chemtronics带来了更多的资源和支持,使其能够进一步扩大生产规模、提升研发能力,并在全球范围内拓展业务。

BERGQUIST公司的发展小趣事

面对日益严峻的环境问题和可持续发展的挑战,BERGQUIST公司始终坚持绿色发展的理念。公司不断投入研发力量,开发环保型热管理材料和生产工艺。同时,公司还积极推广节能减排技术,努力降低生产过程中的能耗和排放。这些举措不仅符合社会发展趋势,也为公司的可持续发展提供了有力保障。

这五个故事从不同角度展示了BERGQUIST公司在电子行业中的发展历程和成就,体现了公司不断创新、追求卓越的精神。这些事实性的描述旨在客观呈现BERGQUIST公司的历史与现状,不含任何褒贬之意。

乐鑫(espressif)公司的发展小趣事

近年来,乐鑫科技的业绩实现了稳步增长。公司的营业收入和净利润均呈现出良好的增长态势,毛利率和净利率也保持在较高水平。这些成绩的取得,离不开乐鑫科技对技术创新的坚持和对市场趋势的敏锐洞察。

DAYLIGHT公司的发展小趣事

在公司的初创阶段,DAYLIGHT就意识到技术研发对于企业发展的重要性。因此,公司投入大量资金用于研发新的电子产品和技术。经过几年的努力,DAYLIGHT成功研发出一项具有革命性的电子芯片技术,这一技术大大提高了电子产品的性能和可靠性,使得DAYLIGHT的产品在市场上获得了极高的声誉。

Aearo Technologies公司的发展小趣事

尽管Aearo Technologies在行业中享有盛誉,但近年来也面临了一些挑战。公司生产的一款名为“Combat Arms”的军用耳塞被指存在设计缺陷和质量问题,导致部分使用者听力受损。这一事件引发了广泛的关注和诉讼。面对这一挑战,Aearo Technologies积极应对,与相关部门合作进行调查,并采取了一系列措施改进产品质量和确保用户安全。

问答坊 | AI 解惑

谁可以说下这个原理图是那里没有设置对????

Processing Rule:  Broken-Net Constraint ( ( On the board) )     Violation             Net netc17_1  is broken into 2 sub-nets. Routed To 0.00%    &n ...…

查看全部问答>

可恶的ActiveSync连接问题,急救...

在Activesync同步时,无法用USB连接PC,当插入USB时,PC机上提示发现新硬件,硬件可以使用,这说明我的驱动没有问题,选了组件ActiveSync 和usb serial ,系统时间日期设置好了,拔下USB口再插上无数次,Pc机子和目标机重启无数次,每次目标机上显 ...…

查看全部问答>

请教:vxworks WDB调试的问题

我想使用vxworks的WDB来进行调试,可是网口怎么挂也挂不上,所以没办法改用串口 现在串口可以挂上了,但是报了一个错:Error: Cannot get target toolname (symbol error) 不晓得该如何解决,希望前辈指点!     具体信息如下: Targ ...…

查看全部问答>

紧急求助:pxa270下SDIO wifi模组的驱动 Marvell 8686

请问谁能发给我一份在PXA270下可以使用的SDIO WIFI模组的驱动,模组型号是USI的WM-G-MR-09,模组使用的芯片是Marvell 8686. 我手里有厂商给的驱动,名称是:SD-8686-WM60-ARMV4I-9.70.3.p23-38.p44.CAB,但是这份是基于PXA310和wince6.0的驱动,我 ...…

查看全部问答>

高分求教~!

我在做四合一个卡座时不小心吧SD卡的DATA0和DATA1连在了一起,经过测试用SD卡可以正常读取,而用MINISD卡确不能读取,SD卡和MINISD卡不是一样的吗,请高人指教,谢谢~~!!…

查看全部问答>

DCD,SPACE问题

代码如下: #define SVC_STACK_LENGTH 0 StackSvc DCD SvcStackSpace+(SVC_STACK_LENGTH-1)*4 AREA MyStack,DATA,NOINIT,ALIGN=2 SvcStackSpace SPACE SVC_STACK_LENGTH*4 --------------------------------------- 请问各位大侠,DCD,SPACE ...…

查看全部问答>

我的STM32工作不起来

   板子是自己画的,芯片用的是STM32F103ZDTB,复位用一个按键加10K的电阻加101的电容,低电平复位,晶振是用12M晶振加30P的电容,VBAT接了一个101的电容再接到VDD,板子再接了一个USART1.    量了一下,晶振是不 ...…

查看全部问答>

can\'t open include file \"c240.h\"

这样的错误要怎么改才行???…

查看全部问答>

有啥画PCB的群、或者画pcb的QQ,高手的

有啥画PCB的群、或者画pcb的QQ,高手的,本人是个新手,刚接触设计PCB,学习过程可能会遇到一些问题,想加一些大侠的Q来指导下,被人q:1729217470.。…

查看全部问答>

找FPGA固件设计兼职人员,出差去上海1到2个月,Verilog语言

用Verilog实现一个通信协议的状态机,协议有40多条,固件框架已经写好,用Verilog写的。因其中的RS232、LVDS、千兆网等IP CORE在上海合作单位那边,需要去那边联合开发调试一到两个月。需要您熟练应用Verilog,XILINX FPGA开工工具,对spartan-6内 ...…

查看全部问答>