📄 sdd_mem.c
字号:
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 + -