/****************************************************************/ // 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 と置き換えるだけで動作する。 /****************************************************************/ #include // Include machine.h #include "iodefine.h" // Include iodefine.h #define CMD0 0x40 #define CMD1 0x41 #define CMD8 0x48 #define CMD55 0x77 // APP_CMD #define ACMD41 0x69 #define CMD9 0x49 #define CMD10 0x4A #define CMD17 0x51 #define CMD24 0x58 #define CMD58 0x7A #define MMCINIT 0x100 #define MMCREADY 0x101 #define MMCREAD 0x102 #define MMCWRITE 0x103 #define NOTFOUND -1 // #define SCBRR_SET 25 // ボーレート分周 unsigned char crc7c(unsigned char *cp,int n); // CRC7 計算 unsigned short crc16c(unsigned char *cp,int n); // CRC16 計算 // 以下、モニタを追加 char getcon(void); void putcon(char); void putscon(char *); union param32{ long l32; int i32; unsigned long ul32; short s16[2]; unsigned short us16[2]; char c8[4]; unsigned char uc8[4]; char *cpoint; unsigned char *ucpoint; short *spoint; unsigned short *uspoint; long *lpoint; unsigned long *ulpoint; union param32 *upoint; long (*ppoint)(); /* アドレスとして関数呼び出し */ }; #define COLUMN 80 char htol(long *,char **); void crlf(void); int chex(char ); void ckasci(short ); void cprintf(); void spacen(int ); //==================================================== char getcon(void); void putcon(char ); void putscon(char *); int combuf2f; char combuf[COLUMN]; // コマンド入力バッファー char combuf2[COLUMN]; // 前回のコマンド記憶 int combuf2f; // 前回のコマンドを有効にするフラグとポインタ union param32 param[9]; int dumpm(union param32 *); int cksjis(unsigned short s); void dumpmt(void); void movem(union param32 *,long ); int argck(char **,union param32 *,int ); char htol(long *,char **); void paramer(void); int verify(union param32 *); void srload(union param32 *,int); int setmemo(union param32 *,int,int ); void findp(union param32 *); long cpysstr(char *,char *,long ); long cpynstr(char *d,char *s,long n); long gosub(union param32 addr); int dhrymain(void); int outcmd(int); int mmccs(int); int dummy74sd(void); void initmmc(int flg); unsigned char *sddbuf; unsigned char response[16]; unsigned char csdbuf[24]; unsigned char cidbuf[24]; union param32 cmdbuf[3]; int sdversion; void hex8b(int s); // 2桁の16進数で表示。cprintf の機能と重複する void hex16b(int s); // 4桁の16進数で表示 void hex32b(long l); // 8桁の16進数で表示 // n桁の10進数の文字に変換。ゼロサプレスを行う // sprintf(cp,"%nd",l); に相当する。 void d32kzs(char *cp,long l,int n); // 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); // LED点滅ソフトの main.c の部分を改造 void main(void) { int i; // int data; // // SCI2 の入力ポートを有効に設定 // PORT1.ICR.BIT.B2 = 1; // SCI0 の入力ポートを有効に設定 PORT2.ICR.BIT.B1 = 1; // SCI0スタンバイ解除 SYSTEM.MSTPCRB.BIT.MSTPB31 = 0; // SCI2スタンバイ解除 // SYSTEM.MSTPCRB.BIT.MSTPB29 = 0; // CMT0,CMT1 スタンバイ解除 MSTP( CMT0 ) = 0; // Wakeup CMT0,CMT1 bit addr = SYSTEM.MSTPCRA.BIT.MSTPA15 // CMT0.CMCOR = 48000000/512/2 - 1; // CMCOR is 500ms Count 0xB71A CMT0.CMCOR = 0xFFFF; // 最大まで。フリーランと同等 CMT0.CMCR.WORD = 0x0083; // CMIE is Enable,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; // タイマーをスタートする // SCI0設定 SCI0.SCR.BYTE = 0x00; // TE=0,RE=0,CKE1=0 SCI0.SMR.BYTE = 0x00; // CHR=0,PE=0,STOP=0,CKS=00(Pφ/1) SCI0.BRR = SCBRR_SET; // 分周設定 115200 bps SCBRR_SET=25:48000000/26/16 = 115384 SCI0.SEMR.BIT.ABCS = 1; // ABCS=1 基本クロック16で1ビット期間 for(i=0;i<0x800;i++);// 1bit時間以上ウェイト SCI0.SCR.BYTE = 0x30; // TIE=0(D6),RIE=0(D7),TE=1(D5) 送信許可,RE=1(D4) 受信許可 // 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; // 外部バス有効設定 CS3(P63,113pin)、CS4(P64,114pin)を、出力に設定する。 SYSTEM.SYSCR0.WORD = 0x5A03;// KEY code = 0x5A 外部バス有効 IOPORT.PF0CSE.BYTE = 0x18; // CS3,CS4 有効 IOPORT.PF1CSS.BYTE = 0x00; // CS4=P64 IOPORT.PF2CSS.BYTE = 0x00; // CS3=P63 IOPORT.PF3BUS.BYTE = 0xFF; // A16--A23 出力有効 IOPORT.PF4BUS.BYTE = 0xFF; // A0--A15 出力有効 IOPORT.PF5BUS.BYTE = 0x50; // P90--P93 を、A16--A19 に設定、D8--D15 をデータバス、P51 をWR1 IOPORT.PF6BUS.BYTE = 0x01; // P55 を、外部バス WAIT 入力 BSC.CS3CR.WORD = 0x0001; // CS3 を有効。外部16ビットバス BSC.CS4CR.WORD = 0x0001; // CS4 を有効。外部16ビットバス SYSTEM.SCKCR.LONG = 0x10100; // ICLK=96MHz,BCLK=48MHz,PCLK=48MHz // 同じCSへの連続アクセスのとき、RD,WR が、連続的にLowにならないようにする。 BSC.CS3WCR2.LONG= 0x00000011; // CS3 の、RD,WR のネゲートの後、1クロックのHighを設ける BSC.CS4WCR2.LONG= 0x00000011; // CS4 の、RD,WR のネゲートの後、1クロックのHighを設ける PORTD.DDR.BYTE = 0xFF; // D0--D7 データバス PORT5.DDR.BYTE = 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) /* 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をリターン SIO0 char statcon() { int i; i = 0; if (SCI0.SSR.BYTE & 0x40) i = 1; return i; } // RS232Cから受信文字があると、1をリターン SIO2 char statcon2() { int i; i = 0; if (SCI2.SSR.BYTE & 0x40) i = 1; return i; } // RS232Cから1文字受信するまで待つ。SIO0 char getcon() { int data; while(1) { if (SCI0.SSR.BYTE & 0x40) break; } data = SCI0.RDR; SCI0.SSR.BYTE = SCI0.SSR.BYTE & 0x80; return data; } // RS232Cから1文字受信するまで待つ。SIO2 char getcon2() { int data; while(1) { if (SCI2.SSR.BYTE & 0x40) break; } data = SCI2.RDR; SCI2.SSR.BYTE = SCI2.SSR.BYTE & 0x80; return data; } // RS232Cに1文字出力。SIO0 void putcon(char c) { while(1) { if (SCI0.SSR.BYTE & 0x80) break; } SCI0.TDR = c; } // RS232Cに1文字出力。SIO2 void putcon2(char c) { while(1) { if (SCI2.SSR.BYTE & 0x80) break; } SCI2.TDR = c; } // 以下、最後までが、モニタの本体。main int mainmoni (int mode) { int ret; char *comp,c;//*cp; // int coma; int i,j,l; // int *lsp,*ldp; // int pret; int ts,te; combuf2f=0; combuf2[0] = 0; putscon("\r\nCustom Monitor 2011.6.20\r\n"); while(1) { LOOP: putscon("RX62N-Bug>"); ret=getscon(combuf,COLUMN-1,0); if(ret == 0) { if(combuf2[0]) // 前回のコマンド記憶の先頭 { combuf2f = 1; if(getscon(combuf,COLUMN - 1,0) == -1) { crlf(); goto LOOP; } cpynstr(combuf2,combuf,COLUMN); // コマンド記憶 } } else { if(ret == -1) { crlf(); goto LOOP; } cpynstr(combuf2,combuf,COLUMN); // memory command } comp=combuf; // cpysstr(combuf2,combuf,15L); ret = checkcommand(combuf,param,ret); if(ret != NOTFOUND) // SD CARD の操作コマンドか? { crlf(); execcommand(param,ret); // SD CARD の操作コマンドを実行 crlf(); goto LOOP; } c= *comp; 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+0x7e; } } } else { param[0].l32=0; param[1].l32=0x3f; } dumpm(param); 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; movem(param,(long)j); te = CMT0.CMCNT; break; // case 'V': case 'v': comp++; if((i=argck(&comp,param,3)) != 3) { paramer(); break; } ts = CMT0.CMCNT; verify(param); te = CMT0.CMCNT; break; /* case 'F':// フィルデータ comp++; if((i=argck(&comp,param,5)) != 5) { paramer(); break; } ts = CMT0.CMCNT; fillp(param); te = CMT0.CMCNT; break; */ // データパターン4バイトまでを検索する。find case 'f': comp++; if((i=argck(&comp,param,4)) != 4) { paramer(); break; } ts = CMT0.CMCNT; findp(param); te = CMT0.CMCNT; break; /* set memory */ // 指定番地から実行する case 'g': comp++; if((i=argck(&comp,param,1))== -1) { paramer(); break; } ts = CMT0.CMCNT; ret = param[0].ppoint(); // ret = gosub((union param32)param[0].l32); te = CMT0.CMCNT; 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; // 指定アドレスのメモリの変更。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; setmemo(param,j,i); te = CMT0.CMCNT; break; // SDカードへのCMDを出す。s が付加されると、1バイトのみの送信 // 引数がそのままCMDとなるので、注意。マスター側の0x40は or で付加される case 'c': j=0; comp++; if(*comp=='s') { j = 1; comp++; } else if(*comp=='p')// powerctl { j = 2; comp++; } else if(*comp=='i')// dummy clk & CMD0 { j = 3; comp++; } if((i=argck(&comp,param,1))== -1) { paramer(); break; } // switch(j) { case 0: outcmd(param[0].l32); break; case 1: ret = mmcout(param[0].l32); cprintf("\r\nret= %08lX",ret); break; case 2: // powerON mmccs(param[0].l32); break; case 3: // CMD0 dummy74sd(); break; } break; // case 'D':// dhry stone テスト // ret = dhrymain(); // cprintf("\r\nTimer HEX = %lX,",ret); cprintf(" time = %ld",ret); // break; // コマンド 'S' はSDカードの操作コマンドに変更 case 'S': break; /* case 'S':// エラトステネスのふるいで、素数を求めたときの実行時間 ts = CMT0.CMCNT; ret = sievemain(); te = CMT0.CMCNT; cprintf("sieve=%ld ",ret); l=te-ts; // l /= 1000; cprintf("\r\nTimer HEX = %lX,",l); cprintf(" time = %ld",l/48); l /= 5; cprintf(".%dμs",l%10); 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; while(param[0].l32--); te = CMT0.CMCNT; } 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 *= 107; l /= 10; // 48000000/512=93750Hz,1/93750=10.666666 μs cprintf(" time = %ld μs",l); break; default: cprintf("default"); break; } crlf(); } return 0; } // 引数で指定する 数値に、10.67μ秒 待つ。タイマーが停止していた場合のタイムアウト機能あり。 int waittim0(int l) { int s,e,e1; int ul; long timeout; s = CMT0.CMCNT; s &= 0xFFFF; e1 = s; ul = 0; if(l > 0x10000) { ul = l >> 16; l &= 0xFFFF; } timeout = 0x4000000; while(ul) { e = CMT0.CMCNT; 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 &= 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,"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]; unsigned char *cp; cp = &cmdbuf[0].uc8[3]; switch(cmdcode) { case MMCINIT: // restart power ON sequence initmmc(1); sdversion = 0; 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); 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]); putscon(" card interface = "); for(ret = 1;ret<7;ret++) { n = response[ret]; hex8b(n & 0xff); putcon(' '); } // 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]); putscon(" OCR = "); for(ret = 1;ret<7;ret++) { n = response[ret]; hex8b(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; 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]); putscon(" response 41 = "); hex8b(response[1]); sdversion |= 1; putscon(" ACMD41 count = "); d32kzs(dbuf,k,3); dbuf[3]=0; putscon(dbuf); putscon(" ("); k *= 43; d32kzs(dbuf,k,5); putscon(dbuf); putscon(" ms )"); 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]); putscon(" OCR = "); for(ret = 1;ret<7;ret++) { n = response[ret]; hex8b(n & 0xff); putcon(' '); } 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]); putscon("\r\n CSD = "); mark = 0; for(ret = 1;ret<22;ret++) { n = csdbuf[ret]; n &= 0xFF; // cprintf("%02X ",n & 0xff); hex8b(n); putcon(' '); 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); } else hex16b((short)(ret & 0xFFFF)); putscon(" MB "); d32kzs(dbuf,ret,5); // dbuf[5]=0; putscon(dbuf);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++; // printf("C_SIZE = %3X + 1 = %d x %d\n",k,k+1,i); putscon(" C_SIZE = 0x"); if(k & 0xFFFF0000) hex32b(k); else hex16b((short)k); putscon(" x 0x"); i >>= 10; if(i & 0xFFFF0000) hex32b(i); else hex16b((short)i); putscon(" kB "); d32kzs(dbuf,i*k,7); dbuf[7]=0; putscon(dbuf); putscon(" kB "); } 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); 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); 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]); putscon(" card interface = "); for(ret = 1;ret<7;ret++) { n = response[ret]; hex8b(n & 0xff); putcon(' '); } 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]); putscon("\r\nCSD = "); mark = 0; for(ret = 1;ret<22;ret++) { n = csdbuf[ret]; n &= 0xFF; // printf("%02X ",n & 0xff); hex8b(n); putcon(' '); 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); } else hex16b((short)(ret & 0xFFFF)); putscon(" MB "); d32kzs(dbuf,k,5); // dbuf[5]=0; putscon(dbuf); } 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++; // printf("C_SIZE = %3X + 1 = %d x %d\n",k,k+1,i); putscon(" C_SIZE = 0x"); if(k & 0xFFFF0000) hex32b(k); else hex16b((short)k); putscon(" x 0x"); i >>= 10; if(i & 0xFFFF0000) hex32b(i); else hex16b((short)i); putscon(" kB "); d32kzs(dbuf,i*k,7); // dbuf[7]=0; putscon(dbuf); putscon(" kB "); } 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]; // printf("%02X ",n & 0xff); hex8b(n & 0xff); putcon(' '); } 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(' '); } 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]); putscon(" response 41 = "); hex8b(response[1]); if(response[0] == 0) sdversion |= 1; // printf("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])); crlf(); for(ret = 0;ret<516;ret++) { n = sddbuf[ret]; // printf("%02X ",n & 0xff); // if((lines & 0xF) == 0xF) // crlf(); } ret = crc16c(&sddbuf[0],512); // printf(" calc crc16 = %04X",(short)(ret & 0xFFFF)); putscon("return crc16 = "); hex8b(sddbuf[512]); hex8b(sddbuf[513]); putscon(" calc crc16 = "); hex16b((short)(ret & 0xFFFF)); putscon("\r\nresponse = "); hex8b(response[0]); hex8b(response[1]); break; case MMCREAD: for(k=0;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:Wodd, 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) { unsigned char *cp; // short *sp; short i,sum,ls; unsigned int s,sjf; union param32 u; unsigned char sbuf[16]; char c2; unsigned long len; // short sbuf[8]; param[0].l32 &= 0xfffffff0l; param[1].l32 &= 0xffffffffl; len = param[1].ul32 - param[0].ul32 + 1; cp=param[0].ucpoint; // sp=param[0].spoint; dumpmt(); sjf=0; ls=0; 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(); } } } } // メモリダンプで、SJISコードの場合、漢字表示できるようにする。 // SJISコードで特定の処理をしてしまうターミナルソフトでは、正常に表示されない場合がある。 // テラタームでは、端末の受信漢字コードを、SJISに変更する。デフォルトでは、UTF-8 になっているので、 // 0x8A で、改行してしまうので、変更しておく。 int cksjis(unsigned short 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); // hex16b((short)ii); /* printf("sm=%x ii=%x",sm,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=26-(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); } } long cpynstr(char *d,char *s,long n) { register char c; register long l; l=0; while(n--) { c= *s++; if(c == '\0')break; *d++ = c; l++; } *d++ = '\0'; return(l); } 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(short s) { s &= 0xff; if(((s >= 0x20) && ( s <= 0x7e))) // || ((s >= 0xa0) && ( s <= 0xfe))) { putcon(s); } else { putcon(0x2e); } } long 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); } // n桁の10進数の文字に変換。ゼロサプレスを行う // sprintf(cp,"%nd",l); に相当する。 void d32kzs(char *cp,long l,int n) { int i,j; long zf; char dbuf[12]; for(i=9;i>=0;i--) { dbuf[i] = (char)(l%10); l /= 10; } zf = 0; for(i=0;i<10;i++) { if(dbuf[i]) { zf = 1; } if(zf) dbuf[i] |= 0x30; } for(i=9,j=n-1;(i>=0) && (j >= 0);i--,j--) { zf = dbuf[i]; if(zf == 0) zf = ' '; cp[j] = zf; } cp[n]=0; } // <---- ここから 主な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_HIGH() {PORT3.DR.BIT.B1 = 1;} // 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 を使う #define SPI_ATTACH() { \ PORT3.ICR.BIT.B0 = 1; \ IOPORT.PFHSPI.BYTE = 0x0E; \ MSTP_RSPI1 = 0; \ } #define FCLK_FAST() { \ RSPI.SPCR.BIT.SPE = 0; \ RSPI.SPBR.BYTE = PCLK/2/CLK_FAST-1; \ RSPI.SPCR.BIT.SPE = 1; \ } #define PORT3_DR *((volatile char *)0x8C023) // ピット制御をバイト単位にするためのポート宣言 #define PORT3_DRR *((volatile char *)0x8C003) void initmmc(int flg) { mmcpower(0); waittim0(1000); // 10.6ms if(flg == 0) return; PORT2.DDR.BIT.B6 = 0; PORT2.DR.BIT.B6 = 0; PORT3.DR.BIT.B4 = 0; // PORT34(TRST#) = Low. SDカード電源ON waittim0(1000); // 10.6ms // PORT3.DR.BIT.B1 = 1; // CS#=OUT // PORT3.DDR.BIT.B1 = 1; // CS#=H PORT3_DRR = 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 PORT3_DR = 0x02; // *((volatile char *)0x8C023) // // PORT0.ICR.BIT.B7 = 1; // INS#=IN // FCLK_FAST(); SPI_ATTACH(); // 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 RSPI.SPCR.BYTE = 0; // Stop SPI RSPI.SPPCR.BYTE = 0; // Fixed idle value, disable loop-back mode RSPI.SPSCR.BYTE = 0; // Disable sequence control RSPI.SPDCR.BYTE = 0x20; // SPLW=1 long word access,1 frame,start 0 RSPI.SPCMD0.WORD = 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 RSPI.SPBR.BYTE = PCLK / 2 / CLK_SLOW - 1; // Bit rate 400KHz 48000000/2/400000 - 1=59 RSPI.SPCR.BYTE = 0x49; // Start SPI in master mode CS_HIGH(); } // SPIで1バイト送信。 int mmcout(int l) { RSPI.SPDR.LONG = l; // Start transmission while (!RSPI.SPSR.BIT.SPRF) ; // Wait for end of transfer return RSPI.SPDR.LONG; // 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出力無効 PORT2.DDR.BIT.B6 = 1; // CMD output PORT。CPU基板でプルアップされているので、入力ポートではだめ。 PORT2.DR.BIT.B6 = 0; // CMD Lowを出力 PORT3.DR.BIT.B4 = 1; // PORT34(TRST#) = Low. SDカード電源OFF } else // 電源ON { PORT2.DDR.BIT.B6 = 0; PORT2.DR.BIT.B6 = 0; PORT3.DR.BIT.B4 = 0; // PORT34(TRST#) = Low. SDカード電源ON SPI_ATTACH(); // SPI制御有効 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; } int dummy74sd()// CSHighで、ダミークロック送出の後、CMD0 を出す { int i; int ret; int ok; ok=0; CS_HIGH(); for(i=0;i<10;i++) mmcout(0xFF); // CSがHighで、ダミークロック。最低74クロック CS_LOW(); mmcout(0x40); // CMD0 mmcout(0); // arg = 0 mmcout(0); mmcout(0); mmcout(0); ret = mmcout(0x95);// 最初のコマンドが0x40、引数が0 の時、正しいCRCが必要 crlf(); for(i=0;i<5;i++) { cprintf("%02x ",ret & 0xFF); ret = mmcout(0xFF); if(ret == 1) // 0x01のレスポンスがあった。 ok = 1; } return ok; } // 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); for(j=10-keta;j<10;j++) *dp++ = cb[j]; wlen += keta; } } else { *dp++ = c; wlen++; } if(wlen >= (COLUMN -1))return wlen; } return wlen; }