使用stm32F4的HSUSB移植一个usb和sd卡组合当做U盘使用的操作
想要做到这个功能,大致如下几个步骤
1,SDIO/SPI 驱动 SD卡,具体的驱动可以使用keil提供的eval库
2,下载usb device驱动,我们这里使用的是被动模式,slave
3,添加usb文件到工程
4,修改添加usb底层驱动代码
其实,移植usb驱动相对来说比较简单,只需要知道什么是移植。usb驱动是干嘛用的,大致了解它的工作顺序就可以了,这里只做简单的简绍移植步骤,具体的usb配置这里不说(其实我也没有搞透)
1,SDIO/SPI 驱动 SD卡
驱动SD卡,SD卡的接口我知道的有两种,一种是SDIO接口,一种是SPI接口的,不过无论哪种接口,都不影响,因为底层代码已经有一个现成的库写好了。
EVAL库是由3.5的标准库提供的,在目录
STM32 3.5固件库官网原文件\STM32F10x_StdPeriph_Lib_V3.5.0\Utilities\STM32_EVAL\Common
从名字可以看出来,分别是几个不同模块的驱动方式,我们这里选择的是SDIO_SD模式,(注意区分F4的库和F1的库)
基本上添加到工程里面,然后调用sd_init 函数初始化之后,就可以用read write进行操作了
2,下载usb device驱动,添加usb文件到工程
usb驱动可以去ST官网是下载,只需要下载device模式的就可以了
我这里没有下载官网的,使用的是野火的例子,然后修改的,代码我已经上传到github了,
[email protected]:writeing/STM32_F4_USB_SD.git
usb_otg:是usb设备的公共驱动文件,里面主要包含的就是中断的索引,比如usb插进去的时候中断工作,比如usb拔除的时候,等等
usb_device:是usb slave模式下的驱动文件
usb_APP:是我们需要修改的文件,下面只有四个。分别是bsp,desc,msd。usr ,sd_bsp是我的sd卡的驱动文件
4,修改添加usb底层驱动代码
这一步是最重要的。也是最麻烦的,
下面想说基本的移植步骤,具体修改那些,后面再说
1,在主函数里面调用初始化函数
USB_OTG_CORE_HANDLE USB_OTG_dev;
USBD_Init(&USB_OTG_dev,USB_OTG_FS_CORE_ID,&USR_desc,&USBD_MSC_cb,&USR_cb);
调用初始化函数之后,事件就会注册到中断上,当USB进行相应的操作的时候就会触发中断,然后调用底层函数
2,填充usbd_storage_msd.c文件下的init。read等函数
int8_t STORAGE_Init (uint8_t lun)
{
#ifdef USB_SD_BSP
#undef USB_SD_BSP
USB_SD_Init();
#endif
return 0;
}
int8_t STORAGE_GetCapacity (uint8_t lun, uint32_t *block_num, uint32_t *block_size)
{
#ifndef USB_SD_BSP
*block_size=512;
*block_num=SDCardInfo.CardCapacity/512;
#endif
return 0;
}
int8_t STORAGE_IsReady (uint8_t lun)
{
USB_STATUS_REG|=0X10;
return 0;
}
int8_t STORAGE_IsWriteProtected (uint8_t lun)
{
return 0;
}
int8_t STORAGE_Read (uint8_t lun,uint8_t *buf,uint32_t blk_addr,uint16_t blk_len)
{
int8_t res=0;
USB_STATUS_REG|=0X02;
#ifndef USB_SD_BSP
res=SD_ReadDisk(buf,blk_addr,blk_len);
#endif
if(res)USB_STATUS_REG|=0X08;
return res;
}
int8_t STORAGE_Write (uint8_t lun,uint8_t *buf,uint32_t blk_addr,uint16_t blk_len)
{
int8_t res=0;
USB_STATUS_REG|=0X01;
#ifndef USB_SD_BSP
res=SD_WriteDisk(buf,blk_addr,blk_len);
#endif
if(res)USB_STATUS_REG|=0X04;
return res;
}
int8_t STORAGE_GetMaxLun (void)
{
return (STORAGE_LUN_NBR - 1);
}
这里野火添加了一些标志了,用来判断USB驱动走到哪一步,出了什么错误
3,添加延时函数
在usb_bsp.c下面,有两个延时函数,一个是us级的,一个是ms级的。最好的办法是使用sys进行延时。记得实现就好
这几个实现完了之后,基本上就移植成功了,下载程序,然后插上usb,基本上就能识别了
下面是移植的时候遇到的几个问题:
1。usb驱动未知(设备描述符无效)
这种情况,有两种可能,一个是设备驱动需要更新,一个是内部的中断程序没有正确相应,
2,设备识别出来了,但是没有读取到SD卡,
这种情况只有一个,那就是sd卡的驱动出了问题
我遇到一个很神奇的事情,就是3.5的库直接调用读写很正常,但是用usb读写就是不行,后来换成了野火的例子,就是好的了, 也分析过,太复杂了,没有找到原因,
其他的一些宏,自己去琢磨,也没啥好说的,
设备读写缓存设置的宏在usb_conf.h里面
设备工作模式选择的宏在sd卡的头文件里面,有DMA和POLL两种