SSブログ

[電子工作] ATxmega (E series)にFatFsを組み込む(USART-SPI) [電子工作]

FatFs R0.12bのATxmega Eシリーズへの組み込みです。

サンプルプロジェクトの、avr/srcから以下のコードを持ってきてベースとします

diskio.h -> 使用しない機能の設定
ff.c -> そのまま使う
ff.h -> そのまま使う
ffconf.h -> 下記の構成設定
integer.h -> そのまま使う
mmc_avr_usart.c -> XMEGA EシリーズのDMA化する

今回はとりあえず読めればいいので、以下の最小構成としました。

ffconf.h
_FS_READONLY = 1 (read only)
_FS_MINIMIZE = 1 (opendir, readdirを使いたいので)
_USE_STRFNUC = 0
_USE_FIND = 0
_USE_MKFS = 0
_USE_FASTSEEK = 0
_USE_EXPAND = 0
_USE_CHMOD = 0
_USR_LABEL = 0
_USE_FORWARD = 0
_USE_LFN = 0
_FS_RPATH = 0

_VOLUMES = 1
_STR_VOLUME_ID = 0
_MULTI_PARTITION = 0
_USR_TRIM = 0
_FS_NOFSINFO = 0

_FS_TINY = 1
_FS_EXFAT = 0
_FS_NORTC = 1
_FS_LOCK = 0
_FS_REENTRANT = 0

diskio.h
_USE_WRITE = 0
_USE_IOCTL = 0
_USE_ISDIO = 0

---------------------------------------------------------------

対応のメインはmmc_avr_usart.cです。
Chan氏のサンプルではAVR MEGA系(1284P)のUSART-SPIの実装になっています。

編集する箇所のサマリは下記になります。

power_on()
 USART-SPIとEDMAの有効化を設定(後述)

power_off()
 USART_SPIとEDMAの無効化を設定(後述)

xchg_spi()
 USART-SPIへのデータ送信&受信(1byte)(後述)
 受信のときはダミーデータ(0xff)を送る

rcvr_spi_multi()(後述)
 DMA化のキモ
 指定された回数だけ、ダミー値(0xFF)を送信してからデータを受信します。

xmit_spi_multi()
 今回はread onlyなので関数ごと削除
 なお、対応自体はrcvr_spi_multiとほぼ同じ。

disk_status(), disk_initialize(), disk_read()
 サンプルでは、CompacfFlashCardとSD-Card(MMC)のそれぞれをdiskio.cで
 呼び分けるようになっています。CFは不要なので、mmc_avr_usart.cにある
 関数"mmc_disk_xxx()"の名前を"disk_xxx()"に変更して直接呼ぶようにします。
 それぞれの関数の第一引数に"BYTE pdrv"を追加して、
 pdrv != 0だったらエラーリターンするよう一応ガードしておきます。

disk_timerproc()
 適当なタイマで100Hzの定期割込みを作って呼ぶようにする。
 WriteProtectとCardSenseを接続しない場合は状態チェックのコードを削除します。

---------------------------------------------------------------

ではいよいよ対応の詳細に行きます。

XMega EのUSART-SPI対応

XMega EにはUSARTC0, USARTD0の2つのUSARTがあります。
今回はUSARTD0側を使いました。
また、ピンアサインの都合で、PORTD[5:7]にリマップしています。
SSはPORTD4を割り当てます。

 PORTD4 : SPI-SS -> Output, High
 PORTD5 : SPI-SCK -> Output, Low
 PORTD6 : SPI-MISO -> In, 外部抵抗でプルアップ
 PORTD7 : SPI-MOSI -> Output, High

USART-SPIの有効化/無効化の設定は以下のようになります。

power_on()関数にて
{
	PORTD.DIRSET   = PIN4_bm;
	PORTD.OUTSET   = PIN4_bm;

	PORTD.DIRSET = PIN5_bm | PIN7_bm;
	PORTD.OUTCLR = PIN5_bm;
	PORTD.OUTSET = PIN7_bm;

	PORTD.DIRCLR = PIN6_bm;

	PORTD.REMAP = PORT_USART0_bm;

	/* Setup USART D0 as MSPI mode */

	/* SPI Mode 0, MSB first */
	USARTD0.CTRLC = USART_CMODE_MSPI_gc;

	USARTD0.CTRLB = USART_TXEN_bm | USART_RXEN_bm;

	USARTD0.BAUDCTRLA = 63; /* 100kHz */


power_off()関数にて
	USARTD0.CTRLB     = 0;

	PORTD.OUTSET = PIN4_bm;


1バイト送信&受信は以下の流れになります。

「送信可能(DREIF = 1)か確認する」->「DATAに書き込む」
 ->「受信完了(RXCIF = 1)を待つ」->「DATAから読む」

static
BYTE xchg_spi (		/* Returns received data */
	BYTE dat		/* Data to be sent */
)
{
	while ( !(USARTD0.STATUS & USART_DREIF_bm));
	USARTD0.DATA = dat;
	while ( !(USARTD0.STATUS & USART_RXCIF_bm));
	return USARTD0.DATA;
}


ここで、とりあえずrcvr_spi_multi()関数を上記のxchg_spi()の処理を繰り返すように実装すれば、USART-SPIを用いたSD-Cardアクセスが動きます。

rcvr_spi_multi()関数のDMA化については長くなってきたので別記事に分けます。

nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。