STM32F4-usb_slave u盘

使用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

这下面有这么几个文件STM32F4-usb_slave u盘_第1张图片

从名字可以看出来,分别是几个不同模块的驱动方式,我们这里选择的是SDIO_SD模式,(注意区分F4的库和F1的库)
基本上添加到工程里面,然后调用sd_init 函数初始化之后,就可以用read write进行操作了

2,下载usb device驱动,添加usb文件到工程
usb驱动可以去ST官网是下载,只需要下载device模式的就可以了
我这里没有下载官网的,使用的是野火的例子,然后修改的,代码我已经上传到github了,

[email protected]:writeing/STM32_F4_USB_SD.git

下载完成之后,对应的添加到工程目录下,这一步就算做完了
STM32F4-usb_slave u盘_第2张图片

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驱动走到哪一步,出了什么错误

  1. STORAGE_Init 函数就是初始化,在插入USB口之后,会触发中断,然后调用这个函数,进行SD卡的 初始化
  2. STORAGE_GetCapacity 这个函数就是返回SD卡的大小和每一块的大小,那个结构体的填充是在SD卡的初始化函数里面实现的errorstatus = SD_GetCardInfo(&SDCardInfo); 这里的值可以随便写。比如把block_num写成10G,在电脑显示的时候,就是10G,
  3. STORAGE_Read 调用的是SD卡的读函数,我这里使用的是野火封装好的一个函数,3.5库自带的是没有这个函数的,得自己封装
  4. STORAGE_Write 这个函数一样,写函数
  5. STORAGE_GetMaxLun 这个函数是返回,有多少个SD卡,也就是在电脑上显示几个盘符,好像这个驱动就支持2个,也就是lun最大也就是2

3,添加延时函数
在usb_bsp.c下面,有两个延时函数,一个是us级的,一个是ms级的。最好的办法是使用sys进行延时。记得实现就好

这几个实现完了之后,基本上就移植成功了,下载程序,然后插上usb,基本上就能识别了

下面是移植的时候遇到的几个问题:
1。usb驱动未知(设备描述符无效)
这种情况,有两种可能,一个是设备驱动需要更新,一个是内部的中断程序没有正确相应,

  1. 更新usb驱动,如果更新之后还是无法识别
  2. 这种情况就是usb设备驱动没有正确被调用与SD卡无关,首先应该是单步更新检查中断调用函数,我发生过两次,一次是延时函数没弄好,导致死机了,一次是usb文件没有移植完成,弄错库了,,,,意思就是说,只要调用初始化函数,基本上就会识别出来,

2,设备识别出来了,但是没有读取到SD卡,
这种情况只有一个,那就是sd卡的驱动出了问题
我遇到一个很神奇的事情,就是3.5的库直接调用读写很正常,但是用usb读写就是不行,后来换成了野火的例子,就是好的了, 也分析过,太复杂了,没有找到原因,

其他的一些宏,自己去琢磨,也没啥好说的,
设备读写缓存设置的宏在usb_conf.h里面
设备工作模式选择的宏在sd卡的头文件里面,有DMA和POLL两种

你可能感兴趣的:(STM32)