SDK的standalone已移植好了FatFs库(SDK中叫做xilffs),所以在BSP中添加xilffs库后就可以在程序中使用FatFs中各API来操作SD卡,该库支持FAT12, FAT16 FAT32 and exFAT文件系统(本例将SD卡格式化为FAT32)。
打开BSP中的system.mss,可以修改BSP的配置信息。
我们选中xilffs这个lib,并在左侧选项卡中,对这个lib进行选项配置。确保fs_interface这个选项的值是true。还有use_lfn这个选项为true。还有use_strfunc这个选项为2,用来使能f_printf()函数。
之后我们可以在BSP中看到xilffs_v3_7这个文件夹。
diskio.c是底层操作函数,和板子相关的硬件操作。
ff.c是文件操作函数,和FATFS相关的文件操作。
我们主要使用的,就是FATFS相关的文件操作。
注意,之前版本中的f_write的关于section的BUG,在V3_7这个版本里,已经被修正了。即使写入的不是256的整数倍也是可以的,而且对写入的长度不再有最小长度的要求,哪怕只有1个BYTE都是可以的。
其中的几个重要函数是:
FRESULT f_mount (
FATFS* fs, /* Pointer to the file system object (NULL:unmount)*/
const TCHAR* path, /* Logical drive number to be mounted/unmounted */
BYTE opt /* 0:Do not mount (delayed mount), 1:Mount immediately */
)
这个函数用来挂载SD卡上的FAT32。
FRESULT f_open (
FIL* fp, /* Pointer to the blank file object */
const TCHAR* path, /* Pointer to the file name */
BYTE mode /* Access mode and file open mode flags */
)
这个函数用来打开一个FILE。
FRESULT f_lseek (
FIL* fp, /* Pointer to the file object */
DWORD ofs /* File pointer from top of file */
)
这个函数用来标记LSEEK。
FRESULT f_read (
FIL* fp, /* Pointer to the file object */
void* buff, /* Pointer to data buffer */
UINT btr, /* Number of bytes to read */
UINT* br /* Pointer to number of bytes read */
)
这个函数用来读取文件中的数据,并转存到buff中来。
FRESULT f_write (
FIL* fp, /* Pointer to the file object */
const void *buff, /* Pointer to the data to be written */
UINT btw, /* Number of bytes to write */
UINT* bw /* Pointer to number of bytes written */
)
这个函数用来把buff中的数据,写入FILE中。
FRESULT f_close (
FIL *fp /* Pointer to the file object to be closed */
)
这个函数用来关闭一个FILE。
还有其他的一些函数,可以在ff.c文件中查看源代码,了解它的功能。
下面进行一些情景分析。
static FATFS fatfs;
声明一个静态的数据对象,FATFS类型,它用来作为SD卡上的FAT32文件系统的句柄。
#define FILE "test123456789.txt"
static char src_str[MAX_LEN] = { 0 } ;
static char dst_str[MAX_LEN] = { 0 } ;
定义缓冲区,定义文件名字符串。
int SD_Init()
{
FRESULT rc;
rc = f_mount(&fatfs,"",0);
if(rc)
{
xil_printf("ERROR : f_mount returned %d\r\n",rc);
return XST_FAILURE;
}
return XST_SUCCESS;
}
定义了初始化函数。主要是mount文件系统,利用空串,检索到系统内的默认的逻辑卷0,并初始化FATFS数据对象。
这是一个比较费解的地方,这里多做一些说明。
在fatfs外挂一个设备的时候,通过 f_mount(&fs, “”, 1);就可以访问,而在多个设备时,就得指定磁盘号。
支持以下两种方式:
f_mount(&fs, “1:”, 1);
f_mount(&fs, “1:/”, 1);
这种方式不支持:
f_mount(&fs, “1”, 1);
result = f_mount(&fs, "", 1); /* Mount a logical drive */
result = f_mount(&fs, "1:/", 1); /* Mount a logical drive */
result = f_mount(NULL, "1:/", 1); /* UnMount a logical drive */
这是f_mount使用的样例。
int SD_Transfer_read(char *FileName,u32 DestinationAddress,u32 ByteLength)
{
FIL fil;
FRESULT rc;
UINT br;
rc = f_open(&fil,FileName,FA_READ);
if(rc)
{
xil_printf("ERROR : f_open returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_lseek(&fil, 0);
if(rc)
{
xil_printf("ERROR : f_lseek returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_read(&fil, (void*)DestinationAddress,ByteLength,&br);
printf("act read len is %d \n\r",br );
if(rc)
{
xil_printf("ERROR : f_read returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_close(&fil);
if(rc)
{
xil_printf(" ERROR : f_close returned %d\r\n", rc);
return XST_FAILURE;
}
return XST_SUCCESS;
}
定义了读文件数据的函数。
int SD_Transfer_write(char *FileName,u32 SourceAddress,u32 ByteLength)
{
FIL fil;
FRESULT rc;
UINT bw;
rc = f_open(&fil,FileName,FA_CREATE_ALWAYS | FA_WRITE);
if(rc)
{
xil_printf("ERROR : f_open returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_lseek(&fil, 0);
if(rc)
{
xil_printf("ERROR : f_lseek returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_write(&fil,(void*) SourceAddress,ByteLength , &bw );
printf("SD_Transfer_write -> f_write result len is %d \n\r" , bw );
if(rc)
{
xil_printf("ERROR : f_write returned %d\r\n", rc);
return XST_FAILURE;
}
rc = f_close(&fil);
if(rc){
xil_printf("ERROR : f_close returned %d\r\n",rc);
return XST_FAILURE;
}
return XST_SUCCESS;
}
定义了写文件数据的函数。
下面来看看在main中如何使用SD的操作函数的具体流程。
r = SD_Init();
if ( XST_SUCCESS != r ){
printf("fail to open SD\n\r");
return 1 ;
}
printf("OK to open SD\n\r");
初始化SD卡。
SD_Transfer_write(FILE,(void *)src_str,(MAX_LEN));
printf("write done SD\n\r");
向FILE中写入buffer里的数据。
SD_Transfer_read(FILE,(void*)dst_str,(MAX_LEN));
printf("read done SD\n\r");
从FILE中读出数据,写入BUFFER。