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

📄 sdd_mem.c

📁 sd卡的高速读写程序 sd卡的高速读写程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	break;

    case HOST2SD_CRC16_DATA:
	/* send crc16 */
	if (SD_xmit_info.data_width){
	    /* wide bus */
	    uint filter = 0x8000;
	    for (i=0; i<16; i++){
		CLEAR_SD_CLK;
		tmp = 0;
                for(j=0; j<4; j++){
		    tmp |= ( (sd_crc[j]&filter?1:0)<<j);
		}
		SET_SD_DAT3_0(tmp);
		SET_SD_CLK;
	    	filter >>= 1;	
	    }
	    /* send end bit */
	    CLEAR_SD_CLK;
	    SET_SD_DAT3_0(0xf); /* set dat[3:0] high */
	    SET_SD_CLK;

	    SD_DAT0_INPUT;    
	} else {
	    /* narrow bus */
	    SD_1_bit_data_out(sd_crc[0]>>8);
	    SD_1_bit_data_out(sd_crc[0]&0xff);
	    /* send end bit */
	    CLEAR_SD_CLK;
	    SET_SD_DAT0;
	    SET_SD_CLK;

	    SD_DAT0_INPUT;    
	}
	PRINTF(("wait to get crc back \n"));
	/* 2 clks..then there should be CRC check start bit */
	PULSE_SD_CLK;	    
	PULSE_SD_CLK;

	/* crc status: 010: Ok
                       101: Transimission error
                       111: Error */
	wr_feedback_crc = SD_1_bit_data_in(5);
	
	sd_cnt = 0;
        if(wr_feedback_crc != 0x5){
	    JPRINTF(("crc after xmit CRC16: %x\n",wr_feedback_crc));
	    SD_xmit_info.com_state = HOST2SD_8CYCLES;
	}
	else{
	    SD_xmit_info.wait_nclk = 100*SD_card_info.n_wr_max; 
	    SD_xmit_info.com_state = HOST2SD_CHECK_BUSY;
	}
	break;
#endif /* SD_ENABLE_WRITE */
    case HOST2SD_CHECK_BUSY:
	
#if 0
	/* Reading performance will be impacted */
	RISC_sleep_nsec(3000000);	
