|
RT-Thread的文件系统基本框架如下:
Device Filesystem,文件系统设备,属于RT-Thread的设备管理
在filesystem\dfs\src下面的文件
------------------------------------------------------------
然后是DFS系统和Fatfs中间的一个转接文件,如下:
filesystem\dfs\filesystems\elmfat\dfs_elm.c
------------------------------------------------------------
然后就是fatfs文件系统。已经不需要移植diskio的相关函数了。
用户自己移植底层驱动的话,关键是添加RT-Thread的设备。
见rt_sd.c文件。
需要重写 rt_sd_read, rt_sd_write, rt_hw_sd_init几个函数。
如何支持时间。
在dfs_elm.c文件中,找到 rt_time_t get_fattime(),范例中直接return 0;
查找fatfs的源代码,可以知道其时间格式为:
/* User defined function to give a current time to fatfs module */
/* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */
/* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
STM32自己支持RTC,我的工程模板里直接有RTC的驱动,做个格式转换即可,因此移植如下:
#include "drv_rtc_time.h"
rt_time_t get_fattime()
{
struct tm time;
time = TimeGetCalendarTime();
time.tm_year -= 1980; // ff文件系统年份起始值1980年
time.tm_sec >>= 1; // 秒除以2, 已符合ff文件系统时间格式要求
return( ((DWORD)time.tm_year << 25) | // 时间格式转换
((DWORD)time.tm_mon << 21) |
((DWORD)time.tm_mday << 16) |
((DWORD)time.tm_hour << 11) |
((DWORD)time.tm_min << 5 ) |
((DWORD)time.tm_sec) );
}
如何支持中文和长文件名。
在ffconf.h中,
#define _CODE_PAGE 936 //使用GBK编码
#define _USE_LFN 2 //支持长文件名,2表示可重入,1不可重入
#define _WORD_ACCESS 0
#define _FS_REENTRANT 0 //此项不太能理解,配置为0是不可重入的,但配为1出现错误。
// 范例代码里也确实是配置为0的,RT_DFS_ELM_REENTRANT这个宏定义从来没有被定义过。
在编译器里加入 cc936.c 文件。
该工程模板提供了SD卡的写入文件,以及读取文件,并测试了读写速度。
通过串口终端,执行结果如下:
Asserted by user
info: File System initialized! // SD卡初始化成功
para: 0
sd test application // 进入SD卡测试线程
sd opened test.bin
sd write 1M byte used 6410 ms // 写入1M的时间用了6.5s,约150Kbyte/s
sd write speed test finished. close test.bin
sd opened test.bin
sd read 1M byte used 5570 ms // 去读1M的时间用了5.5s,约180Kbyte/s
sd read speed test finished. close test.bin
说说官方范例及此驱动的区别。
官方范例的 msd.c 文件就是SD、MMC等卡的SPI模式读写。但是它不支持SDHC卡。msd就是memory sd的意思......
官方范例的 sdcard.c 文件是用SDIO模式读写的,硬件支持的话,用此驱动较好。
此范例中的 drv_sd.c 文件使用SPI模式进行读写的,测试过的卡包括 SanDisk的SDHC, 创建的SD_V2卡, 不知名的卡若干张, 容量最大测试到8GB。
而 rt_sd.c 就是底层驱动和 RT-Thread 设备管理系统的接口文件。
学习RT-Thread一周半,学写驱动两次,关于IO管理模块
RT-Thread的IO设备管理模块的目的:将设备的硬件代码 与 应用层代码 隔离开来。
让软件人员可专注于软件应用开发,驱动人员专注于硬件驱动。让软件人员对设备的操作有一个统一的平台,无需去关注底层硬件驱动的写法。
如果严格一点来说。应用层应该不允许直接调用驱动层的函数,而必须通过IO管理模块的接口进行操作。对标准的操作系统来说,本应如此。。。
但在需求千变万化的嵌入式应用,这一点就较难做到了。
我们有必要把 LED灯、按钮、开关控制信号、SPI通讯、I2C通讯都打包成RT-Thread的设备管理模块吗?
至少LED灯的范例作者自己也没进行打包,I2C通讯有人想打包却比较困难。
我个人观点是,具体应用具体分析。
如果是一个大公司大应用,完全可以充分利用起设备管理模块的优势,一部分人写底层驱动,另外一部分人关注与上层应用。
其好处是写上层应用的人员无需去考虑硬件驱动的写法、实现等技术细节。
如果是小公司小应用,一个项目就一二个软件人员的,驱动也自己写,应用也自己写,那完全可以根据情况决定是否使用设备管理模块。
对已有的设备管理模块——使用之,
通用型或常用的,如SD卡文件系统,网络,标准键盘输入,可以写成设备管理模块。
非常简单的硬件,如LED灯、IO口开关量,不用写了,使用起来也直观方便。
非标准应用,不写了。直接在应用层使用底层驱动。
对个人学习,那非常有必要学习书写一二个设备的驱动,将其加入到设备管理中。在上层应用中能用起来。
最后有二个疑惑:
1.在ffconf.h中,
#define _FS_REENTRANT 0 //此项不太能理解,配置为0是不可重入的,但配为1出现错误。
按照fatfs作者的本意,此处必须配置为1才,表示可重入才对。当然也有可能更上层的dfs系统对此做了相关的线程安全工作。
2.SD卡初始化设备时,为何不用指明设备类型。
设备类型指:
RT_Device_Class_Char = 0, /* character device RT_Device_Class_Block, /* block device RT_Device_Class_NetIf, /* net interface RT_Device_Class_MTD, /* memory device RT_Device_Class_CAN, /* CAN device RT_Device_Class_RTC, /* RTC device RT_Device_Class_Sound, /* Sound device RT_Device_Class_Unknown /* unknown device
RT-Thread文件系统工程目标V021ourdev_702717OZ2I3J.rar(文件大小:3.32M) (原文件名:STM32_RTThread_V021.rar) |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|