深入解析STM32_USB-FS-Device_Lib库

展示了一个典型的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_ DriverApplication Interface layer两个部分组成。

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

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

 

 

 

 

 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_CallbackEPX_OUT_Callback()14个函数(X=12...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.cDevice_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_CONFIGURATIONSET_ADDRESSSET_FEATURECLEAR_FEATURE来调用该文件中的相应函数;然后判断是否接收者是接口并且是标准请求,如果是根据是否是SET_INTERFACE来调用文件中相应的函数;其次判断是否接收者是端点并且是标准请求,如果是则根据CLEAR_FEATURESET_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_CONFIGURATIONGET_INTERFACE,如果是调用相关函数。

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

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

 

 

pdf下载地址 http://u.xunzai.com/fileview_208803.html

 

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值