So-net無料ブログ作成
English Version

3チップ構成68Kマイコンの構想(その12)Blocking/Deblocking [68K]

 前回の記事でプリント基板化のためのパターン設計について書きましたが、プリント基板製造をSeeedさんに注文し待ち状態です^^

 今回はCP/M-68KのSDカードアクセス時のブロッキング/デブロッキング処理を追加しました。
 3チップ構成のCP/M-80の時はCP/Mのメモリサイズを最大の64KBにしたいこともあってSDカードアクセス処理でブロッキング/デブロッキング処理には対応していませんでした。
 今回のCP/M-68KではBIOSのメモリサイズをあまり気にしなくてもいいこと、及びコマンドのサイズがCP/M-80と比較して大きめなのでコマンド実行時に少し待ち時間が発生してしまうのでブロッキング/デブロッキング処理に対応しました。

 SDカードのブロック長は512バイトなのでCP/Mのセクタ(128バイト)の4つ分に該当します。
 今回の対応で変更したワークエリアは
  1. PICと68K間のSDデータ渡し用の領域(SDバッファ)を128バイトから512バイトに変更
  2. SDバッファ内のデータがSDに書き込み済みでない場合の変更フラグを追加
  3. SDバッファの属性としてsector番号での管理をSDのブロック番号の管理に変更

の変更を行いました。

 BIOS内のWriteSectorコール時にD1レジスタに下記の情報が渡されます。
  1. d1.w = 0 : normal write
  2. d1.w = 1 : write to a directory sector
  3. d1.w = 2 : write to first sector of new block

 WriteSector処理での追加処理としては最初にSDバッファがヒット(今回の書込みセクタが含まれている)場合はSDの先読みは不要で含まれていない場合は変更フラグがオンならSDバッファをSDに書き込み後、先読みが必要か判断します。
 3)の場合は先読み不要でそれ以外の場合は先読みが必要になります。
 DMAの内容をSDバッファに書き込み、変更フラグをオンにし、2)の場合は即座にSDバッファ内容をSDに書き込みます(変更フラグはオフにする)。

 ReadSector処理に関してはSDバッファにヒットしている場合はSDバッファからセクタ内容を読み取り、ヒットしない場合は変更フラグがオンの場合SDバッファを書込んだ後、必要なSDブロックの内容をSDバッファに読込みます。
 SDバッファにヒットした場合、変更フラグがオンでもSDへの書込みは不要ですが、今回は長時間変更フラグがオンになる(その間、電源断等が発生すると書込み情報が失われる)のを避けるため、ReadSector処理ではありますがSDへの書込みを行うようにしました。

 文章で書くと少しややこしいですが、プログラム的には若干の追加で対応可能です。
 (ワークエリアはSDバッファが4倍に増えるけどプログラムコードのサイズはあまり増えない)

 参考に今回対応したBIOSのReadSectorとWriteSectorの部分の抜粋を以下に貼っておきます。

