理解和解码标准USB命令到端点零?

时间:2014-01-25 22:22:44

标签: embedded usb hardware risc

我正在尝试为8位RISC MCU编写USB初始化程序。数据表链接如下。

我的目标是编写设备原型代码,让主机成功枚举我的设备并发送/接收数据。

在这个IC的SDK中有一个没有源的UFI静态库,只有很少的函数在头文件中定义:

//
// Command/Data/Status Protocol
//
typedef struct _CBW // Command Block Wrapper
{
    unsigned char dSignature[4];    // 43425355h (little endian)
    unsigned char dTag[4];
    unsigned char dDataTransferLength[4];
    unsigned char bmFlags;          // Bit 7    0 = Data-Out from host to the device.
                                    //          1 = Data-In from the device to host.
                                    // Bit 6    Obsolete
    unsigned char bLUN;
    unsigned char bCBLength;
    unsigned char CB[0x10];         // offset: (15 + bCBLength - 1)
} CBW;
typedef struct _CSW // Command Status Wrapper
{
    unsigned char dSignature[4];    // 53425355h (little endian)
    unsigned char dTag[4];
    unsigned char dDataResidue[4];
    unsigned char bStatus;          // 00h  Command Passed ("good status")
                                    // 01h  Command Failed
                                    // 02h  Phase Error
                                    // 03h and 04h  Reserved (Obsolete)
} CSW;

#define COMMAND_PASSED 0x00
#define COMMAND_FAILED 0x01
#define PHASE_ERROR    0x02

enum
{
UFI_MODE_TIMESYNC = 1,
UFI_MODE_DOWNSTART,
UFI_MODE_DOWNFINISH,
UFI_MODE_IGNORE,
UFI_MODE_NORMAL
};

//
// UFI Command
//
#define INQUIRY                      0x12
#define READ_FORMAT_CAPACITIES       0x23
#define READ_CAPACITY                0x25
#define READ_10                      0x28
#define REQUEST_SENSE                0x03
#define TEST_UNIT_READY              0x00
#define PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
#define WRITE_10                     0x2a
#define VERIFY                       0x2f

typedef struct
{
    UCHAR memType; // 0:eflash 1:s-flash
    ULONG tgtAddr; // Target address to write
    ULONG totSize; // Total size of data
    ULONG curSize; // Downloaded size of data
}stUfiDwnStatus;

UFI_EXT CBW g_cbw;
UFI_EXT CSW g_csw;
UFI_EXT unsigned char g_bUfiWriteMode;
UFI_EXT unsigned char g_bUfiWriteMode_post;
UFI_EXT stUfiDwnStatus g_ufiDwnStaus;



void UFI_proc(void);
void UFI_InitMem(UCHAR *buf, UCHAR *name);  // Buffer size must be larger than 0x200
void UFI_InitFuncEFlash(void (*funcSectorErase)(UCHAR AddH, UCHAR AddM, UCHAR AddL),
                        void (*funcPageProgram)(UCHAR AddH, UCHAR AddM, UCHAR AddL, int size, UCHAR *Buffer),
                        void (*funcRead)(UCHAR AddH, UCHAR AddM, UCHAR AddL, int size, UCHAR *Buffer) );
void UFI_InitFuncSFlash(void (*funcBlockErase)(UCHAR AddH, UCHAR AddM, UCHAR AddL),
                        void (*funcPageProgram)(UCHAR AddH, UCHAR AddM, UCHAR AddL, int size, UCHAR *Buffer),
                        void (*funcRead)(UCHAR AddH, UCHAR AddM, UCHAR AddL, int size, UCHAR *Buffer) );

不知何故,我必须使用此库才能将我的设备设置为大容量存储,以避免处理自定义主机设备驱动程序。

问题是我不知道从哪里开始。特别是我不明白如何配置EP0? USB功能列表提到了

Understanding and decoding of standard USB commands to endpoint zero

究竟是什么意思?文档非常缺乏,我不知道为了至少在设备端初始化USB设备需要遵循什么逻辑。我一般都会阅读有关USB的内容,但我无法将这些知识与我构建代码的方式结合起来......我已经对该IC上的所有外设进行了编码,但USB除外。

任何想法都会受到高度赞赏。

https://www.dropbox.com/s/qd9d25oxxvh23ia/BMC51A_UM_REV1.0.pdf

2 个答案:

答案 0 :(得分:1)

USB规范的第9章介绍了“端点零的标准USB命令”。我通常会参考修订版2.0,你可以在这里找到:

http://www.usb.org/developers/docs/usb20_docs/

只需下载ZIP文件,找到usb_20.pdf,然后转到第9章。该章定义了端点零点上的控制传输,USB主机使用它来获取描述符和设置设备。 USB规范大约有600页,但它非常易读,您应该可以从中学到很多东西。

要使您的设备像大容量存储设备一样运行,您需要实现大容量存储类别中USB-IF设备类文档中描述的更多功能:

http://www.usb.org/developers/docs/devclass_docs/

如果您在此级别使用USB,则需要某种方式来查看总线上的低级别流量。我建议使用hardware USB protocol analyzer,但您也可以找到一个软件解决方案。您也可以使用示波器,但需要很长时间才能解码每个数据包并找到您要查找的内容。

您发布的代码看起来与标准USB命令无关。它可能与MSD类有关,也可能是一些自定义协议。

答案 1 :(得分:1)

“端点零”是USB中的“控制传输”。

对于数据交换,存在“批量转移”(批量输入和批量输出,具有不同的端点)。

我的建议是,您首先在PC中编写一个简单的USB驱动程序,以了解usb的工作原理。

您可以使用“tcpdump”(在“modprobe usbmon”之后使用接口usbmon0,usbmon1等)在linux上嗅探usb数据包。使用wireshark查看数据包。

您可以使用libusb轻松地从用户空间访问USB。