コンパクトフラッシュメモリーを使う

 

メモリーカードの種類

 現在、各種のメモリーカードがいろいろな機器にて使用されている。
 よく聞くのがコンパクトフラッシュ、スマートメディア、メモリースティックあたりだろう。
 最近になり、コンパクトフラッシュをより小型化し、多機能にしたマルチメディアカードなども発表されているが、これを使用している製品はまだそれほど多くない。

 コンパクトフラッシュメモリーは、スマートメディアに比べると容量が大きい傾向にあり、メモリーを効率よく使うためのコントローラーが内蔵されているために、そのコントローラーに対してコマンドを送る形式でアクセスを行う。
 一方、スマートメディアはフラッシュメモリーをパッケージに収め、その端子を出しただけという構造であり、直接メモリICをアクセスする感じとなる。そのために、内部ICの特性をよく理解して使う必要がある。

 コンパクトフラッシュメモリーの端子は接点が表面には出ていないのに対し、スマートメディアでは手で触るような場所に端子が出ている。
 また、コンパクトフラッシュの端子はPCカードの端子とほぼコンパチブルであり、ノートPC用のアダプタは単にピンの順番を入れ替えている程度である。
 電源電圧も、3.3Vと5Vの両方に対応しているので、システムとしても設計しやすい。

 コンパクトフラッシュはメモリーモード、I/Oモード、IDEモードの3つのモードを持っており、各種拡張機器としての可能性を持っている。

 メモリースティックに関しては詳細は調べていないが、音楽配信などをターゲットとして作られているため、著作権保護のための機能なども含まれ、非常に厳格な規格が定義されているようである。

 今回は、コンパクトフラッシュメモリー(以下CF)を手軽に使うことに焦点をおき、その方法を簡単に説明する。

 コンパクトフラッシュの詳細仕様に関しては、http://www.compactflash.org/を参照してほしい。
 今回の設計においては主に日立と三菱の仕様書を参考にしたが、日立の仕様書は所々規格と異なることが書いてあり、三菱の仕様書だけでは具体的な使い方がわかりにくいという問題があるため、複数の仕様書を入手して調べることを奨める。
 

使用条件

使用モード

 前述の通り、CFにはメモリーモード、I/Oモード、IDEモードの3つのモードがある。
 今回の目的は、外部メモリとしての使用なのでI/Oモードは除外する。
 また、IDEモードとしてHDD互換で使用するためにはIDEコントローラーを使用するか、自前でIDEコントローラーと同等のものを作る必要があるので簡単とはいえなくなる。
 そこで、メモリーモードで使用することとする。

通電中の抜き挿し

 また、通電中のCFの抜き挿しは電源端子をコントロールすることで可能とのことだが、今回の説明では省略する。

使用上の注意点

 通常、CFをPCに接続すると自動的にIDEのデバイスとして認識され、FDISK、Formatを行ってHDDとして使うこととなるが、今回の仕様はメモリーモードであるため、この作業を行うとメモリー内のデータが消えてしまうこととなる。
 PCでアクセスする場合はそれなりのプログラムを作成する必要がある。

 一方、PCでは簡単に読み書きができないことにより、セキュリティに関しては有利となる。
 

端子説明

メモリーモードで使用する場合の各端子の機能を表にした。
 
