/****************************************************************/ // Sample for main.c // Add Monitor 2011.6.2 // Modify 2011.6.20 Bitcraft // Copyright Bitcraft Co.Ltd // All rights reserved. // // 外部バスを有効にし、CS3,CS4 を有効にする。2011.6.9 // コメントを追加 2011.6.20 // LEDの点滅サンプルソフトの、main.c と置き換えるだけで動作する。 // I/Oポート設定を、GCCでも可能なように変更 /****************************************************************/ #include // Include machine.h #include "iodefine.h" // Include iodefine.h #include "monitor.h" // 追加ファイル。モニタで使う定数や、プロトタイプ宣言など #include "rx62n.h" // RX62Nの内部I/Oアドレス設定 // #define SCBRR_SET 12 // ボーレート分周 // 以下、モニタを追加 char combuf[COLUMN]; char combuf2[COLUMN]; int combuf2f; union param32 param[16]; // 引数格納 int sdversion; int ts,te; int encrc; // 1で、CRC 計算を有効にする。 int togleled; unsigned char *sddbuf; unsigned char response[16]; unsigned char csdbuf[24]; unsigned char cidbuf[24]; union param32 cmdbuf[3]; void cprintf();// printf の簡易版。整数、文字列のみ int csprintf();// sprintf の簡易版。整数、文字列のみ // int mmcout(int); long execcommand(union param32 *param,int cmdcode); // control SD card int checkcommand(char *cp,union param32 *param,int len); int swap16b(int d); extern long getr0(void); // LED点滅ソフトの main.c の部分を改造 void main(void) { int i; // int data; // // SCI2 の入力ポートを有効に設定 // PORT1.ICR.BIT.B2 = 1; // SCI0 の入力ポートを有効に設定 // PORT2.ICR.BIT.B1 = 1; *PORT2ICR |= 2; // SCI0スタンバイ解除 // SYSTEM.MSTPCRB.BIT.MSTPB31 = 0; *MSTPCRB &= MSTPCRB_MSTPB31; // SCI2スタンバイ解除 // SYSTEM.MSTPCRB.BIT.MSTPB29 = 0; // CMT0,CMT1 スタンバイ解除 // MSTP( CMT0 ) = 0; // Wakeup CMT0,CMT1 bit addr = SYSTEM.MSTPCRA.BIT.MSTPA15 *MSTPCRA &= MSTPCRA_MSTPA15; // CMT0.CMCOR = 48000000/512/2 - 1; // CMCOR is 500ms Count 0xB71A // CMT0.CMCOR = 0xFFFF; // 最大まで。フリーランと同等 *CMCOR0 = 0xFFFF; // 最大まで。フリーランと同等 // CMT0.CMCR.WORD = 0x0083; // CMIE is disable,CKS is PCLK/512 10.6666 us *CMCR0 = 0x0083; // CMIE is disable,CKS is PCLK/512 10.6666 us // IEN( CMT0, CMI0 ) = 1; // CMI0 Enable // IPR( CMT0, CMI0 ) = 1; // CMI0 Interrupt Level is 1 // set_psw( 0x00010000 ); // Set I=1, IPL=0 of PSW // とりあえず、タイマー割り込みは使わない // タイマーをカウント。waittim0( x ) で使う // CMT.CMSTR0.BIT.STR0 = 1; // タイマーをスタートする *CMSTR0 = 1; // タイマーをスタートする // SCI0設定 // SCI0.SCR.BYTE = 0x00; // TE=0,RE=0,CKE1=0 *SCR0 = 0; // SCI0.SMR.BYTE = 0x00; // CHR=0,PE=0,STOP=0,CKS=00(Pφ/1) *SMR0 = 0; // SCI0.BRR = SCBRR_SET; // 分周設定 115200 bps SCBRR_SET=25:48000000/26/16 = 115384 *BRR0 = SCBRR_SET; // SCI0.SEMR.BIT.ABCS = 1; // ABCS=1 基本クロック16で1ビット期間 *SEMR0 = 0x00; for(i=0;i<0x800;i++);// 1bit時間以上ウェイト // SCI0.SCR.BYTE = 0x30; // TIE=0(D6),RIE=0(D7),TE=1(D5) 送信許可,RE=1(D4) 受信許可 *SCR0 = 0x30; // SCI2設定 // SCI2.SCR.BYTE = 0x00; // TE=0,RE=0,CKE1=0 // SCI2.SMR.BYTE = 0x00; // CHR=0,PE=0,STOP=0,CKS=00(Pφ/1) // SCI2.BRR = SCBRR_SET; // 分周設定 115200 bps SCBRR_SET=25:48000000/26/16 = 115384 // SCI2.SEMR.BIT.ABCS = 1; // ABCS=1 基本クロック16で1ビット期間 // for(i=0;i<0x800;i++);// 1bit時間以上ウェイト // SCI2.SCR.BYTE = 0x30; // TIE=0(D6),RIE=0(D7),TE=1(D5) 送信許可,RE=1(D4) 受信許可 // P15 is Output LED点灯。出力データは、初期ではLowになっている // PORT1.DDR.BIT.B5 = 1; *PORT1DDR |= 0x20; // 外部バス有効設定 CS3(P63,113pin)、CS4(P64,114pin)を、出力に設定する。 // SDカードの制御とは直接関係無い // SYSTEM.SYSCR0.WORD = 0x5A03; // KEY code = 0x5A 外部バス有効 *SYSTEM_SYSCR0 = 0x5A03; // KEY code = 0x5A 外部バス有効 // IOPORT.PF0CSE.BYTE = 0x18; // CS3,CS4 有効 *IOPORT_PF0CSE = 0x18; // CS3,CS4 有効 // IOPORT.PF1CSS.BYTE = 0x00; // CS4=P64 *IOPORT_PF1CSS = 0x00; // CS4=P64,CS5=P65,CS6=P66,CS7=P67 // IOPORT.PF2CSS.BYTE = 0x00; // CS3=P63 *IOPORT_PF2CSS = 0x00; // CS0=P60,CS1=P61,CS2=P62,CS3=P63 // IOPORT.PF3BUS.BYTE = 0xFF; // A16--A23 出力有効 *IOPORT_PF3BUS = 0xFF; // A16--A23 出力有効 // IOPORT.PF4BUS.BYTE = 0xFF; // A0--A15 出力有効 *IOPORT_PF4BUS = 0xFF; // A0--A15 出力有効 // IOPORT.PF5BUS.BYTE = 0x50; // P90--P93 を、A16--A19 に設定、D8--D15 をデータバス、P51 をWR1 *IOPORT_PF5BUS = 0x50; // P90--P93 を、A16--A19 に設定、D8--D15 をデータバス、P51 をWR1 // IOPORT.PF6BUS.BYTE = 0x01; // P55 を、外部バス WAIT 入力 *IOPORT_PF6BUS = 0x01; // P55 を、外部バス WAIT 入力 // BSC.CS3CR.WORD = 0x0001; // CS3 を有効。外部16ビットバス *BSC_CS3CR = 0x0001; // CS3 を有効。外部16ビットバス // BSC.CS4CR.WORD = 0x0001; // CS4 を有効。外部16ビットバス *BSC_CS4CR = 0x0001; // CS4 を有効。外部16ビットバス // SYSTEM.SCKCR.LONG = 0x10100; // ICLK=96MHz,BCLK=48MHz,PCLK=48MHz *SYSTEM_SCKCR = 0x10100; // ICLK=96MHz,BCLK=48MHz,PCLK=48MHz // 同じCSへの連続アクセスのとき、RD,WR が、連続的にLowにならないようにする。 // BSC.CS3WCR2.LONG= 0x00000011; // CS3 の、RD,WR のネゲートの後、1クロックのHighを設ける *BSC_CS3WCR2 = 0x00000011; // CS3 の、RD,WR のネゲートの後、1クロックのHighを設ける // BSC.CS4WCR2.LONG= 0x00000011; // CS4 の、RD,WR のネゲートの後、1クロックのHighを設ける *BSC_CS4WCR2 = 0x00000011; // CS4 の、RD,WR のネゲートの後、1クロックのHighを設ける // PORTD.DDR.BYTE = 0xFF; // D0--D7 データバス // *PORTDDDR = 0xFF; // D0--D7 データバス。この設定は必要なし // PORT5.DDR.BYTE = 0x0B; // BCLK を出力 *PORT5DDR = 0x0B; // BCLK を出力 // initmmc(1); // SPIモードでSDカードを使えるポート設定。 // CS_LOW(); // {PORT3.DR.BIT.B1 = 0;} *((char *)0x8C023) &= 0xFD /* while(1) { if (SCI0.SSR.BYTE & 0x40) { // データを受信したか。 パソコンのターミナルソフトから1文字送信すると、エコーバックする data = SCI0.RDR; SCI0.SSR.BYTE = SCI0.SSR.BYTE & 0x80; SCI0.TDR = data; SCI0.SSR.BYTE = SCI0.SSR.BYTE & 0x40; PORT1.DR.BIT.B5 ^= 1; // Reverse P15(LED) // break; } else if (SCI0.SSR.BYTE & 0x80) { // 送信バッファが空いているか // SCI0.TDR = 0x55; // SCI0.SSR.BYTE = SCI0.SSR.BYTE & 0x40; // break; } } */ while( 1 ) mainmoni(0); // モニタを呼び出す } // 割り込み処理は、そのまま残す #pragma interrupt CMI0(vect=VECT( CMT0, CMI0 )) void CMI0(void) // Interrupt Function { // Multiple Interrupt Enable // int data; // PORT1.DR.BIT.B5 ^= 1; // Reverse P15(LED) *PORT1DR ^= 1; /* while(1) { if (SCI0.SSR.BYTE & 0x40) { // データを受信したか。 パソコンのターミナルソフトから1文字送信すると、エコーバックする data = SCI0.RDR; SCI0.SSR.BYTE = SCI0.SSR.BYTE & 0x80; SCI0.TDR = data; SCI0.SSR.BYTE = SCI0.SSR.BYTE & 0x40; break; } else if (SCI0.SSR.BYTE & 0x80) { // 送信バッファが空いているか SCI0.TDR = 0x55; SCI0.SSR.BYTE = SCI0.SSR.BYTE & 0x40; break; } } RSPI.SPDR.LONG = 0x48; // Start transmission. 0x48をSPIポートから出力します。 // while (!RSPI.SPSR.BIT.SPRF) ; // Wait for end of transfer RSPI.SPDR.LONG; // Discard received data */ } // ここからが、モニタのBIOS // モニタを操作するのは、この3個のBIOSのみ。 // RS232Cから受信文字があると、1をリターン SCI0 int statcon() { int i; i = 0; // if (SCI0.SSR.BYTE & 0x40) if( *SSR0 & 0x40) i = 1; return i; } // ポート2の場合。RS232Cから受信文字があると、1をリターン SCI2 char statcon2() { int i; i = 0; // if (SCI2.SSR.BYTE & 0x40) if ( *SSR2 & 0x40) i = 1; return i; } // RS232Cから1文字受信するまで待つ。SIO0 int getcon() { int data; while(1) { // if (SCI0.SSR.BYTE & 0x40) if( *SSR0 & 0x40) break; } // data = SCI0.RDR; data = *RDR0; // SCI0.SSR.BYTE = SCI0.SSR.BYTE & 0x80; *SSR0 = *SSR0 & 0x80; return data; } // ポート2の場合。RS232Cから1文字受信するまで待つ。SIO2 char getcon2() { int data; while(1) { // if (SCI2.SSR.BYTE & 0x40) if ( *SSR2 & 0x40) break; } // data = SCI2.RDR; data = *RDR2; // SCI2.SSR.BYTE = SCI2.SSR.BYTE & 0x80; *SSR2 = *SSR2 & 0x80; return data; } // RS232Cに1文字出力。SIO0 void putcon(int c) { while(1) { // if (SCI0.SSR.BYTE & 0x80) if( *SSR0 & 0x80) break; } // SCI0.TDR = c; *TDR0 = c; } // RS232Cに1文字出力。SIO2 void putcon2(int c) { while(1) { // if (SCI2.SSR.BYTE & 0x80) if( *SSR2 & 0x80) break; } // SCI2.TDR = c; *TDR2 = c; } // 以下、最後までが、モニタの本体。main int mainmoni (int mode) { int ret,spacef; char *comp,c;//*cp; // int coma; int i,j,l; // int *lsp,*ldp; // int pret; combuf2f=0; combuf2[0] = 0; putscon("\r\nRX62N SD Card Monitor 2011.7.14\r\n"); while(1) { LOOP: putscon("RX62N-Bug>"); ret=getscon(combuf,COLUMN-1,0); if(ret == 0) { if(combuf2[0]) // 前回のコマンド記憶の先頭 { combuf2f = 1; ret = getscon(combuf,COLUMN - 1,0); if(ret == -1) { crlf(); goto LOOP; } spacef = cpynstr(combuf2,combuf,COLUMN); // コマンド記憶 } } else { if(ret == -1) { crlf(); goto LOOP; } spacef = cpynstr(combuf2,combuf,COLUMN); // memory command } comp=combuf; c= *comp; if((spacef & 0x1000) == 0)// コマンドにスペースを含んでいない // コマンド解析。最初の1文字で判定し、続く引数(ヘキサ限定)をチェック。 switch(c) { case 'd': j=0; comp++; if((*comp=='S')||(*comp=='s')) { j |= 1; comp++; } // if(j==0) { if(*comp ==0) { l = param[1].l32 - param[0].l32 + 2; l &= 0xfffffffe; param[0].l32 += l; param[1].l32 += l; } else { if((i=argck(&comp,param,1))== -1) { paramer(); break; } if(i==1) { param[1].l32=param[0].l32+0x7f; } } } dumpm(param,j); break; case 'm': j=0; comp++; if((*comp=='W')||(*comp=='w')) { j=1; comp++; } else if((*comp=='L')||(*comp=='l')) { j=2; comp++; } if((i=argck(&comp,param,3)) != 3) { paramer(); break; } // ts = CMT0.CMCNT; ts = *CMCNT0; movem(param,(long)j); // te = CMT0.CMCNT; te = *CMCNT0; break; // case 'V': case 'v': comp++; if((i=argck(&comp,param,3)) != 3) { paramer(); break; } // ts = CMT0.CMCNT; ts = *CMCNT0; verify(param); // te = CMT0.CMCNT; te = *CMCNT0; break; /* case 'F':// フィルデータ comp++; if((i=argck(&comp,param,5)) != 5) { paramer(); break; } ts = *CMCNT0; fillp(param); te = *CMCNT0; break; */ // データパターン4バイトまでを検索する。find case 'f': comp++; if((i=argck(&comp,param,4)) != 4) { paramer(); break; } // ts = CMT0.CMCNT; ts = *CMCNT0; findp(param); // te = CMT0.CMCNT; te = *CMCNT0; break; // 指定番地から実行する case 'g': comp++; if((i=argck(&comp,param,1))== -1) { paramer(); break; } // ts = CMT0.CMCNT; ts = *CMCNT0; ret = param[0].ppoint(); // ret = gosub((union param32)param[0].l32); // te = CMT0.CMCNT; te = *CMCNT0; cprintf("\r\nret= %08lX",ret); break; // case 'L': // ホストから送られるモトローラのSレコードをメモリにロードする。 case 'l': j=0; comp++; if((i=argck(&comp,param,1))== -1) { paramer(); break; } crlf(); srload(param,1); break; // set memory // 指定アドレスのメモリの変更。Byte,Word,Long word 単位の区別ができる。 // アドレス x として、sx(enter):Byte, swx(enter):Woed, slx(enter):Long word case 's': j=0; comp++; if((*comp=='N')||(*comp == 'n')) { j=4; comp++; } if((*comp=='W')||(*comp=='w')) { j |= 1; comp++; } else if((*comp=='L')||(*comp=='l')) { j |= 2; comp++; } param[2].l32 = 1; param[3].l32 = 0; param[4].l32 = 0; param[5].l32 = 0; param[6].l32 = 0; // param[7].l32 = 0; if((i=argck(&comp,param,1))== -1) { paramer(); break; } // ts = CMT0.CMCNT; ts = *CMCNT0; setmemo(param,j,i); // te = CMT0.CMCNT; te = *CMCNT0; break; // case 'D':// dhry stone テスト // ret = dhrymain(); // cprintf("\r\nTimer HEX = %lX,",ret); cprintf(" time = %ld",ret); // break; // コマンド 'S' はSDカードの操作コマンドに変更 case 'S': j = 0; comp++; if(*comp == 'i') { comp++; ret = sdctl(param,3); encrc = 0; mmcclk(0); cprintf("\r\nstop CRC check( dscrc ), SPI speed 24MHz ( clkspeed 0 )"); break; } if(*comp == 'r') { comp++; ret = argck(&comp,param,3); if(ret < 3) { putscon("\r\nSr start,memory,sectors"); break; } if(param[2].l32 > 0x400) { putscon("\r\nsectors must lower 0x401"); break; } ret = sdctl(param,1); break; } if(*comp == 'w') { comp++; ret = argck(&comp,param,3); if(ret < 3) { putscon("\r\nSr start,memory,sectors"); break; } if(param[2].l32 > 0x40) { putscon("\r\nsectors must lower 0x41"); break; } ret = sdctl(param,2); break; } if(*comp == 'R') { comp++; param[3].l32 = 0x20;// default 32 sector ret = argck(&comp,param,3); if(ret < 3) { putscon("\r\nSr start,memory,sectors"); break; } if(param[2].l32 > 0x40) { putscon("\r\nsectors must lower 0x41"); break; } ret = sdctl(param,4); break; } break; // タイマーのテスト case 't': comp++; j = 0; if(*comp == 'x') // program wait { j = 1; comp++; } if((i=argck(&comp,param,1))== -1) { paramer(); break; } if(j == 1) { // ts = CMT0.CMCNT; ts = *CMCNT0; while(param[0].l32--); // te = CMT0.CMCNT; te = *CMCNT0; } else waittim0(param[0].l32); break; // 時間計測ができるコマンドの、実行後の時間表示 // コマンドは、m,v,f,s,t case 'T': te &= 0xFFFF; ts &= 0xFFFF; l=te-ts; l &= 0xFFFF; // l /= 1000; cprintf("\r\nTimer HEX = %lX,",l); l *= 1067; l /= 100; // 48000000/512=93750Hz,1/93750=10.666666 μs cprintf(" time = %ld μs",l); break; // asm test // case 'r': // cprintf("\r\nR0 = %lx",getr0()); break; default: cprintf("default"); break; } else { ret = checkcommand(combuf,param,ret); if(ret != NOTFOUND) // SD CARD の操作コマンドか? { crlf(); execcommand(param,ret); // SD CARD の操作コマンドを実行 } } crlf(); } return 0; } // 引数で指定する 数値に、10.67μ秒 待つ。タイマーが停止していた場合のタイムアウト機能あり。 int waittim0(long l) { int s,e,e1; int ul; long timeout; // s = CMT0.CMCNT; s = *CMCNT0; s &= 0xFFFF; e1 = s; ul = 0; if(l > 0x10000) { ul = l >> 16; l &= 0xFFFF; } timeout = 0x4000000; while(ul) { // e = CMT0.CMCNT; e = *CMCNT0; e &= 0xFFFF; if((s == e) && (e != e1)) ul--; e1 = e; if(--timeout == 0) { if(ul) ul--; else break; timeout = 0x4000000; } } timeout = l * 0x100; while(l) { // e = CMT0.CMCNT; e = *CMCNT0; e &= 0xFFFF; if(((e - s) & 0xFFFF) >= l) break; if(--timeout == 0) break; } return 0; } // SDカード操作のコマンドを判定し、そうでなければ、−1を返す。 int checkcommand(char *cp,union param32 *param,int len) // len: command length { int ret; ret = cmpstr(cp,"mmcinit"); if((ret & 0x7f) == 7) // 7 chars { return MMCINIT; } ret = cmpstr(cp,"dscrc"); if((ret & 0x7f) == 5) // 5 chars { return DSCRC; } ret = cmpstr(cp,"encrc"); if((ret & 0x7f) == 5) // 5 chars { return ENCRC; } ret = cmpstr(cp,"clkspeed"); if((ret & 0x7f) == 8) // 8 chars { cp = &cp[9]; ret = argck(&cp,param,1); if(ret != 1) { putscon("\r\nclkspeed 3b or lower"); return -1; } return CLKSPEED; } ret = cmpstr(cp,"crc7"); if((ret & 0x7f) == 4) // 8 chars { cp = &cp[5]; ret = argck(&cp,param,2); if(ret < 2) { putscon("\r\ncrc7 addr,byte"); return -1; } return CRC7; } ret = cmpstr(cp,"crc16"); if((ret & 0x7f) == 5) // 8 chars { cp = &cp[6]; ret = argck(&cp,param,2); if(ret < 2) { putscon("\r\ncrc16 addr,byte"); return -1; } return CRC16; } ret = cmpstr(cp,"checksects"); if((ret & 0x7f) == 10) // 8 chars { cp = &cp[11]; param[3].l32 = 1;// byte ret = argck(&cp,param,3); if(ret < 3) { putscon("\r\nchecksects start,sects,data"); return -1; } return CHECKSECTS; } ret = cmpstr(cp,"Si"); // automatic setup SD card if((ret & 0x7f) == 2) // 2 chars { return MMCREADY; } ret = cmpstr(cp,"Sr "); // read SD card. start sector,memory,sectors if((ret & 0x7f) == 3) // 3 chars Sr 0,4000,1 { if(len < 8) { putscon("\r\nex. Sr 0,4000,1"); // address = 0x4000 return -1; } cp = &cp[3]; ret = argck(&cp,param,3); if(ret != 3) { putscon("\r\nSr start,memory,sectors"); return -1; } // if(param[2].l32 > 0x20) // { // putscon("\r\nsectors must lower 0x21"); // return -1; // } // if((param[1].l32 + param[2].l32*0x200) return MMCREAD; } ret = cmpstr(cp,"Sw "); // write SD card. start sector,memory,sectors if((ret & 0x7f) == 3) // 3 chars { if(len < 8) { putscon("\r\nex. Sw 0,0,1"); return -1; } cp = &cp[3]; ret = argck(&cp,param,3); if(ret != 3) { putscon("\r\nSr start,memory,sectors"); return -1; } // if(param[2].l32 > 0x20) // { // putscon("\r\nsectors must lower 0x21"); // return -1; // } return MMCWRITE; } ret = cmpstr(cp,"cmd "); // CMD if((ret & 0x7f) == 4) // 4 chars { cp = &cp[4]; ret = argck(&cp,param,1); switch(param[0].l32) { case 0: param[1].l32 = 0; return CMD0; break; case 0x1: return CMD1; break; case 0x9: return CMD9; break; case 0x10: return CMD10; break; case 0x17: return CMD17; break; case 0x24: if(ret >= 3) param[3].l32=1; else param[3].l32=0; return CMD24; break; case 8: param[1].l32 = 0; return CMD8; break; case 0x58: return CMD58; break; case 0x41: param[0].l32 = 0x69; return ACMD41; break; } } return NOTFOUND; } // SDカード操作のコマンドを実行する、 long execcommand(union param32 *param,int cmdcode) // control SD card { int ret; int n,mark,i,k; // char dbuf[12]; union param32 adjustlittle; unsigned char *cp; cp = &cmdbuf[0].uc8[3]; switch(cmdcode) { case MMCINIT: // restart power ON sequence initmmc(1); sdversion = 0; break; case ENCRC: encrc = 1; break; case DSCRC: encrc = 0; break; case CLKSPEED: mmcclk(param[0].l32); break; case CRC7: ret = crc7c(param[0].ucpoint,param[1].l32); cprintf("CRC7 = %02X",ret & 0xFF); break; case CRC16: ret = crc16c(param[0].ucpoint,param[1].l32); cprintf("CRC16 = %04X",ret & 0xFFFF); break; case MMCREADY: // setup SD card ready initmmc(1); // power ON sequence sdversion = 0; // CMD0 cmdbuf[0].uc8[3] = 0x40; cmdbuf[1].l32 = 0; cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0x95 mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) break; } mmccs(1); mmcout(0xff); // putscon("\r\nCMD0 response = "); // CMD8 // hex8b((char)ret); cprintf("\r\nCMD0 response = %02X",ret); cmdbuf[0].uc8[3] = 0x48; cmdbuf[1].l32 = 0xaa010000;// 0x1aa // little endian cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0x87 mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } for(n=1;n<6;n++) { ret = mmcout(0xff); response[n] = ret; } mmccs(1); mmcout(0xff); // putscon("\r\nCMD8 response = "); // hex8b(response[0]); cprintf("\r\nCMD8 response = %02X",response[0]); putscon(" card interface = "); for(ret = 1;ret<7;ret++) { n = response[ret]; // hex8b(n & 0xff); // putcon(' '); cprintf("%02X ",n & 0xFF); } // CMD58 for(k=0;k<2;k++) { cmdbuf[0].uc8[3] = 0x7a; cmdbuf[1].l32 = 0x0; cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0xaf mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } for(n=1;n<7;n++) { ret = mmcout(0xff); response[n] = ret; } mmccs(1); mmcout(0xff); // putscon("\r\nCMD58 response = "); // hex8b(response[0]); cprintf("\r\nCMD58 response = %02X",response[0]); putscon(" OCR = "); for(ret = 1;ret<7;ret++) { n = response[ret]; // hex8b(n & 0xff); // putcon(' '); cprintf("%02X ",n & 0xff); } if(response[1] & 0x40) { sdversion |= 2; } if(response[0] == 1) break; } // ACMD41 ( CMD55,ACMD41 ) for(k=0;k<1000;k++) { cmdbuf[0].uc8[3] = 0x77; // 0x37 = 55 cmdbuf[1].l32 = 0x0; cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<10;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } mmcout(0xff); cmdbuf[0].uc8[3] = 0x69; // ACMD41 cmdbuf[1].l32 = 0x0080FF40;//0x40FF8000; // little endian cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<10;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[1] = ret; break; } } mmccs(1); mmcout(0xff); if(response[0] == 0) { // putscon("\r\nACMD41 response 55 = "); hex8b(response[0]); cprintf("\r\nACMD41 response 55 = %02X",response[0]); // putscon(" response 41 = "); hex8b(response[1]); cprintf(" response 41 = %02X",response[1]); sdversion |= 1; cprintf(" ACMD41 count = %d ( %ld ms )",k,k*43); break; } waittim0(4000); // 10.67us x 4000 = 42.68ms } // CMD58 cmdbuf[0].uc8[3] = 0x7a; cmdbuf[1].l32 = 0x0; cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0xaf mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } for(n=1;n<7;n++) { ret = mmcout(0xff); response[n] = ret; } mmccs(1); mmcout(0xff); // putscon("\r\nCMD58 response = "); // hex8b(response[0]); cprintf("\r\nCMD58 response = %02X",response[0]); putscon(" OCR = "); for(ret = 1;ret<7;ret++) { n = response[ret]; // hex8b(n & 0xff); // putcon(' '); cprintf("%02X ",n & 0xff); } if(response[1] & 0x40) { sdversion |= 2; } // CMD9 ( get CSD ) cmdbuf[0].uc8[3] = 0x49; cmdbuf[1].l32 = 0x0; cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0xaf mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { csdbuf[0] = ret; break; } } for(n=1;n<22;n++) { ret = mmcout(0xff); csdbuf[n] = ret; } mmccs(1); mmcout(0xff); // putscon("\r\nCMD9 response = "); // hex8b(response[0]); cprintf("\r\nCMD9 response = %02X",response[0]); putscon("\r\n CSD = "); mark = 0; for(ret = 1;ret<22;ret++) { n = csdbuf[ret]; n &= 0xFF; // hex8b(n); // putcon(' '); cprintf("%02X ",n & 0xff); if((n == 0xFE)&&(mark == 0)) { mark = ret + 1; } } if((csdbuf[mark] & 0xC0) == 0x40) { putscon("\r\n CSD Version 2.0 SDHC"); sdversion |= 0xC; ret = csdbuf[mark + 7]; ret <<= 8; n = csdbuf[mark + 8]; n &= 0xFF; ret |= n; ret <<= 8; n = csdbuf[mark + 9]; n &= 0xFF; ret |= n; ret++; ret >>= 1; putscon(" 0x"); if(ret & 0xFFFF0000) { // hex32b(ret); cprintf("%lX",ret); } else // hex16b((short)(ret & 0xFFFF)); cprintf("%X",ret); putscon(" MB "); cprintf("%ld MB",ret); } else if((csdbuf[mark] & 0xC0) == 0x0) { putscon("\r\n CSD Version 1.0"); sdversion |= 0x8; k = ((csdbuf[mark+9]) & 0x3) << 1; k |= ((csdbuf[mark+10]) & 0x80) >> 7; k = 1 << (k+2); i = (csdbuf[mark+5]) & 0xF; // READ_BL_LEN i = 1 << i; i *= k; k = ((csdbuf[mark+6]) & 3) << 10; k |= ((csdbuf[mark+7]) & 0xFF) << 2; k |= (((csdbuf[mark+8])>>6) & 3); k++; // cprintf("C_SIZE = %3X + 1 = %d x %d\n",k,k+1,i); putscon(" C_SIZE = 0x"); if(k & 0xFFFF0000) // hex32b(k); cprintf("%lX",k); else // hex16b((short)k); cprintf("%X",k); putscon(" x 0x"); i >>= 10; if(i & 0xFFFF0000) // hex32b(i); cprintf("%08lX",i); else // hex16b((short)i); cprintf("%04X",i); putscon(" kB "); cprintf("%ld kB ",i*k); } break; case CMD0: cmdbuf[0].uc8[3] = 0x40; cmdbuf[1].l32 = 0; cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0x95 mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) break; } mmccs(1); mmcout(0xff); // putscon("response = "); // hex8b((char)ret); cprintf("response = %02X",ret); break; case CMD1: cmdbuf[0].uc8[3] = 0x41; cmdbuf[1].l32 = 0; cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0x95 mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) break; } mmccs(1); mmcout(0xff); // putscon("response = "); // hex8b((char)ret); cprintf("response = %02X",ret); break; case CMD8: cmdbuf[0].uc8[3] = 0x48; cmdbuf[1].l32 = 0xaa010000;//0x1aa; // little endian cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0x87 mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } for(n=1;n<6;n++) { ret = mmcout(0xff); response[n] = ret; } mmccs(1); mmcout(0xff); // putscon("response = "); // hex8b(response[0]); cprintf("response = %02X",response[0]); putscon(" card interface = "); for(ret = 1;ret<7;ret++) { n = response[ret]; // hex8b(n & 0xff); // putcon(' '); cprintf("%02X ",n & 0xff); } break; case CMD9: cmdbuf[0].uc8[3] = 0x49; cmdbuf[1].l32 = 0x0; cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0xaf mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { csdbuf[0] = ret; break; } } for(n=1;n<22;n++) { ret = mmcout(0xff); csdbuf[n] = ret; } mmccs(1); mmcout(0xff); // putscon("response = "); // hex8b(csdbuf[0]); cprintf("response = %02X",csdbuf[0]); putscon("\r\nCSD = "); mark = 0; for(ret = 1;ret<22;ret++) { n = csdbuf[ret]; n &= 0xFF; // hex8b(n); // putcon(' '); cprintf("%02X ",n & 0xff); if((n == 0xFE)&&(mark == 0)) { mark = ret + 1; } } if((csdbuf[mark] & 0xC0) == 0x40) { putscon("\r\nCSD Version 2.0 SDHC"); sdversion |= 0xC; ret = csdbuf[mark + 7]; ret <<= 8; n = csdbuf[mark + 8]; n &= 0xFF; ret |= n; ret <<= 8; n = csdbuf[mark + 9]; n &= 0xFF; ret |= n; ret++; ret >>= 1; putscon(" 0x"); if(ret & 0xFFFF0000) { // hex32b(ret); cprintf("%08lX",ret); } else // hex16b((short)(ret & 0xFFFF)); cprintf("%04X",(short)(ret & 0xFFFF)); putscon(" MB "); cprintf("%ld",k); } else if((csdbuf[mark] & 0xC0) == 0x0) { putscon("\r\nCSD Version 1.0"); sdversion |= 0x8; k = ((csdbuf[mark+9]) & 0x3) << 1; k |= ((csdbuf[mark+10]) & 0x80) >> 7; k = 1 << (k+2); i = (csdbuf[mark+5]) & 0xF; // READ_BL_LEN i = 1 << i; i *= k; k = ((csdbuf[mark+6]) & 3) << 10; k |= ((csdbuf[mark+7]) & 0xFF) << 2; k |= (((csdbuf[mark+8])>>6) & 3); k++; // cprintf("C_SIZE = %3X + 1 = %d x %d\n",k,k+1,i); putscon(" C_SIZE = 0x"); if(k & 0xFFFF0000) // hex32b(k); cprintf("%08lX",i); else // hex16b((short)k); cprintf("%04X",(short)k); putscon(" x 0x"); i >>= 10; if(i & 0xFFFF0000) // hex32b(i); cprintf("%08lX",i); else // hex16b((short)i); cprintf("%04X",(short)i); putscon(" kB "); cprintf("%ld kB ",i*k); } break; case CMD10: cmdbuf[0].uc8[3] = 0x4a; cmdbuf[1].l32 = 0x0; cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0xaf mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { cidbuf[0] = ret; break; } } for(n=1;n<22;n++) { ret = mmcout(0xff); cidbuf[n] = ret; } mmccs(1); mmcout(0xff); putscon("CID = "); for(ret = 0;ret<22;ret++) { n = cidbuf[ret]; // hex8b(n & 0xff); // putcon(' '); cprintf("%02X ",n & 0xff); } break; case CMD58: cmdbuf[0].uc8[3] = 0x7a; cmdbuf[1].l32 = 0x0; cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0xaf mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } for(n=1;n<7;n++) { ret = mmcout(0xff); response[n] = ret; } mmccs(1); mmcout(0xff); putscon("OCR = "); for(ret = 0;ret<7;ret++) { n = response[ret]; // hex8b(n & 0xff); // putcon(' '); cprintf("%02X ",n & 0xff); } if(response[1] & 0x40) { sdversion |= 2; } break; case ACMD41: cmdbuf[0].uc8[3] = 0x77; // 0x37 = 55 cmdbuf[1].l32 = 0x0; cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<10;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } mmcout(0xff); cmdbuf[0].uc8[3] = 0x69; // ACMD41 cmdbuf[1].l32 = 0x0080FF40;//0x40FF8000; // little endian cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<10;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[1] = ret; break; } } mmccs(1); mmcout(0xff); // putscon("response 55 = "); hex8b(response[0]); cprintf("\r\nresponse 55 = %02X ",response[0]); // putscon(" response 41 = "); hex8b(response[1]); cprintf(" response 41 = %02X ",response[1]); if(response[0] == 0) sdversion |= 1; // cprintf("ack 55 = %02X ack41 = %02X",csdbuf[0],csdbuf[1]); break; case CMD17: cmdbuf[0].uc8[3] = 0x51; // CMD17 // cmdbuf[1].l32 = param[1].l32; cmdbuf[1].uc8[0] = param[1].uc8[3]; // to little endian cmdbuf[1].uc8[1] = param[1].uc8[2]; cmdbuf[1].uc8[2] = param[1].uc8[1]; cmdbuf[1].uc8[3] = param[1].uc8[0]; cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } for(n=0;;n++) { ret = mmcout(0xff); ret &= 0xFF; if(ret != 0xFF) { response[1] = ret; break; } if(statcon()) { if(getcon() == 3) { putscon("STOP by console"); return 1; } } } for(n=0;n<516;n++) { ret = mmcout(0xff); sddbuf[n] = ret; } mmccs(1); mmcout(0xff); // putscon("read buffer address ="); // hex32b((long)(&sddbuf[0])); cprintf("read buffer address = %08X",(long)(&sddbuf[0])); crlf(); for(ret = 0;ret<516;ret++) { n = sddbuf[ret]; // cprintf("%02X ",n & 0xff); // if((lines & 0xF) == 0xF) // crlf(); } ret = crc16c(&sddbuf[0],512); // cprintf(" calc crc16 = %04X",(short)(ret & 0xFFFF)); // putscon("return crc16 = "); // hex8b(sddbuf[512]); // hex8b(sddbuf[513]); cprintf("return crc16 = %02X%02X",sddbuf[512],sddbuf[513]); // putscon(" calc crc16 = "); // hex16b((short)(ret & 0xFFFF)); cprintf(" calc crc16 = %04X",(short)(ret & 0xFFFF)); // putscon("\r\nresponse = "); // hex8b(response[0]); // hex8b(response[1]); cprintf("\r\nresponse = %2X%02X",response[0],response[1]); break; case MMCREAD: for(k=0;k>8); // crc16 mmcout(mark); // crc16 for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0xFF) != 0xFF) { response[1] = ret; response[10] = ret; break; } } for(n=0;;n++) { ret = mmcout(0xff); ret &= 0xff; if(ret == 0xff) // レスポンスが0xFFになるまで待つ break; if(statcon()) { if(getcon() == 3) { putscon("STOP by console"); return 1; } } } mmccs(1); mmcout(0xff); // putscon("write buffer address ="); // hex32b((long)(&sddbuf[0])); cprintf("write buffer address =%lX",(long)(&sddbuf[0])); if((response[1] & 0xF) != 5) { // putscon("\r\nrespons error = "); // hex8b(response[1]); cprintf("\r\nrespons error = %02X",response[1]); return 1; } response[8] = (mark>>8); // save crc response[9] = (mark); // putscon("\r\ncommand response = "); // hex8b(response[0]); cprintf("\r\ncommand response = %02X",response[0]); // putscon(" wait ready count = 0x"); // hex32b(n); cprintf(" wait ready count = 0x%lX",n); // putscon(" write response = "); // hex8b(response[1]); cprintf(" write response = %02X",response[1]); if(param[3].l32) { // putscon("\r\ncorrect crc16 = "); // hex16b(mark ^ 0xFFFF); // putscon(" send crc16 = "); // hex16b(mark); cprintf("\r\ncorrect crc16 = %04X send crc16 = %04X",mark ^ 0xFFFF,mark); } break; case MMCWRITE: for(k=0;k>8); // crc16 mmcout(mark); // crc16 for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0xFF) != 0xFF) { response[1] = ret; response[10] = ret; break; } } for(n=0;;n++) { ret = mmcout(0xff); ret &= 0xff; if(ret == 0xff) break; if(statcon()) { if(getcon() == 3) { putscon("STOP by console"); return 1; } } } mmccs(1); mmcout(0xff); if((response[1] & 0xF) != 5) { // putscon("respons error = "); // hex8b(response[1]); cprintf("respons error = %02X",response[1]); return 1; } // if(sdversion & 4) param[0].l32++; // SDHC // else // param[0].l32 += 0x200; // normal SD response[8] = (mark>>8); response[9] = (mark); } break; case CHECKSECTS: checksects(param); break; } return 0; } // セクタのデータに、1〜4バイトの文字列があるかを探す。 int checksects(union param32 *param) { unsigned char chkbuf[512]; union param32 paramt[8]; int i,j,ret,count,countt; int pat1,pat2,pat3,pat4; unsigned char *cp; int mode; mode = param[2].l32; if((mode <= 0)||(mode >4)) mode = 1;// byte paramt[0].l32 = param[0].l32; pat4 = param[3].l32 & 0xFF; // LSB pat3 = (param[3].l32 >> 8) & 0xFF; pat2 = (param[3].l32 >> 16) & 0xFF; pat1 = (param[3].l32 >> 24) & 0xFF;// MSB countt = 0; for(i=0;i>8); // crc16 mmcout(mark); // crc16 for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0xFF) != 0xFF) { response[1] = ret; response[10] = ret; break; } } for(n=0;;n++) { ret = mmcout(0xff); ret &= 0xff; if(ret == 0xff) break; if(statcon()) { if(getcon() == 3) { putscon("CMD24 STOP by console"); return 1; } } } mmccs(1); mmcout(0xff); if((response[1] & 0xF) != 5) { putscon("respons error = "); cprintf("%02X",response[1]); return 1; } param[0].l32++; response[8] = (mark>>8); response[9] = (mark); } // te = CMT0.CMCNT; te = *CMCNT0; break; case 3: // poweron init initmmc(1); // power ON sequence sdversion = 0; // CMD0 cmdbuf[0].uc8[3] = 0x40; cmdbuf[1].l32 = 0; if(encrc) cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0x95 else cmdbuf[2].uc8[0] = 0x95; mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) break; } mmccs(1); mmcout(0xff); putscon("\r\nCMD0 response = "); // CMD8 // hex8b((char)ret); cprintf("%02X",ret); cmdbuf[0].uc8[3] = 0x48; cmdbuf[1].l32 = 0x1aa; // if(encrc) cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0x87 // else // cmdbuf[2].uc8[0] = 0x95;// dummy mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } for(n=1;n<6;n++) { ret = mmcout(0xff); response[n] = ret; } mmccs(1); mmcout(0xff); putscon("\r\nCMD8 response = "); // hex8b(response[0]); cprintf("%02X",response[0]); putscon(" card interface = "); for(ret = 1;ret<7;ret++) { n = response[ret]; // hex8b(n & 0xff); cprintf("%02X",n & 0xFF); putcon(' '); } // CMD58 for(k=0;k<2;k++) { cmdbuf[0].uc8[3] = 0x7a; cmdbuf[1].l32 = 0x0; if(encrc) cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0xaf else cmdbuf[2].uc8[0] = 0x95; mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } for(n=1;n<7;n++) { ret = mmcout(0xff); response[n] = ret; } mmccs(1); mmcout(0xff); putscon("\r\nCMD58 response = "); // hex8b(response[0]); cprintf("%02X",response[0]); putscon(" OCR = "); for(ret = 1;ret<7;ret++) { n = response[ret]; // hex8b(n & 0xff); cprintf("%02X",n & 0xff); putcon(' '); } if(response[1] & 0x40) { sdversion |= 2; } if(response[0] == 1) break; } // ACMD41 ( CMD55,ACMD41 ) for(k=0;k<1000;k++) { cmdbuf[0].uc8[3] = 0x77; // 0x37 = 55 cmdbuf[1].l32 = 0x0; if(encrc) cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // else cmdbuf[2].uc8[0] = 0x95; mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<10;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } mmcout(0xff); cmdbuf[0].uc8[3] = 0x69; // ACMD41 cmdbuf[1].l32 = 0x40FF8000; if(encrc) cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // else cmdbuf[2].uc8[0] = 0x95; for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<10;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[1] = ret; break; } } mmccs(1); mmcout(0xff); if(response[0] == 0) { putscon("\r\nACMD41 response 55 = ");cprintf("%02X",response[0]);// hex8b(response[0]); putscon(" response 41 = ");cprintf("%02X",response[1]);// hex8b(response[1]); sdversion |= 1; putscon(" ACMD41 count = "); cprintf("%d",k); putscon(" ("); cprintf("%ld",k); putscon(" ms )"); break; } waittim0(46); // 21.3us x 46 = 1ms } // CMD58 cmdbuf[0].uc8[3] = 0x7a; cmdbuf[1].l32 = 0x0; if(encrc) cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0xaf else cmdbuf[2].uc8[0] = 0x95; mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } for(n=1;n<7;n++) { ret = mmcout(0xff); response[n] = ret; } mmccs(1); mmcout(0xff); putscon("\r\nCMD58 response = "); cprintf("%02X",response[0]); putscon(" OCR = "); for(ret = 1;ret<7;ret++) { n = response[ret]; cprintf("%02X",n & 0xff); putcon(' '); } if(response[1] & 0x40) { sdversion |= 2; } // CMD9 ( get CSD ) cmdbuf[0].uc8[3] = 0x49; cmdbuf[1].l32 = 0x0; if(encrc) cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // 0xaf else cmdbuf[2].uc8[0] = 0x95; mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { csdbuf[0] = ret; break; } } for(n=1;n<23;n++) { ret = mmcout(0xff); csdbuf[n] = ret; } mmccs(1); mmcout(0xff); putscon("\r\nCMD9 response = "); cprintf("%02X",response[0]); putscon("\r\n CSD = "); mark = 0; for(ret = 0;ret<23;ret++) { n = csdbuf[ret]; n &= 0xFF; cprintf("%02X",n); putcon(' '); if((n == 0xFE)&&(mark == 0)) { mark = ret + 1; } } if((csdbuf[mark] & 0xC0) == 0x40) { putscon("\r\n CSD Version 2.0"); sdversion |= 0xC; ret = csdbuf[mark + 7]; ret <<= 8; n = csdbuf[mark + 8]; n &= 0xFF; ret |= n; ret <<= 8; n = csdbuf[mark + 9]; n &= 0xFF; ret |= n; ret++; ret >>= 1; putscon(" 0x"); if(ret & 0xFFFF0000) { // hex32b(ret); cprintf("%08lX",ret); } else // hex16b((short)(ret & 0xFFFF)); cprintf("%04X",ret); putscon(" MB "); cprintf("%5ld",ret); putscon(" MB"); } else if((csdbuf[mark] & 0xC0) == 0x0) { putscon("\r\n CSD Version 1.0"); sdversion |= 0x8; k = ((csdbuf[mark+9]) & 0x3) << 1; k |= ((csdbuf[mark+10]) & 0x80) >> 7; k = 1 << (k+2); i = (csdbuf[mark+5]) & 0xF; // READ_BL_LEN i = 1 << i; i *= k; k = ((csdbuf[mark+6]) & 3) << 10; k |= ((csdbuf[mark+7]) & 0xFF) << 2; k |= (((csdbuf[mark+8])>>6) & 3); k++; // cprintf("C_SIZE = %3X + 1 = %d x %d\n",k,k+1,i); putscon(" C_SIZE = 0x"); if(k & 0xFFFF0000) // hex32b(k); cprintf("%08lX",k); else // hex16b((short)k); cprintf("%04X",k); putscon(" x 0x"); i >>= 10; if(i & 0xFFFF0000) // hex32b(i); cprintf("%08lX",i); else // hex16b((short)i); cprintf("%04X",i); putscon(" kB "); cprintf("%7ld",k*i); putscon(" kB "); } break; case 4: // read multi sectors MMCREADM // ts = CMT0.CMCNT; ts = *CMCNT0; multi = param[3].l32; if(multi <= 0) multi = 0x20; block = param[2].l32 / multi; for(j=0;j>24; cmdbuf[1].uc8[1] = multi>>16; cmdbuf[1].uc8[2] = multi>>8; cmdbuf[1].uc8[3] = multi; // if(encrc) cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // else cmdbuf[2].uc8[0] = 0x95; mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } cmdbuf[0].uc8[3] = 0x52; // CMD18 if(sdversion & 4) adjustlittle.l32 = param[0].l32; else adjustlittle.l32 = param[0].l32 * 0x200; cmdbuf[1].uc8[0] = adjustlittle.uc8[3]; // adjust little endian. swap 32bit cmdbuf[1].uc8[1] = adjustlittle.uc8[2]; cmdbuf[1].uc8[2] = adjustlittle.uc8[1]; cmdbuf[1].uc8[3] = adjustlittle.uc8[0]; // if(encrc) cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // else cmdbuf[2].uc8[0] = 0x95; mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } for(n=0;;n++) { ret = mmcout(0xff); ret &= 0xFF; if(ret != 0xFF) { response[1] = ret; break; } if(statcon()) { if(getcon() == 3) { putscon("CMD18 STOP by console"); return 1; } } } for(k=0;k>24; cmdbuf[1].uc8[1] = block>>16; cmdbuf[1].uc8[2] = block>>8; cmdbuf[1].uc8[3] = block; if(encrc) cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // else cmdbuf[2].uc8[0] = 0x95; mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } cmdbuf[0].uc8[3] = 0x52; // CMD18 if(sdversion & 4) adjustlittle.l32 = param[0].l32; else adjustlittle.l32 = param[0].l32 * 0x200; cmdbuf[1].uc8[0] = adjustlittle.uc8[3]; // adjust little endian. swap 32bit cmdbuf[1].uc8[1] = adjustlittle.uc8[2]; cmdbuf[1].uc8[2] = adjustlittle.uc8[1]; cmdbuf[1].uc8[3] = adjustlittle.uc8[0]; // if(encrc) cmdbuf[2].uc8[0] = crc7c(&cmdbuf[0].uc8[3],5); // else cmdbuf[2].uc8[0] = 0x95; mmccs(0); for(i=0;i<6;i++) mmcout(cp[i]); for(n=0;n<9;n++) { ret = mmcout(0xff); if((ret & 0x80) == 0) { response[0] = ret; break; } } for(n=0;;n++) { ret = mmcout(0xff); ret &= 0xFF; if(ret != 0xFF) { response[1] = ret; break; } if(statcon()) { if(getcon() == 3) { putscon("CMD18 STOP by console"); return 1; } } } for(k=0;k> 8; a &= 0xff; b = d << 8; b &= 0xFF00; return a | b; } /*long gosub(union param32 addr) { return addr.ppoint(); } */ /* #define SIZE 2559 #define SIZEPL 2560 //char buf[SIZEPL]; sievemain() { long prime,k,i,count,iter; // long l,ts,te; // long time(); int n; char *buf; // l=0; // ppcDisable(); // cprintf("type return to do 10000 iterations:"); // getchar(); // ts=time(NULL); // scanf("%d",&n); buf = (char *)0x3200; for(iter=0;iter<1000;iter++) { count=0; // l=0; for(i=0;i<=SIZE;i++) { buf[i]=1; // l++; } for(i=0;i<=SIZE;i++) { if(buf[i]) { k=i+i+3; prime=k; k += i; // l++; for(;k= COLUMN-1)combuf2f=0; return c2; } else { combuf2f=0; return getcon(); } } else return getcon(); } /* コンソールからコマンドを入力して、コマンドバッファーに書く。 コントロール入力、その他の動作。以下の機能は、コメント行を適宜有効にすると動作する。 ctrl S: 1行入力中、カーソルを左に移動 ctrl D: 1行入力中、カーソルを右に移動 ctrl A: 1行入力中、カーソルを左端に移動 ctrl F: 1行入力中、カーソルを右端に移動 ctrl O: 上書きモードと挿入モードを切り替える。起動時は挿入モードになっている。 backspace: 1行入力中、カーソルの左の文字を消去してカーソルを1文字左に移動 */ int getscon(char *cp,int cn,int f) { int n,n2; char c; int s; int i; // int insf; n=0; n2=0; // insf=1; if(f & 2) // すでにバッファーには入力文字がいくつか有る { for(i=0;i'); for(i=0;i n) { for(i=n;i 0)) { n--; putcon(0x8); // back space code }*/ /* if((c == 'D'-0x40) && (n2 > n)) { putcon(cp[n++]); // edit point char }*/ if(((c=='\10') || (c==0x7f)) && (n)) { if(n == n2) { cp[n--]='\0'; n2--; putcon(0x8); // back space code putcon(0x20); // space code putcon(0x8); // back space code } /* else if((n2 > n) && (n)) { n--; putcon(0x8); /// back space code for(i=n;i= 0x20) && ((c & 0x7f) < 0x7f)) { if(n == n2) { cp[n++]=c; s=c; putcon(s); if(n > n2)n2=n; } /* else if(n2 > n) { if(insf) { for(i=n2-1;i>=n;i--) { cp[i+1]= cp[i]; } cp[n] = c; for(i=n;i=n) { return(count); } else { return(-1); } } else { if(c != ',')// コンマ以外はエラー return(-1); } } } void paramer(void) { putscon("\r\nPARAMETER ERROR !\r\n"); } // ヘキサ文字列から、バイナリーに変換する。 char htol(long *lp,char **cp) { char c; char *p; long l; short s; p= *cp; l=0l; while(1) { c= *p++; s = chex(c); if(s== -1) { *lp = l; *cp = p; return(c); } l <<= 4; l |= s; } } // メモリのコピー。Byte,Word,Long word 単位の指定ができる。 // 引数は、3個必要である。mx,y,z // コマンド m に対し最初の引数 x の間にオプションを挿入する。 // mx:Byte, mwx:Word, mlx:Long word void movem(union param32 *param,long ll) { register long l; register char *s,*d; register short *sp; long *lp,*ldp; short *dp; s=param[0].cpoint; sp=param[0].spoint; d=param[1].cpoint; dp=param[1].spoint; lp=param[0].lpoint; ldp=param[1].lpoint; l=param[2].l32; if(ll==0) { while(l--) { *d++ = *s++; } } else if(ll==1) { while(l--) { *dp++ = *sp++; } } else if(ll==2) { while(l--) { *ldp++ = *lp++; } } } // データパターンの検索 引数は、4個必要。単位はバイト列のみで、最大4バイトまで。 // fx,y,n,p x:比較元先頭アドレス, y:比較先の先頭アドレス, n:バイト数, p:データパターン(最大32ビット) // 例: ffffa0000,ffffff80,4,fffa0400 0xFFFA0000〜0xFFFFFF80まで、4バイトのバイト列で、 // 0xFF,0xFA,0x04, 0x00を探すして、あれば、アドレスを表示する。 void findp(union param32 *param) { register long bytec; register long l; register char *s,*d; /* register char c1,c2;*/ register short count; short shot; long ld; short lfn; s=param[0].cpoint; d=param[1].cpoint; bytec=param[2].l32; l=param[3].l32; if(bytec==0)return; if(bytec==1)l &= 0xffl; if(bytec==2)l &= 0xffffl; if(bytec==3)l &= 0xffffffl; lfn=0; crlf(); while(s != d) { ld=0; for(count=0;count=8) { lfn=0; crlf(); } if(statcon()) { if(getcon()==3)return; if(getcon()==3)return; } } s++; } } void dumpmt(void) { putscon("\r\nADDR 0 1 2 3 4 5 6 7 8 9 A B C D E F ascii\r\n"); } int dumpm(union param32 *param,int mode) { unsigned char *cp; // short *sp; short i,sum,ls; unsigned int s,sjf,l; union param32 u; unsigned char sbuf[16]; char c2; unsigned long len; // short sbuf[8]; if(param[0].ul32 > param[1].ul32) return 0; len = param[1].ul32 - param[0].ul32 + 1; cp=param[0].ucpoint; // sp=param[0].spoint; sjf=0; ls=0; if(mode==1) // dsxxxx { crlf(); u.ucpoint=param[0].ucpoint; while(1) { l = u.ul32; // if(hiki==3) l += param[2].l32; if(u.ul32 & 0xf) { if(param[1].ul32 >= (u.ul32 | 0xf)) { ls = (0x10 - (u.ul32 & 0xf)); // putscon("S3"); // hex8b(ls + 5); cprintf("S3%02X",ls + 5); sum = (0xff - ls - 5); } else { ls = param[1].ul32 - u.ul32 + 1; // putscon("S3"); // hex8b(ls + 5); cprintf("S3%02X",ls + 5); sum = (0xff - ls - 5); } } else if(param[1].ul32 >= (u.ul32 + 16)) { sum=0xEA; /* FF-15 */ ls = 16; putscon("S315"); } else { ls = param[1].ul32 - u.ul32 + 1; // putscon("S3"); // hex8b(ls + 5); cprintf("S3%02X",ls + 5); sum = (0xff - ls - 5); } cprintf("%08lX",l); // hex32b(l); sum -= (l >> 24) & 0xff; sum -= (l >> 16) & 0xff; sum -= (l >> 8) & 0xff; sum -= l & 0xff; for(i=0;i param[1].ul32) break; if(u.ul32 < param[0].ul32) break; if(statcon()) if(getcon()==3)break; } putscon("S70500000000FA\r\n"); } else { dumpmt(); param[0].l32 &= 0xfffffff0l; param[1].l32 &= 0xffffffffl; dumpmt(); while(1) { { // hex32b((long)cp); spacen(1); cprintf("%08lx ",(long)cp); for(i=0;i<16;i++) { s= *cp++; sbuf[i++]=s; // hex8b(s); cprintf("%02x",s); s= *cp++; sbuf[i]=s; // hex8b(s); cprintf("%02x",s); spacen(1); if(statcon()) { c2=getcon(); if((c2==3) || (c2==0xd))return(-1); c2=getcon(); if((c2==3) || (c2==0xd))return(-1); } } len -= 0x10; putcon('['); /* '[' */ s = ls; for(i=0;i<16;) { if(sjf) { s = sbuf[i++]; if(i==16) { sjf=0; break; } s <<= 8; sum = sbuf[i++]; sum &= 0xff; s |= sum; if(cksjis(s)) { putcon(s>>8); putcon((char)s); // i++; } else { ckasci(s>>8); sjf=0; // i++; } } else { s <<= 8; sum = sbuf[i++]; sum &= 0xff; s |= sum; if(cksjis(s)) { putcon(s>>8); putcon((char)s); sjf=1; } else { if(i==1) { putcon(' '); } else ckasci(s>>8); } } } if(sjf==0) ckasci(s); ls=s; putcon(']'); u.ucpoint=cp; if((u.ul32 > param[1].ul32) || (len <=0)) { return 0; } u.ucpoint=cp; if((u.l32 & 0xf)==0) { crlf(); if((u.l32 & 0xff)==0) dumpmt(); } } } } return 0; } // メモリダンプで、SJISコードの場合、漢字表示できるようにする。 // SJISコードで特定の処理をしてしまうターミナルソフトでは、正常に表示されない場合がある。 // テラタームでは、端末の受信漢字コードを、SJISに変更する。デフォルトでは、UTF-8 になっているので、 // 0x8A で、改行してしまうので、変更しておく。 int cksjis(unsigned int s) { int i; i = s>>8; i &= 0xff; if(((i>= 0x81) && (i<= 0x9f)) || ((i>= 0xE0) && (i<= 0xEF))) { s &= 0xff; if((s >= 0x40) && (s <= 0x7e)) return 1; if((s >= 0x80) && (s <= 0xfc)) return 1; } return 0; } // メモリの変更。Byte,Word,Long word 単位の指定ができる。 // 変更データを入力中に、'n' を入力すると、そのアドレスのデータを変更せずに、次のアドレスに進む。 // 同じく、'r' を入力すると、そのアドレスのデータを変更せずに、アドレスを戻す。 int setmemo(union param32 *param,int wf,int argc) { char *cp; short *sp; long *lp; // short s,j; /* union param32 u;*/ char buf[16]; long l,i,updatea,updated; char *c; int wof; wof=0; if(wf & 4) { wof=1; wf &= 3; } if(wf==1) { param[0].l32 &= 0xfffffffel; sp=param[0].spoint; } else if(wf==2) { /* param[0].l32 &= 0xfffffffcl;*/ lp=param[0].lpoint; } else { cp=param[0].cpoint; } if(argc >= 2) { // param[2] count param[3] update param[4] address segment param[5] adjust address update param[6] data update // default param[2].l32 = 1; // param[3].l32 = 0; // param[4].l32 = 0x0; // param[5].l32 = 0; // param[6].l32 = 0; updatea = param[4].l32; updated = param[1].l32; while(param[2].l32--) { switch(wf) { case 0: *cp++ = (char)updated; break; case 1: *sp++ = (short)updated; break; case 2: *lp++ = (long)updated; break; } updated = updated + param[3].l32; updatea--; if(updatea == 0) { updatea = param[4].l32; cp = &cp[param[5].l32]; sp = &sp[param[5].l32]; lp = &lp[param[5].l32]; param[1].l32 += param[6].l32; updated = param[1].l32; } } } if(argc == 1) while(1) { crlf(); if(wf==1) { cprintf("%08lX",(long)sp); // hex32b((long)sp); } else if(wf==2) { cprintf("%08lX",(long)lp); // hex32b((long)lp); } else { cprintf("%08lX",(long)cp); // hex32b((long)cp); } putcon('='); if(wof==0) { if(wf==1) { cprintf("%04X",*sp); // hex16b(*sp); } else if(wf==2) { cprintf("%08lX",*lp); } else { cprintf("%02X",(short)*cp & 0xff); } } putcon(' '); i=getscon(buf,15,1); if(i == -1)return(0); if(i>15) { if((i=='R')||(i=='r')) { if(wf==1) { sp--; } else if(wf==2) { lp--; } else { cp--; } } else if(((i=='X')||(i=='x'))&&(wof==1)) { if(wf==1) { cprintf("%04X",*sp); } else if(wf==2) { cprintf("%08lX",*lp); } else { cprintf("%02X",(short)*cp & 0xff); } putcon(' '); } else /* 'N' */ { if(wf==1) { sp++; } if(wf==2) { lp++; } else { cp++; } } } else { c=buf; if(*c == '.')break; htol(&l,&c); i=l; if(wf==1) { *sp++ = i; } else if(wf==2) { *lp++ = i; } else { *cp++ = i; } } } return 0; } int verify(union param32 *param) { register long l; register char *s,*d; register char c1,c2; short shot; s=param[0].cpoint; d=param[1].cpoint; l=param[2].l32; while(l--) { c1= *s; c2= *d; if(c1 != c2) { crlf(); cprintf("%08lX=",(long)s); // putcon('='); shot=c1; cprintf("%02X ",shot & 0xff); // spacen(1); cprintf("%08lX=",(long)d); // putcon('='); shot=c2; cprintf("%02X",shot & 0xff); if(statcon()) { if(getcon()==3)return(0); if(getcon()==3)return(0); } } s++; d++; } return(0); } /* コマンド文字の比較。Cの標準関数、strcmp とほとんど同じ。 機能追加は、どちらか先0だと、一致文字数 |0x8000 */ int cmpstr(char *d,char *s) { register int n; register char c1,c2; for(n=0;n c2) { return(1); } if(c1 < c2) { return(-1); } if((c1 == 0) && (c2 == 0)) { return(0); } } return(n); } /* int cmpstr(char *d,char *s) { register long l; register char c1,c2; l=250l; while(l--) { c1= *s++; c2= *d++; if(c1 > c2) { return(1); } if(c1 < c2) { return(-1); } if((c1 == 0) && (c2 == 0)) { return(0); } if((c1 == 0) || (c2 == 0)) break; } return(1); } */ // パソコンから送られてくるモトローラSレコード形式のヘキサデータを元に、メモリにロードする。 void srload(union param32 *param,int m) { /* extern short ring0v; extern short ring0r; */ char *cp,*cpb; // char *rp; register long l; register int i,j,k,sm; int ii,flag; long len; // char (*func)(); len=0; flag=0; // if(m==1) // func = (char (*)())getcon; // len=0; flag=0; SRLDL: if((i=getcon()) ==3) goto SRLDE; if(i != 'S')goto SRLDL; if((i=getcon())==3) goto SRLDE; if(i == '9') goto SRLDE; if(i == '8') goto SRLDE; if(i == '7') goto SRLDE; if(i == '0') goto SRLDL; if(i == '5') goto SRLDL; if((i >= '1') && (i <= '3')) { j=(i & 3)+1; /* dly(10);*/ if((i=getcon()) ==3) goto SRLDE; k=chex(i); /* dly(10);*/ if((i=getcon()) ==3) goto SRLDE; i=chex(i); k= k*16 + i; if(k==0) { i='9'; goto SRLDE; } sm = 0xFF; sm -= k; k--; l=0; while(j--) { /* dly(10);*/ if((i=getcon()) ==3) goto SRLDE; ii=chex(i); /* dly(10);*/ if((i=getcon()) ==3) goto SRLDE; ii = ii*16 +chex(i); sm -= ii; l = (l << 8) + ii; k--; } cp = param[0].cpoint; cp = &cp[l]; if(flag==0) { flag=1; cpb=cp; /* putscon("start loading address = ");*/ /* hex32b((long)cp);*/ /* crlf(); */ } while(k--) { /* dly(10);*/ if((i=getcon()) ==3) goto SRLDE; ii=chex(i); /* dly(10);*/ if((i=getcon()) ==3) goto SRLDE; ii = ii*16 + chex(i); sm -= ii; *cp++ = ii; len++; } /* dly(10);*/ if((i=getcon()) ==3) goto SRLDE; ii=chex(i); /* dly(10);*/ if((i=getcon()) ==3) goto SRLDE; ii = ii*16+ chex(i); if((sm & 0xFF) != (ii & 0xff)) { putscon("check sum error !! "); cprintf("%04X %04X",(short)sm,(short)ii);//cprintf(" %04X",(short)ii); i = -2; goto SRLDE; } goto SRLDL; } else { putscon("S1~S3 abarble\r\n"); return; } SRLDE: /* s0icls();*/ if(i == -1) { // putscon("BREAK BY CONSOLE !!\r\n"); return; } if(i == -2) { putscon("SUM CHECK ERROR\r\n"); return; } if((i == '9')||(i == '8')||(i == '7')) { for(j=27-(i & 0xf)*2;j>0;j--) getcon(); putscon("start loading address = "); cprintf("%08lX",(long)cpb); // crlf(); putscon("\r\nEND. bytes loaded = "); cprintf("%08lX\r\n",len); // crlf(); return; } putscon("????? S load stop\r\n"); return; } long cpysstr(char *d,char *s,long n) { register char c; register long l; l=0; while(n--) { c= *s++; if((c == ' ') || (c == '\0'))break; *d++ = c; l++; } *d++ = '\0'; return(l); } void spacen(int n) { while(n--) { putcon(0x20); } } // 文字列をコピーしながら、スペースがあるかチェック int cpynstr(char *d,char *s,int n) { register char c; register long l; int spacef,i; l=0; spacef = 0; while(n--) { c= *s++; if(c == '\0')break; *d++ = c; if(c == ' ') { if(i) spacef = 0x1000; } l++; } *d++ = '\0'; return(l | spacef); } void crlf() { putcon('\r'); putcon('\n'); } int chex(char c) { // hex32b(0); if((c >= 'a') && (c <= 'z'))c -= ' '; if((c >= '0') && (c <= '9'))return(c & 0xf); if((c >= 'A') && (c <= 'F'))return(c -= 0x37); return(-1); } int hex(int i) { i &= 0xF; if(i>9) i+=7; i+=0x30; return(i); } void ckasci(int s) { s &= 0xff; if(((s >= 0x20) && ( s <= 0x7e))) // || ((s >= 0xa0) && ( s <= 0xfe))) { putcon(s); } else { putcon(0x2e); } } int cstrlen(char *cp,char f) { long i; for(i=0;i> 4)); putcon(hex(s)); } void hex16b(int s) // 4桁の16進数で表示 { hex8b(s >> 8); hex8b(s); } void hex32b(long l) // 8桁の16進数で表示 { int s; s=( l >> 16); hex16b(s); s=l; hex16b(s); } */ // <---- ここから 主なSDカードの BIOS // インターフェイス誌2011年6月号付録のCDに収録されている、 // mp3p_rx62n_hew.zip の中の、mmc_rspi.c を参考に、一部をコピーして作成。 #define RSPI_CH 1 // 使用するSPIポートの選択: 0:RSPIA-A, 1:RSPIB-A, 10:RSPIA-B, 11:RSPIB-B //#define CS_LOW() {PORT3.DR.BIT.B1 = 0;} // CS#(P31/SSLB0-A)をLにする(RSPI_CH=1のとき) #define CS_LOW() {*PORT3DR &= 0xFD;} // CS#(P31/SSLB0-A)をLにする(RSPI_CH=1のとき) //#define CS_HIGH() {PORT3.DR.BIT.B1 = 1;} // CS#(P31/SSLB0-A)をHにする(RSPI_CH=1のとき) #define CS_HIGH() {*PORT3DR |= 0x2;} // CS#(P31/SSLB0-A)をHにする(RSPI_CH=1のとき) #define PCLK 48000000UL // PCLKの周波数[Hz] #define CLK_FAST 24000000UL // SCLKの周波数[Hz] (動作中) #define CLK_SLOW 400000UL // SCLKの周波数[Hz] (初期化中) #define RSPI RSPI1 // MISOB-A, MOSIB-A を使う // PORT3.ICR.BIT.B0 = 1; \ // PORT3 入力バッファコントロールレジスタP30 --> INPUT // IOPORT.PFHSPI.BYTE = 0x0E; \ // ポートファンクションレジスタH bit3-1:MISOB,MOSIB,RSPCKB=1 // bit0:P30をMISOB-A端子として設定,P26をMOSIB-A端子として設定 // bit0: P27をRSPCKB-A端子として設定 // MSTP_RSPI1 = 0; \ // MSTPB16=0:RSPI1 解除 #define SPI_ATTACH() { \ *PORT3ICR |= 1; \ *IOPORT_PFHSPI = 0x0E; \ *MSTPCRB &= MSTPCRB_MSTPB16; \ } // RSPI.SPCR.BIT.SPE = 0; \ // RSPI.SPCR: (volatile unsigned char *)0x883A0 bit6:SPE // RSPI.SPBR.BYTE = PCLK/2/CLK_FAST-1; \ // RSPI.SPBR: (volatile unsigned char *)0x883AA // RSPI.SPCR.BIT.SPE = 1; \ // RSPI.SPCR: (volatile unsigned char *)0x883A0 bit6:SPE #define FCLK_FAST() { \ *SPCR1 &= 0xBF; \ *SPBR1 = PCLK/2/CLK_FAST-1; \ *SPCR1 |= 0x40; \ } //#define PORT3_DR *((volatile char *)0x8C023) // ピット制御をバイト単位にするためのポート宣言 //#define PORT3_DRR *((volatile char *)0x8C003) int initmmc(int flg) { mmcpower(0); waittim0(1000); // 10.6ms if(flg == 0) return 0; // PORT2.DDR.BIT.B6 = 0; *PORT2DDR &= 0xBF; // PORT2.DR.BIT.B6 = 0; *PORT2DR &= 0xBF; // PORT3.DR.BIT.B4 = 0; // PORT34(TRST#) = Low. SDカード電源ON *PORT3DR &= 0xEF; waittim0(1000); // 10.6ms // PORT3.DR.BIT.B1 = 1; // CS#=OUT // PORT3.DDR.BIT.B1 = 1; // CS#=H *PORT3DDR = 0x12; // *((volatile char *)0x8C003) ポート3の、B1,B4 を出力 // PORT3.DR.BIT.B4 = 0; // PORT34(TRST#) = Low. SDカード電源ON // PORT3.DDR.BIT.B4 = 1; // PORT34(TRST#) enable SDカード電源ON *PORT3DR = 0x02; // *((volatile char *)0x8C023) // // PORT0.ICR.BIT.B7 = 1; // INS#=IN // FCLK_FAST(); // SPI_ATTACH(); // PORT3.ICR.BIT.B0 = 1; *PORT3ICR |= 1; // IOPORT.PFHSPI.BYTE = 0x0E; *IOPORT_PFHSPI = 0x0E; // ポートファンクションレジスタH bit3-1:MISOB,MOSIB,RSPCKB=1 // bit0:P30をMISOB-A端子として設定,P26をMOSIB-A端子として設定 // bit0: P27をRSPCKB-A端子として設定 // MSTP_RSPI1 = 0; *MSTPCRB &= MSTPCRB_MSTPB16; // RSPI1 解除 // RSPI.SPCR.BYTE = 0x883A0 RSPI1 制御レジスタ // RSPI.SPPCR.BYTE = 0x883A2 RSPI1 端子制御レジスタ // RSPI.SPSR.BYTE = 0x883A3 RSPI1 ステータスレジスタ // RSPI.SPDR.LONG = 0x883A4 RSPI1 データレジスタ // RSPI.SPSCR.BYTE = 0x883A8 RSPI1 シーケンス制御レジスタ // RSPI.SPDCR.BYTE = 0x883AB RSPI1 データコントロールレジスタ // RSPI.SPCMD0.WORD = 0x883B0 RSPI1 コマンドレジスタ0 〜 (7 0x883BE ) // RSPI.SPBR.BYTE = 0x883AA RSPI1 ビットレートレジスタ // RSPI.SPCR.BYTE = 0x883A0 // // Initialize RSPI module *SPCR1 = 0; // Stop SPI *SPPCR1 = 0; // Fixed idle value, disable loop-back mode *SPSCR1 = 0; // Disable sequence control *SPDCR1 = 0x20; // SPLW=1 long word access,1 frame,start 0 *SPCMD1 = 0x0700; // LSBF=0, SPB=7( ビット長8), BRDV=0, CPOL=0, CPHA=0 // SPCMD0 の各ビットの意味 // CPHA=0:奇数エッジでデータサンプル、偶数エッジでデータ変化 // CPOL=0:アイドル時のRSPCKが“0” // BRDV[1:0]=0 0:ベースのビットレートを選択 // SSLA[2:0]=0 0 0:SSL0 // SSLKP=0:転送終了時に全SSL信号をネゲート // SPB[3:0]=7: 0100〜0111:8ビット // LSBF=0:MSBファースト // SPNDEN=0:次アクセス遅延は1RSPCK+2PCLK // SLNDEN=0:SSLネゲート遅延は1RSPCK // SCKDEN=0:RSPCK遅延は1RSPCK *SPBR1 = PCLK / 2 / CLK_SLOW - 1; // Bit rate 400KHz 48000000/2/400000 - 1=59 *SPCR1 = 0x49; // Start SPI in master mode CS_HIGH(); return 1; } void mmcclk(int l) { *SPCR1 = 0; // Start transmission *SPBR1 = (char)l; *SPCR1 = 0x49; } // SPIで1バイト送信。 int mmcout(int l) { *SPDR1 = l; // Start transmission // while (!RSPI.SPSR.BIT.SPRF) ; // Wait for end of transfer togleled++; if((togleled % 1023) == 0) // PORT1.DR.BIT.B5 ^= 1; // Reverse P15(LED) *PORT1DR ^= 1; while (!(*SPSR1 & 0x80)) ; // Wait for end of transfer // return RSPI.SPDR.LONG; // received data return *SPDR1; // received data } // SDカードの電源をON、OFF制御。 // SDカードの電源OFFだけでは、RX62Nポートからや、基板のプルアップ抵抗からの回り込みで // 0Vにはならないので、関連する出力ポートをLowにする。 int mmcpower(int power) { if(power == 0) // 電源OFF { CS_LOW(); // SDチップセレクトLow。ポート3、ビット1をLow // IOPORT.PFHSPI.BYTE = 0x00;// SPI出力無効 *IOPORT_PFHSPI = 0x00; // PORT2.DDR.BIT.B6 = 1; // CMD output PORT。CPU基板でプルアップされているので、入力ポートではだめ。 *PORT2DR |= 0x40; // PORT2.DR.BIT.B6 = 0; // CMD Lowを出力 *PORT2DR &= 0xBF; // PORT3.DR.BIT.B4 = 1; // PORT34(TRST#) = Low. SDカード電源OFF *PORT3DR |= 0x10; } else // 電源ON { // PORT2.DDR.BIT.B6 = 0; *PORT2DDR &= 0xBF; // PORT2.DR.BIT.B6 = 0; *PORT2DR &= 0xBF; // PORT3.DR.BIT.B4 = 0; // PORT34(TRST#) = Low. SDカード電源ON *PORT3DR &= 0xEF; // SPI_ATTACH(); // SPI制御有効 // PORT3.ICR.BIT.B0 = 1; *PORT3ICR |= 1; // IOPORT.PFHSPI.BYTE = 0x0E; *IOPORT_PFHSPI = 0x0E; // MSTP_RSPI1 = 0; *MSTPCRB &= MSTPCRB_MSTPB16; // RSPI1 解除 CS_HIGH(); // SDチップセレクトHigh。初期状態にする。この後ダミークロック必要 } return power; } int mmccs(int c) { if(c == 0) { CS_LOW(); } else { CS_HIGH(); } return 0; } int outcmd(int cmd) { int i; int ret; CS_LOW(); mmcout(cmd); mmcout(0); mmcout(0); mmcout(0); mmcout(0); ret = mmcout(0x95);// CRC crlf(); for(i=0;i<9;i++) { cprintf("%02x ",ret & 0xFF); ret = mmcout(0xFF); // ダミークロック } return 0; } // SDカードの BIOS はここまで ----> // ------------------------------------------------------------------------- // cprintf, csprintf 関数は最後に書いておく // printf 関数の整数版 引数は2個まで。printf lite. Custom printf void cprintf(char *fmt,unsigned long a,unsigned long b /* ,unsigned long c,unsigned long d*/ ) { char bf[COLUMN]; int len; len = csprintf(bf,fmt,a,b /* ,c,d */); // hex32b(len); // hex32b((long)(&bf[0])); bf[len]=0; putscon(bf); } int csprintf(char *dp,char *fmt,unsigned long a,unsigned long b /* ,unsigned long c,unsigned long d*/ ) { char c; int len,i,j,keta,zs,siz; int wlen,hiki; char cb[12]; int s; unsigned long l; char *cp; // hex32b((long)cb); // hex32b((long)dp); len = cstrlen(fmt,(char)0); wlen=0; hiki=0; for(i=0;i= '0') && (c <= '9')) { if(c=='0') { zs=0; i++; c = fmt[i]; } if((c >= '1') && (c <= '9')) { keta=c & 0xf; i++; c = fmt[i]; if((c >= '0') && (c <= '9')) { keta *= 10; keta += c & 0xf; i++; c = fmt[i]; } } else zs=1; } if((c == 'l') || (c == 'L')) { siz=4; i++; c = fmt[i]; } if((c == 'x') || (c == 'X')) { c='x'; } else if((c == 'd') || (c == 'D')) { c='d'; } if(c == 'c') { *dp++ = l; wlen++; } else if(c == 's') { cp = (char *)l; while(*cp) { *dp++ = *cp++; wlen++; if(wlen >= (COLUMN -1))break; } } else { if(siz==2) l &= 0xFFFF; if(keta>10)keta=10; cb[10]=0; if(c == 'x') { cb[0]=' '; cb[1]=' '; for(j=9;j>=2;j--) { s = hex((short)l); cb[j]=s; l >>= 4; } } else { for(j=9;j>=0;j--) { s = (unsigned long)l%10; cb[j]=s | '0'; l = (unsigned long)l/10; } } for(j=0;j<9;j++) { c = cb[j]; if(c == '0') { if(zs) cb[j]=' '; } else if(c != ' ') break; } if(keta < (10-j)) keta=10-j; if((wlen + keta) >= (COLUMN -1)) return wlen; // hex8b(keta);// debug for(j=10-keta;j<10;j++) *dp++ = cb[j]; wlen += keta; } } else { *dp++ = c; wlen++; } if(wlen >= (COLUMN -1))return wlen; } return wlen; }