📄 sdreg.c
字号:
{ //db ("CMD_ERASE failed\n\r"); return -1; } if (rsp[0] & (R1_STAT_ERR | R1_STAT_ERASE_SEQ_ERR | R1_STAT_ERASE_PARAM_ERR | R1_STAT_ERASE_RST)) { //db ("sdhc_erase (CMD_ERASE phase): card status reports error\n\r"); decode_r1 (rsp[0]); return -1; } //db ("sdhc_erase: done\n\r"); return 0;}*/char *tolowercase (char *s){ char *p = s; while (*p) { if (*p >= 'A' && *p <= 'Z') *p += ('a' - 'A'); p++; } return s;}int sdhc_io_init (int *io_func, int *io_mp, unsigned long *ocr){#define R4_IO_RDY BIT(31)#define R4_IO_NUMFUNC (BIT(30)|BIT(29)|BIT(28))#define R4_IO_MEM_PRSNT BIT(27)#define R4_IO_OCR_MASK 0x00FFFFFFUL#define GET_R4_IO_NUMFUNC(a) ((((a) & R4_IO_NUMFUNC) >> 28) & 0x7UL) int i; int error = 0; unsigned long rsp[4]; // send a CMD5 to detect if an SDIO only or SD/SDIO Combo card is present rsp[0] = 0; if (send_cmd_SD (CMD_IO_SEND_OCR, NORMAL, R48, 0, 0, 0, rsp) < 0) { //db ("sdhc_io_init: failed\n\r"); error = 1; goto l_err; } //db ("sdhc_io_init: CMD_IO_SEND_OCR(Init): R4 Response = 0x%08lx\n\r", rsp[0]); *io_func = GET_R4_IO_NUMFUNC(rsp[0]); *io_mp = (rsp[0] & R4_IO_MEM_PRSNT) ? 1 : 0; if (*io_func > 0) { // check if card supports 3.0V, 3.3V and/or 1.8V operation. *ocr = rsp[0] & R4_IO_OCR_MASK; if (*ocr & SDHC_OCR_3VRNG) *ocr = SDHC_OCR_3V; else if (*ocr & SDHC_OCR_33VRNG) *ocr = SDHC_OCR_33V; else { //db ("IO Card voltage requirements cannot be supported.\n\r"); error = 1; goto l_err; } for (i = 0; i < MAX_PWR_UP; i++) { rsp[0] = *ocr & 0x00FFFFFFUL; if (send_cmd_SD (CMD_IO_SEND_OCR, NORMAL, R48, 0, 0, 0, rsp) == 0) { if (rsp[0] & (R4_IO_RDY)) { //db ("sdhc_io_init: CMD_IO_SEND_OCR(WV): R4 Response = 0x%08lx\n\r", rsp[0]); //db ("IO Card has completed initialisation\n\r"); break; } else { delay_ms (1); } } else { //db ("CMD_IO_SEND_OCR Response failed\n\r"); error = 1; break; } } if (i == MAX_PWR_UP) { //db ("SW Timeout waiting for IO Card to Power Up\n\r"); //db ("IO Function will not be initialised further\n\r"); error = 1; } } l_err: if (error) sdhc_reset (SW_RESET_CMD); return error ? -1 : 0;}int sdhc_get_csd (unsigned short rca, CSD_T *csd){ unsigned long rsp[4]; unsigned long tmp[4]; rsp[0] = (rca << 16) | 0xFFFF; if (send_cmd_SD (CMD_SEND_CSD, NORMAL, R136, 0, 1, 1, rsp) < 0) return -1;#if (ENDIAN == BIG_ENDIAN) tmp[3] = rsp[0]; tmp[2] = rsp[1]; tmp[1] = rsp[2]; tmp[0] = rsp[3];#else tmp[3] = SWAPLONG (rsp[0]); tmp[2] = SWAPLONG (rsp[1]); tmp[1] = SWAPLONG (rsp[2]); tmp[0] = SWAPLONG (rsp[3]);#endif *csd = *((CSD_T *) tmp); return 0;}int sdhc_card_init (unsigned short *rca, unsigned long *ocr, CID_T *cid, CSD_T *csd){ int error = 0; unsigned long rsp[4]; unsigned long a_cid[4]; unsigned long a_csd[4]; // 1. Power up the card // 2. Wait for it to stabilise // 3. Send CMD0 without response // 4. Send CMD with response // 5. Send CMD with busy if (card_detect () < 0) return -1; if (bus_pwr (1) < 0) return -1; if (clock_cntl ( CCR_ICLK_EN | CCR_SDCLK_EN, SDCLK_DIV_INIT, 1) < 0) return -1; if (sdhc_io_init (&g_io_num_fn, &g_io_mp, &g_ocr) == 0) { g_cardtype = CARDTYPE_SDIO; myprintf ("SDIO Card detected: IO Functions=%d, Memory Present=%s\n\r", g_io_num_fn, g_io_mp ? "True":"False"); } if ((g_cardtype & CARDTYPE_SDIO) && !g_io_mp) goto l_done; rsp[0] = 0xFFFFFFFF; if (send_cmd_SD ( 0, NORMAL, R0, 0, 0, 0, rsp) < 0) { error = 1; goto l_err; }#if (CARD_TYPE == SD_PANASONIC) // Panasonic accepts this as per spec rsp[0] = 0x0000FFFF; // b31-b16=RCA(0), b15-b0=stuff bits#elif (CARD_TYPE == SD_TWINMOS) // TwinMOS requires 0? rsp[0] = 0x00000000; // b31-b16=RCA(0), b15-b0=stuff bits#endif rsp[1] = 0x00000000; if (send_app_cmd (ACMD_SEND_OCR, NORMAL, R48, 0, 0, rsp) < 0) { //db ("No response to ACMD41! RSP[0]=0x%08lx, RSP[1]=0x%08lx\n\r", rsp[0], rsp[1]); decode_r1 (rsp[0]); decode_r1 (rsp[1]); //db ("Sending CMD0 to Reset Card\n\r"); rsp[0] = 0xFFFFFFFF; if (send_cmd_SD (0, NORMAL, R0, 0, 0, 0, rsp) < 0) { error = 1; goto l_err; } //db ("Trying CMD1 ...\n\r"); rsp[0] = 0; if (send_cmd_SD (CMD_SEND_OCR, NORMAL, R48, 0, 0, 0, rsp) < 0) { error = 1; goto l_err; } else { g_cardtype = CARDTYPE_MMC; g_ocr = rsp[0]; //db ("CMD1 Passed! MMC Card Detected. RSP[0]=0x%08lx\n\r", rsp[0]); } } else { g_cardtype |= CARDTYPE_SDMEM; g_ocr = rsp[1]; //db ("ACMD41 Passed! SD Mem Card Detected. RSP[0]=0x%08lx, RSP[1]=0x%08lx\n\r", rsp[0], rsp[1]); } // check if card supports 3.0V, 3.3V and/or 1.8V operation. if (g_ocr & SDHC_OCR_3VRNG) g_ocr = SDHC_OCR_3V; else if (g_ocr & SDHC_OCR_33VRNG) g_ocr = SDHC_OCR_33V; else { //db ("Memory Card voltage requirements cannot be supported.\n\r"); error = 1; goto l_err; } do { delay_ms (1); if (g_cardtype & CARDTYPE_SDMEM) {#if (CARD_TYPE == SD_PANASONIC) rsp[0] = 0x0000FFFF;#elif (CARD_TYPE == SD_TWINMOS) rsp[0] = 0x00000000;#endif rsp[1] = g_ocr; if (send_app_cmd (ACMD_SEND_OCR, NORMAL, R48, 0, 0, rsp) < 0) { //db ("ACMD(%d)/Response failed\n\r", ACMD_SEND_OCR); error = 1; goto l_err; } } else if (g_cardtype & CARDTYPE_MMC) { rsp[0] = g_ocr; if (send_cmd_SD (CMD_SEND_OCR, NORMAL, R48, 0, 0, 0, rsp) < 0) { //db ("CMD(%d)/Response failed\n\r", CMD_SEND_OCR); error = 1; goto l_err; } } } while (!(((g_cardtype & CARDTYPE_SDMEM) ? rsp[1] : rsp[0]) & 0x80000000)); //db ("Card power is now stable\n\r"); rsp[0] = 0xFFFFFFFF; if (send_cmd_SD (CMD_SEND_ALL_CID, NORMAL, R136, 0, 1, 1, rsp) < 0) { //db ("Command (2) with Response Test failed\n\r"); error = 1; goto l_err; } a_cid[3] = rsp[0]; a_cid[2] = rsp[1]; a_cid[1] = rsp[2]; a_cid[0] = rsp[3]; if (g_cardtype & CARDTYPE_SDMEM) { rsp[0] = 0xFFFFFFFF; if (send_cmd_SD (CMD_SEND_RCA, NORMAL, R48, 0, 1, 1, rsp) < 0) { //db ("sdhc_cmd_test: 1st CMD_SEND_RCA failed\n\r"); error = 1; goto l_err; } *rca = (unsigned short) (rsp[0] >> 16); //db ("card rca (1st request) = %d\n\r", *rca); decode_r6 ((unsigned short)(rsp[0] << 16)); rsp[0] = 0xFFFFFFFF; if (send_cmd_SD (CMD_SEND_RCA, NORMAL, R48, 0, 1, 1, rsp) < 0) { //db ("sdhc_cmd_test: 2nd CMD_SEND_RCA failed\n\r"); error = 1; goto l_err; } *rca = (unsigned short) (rsp[0] >> 16); //db ("card rca (2nd request) = %d\n\r", *rca); decode_r6 ((unsigned short)(rsp[0] << 16)); } else if (g_cardtype & CARDTYPE_MMC) { *rca = MMC_DEF_RCA; rsp[0] = (((unsigned long) *rca) << 16) | 0xffffUL; //db ("MMC card rca (assigned by host) = 0x%04x\n\r", *rca); if (send_cmd_SD (CMD_SEND_RCA, NORMAL, R48, 0, 1, 1, rsp) < 0) { //db ("sdhc_cmd_test: CMD_SEND_RCA failed\n\r"); error = 1; goto l_err; } decode_r1 (rsp[0]); //db ("MMC check status\n\r"); rsp[0] = (((unsigned long) *rca) << 16) | 0xffffUL; if (send_cmd_SD (CMD_SEND_STATUS, NORMAL, R48, 0, 1, 1, rsp) < 0) { //db ("sdhc_cmd_test: CMD_SET_RCA failed\n\r"); error = 1; goto l_err; } else decode_r1 (rsp[0]); } rsp[0] = (*rca << 16) | 0xFFFF; if (send_cmd_SD (CMD_SEND_CID, NORMAL, R136, 0, 1, 1, rsp) < 0) { //db ("Command (CMD_SEND_CID) with Response Test failed\n\r"); error = 1; goto l_err; }#if (ENDIAN == BIG_ENDIAN) a_cid[3] = rsp[0]; a_cid[2] = rsp[1]; a_cid[1] = rsp[2]; a_cid[0] = rsp[3];#else // little endian, we need to swap the data because we want to fit it into the // CSD structure in the correct byte order a_cid[3] = SWAPLONG (rsp[0]); a_cid[2] = SWAPLONG (rsp[1]); a_cid[1] = SWAPLONG (rsp[2]); a_cid[0] = SWAPLONG (rsp[3]);#endif rsp[0] = (*rca << 16) | 0xFFFF; if (send_cmd_SD ( CMD_SEND_CSD, NORMAL, R136, 0, 1, 1, rsp) < 0) { //db ("Command (CMD_SEND_CSD) with Response Test failed\n\r"); error = 1; goto l_err; }#if (ENDIAN == BIG_ENDIAN) a_csd[3] = rsp[0]; a_csd[2] = rsp[1]; a_csd[1] = rsp[2]; a_csd[0] = rsp[3];#else // little endian, we need to swap the data because we want to fit it into the // CSD structure in the correct byte order a_csd[3] = SWAPLONG(rsp[0]); a_csd[2] = SWAPLONG(rsp[1]); a_csd[1] = SWAPLONG(rsp[2]); a_csd[0] = SWAPLONG(rsp[3]);#endif// decode_csd ((CSD_T *) a_csd, g_cardtype);// decode_cid ((CID_T *) a_cid, g_cardtype); *csd = *((CSD_T *) a_csd); *cid = *((CID_T *) a_cid);l_err: sdhc_reset (SW_RESET_CMD);l_done: myprintf("get csd"); if (sdhc_get_csd (g_rca, &g_csd) == 0) { myprintf("decode csd\n\r"); decode_csd (&g_csd, g_cardtype); } else { myprintf("get csd fail\n\r"); } if (error) { myprintf ("Card initialisation unsuccessful\n\r"); } else { myprintf ("Card initialisation passed\n\r"); } return (error ? -1 : 0);} int sdhc_get_cid (unsigned short rca, CID_T *cid){ unsigned long rsp[4]; unsigned long tmp[4]; rsp[0] = (rca << 16) | 0xFFFF; if (send_cmd_SD (CMD_SEND_CID, NORMAL, R136, 0, 1, 1, rsp) < 0) return -1;#if (ENDIAN == BIG_ENDIAN) tmp[3] = rsp[0]; tmp[2] = rsp[1]; tmp[1] = rsp[2]; tmp[0] = rsp[3];#else tmp[3] = SWAPLONG (rsp[0]); tmp[2] = SWAPLONG (rsp[1]); tmp[1] = SWAPLONG (rsp[2]); tmp[0] = SWAPLONG (rsp[3]);#endif *cid = *((CID_T *) tmp); return 0;}int sdhc_card_select (unsigned short rca, unsigned short select){ unsigned long rsp[4]; if ((select && g_cs) || (!select && !g_cs)) {#ifndef __KERNEL__ //db ("sdhc_card_select: card is already %s\n\r", select ? "selected" : "deselected");#endif return 0; } if (select) { rsp[0] = ((unsigned long) rca << 16) | 0x0000ffffUL; if (send_cmd_SD (CMD_SELECT_CARD, NORMAL, R48, 0, 1, 1, rsp) < 0) return -1; } else { // no response expected, since card may think that another card is being auto-selected rsp[0] = 0x0000ffffUL; if (send_cmd_SD (CMD_SELECT_CARD, NORMAL, R0, 0, 0, 0, rsp) < 0) return -1; } if (select && rsp[0] & R1_STAT_ERR) { //db ("sdhc_select: Card %s failed\n\r", select ? "select" : "deselect"); return -1; } g_cs ^= 1; return 0;}int sdhc_get_status (unsigned long *status){ unsigned long rsp[4]; rsp[0] = (((unsigned long) g_rca) << 16) | 0x0000ffffUL; if (send_cmd_SD (CMD_SEND_STATUS, NORMAL, R48, 0, 1, 1, rsp) < 0) return -1; *status = rsp[0]; return 0;}int sdhc_set_blklen (unsigned long blklen){ unsigned long rsp[4]; #if 0 // check blk len if (blklen < (1 << CSD_RD_BLK_LEN(&g_csd))) { if (!CSD_RD_BLK_PARTIAL(&g_csd)) { db ("sdhc_set_blklen: Card does not support partial read\n\r"); return -1; } } else if (blklen > (1 << CSD_RD_BLK_LEN (&g_csd))) { db ("set_blklen: cannot read larger(%ld) than rd_blk_len (%lu)\n\r", blklen, (1 << CSD_RD_BLK_LEN(&g_csd))); return -1; }#endif rsp[0] = blklen; if (send_cmd_SD (CMD_SET_BLKLEN, NORMAL, R48, 0, 1, 1, rsp) < 0) { db ("sdhc_set_blklen: Set Block Length(CMD16) failed\n\r"); return -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -