有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 草帽王子 于 2021-9-10 18:21 编辑
本章教程主要使用CH32V103 USB模拟U盘设备,此程序是移植而来,仅供参考。
1、USB简介及相关函数介绍
关于USB具体介绍,可参考前面章节。
2、硬件设计
本章教程主要进行USB模拟U盘设备,仅需用到开发板USB口。
3、软件设计
本章程序全在主函数中进行,具体程序如下:
main.c文件
- /********************************** (C) COPYRIGHT *******************************
- * File Name : main.c
- * Author : WCH
- * Version : V1.0.0
- * Date : 2019/10/15
- * Description : Main program body.
- *******************************************************************************/
- #include "debug.h"
- #include "string.h"
- #define DevEP0SIZE 0x40
- /* Device Descriptor */
- const UINT8 MyDevDescr[] =
- {
- 0x12, //设备描述符长度,18字节
- 0x01, //描述符类型,0x01为设备描述符
- 0x10, 0x01, //本设备所使用USB版本协议,因为是小端结构,所以低字节在前,即USB1.1版本为0x10,0x01,USB2.0为0x00,0x02
- 0x00, //类代码,此处不在设备描述符中定义设备类,而在接口描述符中定义设备类。对于大多数标准的USB设备类,该字段通常设置为0,而在接口描述符中的bInterfaceClass中指定接口所实现的功能
- 0x00, //子类代码,当类代码bDeviceClass为0时,下面的子类代码bDeviceSubClass也必须为0。
- 0x00, //设备所使用的协议,协议代码由USB协会规定。当该字段为0时,表示设备不使用类所定义的协议。
- DevEP0SIZE, //端点0的最大包长,可以取值8、16、32、64,此处为64字节
- 0x86, 0x1A, //厂商ID
- 0x22, 0x57, //产品设备ID
- 0x00, 0x01, //设备版本号
- 0x01, //描述厂商的字符串索引值。当该值为0时,表示没有厂商字符串
- 0x02, //描述产品的字符串索引值。当该值为0时,表示没有产品字符串
- 0x03, //描述设备的序列号字符串索引值。当该值为0时,表示没有序列号字符串
- 0x01, //可能的配置数,通常为1
- };
- /* Configration Descriptor */
- const UINT8 MyCfgDescr[] =
- {
- //配置描述符
- 0x09, //配置描述符长度,标准USB配置描述符长度为9字节
- 0x02, //描述符类型,配置描述符为0x02
- 0x20, 0x00, //配置描述符集合总长度,32字节
- 0x01, //该配置所支持的接口数,1个接口
- 0x01, //表示该配置的值
- 0x00, //描述该配置的字符串的索引值,0x00表示没有字符串
- 0xA0, //描述设备的一些属性,如供电方式和唤醒等,0xA0表示设备总线供电且支持远程唤醒
- 0x32, //设备需要从总线获取的最大电流量,0x32表示最大电流100ma
- //接口描述符,接口描述符不能单独返回,必须附着在配置描述符后一并返回
- 0x09, //接口描述符长度,标准的USB接口描述符长度为9字节
- 0x04, //描述符类型,接口描述符为0x04
- 0x00, //该接口的编号,从0开始,此处为0x00
- 0x00, //该接口的备用编号,通常设置为0
- 0x02, //该接口所使用的端点数,0x02表示使用2个端点。如果该字段为0,则表示没有非0端点,只使用默认的控制端点
- 0x08, //该接口所使用的类,0x08为大容量存储设备类
- 0x06, //该接口所使用的子类,0x06,即SCSI透明命令集
- 0x50, //该接口所使用的协议,协议代码有3种:0x00、0x01、0x50,前两种需要使用中断传输,最后一种仅使用批量传输
- 0x00, //该接口的字符串的索引值,0x00表示没有字符串
- //端点描述符,端点描述符不能单独返回,必须附着在配置描述符后一并返回
- 0x07, //端点描述符长度,标准的USB端点描述符长度为7字节
- 0x05, //描述符类型,端点描述符为0x05
- 0x01, //该端点的地址,0x01表示端点1作为输出,最高位D7为该端点的传输方向,1为输入,0为输出。D3-D0为端点号,可设置为0-7,D6-4保留,设为0.
- //关于端点属性,最低两位D1-0表示该端点的传输类型,0为控制传输,1为等时传输,2为批量传输,3为中断传输。
- 0x02, //该端点的属性,此处为批量传输方式
- DevEP0SIZE, 0x00, //该端点支持的最大包长度,此处设置为64字节
- 0x00, //端点的查询时间
- //端点描述符,端点描述符不能单独返回,必须附着在配置描述符后一并返回
- 0x07, //端点描述符长度,标准的USB端点描述符长度为7字节
- 0x05, //描述符类型,端点描述符为0x05
- 0x81, //该端点的地址,0x81表示端点1作为输入,最高位D7为该端点的传输方向,1为输入,0为输出。D3-D0为端点号,可设置为0-7,D6-4保留,设为0.
- //关于端点属性,最低两位D1-0表示该端点的传输类型,0为控制传输,1为等时传输,2为批量传输,3为中断传输。
- 0x02, //该端点的属性,此处为批量传输方式
- DevEP0SIZE, 0x00, //该端点支持的最大包长度,此处设置为64字节
- 0x00, //端点的查询时间
- };
- const UINT8 MyProductIDInfo[] =
- {
- 0x14,0x03, 0x32,0x00,0x30,0x00,0x31,0x00,0x37,0x00,0x2D,0x00,0x32,0x00,0x2D,0x00,0x32,0x00,0x35,0x00
- };
- /* Language Descriptor */
- const UINT8 MyLangDescr[] = { 0x04, 0x03, 0x09, 0x04 };
- /* Manufactor Descriptor */
- const UINT8 MyManuInfo[] = { 0x0A,0x03,0x5F,0x6c,0xCF,0x82,0x81,0x6c,0x52,0x60 };
- /* Product Information */
- const UINT8 MyProdInfo[] = {0x14,0x03,0x43,0x00,0x48,0x00,0x35,0x00,0x35,0x00,0x34,0x00,0x5F,0x00,0x43,0x00,0x44,0x00,0x43,0x00, };
- //Get Max LUN 请求,该字节表示设备有多少个逻辑单元,值为0时表示有一个逻辑单元,值为1时表示有两个逻辑单元,以此类推,最大可以取15
- //定义一个最大逻辑单元的变量,跟描述符类型一样,使用数组的方式来定义,尽管他只有一个元素。
- const UINT8 MAX_LUN[] = {0};
- //INQUIRY inform
- const UINT8 DBINQUITY[]=
- {
- 0x00, //Peripheral Device Type
- 0x80, //
- 0x02 , //ISO/ECMA
- 0x02 , //
- 0x1f , //Additional Length
- 00 , //Reserved
- 00 , //Reserved
- 00 , //Reserved
- 'w' , //Vendor Information
- 'c' , //
- 'h' , //
- '.' , //
- 'c' , //
- 'n' , //
- ' ' , //
- ' ' , //
- 0xc7, //Product Identification
- 0xdf, //
- 0xba, //
- 0xe3, //
- 0xb5, //
- 0xe7, //
- 0xd7, //
- 0xd3, //
- 0x55, //
- 0xc5, //
- 0xcc, //
- 0xb7, //
- 0xbd, //
- 0xb0, //
- 0xb8, //
- 0x00, //
- '1' , //Product Revision Level
- '.' , //
- '1' , //
- '0' //
- };
- #define NUMOFBLOCK 0x40
- #define LASTLGCBLOCK 0x3f
- const UINT8 DBCAPACITY[]={(LASTLGCBLOCK>>24)&0xFF,(LASTLGCBLOCK>>16)&0xFF,(LASTLGCBLOCK>>8)&0xFF,LASTLGCBLOCK&0xFF,0x00,0x00,0x02,0x00};
- const UINT8 modesense3F[]={0x0b, 0x00, 0x00/*0x80*/, 0x08 , (NUMOFBLOCK>>24)&0xFF,(NUMOFBLOCK>>16)&0xFF,(NUMOFBLOCK>>8)&0xFF,NUMOFBLOCK&0xFF,0x00, 0x00, 0x02, 0x00 }; //写保护(0x80换成0x00可以去除写保护)
- //DBR(DOS Boot Record):磁盘操作系统引导记录
- //DBR是每个逻辑分区的一个引导记录,里面记录了该分区的众多重要信息以及引导代码,所以十分重要。在U盘系统中,必须有DBR
- //DBR占据逻辑分区的0扇区,大小通常为512字节,DBR各个部分的意义见《圈圈教你玩USB》
- const UINT8 DBR[512]=
- {
- 0xeb,0x3c,0x90,0x4d,0x53,0x44,0x4f,0x53, 0x35,0x2e,0x30,0x00,0x02,0x01,0x06,0x00,
- 0x02,0x00,0x02,NUMOFBLOCK&0xff,(NUMOFBLOCK>>8)&0xff,0xf8,0x01,0x00, 0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x80,0x00,0x29,0xc3, 0xa5,0x20,0xd8,0x4e,0x4f,0x20,0x4e,0x41,
- 0x4d,0x45,0x20,0x20,0x20,0x20,0x46,0x41, 0x54,0x31,0x32,0x20,0x20,0x20,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xaa,
- };
- //FAT(File Allocation Table):文件分配表
- //在DBR之后,就是FAT区(通常有两个,一个为副本)
- const UINT8 FAT[512]=
- {
- 0xF8,0xFF,0xFF,0xFF,0x0F,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- };
- const UINT8 ZERO[512]=
- {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- };
- //UFI通讯
- #define FORMAT_UNIT 0x04
- #define INQUIRY 0x12
- #define FORMATCAP 0x23
- #define MODE_SELECT 0x15
- #define MODE_SENSE5 0x5A
- #define MODE_SENSE 0x1A
- #define PER_RES_IN 0x5E
- #define PER_RES_OUT 0x5F
- #define PRE_OR_MED 0x1E
- #define READ 0x28
- #define READ_CAPACITY 0x25
- #define RELEASE 0x17
- #define REQUEST_SENSE 0x03
- #define RESERVE 0x16
- #define STA_STO_UNIT 0x1B
- #define SYN_CACHE 0x35
- #define TEST_UNIT 0x00
- #define VERIFY 0x2F
- #define WRITE 0x2A
- #define WRITE_BUFFER 0x3B
- typedef union _CBWCB
- {
- unsigned char buf1[16];
- }CBWCB;
- typedef union _MASS_PARA
- {
- unsigned char buf[64];
- struct _SENSE
- {
- unsigned char ErrorCode;
- unsigned char Reserved1;
- unsigned char SenseKey;
- unsigned char Information[4];
- unsigned char AddSenseLength;
- unsigned char Reserved2[4];
- unsigned char AddSenseCode;
- unsigned char AddSenseCodeQua;
- unsigned char Reserved3[4];
- }Sense;
- struct _CBW
- {
- unsigned char dCBWsig[4];
- unsigned char dCBWTag[4];
- unsigned long dCBWDatL;
- unsigned char bmCBWFlags;
- unsigned char bCBWLUN;
- unsigned char bCBWCBLength;
- CBWCB cbwcb;
- }cbw;
- struct _CSW
- {
- unsigned char buf2[13];
- }csw;
- }MASS_PARA;
- union {
- unsigned long mDataLength; //数据长度
- unsigned char mdataLen[4]; //
- } UFI_Length;
- unsigned char mdCBWTag[4]; //dCBWTag
- MASS_PARA MassPara;
- UINT8 CH32BULKUP=0; //数据上传
- UINT8 CH32BULKDOWN = 0; //数据下传
- UINT8 CH32CSW=0; //CSW上传标志
- unsigned char BcswStatus; //CSW状态
- unsigned char mSenseKey;
- unsigned char mASC;
- unsigned char *pBuf;
- unsigned long SecNum; //当前操作的扇区号
- unsigned char dat_tran_flag = 0;
- /**********************************************************/
- UINT8 Ready = 0;
- UINT8 UsbConfig;
- UINT8 SetupReqCode;
- UINT16 SetupReqLen;
- //cdc参数
- UINT8 LineCoding[7]={0x00,0xe1,0x00,0x00,0x00,0x00,0x08}; //初始化波特率为57600,1停止位,无校验,8数据位。
- #define SET_LINE_CODING 0x20 // Configures DTE rate, stop-bits, parity, and number-of-character
- #define GET_LINE_CODING 0x21 // This request allows the host to find out the currently configured line coding.
- #define SET_CONTROL_LINE_STATE 0x22 // This request generates RS-232/V.24 style control signals.
- volatile UINT8 UpPoint2_Busy = 0; //上传端点是否忙标志
- const UINT8 *pDescr;
- /* Endpoint Buffer */
- __attribute__ ((aligned(4))) UINT8 EP0_Databuf[64+64+64]; //ep0(64)+ep4_out(64)+ep4_in(64)
- __attribute__ ((aligned(4))) UINT8 EP1_Databuf[64+64]; //ep1_out(64)+ep1_in(64)
- __attribute__ ((aligned(4))) UINT8 EP2_Databuf[64+64]; //ep2_out(64)+ep2_in(64)
- __attribute__ ((aligned(4))) UINT8 EP3_Databuf[64+64]; //ep3_out(64)+ep3_in(64)
- void USBHD_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
- /*******************************************************************************
- * Function Name : UFI_Hunding
- * Description : 命令的分类与识别 UFI CMD
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
- void UFI_Hunding(void )
- {
- switch(MassPara.cbw.cbwcb.buf1[0])
- {
- //查询命令 INQUIRY,操作代码为0x12
- case INQUIRY:
- pBuf = (UINT8 *)DBINQUITY; //查询U盘信息
- if(UFI_Length.mDataLength>sizeof(DBINQUITY)) UFI_Length.mDataLength=sizeof(DBINQUITY);
- BcswStatus=0;
- mSenseKey=0;
- mASC=0;
- break;
- //主机通常使用WRITE命令往设备写入实际的磁盘数据,操作代码为0x2A
- case WRITE:
- UFI_Length.mDataLength=(((UINT32)MassPara.cbw.cbwcb.buf1[7]<<8) | (UINT32)MassPara.cbw.cbwcb.buf1[8])*512; //发送长度
- SecNum = ((UINT32)MassPara.cbw.cbwcb.buf1[2]<<24) | ((UINT32)MassPara.cbw.cbwcb.buf1[3]<<16) | ((UINT32)MassPara.cbw.cbwcb.buf1[4]<<8) | (UINT32)MassPara.cbw.cbwcb.buf1[5];//起始扇区号
- dat_tran_flag = 1;
- BcswStatus=0;
- mSenseKey=0;
- mASC=0;
- break;
- case PRE_OR_MED:
- case TEST_UNIT:
- case 0x3b:
- CH32BULKDOWN=0;
- CH32BULKUP=0;
- BcswStatus=0;
- mSenseKey=0;
- mASC=0;
- break;
- //主机通常使用READ命令来读取实际的磁盘数据,操作代码为0x28
- case READ:
- UFI_Length.mDataLength=(((UINT32)MassPara.cbw.cbwcb.buf1[7]<<8) | (UINT32)MassPara.cbw.cbwcb.buf1[8])*512; //发送长度
- SecNum = ((UINT32)MassPara.cbw.cbwcb.buf1[2]<<24) | ((UINT32)MassPara.cbw.cbwcb.buf1[3]<<16) | ((UINT32)MassPara.cbw.cbwcb.buf1[4]<<8) | (UINT32)MassPara.cbw.cbwcb.buf1[5];//起始扇区号
- dat_tran_flag = 1;
- BcswStatus=0;
- mSenseKey=0;
- mASC=0;
- break;
- //REQUEST SENSE命令用来探测上一个命令执行失败的原因,主机可在每个命令之后使用该命令来读取命令执行的情况,其命令代码为0x03
- case REQUEST_SENSE:
- MassPara.Sense.ErrorCode=0x70;
- MassPara.Sense.Reserved1=0;
- MassPara.Sense.SenseKey=mSenseKey;
- MassPara.Sense.Information[0]=0;
- MassPara.Sense.Information[1]=0;
- MassPara.Sense.Information[2]=0;
- MassPara.Sense.Information[3]=0;
- MassPara.Sense.AddSenseLength=0x0a;
- MassPara.Sense.Reserved2[0]=0;
- MassPara.Sense.Reserved2[1]=0;
- MassPara.Sense.Reserved2[2]=0;
- MassPara.Sense.Reserved2[3]=0;
- MassPara.Sense.AddSenseCode=mASC;
- MassPara.Sense.AddSenseCodeQua=0;
- MassPara.Sense.Reserved3[0]=0;
- MassPara.Sense.Reserved3[1]=0;
- MassPara.Sense.Reserved3[2]=0;
- MassPara.Sense.Reserved3[3]=0;
- pBuf=MassPara.buf;
- if ( UFI_Length.mDataLength > 18 ) UFI_Length.mDataLength = 18;
- BcswStatus=0;
- mSenseKey=0;
- mASC=0;
- break;
- //读容量命令,可以让主机读取到当前存储媒介的容量,此命令读到的才是实际的磁盘容量
- case READ_CAPACITY:
- if ( UFI_Length.mDataLength > sizeof(DBCAPACITY) ) UFI_Length.mDataLength = sizeof(DBCAPACITY);
- pBuf=(unsigned char*)DBCAPACITY;
- BcswStatus=0;
- mSenseKey=0;
- mASC=0;
- break;
- case MODE_SENSE:
- if ( UFI_Length.mDataLength > sizeof(modesense3F) ) UFI_Length.mDataLength = sizeof(modesense3F);
- pBuf=(unsigned char*)modesense3F;
- BcswStatus=0;
- mSenseKey=0;
- mASC=0;
- break;
- default:
- mSenseKey=5;
- if (MassPara.cbw.cbwcb.buf1[0] == FORMATCAP)
- mASC=0x20;
- else
- mASC=0x24;
- BcswStatus=1;
- if(CH32BULKUP)
- {
- R8_UEP1_CTRL = R8_UEP1_CTRL | UEP_T_RES_STALL;
- }
- else
- {
- R8_UEP1_CTRL = R8_UEP1_CTRL | UEP_R_RES_STALL;
- }
- break;
- }
- }
- /*******************************************************************************
- * Function Name : mCH32UpCsw
- * Description : 批量协议状态上传
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
- void mCH32UpCsw()
- {
- unsigned char i; //如果数据为0
- pBuf=&MassPara.buf[0];
- CH32CSW=0; //上传CSW
- CH32BULKUP=0; //取消数据上传
- MassPara.buf[0]=0x55; //dCSWSignature
- MassPara.buf[1]=0x53;
- MassPara.buf[2]=0x42;
- MassPara.buf[3]=0x53;
- MassPara.buf[4]=mdCBWTag[0];
- MassPara.buf[5]=mdCBWTag[1];
- MassPara.buf[6]=mdCBWTag[2];
- MassPara.buf[7]=mdCBWTag[3];
- MassPara.buf[8]=UFI_Length.mdataLen[3];
- MassPara.buf[9]=UFI_Length.mdataLen[2];
- MassPara.buf[10]=UFI_Length.mdataLen[1];
- MassPara.buf[11]=UFI_Length.mdataLen[0];
- MassPara.buf[12]=BcswStatus;
- for(i = 0;i<13;i++)
- {
- pEP1_RAM_Addr[MAX_PACKET_SIZE+i] = *pBuf;
- pBuf++;
- }
- R8_UEP1_T_LEN = 13;
- R8_UEP1_CTRL = (R8_UEP1_CTRL & ~ MASK_UEP_T_RES) | UEP_T_RES_ACK; // 允许上传
- }
- /*******************************************************************************
- * Function Name : mCH32BulkOnly
- * Description : 批量协议处理
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
- void mCH32BulkOnly(){
- if(MassPara.buf[0]==0x55){
- if(MassPara.buf[1]==0x53){
- if(MassPara.buf[2]==0x42){
- if(MassPara.buf[3]==0x43){
- UFI_Length.mdataLen[3] = *(unsigned char *)(&MassPara.cbw.dCBWDatL); /* 将PC机的低字节在前的16位字数据转换为C51的高字节在前的数据 */
- UFI_Length.mdataLen[2] = *( (unsigned char *)(&MassPara.cbw.dCBWDatL) + 1 );
- UFI_Length.mdataLen[1] = *( (unsigned char *)(&MassPara.cbw.dCBWDatL) + 2 );
- UFI_Length.mdataLen[0] = *( (unsigned char *)(&MassPara.cbw.dCBWDatL) + 3 );
- mdCBWTag[0]=MassPara.buf[4];
- mdCBWTag[1]=MassPara.buf[5];
- mdCBWTag[2]=MassPara.buf[6];
- mdCBWTag[3]=MassPara.buf[7]; //取出数据长度
- if(UFI_Length.mDataLength){
- CH32BULKDOWN=(MassPara.cbw.bmCBWFlags&0X80)?0:1; //判断是上传还是下传数据
- CH32BULKUP=(MassPara.cbw.bmCBWFlags&0X80)?1:0;
- }
- CH32CSW=1;
- dat_tran_flag = 0; //数据传输标志位先清零
- UFI_Hunding(); //调用UFI协议处理
- }
- else
- R8_UEP1_CTRL = R8_UEP1_CTRL | UEP_T_RES_STALL ;
- }
- else
- R8_UEP1_CTRL = R8_UEP1_CTRL | UEP_T_RES_STALL ;
- }
- else
- R8_UEP1_CTRL = R8_UEP1_CTRL | UEP_T_RES_STALL ;
- }
- else
- R8_UEP1_CTRL = R8_UEP1_CTRL | UEP_T_RES_STALL ;
- }
- /*******************************************************************************
- * Function Name : CH32bulkUpData
- * Description : 批量协议上传
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
- unsigned char file_dat[64]; //文件大小固定64字节
- //文件前四个字节(16H 75H 73H 62H) //测试阶段暂用“fusb”
- void CH32bulkUpData()
- { //调用端点1上传数据
- unsigned char len,i;
- unsigned char rootdir = 0; //当前读目录项标志
- unsigned char datfield = 0; //数据区标志
- //根据读取的地址,分析是否切换pBuf
- if(dat_tran_flag)
- {
- if((UFI_Length.mDataLength&0x1ff)==0)
- {
- if(SecNum==0)
- {
- pBuf = (UINT8 *)DBR;
- }
- else if(SecNum==6 || SecNum==7)
- {
- pBuf = (UINT8 *)FAT;
- }
- else
- {
- pBuf = (UINT8 *)ZERO;
- }
- if(SecNum == 8)
- {
- rootdir = 1;
- }
- if(SecNum==40)
- {
- datfield = 1;
- }
- SecNum++;
- }
- }
- if(UFI_Length.mDataLength>MAX_PACKET_SIZE)
- {
- len=MAX_PACKET_SIZE;
- UFI_Length.mDataLength-=MAX_PACKET_SIZE;
- }
- else
- {
- len= (unsigned char) UFI_Length.mDataLength;
- UFI_Length.mDataLength=0;
- CH32BULKUP=0;
- }
- for(i = 0;i<len;i++)
- {
- pEP1_RAM_Addr[MAX_PACKET_SIZE+i] = *pBuf;
- pBuf++;
- }
- /* 改写 */
- if(rootdir) /* 改写根目录 */
- {
- memcpy(&pEP1_RAM_Addr[MAX_PACKET_SIZE],"WCH_CFG TXT ",12);
- pEP1_RAM_Addr[MAX_PACKET_SIZE+0x1A]=2;
- pEP1_RAM_Addr[MAX_PACKET_SIZE+0x1C]= 64;
- }
- if(datfield) /* 改写数据区 */
- {
- //ReadDataFlash(0,64,&pEP1_RAM_Addr[MAX_PACKET_SIZE]);
- }
- R8_UEP1_T_LEN = len;
- R8_UEP1_CTRL = (R8_UEP1_CTRL & ~ MASK_UEP_T_RES) | UEP_T_RES_ACK; // 允许上传
- }
- void mCH32BulkDownData()
- {
- UINT8 len;
- len = R8_USB_RX_LEN;
- if(dat_tran_flag) //传输数据
- {
- if((UFI_Length.mDataLength&0x1ff)==0)
- {
- if((pEP1_RAM_Addr[0]=='f') && (memcmp(&pEP1_RAM_Addr[1],"usb",3)==0))
- {
- //FLASH_Write(0,&pEP1_RAM_Addr[0],64); //同时写入Flash
- }
- }
- }
- UFI_Length.mDataLength-=len;
- if(UFI_Length.mDataLength==0)
- {
- CH32BULKDOWN=0;
- mCH32UpCsw();
- }
- }
- /*******************************************************************************
- * Function Name : USB_DevTransProcess
- * Description : USB device transfer process.
- * Input : None
- * Return : None
- *******************************************************************************/
- void USB_DevTransProcess( void )
- {
- UINT8 len, length, chtype;
- UINT8 intflag, errflag = 0;
- intflag = R8_USB_INT_FG;
- if( intflag & RB_UIF_TRANSFER )
- {
- switch ( R8_USB_INT_ST & ( MASK_UIS_TOKEN | MASK_UIS_ENDP ) )
- {
- case UIS_TOKEN_SETUP:
- R8_UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
- len = R8_USB_RX_LEN;
- if ( len == sizeof( USB_SETUP_REQ ) )
- {
- SetupReqLen = pSetupReqPak->wLength;
- SetupReqCode = pSetupReqPak->bRequest;
- chtype = pSetupReqPak->bRequestType;
- len = 0;
- errflag = 0;
- if ( ( pSetupReqPak->bRequestType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )
- {
- if(SetupReqCode == 0xFE) //GET MAX LUN
- {
- pDescr = (PUINT8)( &MAX_LUN[0] );
- len = 1;
- if ( SetupReqLen > len )
- {
- SetupReqLen = len; // 限制总长度
- }
- len = SetupReqLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupReqLen; // 本次传输长度
- memcpy( pEP0_RAM_Addr, pDescr, len ); /* 加载上传数据 */
- //SetupLen -= len;
- pDescr += len;
- }
- else
- errflag = 0xFF;
- }
- else
- {
- switch( SetupReqCode )
- {
- case USB_GET_DESCRIPTOR:
- {
- switch( ((pSetupReqPak->wValue)>>8) )
- {
- case USB_DESCR_TYP_DEVICE:
- pDescr = MyDevDescr;
- len = MyDevDescr[0];
- break;
- case USB_DESCR_TYP_CONFIG:
- pDescr = MyCfgDescr;
- len = MyCfgDescr[2];
- break;
- case USB_DESCR_TYP_STRING:
- switch( (pSetupReqPak->wValue)&0xff )
- {
- case 1:
- pDescr = MyManuInfo;
- len = MyManuInfo[0];
- break;
- case 2:
- pDescr = MyProdInfo;
- len = MyProdInfo[0];
- break;
- case 0:
- pDescr = MyLangDescr;
- len = MyLangDescr[0];
- break;
- case 3:
- pDescr = (PUINT8)( &MyProductIDInfo[0] );
- len = sizeof( MyProductIDInfo );
- break;
- default:
- errflag = 0xFF;
- break;
- }
- break;
- default :
- errflag = 0xff;
- break;
- }
- if( SetupReqLen>len ) SetupReqLen = len;
- len = (SetupReqLen >= DevEP0SIZE) ? DevEP0SIZE : SetupReqLen;
- memcpy( pEP0_DataBuf, pDescr, len );
- //SetupReqLen -= len;
- pDescr += len;
- }
- break;
- case USB_SET_ADDRESS:
- SetupReqLen = (pSetupReqPak->wValue)&0xff;
- break;
- case USB_GET_CONFIGURATION:
- pEP0_DataBuf[0] = UsbConfig;
- if ( SetupReqLen > 1 ) SetupReqLen = 1;
- break;
- case USB_SET_CONFIGURATION:
- UsbConfig = (pSetupReqPak->wValue)&0xff;
- break;
- case USB_CLEAR_FEATURE:
- if( ( pSetupReqPak->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE ) /* 清除设备 */
- {
- if((pSetupReqPak->wValue) == 0x01 )
- {
- if( MyCfgDescr[ 7 ] & 0x20 )
- {
- /* 唤醒 */
- }
- else
- {
- errflag = 0xFF; /* 操作失败 */
- }
- }
- else
- {
- errflag = 0xFF; /* 操作失败 */
- }
- }
- else if ( ( pSetupReqPak->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
- {
- switch( (pSetupReqPak->wIndex)&0xff )
- {
- case 0x83:
- R8_UEP3_CTRL = (R8_UEP3_CTRL & ~ ( RB_UEP_T_TOG | MASK_UEP_T_RES )) | UEP_T_RES_NAK;
- break;
- case 0x03:
- R8_UEP3_CTRL = (R8_UEP3_CTRL & ~ ( RB_UEP_T_TOG | MASK_UEP_R_RES )) | UEP_R_RES_ACK;
- break;
- case 0x82:
- R8_UEP2_CTRL = (R8_UEP2_CTRL & ~( RB_UEP_T_TOG|MASK_UEP_T_RES )) | UEP_T_RES_NAK;
- break;
- case 0x02:
- R8_UEP2_CTRL = (R8_UEP2_CTRL & ~( RB_UEP_R_TOG|MASK_UEP_R_RES )) | UEP_R_RES_ACK;
- break;
- case 0x81:
- R8_UEP1_CTRL = (R8_UEP1_CTRL & ~( RB_UEP_T_TOG|MASK_UEP_T_RES )) | UEP_T_RES_NAK;
- if(CH32CSW)
- {
- CH32CSW=0;
- mCH32UpCsw();
- }
- break;
- case 0x01:
- R8_UEP1_CTRL = (R8_UEP1_CTRL & ~( RB_UEP_R_TOG|MASK_UEP_R_RES )) | UEP_R_RES_ACK;
- if(CH32CSW)
- {
- CH32CSW = 0;
- mCH32UpCsw();
- }
- break;
- default:
- errflag = 0xFF;
- break;
- }
- }
- else errflag = 0xFF;
- break;
- case USB_SET_FEATURE: /* Set Feature */
- if( ( pSetupReqPak->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE ) /* 设置设备 */
- {
- if(( pSetupReqPak->wValue) == 0x01 )
- {
- if( MyCfgDescr[ 7 ] & 0x20 )
- {
- ;
- }
- else
- {
- errflag = 0xFF; /* 操作失败 */
- }
- }
- else
- {
- errflag = 0xFF; /* 操作失败 */
- }
- }
- else if( ( pSetupReqPak->bRequestType & 0x1F ) == USB_REQ_RECIP_ENDP ) /* 设置端点 */
- {
- if(( pSetupReqPak->wValue) == 0x00 )
- {
- switch(pSetupReqPak->wIndex)
- {
- case 0x83:
- R8_UEP3_CTRL = (R8_UEP3_CTRL & (~RB_UEP_R_TOG)) | UEP_T_RES_STALL;/* 设置端点3 IN STALL */
- break;
- case 0x03:
- R8_UEP3_CTRL = (R8_UEP3_CTRL & (~RB_UEP_R_TOG)) | UEP_R_RES_STALL;/* 设置端点3 OUT Stall */
- break;
- case 0x82:
- R8_UEP2_CTRL = (R8_UEP2_CTRL & (~RB_UEP_R_TOG)) | UEP_T_RES_STALL;/* 设置端点2 IN STALL */
- break;
- case 0x02:
- R8_UEP2_CTRL = (R8_UEP2_CTRL & (~RB_UEP_R_TOG)) | UEP_R_RES_STALL;/* 设置端点2 OUT Stall */
- break;
- case 0x81:
- R8_UEP1_CTRL = (R8_UEP1_CTRL & (~RB_UEP_R_TOG)) | UEP_T_RES_STALL;/* 设置端点1 IN STALL */
- break;
- case 0x01:
- R8_UEP1_CTRL = (R8_UEP1_CTRL & (~RB_UEP_R_TOG)) | UEP_R_RES_STALL;/* 设置端点1 OUT Stall */
- break;
- default:
- errflag = 0xFF; /* 操作失败 */
- break;
- }
- }
- else
- {
- errflag = 0xFF; /* 操作失败 */
- }
- }
- else
- {
- errflag = 0xFF; /* 操作失败 */
- }
- break;
- case USB_GET_INTERFACE:
- pEP0_DataBuf[0] = 0x00;
- if ( SetupReqLen > 1 ) SetupReqLen = 1;
- break;
- case USB_GET_STATUS:
- pEP0_DataBuf[0] = 0x00;
- pEP0_DataBuf[1] = 0x00;
- if ( SetupReqLen > 2 ) SetupReqLen = 2;
- break;
- default:
- errflag = 0xff;
- break;
- }
- }
- }
- else errflag = 0xff;
- if( errflag == 0xff)
- {
- // SetupReqCode = 0xFF;
- R8_UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL;
- }
- else
- {
- if( chtype & 0x80 )
- {
- len = (SetupReqLen>DevEP0SIZE) ? DevEP0SIZE : SetupReqLen;
- SetupReqLen -= len;
- }
- else len = 0;
- R8_UEP0_T_LEN = len;
- R8_UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;
- }
- break;
- case UIS_TOKEN_IN:
- switch( SetupReqCode )
- {
- case USB_GET_DESCRIPTOR:
- len = SetupReqLen >= DevEP0SIZE ? DevEP0SIZE : SetupReqLen;
- memcpy( pEP0_DataBuf, pDescr, len );
- SetupReqLen -= len;
- pDescr += len;
- R8_UEP0_T_LEN = len;
- R8_UEP0_CTRL ^= RB_UEP_T_TOG;
- break;
- case USB_SET_ADDRESS:
- R8_USB_DEV_AD = (R8_USB_DEV_AD&RB_UDA_GP_BIT) | SetupReqLen;
- R8_UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
- break;
- default:
- R8_UEP0_T_LEN = 0;
- R8_UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
- break;
- }
- break;
- case UIS_TOKEN_OUT:
- R8_UEP0_T_LEN = 0;
- R8_UEP0_CTRL ^= RB_UEP_R_TOG; //状态阶段,对IN响应NAK
- break;
- case UIS_TOKEN_OUT | 1:
- if ( R8_USB_INT_ST & RB_UIS_TOG_OK )
- {
- if(CH32BULKDOWN)
- {
- mCH32BulkDownData(); //如果上传数据阶段则调用数据上传
- }
- else
- { //不是数据下传则判断是否
- length = R8_USB_RX_LEN;
- if(!length)break; //数据包长度为零则跳出
- for(len=0;len!=length;len++)
- {
- MassPara.buf[len]=pEP1_RAM_Addr[len]; //将数据读入到缓冲区
- }
- mCH32BulkOnly();
- if(BcswStatus ==0 )
- {
- if(!CH32BULKDOWN){
- if(CH32BULKUP) CH32bulkUpData(); //调用批量数据上传
- else mCH32UpCsw(); //test
- }
- }
- }
- }
- break;
- case UIS_TOKEN_IN | 1:
- if(CH32BULKUP)
- {
- CH32bulkUpData(); //调用数据上传
- }
- else if(CH32CSW)
- {
- CH32CSW = 0;
- mCH32UpCsw(); //上传CSW
- }
- else
- {
- R8_UEP1_T_LEN = 0;
- R8_UEP1_CTRL = (R8_UEP1_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
- }
- break;
- case UIS_TOKEN_OUT | 2:
- break;
- case UIS_TOKEN_IN | 2:
- R8_UEP2_T_LEN = 0;
- R8_UEP2_CTRL = (R8_UEP2_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
- UpPoint2_Busy = 0;
- break;
- case UIS_TOKEN_OUT | 3:
- if ( R8_USB_INT_ST & RB_UIS_TOG_OK )
- {
- len = R8_USB_RX_LEN;
- DevEP3_OUT_Deal( len );
- }
- break;
- case UIS_TOKEN_IN | 3:
- R8_UEP3_T_LEN = 0;
- R8_UEP3_CTRL = (R8_UEP3_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
- break;
- case UIS_TOKEN_OUT | 4:
- if ( R8_USB_INT_ST & RB_UIS_TOG_OK )
- {
- R8_UEP4_CTRL ^= RB_UEP_R_TOG;
- len = R8_USB_RX_LEN;
- DevEP4_OUT_Deal( len );
- }
- break;
- case UIS_TOKEN_IN | 4:
- R8_UEP4_T_LEN = 0;
- R8_UEP4_CTRL ^= RB_UEP_T_TOG;
- R8_UEP4_CTRL = (R8_UEP4_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
- break;
- default:
- break;
- }
- R8_USB_INT_FG = RB_UIF_TRANSFER;
- }
- else if( intflag & RB_UIF_BUS_RST )
- {
- R8_USB_DEV_AD = 0;
- R8_UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
- R8_UEP1_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
- R8_UEP2_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
- R8_UEP3_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
- R8_USB_INT_FG |= RB_UIF_BUS_RST;
- }
- else if( intflag & RB_UIF_SUSPEND )
- {
- if ( R8_USB_MIS_ST & RB_UMS_SUSPEND ) {;}
- else{;}
- R8_USB_INT_FG = RB_UIF_SUSPEND;
- }
- else
- {
- R8_USB_INT_FG = intflag;
- }
- }
- /*******************************************************************************
- * Function Name : Set_USBConfig
- * Description : Set USB clock.
- * Input : None
- * Return : None
- *******************************************************************************/
- void USBHD_ClockCmd(UINT32 RCC_USBCLKSource,FunctionalState NewState)
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, NewState);
- EXTEN->EXTEN_CTR |= EXTEN_USBHD_IO_EN;
- RCC_USBCLKConfig(RCC_USBCLKSource); //USBclk=PLLclk/1.5=48Mhz
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHD,NewState);
- }
- /*******************************************************************************
- * Function Name : main
- * Description : Main program.
- * Input : None
- * Return : None
- *******************************************************************************/
- int main(void)
- {
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- Delay_Init();
- USART_Printf_Init(115200);
- printf("USBHD Device Test\r\n");
- pEP0_RAM_Addr = EP0_Databuf;
- pEP1_RAM_Addr = EP1_Databuf;
- pEP2_RAM_Addr = EP2_Databuf;
- pEP3_RAM_Addr = EP3_Databuf;
- USBHD_ClockCmd(RCC_USBCLKSource_PLLCLK_1Div5,ENABLE);
- USB_DeviceInit();
- NVIC_EnableIRQ( USBHD_IRQn );
- while(1)
- {
- ;
- }
- }
- /*******************************************************************************
- * Function Name : DevEP1_OUT_Deal
- * Description : Deal device Endpoint 1 OUT.
- * Input : l: Data length.
- * Return : None
- *******************************************************************************/
- void DevEP1_OUT_Deal( UINT8 l )
- {
- ;
- }
- /*******************************************************************************
- * Function Name : DevEP2_OUT_Deal
- * Description : Deal device Endpoint 2 OUT.
- * Input : l: Data length.
- * Return : None
- *******************************************************************************/
- void DevEP2_OUT_Deal( UINT8 l )
- {
- ;
- }
- /*******************************************************************************
- * Function Name : DevEP3_OUT_Deal
- * Description : Deal device Endpoint 3 OUT.
- * Input : l: Data length.
- * Return : None
- *******************************************************************************/
- void DevEP3_OUT_Deal( UINT8 l )
- {
- ;
- }
- /*******************************************************************************
- * Function Name : DevEP4_OUT_Deal
- * Description : Deal device Endpoint 4 OUT.
- * Input : l: Data length.
- * Return : None
- *******************************************************************************/
- void DevEP4_OUT_Deal( UINT8 l )
- {
- ;
- }
- /*******************************************************************************
- * Function Name : USB_IRQHandler
- * Description : This function handles USB exception.
- * Input : None
- * Return : None
- *******************************************************************************/
- void USBHD_IRQHandler (void)
- {
- USB_DevTransProcess();
- }
复制代码 main.c文件中描述符部分都进行了注释,便于大家理解,其余部分可以参考《圈圈教你玩USB》。关于USB设备传输过程,可结合应用手册关于USB寄存器介绍进行理解学习。
4、下载验证
将编译好的程序下载到开发板并复位,打开串口调试助手,串口打印如下:
用公对公USB线将开发板与电脑连接起来,打开磁盘驱动器可以看到多了一个U盘设备,如图所示:
查看此电脑,可以看到多了一个U盘,如图所示:
83、CH32V103 USB模拟U盘.rar
83、CH32V103 USB模拟U盘.rar
(491.21 KB, 下载次数: 14)
链接:https://pan.baidu.com/s/1NVWBRbfnxL2WLHEFdXFs1Q
提取码:sw7n
复制这段内容后打开百度网盘手机App,操作更方便哦
完
|