⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmc.c

📁 TI公司TMS320VC5509的外设驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:

/* a write to MMCCMD triggers the sending of the command.  therefore, the argument
registers (MMCARGx) need to be written to before the MMCCMD is written to*/

/* 	command bit positions:
*   -----------------------------------------------------------
*   MMRs        Bit position of command
*   -----------------------------------------------------------
*               [47]         (start bit)
*               [46]         (transmission bit)
*   MMCCMD[5:0] [45:40]      (command index)
*   MMCARGH     [39:24]      (argument)
*   MMCARGL     [23:8]       (argument)
*               [7:1]        (CRC7)
*               [0]          (end bit)
*   -----------------------------------------------------------
    
NOTE:    
	pMMC->cmd tells whether to transfer data or not (DATA), block are stream transfer (STREAM)
	data read or write (WRITE), the response format (read note) and busy signal expected
	(BSYEXP).
	NOTE: For each command, I have already inserted the response expected and where or not
	it expects a busy signal because those seem to be predefined.  might do read/write and
	data bit too as pre defined, but leaving out for debugging purposes???????
*/
 
static void dump_regs( void )
{ 
	Mmc.fckctl     = pMMC->fckctl;
	Mmc.ctl        = pMMC->ctl;
	Mmc.clk        = pMMC->clk;
	Mmc.st0        = pMMC->st0;
    Mmc.st1        = pMMC->st1;
	Mmc.im         = pMMC->im;	
	Mmc.tor        = pMMC->tor;
	Mmc.tod        = pMMC->tod;
	Mmc.blen       = pMMC->blen; 
	Mmc.nblk       = pMMC->nblk;
	Mmc.nblc       = pMMC->nblc;
	Mmc.ddr        = pMMC->ddr;
	Mmc.dxr        = pMMC->dxr;
	Mmc.cmd        = pMMC->cmd;
	Mmc.argl       = pMMC->argl;
	Mmc.argh       = pMMC->argh;
	Mmc.rsp0       = pMMC->rsp0;
	Mmc.rsp1       = pMMC->rsp1;
	Mmc.rsp2       = pMMC->rsp2;
	Mmc.rsp3       = pMMC->rsp3;
	Mmc.rsp4       = pMMC->rsp4;
	Mmc.rsp5       = pMMC->rsp5;
	Mmc.rsp6       = pMMC->rsp6;
	Mmc.rsp7       = pMMC->rsp7;
	Mmc.drsp       = pMMC->drsp;
	Mmc.etok       = pMMC->etok;
    Mmc.cidx       = pMMC->cidx;  
}
  
static void clear_rsp( void )
{
	pMMC->rsp0 = 0;
	pMMC->rsp1 = 0;
	pMMC->rsp2 = 0;
	pMMC->rsp3 = 0;
	pMMC->rsp4 = 0;
	pMMC->rsp5 = 0;
	pMMC->rsp6 = 0;
	pMMC->rsp7 = 0;
	pMMC->drsp = 0;
	pMMC->etok = 0;
    pMMC->cidx = 0;  
}    
static void get_rsp( void )
{
	Mmc.rsp0 = pMMC->rsp0;
	Mmc.rsp1 = pMMC->rsp1;
	Mmc.rsp2 = pMMC->rsp2;
	Mmc.rsp3 = pMMC->rsp3;
	Mmc.rsp4 = pMMC->rsp4;
	Mmc.rsp5 = pMMC->rsp5;
	Mmc.rsp6 = pMMC->rsp6;
	Mmc.rsp7 = pMMC->rsp7;
	Mmc.drsp = pMMC->drsp;
	Mmc.etok = pMMC->etok;
    Mmc.cidx = pMMC->cidx;  
}    
 
static void get_card_status( void )
{
	Mmc.rsp6 = pMMC->rsp6;
	Mmc.rsp7 = pMMC->rsp7;
	CardStatus.busy          = ((Mmc.rsp6 >> 8)  & 1   );   
	CardStatus.state         = (CARD_STATE)((Mmc.rsp6 >> 9)  & 0xf );
	CardStatus.erase_clrd    = ((Mmc.rsp6 >> 13) & 1   );
	CardStatus.erase_partial = ((Mmc.rsp6 >> 15) & 1   ); 
	CardStatus.error_flags   = Mmc.rsp7;                
}	

static void get_card_cid( void )
{

	unsigned long temp;
	get_rsp();  
		
	CardCid.year             = (Mmc.rsp0 >> 8   ) & 0xF; // 11:8
	CardCid.month            = (Mmc.rsp0 >> 12  ) & 0xF; // 12:15
	CardCid.serial	         = (unsigned long)(Mmc.rsp1);// 39:16
	temp                     = (unsigned long)(Mmc.rsp2 & 0x00FF);
	CardCid.serial           |= (temp<<16);
	CardCid.fw_rev            = (Mmc.rsp2 >>8  ) & 0x000F;  // 43:40
	CardCid.hw_rev            = (Mmc.rsp2 >>12 ) & 0x000F;  // 47:44
	CardCid.mfg_id            = (Mmc.rsp6 >>8  ) & 0x00FF;  //127:104
	temp                     = (unsigned long)(Mmc.rsp7      );	
	CardCid.mfg_id            |= temp << 16;   	
}
 
static void get_card_csd(void)
{      
	get_rsp();  
	
	CardCsd.ecc				= (Mmc.rsp0 >>  8   ) & 3;  		// 9:8
	CardCsd.tmp_wp          = (Mmc.rsp0 >>  12  ) & 1;          // 12:12
	CardCsd.perm_wp         = (Mmc.rsp0 >>  13  ) & 1;          // 13:13
	CardCsd.copy            = (Mmc.rsp0 >>  14  ) & 1;	        // 14:14

	CardCsd.wr_bl_part      = (Mmc.rsp1 >>   5  ) & 1;          // 21:21 
	CardCsd.wr_bl_len       = (Mmc.rsp1 >>   6  ) & 0xF;        // 25:22
	CardCsd.r2w_factor      = (Mmc.rsp1 >>  10  ) & 0x7;        // 28:26
	CardCsd.def_ecc         = (Mmc.rsp1 >>  13  ) & 0x3;		// 30:29	
	CardCsd.wp_brp_ena      = (Mmc.rsp1 >>  15  ) & 1;          // 31:31
	
	CardCsd.wp_grp_size     = (Mmc.rsp2         ) & 0x1f;       // 36:32
	CardCsd.er_grp_size     = (Mmc.rsp2  >>  5  ) & 0x1f;       // 41:37
	CardCsd.sect_size       = (Mmc.rsp2  >> 10  ) & 0x1f;       // 46:42
	CardCsd.c_size_mult     = (Mmc.rsp2  >> 15  ) & 1;          // 49:47
	CardCsd.c_size_mult     |=( (Mmc.rsp3 &  3  ) << 1);
	
	CardCsd.vdd_w_curr_max  = (Mmc.rsp3  >>  2  ) & 0x7;  		// 52:50
	CardCsd.vdd_w_curr_min  = (Mmc.rsp3  >>  5  ) & 0x7;        // 55:53
	CardCsd.vdd_r_curr_max  = (Mmc.rsp3  >>  8  ) & 0x7;        // 58:56
	CardCsd.vdd_r_curr_min	= (Mmc.rsp3  >>  11 ) & 0x7;        // 61:59
	CardCsd.c_size          = (Mmc.rsp3  >>  14 ) & 0x3;        // 73:62
	CardCsd.c_size          |=((Mmc.rsp4  & 0x3FF) << 2); 
	
	CardCsd.dsr_imp         = (Mmc.rsp4  >> 12  ) & 1;    		// 76:76
	CardCsd.rd_blk_misal    = (Mmc.rsp4  >> 13  ) & 1;          // 77:77
	CardCsd.wr_blk_misal    = (Mmc.rsp4  >> 14  ) & 1;          // 78:78
	CardCsd.rd_bl_part      = (Mmc.rsp4  >> 15  ) & 1;          // 79:79
	
	CardCsd.rd_bl_len       =  (Mmc.rsp5        ) & 0xf;		// 83:80
	CardCsd.ccc             =  (Mmc.rsp5 >>  4  ) & 0xfff;		// 895:84
	
	CardCsd.tran_speed      =  (Mmc.rsp6        ) & 0xff;		// 103:96
	CardCsd.nsac            =  (Mmc.rsp6  >>  8 ) & 0xff;		// 111:104
	
	CardCsd.taac            =  (Mmc.rsp7        ) & 0xff;       // 119:112
	CardCsd.mmc_prot        =  (Mmc.rsp7  >> 10 ) & 0xf;        // 125:122
	CardCsd.csd_struct      =  (Mmc.rsp7  >> 14 ) & 0x3;        // 127:126
}

// Tested, tnyc   
static int wait_for( unsigned short event )
{     
	// This function assumes that a command will timeout
	// otherwise we will get hung here forever.
	volatile unsigned short stat;
	do
	{
		stat = pMMC->st0;
		stat &= (SPIERR | CRCRS | CRCRD | CRCWR | TOUTRS | TOUTRD | event); 
		
	}while( stat == 0 ); 
	// If we got the event we were looking for then
	// return pass. We may have gotten an event but 
	// maybe not the one we were expecting, i.e. a time our or crc. 
	SaveStat0 = stat;
	
	return( ((stat & event) == event ) ? 0 : -1 );		
}

// Tested, tnyc		  
static int go_idle_state(void)
{    
    pMMC->argh = STUFF_BITS;
    pMMC->argl = STUFF_BITS;
	   
	// Add in the INIT bit so that we wait for the 80
	// clocks before sending the intial command   
	pMMC->cmd  = GO_IDLE_STATE | INIT | DCLR; 
	  
	// Resp = NONE, just check for command sent  
	return( wait_for( RSPDNE ));
}         


// Tested, tnyc
#define VDD_32_33		0x0010  // 0x007f		
/*should have a wide range of voltage-- between 2.6 and 3.6, but 3.3 is the preferred*/
static int 
send_op_cond(void)
{              
	volatile unsigned short stat; 
	long op_timeout;
	             
	// Set flags to busy and fail             
	op_timeout       = OP_TIMEOUT;
	OpLoop           = 0;
	 
	// You will go through this loop at least twice.  The first time
	// you will apply your requested voltage level and receive a
	// busy.  The second time you re-apply your voltage level and
	// generaly get a not busy.  This indicates the card has
	// initialized.
	//  
    // Clear status
    stat = pMMC->st0;     
    
	do
	{    
	    // For debug.  Want to know how many loops it takes.
		OpLoop++;
				              
		// Set minimal voltage range              
		pMMC->argh   = VDD_32_33;
		pMMC->argl   = 0;
		pMMC->cmd    = SEND_OP_COND;	    
   		
		// Break on response fail  
		if( wait_for( RSPDNE ))
			break;
 		// Resp = R3                      
        // Busy bit is in MSB of rsp7.  If '1' (not busy) then we are done.                  
      	stat = pMMC->rsp7;   
	    if( stat & 0x8000 )
	    	return( 0 );
	     	    	  
		if( !Debug )
			op_timeout--; 
					  	    	  
	}while( op_timeout > 0 );
	     
	// Timed out     
	return( -1 );
}  

// Tested, tnyc   
static int all_send_cid( void )
{ 
	volatile unsigned short stat; 
    stat = pMMC->st0;  
    if( Debug )
    	clear_rsp();
    	   		
    pMMC->argh = STUFF_BITS;
    pMMC->argl = STUFF_BITS;
	pMMC->cmd  = ALL_SEND_CID;  
	if( wait_for( RSPDNE ) == 0 )
	{    
 		// Resp = R2, Should probably check for something    	
		get_rsp();
		return( 0 );	
	} 
	return( -1 );  
}


/*NOTE the default rca is 0x0001.  0x0000 is used by CMD7 to deselect
all the cards, so you cannot assign it to a card*/ 
// Tested, tnyc

static int set_relative_addr(unsigned short rca)
{
   if( Debug )
    	clear_rsp();
		    	
    pMMC->argh = rca;
    pMMC->argl = STUFF_BITS;
	pMMC->cmd  = SET_RELATIVE_ADDR;
	if( wait_for( RSPDNE ) == 0 )
	{ 
		// Resp = R1  	  
        get_card_status();
		return(0);	
	}
    return( -1 );
}                                 
    

// Tested, tnyc

static int send_status(unsigned short rca)
{
   if( Debug )
    	clear_rsp();
    	
    pMMC->argh = rca;
    pMMC->argl = STUFF_BITS;
	pMMC->cmd  = SEND_STATUS;   
	
	if( wait_for( RSPDNE ) == 0 )
	{ 
		// Resp = R1  	  
        get_card_status();
		return(0);	
	}
    return( -1 );
}

 

// Tested, tnyc 
static int send_cid(unsigned short rca)
{

    pMMC->argh = rca;
    pMMC->argl = STUFF_BITS;
	pMMC->cmd  = SEND_CID;
	if( wait_for( RSPDNE ) == 0 )
	{ 
		// Resp = R2  	  
        get_card_cid();
		return(0);	
	}
    return( -1 );
} 

// Tested, tync 
static int send_csd(unsigned short rca)
{
    pMMC->argh = rca;
    pMMC->argl = STUFF_BITS;
	pMMC->cmd  = SEND_CSD;      
	if( wait_for( RSPDNE ) == 0 )
	{ 
		// Resp = R2  	  
        get_card_csd();
		return(0);	
	}
    return( -1 );
}                     

// Tested, tnyc
static int select_card(unsigned short rca)
{    
	// Select the card then check status to see if
	// we are in the proper state
    pMMC->argh = rca;
    pMMC->argl = STUFF_BITS;	
	pMMC->cmd  = SELECT_CARD;
	if( wait_for( RSPDNE ) == 0 )
	{   
		if( rca > 0 )
		{
			if(    ( send_status( rca ) == 0 )
			    && (   ( CardStatus.state ==  tran )
			        || ( CardStatus.state ==  prg  )))
				return(0);	
		}	
	} 
	return( -1 );
}                                 

// Tested, tnyc
static int deselect_card( unsigned short rca )
{    
	// Deselect the card then check status to see if
	// we are in the proper state.  Because we are
	// using rca = 0 to deselect there will not be
	// the typical R1 response.
    pMMC->argh = 0;
    pMMC->argl = STUFF_BITS;	
	pMMC->cmd  = DESELECT_CARD;
	if( wait_for( RSPDNE ) == 0 )
	{   
		if(    ( send_status( rca ) == 0 )
		    && (   ( CardStatus.state ==  stby )
		        || ( CardStatus.state ==  dis )))
		return(0);	
	} 
	return( -1 );
}                                 

static int set_blocklen( unsigned short block_len )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -