找回密码
 注册

微信扫码登录

使用验证码登录

只需一步,快速开始

胜天工科技销售各种数字电视信号调制卡胜天工科技销售各种数字电视信号码流卡

【游客、新手、注册会员的区别】 【积分策略和会员晋级说明】 【发帖和附件上传规则】 【如何下载感兴趣的资料】 【如何获取梦游币】 【侵权资料处理及免责说明】
查看: 2363|回复: 0

基于STM32的USB程序开发笔记(四)

[复制链接]
  • TA的每日心情
    开心
    2016-9-26 15:28
  • 签到天数: 56 天

    [LV.5]常住居民I

    发表于 2009-5-4 21:04:38 | 显示全部楼层 |阅读模式
    分享到:
    消息来自- 北京
    首先说明一个变量,定义在usb_core.c中:
    volatile DEVICE_INFO vsDeviceInfo;
    看意思就知道他的作用了,DEVICE_INFO是个结构,定义在usb_type.h中:
    // *****************************************************************************
    // DEVICE_INFO
    // *****************************************************************************
    typedef struct _DEVICE_INFO
    {
    unsigned char bDeviceAddress;

    unsigned char bCurrentFeature;
    unsigned char bCurrentConfiguration;
    unsigned char bCurrentInterface;
    unsigned char bCurrentAlternateSetting;

    WORD_2BYTE uStatusInfo;

    DEVICE_STATE eDeviceState;
    RESUME_STATE eResumeState;
    CONTROL_STATE eControlState;

    SETUP_DATA SetupData;

    TRANSFER_INFO TransInfo;
    } 
    DEVICE_INFO,
    *PDEVICE_INFO;

    在枚举过程中,就是如何处理好SETUP事件,如果STM32 USB接收到正确的SETUP事件,将响应函数CTR_SETUP0(),SETUP事件是特殊的OUT事件,数据方向Host->Device,SETUP事件数据长度固定为8,数据定义在DEVICE_INFO.SetupData,其数据结构是(定义在usb_type.h??):
    typedef struct _SETUP_DATA
    {
    unsigned char bmRequestType; // request type
    unsigned char bRequest; // request code

    WORD_2BYTE wValue;
    WORD_2BYTE wIndex;
    WORD_2BYTE wLength;
    }
    SETUP_DATA,
    *PSETUP_DATA;

    WORD_2BYTE是定义的一个共用体:
    typedef union _WORD_2BYTE
    {
    unsigned short w;
    struct
    {
    unsigned char LSB;
    unsigned char MSB;
    }b;
    }
    WORD_2BYTE;

    为什么将SETUP数据结构中的wValue,wIndex,wLength如此定义?
    1:USB协议中所有数据传输都是依照低位在先的原则
    2:高地位字节可能功能复用
    这样在后续的程序编写中就变得十分方便,ST提供的USB固件方法同样如此,但这方面的处理让人有些摸不着头脑,详情可参阅。至于具体的SETUP数据结构含义如何,还是要具备基本知识:了解USB协议

    CTR_SETUP0()函数将SETUP数据提取出来,SETUP数据结构有0长度和非0长度的数据结构,详细参阅USB2.0官方协议第9章。在这将两种区别开来分别执行SETUP0_NoData()和SETUP0_Data()函数,并返回结果,根据返回结果再响应USB主机
    // *****************************************************************************
    // Function Name : CTR_SETUP0
    // Description :
    // Input :
    // Output :
    // Return :
    // *****************************************************************************
    void CTR_SETUP0(void)
    {
    RESULT eResult;

    BufferCopy_PMAToUser( (unsigned char *)&vsDeviceInfo.SetupData,
    GetBuffDescTable_RXAddr(ENDP0),
    GetBuffDescTable_RXCount(ENDP0));

    if(vsDeviceInfo.SetupData.wLength.w == 0)
    {
    eResult = SETUP0_NoData();
    }
    else
    {
    eResult = SETUP0_Data();
    }

    switch(eResult)
    {
    case RESULT_SUCCESS:

    break;

    case RESULT_LASTDATA:

    break;

    case RESULT_ERROR:
    case RESULT_UNSUPPORT:
    SetEPR_RXStatus(ENDP0, EP_RX_VALID);
    SetEPR_TXStatus(ENDP0, EP_TX_STALL);
    break;
    }
    }

    SETUP0_Data()和SETUP0_NoData()函数支持的所有USB请求类型只有罗列的这些,有多少种组合都定义在USB协议中,程序根据请求代码,再去执行对应函数,这样做的目的就是让程序结构明了。其中注释为"// done"的部分表明此部分功能已完成。对于未完成部分,希望大家在交流中完善。

    // *****************************************************************************
    // Routine Groups: SETUP_Data
    // *****************************************************************************
    RESULT SETUP0_Data(void)
    {
    // SetupData.bRequest: request code
    switch(vsDeviceInfo.SetupData.bRequest)
    {
    case SR_GET_STATUS: return SR_GetStatus(); // done
    case SR_GET_DESCRIPTOR: return SR_GetDescriptor(); // done
    case SR_SET_DESCRIPTOR: return SR_SetDescriptor(); // unsupport
    case SR_GET_CONFIGURATION: return SR_GetConfiguration(); // done
    case SR_GET_INTERFACE: return SR_GetInterface(); // unsupport
    case SR_SYNCH_FRAME: return SR_SynchFrame(); // unsupport

    default: return RESULT_UNSUPPORT;
    }
    }

    // *****************************************************************************
    // Routine Groups: SETUP_NoData
    // *****************************************************************************
    RESULT SETUP0_NoData(void)
    {
    // SetupData.bRequest: request code
    switch(vsDeviceInfo.SetupData.bRequest)
    {
    case SR_CLEAR_FEATURE: return SR_ClearFeature(); // unsupport
    case SR_SET_FEATURE: return SR_SetFeature(); // unsupport
    case SR_SET_ADDRESS: return SR_SetAddress(); // done
    case SR_SET_CONFIGURATION: return SR_SetConfiguration(); // done
    case SR_SET_INTERFACE: return SR_SetInterface(); // unsupport

    default: return RESULT_UNSUPPORT;
    }
    }

    下篇将介绍上述的各个请求函数如何响应主机。朋友们请多支持啊,这是我第一次较为系统的介绍一个知识点,错误在所难免,网上的USB开发资料不是很齐全,我的目标就是努力抽点时间将USB上、下位机程序开发资料公布出来,作为给想学USB的朋友一个辅助指导,请给我点信心,多支持啊!!!
    踩过的脚印
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|数字电视开发网 ( 京ICP备16008897号-5 )

    GMT+8, 2026-5-14 09:43 , Processed in 0.124330 second(s), 24 queries , Gzip On.

    Powered by Discuz! X3.5

    © 2001-2026 Discuz! Team.

    快速回复 返回顶部 返回列表