lynxeyedの電音鍵盤

MBDとFPGAと車載で使うデバイスの備忘録

結局C言語で作った

スクラッチビルドで、初期化からCMD25(マルチプルブロックライト命令)でMMCに512byte(=1 block)書き込む命令を書いてみました。すべて自前のプログラムなので自由に使ってください。(もちろん無保証)
HEWのVersion 4.00.00.027でコンパイルし、メモリーは(東芝miniSD 128MB)にて動作確認しています。

ソースの書き方が大分汚いですけど。

プロセスの概略は
?CMD0発行
?CMD1発行(R1レスポンスが0x00になるまで繰り返し)
?CMD25発行(同上)
?0xfcを送信してマルチプルライトスタート

                                  • -

?512byte分データ送信
?ダミーCRC(0xFFでOK)2バイト送信
?データレスポンス確認(0x05になってればOK)
?ビジー(0x00)解除待ち

                                  • -

(※注1)
?ストップトークン(0xfd)送信
?ビジー解除待ち

(※注1)CMD25を送信する前にブロック長を指定していないため、Open-Ended Multiple Block Writeが実行されます。したがって連続してライトしたい場合は?〜?を繰り返せばよいことになります。停止させたいときは1ブロック分書き終わった区切りのところで、(ブロックの途中では無理)0xFDを送信して終了できます。

#include 
void set_CLK20(void);




////////////////////////////////////////////////
void set_CLK20(void){
prc0=1;
cm1=0x08;
cm0=0x08;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
ocd2=0;
prc0=0;
}


////////////////////////////////////////////////
//	MMC read & write
////////////////////////////////////////////////
#define MMC_SCS p3_4


