結局C言語で作った
スクラッチビルドで、初期化からCMD25(マルチプルブロックライト命令)でMMCに512byte(=1 block)書き込む命令を書いてみました。すべて自前のプログラムなので自由に使ってください。(もちろん無保証)
HEWのVersion 4.00.00.027でコンパイルし、メモリーは(東芝のminiSD 128MB)にて動作確認しています。
ソースの書き方が大分汚いですけど。
プロセスの概略は
?CMD0発行
?CMD1発行(R1レスポンスが0x00になるまで繰り返し)
?CMD25発行(同上)
?0xfcを送信してマルチプルライトスタート
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
?512byte分データ送信
?ダミーCRC(0xFFでOK)2バイト送信
?データレスポンス確認(0x05になってればOK)
?ビジー(0x00)解除待ち
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
(※注1)
?ストップトークン(0xfd)送信
?ビジー解除待ち
(※注1)CMD25を送信する前にブロック長を指定していないため、Open-Ended Multiple Block Writeが実行されます。したがって連続してライトしたい場合は?〜?を繰り返せばよいことになります。停止させたいときは1ブロック分書き終わった区切りのところで、(ブロックの途中では無理)0xFDを送信して終了できます。
#includevoid set_CLK20(void); //////////////////////////////////////////////// void set_CLK20(void){ prc0=1; cm1=0x08; cm0=0x08; asm("nop"); asm("nop"); asm("nop"); asm("nop"); ocd2=0; prc0=0; } //////////////////////////////////////////////// // MMC read & write //////////////////////////////////////////////// #define MMC_SCS p3_4 void main(void){ char c,dummy; int w; set_CLK20(); //////////////// init port ///////////////////// p3=0b10010000; pd3=0b10010000; pd1_5 = 1; p1_5=1; sser=0; ssmr2= 0x41; sscrh=0x60; //master f1/256 ssmr=0x08; sssr=0; ///////////////////////////////////////////////// // MMC initialize // sser = 0x10 means te=1 re=0 // sser = 0x08 means te=0 re=1 ///////////////////////////////////////////////// sser = 0x10; //te=1 re=0 for(c=10;c!=0;c++) { while(!tdre_sssr); sstdr = 0xff; } while(!tend_sssr); //wait transmit ///////////////////////////////////////////////// // transmit CMD0 ///////////////////////////////////////////////// MMC_SCS = 0; sser = 0x10; //te=1 re=0 while(!tdre_sssr); sstdr = 0xff; //dummy while(!tend_sssr); while(!tdre_sssr); sstdr = 0x40; //CMD0=40_0000_0000_95h while(!tend_sssr); while(!tdre_sssr); sstdr = 0x00; while(!tend_sssr); while(!tdre_sssr); sstdr = 0x00; while(!tend_sssr); while(!tdre_sssr); sstdr = 0x00; while(!tend_sssr); while(!tdre_sssr); sstdr = 0x00; while(!tend_sssr); while(!tdre_sssr); sstdr = 0x95; while(!tdre_sssr); while(!tend_sssr); //wait trans end //---------------------------- // wait R1 resp //---------------------------- sser = 0x08; //te=0 re=1 rsstp_sscrh=1; //receive 1 byte dummy = ssrdr; //dummy read for(w=16;w!=0;w--) { while(!rdrf_sssr); //wait resp dummy = ssrdr; if(!(dummy & 0x80))break; }//timed out ///////////////////////////////////////////////// // transmit CMD1 ///////////////////////////////////////////////// do{ sser = 0x10; //te=1 re=0 orer_sssr = 0; //clear overrun flag while(!tdre_sssr); sstdr = 0xff; //dummy while(!tend_sssr); while(!tdre_sssr); sstdr = 0x41; //CMD1=41_00FF_8000_99h while(!tend_sssr); while(!tdre_sssr); sstdr = 0x00; while(!tend_sssr); while(!tdre_sssr); sstdr = 0xff; while(!tend_sssr); while(!tdre_sssr); sstdr = 0x80; while(!tend_sssr); while(!tdre_sssr); sstdr = 0x00; while(!tend_sssr); while(!tdre_sssr); sstdr = 0x99; while(!tdre_sssr); while(!tend_sssr); //wait trans end //---------------------------- // wait R1 resp //---------------------------- sser = 0x08; //te=0 re=1 orer_sssr=0; //clear overrun flag rsstp_sscrh=1; //receive 1 byte dummy = ssrdr; //dummy read for(w=16;w!=0;w--) { while(!rdrf_sssr); //wait resp dummy = ssrdr; if(!(dummy & 0x80))break; }//timed out }while(dummy != 0x00); for (w=100;w!=0;w--); //wait exiting In-Idle-State // sser = 0; sscrh = 0x66; //master, f1/4 ///////////////////////////////////////////////// // transmit CMD25(multiple write) ///////////////////////////////////////////////// do{ sser = 0x10; //te=1 re=0 orer_sssr = 0; //clear overrun flag while(!tdre_sssr); sstdr = 0xff; //dummy while(!tend_sssr); while(!tdre_sssr); sstdr = 0x59; //CMD25=59_0000_0000_01h while(!tend_sssr); while(!tdre_sssr); sstdr = 0x00; while(!tend_sssr); while(!tdre_sssr); sstdr = 0x00; while(!tend_sssr); while(!tdre_sssr); sstdr = 0x00; while(!tend_sssr); while(!tdre_sssr); sstdr = 0x00; while(!tend_sssr); while(!tdre_sssr); sstdr = 0x01; while(!tdre_sssr); while(!tend_sssr); //wait trans end //---------------------------- // wait R1 resp //---------------------------- sser = 0x08; //te=0 re=1 orer_sssr = 0; //clear overrun flag rsstp_sscrh = 1; //receive 1 byte dummy = ssrdr; //dummy read for(w=16;w!=0;w--) { while(!rdrf_sssr); //wait resp dummy = ssrdr; if(!(dummy & 0x80))break; }//timed out }while(dummy != 0x00); //---------------------------- // start writing //---------------------------- while(!rdrf_sssr); sser = 0x10; //te=1 re=0 orer_sssr = 0; //clear overrun flag while(!tdre_sssr); sstdr = 0xfc; //multiple write start token while(!tend_sssr); for(w=512;w!=0;w--){ while(!tdre_sssr); sstdr = 0xAA; //write 512byte Data while(!tend_sssr); } while(!tdre_sssr); sstdr = 0xff; //CRC while(!tend_sssr); while(!tdre_sssr); sstdr = 0xff; //CRC while(!tend_sssr); //---------------------------- // receive resp. //---------------------------- while(!tdre_sssr); sser = 0x08; //te=0 re=1 orer_sssr=0; //clear overrun flag rsstp_sscrh=1; //receive 1 byte dummy = ssrdr; //dummy read while(1){ while(!rdrf_sssr); if((ssrdr&0x0f)==5)break; //get resp. } while(1){ while(!rdrf_sssr); if(ssrdr!=0)break; //wait busy } while(!rdrf_sssr); sser = 0x10; //te=1 re=0 orer_sssr = 0; //clear overrun flag while(!tdre_sssr); sstdr = 0xff; //dummy while(!tend_sssr); while(!tdre_sssr); sstdr = 0xfd; //stop tran token while(!tdre_sssr); while(!tend_sssr); //////////////////////////////////////////////// sser = 0x08; //te=0 re=1 orer_sssr=0; //clear overrun flag dummy = ssrdr; while(1){ while(!rdrf_sssr); if(ssrdr!=0)break; //wait busy } }
次はリード命令(CMD18)です。