MC9S12UF32的嵌入式文件系统数据存储模块

mc9s12uf32的嵌入式文件系统数据存储模块
摘要:随着嵌入式技术的发展,越来越多的系统需要具备大容量数据存储、传输和分析的功能,对于数据灵活性和通用性的要求也随之提高。本文基于mc9s12uf32设计了一款使用fat文件系统对数据进行管理的数据存储模块。详细介绍了该模块的软、硬件构架,并给出了开放源代码的文件系统fatfs软件包的移植与使用方法。
引言
随着信息技术的发展,嵌入式系统简单地对存储介质按地址、字节进行读写的方式已经不能满足实际应用的需求,利用文件系统对存储介质进行管理成为嵌入式系统的一个发展方向。虽然目前存在很多版本的文件系统,但windows的广泛应用使得fat文件系统仍然是最通用的文件系统之一。本文中基于mc9s12uf32单片机,结合开源文件系统fatfs,设计实现了使用fat文件系统的大容量数据存储模块。
1 系统结构
数据存储系统框架如图1所示。该数据存储模块以freescale公司的mc9s12uf32为核心,串行通信接口sci接收到的数据可以直接通过单片机以fat文件的形式存储在micro sd卡中。用户程序可以通过编程控制单片机,直接对micro sd卡中的任意文件进行读写,实现存储数据。由于实现了fat文件系统,用户也可以通过单片机内置的usb接口将本数据模块识别为u盘,用pc机进行读写操作。此外,模块中的sd卡也可以取出,使用标准的读卡器可在任何pc机上读出。
2 硬件结构及底层函数的编写
本文所介绍的数据存储插件由mc9s12uf32、dsl2887实时钟模块、micro sd卡、串行通信接口以及usb接口5部分组成。实时时钟,可以为数据存储模块的文件系统提供正确的时间戳信息,在精简的系统设计中,这个部分则可以省略。
2.1 mc9s12uf32单片机
freescale公司生产的这款16位单片机具有3.5 kbram和32 kb flash eeprom。它最大的特点在于拥有usb2.o接口、ata5接口以及sd/mmc、smartmedia、memorystick等多种存储卡接口。本文所介绍的数据存储插件采用mc9s12uf32单片机内部集成的sd主控制器模块(sdhc)实现micro sd卡的底层读写。
(1)sdhc模块
sdl.o规范协议中定义了对sd卡的两种访问模式:sd模式和spi模式。使用sdhc(secured digital cardhost controller)模块对sd卡读写采用了sd模式。该模块将sd总线转换为mc9s12uf32内部的ipbus总线或者ique总线,使用者只需要对sdhc模块相关的寄存器进行配置,就可以实现向sd卡发送各种命令和读写数据的功能。sd卡与sdhc的连接如图2所示。
mc9s12uf32内部集成的sdhc模块支持sd卡1.o版本的物理层协议,所以本系统使用标准microsd卡(而非sdhc卡),其存储容量最大为2 gb。这样的存储容量已经完全可以满足大多数嵌入式应用的需求。
(2)mc9s12uf32与sd卡之间的数据传输
在完成对时钟频率和传输数据线宽度的配置之后,通过发送相应的读写命令就可以实现单片机与sd卡之间的数据传输了。在单片机向sd卡写入数据的过程中,编程者将需要写入的数据写入sdhc模块的sdata寄存器(16位)之后,该数据将被转移至发送数据fifo中。与此同时,只要发送数据fifo非空,其中的数据就会不断地通过数据线被写入sd卡的相应位置。在单片机从sd卡中读取数据的过程中,sd卡中的数据将不断发送至接收数据fifo中。只要接收fifo非空,单片机就可以不断地通过读sdata寄存器得到接收数据fifo中的数据。
2.2 dsl2887实时钟模块
dsl2887模块使用数据/地址复用的并行异步总线,可以为单片机提供100年以内的实时钟信息(年/月/日/时/分/秒)。它内部具有石英晶振和锂电源,首次使用时,需要对该模块内部的寄存器进行相应配置,激活晶振使其进入工作状态。由于dsl2887内部带有锂电源,所以一旦晶振被激活,即使外部掉电,该模块依然可以保存并提供正确的实时钟信息。
设定dsl2887的时间和从dsl2887中读取时间信息的底层程序比较简单,只需参照芯片手册对寄存器进行合理配置。但是,需要特别注意的是,在写时钟和读取时钟之前需要锁存时钟信息相关的buffer,防止在读写过程中由于出现时钟信息自动更新情况而导致的错误。系统中,在每次读写实时钟之前,查询dsl2887内部控制寄存器a最高位uip是否为o,以避免上述错误的产生。因为芯片手册中给出,一旦uip=o,那么在244μs内实时钟模块都不会自动更新当前的时钟信息,而这段时间足以让单片机完成读写实时钟的过程。
3 fatfs文件系统的移植与配置
3.1 fatfs软件包简介
采用文件系统,是为了在单片机能够对sd卡进行数据读写的同时,保证其读写的数据能够被大多数通用设备识别。换言之,数据在存储器内的组织型式,需要遵循一些已有的工业标准和规范。例如使用fat文件系统,数据存储单元的sd卡取下来后,可以使用任何标准的读卡器在windows、linux等pc机上读出。
当前著名的嵌入式文件系统有若干种选择,比如efsl(embedded filesystem library)、uc/fs、/tinyfatfs等。这之中efsl和fatfs都是开放源码的,具有十分详尽的文档和函数手册,除错更新也十分及时,在本文的设计中我们采用的是fatfs。
fatfs采用使用ansi c编写,具有很好的硬件平***立性,使用者只需要对源程序进行简单的修改和配置,就可以将其移植到各种系列的单片机上。此外,它的内存开销很小,rom的占有量在十几kb的量级,使用者可以根据不同的应用方便的对代码进行裁减。fatfs支持fatl2、fatl6和fat32,可以建立独立的缓冲区对多个文件进行读写。fatfs是一个不断更新完善的软件,大量的相关信息可以从原作者的主页上得到(http://elm-chan.org/fsw/ff/00index_e.html),同时原作者也做了很多性能测试的工作。
3.2 fatfs的移植
可从fatfs的主页上下载得到fatfs r0.07版本。fatfs的主程序包含5个文件,即diskio.c、diskio.h、ff.c、ff.h和integer.h。其中,diskio.c和diskio.h是与底层硬件i/o相关的函数;ff.c和ff.h是应用函数,主要涉及fatfs的配置和裁减;而integer.h中定义了fatfs软件所使用的各种数据类型。
移植fatfs的过程中基本不需要对diskio.h和ff.c进行修改。除了核实integer.h中的数据类型定义是否与mc9s12u32数据类型相符之外,移植的重点工作在于diskio.c中6个主要函数的实现和ff.h中对于文件系统的裁减配置。dikio.c包含的6个接口函数:disk_initial-ize,disk status,disk ioctl,disk read,disk write和disk_fattime。它们分别实现存储介质的初始化、读取/写入若干个扇区的数据和获取实时钟信息的功能。
具体移植过程如下:
(1)存储媒介初始化函数
dstatus disk_initialize(byte drv)
由于采用的存储媒介是sd卡,所以该函数的实际功能是对sd卡进行初始化。drv是存储介质号码,由于tiny-fatfs只支持一个存储介质,所以此处drv始终取o值。执行无误,则返回值=o;执行中出现错误,则返回非o值。
(2)状态检测函数
dstatus disk_status(byte drv)
该函数用于检测是否支持当前的存储介质。此处的drv仍然恒为o。对tiny-fatfs而言,只要drv为o,就认为支持当前介质,函数直接返回o值即可。
(3)读扇区函数
dresult disk read(byte drv,byte*buff,dword seetor,byte.count)
该函数是在“单片机从sd卡读取一个扇区”的函数基础上编写而成的,其功能是从sd卡读取一个或多个扇区的数据。*buff用于存储已经读取的数据,sector是待读取扇区的起始扇区数,count是需要读取的扇区数。如果执行无误则返回o值,否则返回非o值。
(4)写扇区函数
dresult disk_write(byte drv,const byte*buff。dword sector,byte count)
与disk_read相似,该函数是在“单片机向sd卡写入一个扇区”的函数基础上编写而成的,其功能是向sd卡导入一个或多个扇区的数据。*buff用于保存将要写入的数据,sector是待写入扇区的起始扇区数,count是需要写入的扇区数。如果执行无误,则返回0值;否则,返回非0值。
(5)存储介质控制函数
dresult disk_ioctl(byte drv,byte ctrl,voii*buff)
ctrl是控制代码,*buff用于保存或接收需要控制的数据数据。使用者可以在此函数里添加自己需要的功能代码,例如获得存储介质的容量、扇区数等。如果是简单的应用,也可以不执行任何功能,直接返回0值。本文采用的就是这一方法。
(6)实时钟函数
dword disk_fattime(void)
该函数将读取的实时钟信息保存在一个32位无符号整数中,并将其作为函数的返回值。时钟信息在这32位中的具体分布如表1所列。
3.3 fatfs的裁减与配置tiny-fatfs
fatfs提供了丰富的库函数,可以实现创建、读取文件夹,创建、读写文件,移动文件指针,向文件中写入或读取字符串,甚至是类似与c语言fprintf()的格式化输入等各种功能。使用者可以根据自己的需求设置相应的宏,对fatfs进行裁减,仅保留需要的功能函数,从而精简文件系统的内存开销。fatfs提供的函数与宏的对应关系如图3所示。
fatfs的裁减,不仅仅是函数层面的。更重要的是,在内部机制上形成一个精简版本,称为tiny-fatfs。它与标准版fatfs相比,主要的区别在于tiny-fatfs仅支持一个物理存储介质,而且不再针对每个开启的文件建立512字节的缓存,整个文件系统和物理介质使用同一个缓存。显然,tiny-fatfs需要的内存开销比标准版fatfs更低,只要1 kb左右的ram。可以说,tinyr-fatfs是专门为小型嵌入式系统而设计的文件系统模块。本文介绍的数据存储系统使用的正是tiny-fatfs版本。
在表2中,对ff.h中主要配置宏的含义进行了说明,同时给出了本文所介绍的数据存储模块采用的取值。
4 fatfs文件系统的使用
fatfs文件系统中涉及2个基本的数据结构:文件系统(磁盘)的数据结构fatfs和文件的数据结构fil。这两个结构是fatfs软件主要的ram开销,fatfs数据结构中有针对磁盘的512字节读写缓存,fil则有针对每个文件的缓存。而采用tiny fatfs配置则不会开设文件读写缓存,节约ram。
依次使用f_mount、f_open、f_rcad/f_write、f_close可以完成基本的读写。fatfs允许对同一文件同时复数读取,但完全不支持对同一文件同时复数的写入操作,因为这会引起文件系统错误。具体每一个函数,特别是字符串读写、格式化读写等,可以参见原始帮助和例程。
此外,由于嵌入式系统具有突然掉电的可能性,一些关键代码段可能导致文件系统错误,所以要注意调用f_sync()及时写入。当然,如果是一组连续的f_write()写入,而每次写完都f_sync(),则会极大地影响速度,可以全部写完后f_sync()。
v0.07以后版本的fatfs,增加了以下新的功能:
①_fs_tiny。tiny模式变成了一个宏选项,而不是独立的代码包。
②_fs_rpath。决定是否有当前路径的概念,这将影响两个相关函数的参数。
③_use_lfn。启用长文件名支持,可为1或2,为2时可重入。由于长文件名存在堆栈上,而且启用lfn会依据代码页增加一个很大的转换表,占掉几十~几百kb,所以不推荐。
④_lfn_unicode。长文件名使用unicode,实验阶段,尚未正式写入文档。
结语
mc9s12uf32单片机内部集成的sdhc模块,可将sd总线转换为单片机内部的ip总线,开发者只需要对sd协议的基本内容有所了解,通过读写相应的寄存器就可以方便地实现对sd卡的底层读写,大大简化了硬件的开发过程。同时,独立于硬件平台的fatfs软件包可以方便地移植到各种嵌入式系统中,研发者只需要对该软件包的diskio.c和ff.h进行修改,即可完成移植,从而使用fatfs提供的丰富且易于使用的各种接口函数。
应用上述主要技术实现的具有嵌入式文件系统的数据模块如图4所示。
该模块体积小巧、存储数据的灵活性和通用性很高,可以通过模块自带的串行通信接口接收数据,并以文件的形式存储起来。用户既可以直接通过usb接口将本模块识别为u盘进行数据读写和分析,也可以将micro sd卡拔出,在任意一个具有micro sd读卡器功能的设备上读写数据。上述功能特性使得这款数据存储模块具有很良好的应用前景。

赛灵思携手Barco Silex推出IP视频传输综合性平台
荣耀9什么时候上市?荣耀9发布会倒计时:胡歌代言,曲面玻璃+新颜色,颜值比荣耀8还要高?
人工智能课,在中学里教些什么?
芯讯通:积极创新应对车联网大趋势
深开鸿场景化超级终端解决方案推进传统港口向智慧港口转型升级
MC9S12UF32的嵌入式文件系统数据存储模块
科大讯飞语音合成技术屡次刷新世界纪录 达到以假乱真的地步
Wi-SUN标准赋能智慧城市实现互联互通
青海首个电网侧储能项目落地格尔木
如何减少多模LTE智能手机在小区间移动时的连接测试成本?
SMT贴片加工必备:全面解析锡膏种类与特性
明纬电源60W单组输出导轨电源DRA-60系列介绍
T型滤波器对本地电源的隔离
STM32 BSRR BRR ODR寄存器详情解析
什么是CISC型CPU
孢子捕捉分析仪:纪录微生物世界的细腻之美
特斯拉正研发超过400英里的电动汽车电池
国产晶圆代工厂华虹半导体登录科创板今日申购
锐高LED驱动器全新突破 三大系列满足各色需求
中国大陆晶圆产能增幅创全球之最!