RT-Thread GD32F4xx实现SD卡热插拔检测功能

GD32F470移植RT-Thread操作系统添加SD卡功能,增加SD卡热插拔检测

    • 一、RT-Thread移植sd卡功能
    • 二、实现SD卡热插拔检测原理
    • 三、软件实现过程
    • 四、延展之ASSERT ERROR,即RT-Thread断言错误
    • 五、延展之STM32 SD卡热插拔检测
    • 六、结束语

一、RT-Thread移植sd卡功能

RT-Thread官方下载gd32f470的源代码,根据自己的情况裁剪一下无关的文件,配置好工程,打开env配置工具,使能SDIO,使能DFS虚拟文件系统,使能elm-chan fatfs文件系统,将注册的sd0块设备以elm fatfs形式注册到DFS虚拟文件系统中。文件系统需要用到RTC,在env中使能RTC功能,配置一下系统时间。
env配置如下图:
在这里插入图片描述
env配置完之后,打开keil编译工程,下载到板子里,用console查看sd设备是否挂载成功(默认sd0,块设备),如下图挂载成功:
在这里插入图片描述
当设备列表中有sd0块设备时表明sd卡注册成功了,此时在应用层调用dfs_mount挂载sd0,然后就可以使用文件系统了。
SD卡的流程大概就这样,这里不做详细描述了。RT-Thread官方下载的源代码工程裁剪以及env工具配置使用等可以参考我另一篇博文。工程裁剪及env配置

二、实现SD卡热插拔检测原理

添加好sd卡驱动后,挂载sd0块设备后就能用文件系统操作了。刚开始调试好时,测试发现如果上电前未插入sd卡,系统会直接死机;另外在sd卡挂载成功后,中途拔卡也会出现系统故障;如果支持热插拔会好很多,提升用卡体验感。但是gd32f470的sd驱动中不包含卡的热插拔功能,需要自己实现。
实现方式为:
通过检测SD卡的check pin脚的电平边沿变化来检测SD卡时候插入和拔出,当插入SD卡的时候,该脚变为低电平,当拔掉SD卡的时候,该脚变为高电平。
不过该方式有一定的局限性,因为有些板子的check pin是悬空的,并没有接在mcu的任何脚上,这种情况下,使用上面所述的方法进行热插拔检测就不可行了,比方说,野火的F429挑战者开发板,它的SD卡的check pin就是悬空的,如图:
在这里插入图片描述
不过我所用的板子,checkpin脚是有接到mcu的管脚上的,如下图:
在这里插入图片描述
所以只需在sd卡应用代码里增加这个管脚的信号检测就可以实现sd卡的热插拔功能了!

三、软件实现过程

1、定义热插拔检测管脚

/* SD Card hot plug detection pin */
#define SD_CHECK_PIN        GET_PIN(A, 15)

2、创建sd卡挂载线程,sd卡挂载线程代码如下:

static void sd_mount(void *parameter)
{rt_uint8_t re_sd_check_pin = 1;while (1){rt_thread_mdelay(200);if(re_sd_check_pin && (re_sd_check_pin = rt_pin_read(SD_CHECK_PIN)) == 0){if (_sdcard_mount() == RT_EOK){LOG_I("sd mount ok!");rt_event_send(&sd_mount_event, eEVENT_SD_MOUNT);}}if (!re_sd_check_pin && (re_sd_check_pin = rt_pin_read(SD_CHECK_PIN)) != 0){if (_sdcard_unmount() == RT_EOK){LOG_I("sd unmount ok!");rt_event_send(&sd_mount_event, eEVENT_SD_UNMOUNT);}}}
}

该线程只是检测SD卡插拔的状态。
“re_sd_check_pin = 1"的作用是为了让SD卡在未上电的时候已经插进去了这种情况下制造电平边沿用的。因为如果SD卡一直插着,是没有电平变化的。“re_sd_check_pin = 1"就是为了手动制造一个电平变化出来。否则无法通过if语言的电平边沿检测,也就是说无法执行”_sdcard_mount()”。需要注意的是,这段代码中的两个if语句之后都会跟着一个"re_sd_check = rt_pin_read(SD_CHECK_PIN)"去记录上次的的电平值。

在上电后拔卡时,检测SD_CHECK_PIN管脚为高电平,此时第二个if条件成立,执行"_sdcard_unmount()",卸载完sd卡后我加了一个卸载事件发送,告知sd卡应用线程,此时sd卡已拔出,关闭所有对sd卡的操作。

