发新帖本帖赏金 100.00元(功能说明)我要提问
返回列表
打印
[STM32F4]

基于F407的硬件移植Free RTOS+FATFS(SDIO)

[复制链接]
17471|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 DVzhang 于 2023-7-6 17:49 编辑

#申请原创# @21小跑堂
因为最近的产品要用到SD卡,以太网所以计划尝试下上Free RTOS,为加快移植流程,采取CUBE  MX直接生成工程的方式;
本文仅作为个人开发过程中的踩坑填坑笔记之用,记录个人的一些调试心得;
各路大佬根据个人情况,求同存异,若有不当之处请多多指教海涵,轻踩。
先上两个链接,这是关于Fatfs和FreeRTOS相关应用函数的说明,不清楚的函数可以在这里面查找:1.FATFS相关操作函数说明
2.FreeRTOS相关操作函数说明
废话不多说,直接上工程创建的图,毕竟后面还有好多坑要说;
一、使用CUBE MX创建基础工程
1、CUBE MX基准时钟设置
因为FreeRTOS要占用系统的滴答定时器,所以单片机的定时器采用TIM2作为基准,不过看了原子哥的例程,没有区分,这里没有深入研究,就按照大众化的方式分开设置,如下图

2、时钟树配置
采用的时钟源是外部25M晶振设置,目前我这边的配置是主频96M,其他外设的频率在48M,没有设置的太高,够用就好;
这里不得不夸一下CUBE MX的一个优势,就是如果频率设置的不合理会报错,之前有遇到有人直接把别人的demo搬过来,导致时钟配置出问题,然后SWD引脚根本不能用,无法在烧录程序的情况;这个时候要么按照分频系数调整外部晶振大小,要么就采用调整BOOT+串口的方式擦除Flash,然后进行烧录;
时钟树配置如下图;

3、SD卡驱动配置
F407支持SDIO,所以硬件采用的是4总线SDIO的方式,相关配置如下图,但是此处生成的代码会有个问题出现,后面细说,先上图
当然为了调试方便,外设还使能了串口2,作为调试时printf的输出串口,此处不在上图;

4、FreeRTOS设置
勾选FreeRtos之后,大多数按照默认设置即可;但是有个参数的定义需要留意,就是堆空间大小设置,这里后面也需要做一定的调整,先看图,后面细说;

5、文件系统Fatfs设置
5.1勾选FATFS,在模式中选择SD卡模式,对应的参数设置,要做一定的调整,可以参考原子哥关于这方面的一些变量设置的解释说明;直接上图

5.2在FATFS下的SDIO设置中,由于使用了Free RTOS,所以只能选择DMA的方式进行数据处理,且DMA的中断等级要低于SDIO的中断等级,但是在中断系统中0-4的优先级被RTOS占用,所以相应的中断等级设置如下图



5.3生成的工程里会有一个SD插入探测脚,此处因为未添加对应IO所以未选,后面可以在程序中做修改

6、生成工程,因为我这边需要比较大的一个栈空间,所以在工程里调整了对应栈大小,各位大佬根据需要,按需调整,不过如果有问题的话,也可以在启动文件中直接修改;

二、掉坑之路
这里要说的是截止到目前为止所遇到的一些问题,有的地方也折腾了一些时间,先做个记录吧,大家求同存异哈!
在说问题之前,先介绍几个FATFS相关的.c文件,了解这几个文件的关系,有助于调试;
1)bsp_driver_sd.c:硬件层驱动文件,调用的是相关的HAL库函数,处理对应的硬件接口;
2)sd_diskio.c:中间层文件,将bsp下的驱动文件进行封装成和FATFS调用的API函数相匹配的接口文件;
3)diskio.c:FATFS系统功能函数直接调用的函数是sd_diskio.c下相应函数的上层映射;
举个例子,当我们挂载磁盘时,一次进入: f_mount ----->find_volume ----->disk_initialize ----->disk.drv[pdrv]->disk_initialize(disk.lun[pdrv]) ----->BSP_SD_Init;
其中第一个 “disk_initialize”是fatfs直接调用的,后面那个是封装有底层初始化的函数,他俩的对应关系是:被ST的库封装到一个结构体中,然后建立映射关系;