信号名
属性
端子番号
詳細
A10 - A0
I
8,10,11,12,14,15,
16,17,18,19,20
アドレスピン。
A10が最上位で、A0が最下位。
BVD1,BVD2
I/O
46,45 カード内部の電池電圧状態を示すが、電池を搭載していないため、常にHを出力。
/CD1,/CD2
O
26,25 カード挿入検出用。
カード内部でGNDに接続されているので、プルアップ抵抗が必要。
/CE1,/CE2
I
7,32 カード選択信号。Lowアクティブ。
/CE1,/CE2,A0の組み合わせでワード/バイト/奇数アクセスを指定する。
/CE1,/CE2ともLowにするとワードアクセス、/CE1をLow、/CE2をHighにした場合、A0がLowのときに偶数アドレス、Highのときに奇数アドレスのアクセスとなる。
ただし、アトリビュート領域は偶数アドレスのみなのでA0をHighにしたときのデータは無効となる。
/CSEL
I
39 使用しない。
D15 - D0
I/O
31,30,29,28,27,
49,48,47,6,5,4,3,
2,23,22,21
データピン。
D0が偶数バイトの最下位、D8が奇数バイトの最下位。
GND
-
1,50 グランド。
/INPACK
O
43 使用しない。ホスト側にてオープンにしておく。
/IORD
I
34 メモリーモードでは使用しない。
/IOWR
I
35 メモリーモードでは使用しない。
/OE
I
9 レジスタのデータ出力制御に使用する。
RDY/BSY
O
37 電源投入時、リセット時などにはLowになるので、Highになったことを確認してからアクセスを行う。
プルアップ抵抗をつけておく。
/REG
I
44 タスクファイル領域をアクセスするときにはHigh、アトリビュート領域をアクセスするときにはLowにする。
RESET
I
41 Highでカードをリセットする。
VCC
-
13,38 電源入力。(3.3V/5V)
/VS1,/VS2
O
33,40 カード電源電圧を設定する情報をホストに与える。
/VS1はGNDに接続され、/VS2は第2電源のために提供されている。
/WAIT
O
42 カードに対してアクセス要求をした後、データが出力されるまでの間、Lowになる。 *1
CFのアクセスタイムは規格上では300nsec。
/WE
I
36 アトリビュート領域、タスクファイル領域のレジスタのデータ入力時の制御に使用する。
レジスタに対する書き込みクロックとして使用される。
データRead/Write時にはCF内部バッファをインクリメントするクロックとしても使用される。
WP
O
24 ライトプロテクト。ライトプロテクト機能がないので常にLowを出力。
 
 
   

