📄 main.c
字号:
* * Important note: * - Must be augmented with 7 zeros! * */ new_crc = old_crc; for (x = 7; x >= 0; x--) { new_crc <<= 1; new_crc |= GETBIT(data,x); if (GETBIT(new_crc, 7) == 1) { new_crc ^= 0x89; /* XOR with poly -- this clears the top bit, too!*/ } } return new_crc;}/* Provides the zero-padding final step to CRC-7 * * Input arguments: * * old_crc - value from last call to crc_7() * * Returns: * * Finalized CRC-7 checksum * */uint8_t crc_7augment(uint8_t old_crc){ unsigned char new_crc; int x; new_crc = old_crc; for (x = 0; x < 7; x++) { new_crc <<= 1; if (GETBIT(new_crc, 7) == 1) { new_crc ^= 0x89; /* XOR with poly -- this clears the top bit, too!*/ } } return new_crc;}/* CRC-16 (CCITT) as described in the Secure Digital spec * * Input arguments: * * old_crc - 0x0000 to start new CRC, or value from previous call to continue * data - data byte to add to CRC computation * * Returns: * * CRC-16 checksum which MUST be augmented by crc_16augment() before use * */uint16_t crc_16(uint16_t old_crc, uint8_t data){ uint16_t new_crc; uint8_t flipit; int x; /* CRC-16's polynomial is x^16 + x^12 + x^5 + 1 */ new_crc = old_crc; for (x = 7; x >= 0; x--) { flipit = GETBIT(new_crc, 15); /* Carry-out from shift */ new_crc <<= 1; new_crc |= GETBIT(data,x); if (flipit == 1) { /* Unlike CRC-7, we leave out the x^16 term because */ /* the carry bit has left our register */ new_crc ^= 0x1021; } } return new_crc;}/* Provides the zero-padding final step to CRC-16 * * Input arguments: * * old_crc - value from last call to crc_16() * * Returns: * * Finalized CRC-16 checksum * */uint16_t crc_16augment(uint16_t old_crc){ uint16_t new_crc; uint8_t flipit; int x; new_crc = old_crc; for (x = 0; x < 16; x++) { flipit = GETBIT(new_crc, 15); new_crc <<= 1; if (flipit == 1) { new_crc ^= 0x1021; } } return new_crc;}/* Verifies CRC-7 or CRC-16 against expected value * * Input arguments: * * type - SD_CRC7 or SD_CRC16 * b - pointer to character data * len - length of data to check (must not be 0, * which returns CRC_FAIL) * expect - expected CRC-7 (only LSB is significant) or CRC-16 value. * * Returns: * * CRC_OK (0) - Data passes integrity check by selected CRC algorithm * CRC_FAIL (-1) - Data fails integrity check or wrong */int verifyCRC(int type, uint8_t *b, uint32_t len, uint16_t expect){ uint16_t crc = 0x0000; int i; /* Sanity check arguments */ if ((b == NULL) || (len < 1) || (type != SD_CRC7) && (type != SD_CRC16)) { return CRC_FAIL; } for (i = 0; i < len; i++) { if (type == SD_CRC16) { crc = crc_16(crc, *(b+i)); } else { crc = crc_7((uint8_t)(crc & 0x00ff), *(b+i)); } } if (type == SD_CRC16) { crc = crc_16augment(crc); } else { crc = crc_7augment(crc); } if (type == SD_CRC16) { if (crc == expect) { return CRC_OK; } } else { if ((crc & 0x00ff) == (expect & 0x00ff)) { return CRC_OK; } } /* Always error out with failure by default. */ return CRC_FAIL;}/* Decode Card Identification register into human-readable format * * Input arguments: * * b - pointer to data buffer holding CID * * Returns: * * <none> * */void decodeCID(uint8_t *b){ cprintf(C" Manufacturer ID: 0x%02x\r\n", b[0]); cprintf(C" OEM/Application ID: %c%c\r\n", b[1], b[2]); cprintf(C" Product Name: %c%c%c%c%c\r\n", b[3], b[4], b[5], b[6], b[7]); cprintf(C" Product Revision: %u.%u\r\n", b[8], b[9]); cprintf(C" Serial Number: 0x%04x%04x\r\n", (b[10] << 8)+b[11], (b[12] <<8) + b[13]); cprintf(C" Date Code: 0x%04x\r\n", ((b[13] & 0x0f) << 8) + b[14]); return;}/* Transmit command to card. Calculates the proper CRC and handles framing * * Input arguments: * * cmd - one of the SD card commands * arg - four bytes which hold the SD command argument * * Returns: * * <none> * */void xmitcmd(uint8_t cmd, uint8_t *arg){ uint8_t crcb = 0x00; uint8_t out; /* First byte has framing bits and command */ out = 0x40 | (cmd & 0x3f); crcb = crc_7(crcb, out); xferSPI(out); /* Next five bytes hold arguments, if any */ crcb = crc_7(crcb, arg[0]); xferSPI(arg[0]); crcb = crc_7(crcb, arg[1]); xferSPI(arg[1]); crcb = crc_7(crcb, arg[2]); xferSPI(arg[2]); crcb = crc_7(crcb, arg[3]); xferSPI(arg[3]); /* Finally, crc byte is transmitted, * shifted left by one and the stop bit added */ crcb = crc_7augment(crcb); out = (crcb << 1) | 0x01; xferSPI(out);}/* Initialize SD card in SPI mode * * Input arguments: * * retries - number of retries to attempt before erroring out * * Returns: * * <none> * */int init_sd_card(int retries){ uint8_t rxdata; int status, errors, i; status = -1; /* Currently in error */ errors = 0; /* Retry counter */ CLEAR_ARGS(arg); /* Just in case the card is in some unknown state */ /* Flush out all data and attempt to get back to an idle bus */ flush_spi(516); /* Sent the CMD0_GO_IDLE_STATE while CS is asserted */ /* This signals the SD card to fall back to SPI mode */ while ((status == -1) && (errors < retries)) { cprintf(C"-> Send CMD0_GO_IDLE_STATE\r\n"); xmitcmd(CMD0_GO_IDLE_STATE, arg); if ((i = waitForR1(&rxdata, 0)) < 0) { if (i == TR_TIMEOUT) { cprintf(C"ERROR: Timeout\r\n"); } if (i == TR_NOT_IDLE) { cprintf(C"ERROR: Bus not idle\r\n"); } errors++; continue; } if (rxdata != R1_IDLE) { cprintf(C"ERROR: R1 != R1_IDLE\r\n"); errors++; continue; } status = 0; /* We're talking to the card */ cprintf(C"-> Got Idle Card State\r\n"); } if (status < 0) { /* Failure to talk to card */ return TR_FAILURE; } /* Now that card is in SPI mode with IDLE bit set, we need */ /* to send the command to start its initialization process */ /* and wait for R1_IDLE to disappear before issuing other commands */ status = 1; errors = 0; while(status && (errors < retries)) { cprintf(C"-> Send CMD55_APP_CMD\r\n"); xmitcmd(CMD55_APP_CMD, arg); if (waitForR1(&rxdata, 0) < 0) { /* If this is a MultiMediaCard (not SD), it won't respond here */ cprintf(C"ERROR: Timeout! Perhaps this is a MMC card?\r\n"); return TR_TIMEOUT; } check_r1(rxdata, R1_IDLE); cprintf(C"-> Send ACMD41_SEND_OP_COND\r\n"); xmitcmd(ACMD41_SEND_OP_COND, arg); if (waitForR1(&rxdata, 0) < 0) { cprintf(C"ERROR: Timeout on ACMD41_SEND_OP_COND\r\n"); return TR_TIMEOUT; } status = rxdata & R1_IDLE; if (status) { /* Pause here for a bit to let the card start up */ for (i = 0; i < 10000; i++); /* busy loop */ } } if (status) { /* Card never signaled ready */ return TR_FAILURE; } /* Enable CRC to protect against bus-induced data errors */ cprintf(C"-> Send CMD59_CRC_ON_OFF\r\n"); arg[3] = 0x01; /* LSB set to 1 enables CRC verification */ xmitcmd(CMD59_CRC_ON_OFF, arg); CLEAR_ARGS(arg); if (waitForR1(&rxdata, 0) < 0) { cprintf(C"ERROR: Timeout on CMD59_CRC_ON_OFF\r\n"); return TR_TIMEOUT; } check_r1(rxdata, R1_NOERROR); return TR_OK;}/* Retrieve the Card-specific Data register and decode * * Input arguments: * * <none> * * Returns: * * TR_OK if successful, TR_FAILURE otherwise * */int get_sd_csd(void){ uint8_t multiplier; uint32_t cardsize; CLEAR_ARGS(arg); cprintf(C"-> Requesting CSD (Card Specific Data)\r\n"); xmitcmd(CMD9_SEND_CSD, arg); if (waitForR1(rxbuf, 18) < 0) { cprintf(C"ERROR: Timeout on CMD9_SEND_CSD\r\n"); return -1; } check_r1(rxbuf[0], R1_NOERROR); if (verifyCRC(SD_CRC16, &rxbuf[1], 16, (rxbuf[17]<<8) + rxbuf[18]) != CRC_OK) { cprintf(C"ERROR: Data block did not pass CRC16 check\r\n"); return TR_FAILURE; } if (verifyCRC(SD_CRC7, &rxbuf[1], 15, (rxbuf[16] >> 1)) != CRC_OK) { cprintf(C"ERROR: CSD failed internal CRC7 check\r\n"); return TR_FAILURE; } /* Decode Card Specific Data */ /* A couple of items are of interest to us here: * * - block size of card (typically 512, but may differ) from READ_BL_LEN * - total size of card from C_SIZE, C_SIZE_MULT, and READ_BL_LEN * */ /* Blocksize is easy to decode */ blocksize = 0x01 << (rxbuf[6] & 0x0f); /* Cardsize is split over several bytes */ cardsize = ((rxbuf[7] & 0x03) << 10) | (rxbuf[8] << 2) | (rxbuf[9] & 0xc0); /* Multiplier is also split over several bytes */ multiplier = ((rxbuf[10] & 0x03) << 1) | (rxbuf[11] >> 7); /* Compute final card size */ cardsize <<= (multiplier + 2); /* Multiplier is 2^(m+2) */ switch (blocksize) { case 512: cardsize >>= 11; break; case 1024: break; case 2048: cardsize <<= 9; break; default: cprintf(C"Unsupported blocksize!\r\n"); return TR_FAILURE; break; } cprintf(C"Card size: %uMB\r\n", cardsize); return TR_OK;}/* Retrieve the Card Identification register and decode *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -