正点原子wifi实验分析:
fatfs文件系统分为三个层:应用层、FATFS模块、FATS模块提供底层接口驱动层。
1.应用层只需要调用FATS提供的接口函数,如f_open、f_read、f_write和f_close等。
2.FATFS模块提供的是ff.c和ff.h.除非有必要,一般情况下只需要直接包含进去即可。
3.需要编写的是FATFS模块提供的底层接口,它包括存储媒介读/写接口(disk I/O)和供给文件创建修改时间的实时时钟。
FATFS的介绍:doc里面是主要对FATFS的介绍,而src里面才是真正的源码。
src中的源码有:
ffconf.h FATFS模块配置文件
ff.h
FATFS和应用模块公用的包含文件
FATFS FATFS模块
diskio.h FATFS和disk I/O模块公用的包含文件
interger.h 数据类型定义
option.h 可选外部功能支持
注意:以上不同层次间链接关系在于包含文件ff.h和diskio.h的作用!!!!
重点:FATFS模块在移植的时候,我们一般只需要修改2个文件,即ffconf.h和diskio.c。FATFS的所有配置项都放在ffconf.h中。
在使用FATFS的时候,必须先要通过f_mount的函数注册一个工作区,才能对后续的API进行使用。即使用f_mount();
f_mount(FATFS* fs,const TCHAR *path,BTYE opt)函数分析:
其中fs为文件系统对象结构,path将要挂载的驱动的逻辑号,opt为挂载状态设置(0 不挂载:1 挂载)。
目的是为了注册一个工作区。
ff.h文件分析:
1.定义了FATFS结构体为文件系统对象结构,其中包含了各项参数。同时还定义了FIL、DIR、FILINFO等结构体,还有sturct enum{}FRESULT返回错
误枚举类型。
2.定义了各种FATFS模块的应用接口。
重要函数分析:
1.exfuns_init()函数分析:
fs[i] = (FATFS *)mymalloc(SRAMIN,sizeof(FATS)); //其中i为支持磁盘的个数。
file = (FIL *)mymalloc(SRAMIN,sizeof(FIL)); //为file申请内存
ftemp = (FIL *)mymalloc(SRAMIN,sizeof(FIL)); //为ftemp申请内存
fatbuf = (u8 *)mymalloc(SRAMIN,512); //为fatbuf申请内存
2.f_mount(FATFS *fs,const TCHAR *path,BYTE opt)函数分析:
vol = get_ldnumber(&rp); //通过path name来提取逻辑驱动号
其中get_ldnumber获取id的方式有两种,一种是数字id或者是string id。如果是string id ,则根据_VOLUME_STRS
定义的#define _VOLUME_STRS
"RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"的这些情况进行对比,然后
给出返回值vol.
后面将FATFS * fs 赋值给了FATFS[vol],FATFS[vol] = fs;不同的存储介质有对应的一个FATFS结构.其中main.c中使用
的fs[0]、fs[1]是在exfuns.h中定义指向FATFS结构体的指针数组,其为全局变量extern FATFS * fs[_VOLUMES];所以main中能直接使用。
f_mount(fs[0],"0:",1);
f_mount(fs[1],"0:",1);
综上所述两个函数的综上作用是从path中提取了FATFS[vol]数组中的vol编号,并分配了指针fs[i]指向
FATFS[vol]结构体。
3.font_init()字库检查函数分析:
fontok = font_init(); //检查字库是否OK.
W25QXX_Init((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo));//读出ftinfo结构体数据
以上函数可以看出对于main.c中的字库,首先对flash中的的字库地址
FONTINFOADDR 1024*1024*12,读取出一个ftinfo大小的结构体
,这个结构体定义为:
__packed typedef struct{
u8 fontok; //字库存在的标志,0xaa,字库正常;其他,字库不存在
u32 ugbkaddr; //unigbk的地址
u32 ugbksize; //unigbk的大小
u32 f12addr; //gbk12的地址
u32 gbk12size;//gbk12的大小
u32 f16addr; //gbk16地址
u32 gbk16size; //gbk16的地址
u32 f24addr;
u32 gkb24size;
}_font_info;
extern _font_info ftinfo; //字库信息结构体
同时要知道的是fatfs占用了前12M的内存空间(即FONTINFOADDR后),12M以后紧跟着3个字库+UNIGBK.BIN,总大小为3.09M,被字库占用,
不能动!!!!!15.10M以后,用户可以自由使用,建议用最后的100k字节比较好。
而对于字库检查是通过10次读finfo结构体的信息,并判断finfo.fontok == 0xAA,才能正确判断字库正常。
4.SD_Init()和updata_font()从SD卡更新字库函数分析:
上面分析了从flash(W25Q128)中检查字库的方式,但如果检查失败则必须通过SD卡来进行更新字库操作。
(1).SD_Init()函数初始化了SD卡,通过设置为SDIO初始化、获取卡信息、选中SD卡、设置为4位宽度(MMC卡不能用这种方式)、设置SDIO时钟、DMA
模式、查询模式等进行初始化。
(2).updata_font(u16 x,u16 y,u8 size,u8 *src);
strcpy((char*)pname,(char*)src);
//copy src内容到pname
strcat((char*)pname,(char*)UNIGBK_PATH);
res=f_open(fftemp,(const TCHAR*)pname,FA_READ);
...
W25QXX_Read((u8*)buf,((FONTINFOADDR/4096)+i)*4096,4096);
第一步:其中x、y提示信息的显示地址,size字体大小,src字库来源磁盘:"0:",SD卡;"1:",FLASH盘,"2:",U盘。这个函数首先将指定的盘src(0、1或者2)的UNIGBK目录(//SYSTEM/FONT/UNIGBK.BIN)和GBK12_PATH、GBK16_PATH、GBK24_PATH定义的目录文件进行打开检查是否成功。
第二步:然后检查是否FLASH卡(W25Q128)(实验默认为FLASH卡)弄脏(dirty),否则进行擦除操作。
strcpy((char*)pname,(char*)src);
//copy src到pname
strcat((char*)pname,(char*)UNIGBK_PATH);
res=updata_fontx(x+20*size/2,y,size,pname,0);
第三步:在确认文件可以打开,flash无dirty或dirty被擦除后,就可以进行第三步的更新操作,将
updata_fontx(u16 x,u16 y,u8 size,u8 *fxpath,u8 fx)函数分析:
fftemp = (FIL*)malloc(SRAMIN,sizeof(FIL)); //分配内存
tempbuf = mymalloc(SRAMIN,4096); //分配4096个字节
res = f_open(fftemp,(const TCHAR*)fxpath,FA_READ); //将函数fxpath:0/SYSTEM/FONT/UNIGBK.BIN文件打开
//并且赋给fftemp.
上述函数将fxpath路径下的文件打开后,通过f_open()函数得到了该路径目录下的文件的参数,并且赋给了文件
结构体FIL。fftemp->fsize就是在f_open()函数后得到的。
switch(fx)
{
case 0:
ftinfo.ugbkaddr = FONTINFOADDR+sizeof(ftinfo);
ftinfo.ugbksize = fftemp->fsize;
flashaddr = ftinfo.ugbkaddr;
.....
}
上述语句将打开的SD卡的path(有4种情况)后,通过f_open()得到大小,得到每个文件的大小fftemp->fsize,然后将其赋给字库信息全局结构体ftinfo,每个fxpath路径下的文件有两个参数要赋给ftinfo结构体:ftinofo.ugbkaddr和ftinfo.ugbksize。
while(res == FR_OK)
{
...
res = f_read(fftemp,tempbuf,4096,(UINT *)&bread);//读取数据
...
W25QXX_Write(tempbuf,offx+flashaddr,4096); //从0处读取4096个数据
...
}
上述代码是从fftemp结构体使用f_read()函数读取数据到tempbuf,然后将其写入到flash(W25Q128)的地址offx+flashaddr。(
其中fftemp是fxpath路径用f_open()赋予的,所以数据来源于SD卡,数据目的是FLASH )。