在上电后插卡时,检测SD_CHECK_PIN管脚为高电平,此时第一个if条件成立,执行"_sdcard_mount()",挂载完sd卡后我加了一个挂载事件发送,告知sd卡应用线程,此时sd卡已插入,可以对sd卡进行操作。

3、SD卡挂载函数_sdcard_mount()代码如下:

static rt_int32_t _sdcard_mount(void)
{rt_device_t device;device = rt_device_find("sd0");if (device == RT_NULL){if (sd_device_register() != RT_EOK) return -RT_ERROR;device = rt_device_find("sd0");}if (device != RT_NULL){if (dfs_mount("sd0", "/", "elm", 0, 0) == RT_EOK){LOG_I("sd card mount to '/'");return RT_EOK;}else{LOG_W("sd card mount to '/' failed!");return -RT_ERROR;}}return -RT_ERROR;
}

这里主要就是sd卡的挂载,当发现sd0设备找不到的时候,执行sd_device_register()注册设备,注册完之后find sd0设备,然后mount该sd0设备到dfs虚拟文件系统中。

4、SD卡卸载函数_sdcard_unmount()代码如下:

static rt_int32_t _sdcard_unmount(void)
{rt_thread_mdelay(200);if (dfs_unmount("/") != RT_EOK) return -RT_ERROR;LOG_I("Unmount \"/\"");if (sd_device_remove() != RT_EOK) return -RT_ERROR;return RT_EOK;
}

这里主要就是sd卡的卸载,先卸载文件系统,再移除sd0设备。

5、sd_device_register()

rt_err_t sd_device_register(void)
{rt_hw_sdcard_init();return RT_EOK;
}

sd设备驱动就是调用rt_hw_sdcard_init()进行初始化的,检测到重新插卡后就再次初始化一下sd卡。

6、sd_device_remove()

rt_err_t sd_device_remove(void)
{rt_sem_detach(&sd.sem);rt_mutex_detach(&sd.sd_lock);rt_device_unregister(&sd.sdcard_device);return RT_EOK;
}

当时调试的时候,这里导致了一个ASSERT错误,查了一天才找到原因。。。
这里需要分离semaphore和mutex,然后unregister设备。一开始我没有直接分离semaphore和mutex,导致拔卡之后再插卡就提示ASSERT错误,然后系统奔溃。
为啥是分离semaphore和mutex而不是删除,因为在rt_hw_sdcard_init()里面初始化了静态的semaphore和mutex。如果是创建的动态semaphore和mutex,则是执行删除,然后rt_free内存,否则也是会运行出错。

7、运行效果如下
在这里插入图片描述

四、延展之ASSERT ERROR,即RT-Thread断言错误

在这次调试中,有遇到ASSERT错误,导致系统直接死机。即我前面说到的未删除原来初始化的信号量及互斥量,再次初始化时导致ASSERT错误。
当时错误的提示:
在这里插入图片描述
RT-Thread系统还挺好用的,直接把错误给打印出来了,而且还很详细。首先obj != object是断言的内容,在rt_object_init函数里面断言出错的,而且告知了是在383行!我理解的就是:初始化object的时候,系统检测初始化的object和obj列表中的一致,意思是已经初始化了、已经存在该对象信息。
查看代码找到ASSERT错误的地方:
在这里插入图片描述

常见RT-Thread ASSERT错误原因:
1、使用的对象未创建或初始化,如:事件、信号量、消息队列等等。
2、对象还未初始化,在别的线程调用了,如:rt_sem_take等等。
3、初始化函数使用错误,init是静态初始化,先定义好控制块存储地址;create是动态初始化,由动态内存分配,create返回的是控制块的句柄,即指针。
4、RT-Thread默认只需要init一次内核对象,第二次默认不初始化。对未删除或分离的对象,再次初始化也会导致assert错误。

五、延展之STM32 SD卡热插拔检测

最初是使用ST的bsp库来开发sd卡功能的,但是发现在sd卡初始化的时候,读取scr寄存器一直没响应,导致sd卡初始化失败。随后在网上找到一种解决办法:

在这里插入图片描述
在rthw_sdio_send_command()里,去掉接收等待。
在cmd51发送完之后,hw_sdio->sta的值为0x20a400,与上HW_SDIO_IT_RXACT为真,导致超时,此时判断始终返回错误。注释掉cm->err = -RT_ERROR后,挂载成功,可以读写sd卡文件。目前尝试二十几次,均正常。现在始终不明白是读寄存器错误还是其他原因。 同样的程序在st下运行,sta返回值是0x400。