#endif
	sd_cnt++; /* for timeout/mode check */
	for (i=0; i<8; i++) {
	    PULSE_SD_CLKZ;
	    if (SD_DAT0_HIGH) { /* Busy bit */
		/* SD not Busy..continue */
		/* set next_state..
		 *  - for single-block write, prepare to go idle 
		 *  - for multi-block write, write another block
		 */
		PRINTF((" Not busy ... xmit_cnt %d\n", 
			 SD_xmit_info.data_cnt));
		
		if(SD_xmit_info.cmd == SD_CMD_WRITE_MULTI_BLOCK
		   && SD_xmit_info.data_cnt < SD_xmit_info.data_len){
		    SD_xmit_info.wait_nclk = SD_card_info.n_wr_max; 
		    SD_xmit_info.com_state = HOST2SD_WAIT;
		}
		else{
		    SD_xmit_info.com_state = HOST2SD_8CYCLES;
		    SD_xmit_info.result = 0;
		}
		/* single block write  or erase*/
		break;
	    }
	}

	/*consider a timeout mechanism for this state */
	
	if (sd_cnt > SD_xmit_info.wait_nclk){
	    JPRINTF(("Check Bus Busy: Time out\n"));
	    SD_xmit_info.com_state = HOST2SD_8CYCLES; 
	}	
	break;	
    case SD2HOST_NODATA:
	sd_cnt++; /* for timeout/mode check */
	/* response: command index/arg..8bits at a time */
	data_in = 0;
       
	for (i=0; (i<8) && sd_mask; i++) {
	    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;
	    }

	    data_in <<= 1;
	    data_in |= sd_cmd_high;
	    sd_mask--; /* bit count remain */
	}
	
	if (i==8) { /* one arg byte in..cmd index only has 6 bits */
	    SD_rdata32 <<= 8;
	    SD_rdata32 |= data_in;

	    sd_cmd_info += 8; /* received bits */	    
	    if (sd_cmd_info == 32) { /* received 32 bits */
		*sd_rdata_ptr++ = SD_rdata32;
		/* for 32 bit data we won't get anymore */
		sd_cmd_info = 0; /* reset */
	    }
	}
	
	if (!sd_mask) {
	    if (sd_cnt == 1) {
		/* finished cmd..get arg */
		if (SD_xmit_info.response_expected == SD_R2) {
		    sd_mask = 120; /* CID/CSD bit count */
		    sd_crc[0] = 0; /* CRC7 on arg data only */
		} else {
		    sd_mask = 32; /* bit count */
		}
		sd_cmd_info = 0; /* clear received bits */
		
		/* no state change..SD_xmit_info.com_state */
	    } else if ((sd_cnt == 16) &&
		       (SD_xmit_info.response_expected == SD_R2)) {
		/* finished CID/CSD register..next CRC7 */
		sd_crc[1] = sd_crc[0]; /* save current crc */
		sd_mask = 8; /* internal CRC7 + end bit */

		/* no state change..SD_xmit_info.com_state */
	    } else {
		/* finished arg.. */
		if (SD_xmit_info.response_expected == SD_R2) {
		    /* internal crc */
#if SD_CHECK_RECV_CRC
		    data_in = 
			(SD_xmit_info.cmd == SD_CMD_SEND_CSD) ?
			(uint)SD_csd_reg_ptr->crc : 
			(uint)SD_cid_reg_ptr->crc;
		    
		    data_in &= 0x7f; /* 7bit crc */
		    sd_crc[1] &= 0x7f; /* 7bit crc */
		    if (data_in != sd_crc[1]) {
			/* crc error */
			SD_xmit_info.crc7_err_cnt++;
			CPRINTF(("R2 CRC7 error in SD_service()\n"));
			CPRINTF(("xmit crc: 0x%x, gen crc: 0x%x\n",
				 data_in, sd_crc[1]));
			BREAKPOINT(0);
		    }
#endif /* SD_CHECK_RECV_CRC */
		    SD_xmit_info.response_recv = 1;
		    SD_xmit_info.com_state = HOST2SD_8CYCLES;
		} else {
		    /* R6 response data */
		    if (SD_xmit_info.response_expected == SD_R6) {
			sd_rdata_ptr = (uint *)SD_card_status_ptr;
			*sd_rdata_ptr &= (~0x1fff);
			*sd_rdata_ptr |= (SD_rdata32 & 0x1fff);
			SD_card_status_ptr->error = 
			    (SD_rdata32>>12) & 1;
			SD_card_status_ptr->illegal_cmd = 
			    (SD_rdata32>>13) & 1;
			SD_card_status_ptr->com_crc_error = 
			    (SD_rdata32>>14) & 1;

			SD_rca_reg = SD_rdata32>>16;			
		    }

		    if (SD_xmit_info.response_expected == SD_R3) {
			/* R3 response has no CRC7 */
			sd_crc[0] = 0x7f;
		    }
		    /* finished arg..get CRC */
		    SD_xmit_info.com_state = SD2HOST_CRC7_NODATA;
		}
	    }
	}
	break;

    case SD2HOST_DATA1:	
	/* just get data, 32*sd_maskbits at a time..ignore response */
         
	 PRINTF(("SD2HOST_DATA1: xmit_len %d, xmit_data %d sd_mask %d\n",
		  SD_xmit_info.data_len, SD_xmit_info.data_cnt, sd_mask));
	 
	 sd_cmd_info = sd_mask;
	 j = (sd_mask+3)/4;
	 if(sd_is_mmc){
	     do{
		 data_in = 0;    
		 for (i=0; (i<32); i++){
		     data_in <<= 1;
		     SD_LOCK15;
		     SET_SD_CLK;
		     CLEAR_SD_CLK;
		     asm("nop"); asm("nop");asm("nop");
		     data_in |= SD_DAT0;
		 }     
		 *sd_rdata_ptr++ = data_in;
	     }while(--j>0);
	 
	 }else{
	     do{
		 data_in = 0;    
		 for (i=0; (i<32); i++){
		     data_in <<= 1;
		     SD_LOCK15;
		     SET_SD_CLK;
		     data_in |= SD_DAT0;
		     CLEAR_SD_CLK;
		 }     
		 *sd_rdata_ptr++ = data_in;
	     }while(--j>0);
	 }
	 PRINTF(("SD_xmit_cmd %d\n", SD_xmit_info.cmd));
	 if(SD_xmit_info.cmd == SD_CMD_READ_MULTI_BLOCK){
	     SD_xmit_info.data_cnt += sd_cmd_info;
	     PRINTF(("SD_xmit_cmd %d\n", SD_xmit_info.cmd));
	 }
	 else{
	     SD_xmit_info.data_cnt = sd_cmd_info;
	 }
	 	
	 /* set wait timeout cycles..in case multi-block */
	 SD_xmit_info.wait_nclk = SD_card_info.n_ac_max;
	 
	 /* finished arg..get CRC */
	 if(SD_xmit_info.cmd == MMC_CMD_READ_UNTIL_STOP){
	     SD_xmit_info.com_state = SD_IDLE;
	 }else{
	     SD_xmit_info.com_state = SD2HOST_CRC16_DATA;
	     PRINTF(("go to get CRC16\n"));
	 }
	 break;

    case SD2HOST_DATA4:	
	/* just get data, 32bits at a time..ignore response */
	sd_cmd_info += sd_mask;
	sd_mask >>= 2;
	do{
	    data_in = 0;
	    for (i=0; (i<8); i++){	
		SD_LOCK15;
		SET_SD_CLK;
		data_in <<= 4;
		data_in |= SD_DAT3_0;
		CLEAR_SD_CLK;
	    }
	    *sd_rdata_ptr++ = data_in;
	    sd_mask--; /* bytes remain */
	}while(sd_mask>0);
	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_ac_max; 
	/* finished data block..get CRC */
	SD_xmit_info.com_state = SD2HOST_CRC16_DATA;
	break;

    case SD2HOST_CRC7_NODATA:
	/* get crc7 */
	data_in = 0;
	/* clock in crc7 + end bit */
 
	for (i=0; (i < 8); i++) {
	    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;
	    }
