[電子工作] 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()関数にて
power_off()関数にて
1バイト送信&受信は以下の流れになります。
「送信可能(DREIF = 1)か確認する」->「DATAに書き込む」
->「受信完了(RXCIF = 1)を待つ」->「DATAから読む」
ここで、とりあえずrcvr_spi_multi()関数を上記のxchg_spi()の処理を繰り返すように実装すれば、USART-SPIを用いたSD-Cardアクセスが動きます。
rcvr_spi_multi()関数のDMA化については長くなってきたので別記事に分けます。
サンプルプロジェクトの、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化については長くなってきたので別記事に分けます。
コメント 0