Porting Fatfs File System To KL26 SPI SD Code
Porting Fatfs File System To KL26 SPI SD Code
1 Abstract
Without the SDHC module, Kinetis KL series need to use the SPI interface to communicate
with the SD card. Normally, when customer use the SD card, they are not only want to write and
read the SD card, but also prefer to create files(eg, text file, csv file,etc.) in the SD card to record
some important data. Use the file to record the data, then the data can be read easily by the PC.
MCU need to use the file system to operate the files, the file system should realize the function of
file creating, file deleting, file reading and writing, etc. FatFs is a generic FAT/exFAT file system
module for small embedded systems. This document mainly describe how to port a FatFs file
system to the KL26 SPI SD card code, SD card SPI interface hardware circuit and the SD card
basic operation code.
2 FatFs file system introduction
2.1 FatFs feature
Windows compatible FAT/exFAT file system.
Platform independent. Easy to port.
Very small footprint for program code and work area.
Various configuration options to support for:
o Multiple volumes (physical drives and partitions).
o Multiple ANSI/OEM code pages including DBCS.
o Long file name in ANSI/OEM or Unicode.
o exFAT file system.
o RTOS envilonment.
o Fixed or variable sector size.
o Read-only, optional API, I/O buffer and etc...
2.2 FatFs file system organizations
From the above pictures, we can see that in a project with Fatfs module, there mainly 4 parts:
application, Fatfs, Disk I/O layer and the Media(SD card).
(1) Application, user just need to call the FatFs API function to realize the file creation, read,
write and delete.
(2) FatFs module, this module contains 6 important files which customer need to use, it is:
diskio.c, diskio.h, ff.c, ff.h, ffconf.h, integer.h. diskio.c and diskio.h is used to call the SD card
operation function from the Disk I/O layer, user need to modify this file to match the disk I/O
layer, or write the disk I/O layer match this file. ff.c,ff.h is the FatFs file system layer, it defines
1
the API function, user don’t need to modify it. ffconf.h is the system configuration file. integer.h
is the data type define file, user don’t need to modify these two files.
(3) Disk I/O layer, there has mmc.c and spi.c, actually, the detail name can be defined by the
user, it is not fixed. Mmc.c is used to realize the SD card function, eg, SD initialization, SD block
writing and reading. Spi.c is the MCU SPI interface file, it realize the SPI communication
function, because the Kinetis series don’t have the SDHC interface, then it use the SPI interface
to communicate with the SD card.
(4) Media, it can be SD,MMC, USB, NAND flash, here we use the SD card.
More details, please refer to FatFs Module application note.
2.3 Common API function
f_mount - Register/Unregister a work area of a volume
f_open - Open/Create a file
f_close - Close an open file
f_read - Read data
f_write - Write data
f_lseek - Move read/write pointer, Expand size
f_truncate - Truncate size
f_sync - Flush cached data
More functions, please go to this link: http://elm-chan.org/fsw/ff/00index_e.html
3 SPI SD operation
3.1 Hardware
This document use the YL_KL26 as the testing board, customer also can add an external SD
card circuit to the FRDM-KL26 board.
2
The pin assignment in the YL-KL26 board is defined as follows:
KL26 pin SPI name
PTC4 SPI_CS0
PTC5 SPI_SCK
PTC6 SPI_MOSI
PTC7 SPI_MISO
3.2 Softwave
The test code project is based on the MDK5.1x.
3.3 SD I/O Layer
3.3.1 SD card initialization
The communication speed for SD card initialization can’t exceed 400kb/s, if the speed is
higher than 400kbps, user need to add the delay in the initialization code, otherwise the
initialization will be failure. After the initialization is successful, user can increase the SD card
communication speed.
Initialization process:
(1) Initialize the SPI interface which connect to the SD card, down to low speed.
(2) Power on delay 72clks, wait for the SD card ready
(3) Go idle state, CMD0, this command will trigger the SD card to use the SPI interface.
(4) Get SD card information, CMD8, get the SD card version.
(5) Active the SD card, with CMD55+CMD41
(6) Read OCR data,CMD59.
(7) Set SD card block size to 512Byte. CMD16
(8) Read CSD, get other information, CMD9
(9) Change to high speed and disable the CS
uint8 MMCInit(void)
{
uint8 i = 0,k = 0,tmp = 0;
uint16 cnt=0;
uint8 buff[512];
if(k == 0)
{
MMCCS(1); //cs pullup, disconnect
Send_Byte(0xFF);
printf("\n SD reset fail");
return 1;//
}
//get SD card version
tmp = MMCWriteCmd( CMD8,0x1AA,0x87 );
printf( "SD_CMD8 return %d........\n\n", tmp );
if(tmp == 1)// 2.0 card
3
{
cnt=0xffff;
do
{
MMCWriteCmd( CMD55, 0, 0xff );
tmp = MMCWriteCmd( CMD41,0x40000000, 0xff);//CMD41
cnt--;
} while ((tmp) && (cnt));
//Get OCR information
tmp = MMCWriteCmd(CMD58, 0, 0 );
if ( tmp != 0x00 )
{
MMCCS(1); //cs pullup, SD card disconnect
printf( "\nSD_CMD58 return %d....\n", tmp );
return 1;//
}
4
for (i=0; i<512; i++)
{
buf[i] = Send_Byte(0xFF);
}
}
Send_Byte(0xFF);
Send_Byte(0xFF);
MMCCS(1);
return 0;
}
3.3.3 Read multiple SD card block
uint8 MMCReadMultipleBolck(uint32 addr,uint8 *buf,uint8 count)
{
uint16 i;
if(SD_Type!=SD_TYPE_V2HC)
{
addr= addr<<9;
}
if (MMCWriteCmd(CMD18,addr,0xFF) != 0x00)
{
return 1;
}
MMCCS(0);
do
{
while (Send_Byte(0xFF) != 0xFE){;}
for (i=0; i<512; i++)
{
*buf++ = Send_Byte(0xFF);
}
Send_Byte(0xFF);
Send_Byte(0xFF);
}while (--count);
MMCCS(1);
MMCWriteCmd(CMD12,0x00,0xFF);
Send_Byte(0xFF);//delay
return 0;
}
3.3.4 Write one SD card block
The procedure is:
(1) Send CMD24 and wait the response
(2) Receive the start token 0XFE
(3) Send the 512Byte data
(4) Send 2 bytes CRC
(5) Disable the CS pin
if(SD_Type!=SD_TYPE_V2HC)
{
addr=addr<<9 ;
}
if (MMCWriteCmd(CMD24,addr,0x01) != 0x00)
{
return 1;
}
MMCCS(0);
//wait SD card ready
Send_Byte(0xFF);
5
Send_Byte(0xFF);
Send_Byte(0xFF);
Send_Byte(0xFE);
if (MMCWriteCmd(CMD18,addr,0xFF) != 0x00)
{
return 1;
}
MMCCS(0);
do
{
while (Send_Byte(0xFF) != 0xFE)
{
;
}
Send_Byte(0xFF);
Send_Byte(0xFF);
}while (--count);
MMCCS(1);
MMCWriteCmd(CMD12,0x00,0xFF);
Send_Byte(0xFF);//delay
return 0;
}
6
4 FatFs file system porting
4.1 FatFs source code download
Go to FatFs official website download the source code, the link is:
http://elm-chan.org/fsw/ff/00index_e.html
The latest version is FatFs R0.12.
download
Unzip it, like the following picture, just need 6 files, user can copy it to the project SPI driver
folder, and create a new folder named as fatfs.
Useful files
7
4.2 Modify diskio.c file
We need to modify these functions:
disk_initialize:Disk initialize
disk_status :Get the Disk status
disk_read :Read Disk block
disk_write :Write Disk block
disk_ioctl :control device character
get_fattime :Get current time
4.2.1 disk_initialize function
DSTATUS disk_initialize (
BYTE pdrv
)
{
DSTATUS stat;
stat=MMCInit(); //SD card initialization
if(stat == STA_NODISK)
{
return STA_NODISK;
}
else if(stat != 0)
{
return STA_NOINIT;
}
else
{
return 0;
}
}
if(pdrv)
{
return STA_NOINIT;
}
return RES_OK;
}
4.2.3 disk_read function
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res;
if (pdrv || !count)
{
return RES_PARERR;
}
if (count == 1)
{
res = MMCReadSingleBolck(sector,buff);
}
else
8
{
res = MMCReadMultipleBolck(sector,buff,count);
}
if(res == 0x00)
{
return RES_OK;
}
else
{
return RES_ERROR;
}
}
4.2.4 disk_write function
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
if (pdrv || !count)
{
return RES_PARERR;
}
if(count == 1)
{
res = MMCWriteSingleBlock(sector, buff);
}
else
{
res = MMCWriteMultipleBlock(sector, buff, count);
}
if(res == 0)
{
return RES_OK;
}
else
{
return RES_ERROR;
}
}
9
{
if((csd[0] >> 6) == 1) /* SDC ver 2.00 */
{
csize = csd[9] + ((WORD)csd[8] << 8) + 1;
*(DWORD*)buff = (DWORD)csize << 10;
}
else /* MMC or SDC ver 1.XX */
{
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
*(DWORD*)buff = (DWORD)csize << (n - 9);
}
res = RES_OK;
}
break;
case GET_SECTOR_SIZE : /* Get sectors on the disk (WORD) */
*(WORD*)buff = 512;
res = RES_OK;
break;
case GET_BLOCK_SIZE :
if ((MMCWriteCmd(0x49,0x00,0x95) == 0) && MMCCSD_CID(0x49, csd)) /* Read CSD */
{
*(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
res = RES_OK;
}
break;
return res;
}
4.2.6 Get_fattime function
This function is used to get the current time, and write it in the file attribute when create, modify
the files. It should associate with the RTC, this project didn’t add this function, so just write the
code like this:
DWORD get_fattime (void)
{
return 0;
}
10
int main (void)
{
uint16 i,j;
FATFS fs;
FRESULT fr;
FIL fil;
UINT bw;
char file_name1[12]="Test.csv";
char file_name2[12]="Test.txt";
System_init();
spiInit(SPI0_BASE_PTR , Master);
fr= f_mount(&fs,file_name1,0);
if(fr)
{
printf("\nError mounting file system\r\n");
for(;;){}
}
fr = f_open(&fil, file_name1, FA_WRITE | FA_OPEN_ALWAYS);//create csv file
if(fr)
{
printf("\nError opening text file\r\n");
for(;;){}
}
fr = f_write(&fil, "Test1 ,Test2 ,Test3 ,Test4 \r\n", 29, &bw); //write data to the excel file
if(fr)
{
printf("\nError write text file\r\n");
for(;;){}
}
fr = f_close(&fil);
if(fr)
{
printf("\nError close text file\r\n");
for(;;){}
}
fr= f_mount(&fs,file_name2,0);
if(fr)
{
printf("\nError mounting file system\r\n");
for(;;){}
}
fr = f_open(&fil, file_name2, FA_WRITE | FA_OPEN_ALWAYS);//create txt file
11
if(fr)
{
printf("\nError opening text file\r\n");
for(;;){}
}
fr = f_write(&fil, "Test1 ,Test2 ,Test3 ,Test4 \r\n", 29, &bw); //write data to the txt file
if(fr)
{
printf("\nError write text file\r\n");
for(;;){}
}
fr = f_close(&fil);
if(fr)
{
printf("\nError close text file\r\n");
for(;;){}
}
while(1)
{
for(i=0;i<10;i++) for(j=0;j<65535;j++);
printf("\ntest_sd\n");//
}
}
#include "spi.h"
#include "SD.h"
#include "diskio.h"
#include "ff.h"
5 Test result
After download the code to the KL26 board, then insert a 8G microSD card which already
format with the Fat32, press the reset button on the board, user can find the following printf log
from the com port:
12
It means the SD card is identified.
Now, take out the SD card and insert it to the PC, user will find there has two files: Test.csv
and Test.txt. Open these files, data Test1, Test2, Test3, Test4 can be find in it, it means the FatFs
file system is porting successfully.
13