[文章]基于OpenHarmony标准接口的文件读写实现案例

阅读量0
1
1


基于OpenHarmony标准接口的文件读写实现案例一、简介
在嵌入式领域,FLASH是一种常用的存储设备,Flash闪存作为嵌入式系统的主要存储设备有其自身的特性。Fash的写入操作只能把对应位置的1修改成0,而不能把0修改为1,而擦除Fash就是把对应存储块的内容恢复为1。因此,一般情况下向Fash写入内容时,需要先擦除对应的存储区间,这种擦除是以块(Bock)为单位进行的。闪存主要有NORNAND两种技术。因为Flash存储器的擦写次数是有限的,NAND闪存还有特殊的硬件接口和读写时序,于是就出现了专门针对FLASH的文件系统。比较常用的有jffs2yaffs2logfsubifs。本文基于小凌派-RK2206开发板 + OpenHarmony轻量级操作系统 + LitteFS文件系统,通过hal_file标准接口实现对Flash读写功能

二、hal_file标准接口
头文件://utils/native/lite/hals/file/hal_file.h
1HalFileOpen()
打开/创建文件,类似于Linuxopen函数。
  1. int HalFileOpen(const char *path, int oflag, int mode);
复制代码

参数说明:
名字
描述
path
文件路径
oflag
参考///utils/native/lite/include/utils_file.h
O_RDONLY_FS:只读
O_WRONLY_FS:只写
O_RDWR_FS:读写
O_CREAT_FS:如果没有则创建
O_EXCL_FS:如果没有则创建;如有则不能打开
O_TRUNC_FS:如果文件存在,则清空文件内容
O_APPEND_FS:如果文件存在,则标记位置移动到文件最后
mode
0
返回值为LOS_OK表示成功,其余为失败。
2HalFileClose()
关闭文件,类似于Linuxclose函数。
  1. int HalFileClose(int fd);
复制代码

参数说明:
名字
描述
fd
文件句柄
返回值为LOS_OK表示成功,其余为失败。
3HalFileRead()
从文件中读取一段内容,类似于Linuxread函数。
  1. int HalFileRead(int fd, char* buf, unsigned int len);
复制代码

参数说明:
名字
描述
fd
文件句柄
buf
从文件读取内容的缓冲区
len
从文件读取内容的大小
返回值为从文件读取内容的大小,0或者小于0则为失败。
4HalFileWrite()
往文件写入一段内容,类似于Linuxwrite函数。
  1. int HalFileWrite(int fd, const char* buf, unsigned int len);
复制代码

参数说明:
名字
描述
fd
文件句柄
buf
需要写入到文件的内容缓冲区
len
需要写入到文件的内容大小
返回值为成功写入到文件的内容大小,0或者小于0则为失败。
5HalFileDelete()
删除文件,类似于Linuxunlink函数。
  1. int HalFileDelete(const char* path);
复制代码

参数说明:
名字
描述
path
文件路径
返回值为LOS_OK为成功,其余则为失败。
6HalFileStat()
获取文件大小,类似于Linuxstat函数。
  1. int HalFileStat(const char* path, unsigned int* fileSize);
复制代码

参数说明:
名字
描述
path
文件路径
fileSize
文件内容大小
返回值为LOS_OK为成功,其余则为失败。
7HalFileSeek()
文件所在位置移动,类似于Linuxlseek函数。
  1. int HalFileSeek(int fd, int offset, unsigned int whence);
复制代码

参数说明:
名字
描述
fd
文件句柄
offset
文件位置移动位数
whence
SEEK_SET_FS:从文件开头移动
SEEK_CUR_FS:从文件当前位置移动
SEEK_END_FS:从文件结尾移动
返回值为LOS_OK为成功,其余则为失败。
三、程序设计
本例程演示如何在小凌派-RK2206开发板上使用鸿蒙LiteOS-M内核接口,进行文件读写开发。例程流程如下所示:
1)创建一个文件;
2)每5秒进行1次文件读写操作;
3)文件标识移动到文件起始处,读文件内容,并打印;
4)文件标识移动到文件起始处,写文件内容;
5)循环上述的第24步骤。