接下来说具体遇到的问题吧;
问题1:关于SD卡四总线的设置;
SD卡在刚上电寻卡获取卡参数等一系列的初始化过程中,是采用单总线模式(SDIO_BUS_WIDE_1B)且时钟频率不超过400K的模式下进行的;
ST的大神们也知道这个,所以在初始化的过程中是没有使用我们设置的参数的,如下图

获取到一部分参数之后,库开始用我们设置的参数,初始化对应驱动;这里本没有问题

但是问题在于初始化完成之后,要调用  HAL_SD_ConfigWideBusOperation  设置为4总线,在这个过程中要获取  SD卡 scr下的内容,此时采用4总线的方式获取不到数据,所以会导致最终的初始化失败!!!如下图


解决方法:所以我们要将初始化配置里的总线模式从  SDIO_BUS_WIDE_4B   改为  SDIO_BUS_WIDE_1B,然后后面在使用  HAL_SD_ConfigWideBusOperation 使能设置为4总线时就没有问题了;  

问题2:也是比较重要的问题,使用 fatfs 往SD卡添加文件时,造成栈空间不足;
如下图,在free rtos中创建任务时需要确定以下几个参数:函数入口,函数名,栈空间,传参,优先级等参数;

而我在前期测试过程中喜欢使用  uxTaskGetStackHighWaterMark 函数查看任务所占的 栈空间大小,,只要调用 f_open 创建文档时,返回的剩余栈空间为0,
如下图所示

然后我就理所当然的增加任务栈空间,一开始并不知道需要多大的栈空间,所以直接从 1K字长 怼到 4K字长,然后问题来了,程序根本不会跳转到我这个程序,也就是说任务都没创建起来;经过调试发现,系统在创建任务时 会调用  pvPortMalloc 从设置的堆中分配 任务栈空间;然而上面我们创建任务时默认设置的  configTOTAL_HEAP_SIZE  为 15360=15K字节,然后我设置的是 4K字长=16K字节,所以创建失败;

解决方案:调整任务栈和创建工程时堆的大小

最后还有个插曲,就是最后我确认了需要的SD卡写需要的任务栈大小之后,就把堆给改小了,但是发现运行一段时间之后程序也会飞,后来排查发现因为我还移植了以太网的LWIP,然后剩余的堆空间,不够系统用了;最后还是把堆改大了。
当然整个过程还有很多其他问题,比如我先移植了  freertos  在移植 fatfs 的时候,没注意默认开启了DMA,所以SD这里挂载一直失败,然后调试发现  读写时调用  HAL_SD_ReadBlocks_DMA(写也是一样)一直失败,一开始网上搜资料 也有人说是因为 HAL_SD_TxCpltCallback 在 中断 中被弱定义了,需要补上之类,但是后来发现这一版的 hal 库已经补上了,而实际上是我没有使能 DMA功能造成的
反正大大小小问题不少,但是收获也不少!
致敬伟大的踩坑爬坑工程师们,哈哈哈



使用特权

评论回复

打赏榜单

21小跑堂 打赏了 100.00 元 2023-07-18
理由:恭喜通过原创审核!期待您更多的原创作品~

评论
21小跑堂 2023-7-18 16:17 回复TA
使用OneOS-Cube工具快速实现RTOS OneOS工程,过程详细,并开放搭建视频,良心作者,点赞 
沙发
jobszheng| | 2023-7-18 10:19 | 只看该作者
从文章看下来,使用官方的代码生成工具需要的技术门槛仍然不低啊~~

使用特权

评论回复
评论
21小跑堂 2023-7-18 16:18 回复TA
期待大佬的文章~~ 
板凳
MessageRing| | 2023-7-18 23:23 | 只看该作者
jobszheng 发表于 2023-7-18 10:19
从文章看下来,使用官方的代码生成工具需要的技术门槛仍然不低啊~~

这个生成工具已经把门槛降的很低了

使用特权

评论回复
地板
li880wert| | 2023-7-24 14:13 | 只看该作者
本帖最后由 li880wert 于 2023-7-24 14:15 编辑

外设都是用的STD 标准库,HAL库用了几次,我这WIN732位 I3的CPU 编译一次要10分钟,新版本的 CUBE也不支持32位系统了,直接放弃了。

使用特权

评论回复
发新帖 本帖赏金 100.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

30

主题

280

帖子

5

粉丝