但是我调试发现偶尔有那么一两次能成功,但是概率很低,几乎99.9%初始化失败。对比找了两个芯片的驱动差异,没找到具体原因。。。最后无奈用gd32f470的bsp工程来调试sd卡,发现env配置好下载到板子里就能挂载sd设备!

用STM32的芯片驱动实现SD卡热插拔功能,原理一样,只是驱动库不一样,其实就是_sdcard_mount()和_sdcard_unmount()不一样,具体看代码:

1、_sdcard_mount()

static void _sdcard_mount(void)
{rt_device_t device;device = rt_device_find("sd0");if (device == NULL){mmcsd_wait_cd_changed(0);stm32_mmcsd_change();mmcsd_wait_cd_changed(RT_WAITING_FOREVER);device = rt_device_find("sd0");}if (device != RT_NULL){if (dfs_mount("sd0", "/", "elm", 0, 0) == RT_EOK){LOG_I("sd card mount to '/'");}else{LOG_W("sd card mount to '/' failed!");}}
}

2、_sdcard_unmount()

static void _sdcard_unmount(void)
{rt_thread_mdelay(200);dfs_unmount("/");LOG_I("Unmount \"/\"");mmcsd_wait_cd_changed(0);stm32_mmcsd_change();mmcsd_wait_cd_changed(RT_WAITING_FOREVER);
}

stm32_mmcsd_change()是drv_sdio里面提供的一个接口,该函数实际是调用mmcsd_change()函数,触发mmcsd检测线程,检测线程按流程检测各类卡(SD卡、MMC卡),继续查看源代码可以发现,在init_sd里面有块设备探测失败的情况,该情况下会进入remove card的流程:
在这里插入图片描述

继续查看rt_mmcsd_blk_remove做了什么:
在这里插入图片描述
可以看到这里面起始也是删除当时初始化SD卡时创建的sem,然后unregister设备,再从对象信息列表中移除之前创建的object,最后rt_free该设备块。

六、结束语

最近调试GD32F470的sd卡功能,对RT-Thread操作系统还不是很熟悉,都是不断摸索的过程,特写此博文记录一下。也给正在调试或使用RT-Thread的朋友一点帮助。文中如有描述不对的地方还望提醒纠正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/618190.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最近很火的一款的低代码开发平台

目录 一、JNPF开发平台 二、JNPF界面示意图 三、技术栈展示 技术点: 开发环境 前后端分离 服务无状态 现在,很多公司在数据化的过程中,都需要构建很多相应的内部工具来支持他们的业务发展,比如运营使用的活动后台、用户管理…

红队专题-Golang工具ChYing

Golang工具ChYing 招募六边形战士队员原chying工具代码分析并发访问控制并发 原子 写入读取 通道嵌套映射结构初始化启动代理服务器重启代理服务器 招募六边形战士队员 一起学习 代码审计、安全开发、web攻防、逆向等。。。 私信联系 原chying工具代码分析 前有 Chying 后有…

DAY6--learning english

一、积累 1.sip She took a small sip of the hot tea to savor its delicate flavor. 她小口抿了一口热茶,细细品味其中的淡雅滋味。 2.vacuum Expreience the amazing cleaning power of vaccum cleaner. 体验真空吸尘器惊人的清洁能力。 3.stray Stray kitte…

伴鱼实时数仓建设案例

伴鱼实时数仓建设案例 文章目录 伴鱼实时数仓建设案例伴鱼实时作业应用场景伴鱼实时数仓的建设体系DWD 层复杂场景数据处理方案1. 数据的去重2. join场景两条实时数据流相关联对于关联历史数据 3. 从数据形态观查join DWS 数据层数据处理方案未来与展望 随着伴鱼业务的快速发展…

如何在 Windows 10、11 上恢复删除、未保存或覆盖的 Excel 文件?

我们中的大多数人可能都经历过其中一种情况——关闭电源时未保存 Excel 文件或误点击“不要保存”,不小心删除了重要的 Excel 文件,或覆盖了 Excel 文件而未保存原始副本。在遇到这些情况时,我们都会为没有采取适当的措施而感到内疚&#xff…

计算机毕业设计----Springboot超市订单管理系统

项目介绍 该超市订单管理毕业设计基于jdk8版本开发,在部署时需要使用jdk8以上的版本。使用了目前流行的框架组合springbootmybatis的框架技术, 实现了供应商管理对供应商实现增删改查、订单管理对超市订单实现增删改查、用户管理等功能,适用…

都是取所有行的某列数据,这个array[:,2]和array[:,2:3]有什么不同呢

