要約
この記事では、Secure Digital (SD)メディアフォーマットによってMAXQ2000の不揮発性データストレージを拡張する方法について検証します。
低電力で低ノイズのMAXQ2000マイクロコントローラは、幅広いアプリケーションに適しています。MAXQ2000はフラッシュメモリ内に不揮発性データを格納し、ユーザコード空間と共用する32kワード(64kB)のフラッシュ容量を備えています。しかし、読者のアプリケーションがもっと多くの不揮発性ストレージを必要とする場合はどうしますか?この記事では、Secure Digital (SD™)メディアフォーマットによってMAXQ2000の不揮発性データストレージを拡張する方法について検証します。
外部ストレージ設計の注意点
アプリケーションに関する第1の設計注意事項は、電源電圧および電流要件です。標準的なMAXQ2000のアプリケーションでは、デュアルリニアレギュレータを使って、選択した設計クロック速度に必要な最低電圧でプロセッサコアの電圧(VDD)を動作させます。MAXQ2000のVDD電源電圧は、1.8Vまで低くすることができます。MAXQ2000のI/O端子はVDDIOから供給され、VDDの許容下限範囲と3.6Vの上限を備えています。外部ストレージの許容電流消費量は電源の電流定格によって規定され、バッテリ駆動デバイスの場合は、バッテリシステムの容量によって規定されます。
第2に、外部ストレージ接続用のMAXQ2000のI/Oラインの数は、対象アプリケーションに十分な帯域幅を提供する一方で、最低本数にしておく必要があります。たとえば、Atmel社のフラッシュチップAT29LV512は、ホストマイクロコントローラとインタフェースする場合には、15本のアドレスライン、8本のデータライン、および3本の制御ラインを必要とします。MAXQ2000は外部アドレス/データバスを備えていないため、この場合、ソフトウェアがバス伝送を制御する必要があります。一部のアプリケーションでは、この方式はMAXQ2000のI/O端子の効率的な使い方ではありません。
ただし、SPI™およびI²Cベースの外部フラッシュデバイスには、3または4つのインタフェース端子しか必要ありません。MAXQ2000はハードウェアSPIモジュールを備えていますが、ユーザがソフトウェアでMAXQ2000にI²Cを実装する必要があります(すなわち、「ビットバンギング」)。この統合能力は、SPIインタフェースは外部の不揮発性ストレージにアクセスするのに不可欠な手段であることを意味します。
SDメモリカードフォーマット
SDメディアフォーマットは、多くのアプリケーションに上記の注意事項を満たす不揮発性外部メモリです。SDフォーマットは、「MultiMedia Card」フォーマット、すなわちMMCの後継フォーマットです。SDカードのメモリは、緩やかな電流要件で標準3.3Vの電源電圧で動作します。SDカードの容量の範囲は、数メガバイトから最大4GBまでです。この広範囲の利用可能な容量によって、多くのアプリケーションに十分な外部ストレージがもたらされます。
一見したところ、SDはSD独自の共用バスのためにMAXQ2000とインタフェースするのは容易ではないように見えるかもしれません。しかしながら、SDはMMCの第2バス形式SPIを継承しています。したがって、MAXQ2000はSPI用のハードウェアサポートを備えているため、インタフェースするのは容易です。
図1. MAXQ2000はSDメモリカードと容易にインタフェースします。
図1の回路図は、標準動作回路を示しています。SDカードは、フルデュープレックス、8ビットSPI動作を必要とします。データはMAXQ2000のMOSI端子からカードのDI端子にクロック入力され、カードのDOラインからMAXQ2000のMISO端子にクロック出力されます。データは、CLKラインの立上りエッジで、カードとの間で同時にクロック入力および出力されます。8個の追加クロックを各トランザクションの最後に供給し、SDカードが未処理の動作を完了するようにする必要があります。これらの追加クロックの間の入力データは、すべて1である必要があります。クロック速度は、識別フェーズ時には最高400kHzに制限する必要がありますが、SDカードが識別されると最高25MHzまで上げることができます。
MAXQ2000 SPIモジュール
MAXQ2000は、SDカードインタフェース用に容易に設定されるハードウェアSPIモジュールを備えています。クロック極性とデータ長を設定するには、SPICFレジスタをすべてゼロに設定します。これによって、SPIモジュールがクロックの立上りエッジでデータをラッチするように設定され、データ長が8ビットに設定されます。このアプリケーションの場合は、MAXQ2000のシステムクロック周波数は16MHzです。この場合、SPICKレジスタは0x28に設定され、SPIクロックは約380kHzになります。SPICNレジスタの下位2ビットを設定して、SPIマスタモードをイネーブルする必要があります。
SDのSPIデータフォーマット
SDカードのSPIプロトコルは、SDバスプロトコルに類似しています。全クロックエッジでSDカードのDO端子から有効データを受信せずに、送信するデータがないカードは、DO端子をすべて1のアイドル状態に保持します。カードがホストに返送するデータを持っている場合は、スタートビットがゼロの専用トークンがそのデータの前に送信されます。SDカードから送信されるすべてのデータは、これらのトークンの直後に送信され、固定長です。受信側が予期するバイトの数を事前に認識しているため、バイト長は応答には含まれません。さらに、開始トークンおよびデータの送信が終了するまでアイドル状態は発生しないため、すべてのデータバイトは変更なしで、プレフィックスを伴わずに送信されます。バス上のその他のトラフィックと共に、トークンはSPIトランザクションの8ビット境界で整合されます。ホストからカードへのコマンドおよびデータは同様の形式に従い、すべて1はアイドルバスを示します。ステータストークンを除く全トランザクションは、データの最後に付加される巡回冗長検査(CRC)コードによって保護されます。データの短ブロック用のCRC-7と、データの長ブロック用のCRC-16という2つのCRCアルゴリズムが提供されます。CRCはSD SPIインタフェースのオプション部分ですが、アプリケーションの制約がその利用を妨げない限り、このCRCによってデータ完全性を保証する必要があります。
巡回冗長検査
通常、CRCアルゴリズムは信頼性の低い通信経路によって引き起こされる誤りを検出するために使用されます。特定のCRCの選択は、保護されるデータサイズによって規定されます。SDメディアの場合、CRC-7およびCRC-16に特定されます。
CRCアルゴリズムは選択した除数で保護されるデータを除算して剰余を求めます。この除算はアルゴリズムで使用される多項計算により桁上げロジックなしで行われます。桁上げが不要のため、除算は論理XOR演算で達成することができます。選択した除数は通常CRCの多項式として参照されます。結果として出た剰余はその後データと共に伝送され、これを使ってレシーバは伝送中にデータが壊れていないことをチェックすることができます。
CRC-7の場合、ソフトウェアにおいて剰余は7ビットシフトレジスタを使って計算することができます。このシフトレジスタは計算を開始するときにすべてゼロに初期化されます。保護されるデータの各ビット(MSBファースト)はシフトレジスタのLSBにシフトされ、シフトレジスタのMSBはシフトアウトされ調べられます。シフトアウトされたビットが1であれば、シフトレジスタの内容はCRC-7の多項式の値0x09でXORして変更されます。シフトレジスタからシフトアウトされたビットがゼロであればXORは実行されません。保護されるデータの最終ビットがシフトインされ条件付きのXORが完了すると、さらに7つのゼロが同様にシフトされる必要があります。このプロセスはオーグメンテーションと呼ばれ、多項式除算を完了します。この時点で、CRC-7の値はシフトレジスタから直接読み取ることが可能です。
図2. CRC-7はシフトレジスタアーキテクチャで計算可能です。
レシーバが保護されたすべてのデータを備えているとき、レシーバはそれらのデータからCRC-7の値を計算し、受け取ったCRC-7の値と比較することができます。これらの値が異なる場合、レシーバは保護されたデータが伝送中に壊れたことを認識します。値が一致した場合、レシーバは通信経路においてデータ完全性の障害が起きなかったことを高い確度で認識できます。
CRC-16アルゴリズムの場合も同様に構成することができます。この場合、シフトレジスタの長さは7ビットの代わりに16ビットとなり、多項式値は0x1021に変更され、入力データは16のゼロビットで増加します。
SDのコマンドフォーマット
コマンドは、6バイトフォーマットでカードに送出されます(図3)。16進数0x40付きの6ビットコマンドコードをOR-ingして、コマンドの先頭バイトを構築することができます。コマンドが要求する場合は、その次の4バイトは単一の32ビット引数を備え、最終バイトは、バイト1~5に対するCRC-7チェックサムを備えています。表1は、重要なSDコマンドを一覧表示しています。
図3. SPIモードのSDコマンドは、6バイト形式でカードに送出されます。
表1. 主なSDメモリカードのコマンド
Command | Mnemonic | Argument | Reply | Description |
0 (0x00) | GO_IDLE_STATE | none | R1 | Resets the SD card. |
9 (0x09) | SEND_CSD | none | R1 | Sends card-specific data. |
10 (0x0a) | SEND_CID | none | R1 | Sends card identification. |
17 (0x11) | READ_SINGLE_BLOCK | address | R1 | Reads a block at byte address. |
24 (0x18) | WRITE_BLOCK | address | R1 | Writes a block at byte address. |
55 (0x37) | APP_CMD | none | R1 | Prefix for application command. |
59 (0x3b) | CRC_ON_OFF | Only Bit 0 | R1 | Argument sets CRC on (1) or off (0). |
41 (0x29) | SEND_OP_COND | none | R1 | Starts card initialization. |
SPIモードでのSDカードの初期化
電源投入時、SDカードはデフォルトの独自仕様SDバスプロトコルに設定されます。カードをSPIモードに切り替えるには、ホストがコマンド0 (GO_IDLE_STATE)を発行します。GO_IDLE_STATEコマンドの間、カード選択端子(CS)がローに保持されることを監視することで、SDカードはSPIモードの選択を検出します。カードは、応答形式R1で応答します(図4)。アイドル状態ビットは、ハイに設定されてカードがアイドル状態にあることを示します。MMCカードとの互換性を維持するために、SPIクロック速度はこの段階で400kHzを超えてはいけません。
図4. 応答形式R1は、送出されたコマンドの成功または失敗を通知します。
SDカードがSPIモードになると、SDの仕様は、その他の要求が処理可能となる前に、ホストが初期化コマンドを送出することを必要とします。MMCカードとSDカードを識別するために、SDカードは、MMCカードが応答しない別の初期化コマンドを実装します。コマンド55 (APP_CMD)、続いてアプリケーションコマンド41 (SEND_OP_COND)をカードに送出すると、この重要なステップが終了します。MMCカードはコマンド55に応答せず、このコマンドを使ってMMCカードを無効メディアとして拒否することができます。カードからのR1の応答における全ビットがゼロになる(すなわち、IDLEビットがローになる)まで、このコマンドシーケンスが繰り返されます。
リスト1. コードはSEND_OP_CONDを使ってSDおよびMMCカードを識別する必要があります。
SDカードは、SDカードに関する情報を提供する重要なレジスタを複数備えています。最も重要なレジスタは、カード固有データ(Card Specific Data)レジスタ(CSD)です。サンプルアプリケーションの場合は、メモリのブロックサイズと合計サイズに留意しています。カード識別データ(Card Identification Data)レジスタ(CID)はカードのメーカーおよびシリアル番号に関する詳細を含んでいるため、このレジスタにも留意する必要があります。図5は、CSDおよびCIDレジスタのレイアウトを示しています。
図5. CSDおよびCIDレジスタは、SDカードに関する情報を備えています。
SDカードの応答の検証
カードのレジスタまたはブロックをカードから読み取るには、まずカードがどのように照会に応答するかを理解する必要があります。SPIモードでは、SDカードは、コマンドSEND_CSD (9)、SEND_CID (10)、およびREAD_SINGLE_BLOCK (17)にR1形式の応答で応答します。開始トークン、要求されたデータ、そして最後にデータに対するCRC-16チェックサムが続きます。R1応答とデータ開始トークンが次々とすぐに実施されると想定してはいけません。というのは、バスはこれらの2つのイベントの間にしばらくの間、アイドル状態に移行する場合があるためです。図6は、データ応答を詳述しています。
図6. SDカードからホストへのデータ転送は、開始トークンによってプレフィックスされます。
CSDおよびCIDレジスタのメタデータ読取り
SEND_CSDおよびSEND_CIDコマンドは、SDカードパラメータの設定に使用されるレジスタ内容を返送します。これらのコマンドは固定数のバイトを返し、これはそれぞれCSDまたはCIDレジスタのサイズに対応します。コマンドバイト内に含まれる引数は、これらのSENDコマンドのためにSDカードによって無視されます。
SDカードからのデータブロックの読取り
SDカードからのデータブロックの読取りはごく簡単です。ホストは、引数として開始バイトアドレスとともにREAD_SINGLE_BLOCKコマンドを送出します。このアドレスは、メディアのブロックの先頭と整合される必要があります。次に、SDカードはこのバイトアドレスを評価し、R1コマンド応答で返答します。範囲外のアドレスは、このコマンド応答で示されます。
SDメディアからの読取りがエラーなしで終了すると、開始データトークンが送信され、その後に固定数のデータバイトとCRC-16チェックサム用の2バイトが続きます。SDカードにハードウェア障害やメディア読取りエラーが発生すると、開始データトークンは送信されません。代わりに、エラートークンが送信され、データ転送が中止されます。
SDカードへのデータブロックの書込み
ホストは、SDカードブロック境界に整合されたバイトアドレスを提供する必要があり、データブロックの書込みは読取りと類似しています。書込みブロックサイズはREAD_BL_LENと等しい必要があり、通常は512バイトです。書込みはWRITE_BLOCK (24)コマンドの送出で開始され、このコマンドに対してSDカードはR1コマンド応答形式で応答します。書込みが続行可能であるとコマンド応答が示すと、ホストはデータ開始トークン、続いて固定数のデータバイトを送信し、送信データのCRC-16チェックサムで終了します。SDカードは、書き込まれるデータの受諾または拒否を示すデータ応答トークンを返します。
データが受理されると、SDカードがビジーの間は、SDカードはDOラインを連続的にローに維持します。ホストは、ビジー期間にカードの選択をローに維持する必要はありませんが、CSがデアサートされると、SDカードはDOラインを解放します。複数のデバイスがSPIバスに接続されている場合に、このプロセスは便利です。ホストは、SDカードがビジー表示を解放するのを待機したり、またはチップ選択を定期的にアサートしてカードをチェックすることができます。カードが引き続きビジーの場合は、DOラインをローにプルしてこの状態を表示します。ビジー状態でない場合は、カードはDOラインをアイドル状態に戻します(図7を参照)。
図7. ホストからSDカードへのデータ転送には、より複雑なハンドシェイクが必要です。
SPIコマンドおよびデータエラー検出
CRC-7およびCRC-16チェックサムを使って、ホストとSDカード間の通信のエラーを検出することができます。エラー検出によって、着脱時の接点のはね返りや、着脱可能なメディアに特有の理想的でない接触保持状態などの物理的に誘発されたエラーが発生した場合のエラー回復が強化されます。最下位ビットを引数に設定したCRC_ON_OFF (59)コマンドを送出して、チェックサムを利用することを強く推奨します。
リスト2. CRCチェックサムの利用を強く推奨します。
まとめ
SDメディアカードフォーマットは、組込みシステム用の小型で低電力の不揮発性メモリソリューションです。MAXQ2000マイクロコントローラで提供されるハードウェアSPIのサポートによって、ほんの少しのオーバヘッドでSDメディアカードにアクセスすることができます。japan.maximintegrated.com/MAXQ2000_SD (英文)でマキシムから提供されるリファレンスソフトウェアは、最小限の実装を検証し、これには、SDカードとの間のブロックの読取りと書込みに不可欠な動作が含まれています。
参考資料
SDメディアフォーマットの詳細については、Secure Digital Association (英文)から入手することができます。このプロジェクトで使用されたSDメディアブレイクアウトボードをhttp://www.sparkfun.com/commerce/product_info.php?products_id=204 (英文)に注文することができます。
この記事に関して
製品
{{modalTitle}}
{{modalDescription}}
{{dropdownTitle}}
- {{defaultSelectedText}} {{#each projectNames}}
- {{name}} {{/each}} {{#if newProjectText}}
-
{{newProjectText}}
{{/if}}
{{newProjectTitle}}
{{projectNameErrorText}}