[开发工具]如何使用 F4A0 RT-Thread bsp 驱动 sd/tf 卡文件系统?

    由于MCU本身的FLASH容量有限,而在本项目中需要存储大量的电能数据,此时则要使用外部的存储器,同时考虑到成本以及方便在其他设备上使用,microSD卡成为常用外部存储器,它具有体积小、易使用、容量大的优点,同时现有的配套软件和硬件非常齐全,能够达到开箱即用的效果。为了管理大容量的SD卡设备,还需要一个文件系统,好在RT-Thread已经为我们提供了一套完善的文件系统机制,称为Device Virtual File System(即设备虚拟文件系统),提供POSIX标准的文件操作功能(open,write,read等),完全可以使用与PC端基本一致的API调用进行文件的读写等操作。microSD卡和文件系统之间需要的驱动程序(elm-FatFs和MSD)也由RT-Thread提供了,我们几乎不需要编写代码就能够在MCU的嵌入式系统上,读写SD卡上的文件了,省去学习和调试代码的大量时间。本文将介绍在 F4A0 平台上,基于 RT-Thread bsp 框架实现使用 spi 接口对外部 SD/TF 卡的操作。
  • IDE :Keil MDK 5.2X
  • 硬件平台 :EV_HC32F4A0_LQFP176_Rev1.0 开发板和 16G 的 TF 卡
  • Env tool :env_released_x_x_x
  • 调试工具 :USB 串口线和逻辑分析仪



基础工程
    本项目工程之前是基于 RT-Thread v4.0.4 版本上开发的,所以得克隆下对应版本,链接为: https://gitee.com/rtthread/rt-thread/tree/v4.0.4 。至于如何搭建 env 环境和构建基础的 F4A0 rt-thread bsp 的 MDK 工程,在此忽略,可参考上篇介绍的流程进行处理: https://bbs.21ic.com/icview-3320018-1-1.html 。
配置工程
    得到基础工程后,需要在 menuconfig 环境下完成所需功能的配置。

  • RT-Thread Components -> Device virtual file system 开启文件系统,并启用 Enable elm-chan fatfs 开启 elm-fatfs 文件系统

  • Hardware Drivers Config -> On-chip Peripheral Drivers -> SPI Drivers  开启spi1

  • RT-Thread Components -> Device Drivers -> Using SPI Bus/Device device drivers开启SPI设备驱动,并启用Using SD/TF card driver with spi选项开启spi协议的sd卡驱动支持,由于文件系统中还会需要 RTC 的支持,暂时使用软件模拟 RTC 来适配该功能,启用 Using RTC device drivers 选项和启用 Using software simulation RTC device 选项来开启 RTC 功能


    到此,已经完成了所需驱动的所有配置。接下来就可以重新生成对应的 Keil 工程了,使用命令 : scons --target=mdk5 -s ,生成的工程文件为根目录下的 project.uvprojx 。

修改配置代码
    由于 bsp 中未使能 spi 对应引脚的配置功能,所以需要根据硬件原理图完成更改,开发板上的连线方式是 SDIO 接口的,实际上也可以直接换成 SPI 接口的,而且加上 F4A0 具备通信端口可自由映射的超级方便的功能,这样可以直接在原 demo 板上实现一个 TF 卡既可以用 SDIO 驱动又可以用 SPI 模式驱动。根据原理图可以得到对应的通信引脚功能配置如下:

  • PB05   -  SPI1_NSS       3线制软cs
  • PD02  -   SPI1_MOSI    FUNC41
  • PC12  -   SPI1_SCK       FUNC40
  • PB07  -  SPI1_MISO     FUNC42


    相应需要更改的 board_config.h 代码如下:

复制
#if defined(BSP_USING_SPI1)

#define SPI1_NSS_PORT                   (GPIO_PORT_B)

#define SPI1_NSS_PIN                    (GPIO_PIN_05)

#define SPI1_NSS_GPIO_FUNC              (GPIO_FUNC_0_GPO)



#define SPI1_SCK_PORT                   (GPIO_PORT_C)

#define SPI1_SCK_PIN                    (GPIO_PIN_12)

#define SPI1_SCK_GPIO_FUNC              (GPIO_FUNC_40_SPI1_SCK)



#define SPI1_MOSI_PORT                  (GPIO_PORT_D)

#define SPI1_MOSI_PIN                   (GPIO_PIN_02)

