电子说
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 number 66 */ 67 #define __BLK_NAME "/dev/sdcardB0" 149 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 = <&pin1 PIN_PD28 (IOC_PD28_FUNC_CTL_SDC1_CDN|HPM_PIN_DS(6)|HPM_PIN_PE(_HPM_PIN_PE_ON)|AW_PIN_CFG_PULL_UP) (IOC_PD28_FUNC_CTL_SDC1_CDN|HPM_PIN_DS(6)|HPM_PIN_PE(_HPM_PIN_PE_ON)|AW_PIN_CFG_PULL_UP) (IOC_PD28_FUNC_CTL_SDC1_CDN|HPM_PIN_DS(6)|HPM_PIN_PE(_HPM_PIN_PE_ON)|AW_PIN_CFG_PULL_UP) >; */代码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卡插入。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !