我正在尝试为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
答案 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。