前两天官网上下载的STM32_USB-FS-Device_Driver固件库,当时是最新的。。以后当然就不是最新的了。。别说我骗你。。
V3.6.1 固件库 + V4.0.0 USB库 + 0.10a Fatfs + V5.1.0 SDIO_SDCARD
昨天忙了一天,把这几样东西移到了一起,基本上没什么难的,但是有一些比较蛋疼的地方,研究了很久,才搞定,在此记录一下,避免其他人走弯路。感觉新版本的移植,比旧版本容易一点。网络上目前现有的资料,版本都相当古老,新版本的资料除了官网的例程以外,几乎没有。所以稍微讲讲移植中要注意的问题吧。
现在FATFS的版本是0.10a,和之前0.07,0.09版本最大的不同,就是盘符可以支持字母了。f_mount的用法有变,不再用数字了,而用一个字符串表示盘符,最后一个参数表示是否立刻挂载。如果不立刻挂载,下次调用其他函数的时候,会自动挂载:
res = f_mount(&fs, "1:", 1);
FATFS移植,只要修改diskio.c就可以了。
disk_initialize()里面,直接改成这样就可以:
result = SD_Init();
if(result == SD_OK)
return RES_OK;
disk_read()比较坑,用以前的代码直接复制进去,结果只能读2048个字节,一次读取超过2048个,则卡死在disk_read里面,这类问题之前也有很多人遇到,但是我没找到什么有用的经验。参考官方SDIO的例程,发现V5.1.0的stm3210e_eval_sdio_sd的用法有一点点小变化:
result = SD_ReadMultiBlocks((uint8_t *)buff, sector << 9, _MAX_SS, count);
SD_WaitReadOperation();
while(SD_GetStatus() != SD_TRANSFER_OK);
后面两句一定不能少,之前我用的版本V4.7.0,没有调用SD_WaitReadOperation(),但是现在这个版本如果缺了这句,会出现只能读取2048个的问题。
disk_write()跟read一样的,SD_WaitWriteOperation();要加上。
FATFS移植就讲到这。然后看看USB。之前我一直用的都是V3.1.1的USB库,前两天下载官方例程,发现里面的USB库已经更新到V4.0.0了,应该更新了无数次了吧?当时就想想,已经好久没更新了,就想试一下换新版本。先试了一下Joystick,然后修改成USB HID 键盘,整个修改过程和之前V3.1.1没有很大差别,网络上的各种资料仍然适用,就不多说了。。
然后Mass Storage,其实Mass Storage移植,跟FATFS差不多的,我们需要修改mass_mal.c,这个文件就好比FATFS的diskio.c,要在里面实现init、read、write、get_status这几个方法。
官方例程是在eval板上跑的,里面掺杂了很多LED控制之类的,和一般的开发板不能通用。移植过来,第一步,就把LED相关的东西,全换成这样:比如LED1_ON() LED2_OFF()之类,然后用
#define LEDx_ON NOP_PROCESS
这样先把它编译过去,这个灯之类的,以后可以根据不同的开发板,#define成不同的东西,不用去一大堆源代码里面找,比较方便。
platform_config.h里面的东西,只有一个有用,
#define ID1 (0x1FFFF7E8)
#define ID2 (0x1FFFF7EC)
#define ID3 (0x1FFFF7F0)
#define USB_DISCONNECT GPIOA
#define USB_DISCONNECT_PIN GPIO_Pin_8
#define RCC_APB2Periph_GPIO_DISCONNECT RCC_APB2Periph_GPIOA
前三个无所谓,后面三个换成自己开发板上的引脚,其他内容,统统删了,没用。
hw_config.c里面
Set_System()里面一堆东西,无非初始化一下引脚之类。留下这些就行了。
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO_DISCONNECT, ENABLE);
GPIO_InitStructure.GPIO_Pin = USB_DISCONNECT_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(USB_DISCONNECT, &GPIO_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line18);
EXTI_InitStructure.EXTI_Line = EXTI_Line18;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
MAL_Config();
USB_Interrupts_Config()里面有一个东西很坑,就是
NVIC_InitStructure.NVIC_IRQChannel = SD_SDIO_DMA_IRQn;
不知道这个SD_SDIO_DMA_IRQn是哪个中断号,在我的工程里是没有定义的,而且默认的范例工程,这句话是不编译的,把范例工程改成stm32f10x_hd的工程,编译跟踪这个玩意,发现:
#define SD_SDIO_DMA_IRQn DMA2_Channel4_5_IRQn
#define SD_SDIO_DMA_IRQHANDLER DMA2_Channel4_5_IRQHandler
简直令人吐血。。好吧,我对STM32的IRQ还不是很了解。。
直接把它替换成DMA2_Channel4_5_IRQn,并在stm32_it.c里面,把USB中断相关的代码,全复制到自己的工程的stm32f10x_it.c里,把其中一个SD_SDIO_DMA_IRQHANDLER(),换成DMA2_Channel4_5_IRQHandler()
然后还有mass_mal.c,按照编译错误,稍微改改,就编译通过了。于是连上电脑,显示出了一个盘符,而且容量显示为59MB,没有提示要格式化,但是里面是空的,而且点格式化,提示“Windows无法完成格式化”。按理来说,这个工程应该显示出两个盘符,一个SDCARD,一个NAND。现在出现容量显示不正确的情况,怀疑mass_mal.c里面有问题。
想试一下,直接把之前V3.1.1的mass_mal代码复制进来,发现这两个版本,代码相差甚大,很多函数调用都不一样,不好改,于是作罢。
这个mass_mal.c,是官方提供的,版本也是V4.0.0,按理来说应该不会有问题啊。找了很久了毛病,最后,终于发现,问题出在MAL_GetStatus()里面。把相关的#ifdef之类,都给去掉,这样代码会比较清晰,然后看到这一句
Mass_Memory_Size[0] = Mass_Block_Count[0] * Mass_Block_Size[0];
之前V3.1.1的代码,是没有类似的内容的,把它注释掉以后,连上电脑,显示两个盘符,SD卡的盘符工作完全正常,NAND盘显示需要格式化。NAND之前用V3.1.1的时候也是这样,可能因为我并不需要NAND,所以一直也懒得去调它。
把mass_mal.h的MAX_LUN改成0,把usb_prop.c最上面的Max_Lun的定义改成:
uint32_t Max_Lun = MAX_LUN;
这样连接电脑,就只显示一个SD卡的盘符,不显示NAND的了。
官方提供的代码,在MAL_GetStatus()有问题,而且只不过多了一句代码。。实在不明白为何官方的代码经常有这种奇怪的错误。。
然后测试了一下,用128MB的TF卡,和16GB的TF卡,均没有问题,写入速度250K左右,读取速度600K左右,没快,跟之前的差不多。。囧。。也不知道新版的库改进在哪了。。
|