#define SPI1_MOSI_GPIO_FUNC             (GPIO_FUNC_41_SPI1_MOSI)



#define SPI1_MISO_PORT                  (GPIO_PORT_B)

#define SPI1_MISO_PIN                   (GPIO_PIN_07)

#define SPI1_MISO_GPIO_FUNC             (GPIO_FUNC_42_SPI1_MISO)

#endif

    接着创建 spi_tfcard.c 应用代码层源文件,主要是在整个 component 初始化时触发调用 spi msd 驱动设备的初始化,详细见下面代码:

复制
void sd_mount(void *parameter)

{

    while (1)

    {

        rt_thread_mdelay(500);

        if(rt_device_find("sd0") != RT_NULL)

        {

            if (dfs_mount("sd0", "/", "elm", 0, 0) == RT_EOK)

            {

                LOG_I("sd card mount to '/'");

                break;

            }

            else

            {

                LOG_W("sd card mount to '/' failed!");

            }

        }

    }

}



int hc32_sdcard_mount(void)

{

    rt_thread_t tid;



    tid = rt_thread_create("sd_mount", sd_mount, RT_NULL,

                           1024, RT_THREAD_PRIORITY_MAX - 2, 20);

    if (tid != RT_NULL)

    {

        rt_thread_startup(tid);

    }

    else

    {

        LOG_E("create sd_mount thread err!");

    }

    return RT_EOK;

}

INIT_APP_EXPORT(hc32_sdcard_mount);



static int rt_hw_spi1_tfcard(void)

{

    hc32_hw_spi_device_attach("spi1", "spi10", SPI1_NSS_PORT, SPI1_NSS_PIN);

    LOG_I("hw_spi_device_attach ok!\r\n");

    return msd_init("sd0", "spi10");

}

INIT_DEVICE_EXPORT(rt_hw_spi1_tfcard);

    似乎到这里基本就完成了所有代码的编辑了。好,现在是踩坑时刻,编译运行起来后串口输出没有正确 mount 的信息,得一步步 debug 了。
    首先一个坑,msd_init 函数调用后一直无法正确触发回调到底层配置 hc32_spi_configure 函数里面来,导致 spi1 初始化未能正确完成。经过一番挣扎,终于发现到问题点:之前用的是  INIT_COMPONENT_EXPORT(rt_hw_spi1_tfcard); 需要改成  INIT_DEVICE_EXPORT(rt_hw_spi1_tfcard);   至于为什么,那要好好研究 rt-thread 了,在此不作过多讨论。
    第二个坑,使用逻辑分析仪抓波形,发现 cs 引脚电平一直不变而其它引脚上有波形了。很明显这是 IO 配置的问题,一下子就定位到了问题点:需要在 board_config.c  的 hc32_board_spi_init 初始化函数中添加以下代码使能输出作用并且初始化拉高 cs:

复制
GPIO_OE(SPI1_NSS_PORT, SPI1_NSS_PIN, Enable);

GPIO_SetPins(SPI1_NSS_PORT, SPI1_NSS_PIN);

    到这里填完坑后,才真正可以实现所需要的功能了。

测试验证
    编译代码并下载成功后,飞线将 PH15/PH13 连接到板载 CMSIS-Dap 端的 RX/TX 即可使用调试器枚举出的虚拟串口,开启串口工具以及抓取对应的 SPI1 波形,正常会显示如下:
 

 


    另外,不再多写一句代码都可以进行测试读写 TF 卡,那就是在 msh 中使用命令实现,因为文件系统中已经自带了该功能。大致命令流程梳理如下:

  • 输入list device命令并回车,可以查看设备,[size=1em]这里sd0为分区,后续会对他进行操作
  • [size=1em]使用 date 命令进行时间的设置和查询,让文件系统具备时钟功能
  • 初次使用的SD卡,可能没有文件系统,或者文件系统不是FAT格式的,需要使用 mkfs 命令将SD卡格式化为FAT文件系统,后续才能挂载成功
  • 使用 ls、echo、cat 命令,进行文件读写操作,使用 cd、mkdir、pwd 等命令,进行文件目录的操作
     

    当然也可以使用文件系统的 api 接口来实现文件的读写操作,这里也不做过多探讨了,因为底层都已经通了,后面可以随便造了。

---------------------
作者:yang377156216
链接:https://bbs.21ic.com/icview-3324120-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值