效果图 代码 import numpy as nplist [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20],[21,22,23,24,25] ] array np.array(list) print(array) 输出: [[ 1 2 3 4 5][ 6 7 8 9 10][11 12 13 14 15][16 17 18 19 20][21 22 23 24 25]]a arr…

【上分日记】第369场周赛(分类讨论 + 数学 + 前缀和)

文章目录 前言正文1.3000. 对角线最长的矩形的面积2.3001. 捕获黑皇后需要的最少移动次数3.3002. 移除后集合的最多元素数3.3003. 执行操作后的最大分割数量 总结尾序 前言 终于考完试了,考了四天,也耽搁了四天,这就赶紧来补这场周赛的题了&a…

【Linux实用篇】项目部署 基于Shell脚本自动部署

目录 1. 项目部署 1.1 手动部署项目 1.2 基于Shell脚本自动部署 1.2.1 介绍 1.2.2 推送代码到远程 1.2.3 Git操作 1.2.4 Maven安装 1.2.5 Shell脚本准备 1.2.6 Linux权限 1.2.7 授权并执行脚本 1.2.8 设置静态IP 1. 项目部署 之前我们讲解Linux操作系统时&#xff0…

Dcoker构建部署Java项目过程

目录 前言 一、打包 二、Docker File文件编写 一个简单的Docker File文件 三、上传文件 四、构建镜像 五、运行 六、端口开放 前言 使用Dcoker构建部署Java项目,发布到服务器 一、打包 我这里打包的是item-service这个module,clean-cpmpile-pa…

uniapp 查找不到uview-ui文件怎么办?

用官方的方式总是报:文件查找失败:uview-ui at main.js 解决方案: 1.先安装uview-ui npm install uview-ui 下载成功是这样的: 而不是这样的: 这样的原因是你的项目里没有package.json包,先执行 npm …

Qt 调试系统输出报警声以及添加资源

文章目录 前言一、方法1 使用 Qsound1.添加都文件 直接报错2.解决这个错误 添加 QT multimedia3. 加入代码又遇到新的错误小结 二、第二种方法1.引入库2.添加资源2.1依次点击Qt--->Qt Resource File--->Choose2.2给资源文件起个名字,如:res&#…

【每日一题】构造限制重复的字符串

文章目录 Tag题目来源解题思路方法一:贪心空间复杂度: O ( ∑ ) O(\sum) O(∑)。 写在最后 Tag 【贪心】【字符串】【2024-01-13】 题目来源 2182. 构造限制重复的字符串 解题思路 方法一:贪心 思路 解题思想比较简单,利用贪…

【MySQL】:掌握SQL中DDL的数据库定义与操作

🎥 屿小夏 : 个人主页 🔥个人专栏 : MySQL从入门到进阶 🌄 莫道桑榆晚,为霞尚满天! 文章目录 📑前言一. SQL的分类二. DDL数据库操作2.1 查询所有数据库2.2 查询当前数据库2.3 创建数…

[足式机器人]Part2 Dr. CAN学习笔记-Advanced控制理论 Ch04-8 状态观测器设计 Linear Observer Design

本文仅供学习使用 本文参考: B站:DR_CAN Dr. CAN学习笔记-Advanced控制理论 Ch04-8 状态观测器设计 Linear Observer Design

虚幻引擎nDisplay教程:如何同步nDisplay节点与Switchboard + Helix Core

对于使用大型LED屏幕进行拍摄的虚拟制作团队来说,虚幻(Unreal)的nDisplay是一个重要的工具。但是,在nDisplay中将正确版本的文件发送到每个节点会非常耗时。立即阅读本文,您将了解到如何使用Perforce Helix Core版本控…

Linux 系统之部署 ZFile 在线网盘服务

一、ZFile 介绍 1)ZFile 简介 官网:https://www.zfile.vip/ GitHub:https://github.com/zfile-dev/zfile ZFile 是一款基于 Java 的在线网盘程序,支持对接 S3、OneDrive、SharePoint、又拍云、本地存储、FTP 等存储源&#xff0…

【Go】excelize库实现excel导入导出封装(三),基于excel模板导出excel

前言 大家好,这里是符华~ 关于excelize库实现excel导入导出封装,我已经写了两篇了,我想要的功能基本已经实现了,现在还差一个模板导出,这篇文章就来讲讲如何实现用模板导出excel。 前两篇: 【Go】excel…

爬虫-5-数据提取-正则,xpath

#免责声明:本文仅供学习,请遵纪守法。 ԅ(ㅂԅ)

Leetcode 剑指 Offer II 061. 查找和最小的 K 对数字

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定两个以升序排列的整数数组 nums1 和 nums2 , 以及一个整数 k…