Top > R8C >ELMさんのFatFs

FatFs

 ELMさんが 公開されているFATファイルシステム・モジュールをR8C用に移植してみました。 FatFsは非常によくできています。少し修正するだけで様々なプラットフォームに 移植することができます。今回は以下の条件を想定します。 古いバージョンのFatFsなので多少変更がでているかもしれません。

項目条件
コンパイラKPIT GNU v0801
FatFsFatFs R0.06
メディアSD/MMC
デバイスR8C/2A
シリアルI/FUSART2
CSp6_0
DIp6_3/TXD2
DOp6_4/RXD2
CLKp6_5/CLK2
WriteProtectSWなし
CardDetectSWなし

上位レイヤI/F

        if (c == 'c') {                         /* Type is character */
               
/* どうやら、KPIT_GNUでは va_arg に char を渡すとエラーらしい。
                int に修正 */

                cc
= fputc(va_arg(arp, int), fil);
               
if (cc != EOF) cc = 1;
               
continue;
       
}

下位レイヤI/F

 下位レイヤのプログラムはELMさんのFatFsサンプルプログラム(mmc.c)を少し修正しただけです。 基本的には(Platform dependent)の項目を修正するだけです。

Port controls

ポート関連の項目です。CS信号の制御マクロを修正します。 今回、SOCKWPとSOCKINSは使用しないので適当に処理しておきます。

/* Port Controls  (Platform dependent) */
#define SELECT()        p6_0 = 0                /* MMC CS = L */
#define DESELECT()      p6_0 = 1                /* MMC CS = H */

#define SOCKPORT        p6                      /* Socket contact port */
#define SOCKWP          0x00                    /* Write protect switch (not use) */
#define SOCKINS         0x00                    /* Card detect switch (not use) */

SPI入出力

UART2モジュールを介してMMCにアクセスします。受信完了フラグRIは、 u2rbレジスタをリードしないとクリアされません。なので、 読み出し開始前にu2rbレジスタを空読みします。 また、u2rbレジスタはワードアクセスが推奨されています。

/*-----------------------------------------------------------------------*/
/* Transmit a byte to MMC via SPI  (Platform dependent)                  */
/*-----------------------------------------------------------------------*/

#define xmit_spi(dat)   u2tbl=(dat); while( txept_u2c0==0 )

/*-----------------------------------------------------------------------*/
/* Receive a byte from MMC via SPI  (Platform dependent)                 */
/*-----------------------------------------------------------------------*/

static
BYTE rcvr_spi
(void)
{
        WORD d
= u2rb.word;
        u2tbl
= 0xFF;
       
while ( ri_u2c1==0 );
       
return (BYTE)u2rb.word;
}

/* Alternative macro to receive data fast */
static
void rcvr_spi_m (BYTE* dst)
{
        WORD d
= u2rb.word;
        u2tbl
= 0xFF;
       
while ( ri_u2c1==0 );
       
*dst = (BYTE)u2rb.word;
}

Power control

今回、SD/MMCの電源管理はしないので、 UARTモジュールの初期化終了処理のみ記述しておきます。

/*-----------------------------------------------------------------------*/
/* Power Control  (Platform dependent)                                   */
/*-----------------------------------------------------------------------*/
/* When the target system does not support socket power control, there   */
/* is nothing to do in these functions and chk_power always returns 1.   */

static
void power_on (void)
{
       
for (Timer1 = 3; Timer1; );     /* Wait for 30ms */
        p6
.byte = 0x05;                 //P6[0,3]=1
        pd6
.byte = 0x6f;                //P6[0-3,5,6]出力ポート
        u2mr
.byte = _BV(SMD0);          //クロック同期式シリアルI/O
        u2brg
.byte = 0;                 //クロック分周なし
        u2c0
.byte = _BV(UFORM);         //SPI Mode0 MSB first
        u2c1
.byte = _BV(TE) | _BV(RE);  //送受信許可
}

static
void power_off (void)
{
        SELECT
();                       /* Wait for card ready */
        wait_ready
();
        release_spi
();

        u2c1
.byte = 0;                  /* Disable SPI function */
        p6
.byte = 0x00;
       
Stat |= STA_NOINIT;             /* Set STA_NOINIT */
}

static
int chk_power(void)                     /* Socket power state: 0=off, 1=on */
{
       
return 1;
}

FatFs用タイマ

今回、ライトプロテクトSWとカード検出SWは使用しないので、該当部を削除します。 また、この関数は割り込み処理から10msおきに呼び出す必要があります。

/*-----------------------------------------------------------------------*/
/* Device Timer Interrupt Procedure                                      */
/*-----------------------------------------------------------------------*/
/* This function must be called in period of 10ms                        */

void disk_timerproc (void)
{
        BYTE n
;

        n
= Timer1;             // 100Hz decrement timer
       
if (n) Timer1 = --n;
        n
= Timer2;
       
if (n) Timer2 = --n;
}

結果

以下の設定でのコンパイル後のサイズは10351バイトでした。 今回使用したソースファイルを置いておきます。

項目設定
_MCU_ENDIAN1
_FS_READONLY0
_FS_MINIMIZE0
_USE_STRFUNC0
_USE_MKFS0
_DRIVES1
_MULTI_PARTITION0
_USE_FSINFO0
_USE_SJIS1
_USE_NTFLAG1