stm32--USB(作为U盘)+FatFs的实现
一、USB功能的添加(作为U盘)
添加文件
将官方库中的Library文件夹中的所有有效文件添加到工程中,分为4个文件夹:
- usb class为硬件相关(Library\Class);
- usb driver为底层驱动(Driver);
- usb library为设备核心库(Library\Core);
- usb application为自建目录,存放上述三个文件夹中的各需要修改的template文件(.c.h各2个),和官方例程中的几个文件(3个.c1个.h)。
- 前三个目录下的文件均为只读,不修改;移植时只修改usb application目录下的文件。
移植修改
-
usbd_desc.c、.h, usbd_pwr.c, usbd_usr.c:来自官方例程,不修改
-
usb_conf.h:去掉eval相关的两个.h包含;添加#define INTERNAL_PULLUP
-
usbd_conf.h:删除MSC Class之外的所有Class defines;修改MSC_MEDIA_PACKET为单扇区大小(4096)
-
usb_bsp.c:
-
USB_BSP_Init函数:修改输入参数,符合头文件;使能USB APB时钟;将RCC_USBCLK_HSI48选为USB CLK;配置CRS(时钟恢复系统)。
-
USB_BSP_EnableInterrupt函数:配置、使能USB中断。
-
usbd_storage.c:
-
将USBD_MICRO_SDIO_fops的定义移到相关函数声明下方,修改STORAGE_GetCapacity函数第三个参数的参数类型(2处),为STORAGE_Inquirydata加上强制类型转换
-
修改STORAGE_GetCapacity、STORAGE_IsReady、STORAGE_Read、STORAGE_Write函数。
调试修改
出现的问题:编译一直无法通过,提示某些宏定义不存在——可是它们都已经正确地定义了。
解决:将SPIFlash的头文件从usbd_conf.h中移走,仅在usbd_storage.c中包含,问题解决,原因未明。
二、USB与FatFs不冲突的方案选择
USB和FatFs都会操作SPIFlash、对文件页表、目录表做出修改。如果同时在程序中开启USB、挂载FatFs,有可能出现同时修改文件页表、一方修改文件数据与另一方修改文件页表冲突、二者操作SPIFlash冲突等情况,导致系统崩溃。
为了避免这个可能会发生的问题,设想了三种方案:
-
方案1:在需要用FatFs写入时禁用USB中断,检测完毕打开中断。
-
程序中的现象:程序可以正常运行,USB功能没有崩溃;但可能是由于禁用USB中断后没有清空中断标志位,使能中断后有时会错误地进入中断(不影响程序功能)。
-
PC端的现象:在程序禁用USB中断后,PC端依旧能看到可移动磁盘,但无法正常对其进行有效操作;使能中断后,PC又可以正常访问可移动磁盘。
-
选择:这种方法虽然可行性、操作性上没有问题,但这是不合规范的、有风险的,如果有更优方案,应选择更优方案;如果找不到更优方案,只能选择此方案。
-
-
方案2:通过三极管,在需要用FatFs写入时断开D+D-。
-
因需进行硬件修改,暂时无法测试,但这可能是手机上选择充电模式/传文件模式的原理。硬件上直接断开这两根线,相当于拔出了USB线(仅保留供电),理论上完全可行,并且没有风险。
-
选择:此方案优于方案1,但需要对硬件进行更改,如果有其他方案优先选择不更改硬件的方案。
-
-
方案3:仅在需要USB时初始化USB(其他中断控制),其他时候不初始化USB。
-
实现方式:开机后不初始化USB;在收到设定的某个中断时(比如串口收到”connect”)break出原while(1),初始化USB;收到另一个中断信号后(比如串口收到”disconnect”),软件复位单片机。
-
测试结果:完全可行,USB和FatFs在完全分隔开的两端程序中,完全没有交叉,不会互相影响;也不用担心USB的注销问题,直接软件复位即可。
-
选择:选择方案3。
-