マイコン独立大作戦
SDカードインターフェースの製作
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
WindowsパソコンにUSB接続して使う現行方式はそれなりに便利ではありますが、ときとしてWindows
のしがらみから開放されて、小さいながらも独立した一個のパソコンとして機能したいと思うこともあります。
独立大作戦の作戦その1はCRTインターフェースボードの製作です。
作戦その2はキーボードインターフェースです。
そして作戦その3は、SDカードインターフェースです。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第28回]
●SDHCカード初期化+セクタREADプログラム
SDHCカード初期化+セクタREADプログラムは[第22回]でお見せしましたが、その後に初期化の手続き部分に手を加えました。
ですので手直し後のプログラムを下に再掲します。
基本的な部分は変わっていません。
2016/12/5 16:27 sdcdif5v.txt
END=8334
;;; SD card PCI test program
;16/10/10 10/11 10/12 10/13 10/25 10/26 10/27 10/28 10/29 10/31
;12/4 12/5
;
ORG $8100
;
ADISP=$1015
DEDP=$1018
CRLF=$101B
HDCMP=$1027
REENT=$1033
HXDP2=$104B
HXDP4=$104E
DMSB=$1A08
;
8100 C30981 JP START0
8103 00 SCTN_H:DB 00
8104 00 SCTN_M:DB 00
8105 00 SCTN_L:DB 00
8106 00 SCTN_L0:DB 00
8107 00 WKCNTR:DB 00
8108 00 WKA:DB 00
8109 3E90 START0:LD A,90
810B D383 OUT (83),A
;card init
810D 2E0A LD L,0A
810F 16FF START01:LD D,FF
8111 CD8D82 CALL SOUT
8114 2D DEC L
8115 C20F81 JP NZ,START01
;CMD0 out
8118 110D83 LD DE,CMD0T
811B CD1810 CALL DEDP
811E 3E02 LD A,02
8120 D382 OUT (82),A;CS=L
8122 0E40 LD C,40;cmd
8124 110000 LD DE,$0000
8127 210000 LD HL,$0000
812A 3E95 LD A,95;crc
812C CDC482 CALL COUT
812F CDA782 START03:CALL SIN
8132 63 LD H,E
8133 7B LD A,E
8134 F5 PUSH AF
8135 CD4B10 CALL HXDP2
8138 F1 POP AF
8139 FE01 CP 01
813B C22F81 JP NZ,START03
813E CD1B10 CALL CRLF
;
;CMD8 out
8141 111283 START04:LD DE,CMD8T
8144 CD1810 CALL DEDP
8147 0E48 LD C,48
8149 110000 LD DE,$0000
814C 21AA01 LD HL,$01AA
814F 3E87 LD A,87
8151 CDE682 CALL CMD8S
8154 CD1B10 CALL CRLF
;
;CMD58
8157 111783 LD DE,CMD58T
815A CD1810 CALL DEDP
815D 0E7A LD C,7A
815F 110000 LD DE,$0000
8162 210000 LD HL,$0000
8165 3EFF LD A,FF
8167 CDE682 CALL CMD8S
;
816A CD1B10 CMD55_0:CALL CRLF
;
;CMD55
816D 111D83 CMD55:LD DE,CMD55T
8170 CD1810 CALL DEDP
8173 0E77 LD C,77
8175 110000 LD DE,$0000
8178 210000 LD HL,$0000
817B 3EFF LD A,FF
817D CDC482 CALL COUT
8180 CDA782 CMD55_2:CALL SIN
8183 63 LD H,E
8184 7B LD A,E
8185 F5 PUSH AF
8186 CD4B10 CALL HXDP2
8189 F1 POP AF
818A FE01 CP 01
818C CA9381 JP Z,CMD55_3
818F B7 OR A
8190 C28081 JP NZ,CMD55_2
8193 CD1B10 CMD55_3:CALL CRLF
;
;ACMD41
8196 112383 LD DE,ACMD41T
8199 CD1810 CALL DEDP
819C 0E69 LD C,69
819E 11FF40 LD DE,$40FF
81A1 210080 LD HL,$8000
81A4 3EFF LD A,FF
81A6 CDC482 CALL COUT
81A9 CDA782 ACMD41_2:CALL SIN
81AC 63 LD H,E
81AD 7B LD A,E
81AE F5 PUSH AF
81AF CD4B10 CALL HXDP2
81B2 F1 POP AF
81B3 FEFF CP FF
81B5 CAA981 JP Z,ACMD41_2
81B8 B7 OR A
81B9 C26A81 JP NZ,CMD55_0
81BC CD1B10 CALL CRLF
;
;second CMD58
81BF 111783 LD DE,CMD58T
81C2 CD1810 CALL DEDP
81C5 0E7A LD C,7A
81C7 110000 LD DE,$0000
81CA 210000 LD HL,$0000
81CD 3EFF LD A,FF
81CF CDE682 CALL CMD8S
81D2 CD1B10 CALL CRLF
;
;CMD9
81D5 112A83 LD DE,CMD9T
81D8 CD1810 CALL DEDP
81DB 0E49 LD C,49
81DD 110000 LD DE,$0000
81E0 210000 LD HL,$0000
81E3 3EFF LD A,FF
81E5 CDC482 CALL COUT
81E8 CDA782 CMD9_2:CALL SIN
81EB 63 LD H,E
81EC 7B LD A,E
81ED F5 PUSH AF
81EE CD4B10 CALL HXDP2
81F1 F1 POP AF
81F2 B7 OR A
81F3 C2E881 JP NZ,CMD9_2
;
81F6 CDA782 CMD9_3:CALL SIN
81F9 63 LD H,E
81FA 7B LD A,E
81FB F5 PUSH AF
81FC CD4B10 CALL HXDP2
81FF F1 POP AF
8200 FEFE CP FE
8202 C2F681 JP NZ,CMD9_3
8205 CD1B10 CALL CRLF
8208 0612 LD B,12;****
820A C5 PUSH BC
820B CDA782 CMD9_4:CALL SIN
820E 63 LD H,E
820F 7B LD A,E
8210 CD4B10 CALL HXDP2
8213 C1 POP BC
8214 05 DEC B
8215 C5 PUSH BC
8216 C20B82 JP NZ,CMD9_4
8219 C1 POP BC
821A CD1B10 CALL CRLF
;
;read test
821D 112F83 RTEST0:LD DE,RTESTT
8220 CD1810 CALL DEDP
8223 210381 RTEST:LD HL,SCTN_H
8226 56 LD D,(HL)
8227 23 INC HL
8228 5E LD E,(HL)
8229 23 INC HL
822A 46 LD B,(HL)
822B 23 INC HL
822C 6E LD L,(HL)
822D 60 LD H,B
822E E5 PUSH HL
822F D5 PUSH DE
8230 0E51 LD C,51;index=11(17d)
8232 CDC482 CALL COUT
;test
8235 CDA782 RTEST2:CALL SIN
8238 63 LD H,E
8239 7B LD A,E
823A F5 PUSH AF
823B CD4B10 CALL HXDP2
823E F1 POP AF
823F FEFE CP FE;token
8241 C23582 JP NZ,RTEST2
8244 CD1B10 CALL CRLF
;data block read
8247 0610 LD B,10;=16 16x32=512
8249 210088 LD HL,$8800;*********** test
824C 0E20 RTEST3:LD C,20;=32byte
824E C5 RTEST4:PUSH BC
824F CDA782 CALL SIN
; PUSH HL
; LD H,E
; CALL HXDP2
; POP HL
8252 73 LD (HL),E
8253 23 INC HL
8254 C1 POP BC
8255 0D DEC C
8256 C24E82 JP NZ,RTEST4
; CALL CRLF
8259 05 DEC B
825A C24C82 JP NZ,RTEST3
825D 3E5B LD A,5B
825F CD1510 CALL ADISP
8262 E1 POP HL
8263 CD4E10 CALL HXDP4
8266 E1 POP HL
8267 CD4E10 CALL HXDP4
826A 3E5D LD A,5D
826C CD1510 CALL ADISP
826F CD1B10 CALL CRLF
8272 CDA782 CALL SIN;crc(2bytes) read
8275 210088 LD HL,$8800;*******test
8278 11FF89 LD DE,$89FF;*******
827B CD081A RTEST42:CALL DMSB
827E CD2710 CALL HDCMP
8281 CA7B82 JP Z,RTEST42
8284 DA7B82 JP C,RTEST42
8287 CD1B10 END:CALL CRLF
828A C33310 JP REENT
;
;*** SUBROUTINE ***
;
; D:out data
828D 0608 SOUT:LD B,08
828F 7A SOUT2:LD A,D
8290 2F CPL
8291 D381 OUT (81),A;data out
8293 3E01 LD A,01
8295 D383 OUT (83),A;pc0=1 out ~I_
8297 7A LD A,D
8298 17 RLA
8299 57 LD D,A
829A 3E00 LD A,00
829C D383 OUT (83),A;pc0=0 out _I~
829E 05 DEC B
829F C28F82 JP NZ,SOUT2
82A2 3E01 LD A,01
82A4 D383 OUT (83),A;pc0=1 out ~I_
82A6 C9 RET
; E:in data
82A7 0608 SIN:LD B,08
82A9 3E01 SIN2:LD A,01
82AB D383 OUT (83),A;pc0=1 out ~I_
82AD 00 NOP
82AE 00 NOP
82AF 00 NOP
82B0 3E00 LD A,00
82B2 D383 OUT (83),A;pc0=0 out _I~
82B4 DB80 IN A,(80)
82B6 2F CPL
82B7 1F RRA
82B8 7B LD A,E
82B9 17 RLA
82BA 5F LD E,A;data in
82BB 05 DEC B
82BC C2A982 JP NZ,SIN2
82BF 3E01 LD A,01
82C1 D383 OUT (83),A;pc0=1 out ~I_
82C3 C9 RET
;
; CMD out
;C cmd
;D,E,H,L argument
;A crc7+stopbit
82C4 D5 COUT:PUSH DE
82C5 320881 LD (WKA),A
82C8 51 LD D,C
82C9 CD8D82 CALL SOUT;cmd out
82CC D1 POP DE
82CD D5 PUSH DE
82CE CD8D82 CALL SOUT;D out
82D1 53 LD D,E
82D2 CD8D82 CALL SOUT;E out
82D5 54 LD D,H
82D6 CD8D82 CALL SOUT;H out
82D9 55 LD D,L
82DA CD8D82 CALL SOUT;L out
82DD 3A0881 LD A,(WKA)
82E0 57 LD D,A
82E1 CD8D82 CALL SOUT;crc7+stop bit out
82E4 D1 POP DE
82E5 C9 RET
;
82E6 CDC482 CMD8S:CALL COUT
82E9 CDA782 CMD8S2:CALL SIN
82EC 63 LD H,E
82ED 7B LD A,E
82EE F5 PUSH AF
82EF CD4B10 CALL HXDP2
82F2 F1 POP AF
82F3 FEFF CP FF
82F5 CAE982 JP Z,CMD8S2
82F8 F5 PUSH AF
82F9 0E04 LD C,04
82FB C5 PUSH BC
82FC CDA782 CMD8S3:CALL SIN
82FF 63 LD H,E
8300 7B LD A,E
8301 CD4B10 CALL HXDP2
8304 C1 POP BC
8305 0D DEC C
8306 C5 PUSH BC
8307 C2FC82 JP NZ,CMD8S3
830A C1 POP BC
830B F1 POP AF
830C C9 RET
;
830D 434D4430 CMD0T:"CMD0"
8311 0D DB 0D
8312 434D4438 CMD8T:"CMD8"
8316 0D DB 0D
8317 434D4435 CMD58T:"CMD5"
831B 38 "8"
831C 0D DB 0D
831D 434D4435 CMD55T:"CMD5"
8321 35 "5"
8322 0D DB 0D
8323 41434D44 ACMD41T:"ACMD"
8327 3431 "41"
8329 0D DB 0D
832A 434D4439 CMD9T:"CMD9"
832E 0D DB 0D
832F 52544553 RTESTT:"RTES"
8333 54 "T"
8334 0D DB 0D
;
;END
ACMD41T =8323 ACMD41_2 =81A9 ADISP =1015
CMD0T =830D CMD55 =816D CMD55T =831D
CMD55_0 =816A CMD55_2 =8180 CMD55_3 =8193
CMD58T =8317 CMD8S =82E6 CMD8S2 =82E9
CMD8S3 =82FC CMD8T =8312 CMD9T =832A
CMD9_2 =81E8 CMD9_3 =81F6 CMD9_4 =820B
COUT =82C4 CRLF =101B DEDP =1018
DMSB =1A08 END =8287 HDCMP =1027
HXDP2 =104B HXDP4 =104E REENT =1033
RTEST =8223 RTEST0 =821D RTEST2 =8235
RTEST3 =824C RTEST4 =824E RTEST42 =827B
RTESTT =832F SCTN_H =8103 SCTN_L =8105
SCTN_L0 =8106 SCTN_M =8104 SIN =82A7
SIN2 =82A9 SOUT =828D SOUT2 =828F
START0 =8109 START01 =810F START03 =812F
START04 =8141 WKA =8108 WKCNTR =8107
|
シリアルデータOUT、データIN、コマンドOUTの各サブルーチンは2GBまでのSDカードプログラムと同じです(2GBまでのSDカードプログラムは[第12回]を参照してください)。
コマンドの送出とレスポンスの処理のパターンが同じ部分をサブルーチン化しました。
CMD8Sです。
初期化の最初のCMD0の送出のところまでは2GB以下のSDカードプログラムと同じですが、そのあとCMD1を送る代わりにCMD8を送ります。
初期化の簡単なフローチャートが[第23回]にありますから、そちらも参考にしてください。
●セクタREAD
上記プログラムは初期化のあとにセクタREADを行ないます。
基本的には2GBまでのプログラムと変わりません。
どちらもCMD17を使います。
コマンドは同じなのですが引数の単位が変わっています。
プログラムの先頭部分を比較してください。
[第12回]のSDカードプログラムではプログラム先頭のアドレス置数部が3バイトですが、今回のプログラムでは4バイトになっています。
スタンダードのSDカードのCMD17の引数で指定する読み出し開始アドレスの単位はバイトです。
過去からの色々があってこうなっているのだとは思いますが、無駄な設定だと思います。
バイト単位なので、それなら12345678なんて数も指定できるかというと、これはエラーになってしまいます。
単位はバイトなのですが、指定できるアドレスはセクタの先頭アドレスに限られます。
1セクタは512バイトなので、16進数に直すと200Hです。
つまり4バイト(32ビット)の下位9ビットは常に0ということになります。
さらにいいますと、セクタの先頭アドレスの上位3バイトはセクタb左に1ビットシフトした値に一致します。
ですからスタンダードのSDカードプログラムでは、先頭で3バイトのセクタb置数するようにして、CMD17を送出する段階でその3バイトの値を左に1ビットしたあと下位9ビットを0にして、それを引数にしているのです。
スタンダードのSDカードのセクタアドレス指定はそういうルールですから、指定できる最大アドレスはFFFFFE00になります。
10進数に直すと4294966784です。
約4GBです。
つまりスタンダードのSDカードのルール(Ver.1)では4GB以上のカードは扱えないことになります(実際は2GBまでのカードがスタンダードのSDカードのようです)。
そこでSDHCカードのためのルール(Ver.2)が作られたのでありましょう。
●Ver.2のCMD17
Ver.1とVer.2のCMD17は見かけ上は同じです。
しかし上で書いたように、引数の単位が違います。
Ver.1ではバイト単位(しかし実際にはセクタ単位のアドレス指定しかできない)ですが、Ver.2ではセクタnw定に変わりました。
うむ。
そうするべきでありましょう。
これですっきりしました。
CMD17の引数を指定するところでスタンダードのSDカード用プログラムではセクタb開始アドレスに換算するために、置数を左シフトして下位9ビットを0にしました。
その左シフトが不要になったので、SDHCカード用のプログラムでは、置数(セクタaj4バイトをそのままCMD17の引数として与えています。
そのようにルールを変更したおかげで、同じ32ビットの引数でありながら、扱えるカード容量は4GB×512≒2TB(テラバイト)と飛躍的に増大しました。
ただしSDHCカードは32GBまでです。
それを越えるサイズのカードはSDXCカードになります。
下は「Physical Layer Simplified Specification」からの引用です。
最新版(2016年12月現在)のV5.00です。

[出典]SD Card Association:Physical Layer Simplified Specification Version 5.00
それではSDXCカードでもSPIモードが使えるのか、ということなのですが。
どうやら使えるようではあります。

[出典]SD Card Association:Physical Layer Simplified Specification Version 5.00
下線部を読んで、一瞬「あれ?SDXCではSPIモードは使えないのか?」と思いましたが、落ち着いてよくよく読み直してみましたら、使えることは使えるようです。
「ただしVer.2以後に追加されたSDコマンドはSPIモードではサポートされませんよ」という但し書きのようです。
「使えるだろうけれど、パフォーマンスが悪いからSPIモードは使うべきではない」とのご託宣であります。
それはそうでしょうけれど、たっぷり年会費とロイヤリティを払わなければならないわけでありますから、たかが8ビットのシステムとしては、それはできない相談なのであります。
「身の丈に合った」という言葉がありますように、8ビットのCPUでクロックもせいぜい20MHzが精一杯なのですから、パフォーマンスなど、はなから計算外なのであります。
●セクタbO(MBR)
さてそれではいよいよSDHCカードの中身の解析にかかることにします。
もうすでに何回かお見せしていますが、下がSDHCカード(8GB)のセクタbOです。
カード先頭のセクタbOはMBR(Master Boot Record)です。
そのカードの最も基本的なファクタが書かれています。
[00000000] 8800 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8810 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8820 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8830 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8840 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8850 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8860 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8870 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8880 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8890 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 88A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 88B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 88C0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 88D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 88E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 88F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8900 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8910 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8920 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8930 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8940 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8950 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8960 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8970 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8980 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 8990 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 89A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 89B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 82 ................ 89C0 03 00 0B 19 D1 C8 00 20-00 00 00 30 ED 00 00 00 ....ムネ. ...0.... 89D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 89E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 89F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 55 AA ..............Uェ |
セクタbOの構成はスタンダードのSDカードと同じようです([第11回]参照)。
一番最後の2バイトは55AAです。
これはFATファイルの識別情報です。
ここに55AAがないと、このディスクは正しいFATファイルディスクとして認識されません。
その2バイトよりも前の64バイトが16バイトずつ4つのブロックに区切られていて、最大4個のパーティションブロックの情報が入れられます。
セクタREADプログラムは解析の便を考えて、読み込んだ1セクタ分のデータをND80Z3.5のアドレス8800〜89FFに置いています。
64バイトのパーティションブロック情報はアドレス89BE〜89FDにあります。
これを見ると、最初のブロックのみデータがありますが、そのあとの3ブロックにはデータがありません。
このSDHCカードはパーティションが1つだけであることがわかります。
パーティションブロックの16バイトの解析です。
16バイトの情報は先頭から下のように区切られています。
1バイト 00 ブート情報 80:ブート可 00:ブート不可
3バイト 820300 開始ヘッド、セクタ、シリンダ情報(古い表示方法です。現在は利用されません)
1バイト 0B FAT種別 0B:FAT32
3バイト 19D1C8 終了ヘッド、セクタ、シリンダ情報(古い表示方法です。現在は利用されません)
4バイト 00200000 パーティションの開始セクタ
4バイト 0030ED00 パーティションのセクタ数
最後にセクタ数があります。
格納されているデータ順はリトルエンディアンなので、通常の表現で示すと 00 ED 30 00 になります。
これを10進数に直すと15544320です。
1セクタは512バイトですから、512を掛ける代わりに2で割るとKBが求まります。
15544320/2≒7772160(KB)≒7.8(GB)
ということはSDHCカード(8GB)全部ををひとつのパーティションだけで使っている計算になります。
SDカードインターフェースの製作[第28回]
2016.12.8upload
前へ
次へ
ホームページトップへ戻る