自作電子小物/TIPS/簡易SDカードサポート/PSoC

 
 

サイプレスセミコンダクタ社のマイクロコントローラPSoC1シリーズ用の、最低限の機能に絞ったSDカードの入出力サブルーチンです。PSoC DesignerのSD/MMCカードサポートモジュールの代わりとして作りました。FATファイルシステムを含んだ機能を持っていますので、これだけでSDカードへのファイル読み書きが出来る様になります。

2010.1.22 PIC18版も追加2010.7.16 AVR版も追加

Easy SDcard FAT Library for PSoC1

2009年12月29日

主な仕様

 物理インタフェース: SPI(SCLK=100kHz〜400kHz) と1ビットポート(CS pin)

 SDカード: 2GB以下、MMC,SDHC,SDXCは未対応

 通信方法: SPIモード、誤り検出(CRC)&再試行有り

 記録フォーマット: マスタブートレコードの付いたFAT12とFAT16ファイルシステム(※1)

     扱えるファイルはルートディレクトリ直下のショートファイル名(8.3)のみ

 多重使用: 1パーティション(ボリューム)下のnファイル同時オープン、マルチタスク不可

 対応CPU: Cypress社CY8C29466,CY8C29666

 開発環境: PSoC Designer 5 Service Pack 6(Build 1127), ImageCraft C compiler 7.02.004(free version)

 使用プログラムメモリ量: 読込みのみ=8.6k、書込み=11.9k、最大=13.5kバイト/最適化なし

 使用データメモリ量: 668バイト

 処理速度: 約2kバイト/秒(SCLK=400kHz,CPU=12MHz,レコード長100バイト時の参考)

 API (アプリケーションプログラムインタフェース、UNIXのシステムコールに似せています)

   
一般
int sd_mount(void);
int sd_unmount(void);
int sd_open(char *filename, int oflags, int attr);
int sd_close(int fd);
int sd_read(int fd, char *buf, int bufsize);
int sd_write(int fd, char *buf, int bufsize);
int sd_lseek(int fd, long offset, int whence);
int sd_sync(int fd);
int sd_unlink(char *filename); 
通常のコール順は、sd_mount() → sd_open() → sd_read(),sd_write() → sd_close() → sd_unmount() です。sd_syncはクローズと同じく書込みを確定させます。極端にコールしすぎると、通常の磁気ディスクと違い、メディアの寿命が縮む(書込み回数制限に達する)ので要注意です。

   
ディレクトリ操作
SD_DIR *sd_opendir(char *dirname);
struct sd_dirent *sd_readdir(SD_DIR *dirp);
int sd_readdir_r(SD_DIR *dirp, struct sd_dirent *entry, struct sd_dirent **result));
long sd_telldir(SD_DIR *dirp);
void sd_seekdir(SD_DIR *dirp, long loc);
void sd_rewinddir(SD_DIR *dirp);
int sd_closedir(SD_DIR *dirp);
int sd_dirfd(SD_DIR *dirp);

   
タイムスタンプ操作
SD_SET_DATE(year,month,day)
SD_SET_TIME(hour,min,sec) 
このAPIで逐次日時を設定する事で、ファイルのタイムスタンプが正しく設定されます。

 (char *)は文字列リテラルを直接指定すると正しく動きません。ROMにバインドされないようにして下さい。


注意:

1 基本的には、SDカードの規格を決めているSDアソシエーションが提供するユーティリティ・SDフォーマッターをお使い頂き、FAT16で初期化して下さい。Windows用、Mac用の両方があります。Windows自体が持つフォーマット機能を使用する場合は、FAT32にならない様に注意して下さい。Mac OS Xの付属のディスクユーティリティは、FAT16でフォーマットが出来ないようです。2GB以下のSDカード購入時のフォーマットはFAT16になっている事がほとんどのようなのでそのまま使えると思います。


ダウンロード

関連ソース全てとサンプルプログラムが入ったPSoC Designer 5プロジェクトファイル

Easy_SDcard_FAT_Library_for_PSoC1_files/SDcm01c_sample.zip
SDcm01c_sample.zip(560kB) V0.1c(2010.4.2更新)

 sd_config.hでSD_OPT_STRING_Hオプションを有効にした場合、既存ファイルをオープン出来ない事がある不具合を対応しました。ファイルにアーカイブ属性が付いていたりすると発生します。

ソースコードはPSoC1,PIC18版で同一です。#defineでプロセッサの違いを認識し、適したコードがコンパイルされるようになっています。


サンプルの動かし方

・回路は下の物を用意。

・ダウンロードしたファイルを、適当なディレクトリに展開し、PSoC Designerでプロジェクトとして開く。

・プロジェクトメニューからビルド。

・電源3.3Vを与える。

LEDが最初全て点灯し、処理が進むにつれ消灯位置がずれていきます。

動かない場合は、電源ラインの変動を確認してみて下さい。BOR等が発生していたり、誤動作していたりする事があります。


ユーザアプリケーションプログラムでの使い方

(1)PSoC DesignerでSPIユーザモジュールとLEDユーザモジュールを配置し、名前をそれぞれSD_SPI, SD_CSに変更。また、以下の画面イメージを参考にしてプロパティを設定。

(2)必要となるソース・ヘッダファイルをプロジェクトディレクトリにコピーしておき、プロジェクトメニューから、このソースファイルを全部ADDします。ソースツリーに表示されます。

(3)sd_config.hを修正。必要なオプションの#defineを有効/無効にする。

(4)以上でビルド出来る様になる。

