X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Fcortex-m3%2Fdrv%2Fsd_sam3.c;h=0c1c0a0628f51acd7980c6237e59df6bfd344e33;hb=f1fab319eb3fe91c157b3a9564841aef62a03554;hp=3c228347d8d3e3eb776b85ac2f05bb5df4a1ce52;hpb=8973c9fd922de49b3c0cdcd23610641ee1cbd4f2;p=bertos.git diff --git a/bertos/cpu/cortex-m3/drv/sd_sam3.c b/bertos/cpu/cortex-m3/drv/sd_sam3.c index 3c228347..0c1c0a06 100644 --- a/bertos/cpu/cortex-m3/drv/sd_sam3.c +++ b/bertos/cpu/cortex-m3/drv/sd_sam3.c @@ -26,12 +26,12 @@ * invalidate any other reasons why the executable file might be covered by * the GNU General Public License. * - * Copyright 2007 Develer S.r.l. (http://www.develer.com/) + * Copyright 2011 Develer S.r.l. (http://www.develer.com/) * --> * * \brief Function library for secure digital memory. * - * \author Francesco Sacchi + * \author Daniele Basile */ @@ -55,20 +55,41 @@ #include /* memset */ +#define SD_SEND_ALL_CID BV(0) #define SD_STATUS_APP_CMD BV(5) #define SD_STATUS_READY BV(8) -#define SD_STATUS_CURR_MASK 0x1E00 -#define SD_STATUS_CURR_SHIFT 9 +#define SD_CARD_IS_LOCKED BV(25) -#define SD_READY_FOR_DATA BV(8) -#define SD_CARD_IS_LOCKED BV(25) +#define SD_OCR_CCS BV(30) /**< SD Card Capacity Status (CCS) */ +#define SD_OCR_BUSY BV(31) /**< SD/MMC Card power up status bit (busy) */ -#define SD_SEND_CID_RCA 0 -#define SD_SEND_ALL_CID BV(0) +#define SD_OCR_VDD_27_28 BV(15) +#define SD_OCR_VDD_28_29 BV(16) +#define SD_OCR_VDD_29_30 BV(17) +#define SD_OCR_VDD_30_31 BV(18) +#define SD_OCR_VDD_31_32 BV(19) +#define SD_OCR_VDD_32_33 BV(20) +#define SD_HOST_VOLTAGE_RANGE (SD_OCR_VDD_27_28 | \ + SD_OCR_VDD_28_29 | \ + SD_OCR_VDD_29_30 | \ + SD_OCR_VDD_30_31 | \ + SD_OCR_VDD_31_32 | \ + SD_OCR_VDD_32_33) + + +#define CMD8_V_RANGE_CHECK_PAT 0xAA +#define CMD8_V_RANGE_27V_36V (0x100 | CMD8_V_RANGE_CHECK_PAT) +#define CMD8_V_RANGE_LOW (0x1000 | CMD8_V_RANGE_CHECK_PAT) +#define CMD8_V_ECHO_REPLY 0xFF +#define CMD8_SUPP_V_RANGE_REPLY 0xFF00 + +#define SD_STATUS_ERROR BV(19) + +#define SD_GET_ERRORS(status) ((status) & 0xFFF80000) #define SD_ADDR_TO_RCA(addr) (uint32_t)(((addr) << 16) & 0xFFFF0000) -#define SD_GET_STATE(status) (uint8_t)(((status) & SD_STATUS_CURR_MASK) >> SD_STATUS_CURR_SHIFT) +#define SD_GET_STATE(status) (uint8_t)(((status) & 0x1E00) >> 9) static const uint32_t tran_exp[] = { @@ -83,22 +104,22 @@ static const uint8_t tran_mant[] = }; -void sd_dumpCsd(SDcsd *csd); -void sd_dumpCid(SDcid *cid); -void sd_dumpSsr(SDssr *ssr); +void sd_dumpCsd(SdCSD *csd); +void sd_dumpCid(SdCID *cid); +void sd_dumpSsr(SdSSR *ssr); void sd_sendInit(void); void sd_goIdle(void); int sd_sendIfCond(Sd *sd); int sd_sendAppOpCond(Sd *sd); -int sd_getCid(Sd *sd, SDcid *cid, uint32_t addr, uint8_t flag); -int sd_getCsd(Sd *sd, SDcsd *csd); +int sd_getCid(Sd *sd, SdCID *cid, uint32_t addr, uint8_t flag); +int sd_getCsd(Sd *sd, SdCSD *csd); int sd_getSrc(Sd *sd); int sd_appStatus(Sd *sd); int sd_getRelativeAddr(Sd *sd); -int sd_getStatus(Sd *sd, SDssr *ssr, uint32_t *buf, size_t words); +int sd_getStatus(Sd *sd, SdSSR *ssr, uint32_t *buf, size_t words); int sd_selectCard(Sd *sd); int sd_deSelectCard(Sd *sd); @@ -139,7 +160,7 @@ static void dump(const char *label, uint32_t *r, size_t len) } ) -void sd_dumpCsd(SDcsd *csd) +void sd_dumpCsd(SdCSD *csd) { ASSERT(csd); @@ -157,7 +178,7 @@ void sd_dumpCsd(SDcsd *csd) } -void sd_dumpCid(SDcid *cid) +void sd_dumpCid(SdCID *cid) { ASSERT(cid); @@ -170,7 +191,7 @@ void sd_dumpCid(SDcid *cid) (BCD_TO_INT_32BIT(cid->year_off) % 12)); } -void sd_dumpSsr(SDssr *ssr) +void sd_dumpSsr(SdSSR *ssr) { ASSERT(ssr); @@ -182,7 +203,7 @@ void sd_dumpSsr(SDssr *ssr) } -static int sd_decodeCsd(SDcsd *csd, uint32_t *resp, size_t len) +static int sd_decodeCsd(SdCSD *csd, uint32_t *resp, size_t len) { ASSERT(csd); ASSERT(resp); @@ -290,7 +311,6 @@ int sd_sendIfCond(Sd *sd) return 0; } LOG_ERR("IF_COND: %lx\n", (sd->status)); - return -1; } @@ -318,8 +338,6 @@ int sd_sendAppOpCond(Sd *sd) LOG_INFO("SD power up! Hight Capability [%d]\n", (bool)((sd->status) & SD_OCR_CCS)); return 0; } - - LOG_ERR("sd not ready.\n"); } } @@ -327,11 +345,11 @@ int sd_sendAppOpCond(Sd *sd) } -int sd_getCid(Sd *sd, SDcid *cid, uint32_t addr, uint8_t flag) +int sd_getCid(Sd *sd, SdCID *cid, uint32_t addr, uint8_t flag) { ASSERT(sd); ASSERT(cid); - memset(cid, 0, sizeof(SDcid)); + memset(cid, 0, sizeof(SdCID)); uint8_t idx = 9; // CMD9 get cid from gived sd address (RCA) if (flag & SD_SEND_ALL_CID) @@ -365,11 +383,11 @@ int sd_getCid(Sd *sd, SDcid *cid, uint32_t addr, uint8_t flag) return 0; } -int sd_getCsd(Sd *sd, SDcsd *csd) +int sd_getCsd(Sd *sd, SdCSD *csd) { ASSERT(sd); ASSERT(csd); - memset(csd, 0, sizeof(SDcsd)); + memset(csd, 0, sizeof(SdCSD)); LOG_INFO("Send to RCA: %lx\n", SD_ADDR_TO_RCA(sd->addr)); if (hsmci_sendCmd(9, SD_ADDR_TO_RCA(sd->addr), HSMCI_CMDR_RSPTYP_136_BIT)) @@ -412,6 +430,7 @@ int sd_appStatus(Sd *sd) if (hsmci_sendCmd(13, SD_ADDR_TO_RCA(sd->addr), HSMCI_CMDR_RSPTYP_48_BIT)) { LOG_ERR("STATUS: %lx\n", HSMCI_SR); + sd->status |= SD_STATUS_ERROR; return -1; } @@ -434,6 +453,7 @@ INLINE int sd_cardSelection(Sd *sd, uint32_t rca) if (hsmci_sendCmd(7, rca, HSMCI_CMDR_RSPTYP_R1B)) { LOG_ERR("SELECT_SD: %lx\n", HSMCI_SR); + sd->status |= SD_STATUS_ERROR; return -1; } @@ -504,7 +524,6 @@ int sd_setBusWidth(Sd *sd, size_t len) hsmci_readResp(&(sd->status), 1); if ((sd->status) & (SD_STATUS_APP_CMD | SD_STATUS_READY)) { - hsmci_setBusWidth(len); uint8_t arg = 0; if (len == 4) @@ -522,7 +541,10 @@ int sd_setBusWidth(Sd *sd, size_t len) LOG_INFO("State[%d]\n", SD_GET_STATE(sd->status)); if (sd->status & SD_STATUS_READY) + { + hsmci_setBusWidth(len); return 0; + } } LOG_ERR("SET_BUS_WIDTH REP %lx\n", (sd->status)); @@ -553,13 +575,13 @@ int sd_set_BlockLen(Sd *sd, size_t len) return -1; } -int sd_getStatus(Sd *sd, SDssr *ssr, uint32_t *buf, size_t words) +int sd_getStatus(Sd *sd, SdSSR *ssr, uint32_t *buf, size_t words) { ASSERT(sd); ASSERT(ssr); // Status reply with 512bit data, so the block size in byte is 64 - hsmci_prgRxDMA(buf, words, 64); + hsmci_read(buf, words, 64); if (hsmci_sendCmd(55, SD_ADDR_TO_RCA(sd->addr), HSMCI_CMDR_RSPTYP_48_BIT)) { @@ -567,8 +589,8 @@ int sd_getStatus(Sd *sd, SDssr *ssr, uint32_t *buf, size_t words) return -1; } - uint32_t status = HSMCI_RSPR; - if (status & (SD_STATUS_APP_CMD | SD_STATUS_READY)) + hsmci_readResp(&(sd->status), 1); + if (sd->status & (SD_STATUS_APP_CMD | SD_STATUS_READY)) { if (hsmci_sendCmd(13, 0, HSMCI_CMDR_RSPTYP_48_BIT | BV(HSMCI_CMDR_TRDIR) | HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_SINGLE)) @@ -586,7 +608,7 @@ int sd_getStatus(Sd *sd, SDssr *ssr, uint32_t *buf, size_t words) hsmci_waitTransfer(); LOG_INFOB(dump("STATUS", buf, words);); - memset(ssr, 0, sizeof(SDssr)); + memset(ssr, 0, sizeof(SdSSR)); ssr->bus_width = UNSTUFF_BITS(buf, 510, 2); ssr->card_type = UNSTUFF_BITS(buf, 480, 16); ssr->au_size = UNSTUFF_BITS(buf, 432, 8); @@ -604,26 +626,25 @@ int sd_getStatus(Sd *sd, SDssr *ssr, uint32_t *buf, size_t words) void sd_setHightSpeed(Sd *sd) { (void)sd; - hsmci_setSpeed(2100000, true); + hsmci_setSpeed(HSMCI_HIGH_SPEED, HSMCI_HS_MODE); } static size_t sd_SdReadDirect(struct KBlock *b, block_idx_t idx, void *buf, size_t offset, size_t size) { ASSERT(buf); + ASSERT(!((uint32_t)buf & 0x3)); + Sd *sd = SD_CAST(b); LOG_INFO("reading from block %ld, offset %d, size %d\n", idx, offset, size); - if (sd_selectCard(sd) < 0) - return -1; - - hsmci_prgRxDMA(buf, size / 4, sd->b.blk_size); + hsmci_waitTransfer(); + hsmci_read(buf, size / 4, sd->b.blk_size); if (hsmci_sendCmd(17, idx * sd->b.blk_size + offset, HSMCI_CMDR_RSPTYP_48_BIT | BV(HSMCI_CMDR_TRDIR) | HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_SINGLE)) { LOG_ERR("SIGLE_BLK_READ: %lx\n", HSMCI_SR); - sd_deSelectCard(sd); return -1; } @@ -635,31 +656,27 @@ static size_t sd_SdReadDirect(struct KBlock *b, block_idx_t idx, void *buf, size if (sd->status & SD_STATUS_READY) { hsmci_waitTransfer(); - sd_deSelectCard(sd); return size; } - - sd_deSelectCard(sd); return -1; } static size_t sd_SdWriteDirect(KBlock *b, block_idx_t idx, const void *buf, size_t offset, size_t size) { ASSERT(buf); + ASSERT(!((uint32_t)buf & 0x3)); + Sd *sd = SD_CAST(b); const uint32_t *_buf = (const uint32_t *)buf; - LOG_INFO("reading from block %ld, offset %d, size %d\n", idx, offset, size); + LOG_INFO("writing block %ld, offset %d, size %d\n", idx, offset, size); - if (sd_selectCard(sd) < 0) - return 0; - - hsmci_prgTxDMA(_buf, size / 4, sd->b.blk_size); + hsmci_waitTransfer(); + hsmci_write(_buf, size / 4, sd->b.blk_size); if (hsmci_sendCmd(24, idx * sd->b.blk_size + offset, HSMCI_CMDR_RSPTYP_48_BIT | HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_SINGLE)) { LOG_ERR("SIGLE_BLK_WRITE: %lx\n", HSMCI_SR); - sd_deSelectCard(sd); return -1; } @@ -670,12 +687,9 @@ static size_t sd_SdWriteDirect(KBlock *b, block_idx_t idx, const void *buf, size if (sd->status & SD_STATUS_READY) { - hsmci_waitTransfer(); - sd_deSelectCard(sd); return size; } - sd_deSelectCard(sd); return -1; } @@ -683,7 +697,7 @@ static size_t sd_SdWriteDirect(KBlock *b, block_idx_t idx, const void *buf, size static int sd_SdError(KBlock *b) { Sd *sd = SD_CAST(b); - return 0;//sd->status; + return SD_GET_ERRORS(sd->status); } static void sd_SdClearerr(KBlock *b) @@ -694,6 +708,7 @@ static void sd_SdClearerr(KBlock *b) static bool sd_blockInit(Sd *sd, KFile *ch) { + (void)ch; ASSERT(sd); memset(sd, 0, sizeof(*sd)); DB(sd->b.priv.type = KBT_SD); @@ -722,7 +737,7 @@ static bool sd_blockInit(Sd *sd, KFile *ch) if (sd_power_on) { - SDcid cid; + SdCID cid; if(sd_getCid(sd, &cid, 0, SD_SEND_ALL_CID) < 0) return false; else @@ -737,7 +752,7 @@ static bool sd_blockInit(Sd *sd, KFile *ch) LOG_INFO("RCA: %0lx\n", sd->addr); } - SDcsd csd; + SdCSD csd; if (sd_getCsd(sd, &csd) < 0) return false; else @@ -759,13 +774,12 @@ static bool sd_blockInit(Sd *sd, KFile *ch) return false; } - if (sd->status & SD_READY_FOR_DATA) + if (sd->status & SD_STATUS_READY) { sd_selectCard(sd); sd_set_BlockLen(sd, SD_DEFAULT_BLOCKLEN); sd_setBus4bit(sd); sd_setHightSpeed(sd); - sd_deSelectCard(sd); #if CONFIG_SD_AUTOASSIGN_FAT disk_assignDrive(&sd->b, 0); @@ -774,7 +788,7 @@ static bool sd_blockInit(Sd *sd, KFile *ch) return true; } } - + LOG_ERR("SD not ready.\n"); return false; }