BIOS内ブロッキング/デブロッキング処理
212 * caliculate sector number 213 * d2 -> logical sector number in buffer 214 * d3 -> SD block No 215 CalSdSec: 216 0000017A 4283 clr.l d3 217 0000017C 363900000002 move.w track,d3 218 00000182 ED8B lsl.l #SEC_TR_SFT,d3 219 00000184 4282 clr.l d2 220 00000186 343900000004 move.w sector,d2 221 0000018C D682 add.l d2,d3 222 0000018E 2403 move.l d3,d2 223 00000190 028200000003 andi.l #$03,d2 * logical sec in buffer 224 00000196 E48B lsr.l #SD_SFT,d3 225 00000198 4E75 rts 226 227 * read sector 228 * d0.w -> 0:no error, 1:error 229 read: 230 0000019A 610000A8 bsr flush * if no error then d0.w=0 231 0000019E 66000038 bne rdend * if error 232 000001A2 61D6 bsr CalSdSec 233 000001A4 B6A90002 cmp.l OSdSec(a1),d3 234 000001A8 67000014 beq rd010 * if hit buffer 235 236 000001AC 12BC0004 move.b #FC_READ,(a1) 237 000001B0 23430002 move.l d3,OSdSec(a1) 238 000001B4 4E70 reset 239 000001B6 30290006 move.w ORetVal(a1),d0 * get return val 240 000001BA 6600001C bne rdend * if error 241 242 000001BE C4FC0080 rd010: mulu #SEC_SIZE,d2 243 000001C2 D4BC0007FE00 add.l #PICDMA,d2 244 000001C8 2042 move.l d2,a0 245 000001CA 247900000006 move.l dma,a2 246 000001D0 747F moveq #(SEC_SIZE-1),d2 247 000001D2 14D8 rdcpy: move.b (a0)+,(a2)+ * DMA is able to be odd 248 000001D4 51CAFFFC dbf d2,rdcpy 249 000001D8 4E75 rdend: rts 250 251 252 * write sector 253 * d1.w <- 0:normal write 1:directory write 2:write to first sector of new block 254 * d0.w -> 0:no error, 1:error 255 write: 256 000001DA 4280 clr.l d0 * set no error value 257 000001DC 619C bsr CalSdSec 258 000001DE B6A90002 cmp.l OSdSec(a1),d3 259 000001E2 67000024 beq wr010 * if hit buffer 260 261 000001E6 6100005C bsr flush 262 000001EA 66000056 bne wrend * if error 263 264 000001EE 23430002 move.l d3,OSdSec(a1) 265 000001F2 B27C0002 cmp.w #2,d1 266 000001F6 67000010 beq wr010 * if new block 267 268 000001FA 12BC0004 move.b #FC_READ,(a1) 269 000001FE 4E70 reset 270 00000200 30290006 move.w ORetVal(a1),d0 * get return val 271 00000204 6600003C bne wrend * if error 272 273 00000208 C4FC0080 wr010: mulu #SEC_SIZE,d2 274 0000020C D4BC0007FE00 add.l #PICDMA,d2 275 00000212 2042 move.l d2,a0 276 00000214 247900000006 move.l dma,a2 277 0000021A 747F moveq #(SEC_SIZE-1),d2 278 0000021C 10DA wrcpy: move.b (a2)+,(a0)+ 279 0000021E 51CAFFFC dbf d2,wrcpy 280 281 00000222 13FC000100000001 move.b #1,ChgFlg * set change flag 282 0000022A B27C0001 cmp #1,d1 283 0000022E 66000012 bne wrend * if not directory wite 284 285 00000232 423900000001 clr.b ChgFlg 286 00000238 12BC0005 move.b #FC_WRITE,(a1) 287 0000023C 4E70 reset 288 0000023E 30290006 move.w ORetVal(a1),d0 * get return val 289 00000242 4E75 wrend: rts 290 291 292 * flush disk 293 * d0.w -> 0:no err, $ffff:cann't flush 294 00000244 4240 flush: clr.w d0 295 00000246 103900000001 move.b ChgFlg,d0 296 0000024C 67000012 beq flend 297 00000250 423900000001 clr.b ChgFlg 298 00000256 12BC0005 move.b #FC_WRITE,(a1) 299 0000025A 4E70 reset 300 0000025C 30290006 move.w ORetVal(a1),d0 * get return val 301 00000260 4E75 flend: rts 302 303


 ブロッキング/デブロッキング対処後の動作例として「XMODEMアプリの作成」の記事で載せたxmodemでのファイル送信中のロジアナ波形のbefore/Afterを貼っておきます。

Before


 対処後は下図の赤丸部分に示すようにSDカードのアクセス回数が減少しています。

After


★2018/10/17 追記
 コメントに書いたようにCP/MからBIOSのWriteSectorには新たに確保したブロックの最初のセクタ書込み(D1レジスタ=2)であるという情報が渡されています。
 今回はCP/Mのブロックサイズを2048バイトにしているので、この情報からSDカードの4ブロック分(SDカードのブロックサイズは512バイト)、先読み無しで書込んでも問題ないはずなので改善してみました。
 ワークエリアとして新たに先読み不要カウンタと先読み無しで書込んだブロック番号の保存用ワークを追加して、念のためにSDカードのブロック番号が連番であることも確認するようにしています。
 また、ワークエリアを絶対アドレス指定でアクセスするとコード効率が悪くなるのでアドレスレジスタとのオフセットでアクセスするように一部変更しました。

 CP/Mの2ブロック分をバイナリモードで単純に書き込むテストプログラムを作りSDカードへの書込み動作を確認してみました。新規ファイルへの書込み動作のみを確認するためにファイルオープン後の書込み開始前と書込み終了後のファイルクローズ前にキー入力処理を入れることでファイルへの書込み中の波形をロジアナで確認しました。

 下のキャプチャがロジアナ波形のBefore/After比較になります。

 対処前はCP/Mブロックの最初の書込みだけ先読みがない状態なのでSDへの書込みの4回に3回は先読みが発生しています。

Before


 改善後は新規書込みの場合、常に先読み無しでSDカードへの書込みが行われていて想定通りの動作になっています。

After


 今回、CPM.SYSを何度か変更して評価するにあたり、CP/M-68Kで採用されているCP/Mローダのおかげで、AドライブのCPM.SYSファイルを入れ替えてCP/Mを再立ち上げするだけでいいので効率的に作業が出来ました。

 CP/Mのファイルセットに含まれているサイズが大きめのDDT68000.68K(431セクタ、54KB)のファイルをpipコマンドで空ディスクにコピーする時間を計ってみたところ 5.2秒から4.9秒に改善されました(あまり変わらないですねw)


[TOP] [ 前へ ] 連載記事 [ 次へ ]

nice!(0)  コメント(2) 
共通テーマ:趣味・カルチャー

nice! 0

コメント 2

skyriver

今回、CP/Mのディスク定義でblocksizeを2048にしているのでBIOSのWriteSectorがコールされた際、「d1.w = 2 : write to first sector of new block」であれば、SDのブロックが連番で4ブロックの書込みであれば、4ブロック分先読み無しで行けそうですね。
by skyriver (2018-10-15 23:01) 

skyriver

上のコメントに書いたように新規書込みの場合、先読み無しになるように改善し、記事に追記しました。
by skyriver (2018-10-17 00:36) 

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。