1、任务创建代码分析
file_example函数中通过LOS_TaskCreate函数创建一个线程:hal_file_thread
  1. <p class="15"><font face="Courier New">void file_example()</font><o:p></o:p></p><p class="15"><font face="Courier New">{</font><o:p></o:p></p><p class="15">    <font face="Courier New">unsigned int thread_id;</font><o:p></o:p></p><p class="15">    <font face="Courier New">TSK_INIT_PARAM_S task = {0};</font><o:p></o:p></p><p class="15">    <font face="Courier New">unsigned int ret = LOS_OK;</font><o:p></o:p></p><p class="15"><o:p> </o:p></p><p class="15">    <font face="Courier New">task.pfnTaskEntry = (TSK_ENTRY_FUNC)hal_file_thread;</font><o:p></o:p></p><p class="15">    <font face="Courier New">task.uwStackSize = 1024 * 10;</font><o:p></o:p></p><p class="15">    <font face="Courier New">task.pcName = "hal_file_thread";</font><o:p></o:p></p><p class="15">    <font face="Courier New">task.usTaskPrio = 25;</font><o:p></o:p></p><p class="15">    <font face="Courier New">ret = LOS_TaskCreate(&thread_id, &task);</font><o:p></o:p></p><p class="15">    <font face="Courier New">if (ret != LOS_OK)</font><o:p></o:p></p><p class="15">    <font face="Courier New">{</font><o:p></o:p></p><p class="15">        <font face="Courier New">printf("Falied to create hal_file_thread ret:0x%xn", ret);</font><o:p></o:p></p><p class="15">        <font face="Courier New">return;</font><o:p></o:p></p><p class="15">    <font face="Courier New">}</font><o:p></o:p></p><p class="15"><font face="Courier New">}</font><o:p></o:p></p><p class="15"><o:p> </o:p></p><p class="15"><font face="Courier New">APP_FEATURE_INIT(file_example);</font></p>
复制代码

