2016.11.5
前へ
次へ
ホームページトップへ戻る

マイコン独立大作戦
SDカードインターフェースの製作

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
WindowsパソコンにUSB接続して使う現行方式はそれなりに便利ではありますが、ときとしてWindows
のしがらみから開放されて、小さいながらも独立した一個のパソコンとして機能したいと思うこともあります。
独立大作戦の作戦その1はCRTインターフェースボードの製作です。
作戦その2はキーボードインターフェースです。
そして作戦その3は、SDカードインターフェースです。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

[第10回]


●セクタREADプログラム

いよいよセクタREADです。
SDカードは512バイトのセクタで構成されています。
READ/WRITEはセクタ単位で行ないます。
今回は前回のプログラムに追加変更を行なって、セクタアドレスを指定して1セクタ512バイトを読んで16進数で表示できるようにします。
下がそのように追加変更を行なったプログラムのアセンブルリストです。

2016/10/25  13:43  sdcdif2q.txt
END=81F6
              ;;; SD card PCI test program
              ;16.10.10 10.11 10.12 10.13 10.25
              ;
                ORG $8100
              ;
                CRLF=$101B
                REENT=$1033
                HXDP2=$104B
              ;
8100 3E90     START0:LD A,90
8102 D383       OUT (83),A
              ;card init
8104 2E0A       LD L,0A
8106 16FF     START01:LD D,FF
8108 CDA381     CALL SOUT
810B 2D         DEC L
810C C20681     JP NZ,START01
              ;CMD0 out
810F 3E02       LD A,02
8111 D382       OUT (82),A;CS=L
8113 1640       LD D,40
8115 CDA381     CALL SOUT
8118 0604       LD B,04
811A C5       START02:PUSH BC
811B 1600       LD D,00
811D CDA381     CALL SOUT
8120 C1         POP BC
8121 05         DEC B
8122 C21A81     JP NZ,START02
8125 1695       LD D,95
8127 CDA381     CALL SOUT
812A CDBD81   START03:CALL SIN
812D 63         LD H,E
812E 7B         LD A,E
812F F5         PUSH AF
8130 CD4B10     CALL HXDP2
8133 F1         POP AF
8134 FE01       CP 01
8136 C22A81     JP NZ,START03
              ;
              ;CMD1 out
8139 0E41     START07:LD C,41
813B 110000     LD DE,$0000
813E 210000     LD HL,$0000
8141 CDDA81     CALL COUT
8144 CDBD81   START09:CALL SIN
8147 63         LD H,E
8148 7B         LD A,E
8149 F5         PUSH AF
814A CD4B10     CALL HXDP2
814D F1         POP AF
814E B7         OR A;00?
814F CA5A81     JP Z,RTEST
8152 FE01       CP 01
8154 C24481     JP NZ,START09
8157 C33981     JP START07
              ;read test
815A 0E51     RTEST:LD C,51;index=11(17d)
815C 110000     LD DE,$0000;adrs=00000000
815F 210000     LD HL,$0000
8162 CDDA81     CALL COUT
              ;test
8165 CDBD81   RTEST2:CALL SIN
8168 63         LD H,E
8169 7B         LD A,E
816A F5         PUSH AF
816B CD4B10     CALL HXDP2
816E F1         POP AF
816F FEFE       CP FE;token
8171 C26581     JP NZ,RTEST2
8174 CD1B10     CALL CRLF
              ;data block read
8177 0610       LD B,10;=16 16x32=512
8179 0E20     RTEST3:LD C,20;=32byte
817B C5       RTEST4:PUSH BC
817C CDBD81     CALL SIN
817F 63         LD H,E
8180 CD4B10     CALL HXDP2
8183 C1         POP BC
8184 0D         DEC C
8185 C27B81     JP NZ,RTEST4
8188 CD1B10     CALL CRLF
818B 05         DEC B
818C C27981     JP NZ,RTEST3
818F CDBD81     CALL SIN;crc(2bytes) read 
8192 63         LD H,E
8193 CD4B10     CALL HXDP2
8196 CDBD81     CALL SIN
8199 63         LD H,E
819A CD4B10     CALL HXDP2
819D CD1B10   END:CALL CRLF
81A0 C33310     JP REENT
              ;
              ; D:out data
81A3 0608     SOUT:LD B,08
81A5 7A       SOUT2:LD A,D
81A6 2F         CPL
81A7 D381       OUT (81),A;data out
81A9 3E01       LD A,01
81AB D383       OUT (83),A;pc0=1 out ~I_
81AD 7A         LD A,D
81AE 17         RLA
81AF 57         LD D,A
81B0 3E00       LD A,00
81B2 D383       OUT (83),A;pc0=0 out _I~
81B4 05         DEC B
81B5 C2A581     JP NZ,SOUT2
81B8 3E01       LD A,01
81BA D383       OUT (83),A;pc0=1 out ~I_
81BC C9         RET
              ; E:in data
81BD 0608     SIN:LD B,08
81BF 3E01     SIN2:LD A,01
81C1 D383       OUT (83),A;pc0=1 out ~I_
81C3 00         NOP
81C4 00         NOP
81C5 00         NOP
81C6 3E00       LD A,00
81C8 D383       OUT (83),A;pc0=0 out _I~
81CA DB80       IN A,(80)
81CC 2F         CPL
81CD 1F         RRA
81CE 7B         LD A,E
81CF 17         RLA
81D0 5F         LD E,A;data in
81D1 05         DEC B
81D2 C2BF81     JP NZ,SIN2
81D5 3E01       LD A,01
81D7 D383       OUT (83),A;pc0=1 out ~I_
81D9 C9         RET
              ; CMD out
              ;C cmd
              ;D,E,H,L argument
81DA D5       COUT:PUSH DE
81DB 51         LD D,C
81DC CDA381     CALL SOUT;cmd out
81DF D1         POP DE
81E0 D5         PUSH DE
81E1 CDA381     CALL SOUT;D out
81E4 53         LD D,E
81E5 CDA381     CALL SOUT;E out
81E8 54         LD D,H
81E9 CDA381     CALL SOUT;H out
81EC 55         LD D,L
81ED CDA381     CALL SOUT;L out
81F0 16FF       LD D,FF
81F2 CDA381     CALL SOUT;crc(dummy)+stop bit out
81F5 D1         POP DE
81F6 C9         RET
              ;
              ;END
COUT         =81DA  CRLF         =101B  END          =819D  
HXDP2        =104B  REENT        =1033  RTEST        =815A  
RTEST2       =8165  RTEST3       =8179  RTEST4       =817B  
SIN          =81BD  SIN2         =81BF  SOUT         =81A3  
SOUT2        =81A5  START0       =8100  START01      =8106  
START02      =811A  START03      =812A  START07      =8139  
START09      =8144  

前回のプログラムではSDカードにアクセスするのにSINOUTサブルーチンを使いました。
SPIモードのルールに忠実なプログラムのサンプルというつもりで作りましたから、データ出力とデータ入力を同時に行なうようになっていました。
しかし実際の動作では出力(送信)と入力(受信)を同時に行なうことはまず無いのではと思います。
そこで今回は出力(送信)サブルーチンと入力(受信)サブルーチンに分けました。
またコマンド送信は6バイトの固定長なので、コマンド送信のためにコマンド送信サブルーチンを作りました。

上の全体のプログラムリストから、送信サブルーチンのみを取り出して下に示します。

              ;
              ; D:out data
81A3 0608     SOUT:LD B,08
81A5 7A       SOUT2:LD A,D
81A6 2F         CPL
81A7 D381       OUT (81),A;data out
81A9 3E01       LD A,01
81AB D383       OUT (83),A;pc0=1 out ~I_
81AD 7A         LD A,D
81AE 17         RLA
81AF 57         LD D,A
81B0 3E00       LD A,00
81B2 D383       OUT (83),A;pc0=0 out _I~
81B4 05         DEC B
81B5 C2A581     JP NZ,SOUT2
81B8 3E01       LD A,01
81BA D383       OUT (83),A;pc0=1 out ~I_
81BC C9         RET

前回のSINOUTサブルーチンから入力(受信)部分を外しました。

下は受信サブルーチンです。

              ; E:in data
81BD 0608     SIN:LD B,08
81BF 3E01     SIN2:LD A,01
81C1 D383       OUT (83),A;pc0=1 out ~I_
81C3 00         NOP
81C4 00         NOP
81C5 00         NOP
81C6 3E00       LD A,00
81C8 D383       OUT (83),A;pc0=0 out _I~
81CA DB80       IN A,(80)
81CC 2F         CPL
81CD 1F         RRA
81CE 7B         LD A,E
81CF 17         RLA
81D0 5F         LD E,A;data in
81D1 05         DEC B
81D2 C2BF81     JP NZ,SIN2
81D5 3E01       LD A,01
81D7 D383       OUT (83),A;pc0=1 out ~I_
81D9 C9         RET

こちらは前回のSINOUTサブルーチンから送信部分を外したものです。
送信データがなくて大丈夫かと思われるかもしれませんが、大丈夫です。
送信データの終わりは必ずストップビット(1)で終りますから、データを何も送らないときは、実はそのままの状態(連続した1、つまりFF)を送っていることになります。

下は今回新たに作ったコマンド送信サブルーチンです。

              ; CMD out
              ;C cmd
              ;D,E,H,L argument
81DA D5       COUT:PUSH DE
81DB 51         LD D,C
81DC CDA381     CALL SOUT;cmd out
81DF D1         POP DE
81E0 D5         PUSH DE
81E1 CDA381     CALL SOUT;D out
81E4 53         LD D,E
81E5 CDA381     CALL SOUT;E out
81E8 54         LD D,H
81E9 CDA381     CALL SOUT;H out
81EC 55         LD D,L
81ED CDA381     CALL SOUT;L out
81F0 16FF       LD D,FF
81F2 CDA381     CALL SOUT;crc(dummy)+stop bit out
81F5 D1         POP DE
81F6 C9         RET

Cレジスタにコマンド、D、E、H、Lレジスタにアーギュメント(引数)を入れてコールします。
CMD0以外はCRCはダミーで構いませんからFFを送ります。

メインプログラムのうち、最初のCMD0とCMD1を実行する部分は、前回のプログラムと同じですから、説明を省略します。
下は今回追加したセクタREADプログラムです。

              ;read test
815A 0E51     RTEST:LD C,51;index=11(17d)
815C 110000     LD DE,$0000;adrs=00000000
815F 210000     LD HL,$0000
8162 CDDA81     CALL COUT
              ;test
8165 CDBD81   RTEST2:CALL SIN
8168 63         LD H,E
8169 7B         LD A,E
816A F5         PUSH AF
816B CD4B10     CALL HXDP2
816E F1         POP AF
816F FEFE       CP FE;token
8171 C26581     JP NZ,RTEST2
8174 CD1B10     CALL CRLF
              ;data block read
8177 0610       LD B,10;=16 16x32=512
8179 0E20     RTEST3:LD C,20;=32byte
817B C5       RTEST4:PUSH BC
817C CDBD81     CALL SIN
817F 63         LD H,E
8180 CD4B10     CALL HXDP2
8183 C1         POP BC
8184 0D         DEC C
8185 C27B81     JP NZ,RTEST4
8188 CD1B10     CALL CRLF
818B 05         DEC B
818C C27981     JP NZ,RTEST3
818F CDBD81     CALL SIN;crc(2bytes) read 
8192 63         LD H,E
8193 CD4B10     CALL HXDP2
8196 CDBD81     CALL SIN
8199 63         LD H,E
819A CD4B10     CALL HXDP2
819D CD1B10   END:CALL CRLF
81A0 C33310     JP REENT
              ;

セクタREADコマンドはCMD17です。
17は10進数ですから16進数では11Hです。
01XXXXXXのXのところが11(010001)ですから、コマンド部分は01010001(51H)になります。
今回はテストとして最初のセクタ(セクタbO)を読み出しますから、引数部分は00 00 00 00になります。
セクタREADコマンドを送ったあとはトークン(FE)が送られてくるのを待ちます。
テストですから、トークンが送られてくるまで、受信データを16進数2桁で画面に表示します。
トークンを受信すると、そのあとはセクタデータが512バイト連続して送られてきますから、それを1バイトごとに16進数2桁で画面に表示します。
最後にCRC2桁が送られてきます。
CRCは処理としては不要ですがこれもテストですからそのまま16進数で表示します。

●プログラムの実行

セクタREADプログラムsdcdif2q.binをND80Z3.5で実行しました。

logfile nd80zlog\11031046.txt open

ND80ZVに接続しました
0001 0000 - z
1000 00C3 - 
*** nd80z3 basic ****
ndwr2h.bin loaded,from E23F to E535
>/ld sdcdif2q.bin,8100
loading SDCDIF2Q.BIN ...00f7(247)bytes loaded,from 8100 to 81F6
>jp 8100
FF01FF01FF00FF00FFFFFE
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000201511256B0000000000000000000002
0E000614D4B48B00000075573A00000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000055AA
A3DB
>/exit
0000 00C3 - 
リモート接続を終了しました
logfile closed at Thu Nov 03 10:46:58 2016

SDカードのセクタbOが読めました。
これからいよいよセクタbOの内容を解読して、FAT16の構造にせまります。

SDカードインターフェースの製作[第10回]
2016.11.5upload

前へ
次へ
ホームページトップへ戻る