介绍AWorksLP基于FatFs的SD卡的基本用法

aworkslp对存储类设备进行了高度抽象化,为存储类设备提供了通用的文件操作接口,应用程序可以轻松跨平台。本文以mr6450平台为例,介绍aworkslp基于fatfs的sd卡的基本用法。
  简介
sd卡(secure digital card)即安全数字卡。是一种基于半导体快闪记忆器的新一代记忆设备,从mmc的基础上发展而来。由于它的体积小、数据传输速度快、可热拔插等优点,被广泛的运用于便携式和嵌入式设备上。 fatfs是一种面向小型嵌入式系统的通用的fat文件系统。它完全是由ansic语言编写并且完全独立于底层i/o。
因此它可以很容易的移植到不同且资源有限的微控制器中。
由此可见在嵌入式开发中对sd卡中的文件进行管理时,fatfs是使用的最多的文件系统。 在aworkslp中已经集成了fatfs文件系统,并支持使用该文件系统对sd卡的文件进行管理。
  相关api
在sd卡例程中,是通过文件接口实现对sd卡中文件进行操作的。在本文中仅介绍用到的文件接口,其他文件接口,请参考sdk中《aworkslp os 标准api参考手册(html)》。
aworkslp函数列表:
部分接口参数属性表:
工程编译
环境的搭建、eclipse工程的编译与配置、开发板的仿真与调试、请参考《aworkslp sdk快速入门(mr6450)——开箱体验》。
  例程介绍
本文介绍例程在{sdk}demosperipheralsdcard目录下。
在src目录下的demo_sdcard_fs.c例程代码中的第149行到第157行使用了while循环如代码1示,在循环中每隔500ms打开一次sd卡设备,通过检查返回值来检测是否有sd卡插入。如检测到返回值大于等于0则表明有sd卡插入。需要注意的是打开sd卡的设备名(“__blk_name”在demo_sdcard_fs.c的第67行中默认被宏定义为“/dev/sdcardb0”)需要与实际检测到的sd卡设备名一致。
在aworkslp中sd卡默认是动态监测,在sd卡插入时会在串口打印设备信息如图1示,串口显示sd卡设备名为“sdcarda0”,所以我们需要修改“__blk_name”的宏定义为“/dev/sdcarda0”。
64 /* sd卡设备分区名,是由sd卡设备分区注册为字符型设备65 * sd卡设备分区名一般是由sd卡设备名加上part number66 */67 #define __blk_name      /dev/sdcardb0149 do{150     fd = aw_open(__blk_name, aw_o_rdwr, 0);151     if (fd < 0) {152         aw_kprintf(open device failed);153         aw_mdelay(500);154     } 155 }while(fd < 0);156 157    aw_close(fd);代码1 sd卡设备检测流程
图1 串口打印sd卡设备名 代码2中第159行到172行的功能为使用aw_make_fs函数接口将sd卡格式化为fatfs文件系统。第159行的宏定义默认为 #if 0,本次例程为了演示该步骤将宏改为 #if 1。需要注意的是格式化会把卡内的数据清除,在执行格式化之前需要确保卡内没有重要数据。
159 #if 1 /* 格式化一次即可 */160 161 /* 卷名为awdisk, 卷大小为4k */162 struct aw_fs_format_arg fmt = {awdisk, 1024 * 4, 0};163 164 /* 制作文件系统 ,将存储器名为 /dev/sd0制作为vfat类型的文件系统 */165 ret = aw_make_fs(__blk_name, vfat, &fmt);166 if (ret != aw_ok) {167 aw_errf((failed: %d, ret));168 return;169 }170 aw_infof((make fs ok));171 172 #endif  
代码2 sd卡格式化
格式化完成后,代码3中第174行通过aw_mkdir函数创建一个名为“/sd”的目录,以该目录为sd卡的挂载点。创建目录的文件模式为文件所有者、用户组和其他用户都可以对该目录进行读写。第181行通过aw_mount函数将sd卡挂载在“/sd”目录中。需要注意的挂载前需要确保目录存在,如果将sd卡挂载在不存在的目录上,挂载会失败。挂载的文件系统也需要与sd卡格式化的文件系统格式一致,否则挂载同样会失败。
173 /* 创建挂载节点 */174 ret = aw_mkdir(/sd, aw_s_irwxu | aw_s_irwxg | aw_s_irwxo);175 if (ret != aw_ok) {176     aw_errf((/sd create error: %d!, ret));177     return;178 }179 180 /* 文件系统挂载到/sd节点  */181 ret = aw_mount(/sd, __blk_name, vfat, 0, null);182 if (ret != aw_ok) {183     aw_errf((/sd mount fatfs error: %d!, ret));184     return;185 }186 aw_infof((mount ok));187 188 /* sd 卡读写测试  */189 __fs_file_rw();  
代码3 挂载sd卡
最终例程会在第189行调用__fs_file_rw函数,函数体如代码4所示。在该函数中会在“/sd”目录下创建一个名为“aworks_sd_test.txt”的测试文件,通过对该文件进行读写测试,读写完成后对数据进行效验,效验通过则表明sd卡读写测试成功。至此sd卡例程执行完毕,整个过程会有串口信息打印如图2所示。
69 aw_local void __fs_file_rw (void)70 {71 int i = 0;72 int handle;73 char *p_file_name = /sd/aworks_sd_test.txt;74 uint8_t str_buf[256] = {0};75 int len;76 77 /*78 * 写文件测试(包括创建,文件写操作,关闭操作)79 */80 /* 创建新文件 */81 handle = aw_open(p_file_name, aw_o_rdwr | aw_o_creat, 0777);82 if (handle < 0) {83 aw_errf((creat file error: %d, handle));84 return;85 }86 aw_infof((creat file %s ok, p_file_name));87 88 len = sizeof(str_buf);89 for (i = 0; i < len; i++) {90 str_buf[i] = (uint8_t)i;91 }92 93 /* 写文件 */94 if (aw_write(handle, str_buf, sizeof(str_buf)) != sizeof(str_buf)) {95 aw_close(handle);96 aw_errf((write file error));97 return;98 }99 aw_infof((write file %s ok, p_file_name));100 101 /* 关闭文件 */102 aw_close(handle);103 aw_infof((close file %s ok, p_file_name));104 105 /*106 * 读文件测试(包括打开,文件读操作,关闭操作)107 */108 /* 打开文件 */109 handle = aw_open(p_file_name, aw_o_rdonly, 0777);110 if (handle < 0) {111 aw_errf((open file error: %d, handle));112 return;113 }114 aw_infof((open file %s ok, p_file_name));115 116 memset(str_buf, 0, sizeof(str_buf));117 118 /* 读取文件 */119 len = sizeof(str_buf);120 if (aw_read(handle, str_buf, sizeof(str_buf)) != sizeof(str_buf)) {121 aw_close(handle);122 aw_errf((read file error!));123 return;124 }125 aw_infof((read file %s ok, p_file_name));126 127 /* 检验数据是否正确 */128 for (i = 0; i < len; i++) {129 if ((uint8_t)i != str_buf[i]) {130 aw_errf((file data error!));131 aw_close(handle);132 return;133 }134 }135 136 aw_infof((file %s data check ok, p_file_name));137 }  
代码4 __fs_file_rw读写测试函数
图2 sd卡例程执行成功的串口信息
  扩展介绍
在上节中有提到aworkslp sd卡默认是动态检测设备,即支持热拔插,这是通过一个检测引脚实现的。在实际应用中,可能出于节约i/o资源的考虑,需要将检测引脚复用为其他功能。在这种情况下可以将sd卡定义为静态设备,这样检测引脚就能复用作其他功能了。
在aworkslp中sd卡的动态设备在图形化配置界面中没有sd卡设备可供使用,只需将对应的sdio控制器选上即可。上文例程中sd卡是通过sdio1设备来控制的,所以仅需保证sdio1设备使能即可,如图3所示。
图3 动态设备下确认控制器被选上
将sd卡设备以静态方式注册时,则需要进行如下操作:
将pins.dts({board}dtspins.dts)文件中cd引脚配置注释,修改完成后如代码5所示;
在board.dts文件中添加sd卡设备,如代码5所示。
/*   cd-pins = ; */代码5 注释引脚 &sdio1 {     sdio_mem_card0:sdio_mem_card0 {         compatible = general,sdio_mem_card;         label = sdcarda;         status = disabled;     }; };代码6 添加sd卡设备  
完成修改后,重新打开例程编译图形化配置界面,即可在board epc6450-awi/devices/external memories选项下看到板卡下新增sdcarda设备如图4所示,使能该项并保存退出,再次编译工程并执行固件,例程现象与上节中所描述完全一致。
图4 选择sd卡设备
注意:例程在静态sd卡设备下执行需要在固件运行前将sd卡插入。


降压型DC/DC控制器LTC3865/-1的功能特性及适用范围
Wi-Fi6都还没普及,Wi-Fi7的研发已在路上
骨传导蓝牙耳机排行榜10强(前十名)
二次回路故障查找方法
Python变量很难记?常见的解决办法有三种
介绍AWorksLP基于FatFs的SD卡的基本用法
GSM/GPRS通信在配电自动化系统中的应用
全自动插拔力试验机的应用及优势
TikTok究竟取得了怎样的成绩呢?为什么被川普政府盯上了?
中继台技术详解
苹果13预计有8款配色
苹果在WWDC 2017敢将旧貌换新颜! App Store全新设计值得期待
北斗卫星 | 国产化北斗专用芯片样机的设计与实现
电源插座安装步骤及注意事项
人工智能在预防欺诈与消费者体验中起到了重要作用
D类功放有哪些优缺点
简要分析贴片电感为何兼容伍尔特电感744778004
WIFI天线信号增强器的制作
激光切割机常见故障以及解决方案
普渡机器人亮相第二届Foodtech Japan大阪展