rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加

目录

一、SD基础知识

1.1、SD卡分类

1.2、SD卡的物理结构 ​

1.3、SD卡寄存器

1.4、SDIO协议简介

二、SD卡驱动

2.1、CubeMX配置

2.2、ENV配置

2.3、驱动测试


一、SD基础知识

1.1、SD卡分类

rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加_第1张图片

STM32F4里,只支持SD 2.0协议,SD和SDHC属于这个范畴,SDXC是4.0协议,所以不支持;另外SDHC卡,有些数据块大小是512,有的是1024,STM32F4只支持读取512大小的,意思是说,SDHC卡的一部分也不支持的。其他相关的技术,可以去SD卡协会网站查看

1.2、SD卡的物理结构 rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加_第2张图片

SD卡一般支持SDIOSPI两种接口,STM32F429x 系列控制器的SDIO是不支持SPI 通信模式的,如果需要用到SPI 通信只能使用SPI 外设。SDIO 不管是从主机控制器向SD 卡传输,还是SD 卡向主机控制器传输都只以CLK 时钟线的上升沿为有效。SD 卡操作过程会使用两种不同频率的时钟同步数据,一个是识别卡阶段时钟频率FOD,最高为400kHz,另外一个是数据传输模式下时钟频率FPP,默认最高为25MHz,如果通过相关寄存器配置使SDIO 工作在高速模式,此时数据传输模式最高频率为50MHz

1.3、SD卡寄存器

rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加_第3张图片 rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加_第4张图片

1.4、SDIO协议简介

rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加_第5张图片

原本SD协议是用在存储上的,后来扩展了一个叫SDIO的协议(全名:Secure Digital Input and Output),这个协议属于外设接口,使得它能连接一些外设,例如:GPS、相机、Wi-Fi、调频广播、以太网、条形码读卡器、蓝牙等,从此跳出存储这个局限

MMC 卡可以说是SD 卡的前身,现阶段已经用得很少

SD I/O 卡本身不是用于存储的卡,它是指利用SDIO 传输协议的一种外设

二、SD卡驱动

为了能满足不同SDIO设备的驱动,比如 SD I/O设备的驱动、SD Card的驱动、MMC的驱动,rtthread提供了SDIO的设备驱动框架,路径为 \rt-thread\components\drivers\sdio,对上通过I/O设备管理层给应用程序提供标准的API接口,对下通过 \libraries\HAL_Drivers\drv_sdio.c/h 驱动完成对STM32 SDIO外设的配置及读写操作,在drv_sdio.c中并没有使用STM32提供的HAL库驱动,而是直接操作的寄存器,但是会调用CubeMX配置生成的SDIO时钟配置及引脚初始化函数 HAL_SD_MspInit,所以在添加SDIO驱动前,需要先通过CubeMX配置SDIO生成HAL_SD_MspInit函数。

2.1、CubeMX配置

rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加_第6张图片

2.2、ENV配置

1、硬件驱动使能

/*添加 BSP_USING_SDCARD 宏*/
--->Hardware Drivers Config
    ---> Onboard Periperal Drivers
        ---> Enable SDCARD (sdio)
/*添加 BSP_USING_SDIO宏*/
--->Hardware Drivers Config
    ---> On-chip Periperal Drivers
        ---> Enable SDIO  
/*配置 SDIO设备驱动框架 如下图*/
--->RT-Thread Components Configuration
    ---> Device Drivers
        ---> Using SD/MMC device drivers   

rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加_第7张图片

2、文件系统配置

SD卡一般需要文件系统的支持,有了文件系统的加持,SD卡操作才能更加灵活方便。由于我前面已经在SPI FLASH上创建了一个elm-FAT并且挂载到了 根目录(/)下,如果要再添加一个文件系统,需要先开启 RomFS文件系统,在根目录下创建2个文件夹,然后再将SPI FLASH和SD卡挂载到这两个文件夹下,因为同一个目录下不能同时挂载2个文件系统!!所以需要在menuconfig中修改 “挂载的文件系统数量”、“支持的文件系统类型数量”,系统中使用了dev、RomFS、elm-FAT3种文件系统, 分别为dev + RomFS + SPI FLASH elm-FAT + SD卡 elm-FAT 共4个

rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加_第8张图片

 elm-FAT文件系统配置

rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加_第9张图片

配置的扇区大小会用于配置FatFs的_MAX_SS,FatFs中_MIN_SS定义最小扇区大小,_MAX_SS定义最大扇区大小。都设置为512可以兼容所有SD卡和硬盘,但是在SPI FLASH上需要更大值。当_MAX_SS > _MIN_SS,FatFs被配置为扇区大小可变的并且必须在函数disk_ioctl中实现GET_SECTOR_SIZE命令。也就是在操作SPI FLSH时扇区大小为4096,而在操作SD卡时会为512

 3、注册具体的文件系统到DFS中

1、devfs_init() ---> dfs_register(&_device_fs) /* 如果开启了RT_USING_DFS_DEVFS,则会在dfs_init中完成自动初始化*/
2、elm_init()/dfs_elm.c --> dfs_register(&dfs_elm) /* 初始化elm文件系统 ,已INIT_COMPONENT_EXPORT自动添加,不在需要手动调用*/
3、dfs_romfs_init()/dfs_romfs.c --> dfs_register(&_romfs) /* 初始化romfs文件系统,已INIT_COMPONENT_EXPORT自动添加,不在需要手动调用 */

rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加_第10张图片

4、块设备挂载

挂载是指将一个存储设备挂接到一个已存在的路径上。我们要访问存储设备中的文件,必须将文件所在的分区挂载到一个已存在的路径上,然后通过这个路径来访问存储设备。这里分别将W25Q12864的"fs"分区挂载到 /w25q 目录下、SD卡挂载到 /sdcard目录下

#if defined(BSP_USING_SPI_FLASH)
static int rt_hw_spi_flash_init(void)
{
    __HAL_RCC_GPIOG_CLK_ENABLE();
    rt_soft_spi_device_attach("softspi1", "softspi10", GPIOG, GPIO_PIN_10);

    if (RT_NULL == rt_sfud_flash_probe("W25Q64", "softspi10"))
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
#endif

#if defined(PKG_USING_FAL)
int fs_init(void)
{
    /* partition initialized */
    fal_init();
	return 0;
}
INIT_COMPONENT_EXPORT(fs_init);
#endif

#if defined(RT_USING_DFS_ELMFAT)
#define FS_PARTITION_NAME "fs"
extern const struct romfs_dirent romfs_root;
int elm_fatfs_init(void)
{
    /* partition initialized */
//    elm_init();
	//dfs_mkfs("elm", "fs"); /* 在fs块设备上创建elm文件系统*/
  
	/* Create a block device on the "fs" partition of spi flash */
    struct rt_device *flash_dev = fal_blk_device_create(FS_PARTITION_NAME);
    if (flash_dev == NULL) {
        LOG_D("Can't create a block device on '%s' partition", FS_PARTITION_NAME);
    } else {
        LOG_I("Create a block device on the %s partition of flash successful", FS_PARTITION_NAME);
    }
	
#if defined(RT_USING_DFS_ROMFS)
	/* mount ROMFS as root directory */
	if (dfs_mount(RT_NULL, "/", "rom", 0,  &(romfs_root)) == 0) {
		LOG_I("ROMFS filesystem initialized!");
	} else {
		LOG_D("ROMFS filesystem initialized Failed!");
	}

	/* mount elm file system from "fs" partition of spi flash to /w25q. */
	if (dfs_mount(FS_PARTITION_NAME, "/w25q", "elm", 0, 0) == 0){
	   LOG_I("FATFS filesystem initialized!");
	} else {
	   LOG_E("Failed to initialize FATFS filesystem!");
	   LOG_D("You should create a filesystem on the block device first!");
	}
#elif 
	/* mount elm file system from "fs" partition of spi flash to / */
   if (dfs_mount(FS_PARTITION_NAME, "/", "elm", 0, 0) == 0) {
       LOG_I("FATFS filesystem initialized!");
   } else {
       LOG_E("Failed to initialize filesystem!");
       LOG_D("You should create a filesystem on the block device first!");
   }
#endif //RT_USING_DFS_ROMFS
	
	return 0;
}
INIT_COMPONENT_EXPORT(elm_fatfs_init);
#endif

void sd_mount(void *parameter)
{
    while (1)
    {
        rt_thread_mdelay(500);
        if(rt_device_find("sd0") != RT_NULL)
        {
            if (dfs_mount("sd0", "/sdcard", "elm", 0, 0) == RT_EOK)
            {
                LOG_I("sd card mount to '/sdcard'");
                break;
            }
            else
            {
                LOG_W("sd card mount to '/sdcard' failed!");
            }
        }
    }
}

 /w25q目录和/sdcard在挂载RomFS的时候会被自动创建

rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加_第11张图片

2.3、驱动测试

测试SD卡的读写速度

 rt-thread驱动篇(07)---STM32F429单片机SD卡驱动添加_第12张图片

你可能感兴趣的:(RT-Thread,单片机,stm32,嵌入式硬件)