void main(void){

char c,dummy;
int w;

set_CLK20();
//////////////// init port /////////////////////

p3=0b10010000;
pd3=0b10010000;

pd1_5 = 1;
p1_5=1;
sser=0;
ssmr2= 0x41;
sscrh=0x60;		//master f1/256
ssmr=0x08;
sssr=0;

/////////////////////////////////////////////////
// 		MMC initialize
//	sser = 0x10 means te=1 re=0
//	sser = 0x08 means te=0 re=1
/////////////////////////////////////////////////

sser = 0x10;	//te=1 re=0
for(c=10;c!=0;c++)
{
	while(!tdre_sssr);
	sstdr = 0xff;
}
while(!tend_sssr);	//wait transmit
/////////////////////////////////////////////////
//	transmit CMD0
/////////////////////////////////////////////////

MMC_SCS = 0;
sser = 0x10;		//te=1 re=0
while(!tdre_sssr);
sstdr = 0xff;		//dummy
while(!tend_sssr);
while(!tdre_sssr);

sstdr = 0x40;		//CMD0=40_0000_0000_95h
while(!tend_sssr);
while(!tdre_sssr);

sstdr = 0x00;		
while(!tend_sssr);
while(!tdre_sssr);
sstdr = 0x00;		
while(!tend_sssr);
while(!tdre_sssr);

sstdr = 0x00;		
while(!tend_sssr);
while(!tdre_sssr);
sstdr = 0x00;		
while(!tend_sssr);
while(!tdre_sssr);

sstdr = 0x95;		
while(!tdre_sssr);
while(!tend_sssr);	//wait trans end

//----------------------------
//	wait R1 resp
//----------------------------

sser = 0x08;		//te=0 re=1
rsstp_sscrh=1;		//receive 1 byte
dummy = ssrdr;		//dummy read
for(w=16;w!=0;w--)
	{
		while(!rdrf_sssr);	//wait resp
		dummy = ssrdr;
		if(!(dummy & 0x80))break;
		
	}//timed out



/////////////////////////////////////////////////
//	transmit CMD1
/////////////////////////////////////////////////
do{
sser = 0x10;		//te=1 re=0
orer_sssr = 0;		//clear overrun flag

while(!tdre_sssr);
sstdr = 0xff;		//dummy
while(!tend_sssr);
while(!tdre_sssr);

sstdr = 0x41;		//CMD1=41_00FF_8000_99h
while(!tend_sssr);
while(!tdre_sssr);

sstdr = 0x00;		
while(!tend_sssr);
while(!tdre_sssr);
sstdr = 0xff;		
while(!tend_sssr);
while(!tdre_sssr);

sstdr = 0x80;		
while(!tend_sssr);
while(!tdre_sssr);
sstdr = 0x00;		
while(!tend_sssr);
while(!tdre_sssr);

sstdr = 0x99;		
while(!tdre_sssr);
while(!tend_sssr);	//wait trans end
//----------------------------
//	wait R1 resp
//----------------------------

sser = 0x08;		//te=0 re=1
orer_sssr=0;		//clear overrun flag

rsstp_sscrh=1;		//receive 1 byte
dummy = ssrdr;		//dummy read

for(w=16;w!=0;w--)
	{
		while(!rdrf_sssr);	//wait resp
		dummy = ssrdr;
		if(!(dummy & 0x80))break;	
	}//timed out
}while(dummy != 0x00);

for (w=100;w!=0;w--);	//wait exiting In-Idle-State
//
sser = 0;
sscrh = 0x66;		//master, f1/4

/////////////////////////////////////////////////
//	transmit CMD25(multiple write)
/////////////////////////////////////////////////
do{
sser = 0x10;		//te=1 re=0
orer_sssr = 0;		//clear overrun flag

while(!tdre_sssr);
sstdr = 0xff;		//dummy
while(!tend_sssr);
while(!tdre_sssr);

sstdr = 0x59;		//CMD25=59_0000_0000_01h
while(!tend_sssr);
while(!tdre_sssr);

sstdr = 0x00;		
while(!tend_sssr);
while(!tdre_sssr);
sstdr = 0x00;		
while(!tend_sssr);
while(!tdre_sssr);

sstdr = 0x00;		
while(!tend_sssr);
while(!tdre_sssr);
sstdr = 0x00;		
while(!tend_sssr);
while(!tdre_sssr);

sstdr = 0x01;
while(!tdre_sssr);		
while(!tend_sssr);	//wait trans end



//----------------------------
//	wait R1 resp
//----------------------------

sser = 0x08;		//te=0 re=1
orer_sssr = 0;		//clear overrun flag

rsstp_sscrh = 1;		//receive 1 byte
dummy = ssrdr;		//dummy read

for(w=16;w!=0;w--)
	{
		while(!rdrf_sssr);	//wait resp
		dummy = ssrdr;
		if(!(dummy & 0x80))break;
		
	}//timed out
}while(dummy != 0x00);

//----------------------------
//	start writing
//----------------------------

while(!rdrf_sssr);
sser = 0x10;		//te=1 re=0
orer_sssr = 0;		//clear overrun flag

while(!tdre_sssr);
sstdr = 0xfc;		//multiple write start token
while(!tend_sssr);
for(w=512;w!=0;w--){ 
	while(!tdre_sssr);
	sstdr = 0xAA;	//write 512byte Data	
	while(!tend_sssr);
}
while(!tdre_sssr);
sstdr = 0xff;		//CRC
while(!tend_sssr);
while(!tdre_sssr);
sstdr = 0xff;		//CRC
while(!tend_sssr);
		
//----------------------------
//	receive resp.
//----------------------------
while(!tdre_sssr);
sser = 0x08;		//te=0 re=1
orer_sssr=0;		//clear overrun flag

rsstp_sscrh=1;		//receive 1 byte
dummy = ssrdr;		//dummy read
while(1){
	while(!rdrf_sssr);
	if((ssrdr&0x0f)==5)break;		//get resp.
}	

while(1){
	while(!rdrf_sssr);
	if(ssrdr!=0)break;	//wait busy
}




while(!rdrf_sssr);
sser = 0x10;		//te=1 re=0
orer_sssr = 0;		//clear overrun flag

while(!tdre_sssr);
sstdr = 0xff;		//dummy
while(!tend_sssr);
while(!tdre_sssr);
sstdr = 0xfd;		//stop tran token
while(!tdre_sssr);
while(!tend_sssr);
////////////////////////////////////////////////

sser = 0x08;		//te=0 re=1
orer_sssr=0;		//clear overrun flag
dummy = ssrdr;
while(1){
	while(!rdrf_sssr);
	if(ssrdr!=0)break;	//wait busy
	}
}


次はリード命令(CMD18)です。