2. 文件读写代码分析
hal_file_thread函数负责打开文件,每5秒移动到文件头读取数据,再移动到文件头写入一段内容,重复以上流程。
  1. <p class="15"><font face="Courier New">void hal_file_thread()</font><o:p></o:p></p><p class="15"><font face="Courier New">{</font><o:p></o:p></p><p class="15">    <font face="Courier New">int fd;</font><o:p></o:p></p><p class="15">    <font face="Courier New">char buffer[1024];</font><o:p></o:p></p><p class="15">    <font face="Courier New">int read_length, write_length;</font><o:p></o:p></p><p class="15">    <font face="Courier New">int current = 0;</font><o:p></o:p></p><p class="15"><o:p> </o:p></p><p class="15">    <font face="Courier New">/* </font><font face="宋体">打开文件,如果没有该文件就创建,如有该文件则打开</font><o:p></o:p></p><p class="15">     <font face="Courier New">* O_TRUNC_FS => </font><font face="宋体">清空文件内容</font><o:p></o:p></p><p class="15">     <font face="Courier New">*/</font><o:p></o:p></p><p class="15">    <font face="Courier New">//fd = HalFileOpen(FILE_NAME, O_RDWR_FS | O_CREAT_FS, 0);</font><o:p></o:p></p><p class="15">    <font face="Courier New">fd = HalFileOpen(FILE_NAME, O_RDWR_FS | O_CREAT_FS | O_TRUNC_FS, 0);</font><o:p></o:p></p><p class="15">    <font face="Courier New">if (fd == -1)</font><o:p></o:p></p><p class="15">    <font face="Courier New">{</font><o:p></o:p></p><p class="15">        <font face="Courier New">printf("%s HalFileOpen failed!n", FILE_NAME);</font><o:p></o:p></p><p class="15">        <font face="Courier New">return;</font><o:p></o:p></p><p class="15">    <font face="Courier New">}</font><o:p></o:p></p><p class="15"><o:p> </o:p></p><p class="15">    <font face="Courier New">while (1)</font><o:p></o:p></p><p class="15">    <font face="Courier New">{</font><o:p></o:p></p><p class="15">        <font face="Courier New">/* </font><font face="宋体">文件位置移动到文件开始位置 </font><font face="Courier New">*/</font><o:p></o:p></p><p class="15">        <font face="Courier New">HalFileSeek(fd, 0, SEEK_SET);</font><o:p></o:p></p><p class="15">        <font face="Courier New">memset(buffer, 0, sizeof(buffer));</font><o:p></o:p></p><p class="15">        <font face="Courier New">/* </font><font face="宋体">读取文件内容 </font><font face="Courier New">*/</font><o:p></o:p></p><p class="15">        <font face="Courier New">read_length = HalFileRead(fd, buffer, sizeof(buffer));</font><o:p></o:p></p><p class="15">        <font face="Courier New">printf("read: n");</font><o:p></o:p></p><p class="15">        <font face="Courier New">printf("    length = %dn", read_length);</font><o:p></o:p></p><p class="15">        <font face="Courier New">printf("    content = %sn", buffer);</font><o:p></o:p></p><p class="15"><o:p> </o:p></p><p class="15">        <font face="Courier New">/* </font><font face="宋体">文件位置移动到文件开始位置 </font><font face="Courier New">*/</font><o:p></o:p></p><p class="15">        <font face="Courier New">HalFileSeek(fd, 0, SEEK_SET);</font><o:p></o:p></p><p class="15">        <font face="Courier New">memset(buffer, 0, sizeof(buffer));</font><o:p></o:p></p><p class="15">        <font face="Courier New">snprintf(buffer, sizeof(buffer), "Hello World(%d) => ", current);</font><o:p></o:p></p><p class="15">        <font face="Courier New">/* </font><font face="宋体">写入文件 </font><font face="Courier New">*/</font><o:p></o:p></p><p class="15">        <font face="Courier New">write_length = HalFileWrite(fd, buffer, strlen(buffer));</font><o:p></o:p></p><p class="15"><o:p> </o:p></p><p class="15">        <font face="Courier New">current++;</font><o:p></o:p></p><p class="15">        <font face="Courier New">LOS_Msleep(5000);</font><o:p></o:p></p><p class="15">    <font face="Courier New">}</font><o:p></o:p></p><p class="15"><o:p> </o:p></p><p class="15">    <font face="Courier New">HalFileClose(fd);</font><o:p></o:p></p><p class="15"><font face="Courier New">}</font></p>
复制代码

四、编译过程
1、搭建和下载源代码
我已将OpenHarmony源代码上传到Gitee社区中,大家可以根据以下网址下载。
https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk2206-openharmony3.0lts
注意:编译环境可根据以下网址来操作:https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk2206-openharmony3.0lts/blob/master/vendor/lockzhiner/rk2206/README_zh.md
2、修改编译脚本
修改 vendor/lockzhiner/rk2206/sample 路径下 BUILD.gn 文件,指定 a7_hal_file 参与编译。
"./a7_hal_file:hal_file_example"
修改 device/lockzhiner/rk2206/sdk_liteos 路径下 Makefile 文件,添加 -lhal_file_example 参与编译。
apps_LIBS = -lhal_file_example
3、编译固件
  1. <p class="MsoNormal" align="justify"><font face="Calibri">hb set -root .</font><o:p></o:p></p><p class="MsoNormal" align="justify"><font face="Calibri">hb set</font><o:p></o:p></p><p class="MsoNormal" align="justify"><font face="Calibri">hb build -f</font></p>
复制代码

4、烧写固件
请参考Gitee网址的说明手册(“烧录打印”章节):https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk2206-openharmony3.0lts/blob/master/device/rockchip/README_zh.md
五、实验结果
程序编译烧写到开发板后,按下开发板的RESET按键,通过串口软件查看日志如下
  1. <p class="15"><font face="Courier New">HalFileInit: Flash Init Successful!</font><o:p></o:p></p><p class="15"><font face="Courier New">read:</font><o:p></o:p></p><p class="15">    <font face="Courier New">length = 0</font><o:p></o:p></p><p class="15">    <font face="Courier New">content =</font><o:p></o:p></p><p class="15"><font face="Courier New">read:</font><o:p></o:p></p><p class="15">    <font face="Courier New">length = 18</font><o:p></o:p></p><p class="15">    <font face="Courier New">content = Hello World(0) =></font><o:p></o:p></p><p class="15"><font face="Courier New">read:</font><o:p></o:p></p><p class="15">    <font face="Courier New">length = 18</font><o:p></o:p></p><p class="15"><font face="Courier New">content = Hello World(1) =></font></p>
复制代码

好了,今天的课程就到这里,我们下次再见!



回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友