📄 sdreg.c
字号:
unsigned short rsp, int data_prsnt, int crc_check, int idx_check, unsigned long arg[4]){// myprintf("%s(sdhc=0x%x,idx%d,type%d,resp%d,data_prsnt%d,crc_check%d,idx_check%d,arg[4])\n\r",__FUNCTION__,sdhc,idx, type, rsp, data_prsnt, crc_check, idx_check);// myprintf("arg[0-3]=0x%x, 0x%x, 0x%x, 0x%x\n\r",arg[0],arg[1],arg[2],arg[3]); int i; int psr_inhibit_dat = 0; int error = 0; unsigned short cmd = 0; unsigned short u16NrmIntrSignalEn = 0; unsigned short u16ErrIntrSignalEn = 0; if (type == SUSPEND || type == RESUME) { //db ("send_cmd_SD: Suspend/Resume are not supported\n\r"); return -1; } if (SSD_REGRL(REG_u32PrsntState) & PSR_INHIBIT_CMD) { //db ("send_cmd_SD (CMD%u): Command Inhibit CMD is active\n\r", idx); return -1; } if (rsp == R48b || data_prsnt) { SSD_REGWB(REG_u8ToutCntl, 0x0e); // TMCLK * 2^^27 } if (!g_irq) { // this has nothing to do with interrupts enabling control u16NrmIntrSignalEn = SSD_REGRW(REG_u16NrmIntrSignalEn); u16ErrIntrSignalEn = SSD_REGRW(REG_u16ErrIntrSignalEn); SSD_REGWW(REG_u16NrmIntrSignalEn, 0); // turn off any irqs, send command is done synchronously SSD_REGWW(REG_u16ErrIntrSignalEn,0); // turn off any irqs } // clear previous status SSD_REGWW(REG_u16NrmIntrStatus , (INTR_CMD_COMPLETE | (data_prsnt ? INTR_DAT_COMPLETE : 0))); SSD_REGWW(REG_u16NrmIntrStatusEn , SSD_REGRW(REG_u16NrmIntrStatusEn)| (INTR_CMD_COMPLETE | (data_prsnt ? INTR_DAT_COMPLETE : 0))); SSD_REGWW(REG_u16ErrIntrStatus, SSD_REGRW(REG_u16ErrIntrStatus)); // clear previous status SSD_REGWW(REG_u16ErrIntrStatusEn , SSD_REGRW(REG_u16ErrIntrStatusEn)| EINTR_CMD_TOUT | EINTR_CMD_END | (crc_check ? EINTR_CMD_CRC : 0) | (idx_check ? EINTR_CMD_IDX : 0) | (data_prsnt ? (EINTR_DAT_TOUT | EINTR_DAT_CRC | EINTR_DAT_END | EINTR_VS_DAT_CONFLICT | EINTR_VS_BLKSZ_ERR) : 0) | ((rsp == R48b) ? EINTR_DAT_TOUT : 0) | EINTR_VS_RSP_DIR ); SSD_REGWL(REG_u32Arg, SWAP32(arg[0])); cmd |= CMD_IDX (idx) | CMD_TYPE (type) | CMD_RSP (rsp) | (crc_check ? CMDR_CRC_CHECK_EN : 0) | (idx_check ? CMDR_IDX_CHECK_EN : 0) | (data_prsnt ? CMDR_DATA_PRESENT : 0);// //db ("send_cmd_SD (CMD%u): Present State Register (0x%08lx)\n\r", idx, SWAP32(sdhc->REG_u32PrsntState)); SSD_REGWW(REG_u16Cmd , cmd); for (i = 0; i < MAX_WAIT; i++) { if ((SSD_REGRL(REG_u32PrsntState) & PSR_INHIBIT_CMD) || (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_CMD_COMPLETE)) break; } if (i == MAX_WAIT) { //db ("send_cmd_SD (CMD%u): Command Inhibit (CMD) not set NISR=0x%04x, PSR=0x%08lx, test failed\n\r", idx, // SWAP16 (SSD_REGRW(REG_u16NrmIntrStatus)), SWAP32(SSD_REGRL(REG_u32PrsntState))); error = -1; goto l_err; }#if 0 //db ("send_cmd_SD (CMD%u): Command Inhibit (CMD) set\n\r", idx); //db ("send_cmd_SD (CMD%u): Waiting for Command Complete Status\n\r", idx);#endif for (i = 0; i < MAX_WAIT; i++) { if (SSD_REGRW(REG_u32PrsntState) & PSR_INHIBIT_DAT) psr_inhibit_dat = 1; if (SSD_REGRW(REG_u16NrmIntrStatus) & (INTR_CMD_COMPLETE | INTR_ERR)) break;// delay_us (1); } arg[0] = SWAP32 (SSD_REGRL(REG_a32Rsp+0)); arg[1] = SWAP32 (SSD_REGRL(REG_a32Rsp+4)); arg[2] = SWAP32 (SSD_REGRL(REG_a32Rsp+8)); arg[3] = SWAP32 (SSD_REGRL(REG_a32Rsp+12)); if (g_verbose) { //db ("send_cmd_SD (CMD%u): NISR (0x%04x), NISREN (0x%04x)\n\r", idx, // SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16NrmIntrStatusEn)) ); //db ("send_cmd_SD (CMD%u): EISR (0x%04x), EISREN (0x%04x)\n\r", idx, // SWAP16(SSD_REGRW(REG_u16ErrIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatusEn))); //db ("send_cmd_SD (CMD%u): (After Command Complete) Present State Register (0x%08lx)\n\r", // idx, SWAP32(SSD_REGRL(REG_u32PrsntState))); //db ("send_cmd_SD (CMD%u): RSP[127..0] = 0x%08lx %08lx %08lx %08lx\n\r", idx, // arg[3], arg[2], arg[1], arg[0]); } if (i == MAX_WAIT) { //db ("send_cmd_SD (CMD%u): Timeout waiting for Command Complete\n\r", idx); error = 1; goto l_err; } if (rsp == R48b) { if (SSD_REGRL(REG_u32PrsntState) & PSR_INHIBIT_DAT) { //db ("send_cmd_SD (CMD%u): Busy detection in progress\n\r", idx); } else { //db ("send_cmd_SD (CMD%u): NO busy detection in progress\n\r", idx); } for (i = 0; i < MAX_WAIT; i++) { if (SSD_REGRW(REG_u16NrmIntrStatus) & (INTR_DAT_COMPLETE | INTR_ERR)) break; delay_us (1); } if (i == MAX_WAIT) { //db ("send_cmd_SD (CMD%u): PSR = 0x%08lx\n\r", idx, SWAP32(SSD_REGRL(REG_u32PrsntState))); //db ("send_cmd_SD (CMD%u): Timeout waiting for Transfer Complete\n\r", idx); error = 1; goto l_err; } } if (rsp == R48b && (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_DAT_COMPLETE) && (SSD_REGRW(REG_u16ErrIntrStatus) & EINTR_DAT_TOUT)) { //db ("send_cmd_SD (CMD%u): Transfer Complete occured together with Busy end timeout\n\r", idx); //SSD_REGWW(REG_u16ErrIntrStatus , EINTR_DAT_TOUT); } if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_ERR) { //db ("send_cmd_SD (CMD%u): Command resulted in Error, NISR (0x%04x), EISR(0x%04x)\n\r", // idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); SSD_REGWW(REG_u16ErrIntrStatus , SSD_REGRW(REG_u16ErrIntrStatus)); if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_ERR) { //db ("send_cmd_SD (CMD%u): NISR.INTR_ERR(b15) could not be cleared. " // "NISR (0x%04x), EISR (0x%04x)\n\r", // idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); } SSD_REGWW(REG_u16NrmIntrStatus , INTR_CMD_COMPLETE); if (SSD_REGRW(REG_u16NrmIntrStatus)) { //db ("send_cmd_SD (CMD%u): NISR (0x%04x) -> bits are still set in NISR\n\r", // idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus))); SSD_REGWW(REG_u16NrmIntrStatus , SSD_REGRW(REG_u16NrmIntrStatus)); } error = 1; goto l_err; } if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_CMD_COMPLETE) { SSD_REGWW(REG_u16NrmIntrStatus , INTR_CMD_COMPLETE); if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_CMD_COMPLETE) { //db ("send_cmd_SD (CMD%u): NISR.INTR_CMD_COMPLETE(b0) could not be cleared. " // "NISR (0x%04x), EISR (0x%04x). Trying again!\n\r", // idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); SSD_REGWW(REG_u16NrmIntrStatus , INTR_CMD_COMPLETE); if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_CMD_COMPLETE) error = 1; else { //db ("send_cmd_SD: 2nd time success\n\r"); } } #if 0 // commented off - by Sree, since PSR_INHIBIT_DAT has already been checked for previously and // can toggle back to 0 once data transmission is complete. if (data_prsnt && !(SSD_REGWL(REG_u32PrsntState & PSR_INHIBIT_DAT)) { //db ("send_cmd_SD (CMD%u): Data Present but PSR_INHIBIT_DAT is NOT set\n\r", idx); error = 1; }#endif } if (rsp == R48b) { for (i = 0; i < MAX_WAIT; i++) { if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_DAT_COMPLETE) { SSD_REGWW(REG_u16NrmIntrStatus , INTR_DAT_COMPLETE); if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_DAT_COMPLETE) { //db ("send_cmd_SD (CMD%u): NISR.INTR_DAT_COMPLETE(b0) could not be cleared. " // "NISR (0x%04x), EISR (0x%04x)\n\r", // idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); error = 1; } break; } delay_us (1); } if (i == MAX_WAIT) { //db ("send_cmd_SD (CMD%u): SW TOUT: R48b but no INTR_DAT_COMPLETE, NISR(0x%04x)\n\r", // idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus))); error = 1; } if (error) goto l_err; }l_err: SSD_REGWW(REG_u16NrmIntrStatusEn, SSD_REGRW(REG_u16NrmIntrStatusEn)& ~INTR_CMD_COMPLETE); SSD_REGWW(REG_u16ErrIntrStatusEn, SSD_REGRW(REG_u16ErrIntrStatusEn) & ~(EINTR_CMD_TOUT | EINTR_CMD_CRC | EINTR_CMD_IDX | EINTR_CMD_END | EINTR_VS_RSP_DIR)); if (error || g_verbose) //db ("send_cmd_SD (CMD%u): Result = %s\n\r", idx, (error ? "Failed": "Passed")); // should be protected from interrupts if (!g_irq) { SSD_REGWW(REG_u16NrmIntrSignalEn , u16NrmIntrSignalEn); SSD_REGWW(REG_u16ErrIntrSignalEn , u16ErrIntrSignalEn); } return (error ? -1 : 0);}int send_app_cmd ( unsigned short idx, unsigned short type, unsigned short rsp, int crc_check, int idx_check, unsigned long arg[4]){ int i; int error = 0; unsigned short cmd; unsigned long arg0 = 0; unsigned long arg1 = arg[1]; // save it here unsigned short u16NrmIntrSignalEn = 0; unsigned short u16ErrIntrSignalEn = 0; if (type == SUSPEND || type == RESUME) { //db ("send_app_cmd(ACMD%u): Suspend/Resume are not supported\n\r", idx); return -1; } if (SSD_REGRL(REG_u32PrsntState) & PSR_INHIBIT_CMD) { //db ("send_app_cmd(ACMD%u): Command Inhibit CMD is active\n\r", idx); return -1; } if (!g_irq) { u16NrmIntrSignalEn = SSD_REGRW(REG_u16NrmIntrSignalEn); u16ErrIntrSignalEn = SSD_REGRW(REG_u16ErrIntrSignalEn); SSD_REGWW(REG_u16NrmIntrSignalEn, 0); // turn off any irqs SSD_REGWW(REG_u16ErrIntrSignalEn, 0); // turn off any irqs } SSD_REGWW(REG_u16NrmIntrStatus , SSD_REGRW(REG_u16NrmIntrStatus)); // clear previous status SSD_REGWW(REG_u16NrmIntrStatusEn, SSD_REGRW(REG_u16NrmIntrStatusEn) | INTR_CMD_COMPLETE); SSD_REGWW(REG_u16ErrIntrStatus,SSD_REGRW(REG_u16ErrIntrStatus)|SSD_REGRW(REG_u16ErrIntrStatus)); // clear previous status SSD_REGWW(REG_u16ErrIntrStatusEn,SSD_REGRW(REG_u16ErrIntrStatusEn) | ( EINTR_CMD_TOUT | EINTR_CMD_END | EINTR_VS_RSP_DIR | (crc_check ? EINTR_CMD_CRC : 0) | (idx_check ? EINTR_CMD_IDX : 0))); SSD_REGWL(REG_u32Arg , SWAP32(arg[0])); cmd = CMD_IDX (0x37) | CMD_TYPE (NORMAL) | CMD_RSP (R48); cmd |= crc_check ? CMDR_CRC_CHECK_EN : 0; cmd |= idx_check ? CMDR_IDX_CHECK_EN : 0; //db ("send_app_cmd (ACMD%u): Present State Register (0x%08lx)\n\r", idx, SWAP32(SSD_REGRL(REG_u32PrsntState))); SSD_REGWW(REG_u16Cmd , cmd); for (i = 0; i < MAX_WAIT; i++) if (SSD_REGRL(REG_u32PrsntState) & PSR_INHIBIT_CMD) { break; }#if 0 if (i == MAX_WAIT) { //db ("send_app_cmd (ACMD%u): Command Inhibit (CMD) not set, test failed\n\r", idx); return -1; }#endif // wait for command complete or error for (i = 0; i < MAX_WAIT; i++) { if (SSD_REGRW(REG_u16NrmIntrStatus) & (INTR_CMD_COMPLETE | INTR_ERR)) break;// delay_us (1); } arg0 = SWAP32 (SSD_REGRL(REG_a32Rsp)); // arg[0] - contains response to CMD55 arg[0] = arg0; arg[1] = SWAP32 (SSD_REGRL(REG_a32Rsp+4)); arg[2] = SWAP32 (SSD_REGRL(REG_a32Rsp+8)); arg[3] = SWAP32 (SSD_REGRL(REG_a32Rsp+12));#if 1 //db ("send_app_cmd (CMD55): NISR (0x%04x), NISREN (0x%04x)\n\r", // SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16NrmIntrStatusEn)) ); //db ("send_app_cmd (CMD55): EISR (0x%04x), EISREN (0x%04x)\n\r", // SWAP16(SSD_REGRW(REG_u16ErrIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatusEn)) ); //db ("send_app_cmd (CMD55): (After Command Complete) Present State Register (0x%08lx)\n\r", // SWAP32(SSD_REGRL(REG_u32PrsntState))); //db ("send_app_cmd (CMD55): RSP[127..0] = 0x%08lx %08lx %08lx %08lx\n\r", // arg[3], arg[2], arg[1], arg[0]);#endif if (i == MAX_WAIT) { //db ("send_app_cmd (CMD55): Timeout waiting for Command Complete\n\r"); error = 1; goto l_err; } if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_ERR) { //db ("send_app_cmd (CMD55): Command resulted in Error, ErrIntrStatus (0x%04x)\n\r", // SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); SSD_REGWW(REG_u16ErrIntrStatus , SSD_REGRW(REG_u16ErrIntrStatus)); if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_ERR) { //db ("send_app_cmd (CMD55): NISR.INTR_ERR(b15) could not be cleared. " // "NISR (0x%04x), EISR (0x%04x)\n\r", // SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); } SSD_REGWW(REG_u16NrmIntrStatus , INTR_CMD_COMPLETE); if (SSD_REGRW(REG_u16NrmIntrStatus)) { //db ("send_app_cmd (CMD55): NISR (0x%04x) -> bits are still set in NISR\n\r", // SWAP16(SSD_REGRW(REG_u16NrmIntrStatus))); SSD_REGWW(REG_u16NrmIntrStatus , SSD_REGRW(REG_u16NrmIntrStatus)); } sdhc_reset (SW_RESET_CMD); error = 1; goto l_err; } if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_CMD_COMPLETE) { SSD_REGWW(REG_u16NrmIntrStatus , INTR_CMD_COMPLETE);#if 0 if (SSD_REGWW(REG_u16NrmIntrStatus & INTR_CMD_COMPLETE) { //db ("send_app_cmd (ACMD%u): NISR.INTR_CMD_COMPLETE(b0) could not be cleared. " "NISR (0x%04x), EISR (0x%04x)\n\r", idx, SWAP16(SSD_REGWW(REG_u16NrmIntrStatus), SWAP16(SSD_REGWW(REG_u16ErrIntrStatus)); error = 1; }#endif } SSD_REGWL(REG_u32Arg , SWAP32(arg1)); cmd = CMD_IDX (idx) | CMD_TYPE (NORMAL) | CMD_RSP (R48); cmd |= crc_check ? CMDR_CRC_CHECK_EN : 0; cmd |= idx_check ? CMDR_IDX_CHECK_EN : 0; SSD_REGWW(REG_u16Cmd , cmd); for (i = 0; i < MAX_WAIT; i++) if (SSD_REGRL(REG_u32PrsntState) & PSR_INHIBIT_CMD) break; if (i == MAX_WAIT) { //db ("App send_app_cmd (ACMD%u): Command Inhibit (CMD) not set, test failed\n\r", idx); error = 1; goto l_err; } // wait for command complete or error for (i = 0; i < MAX_WAIT; i++) { if (SSD_REGRW(REG_u16NrmIntrStatus) & (INTR_CMD_COMPLETE | INTR_ERR)) break;// delay_us (1); } if (i == MAX_WAIT) { //db ("send_app_cmd (ACMD%u): Timeout waiting for Command Complete\n\r", idx); error = 1; goto l_err; } arg1 = SWAP32 (SSD_REGRL(REG_a32Rsp+0)); // arg[0] - contains response to ACMD arg[0] = arg1; arg[1] = SWAP32 (SSD_REGRL(REG_a32Rsp+4) ); arg[2] = SWAP32 (SSD_REGRL(REG_a32Rsp+8) ); arg[3] = SWAP32 (SSD_REGRL(REG_a32Rsp+12) );#if 0 //db ("send_app_cmd (ACMD%u): NISR (0x%04x), NISREN (0x%04x)\n\r", idx, SWAP16(SSD_REGWW(REG_u16NrmIntrStatus), SWAP16(SSD_REGWW(REG_u16NrmIntrStatusEn)); //db ("send_app_cmd (ACMD%u): EISR (0x%04x), EISREN (0x%04x)\n\r", idx, SWAP16(SSD_REGWW(REG_u16ErrIntrStatus), SWAP16(SSD_REGWW(REG_u16ErrIntrStatusEn)); //db ("send_app_cmd (ACMD%u): (After Command Complete) Present State Register (0x%08lx)\n\r", idx, SWAP32(SSD_REGWL(REG_u32PrsntState)); //db ("send_app_cmd (ACMD%u): RSP[127..0] = 0x%08lx %08lx %08lx %08lx\n\r", idx, arg[3], arg[2], arg[1], arg[0]);#endif if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_ERR) { //db ("send_app_cmd (ACMD%u): Command resulted in Error, ErrIntrStatus (0x%04x)\n\r", // idx, SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); SSD_REGWW(REG_u16ErrIntrStatus, SSD_REGRW(REG_u16ErrIntrStatus)); if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_ERR) { //db ("send_app_cmd (ACMD%u): NISR.INTR_ERR(b15) could not be cleared. " // "NISR (0x%04x), EISR (0x%04x)\n\r", // idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); } if (SSD_REGRW(REG_u16NrmIntrStatus)) { //db ("send_app_cmd (ACMD%u): NISR (0x%04x) -> bits are still set in NISR\n\r", // idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus))); SSD_REGWW(REG_u16NrmIntrStatus , SSD_REGRW(REG_u16NrmIntrStatus)); } sdhc_reset (SW_RESET_CMD); error = 1; goto l_err; } if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_CMD_COMPLETE) SSD_REGWW(REG_u16NrmIntrStatus , INTR_CMD_COMPLETE);l_err: SSD_REGWW(REG_u16NrmIntrStatusEn, SSD_REGRW(REG_u16NrmIntrStatusEn) & ~INTR_CMD_COMPLETE); SSD_REGWW(REG_u16ErrIntrStatusEn, SSD_REGRW(REG_u16ErrIntrStatusEn) & ~(EINTR_CMD_TOUT | EINTR_CMD_CRC | EINTR_CMD_IDX | EINTR_CMD_END)); arg[0] = arg0; arg[1] = arg1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -