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

📄 mmc.c

📁 TMS320VC5509AMMC测试程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*   -----------------------------------------------------------						*/
/*   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   */
/*	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???????			  */
/**************************************************************************************** */

int MMC_Init(void);
void PLL_Init(int freq);
int write_single_block( unsigned long address );
static int read_single_block( unsigned long address );
static int send_status(unsigned short rca);
static int deselect_card( unsigned short rca );
int firstbit(unsigned short mask);

//  Read and write from an address
#define Read(addr) addr
#define Write(addr,data) addr = data

//  Set or clear all bits in the mask
#define ClearMask(addr,mask) addr = (addr & ~(mask))
#define SetMask(addr,mask) addr = (addr | (mask))  

//  Read and write data at addr, only bits in mask are affected
#define ReadMask(addr,mask) (addr & (mask))
#define WriteMask(addr,data,mask) addr = (addr & ~(mask)) | (data)

//  Read and write data at addr, shift data so that bit 0 of data is aligned
//  with lowest set bit in mask.  Only bits in mask are modified.  Example
//  with address 0x1000 initial contents = 0x4007:
//  WriteField(0x1000, 0x56, 0x0ff0) will set address 0x1000 to 0x4567.
#define ReadField(addr,mask) ((addr & (mask)) >> firstbit(mask)) 
#define WriteField(addr,data,mask) addr = (addr & ~(mask)) | (data << firstbit(mask))


main()
{
    int TestFail;
    int j;
	unsigned long BlockAddr = 0; 
	  
	/*系统初始化*/
	/*设置系统的运行速度为144MHz*/
	PLL_Init(120);
    
    /*mmc初始化*/
    if(MMC_Init())
    {
    	for(;;)
    	{}
    }      
    
	BlockAddr = 0;	 
	for( j=0; j<4; j++ )
	{
					 
	    for( OpLoop=0; OpLoop<256; OpLoop++)
	    {
	    	ReadBlock[OpLoop] = OpLoop + j;
	    }
	    	
	    OpLoop = 0; 
	    // Set done to 0.  
	    //If we get a DATADNE then this will be set to 1
	    // if DATDNE is working. 
	    Done = 0;
	    TestFail = write_single_block( BlockAddr );		      
		if(TestFail)
		{
			return(-1);	
		}	
		BlockAddr += 512;	
	}										
             
	BlockAddr = 0;	 
	for( j=0; j<4; j++ )
	{
	     
		// Set done to 0.  If we get a DATADNE then this will be
	    // set to 1 if DATDNE is working.            
        Done = 0;                  
        read_single_block(BlockAddr);    						
		BlockAddr += 512;
	}   

	if( TestFail = deselect_card( MmcAddr ))
	{
		return(-1);
	} 
	/*测试完成,进入死循环*/
	for(;;)
	{}
}
 
void DelayUsec(int usec)
{
    unsigned int i, j,k;
    for (i=0;i<usec;i++)
    {
    	for (j = 0; j < 10; j++);
    	{k = k+1;}
    }      
}

void PLL_Init(int freq)
{
    PC55XX_CMOD pCMOD = (PC55XX_CMOD)C55XX_CLKMD_ADDR;

    // Calculate PLL multiplier values (only integral multiples now)
    dspclk.clkin = DSP_CLKIN;
    dspclk.pllmult = freq / dspclk.clkin;
    dspclk.freq = dspclk.pllmult * dspclk.clkin;
    dspclk.plldiv = 0;
    dspclk.nullloopclk = NULLLOOP_CLK;

    // Turn the PLL off
    ClearMask(pCMOD -> clkmd, CLKMD_PLLENABLE);
    while(ReadMask(pCMOD -> clkmd, CLKMD_LOCK));
    
    // Initialize PLL flags    
    ClearMask(pCMOD -> clkmd, CLKMD_IAI);
    SetMask(pCMOD -> clkmd, CLKMD_IOB | CLKMD_BREAKLN);    

    // Set the multiplier/divisor
    WriteMask(pCMOD -> clkmd,
        CLKMD_PLLDIV_1 | CLKMD_BYPASSDIV_1,
        CLKMD_PLLDIV_MASK | CLKMD_BYPASSDIV_MASK);
    WriteField(pCMOD -> clkmd, dspclk.pllmult, CLKMD_PLLMULT_MASK);
        
    // Enable the PLL and wait for lock
    SetMask(pCMOD -> clkmd, CLKMD_PLLENABLE);
    while(!ReadMask(pCMOD -> clkmd, CLKMD_LOCK)); 
}

int firstbit(unsigned short mask)
{
    int shiftamt;
    unsigned short bit;

    // Find offset of first bit in mask
    bit = 1;
    for (shiftamt = 0; shiftamt < 16; shiftamt++) {
        if (bit & mask)
            break;
        bit = bit << 1;
    }
    
    return shiftamt;    
}

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;  

⌨️ 快捷键说明

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