#if SD_CHECK_RECV_CRC
	    data_in <<= 1;
	    data_in |= sd_cmd_high;
#endif
	}
	SD_xmit_info.response_recv = 1;
	if(SD_xmit_info.response_expected == SD_R1b){

	    if(SD_xmit_info.cmd == SD_CMD_ERASE
	   && (SD_card_status_ptr->erase_seq_error
	       || SD_card_status_ptr->erase_param)
	       ){
		JPRINTF(("Erase error...\n"));
		SD_xmit_info.com_state = HOST2SD_8CYCLES;
	    }else{
		SD_xmit_info.wait_nclk = 100*SD_card_info.n_wr_max; 
		SD_xmit_info.com_state = HOST2SD_CHECK_BUSY;
		JPRINTF(("R1b: to check busy state: card_status %x, cmd %d \n",
			 *(int*)SD_card_status_ptr, SD_xmit_info.cmd));
	    }
	}else{
#ifdef SD_ENABLE_WRITE
	    if (SD_xmit_info.cmd == SD_CMD_WRITE_BLOCK
		||SD_xmit_info.cmd == SD_CMD_WRITE_MULTI_BLOCK ) { 
		/* data write */
		if (SD_xmit_info.data_width) {
		    SET_SD_DAT3_0(0xf); /* set dat[3:0] high */
		} else {
		    SET_SD_DAT0;
		}
		SD_xmit_info.wait_nclk = SD_card_info.n_wr_max;
		SD_xmit_info.com_state = HOST2SD_WAIT;
		SD_xmit_info.data_cnt = 0;
		JPRINTF(("Wait to write data, status %x\n",
			 *(int*)SD_card_status_ptr));
	    }else
#endif /* SD_ENABLE_WRITE */
		SD_xmit_info.com_state = HOST2SD_8CYCLES;

	}
	break;

    case SD2HOST_CRC16_DATA:
	/* get crc16 */
	data_in = 0;
	/* clock in crc16 + end bit */
        PRINTF(("SD2HOST_CRC16_DATA:\n"));
	for (i=0; (i < 17); i++) {
	    data_in <<= 1;
	    SD_LOCK15;
	    SET_SD_CLK;
	    if(sd_is_mmc){
		CLEAR_SD_CLK;
		data_in |= SD_DAT0;
	    }else{
		data_in |= SD_DAT0;
		CLEAR_SD_CLK;
	    }
	}
	if(data_in &1 == 0)
	JPRINTF(("End bit not found.\n"));
	/* 
	 *  - for single-block read, prepare to go idle 
	 *  - for multi-block read, get another block
	 */
	if (SD_xmit_info.cmd == SD_CMD_READ_MULTI_BLOCK) {
	    PRINTF(("end of sector, xmit_cnt %d  xmit_len %d\n", 
		     SD_xmit_info.data_cnt,SD_xmit_info.data_len));
	    if(sd_is_mmc 
	       && SD_xmit_info.data_cnt>= SD_xmit_info.data_len){
		   SD_xmit_info.com_state = HOST2SD_8CYCLES;
		   SD_xmit_info.response_recv = 1;
		   PRINTF(("command->HOST2SD_8CYCLES \n"));
	       }
	    else{
		SD_xmit_info.com_state = HOST2SD_WAIT;
	    }
	} else {
	    SD_xmit_info.response_recv = 1; /* prevent resend */
	    SD_xmit_info.com_state = HOST2SD_8CYCLES;
	}	
	break;

    case HOST2SD_8CYCLES:
	/* extra 8 Clocks for SD card's post-processing */
	for (i = 0; i < 8; i++){
	    SD_LOCK15;
	    SET_SD_CLK;
	    CLEAR_SD_CLK;
	}
	/* check for next command..or resend */
	if (SD_get_next_cmd()){
	    JPRINTF(("next cmd not empty\n"));
	    SD_xmit_info.com_state = HOST2SD_START;
	} else {
	    SD_xmit_info.cmd_sent = 1; /* cmd completed */
	    SD_xmit_info.com_state = SD_IDLE;
	}	
	break;

    case SD_IDLE:
    default:
	break;
    }
    VCX_service();
}

int SD_get_status(void)
{
    int status = 0;
    
    status = SD_send_cmd(SD_CMD_SEND_STATUS,  SD_rca_reg<<16, 1);
    if(status != 1)
	return -1;
    else
	return (*(int*)SD_card_status_ptr);
}

#ifdef MD_ASYNC_RW


void SD_clear_state()
{
    SD_xmit_info.com_state = SD_IDLE;
    SD_xmit_info.cmd = SD_CMD_EMPTY;
    SD_acmdq.cmd = SD_CMD_EMPTY; /* clear cmd-Q */
    return;
}

/* return: 0: not finish; 1: finish; 2:read single finish; *
 * 3:write single finish; 4: read multi finish; 5: write multi finish*/
int SD_cmd_service()
{
    int ret = 0, status = 1;
    if (!SD_card_info.inserted) {
	SD_clear_state();
	return 1;
    }
    if (SD_xmit_info.com_state != SD_IDLE) SD_service();
    if (SD_xmit_info.com_state == SD_IDLE) {
	if (SD_xmit_info.cmd == SD_CMD_READ_SINGLE_BLOCK) {
	    ret = 2;
	}
	else if (SD_xmit_info.cmd == SD_CMD_WRITE_BLOCK) {
	    ret = 3;
	}
	else if (SD_xmit_info.cmd == SD_CMD_READ_MULTI_BLOCK) {
	    ret = 4;
	}
	else if (SD_xmit_info.cmd == SD_CMD_WRITE_MULTI_BLOCK) {
	    ret = 5;
	}

	if (SD_xmit_info.cmd == SD_CMD_WRITE_MULTI_BLOCK || 
	    SD_xmit_info.cmd == SD_CMD_READ_MULTI_BLOCK) {
	    SD_xmit_info.cmd = SD_CMD_EMPTY;
	    status = SD_send_cmd(SD_CMD_STOP_TRANSMIT, 0, 0);
	}
	else {
	    SD_xmit_info.cmd = SD_CMD_EMPTY;
	    if (!SD_get_next_cmd() && !ret) ret = 1;
	}
    }
    else if (SD_xmit_info.cmd == SD_CMD_READ_MULTI_BLOCK &&
	     SD_xmit_info.data_cnt >= SD_xmit_info.data_len && !sd_is_mmc) {
	status = SD_send_cmd(SD_CMD_STOP_TRANSMIT, 0, 0);
	ret = 4;
    }
    return ret;
}
#endif /*MD_ASYNC_RW*/


#if NOT_USED 
/* 
  Function: 

  input:

  output:		      

  side-effects:
*/
int SD_get_status(void)
{
    uint status = 0;
    
    if (SD_card_info.type > SD_MMC) {
	SD_send_acmd(SD_ACMD_SD_STATUS, 0, 1);
    }

    return (status);
}

/* 
  Function: SD lock card (password protect)

  input:

  output:		      

  side-effects:
*/
int SD_lock_card(int action, char *passwd)
{
    int status;
    
    /*  lock/unlock card */
    return (status);
}

/* 
  Function: SD set password 

  input:

  output:		      

  side-effects:
*/
int SD_set_password(char *passwd)
{
    int status;
    
    /* set password */
    return (status);
}

/* 
  Function: SD reset password 

  input:

  output:		      

  side-effects:
*/
int SD_reset_password(char *passwd)
{
    int status;
    
    /* reset password  w/ and w/o password */
    return (status);
}

/* 
  Function: 

  input:

  output:		      

  side-effects:
*/
int SD_write_data(uint data)
{
    int status;

    /* send data w/ CRC16 */
    return (status);
}
#endif

#endif /* SD_MEMORY */

⌨️ 快捷键说明

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