以前的MCU要PO FAT可說是個大工程
但現在很多原廠都有提供FAT lib
使用都很少需要在自已去了解FAT的部份
但如果真的有問題時
就只能等待原廠的回應嗎?
FATFS 這個網站的作者
提供了FAT系統
符合ANSI C 的標準
所以在移植上非常的容易
而且所有sourde code都是開放的
可用於商業行為
FATFS 對RAM的需求比較高,但功能較完整
能Mount SDC/CF/HD/USB.....等裝置
Petit FAT 是簡易版,對RAM和ROM的要求較小
但在寫檔方面的限制是
只能取代原檔案內的內容
不能開新檔案
Petit FAT移植範例:
在原文件中提到移植Petit FAT
需使用者完成三個API
1. disk_initialze
2. disk_readp
3. disk_writep
另integer.h也是需要注意的地方
但基本上是不需要做修改的
PFF.h是功能定義的設定檔
首先了解SD/MMC是使用SPI方式做溝通
SPI Mode0 /Mode3 二種都可
在來就是實作需要的三個API
1. disk_initialze
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (void)
{
BYTE n, cmd, ty, ocr[4];
UINT tmr;
#if _USE_WRITE
if(CardType && MMC_SEL)
disk_writep(0, 0); /* Finalize write process if it is in progress */
#endif
init_spi(); /* Initialize ports to control MMC */
DESELECT(); //SPI CS = H
for(n = 10; n; n--)
spi_wr(0xFF); /* 80 dummy clocks with CS=H */
ty = 0;
if(send_cmd(CMD0, 0) == 1) /* Enter Idle state */
{
if(send_cmd(CMD8, 0x1AA) == 1) /* SDv2 */
{
for(n = 0; n < 4; n++)
ocr[n] = spi_wr(0xFF); /* Get trailing return value of R7 resp */
if(ocr[2] == 0x01 && ocr[3] == 0xAA) /* The card can work at vdd range of 2.7-3.6V */
{
for(tmr = 10000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) /* Wait for leaving idle state (ACMD41 with HCS bit) */
DELAY_100u();
if(tmr && send_cmd(CMD58, 0) == 0) /* Check CCS bit in the OCR */
{
for(n = 0; n < 4; n++)
ocr[n] = spi_wr(0xFF);
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */
}
}
}
else
{ /* SDv1 or MMCv3 */
if (send_cmd(ACMD41, 0) <= 1)
{
ty = CT_SD1;
cmd = ACMD41; /* SDv1 */
}
else
{
ty = CT_MMC;
cmd = CMD1; /* MMCv3 */
}
for (tmr = 10000; tmr && send_cmd(cmd, 0); tmr--)
DELAY_100u(); /* Wait for leaving idle state */
if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */
ty = 0;
}
}
CardType = ty;
DESELECT();
spi_wr(0xFF);
return ty ? 0 : STA_NOINIT;
}
2. disk_readp/*-----------------------------------------------------------------------*/
/* Read partial sector */
/*-----------------------------------------------------------------------*/
/* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */
/* Sector number (LBA) */
/* Byte offset to read from (0..511) */
/* Number of bytes to read (ofs + cnt mus be <= 512) */
DRESULT disk_readp(BYTE *buff,DWORD lba,WORD ofs,WORD cnt)
{
DRESULT res;
BYTE rc;
WORD bc;
if(!(CardType & CT_BLOCK))
lba *= 512; /* Convert to byte address if needed */
res = RES_ERROR;
if(send_cmd(CMD17, lba) == 0) /* READ_SINGLE_BLOCK */
{
bc = 40000;
do{ /* Wait for data packet */
rc = spi_wr(0xFF);
} while (rc == 0xFF && --bc);
if(rc == 0xFE) /* A data packet arrived */
{
bc = 514 - ofs - cnt;
/* Skip leading bytes */
if(ofs)
{
do spi_wr(0xFF); while (--ofs);
}
/* Receive a part of the sector */
if(buff)
{ /* Store data to the memory */
do{
*buff++ = spi_wr(0xFF);
} while (--cnt);
}
else
{ /* Forward data to the outgoing stream (depends on the project) */
// do{
// FORWARD(spi_read());
// } while (--cnt);
}
/* Skip trailing bytes and CRC */
do spi_wr(0xFF); while (--bc);
res = RES_OK;
}
}
DESELECT();
spi_wr(0xFF);
return res;
}
3. disk_writep/*-----------------------------------------------------------------------*/
/* Write partial sector */
/*-----------------------------------------------------------------------*/
/* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */
/* Number of bytes to send, Sector number (LBA) or zero */
#if _USE_WRITE
DRESULT disk_writep (const BYTE *buff,DWORD sa)
{
DRESULT res;
WORD bc;
static WORD wc;
res = RES_ERROR;
if(buff)
{ /* Send data bytes */
bc = (WORD)sa;
while (bc && wc)
{ /* Send data bytes to the card */
spi_wr(*buff++);
wc--; bc--;
}
res = RES_OK;
}
else
{
if(sa)
{ /* Initiate sector write process */
if(!(CardType & CT_BLOCK))
sa *= 512; /* Convert to byte address if needed */
if(send_cmd(CMD24, sa) == 0)
{ /* WRITE_SINGLE_BLOCK */
spi_wr(0xFF);
spi_wr(0xFE); /* Data block header */
wc = 512; /* Set byte counter */
res = RES_OK;
}
}
else
{ /* Finalize sector write process */
bc = wc + 2;
while (bc--)
spi_wr(0); /* Fill left bytes and CRC with zeros */
if((spi_wr(0xFF) & 0x1F) == 0x05) /* Receive data resp and wait for end of write process in timeout of 500ms */
{
for(bc = 5000; spi_wr(0xFF) != 0xFF && bc; bc--)
DELAY_100u(); /* Wait ready */
if(bc)
res = RES_OK;
}
DESELECT();
spi_wr(0xFF);
}
}
return res;
}
#endif
一樣提供source code 有IAR和KEIL二種IDE
Petit FAT for NCU122
沒有留言:
張貼留言