R8CでSDカード

さて、LCDも何とか動くようになったので、避けては通れないSDカードのアクセス
をやってみたいと思います。

先日 Flash が64Kある事が判ったので、RAM容量は心細いですが、
SDカードアクセスに不安はありません。
組み込みでSDカードと言ったら ChaN さんでしょうー、えるむさんが実装して、ソース
を公開しているSDカードのソリューションは非常に柔軟性があり、細部まで良く考えら
れており、組み込みマイコンにおけるSDカードスタンダードだと思います。
少ないリソースでも動作するように、プチ fatfs もあり、今回のR8Cに最適な
ソリューションです。(感激!感謝です!)

SDカードですが、FlashAir を使えるように、標準SDカードソケットを使います。
標準SDカードソケットなら、直接ユニバーサル基板にハンダ付けできますが、スイッチ
関係のパッドが狭く、その部分は、絶縁テープで保護して、直接配線します。
SDカードソケットは、ヒロセ製(DM1B-DSF-PEJ)を使いました。
このソケットは、価格は高いですが、機能と品質が非常に優れています。

事前に考えておかなければならない点として、ポートにどのように、各信号を割り当てる
かです。
まず・・
・「/RESET(3)」は、ポートにも割り当てが出来るけど、一応キープ。
・「MODE(8)」端子は当然のようにキープ。
・「TXD(16)、RXD(15)」もシリアル通信で必須なのでキープ
・「AN0(20)、AN1(19)、AN2(18)、AN3(17)」は、とりあえずキープ
・「XIN(6)」は、高精度なクロックを入れて使う場合があるのでキープ
・「TRJIO(13)」は、周期測定用としてキープ

// P4_2(1):   LCD_SCK  ,SD_CLK(5)
// P3_7(2):   LCD_/CS
// /RES(3):  (System reset)
// P4_7(4):            ,SD_DO/DAT0(7)
// VSS:(5)   (Power GND)
// P4_6(6):   XIN (高精度なクロック用)
// VCC(7):   (Power +V)
// MODE(8):  (System mode)
// P3_5(9):   I2C_SDA
// P3_4(10):           ,SD_/CS(1)
// P1_0(20):  AN0 (keep)
// P1_1(19):  AN1 (keep)
// P1_2(18):  AN2 (keep)
// P1_3(17):  AN3 (keep)
// P1_4(16):  TXD0
// P1_5(15):  RXD0
// P1_6(14):  LCD_A0 (share)
// P1_7(13):  TRJIO (keep)
// P4_5(12):  LCD_SDA  ,SD_DI/CMD(2)
// P3_3(11):  I2C_SCL

こんな感じになりました、これで、ほぼ全てのポートが埋まりました。
「P1_6(16)」は、Flash 書き込み時に使うので注意が必要です。
※無難な、LCD_A0(コマンド/データ切り替え信号)にしています。
※AN0、AN1、AN2、AN3 はアプリによって自由に使えるポートとしています。
IMG_0751s
※電源は3.3Vで動かします!
R8Cは3.3Vで動かしても、20MHzで動作します、フラッシュプログラムも問題なくできます。

ぷち FatFsはソースコードを展開して、pffconf.h で基本的な設定を行います。

/*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/

#define	_USE_READ	1	/* Enable pf_read() function */
#define	_USE_DIR	1	/* Enable pf_opendir() and pf_readdir() function */
#define	_USE_LSEEK	1	/* Enable pf_lseek() function */
#define	_USE_WRITE	1	/* Enable pf_write() function */

#define _FS_FAT12	1	/* Enable FAT12 */
#define _FS_FAT16	1	/* Enable FAT16 */
#define _FS_FAT32	1	/* Enable FAT32 */

とりあえず、全て「1」で良いでしょう。
FAT12、FAT16 は「0」でも問題は少ないですが、古いSDカードは「FAT12」や「FAT16」
でフォーマットされており、それらを使う必要があるなら「1」にする必要があります、
但し、実行バイナリーは多少大きくなります。(おおよそ1Kバイト増加)
※FAT32でフォーマットをやり直せば、使える物もあるかと思います。

/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/

#define _USE_LCC	1	/* Allow lower case characters for path name */

#define	_CODE_PAGE	932

「_USE_LCC」を「1」にして
コードページは932にしておきます。

Sample プロジェクトの generic を参考に、「diskio.c」シリアル/パラレル変換の部分を書き換えます。
自分のシステムでは、I/O ポートの制御部分は C++ のクラスで構成されているので、
「diskio.cpp」として、メインのポート定義「port_def.hpp」を使って、実装します。
※port_def で宣言しているポートクラスの実体は、「diskio.cpp」で宣言していますが、
このクラスは、最適化されインラインで組み込まれるものと思います。
他に、「マイクロ秒」単位の時間待ちルーチンが必要で、「common/delay.hpp」に該当する
関数があるので、それを使います。
※「utils::delay::micro_second(n);」

// マイクロ秒単位の、「時間待ち」
static void dly_us(unsigned int n)

/*-----------------------------------------------------------------------*/
/* Transmit a byte to the MMC (bitbanging)                               */
/*-----------------------------------------------------------------------*/
static void xmit_mmc(BYTE d)

/*-----------------------------------------------------------------------*/
/* Receive a byte from the MMC (bitbanging)                              */
/*-----------------------------------------------------------------------*/
static BYTE rcvr_mmc(void)

/*-----------------------------------------------------------------------*/
/* Receive a byte from the MMC (bitbanging)                              */
/*-----------------------------------------------------------------------*/
static BYTE rcvr_mmc()

基本的に以上の4つの関数を実装すれば良く、他に、元のソースでは、コマンド
の定義を、「#define」で行っていたので、「static const BYTE」に換えました、C++
では、この定数は、コンパイル時にのみ使われ、メモリー上に置かれる事はありません。

これで完了です。
簡単なテストとして、カードをマウントして、ディレクトリーをリストしてみます。

    FATFS fatfs;
    bool mount = false;
    // pfatfs を開始
    {
        if(pf_mount(&fatfs) != FR_OK) {
            sci_puts("SD mount error\n");
        } else {
            sci_puts("SD mount OK!\n");
            mount = true;
        }
    }

    if(mount) {
        DIR dir;
        if(pf_opendir(&dir, "") != FR_OK) {
            sci_puts("Can't open dir\n");
        } else {
            for(;;) {
                FILINFO fno;
                // Read a directory item
                if(pf_readdir(&dir, &fno) != FR_OK) {
                    sci_puts("Can't read dir\n");
                    break;
                }
                if(!fno.fname[0]) break;

                if(fno.fattrib & AM_DIR) {
                    utils::format("          /%s\n") % fno.fname;
                } else {
                    utils::format("%8d  %s\n") % static_cast<uint32_t>(fno.fsize) % fno.fname;
                }
            }
        }

SD_test_0

GitHub R8C

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください