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

📄 sdd_mem.c

📁 sd卡的高速读写程序 sd卡的高速读写程序
💻 C
📖 第 1 页 / 共 4 页
字号:
    SD_xmit_info.arg = arg;
    SD_xmit_info.response_expected = (sd_resp_ptr[cmd] & 0xf);
    SD_xmit_info.response_recv = 0;
    SD_xmit_info.use_data = (sd_resp_ptr[cmd]>>4);
    SD_xmit_info.wait_nclk = SD_NCR_MAX;
    SD_xmit_info.cmd_sent = 0; 
    SD_xmit_info.retry_cnt = 0;    

    if (SD_xmit_info.use_data == 2) { /* data read */
	/* data destination */
	if (SD_xmit_info.cmd == SD_ACMD_SD_STATUS) {
	    SD_xmit_info.cur_blk_size = 6; /* 64Bytes */
	    SD_xmit_info.rd_dest_ptr = (uint *)SD_status_ptr;
	} else if (SD_xmit_info.cmd == SD_ACMD_SEND_SCR) {
	    SD_xmit_info.cur_blk_size = 3; /* 8Bytes */
	    SD_xmit_info.rd_dest_ptr = (uint *)SD_scr_reg_ptr;
	}
    } else if (!SD_xmit_info.use_data
	       || SD_xmit_info.response_expected) { 
	/* response data destination */
	if (SD_xmit_info.response_expected == SD_R2) {
	    SD_xmit_info.rd_dest_ptr = 
		(SD_xmit_info.cmd == SD_CMD_SEND_CSD) ?
		(uint *)SD_csd_reg_ptr : (uint *)SD_cid_reg_ptr;
	} else {
	    if (SD_xmit_info.response_expected == SD_R3){
		SD_xmit_info.rd_dest_ptr = (uint *)SD_ocr_reg_ptr;
	    } else if (SD_xmit_info.response_expected == SD_R6){
		/* R6 is special..*/
		SD_xmit_info.rd_dest_ptr = &SD_rdata32;
	    } else { /* R1 or R1b */
		SD_xmit_info.rd_dest_ptr = (uint *)SD_card_status_ptr;
	    }
	}
    }

    return(1);
}

static int SD_slow_clk_data_out(uchar out_data)
{  
    int i;
    unsigned sclk_high, sclk_low;

    SD_GET_SCLK_VAL(sclk_high, sclk_low);

    for(i=0; i<8; i++){
	if (out_data & 0x80) {
	    SET_SD_CMD;
	} else {
	    CLEAR_SD_CMD;
	}	
	out_data <<= 1;
	CLEAR_SD_CLK;
	risc_sleep_a_bit(USEC(2));
	SET_SD_CLK;
	risc_sleep_a_bit(USEC(2));
    }
}
/***********************************************
 up to 1 DWORD
************************************************/
static int SD_slow_clk_data_in(int bit_cnt)
{
    int data_in = 0, i;
    unsigned sclk_high, sclk_low;

    SD_GET_SCLK_VAL(sclk_high, sclk_low);

    for (i=0; i<bit_cnt; i++) {
	CLEAR_SD_CLK;
	risc_sleep_a_bit(USEC(2));
	SET_SD_CLK;
	risc_sleep_a_bit(USEC(1));
	data_in <<= 1;
	data_in |= (SD_CMD_HIGH != 0);
	risc_sleep_a_bit(USEC(1));
    }
    return data_in;
}
static void SD_slow_clk_pulse_l2h(void)
{
    unsigned sclk_high, sclk_low;

    SD_GET_SCLK_VAL(sclk_high, sclk_low);

    CLEAR_SD_CLK;
    risc_sleep_a_bit(USEC(2));
    SET_SD_CLK;
    risc_sleep_a_bit(USEC(2));
}
/* 
  Function: For init commands during SD card initialization,
	    under clock restriction (100KHz < clk < 400KHz).
	    (Also for MMC's CMD1)

  input:
	command: command index (CMD1,CMD2,CMD3,CMD55,ACMD41).
	arg:	command argument.

  output:		      
	-1:	timed out (reached retry limit).
	 0:	crc error.
     	 1:	successful

  side-effects:
	updates SD_card_status for CMD55 if success.
	updates SD_ocr_reg for ACMD41/CMD1 if success. 
	updates SD_cid_reg for CMD2 if success. 
	updates SD_rca_reg for CMD3 if success. 
*/
int SD_clk_restricted_cmd(int command, uint arg)
{
    int i, j,cnt, sd_timeout, rcv_cnt, crc_check;
    ushort sd_crc;
    uint sd_mask, tmp, data_in, *sd_rdata_ptr;
    char cmd_buf[8], rcv_buf[8], *pChar, *rdata_pchar;
    unsigned sclk_high, sclk_low;

    PRINTF(("SD_clk_restricted_cmd ...command %x, arg %x\n", command, arg));

    SD_GET_SCLK_VAL(sclk_high, sclk_low);
    
    pChar = cmd_buf;
    data_in = 0x40|(command & 0x3f);
    *pChar++ = data_in;

    *pChar++ = (arg>>24) & 0xff;
    *pChar++ = (arg>>16)& 0xff;
    *pChar++ = (arg>>8) &0xff;
    *pChar++ = arg & 0xff;
    sd_crc = SD_calc_crc7(cmd_buf, 5);

    for (i=0; i<5; i++)
	SD_slow_clk_data_out(cmd_buf[i]);

    tmp = (sd_crc<<1) | 1;
    /* crc7 + end bit */
    SD_slow_clk_data_out(tmp);

    SD_CMD_INPUT; /* get ready for response */
    if(SD_card_info.type == SD_MMC
       && command == SD_CMD_SEND_REL_ADDR)
	sd_timeout = SD_NCR_MAX;
    else
	sd_timeout = SD_NID_MAX;

    
    for (i = 0; (i < sd_timeout); i++) {
	SD_slow_clk_pulse_l2h();
	
	if (SD_CMD_LOW) { /* response start bit */
	    /* xmit bit */
	    SD_slow_clk_pulse_l2h();
	    /* get SD response */	
	    sd_crc = 0;
	    break;
	}
    }

    if (i >= sd_timeout){
	/* timed out..*/
	JPRINTF(("clk_res: timed out\n"));
	return (-1);
    } else {
	cnt = 0;
	crc_check = 0;
	if (command == SD_CMD_ALL_SEND_CID
	    ||command == SD_CMD_SEND_CID ) {
	    cnt = 3; /* extra data for R2 response */
	    sd_rdata_ptr = (uint *)SD_cid_reg_ptr;
	} else if ((command == SD_ACMD_SD_SEND_OP_COND) ||
		   (command == SD_CMD_MMC_SEND_OP_COND)) {
	    sd_rdata_ptr = (uint *)SD_ocr_reg_ptr;
	    /* R3 */
	} else if (command == SD_CMD_SEND_REL_ADDR
		   && SD_card_info.type == SD_MEM) {
	    sd_rdata_ptr = &SD_rdata32;
	    /* R6 */
	    crc_check = 1;
	} else { /* R1 (SD_CMD_APP_CMD)*/
	    sd_rdata_ptr = (uint *)SD_card_status_ptr;
	    crc_check = 1;
	}
    }

    
    /* clock in cmd and arg (38bits)..save only arg (last 32bits) */
    pChar = rcv_buf;

    data_in = SD_slow_clk_data_in(6);
    *pChar++ = data_in;
    rcv_cnt = 1;

    rdata_pchar = (char*)sd_rdata_ptr;
    for(j=0; j<4; j++){
	data_in = SD_slow_clk_data_in(8);
	*pChar++ = data_in;
	rcv_cnt++;
	*rdata_pchar++ = data_in;
    }
    
    cnt <<= 2;
    while (cnt){
	*rdata_pchar++ = SD_slow_clk_data_in(8) ;
	cnt--;
	if (!cnt) goto sd_exit;
    }

    /* crc7 + end bit */
    data_in = SD_slow_clk_data_in(8) ;
    
#if CHECK_RECV_CRC 
    if (!crc_check) {
	sd_crc = 0x7f; /* no CRC for R3 response */
    }else
	sd_crc = SD_calc_crc7(rcv_buf, rcv_cnt);
    data_in >>= 1; /* remove end bit */
    PRINTF(("Received crc: %x, Computed crc: %x\n", data_in, sd_crc));
    if (data_in != sd_crc) {
	/* crc error */
	CPRINTF(("CRC error in SD_clk_restricted_cmd()\n"));
	CPRINTF(("cmd: %d, arg: %\n", command, arg));
	CPRINTF(("xmit crc: 0x%x, gen crc: 0x%x\n", data_in, sd_crc));
	BREAKPOINT(0);
	return (0);
    }
#endif

    if (command == SD_CMD_SEND_REL_ADDR
	&& SD_card_info.type == SD_MEM) {
	sd_rdata_ptr = (uint *)SD_card_status_ptr;
	*sd_rdata_ptr &= (~0x1fff); /* bit 0-12 */
	*sd_rdata_ptr |= (SD_rdata32 & 0x1fff);
	SD_card_status_ptr->error = 
	    (SD_rdata32>>13) & 1;
	SD_card_status_ptr->illegal_cmd = 
	    (SD_rdata32>>14) & 1;
	SD_card_status_ptr->com_crc_error = 
	    (SD_rdata32>>15) & 1;
	
	SD_rca_reg = SD_rdata32>>16; /* new RCA */
    }

sd_exit:
    /* extra 8 Clocks for SD card post-processing */
    for (i = 0; i < 8; i++) {
	SD_slow_clk_pulse_l2h();
    }

    return (1); 
}


static void SD_cmd_output(uchar out_cmd)
{
    int i;
    unsigned sclk_high, sclk_low;

    SD_GET_SCLK_VAL(sclk_high, sclk_low);

    for (i=0; i<8; i++) {
	if (out_cmd &0x80) {
	    SET_SD_CMD;
	} else {
	    CLEAR_SD_CMD;
	}
	PULSE_SD_CLK_HL;
	out_cmd <<= 1;
    }
}
static void SD_1_bit_data_out(uchar out_data)
{
    int i;
    unsigned sclk_high, sclk_low;

    SD_GET_SCLK_VAL(sclk_high, sclk_low);

    for (i=0; i<8; i++) {
	CLEAR_SD_CLK;
	if (out_data & 0x80) {
	    SET_SD_DAT0;
	} else {
	    CLEAR_SD_DAT0;
	}	
	SET_SD_CLK;	
	out_data <<= 1;
    }
}

static void SD_4_bit_data_out(char *pOutData, int cnt)
{
    int i;
    char out_data;
    unsigned sclk_high, sclk_low;

    SD_GET_SCLK_VAL(sclk_high, sclk_low);

    for(i= 0; i<cnt; i++){
	out_data = *pOutData++;
	CLEAR_SD_CLK;
	SET_SD_DAT3_0( ((out_data>>4) & 0xf));
	SET_SD_CLK;
	CLEAR_SD_CLK;
	SET_SD_DAT3_0( (out_data&0xf));
	SET_SD_CLK;
    }
}

/*****************************************************************
  up to 1 DWORD
******************************************************************/
static int SD_1_bit_data_in(int bit_cnt)
{
    int i, data_in;
    unsigned sclk_high, sclk_low;

    SD_GET_SCLK_VAL(sclk_high, sclk_low);

    data_in = 0;    
    for (i=0; i<bit_cnt; i++){
	data_in <<= 1;
	CLEAR_SD_CLK;
	if(sd_is_mmc){
	    asm("nop"); asm("nop");asm("nop");
	    data_in |= SD_DAT0;
	    SET_SD_CLK;
	}else{
	    SET_SD_CLK;
	    data_in |= SD_DAT0;
	}
    }     
    return data_in;
}
/* 
  Function: The main SD transmission state machine..processes
	    all SD/MMC related commands. 
	    (ref. SD bus protocol, pp.10-83, 
	     SD-mem Physical layer specifications)

  input: no arguments, but relies on "SD_xmit_info" structure for
         state transitions and transmission info.

  output:		      

  side-effects: 
	"SD_xmit_info" members are updated according to 
	transmission progress.
*/
void SD_service(void) 
{    
    static uint sd_mask, sd_cmd_info, *sd_rdata_ptr, sd_cnt;
    static ushort sd_crc[4];
    int i,j, sd_cmd_high, sd_dat0_high, arg;
    uint tmp, data_in;
    int wr_feedback_crc;
    char cmd_buf[8], *pChar;
    unsigned sclk_high, sclk_low;

    SD_GET_SCLK_VAL(sclk_high, sclk_low);

    switch (SD_xmit_info.com_state) {
    case HOST2SD_START:
	SET_SD_CMD;
	CLEAR_SD_CLK;     /* prepare */

	sd_cmd_info = (SD_xmit_info.cmd&0x3f)|0x40;
	sd_cnt = 0;
	pChar = cmd_buf;
	*pChar++ = sd_cmd_info;
	arg = SD_xmit_info.arg;
	*pChar++ =(arg>>24)&0xff;
	*pChar++ =(arg>>16)&0xff;
	*pChar++ =(arg>>8)&0xff;
	*pChar = arg & 0xff;
	sd_crc[0] = SD_calc_crc7(cmd_buf, 5);

	SD_xmit_info.com_state = HOST2SD_CMD;
	SD_xmit_info.result = -1; /* need to set to be 0 when succeed, 
                                     currently only used in case of Erase */
	/*break; save time..let it drop*/
    case HOST2SD_CMD:
	sd_cnt++; /* for timeout/mode check */
	/* command index/argument..8bits at a time */
	for(i=0; i<5; i++)
	    SD_cmd_output(cmd_buf[i]);
 
	SD_xmit_info.com_state = HOST2SD_CRC7;
	break;
    
    case HOST2SD_CRC7:
	/* send crc7 */
	tmp = (sd_crc[0]<<1) | 1; /* crc7 + end bit */
	SD_cmd_output(tmp);

	CLEAR_SD_CLK;
	if (SD_xmit_info.response_expected) {	    
	    SD_CMD_INPUT; /* tristate cmd */

	    if (SD_xmit_info.use_data == 2) { 
		/* data read */
		if (SD_xmit_info.data_width) {
		    /* all four data lines used */
		    SD_DAT3_0_INPUT;
		} else {
		    SD_DAT0_INPUT;
		}
		sd_cmd_info = 0; /* bytes received */
		SD_xmit_info.wait_nclk = SD_card_info.n_ac_max;
	    } 
	    else if(SD_xmit_info.response_expected == SD_R1b){
		SD_DAT0_INPUT; /* busy check */
	    }

	    sd_rdata_ptr = SD_xmit_info.rd_dest_ptr;
	    SD_xmit_info.com_state = HOST2SD_WAIT;
	} else {
	    SD_xmit_info.com_state = HOST2SD_8CYCLES;
	}
	break;
	
    case HOST2SD_WAIT:
	/* check 8 cycles at a time */
     
	for (i = 0; SD_xmit_info.wait_nclk; i++) {
	    SD_LOCK15;
	    SET_SD_CLK;
	    if(sd_is_mmc){
		CLEAR_SD_CLK;
		sd_cmd_high = SD_CMD_HIGH? 1:0;
		sd_dat0_high = SD_DAT0_HIGH? 1:0;
	    }else{
		sd_cmd_high = SD_CMD_HIGH? 1:0;
		sd_dat0_high = SD_DAT0_HIGH? 1:0;
		CLEAR_SD_CLK;
	    }	

	    if (SD_xmit_info.use_data != 2
		&& !SD_xmit_info.response_recv
		&& !sd_cmd_high){ /* response start bit */
		
		SD_LOCK15;
		SET_SD_CLK;
		if(sd_is_mmc){
		    CLEAR_SD_CLK;
		    sd_cmd_high = SD_CMD_HIGH? 1:0;
		}else{
		    sd_cmd_high = SD_CMD_HIGH? 1:0;
		    CLEAR_SD_CLK;
		}
		
		/* get SD response */
		sd_crc[0] = 0;	
		sd_mask = 6; /* bit count */
		sd_cmd_info = 0; /* clear received bits */	 
		sd_cnt = 0; /* for timeout/mode check */
		SD_xmit_info.com_state = SD2HOST_NODATA;
		break;
	    } else if ((SD_xmit_info.use_data==2) 
		       && !sd_dat0_high) { /* data start bit? */

		sd_crc[0] = 0; /* clear crc */
		/* current block size (bytes) */
	        if(SD_xmit_info.cmd == MMC_CMD_READ_UNTIL_STOP)
		    sd_mask = SD_xmit_info.data_len;
		else
		    sd_mask = 1 << (SD_xmit_info.cur_blk_size);
		if(SD_xmit_info.data_width){
		    SD_xmit_info.com_state = SD2HOST_DATA4;
		}
		else{
		    SD_xmit_info.com_state = SD2HOST_DATA1;
		}
		break;
	    }
	    /* btan: After received response, we actually don't need wait n_wr_max clk. *
	     * 4 clk is ok for my SD. I did not test other SD. If you meet problem in   *
	     * SD writing function, please increase it or let me know. */
	    else if (SD_xmit_info.use_data != 2 && SD_xmit_info.response_recv 
		     && sd_cmd_high && SD_xmit_info.wait_nclk > 4) {
		SD_xmit_info.wait_nclk = 4;
	    }
	    SD_xmit_info.wait_nclk--;
	}

	if (!SD_xmit_info.wait_nclk) {
#ifdef  SD_ENABLE_WRITE
	    if (SD_xmit_info.use_data == 1
		&& SD_xmit_info.response_recv) {
		/* prepare to write.. */
		
		/* current block size (bytes) */
		sd_cmd_info = 1 << (SD_xmit_info.cur_blk_size);		
		if (SD_xmit_info.data_width) {
		    /* write wide bus */
		    CLEAR_SD_DAT3_0;
		    SD_xmit_info.com_state = HOST2SD_DATA4;
		} else {
		    CLEAR_SD_DAT0;
		    SD_xmit_info.com_state = HOST2SD_DATA1;
		}		    
		break;		
	    } else 
#endif /* SD_ENABLE_WRITE */
	    {
		/* timed out..send again?? */
                JPRINTF(("SD res:time out. xmit_len %d, xmit_cnt %d cmd %d\n",
			 SD_xmit_info.data_len, SD_xmit_info.data_cnt,
			 SD_xmit_info.cmd));
		SD_xmit_info.retry_cnt++;
		SD_xmit_info.com_state = HOST2SD_8CYCLES;
	    }
	}
	break;

#ifdef SD_ENABLE_WRITE
    case HOST2SD_DATA1:	
	/* write data, one byte at a time */
	sd_cmd_info = 1 << (SD_xmit_info.cur_blk_size);
	pChar = (char*)SD_xmit_info.wr_src_ptr + SD_xmit_info.data_cnt;
	/* crc16 calculation for narrow bus */
	sd_crc[0] = SD_calc_crc16((uchar *)pChar,sd_cmd_info);
        JPRINTF(("Xmit src %x, len %d\n", pChar, sd_cmd_info));
	/* send start bit */
	    CLEAR_SD_DAT0;
	    CLEAR_SD_CLK;
	    SET_SD_CLK;
	for(i=0; i<sd_cmd_info; i++)
	    SD_1_bit_data_out(*pChar++);
   	
	SD_xmit_info.data_cnt += sd_cmd_info; /* monitor total bytes */
	
	/* set wait timeout cycles..in case multi-block */
	SD_xmit_info.wait_nclk = SD_card_info.n_wr_max; 
	/* finished data..send CRC */
	SD_xmit_info.com_state = HOST2SD_CRC16_DATA;
	break;

    case HOST2SD_DATA4:	
	/* wide bus write, 32bits at a time */
	sd_cmd_info = 1 << (SD_xmit_info.cur_blk_size);
	pChar = (char*)SD_xmit_info.wr_src_ptr + SD_xmit_info.data_cnt;
        PRINTF(("wr_src_ptr %x, data_cnt %x pChar %x\n",
		 SD_xmit_info.wr_src_ptr, SD_xmit_info.data_cnt, pChar));
	/* crc16 calculation for 4-bit bus */
	SD_calc_crc16_4_bit((int*)pChar, sd_cmd_info>>2, sd_crc);
	/* send start bit */
	    CLEAR_SD_DAT3_0;
	    CLEAR_SD_CLK;
	    SET_SD_CLK;

	SD_4_bit_data_out(pChar, sd_cmd_info);

	SD_xmit_info.data_cnt += sd_cmd_info; /* monitor total bytes */
	/* set wait timeout cycles..in case multi-block */
	SD_xmit_info.wait_nclk = SD_card_info.n_wr_max; 
	/* finished data "block"..get CRC */
	SD_xmit_info.com_state = HOST2SD_CRC16_DATA;

⌨️ 快捷键说明

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