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