*1:日立の仕様書('99.5.28 Rev2.0)では常時HighとなっているがCFの規格ではそのような仕様にはなっていない。
 
 

接続例

8bitアクセスにおける接続例を以下に示す。
これだけの信号線を接続しておけば、メモリーモードで使えるようになる。


 

 8ビットアクセスのため、/CE2はHighにして、/CE1のみでの制御となる。
 アドレスバス、データバスはCPUのバスに接続し、/RD、/WRはCPUの制御信号に接続、/CD、/RDY、/RESETはCPUのポートに接続した。
 /CE1、/REGはアドレスデコードにより、アトリビュート領域とタスクファイル領域をそれぞれメモリ空間にマッピングした。

 この図では/WAIT端子を使用していないが、本来であればCPUの/WAIT端子に接続する。今回は、CFへのアクセスがあった場合にFPGA内でWAITタイミングを生成し、CPUの/WAIT端子に信号を出力する方法をとった。
 日立以外のCFを使うのであればこのような処理は不要と思える。
 
 

レジスタ構成

 CFにはアトリビュート領域とタスクファイル領域が存在し、アトリビュート領域はCFの各種情報と設定用のレジスタが、タスクファイル領域には実際のデータアクセスに使用するレジスタがある。
 

アトリビュート領域

 タスクファイル領域をアクセスするときには/REGはHighにする。
 アトリビュート領域のアドレス0からはCIS(Card Information Structure)情報が格納されている。
 この情報は、Tuple(タプル)によるリンクにより構成され、ある情報の最初にTuple-Linkにてデータのワード数を指定し、データの最後はFFHでターミネートするという構造の連続となっている。
 CISはRead Onlyである。

 200HはConfigration Option Registerとなっており、CFカードをメモリーモード、I/Oモード、IDEモードのどのモードで使用するかの指定と、ハードリセット、割りこみの指定などを行う。
 電源投入時にはメモリーモードとなっているので、特に設定する必要はない。

 202HはConfigration and Status Registerとなっており、カードの状態を知ることができる。

 204HはPin Replacement registerとなっており、このレジスタのBit1を読みとることにより、RDY/BSY状態を知ることができる。

 206HはSocket and Copy registerとなっており、ドライブ番号を指定する。
 Configuration Option registerを設定する前にここを設定しておく必要がある。
 通常、0に指定しておくことになるのでここは設定する必要はない。
 

タスクファイル領域

 CFカードに対してデータのRead/Writeを行うときには、必ずタスクファイルレジスタを通して行う。
 タスクファイル領域をアクセスするときには/REGはHighにする。

レジスタ一覧

 タスクファイルレジスタの一覧を以下に示す。
 
A10
A9-A4
A3
A2
A1
A0
Offset
/OE=L
/WE=L
0
×
0
0
0
0
0H
Data Register Data Register
0
×
0
0
0
1
1H
Error Register Feature Register
0
×
0
0
1
0
2H
Sector Count Register Sector Count Register
0
×
0
0
1
1
3H
Sector Number Registor Sector Number Registor
0
×
0
1
0
0
4H
Cylinder Low Register Cylinder Low Register
0
×
0
1
0
1
5H
Cylinder High Register Cylinder High Register
0
×
0
1
1
0
6H
Drive Head Register Drive Head Register
0
×
0
1
1
1
7H
Status Register Command Register
0
×
1
0
0
0
8H
Dup. Even Data Register Dup. Even Data Register
0
×
1
0
0
1
9H
Dup. Odd Data Register Dup. Odd Data Register
0
×
1
1
0
1
DH
Dup. Error Registor Dup. Error Registor
0
×
1
1
1
0
EH
Alt. Status Register Device Control Register
0
×
1
1
1
1
FH
Drive Address Register Reserved
1
×
×
×
×
0
8H
Even Data Register Even Data Register
1
×
×
×
×
1
9H
Odd Data Register Odd Data Register

 データのRead/Writeを行うときにはそれぞれのコマンドに必要なレジスタを設定した後、Command Registerにコマンドを設定し、Status Registerを見ながらData RegisterのRead/Writeを行う。
 

コマンド一覧

 Command Registerに設定できるコマンドセットと、それぞれのコマンドを実行する際に設定を必要とするレジスタの一覧を以下に示す。
 
Command
Code
FR
SC
SN
CY
DR
HD
LBA
Check Power Mode
E5H or 98H
       
   
Execute Drive Diagnostic
90H
       
   
Erace Sector
C0H
 
Format Track
50H
 
 
Identyfy Drive
ECH
       
   
Idle
E3H or 97H
 
   
   
Idle Immediate
E1H or 95H
       
   
Initialize Drive Parameters
91H
 
   
 
Read Buffer
E4H
       
   
Read Multiple
C4H
 
Read Long Sector
22H or 23H
   
Read Sector
20 or 21H
 
Read Verify Sector
40H or 41H
 
Recalibrate
1XH
       
   
Request Sense
03H
       
   
Seek
7XH
   
Set Features
EFH
     
   
Set Multiple Mode
C6H
 
   
   
Set Sleep Mode
E6H or99H
       
   
Stand By
E2H or 96H
       
   
Stand By Immediate
E0H or 94H
       
   
Transrate Sector
87H
 
Wear Level
F5H
       
 
Write Buffer
E8H
       
   
Write Long Sector
32H or 33H
   
Write Multiple
C5H
 
Write Multiple Without erase
CDH
 
Write Sector
30H or 31H
 
Write Sector Without erase
38H
 
Write Verify Sector
3CH
 

FR : Feature Register
SC : Sector Count Register
SN : Sector Number Register
CY : Cylinder Register
DR : Drive Bit of Drive Head Register
HD : Head Number of Drive Head Register
LBA : Logical Block Address Mode Supported

 例えば、Read Sectorを実行する際にはSC、SN、CY、DR、HDをセットしてからCommand Registerに20Hをセットし、Read動作を行う。
 

コマンド概略

  • Check Power Mode

  • パワーモードをチェックするときに使用する。
    SleepモードのときにはSector Count RegisterにOOHを、IdleモードのときにはFFHをセットする。
  • Execute Drive Diagnostic

  • カードの自己診断を行う。診断結果はErrorレジスタに書き込まれる。
    01H : 正常、02H : デバイス不良、03H : Sector Buffer Error、04H : ECC回路異常、05H : MPU異常
  • Erace Sector

  • 指定セクタの消去を行う。
  • Format Track

  • Drive、Cylinder、Headにて指定されたすべてのセクタ(32セクタ)にFFを書き込む。
    動作はWrite Sectorと同じで、データを書き込まないだけ。
  • Identyfy Drive

  • シリンダ数、ヘッド数、トラックあたりのセクタ数、シリアルナンバー等、カードの属性情報を得る。
    動作はRead Sectorと同じ。
  • Idle

  • コマンド実行終了時、設定時間経過後に自動的にPower Downモードとなる。
    設定時間はSector Count Registerに設定された値×5ms。
  • Idle Immediate

  • Idle Modeに移行する。
  • Initialize Drive Parameters

  • トラックあたりのセクタ数、シリンダあたりのヘッド数を変更する。
  • Read Buffer

  • セクタバッファよりデータを読みだす。
    データ転送方法はRead Sectorと同じ。
  • Read Multiple

  • Multiple転送を行う。
    実質的にMultiple転送はサポートされていない。
  • Read Long Sector

  • 通常のRead Sectorでは、1セクタ当たり512バイトの転送を行うのに対し、Read Long Sectorでは516バイトの転送を行う。ただし、この時にはカード側でのECCチェックは行われない。
  • Read Sector

  • Head、Cylinder、Sector Numberで指定されたセクタよりSector Count数分のセクタのデータを読みだす。
  • Read Verify Sector

  • セクタのベリファイを行う。
    データの転送が発生しない点を除き、Read Sectoprと同等。
  • Recalibrate

  • HDDとの整合性のために残されているコマンドで、実質的にNOP。
  • Request Sense

  • コマンドが異常終了した際に、拡張エラーコードを知ることができる。
  • Seek

  • HDDとの整合性のために残されているコマンドで、実質的にNOP。
  • Set Features

  • カードに対して特定機能の設定を行う。
    標準ATA規格には存在しないコマンド。
  • Set Multiple Mode

  • Read/Write MultipleコマンドのEnableもしくはブロックを構成するセクタ数の設定を行う。
    ブロック数は1に限定されている(Read/Write Multipleはサポートされていない)ので実質的には必要性のないコマンド。
  • Set Sleep Mode

  • Sleep Modeに移行する。
  • Stand By

  • Stand Byモードに移行する。
  • Stand By Immediate

  • Stand Byモードに移行する。
  • Transrate Sector

  • 各セクタの書き換え回数を知ることができる。
    標準ATA規格には存在しないコマンド。
  • Wear Level

  • 実質的にNOP。
  • Write Buffer

  • セクタバッファを上書きする。
    データ転送方法はWrite Sectorと同じ。
  • Write Long Sector

  • Read Long Sectorと同様に516バイトでデータ転送を行うが、ECCの4バイトは破棄され、カード内部で生成したECCが書き込まれる。
  • Write Multiple

  • Multiple転送を行う。
    実質的にMultiple転送はサポートされていない。
  • Write Multiple Without erase

  • Write動作に先立ってErase動作が行われないことを除いてWrite Multipleと同じ。
  • Write Sector

  • Head、Cylinder、Sector Numberで指定されたセクタよりSector Count数分のセクタのデータを書き込む。
  • Write Sector Without erase

  • Write動作に先立ってErase動作が行われないことを除いてWrite Multipleと同じ。
  • Write Verify Sector

  • 書き込みを行った後にベリファイを行う。

    ソフトの流れ

    CFをRead/Writeするのに必要な操作をまとめてみた。

    初期設定

  • 装置の電源投入後、/CD1にてCFの検出を行う。LでCFあり。
  • CFが検出された場合、RESETをHにしてからCFの電源を入れ、しばらく待ってからRESETをLにする。(HでRESET)
  • RDYがHになるのを待つ。
  • Socket and Copy Register(アトリビュートの206H)に00Hをセット
  • Configuration Option Register(アトリビュートの200H)に00Hをセットし、メモリーモードにセットする。
  • Status Register(タスクファイルの07H)を読み込み、58Hになるまで待つ。
  • Drive Head Register(タスクファイルの06H)にA0Hをセットし、CHSモードにする。
  • Status Register(タスクファイルの07H)を読み込み、58Hになるまで待つ。
  • Sector Count Register(タスクファイルの02H)に1をセットする。
  • Status Register(タスクファイルの07H)を読み込み、58Hになるまで待つ。
  • Command Register(タスクファイルの07H)にIdentify Driveを得るためにECHをセットする。
  • Status Register(タスクファイルの07H)を読み込み、58Hになるまで待つ。
  • Data Register(8bitアクセスの場合はタスクファイルの00/01Hを交互)を512Byte読みこむ。
  • Word Addressの1、3、6よりシリンダ数、ヘッド数、セクタ数を得る。この値をもとにデータのアクセスを行う。
  •  カードのCIS情報はアトリビュートの000Hから136Hに格納されているので、必要に応じて参照する。
     

    書き込み

  • Cylinder Low/high Register(タスクファイルの04H、05H)にシリンダ番号をセットする
  • Drive Head Register(タスクファイルの06H)の下位4ビットにヘッド番号をセットする。上位4ビットはAH固定。
  • Sector Number Register(タスクファイルの03H)にセクタ番号をセットする。
  • Sector Count Register(タスクファイルの02H)に1をセットする
  • Command Register(タスクファイルの07H)にWrite Sectorを行うために30Hをセットする。
  • Status Register(タスクファイルの07H)を読み込み、58Hになるまで待つ。
  • Data Register(8bitアクセスの場合はタスクファイルの00/01Hを交互)に512Byte書きこむ。
  • Status Register(タスクファイルの07H)を読み込み、50Hになるまで待つ。

  •  

    読み出し

  • Cylinder Low/high Register(タスクファイルの04H、05H)にシリンダ番号をセットする
  • Drive Head Register(タスクファイルの06H)の下位4ビットにヘッド番号をセットする。上位4ビットはAH固定。
  • Sector Number Register(タスクファイルの03H)にセクタ番号をセットする。
  • Sector Count Register(タスクファイルの02H)に1をセットする
  • Command Register(タスクファイルの07H)にRead Sectorを行うために20Hをセットする。
  • Status Register(タスクファイルの07H)を読み込み、58Hになるまで待つ。
  • Data Register(8bitアクセスの場合はタスクファイルの00/01Hを交互)に512Byte読みこむ。
  • Status Register(タスクファイルの07H)を読み込み、50Hになるまで待つ。

  •  

    その他

  • レジスタをRead/Writeする場合には、必らずStatus Registerを監視し、RDY状態であることを確認してから行う。
  • Sector Count Registerに1以外の数値を入れて複数セクタを連続して読み出す方法もできるようだが、なぜかアクセス速度が遅くなってしまった。512Byte毎にSector Numberを設定して読み出すほうが速かった。
  • データのアクセスタイムは300nsecであるが、低速のCPUの場合、CPUの処理速度のほうがネックとなってくるので、処理の効率化も考慮する必要がある。
  •  

    参考文献
    (株)日立製作所  HB289048C4データブック (ADJ-203-359B Rev.2.0)
    三菱樹脂(株) PC Card ATAバスカード NOR型ATAバスコンパクトシリーズ(I) (SCF1-2.3)
    CompactFlash Association CF+ and CompactFlash Specification Revision 1.4
    表紙へ