ソースファイル

sd_L1.c

sd_L2.c

sd_L3.c

sd_common.c

delay.c

ヘッダファイル

sd_config.h

sd.h

sd_L1.h

sd_L2.h

sd_L3.h

sd_common.h

delay.h



なぜ、これを作ったか?

以前、 PSoC DesignerにはSD/MMCカードサポートモジュールと言う物が用意されており、とても簡単にSDカード上のファイルを扱う事が出来ました。所が、最近のバージョンになってモジュール一覧に出てこなくなってしまいました。理由はハッキリしませんが、Cypress社が意図的に使えなくしたとの事です。でも、過去に作った配置済みのプロジェクトを開いたりビルドする事は可能で、モジュール機能自体が削除されているものでもないようです。過去のプロジェクトを使い回せばモジュールを利用し続ける事は可能なのですが、Cypress社の本意ではないでしょうし、いつ完全に削除されるか分りません。逆に再サポートされる可能性もありますが、待てど暮らせどアナウンスはありません。

Cypress社以外が提供するPSoC用のSDカード機能も見つけられず、悶々とした日々を過ごしていました。思い切って、自分で作ってしまえば悩む必要がなくなりますし、勉強になります。希望的にはROMサイズが減れば言う事ありません。SPIは難しくはありませんが、その後のファイルシステムを解釈する部分が大変です。20年以上前、8インチフロッピーディスクを使った簡単なDOSを作る過程でFATにアクセスするロジックを作った事があったので、時間さえあれば何とかなるのではないかと考え、チャレンジした次第です。


クロックSCLKについて

SDカードの仕様では、セットアップ中は100〜400KHzに制限されています。セットアップフェーズが済んだら、フルスピードに切り替える必要がありますが、動的にクロック数を変更するエレガントな方法(デバイス依存を少なくしたい)が思いつかなかったので、このライブラリでは、常時この速度となっています。手持ちの3種類のメディアで試した所、最初からSPIユーザモジュールの上限の4MHzに設定しても、うまく動きました。しかしSCLKを上げてもCPU性能の方がネックで、読み書きスピードはあまり向上しませんでした。


メモリ・性能について

性能よりは、省メモリにウエイトをおいたせいか、かなり低性能になってしまいました。また、以前Designerに標準搭載されていたSD/MMCカードサポートユーザモジュールの使用ROMサイズが約15kバイトだったので、大きな改善もできなかったという結果になりました。何度も、メモリを減らすコードの書き方を試行してみましたが、1日かけてソース全体を再整理しても300バイト減る程度、アセンブラで書き換える程根性もないのでなので、とりあえず諦めました。やはり、このレベルのCPUには荷が重いかもしれません。資金に余裕のある方でしたら、コード最適化の良いコンパイラに切り替えるのが一番楽です。

性能については、特に高速化を考慮しておりません。せいぜい、SDカードの読み書き回数が増えない様に、単純キャッシングする程度です。これについては、性能目的よりSDカードの書込み回数制限に対する対策です。遅さの原因は、SDカードとのデータ転送ではなく、CPUバウンドによるものです。CRC計算をソフトウエアで実装しており、これがかなりのウエイトを占めています。#defineオプションで無効化すれば〜2倍位改善できます。もっと、速くしたい場合はCPUクロックを上げるしかなく、5V電源で24MHz動作させれば2倍速になります。この時は、SDカードとのインタフェースに電圧レベル変換が必要になりますが、アマチュア的に抵抗数本で簡易的にやる方法があります。


SDカードの低電力モード移行について

本ライブラリのように、SPIでSDカードをアクセスする方向けの情報です。

SDカードにアクセスしていない(SCLKが発生していない)状態では、自動的に低電力動作(スリープとかスタンバイモードとかで表現)に入る記述(SDカードのデータシート)があったのですが、実際やってみると10mA位流れていました。DesignerのSDカードユーザモジュールでは10μA程度まで落ちる事は判っていたので、低電力動作状態に移行してはいません。何か足りないという事です。SDカードの仕様書が完全版ではないためか、ずっと悩んでおりました。

そんな時、タイミング関係で試行錯誤しているうちに、偶然低電力状態になりました。変えたのは、最後のデータを送信・受信してから、CSをインアクティブにする前に1バイトの捨てデータを送信するようにした事でした。単に1バイト送信分の時間を待っても低電力状態にはなりませんでした。SCLKとCSの関係だけの事なのか、SPIの特性なのか、実際流れるデータが関係しているのか、正確な原因は判っていませんが、同様に悩んでいる方がおられるのであれば参考に。


権利関係

GPL v3に準じます。0から書き起こしましたので、他から流用したソース部分はありません。SDカード・FAT仕様の情報源については、次の3つの公開情報を元にしています。英文のため誤読の可能性が高い上、SDカードの仕様書が概略版で、タイミング関係が不明だったため試行錯誤での開発となりました。よって正しい実装とは言えませんので、重要な場面では使わないようにした方が良いと思います。

SD Specifications, Part 1, Physical Layer, Simplified Specification, Version 2.00, September 25, 2006 <www.sdcard.org /developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf>

Microsoft Extensible Firmware Initiative, FAT32 File System Specification, FAT: General Overview of On-Disk Format Version 1.03, December 6, 2000 <www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx>

どちらも英文。FAT仕様は標準化されていませんので、使われている場面の多さでMicrosoftの情報に従うのがよろしいと考えました。

マスターブートレコード構造

<http://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%96%E3%83%BC%E3%83%88%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89>