Misc. improvements (#12747)
* Make ExtUI respect MAXTEMP limits - Temperatures are now clamped by MAXTEMP limits rather than arbitrary values. * Speed up USB init, add status - Speed up USB initialization - Show status message if init failed * Enable status messages for EXTENSIBLE_UI * Adjust max limit to MAX_TEMP - 15 * Misc. tweaks to formatting, const, etc.
This commit is contained in:
committed by
Scott Lahteine
parent
4f2473053c
commit
60cb36bef3
@@ -65,7 +65,7 @@
|
||||
|
||||
static uint8_t CRC7(const uint8_t* data, uint8_t n) {
|
||||
uint8_t crc = 0;
|
||||
while ( n > 0 ) {
|
||||
while (n > 0) {
|
||||
crc = pgm_read_byte(&crctab7[ (crc << 1) ^ *data++ ]);
|
||||
n--;
|
||||
}
|
||||
@@ -87,44 +87,42 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// send command and return error code. Return zero for OK
|
||||
uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
|
||||
// select card
|
||||
// Send command and return error code. Return zero for OK
|
||||
uint8_t Sd2Card::cardCommand(const uint8_t cmd, const uint32_t arg) {
|
||||
// Select card
|
||||
chipSelect();
|
||||
|
||||
// wait up to 300 ms if busy
|
||||
waitNotBusy( SD_WRITE_TIMEOUT );
|
||||
// Wait up to 300 ms if busy
|
||||
waitNotBusy(SD_WRITE_TIMEOUT);
|
||||
|
||||
uint8_t *pa = (uint8_t *)(&arg);
|
||||
|
||||
#if ENABLED(SD_CHECK_AND_RETRY)
|
||||
#if ENABLED(SD_CHECK_AND_RETRY)
|
||||
|
||||
// form message
|
||||
uint8_t d[6] = {(uint8_t) (cmd | 0x40), pa[3], pa[2], pa[1], pa[0] };
|
||||
// Form message
|
||||
uint8_t d[6] = {(uint8_t) (cmd | 0x40), pa[3], pa[2], pa[1], pa[0] };
|
||||
|
||||
// add crc
|
||||
d[5] = CRC7(d, 5);
|
||||
// Add crc
|
||||
d[5] = CRC7(d, 5);
|
||||
|
||||
// send message
|
||||
for (uint8_t k = 0; k < 6; k++ )
|
||||
spiSend( d[k] );
|
||||
// Send message
|
||||
for (uint8_t k = 0; k < 6; k++) spiSend(d[k]);
|
||||
|
||||
#else
|
||||
// send command
|
||||
spiSend(cmd | 0x40);
|
||||
#else
|
||||
// Send command
|
||||
spiSend(cmd | 0x40);
|
||||
|
||||
// send argument
|
||||
for( int8_t i = 3; i >= 0; i-- )
|
||||
spiSend( pa[i] );
|
||||
// Send argument
|
||||
for (int8_t i = 3; i >= 0; i--) spiSend(pa[i]);
|
||||
|
||||
// send CRC - correct for CMD0 with arg zero or CMD8 with arg 0X1AA
|
||||
spiSend( cmd == CMD0 ? 0X95 : 0X87 );
|
||||
#endif
|
||||
// Send CRC - correct for CMD0 with arg zero or CMD8 with arg 0X1AA
|
||||
spiSend(cmd == CMD0 ? 0X95 : 0X87);
|
||||
#endif
|
||||
|
||||
// skip stuff byte for stop read
|
||||
// Skip stuff byte for stop read
|
||||
if (cmd == CMD12) spiRec();
|
||||
|
||||
// wait for response
|
||||
// Wait for response
|
||||
for (uint8_t i = 0; ((status_ = spiRec()) & 0x80) && i != 0xFF; i++) { /* Intentionally left empty */ }
|
||||
return status_;
|
||||
}
|
||||
@@ -159,9 +157,7 @@ uint32_t Sd2Card::cardSize() {
|
||||
|
||||
void Sd2Card::chipDeselect() {
|
||||
digitalWrite(chipSelectPin_, HIGH);
|
||||
|
||||
// insure MISO goes high impedance
|
||||
spiSend( 0xFF );
|
||||
spiSend(0xFF); // Ensure MISO goes high impedance
|
||||
}
|
||||
|
||||
void Sd2Card::chipSelect() {
|
||||
@@ -195,13 +191,8 @@ bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
|
||||
goto FAIL;
|
||||
}
|
||||
}
|
||||
if (type_ != SD_CARD_TYPE_SDHC) {
|
||||
firstBlock <<= 9;
|
||||
lastBlock <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD32, firstBlock)
|
||||
|| cardCommand(CMD33, lastBlock)
|
||||
|| cardCommand(CMD38, 0)) {
|
||||
if (type_ != SD_CARD_TYPE_SDHC) { firstBlock <<= 9; lastBlock <<= 9; }
|
||||
if (cardCommand(CMD32, firstBlock) || cardCommand(CMD33, lastBlock) || cardCommand(CMD38, 0)) {
|
||||
error(SD_CARD_ERROR_ERASE);
|
||||
goto FAIL;
|
||||
}
|
||||
@@ -236,7 +227,7 @@ bool Sd2Card::eraseSingleBlockEnable() {
|
||||
* \return true for success, false for failure.
|
||||
* The reason for failure can be determined by calling errorCode() and errorData().
|
||||
*/
|
||||
bool Sd2Card::init(uint8_t sckRateID, pin_t chipSelectPin) {
|
||||
bool Sd2Card::init(const uint8_t sckRateID/*=0*/, const pin_t chipSelectPin/*=SD_CHIP_SELECT_PIN*/) {
|
||||
errorCode_ = type_ = 0;
|
||||
chipSelectPin_ = chipSelectPin;
|
||||
// 16-bit init start time allows over a minute
|
||||
@@ -308,23 +299,23 @@ bool Sd2Card::init(uint8_t sckRateID, pin_t chipSelectPin) {
|
||||
watchdog_reset();
|
||||
#endif
|
||||
|
||||
// initialize card and send host supports SDHC if SD2
|
||||
// Initialize card and send host supports SDHC if SD2
|
||||
arg = type() == SD_CARD_TYPE_SD2 ? 0x40000000 : 0;
|
||||
while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
|
||||
// check for timeout
|
||||
// Check for timeout
|
||||
if (ELAPSED(millis(), init_timeout)) {
|
||||
error(SD_CARD_ERROR_ACMD41);
|
||||
goto FAIL;
|
||||
}
|
||||
}
|
||||
// if SD2 read OCR register to check for SDHC card
|
||||
// If SD2 read OCR register to check for SDHC card
|
||||
if (type() == SD_CARD_TYPE_SD2) {
|
||||
if (cardCommand(CMD58, 0)) {
|
||||
error(SD_CARD_ERROR_CMD58);
|
||||
goto FAIL;
|
||||
}
|
||||
if ((spiRec() & 0xC0) == 0xC0) type(SD_CARD_TYPE_SDHC);
|
||||
// discard rest of ocr - contains allowed voltage range
|
||||
// Discard rest of ocr - contains allowed voltage range
|
||||
for (uint8_t i = 0; i < 3; i++) spiRec();
|
||||
}
|
||||
chipDeselect();
|
||||
@@ -344,8 +335,7 @@ bool Sd2Card::init(uint8_t sckRateID, pin_t chipSelectPin) {
|
||||
* \return true for success, false for failure.
|
||||
*/
|
||||
bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; // Use address if not SDHC card
|
||||
|
||||
#if ENABLED(SD_CHECK_AND_RETRY)
|
||||
uint8_t retryCnt = 3;
|
||||
@@ -447,44 +437,39 @@ bool Sd2Card::readData(uint8_t* dst) {
|
||||
#endif
|
||||
#endif // SD_CHECK_AND_RETRY
|
||||
|
||||
bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
|
||||
// wait for start block token
|
||||
bool Sd2Card::readData(uint8_t* dst, const uint16_t count) {
|
||||
bool success = false;
|
||||
|
||||
const millis_t read_timeout = millis() + SD_READ_TIMEOUT;
|
||||
while ((status_ = spiRec()) == 0xFF) {
|
||||
while ((status_ = spiRec()) == 0xFF) { // Wait for start block token
|
||||
if (ELAPSED(millis(), read_timeout)) {
|
||||
error(SD_CARD_ERROR_READ_TIMEOUT);
|
||||
goto FAIL;
|
||||
}
|
||||
}
|
||||
if (status_ != DATA_START_BLOCK) {
|
||||
error(SD_CARD_ERROR_READ);
|
||||
goto FAIL;
|
||||
}
|
||||
// transfer data
|
||||
spiRead(dst, count);
|
||||
|
||||
#if ENABLED(SD_CHECK_AND_RETRY)
|
||||
{
|
||||
uint16_t recvCrc = (spiRec() << 8) | spiRec();
|
||||
if (crcSupported && recvCrc != CRC_CCITT(dst, count)) {
|
||||
error(SD_CARD_ERROR_READ_CRC);
|
||||
goto FAIL;
|
||||
}
|
||||
if (status_ == DATA_START_BLOCK) {
|
||||
spiRead(dst, count); // Transfer data
|
||||
|
||||
const uint16_t recvCrc = (spiRec() << 8) | spiRec();
|
||||
#if ENABLED(SD_CHECK_AND_RETRY)
|
||||
success = !crcSupported || recvCrc == CRC_CCITT(dst, count);
|
||||
if (!success) error(SD_CARD_ERROR_READ_CRC);
|
||||
#else
|
||||
success = true;
|
||||
UNUSED(recvCrc);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
// discard CRC
|
||||
spiRec();
|
||||
spiRec();
|
||||
#endif
|
||||
chipDeselect();
|
||||
return true;
|
||||
else
|
||||
error(SD_CARD_ERROR_READ);
|
||||
|
||||
FAIL:
|
||||
chipDeselect();
|
||||
return false;
|
||||
return success;
|
||||
}
|
||||
|
||||
/** read CID or CSR register */
|
||||
bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
|
||||
bool Sd2Card::readRegister(const uint8_t cmd, void* buf) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
|
||||
if (cardCommand(cmd, 0)) {
|
||||
error(SD_CARD_ERROR_READ_REG);
|
||||
@@ -506,13 +491,11 @@ bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
|
||||
*/
|
||||
bool Sd2Card::readStart(uint32_t blockNumber) {
|
||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||
if (cardCommand(CMD18, blockNumber)) {
|
||||
error(SD_CARD_ERROR_CMD18);
|
||||
chipDeselect();
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool success = !cardCommand(CMD18, blockNumber);
|
||||
if (!success) error(SD_CARD_ERROR_CMD18);
|
||||
chipDeselect();
|
||||
return true;
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -522,13 +505,10 @@ bool Sd2Card::readStart(uint32_t blockNumber) {
|
||||
*/
|
||||
bool Sd2Card::readStop() {
|
||||
chipSelect();
|
||||
if (cardCommand(CMD12, 0)) {
|
||||
error(SD_CARD_ERROR_CMD12);
|
||||
chipDeselect();
|
||||
return false;
|
||||
}
|
||||
const bool success = !cardCommand(CMD12, 0);
|
||||
if (!success) error(SD_CARD_ERROR_CMD12);
|
||||
chipDeselect();
|
||||
return true;
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -543,16 +523,20 @@ bool Sd2Card::readStop() {
|
||||
* \return The value one, true, is returned for success and the value zero,
|
||||
* false, is returned for an invalid value of \a sckRateID.
|
||||
*/
|
||||
bool Sd2Card::setSckRate(uint8_t sckRateID) {
|
||||
if (sckRateID > 6) {
|
||||
bool Sd2Card::setSckRate(const uint8_t sckRateID) {
|
||||
const bool success = (sckRateID <= 6);
|
||||
if (success)
|
||||
spiRate_ = sckRateID;
|
||||
else
|
||||
error(SD_CARD_ERROR_SCK_RATE);
|
||||
return false;
|
||||
}
|
||||
spiRate_ = sckRateID;
|
||||
return true;
|
||||
return success;
|
||||
}
|
||||
|
||||
// wait for card to go not busy
|
||||
/**
|
||||
* Wait for card to become not-busy
|
||||
* \param[in] timeout_ms Timeout to abort.
|
||||
* \return true for success, false for timeout.
|
||||
*/
|
||||
bool Sd2Card::waitNotBusy(const millis_t timeout_ms) {
|
||||
const millis_t wait_timeout = millis() + timeout_ms;
|
||||
while (spiRec() != 0xFF)
|
||||
@@ -562,36 +546,31 @@ bool Sd2Card::waitNotBusy(const millis_t timeout_ms) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a 512 byte block to an SD card.
|
||||
* Write a 512 byte block to an SD card.
|
||||
*
|
||||
* \param[in] blockNumber Logical block to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return true for success, false for failure.
|
||||
*/
|
||||
bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||
if (cardCommand(CMD24, blockNumber)) {
|
||||
error(SD_CARD_ERROR_CMD24);
|
||||
goto FAIL;
|
||||
}
|
||||
if (!writeData(DATA_START_BLOCK, src)) goto FAIL;
|
||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; // Use address if not SDHC card
|
||||
|
||||
// wait for flash programming to complete
|
||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_WRITE_TIMEOUT);
|
||||
goto FAIL;
|
||||
}
|
||||
// response is r2 so get and check two bytes for nonzero
|
||||
if (cardCommand(CMD13, 0) || spiRec()) {
|
||||
error(SD_CARD_ERROR_WRITE_PROGRAMMING);
|
||||
goto FAIL;
|
||||
bool success = false;
|
||||
if (!cardCommand(CMD24, blockNumber)) {
|
||||
if (writeData(DATA_START_BLOCK, src)) {
|
||||
if (waitNotBusy(SD_WRITE_TIMEOUT)) { // Wait for flashing to complete
|
||||
success = !(cardCommand(CMD13, 0) || spiRec()); // Response is r2 so get and check two bytes for nonzero
|
||||
if (!success) error(SD_CARD_ERROR_WRITE_PROGRAMMING);
|
||||
}
|
||||
else
|
||||
error(SD_CARD_ERROR_WRITE_TIMEOUT);
|
||||
}
|
||||
}
|
||||
else
|
||||
error(SD_CARD_ERROR_CMD24);
|
||||
|
||||
chipDeselect();
|
||||
return true;
|
||||
FAIL:
|
||||
chipDeselect();
|
||||
return false;
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -600,28 +579,30 @@ bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
|
||||
* \return true for success, false for failure.
|
||||
*/
|
||||
bool Sd2Card::writeData(const uint8_t* src) {
|
||||
bool success = true;
|
||||
chipSelect();
|
||||
// wait for previous write to finish
|
||||
// Wait for previous write to finish
|
||||
if (!waitNotBusy(SD_WRITE_TIMEOUT) || !writeData(WRITE_MULTIPLE_TOKEN, src)) {
|
||||
error(SD_CARD_ERROR_WRITE_MULTIPLE);
|
||||
chipDeselect();
|
||||
return false;
|
||||
success = false;
|
||||
}
|
||||
chipDeselect();
|
||||
return true;
|
||||
return success;
|
||||
}
|
||||
|
||||
// send one block of data for write block or write multiple blocks
|
||||
bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
|
||||
// Send one block of data for write block or write multiple blocks
|
||||
bool Sd2Card::writeData(const uint8_t token, const uint8_t* src) {
|
||||
|
||||
#if ENABLED(SD_CHECK_AND_RETRY)
|
||||
uint16_t crc = CRC_CCITT( src, 512 );
|
||||
#else // ENABLED(SD_CHECK_AND_RETRY)
|
||||
uint16_t crc = 0xFFFF;
|
||||
#endif // ENABLED(SD_CHECK_AND_RETRY)
|
||||
spiSendBlock( token, src );
|
||||
spiSend( crc >> 8 );
|
||||
spiSend( crc & 0XFF );
|
||||
uint16_t crc =
|
||||
#if ENABLED(SD_CHECK_AND_RETRY)
|
||||
CRC_CCITT(src, 512)
|
||||
#else
|
||||
0xFFFF
|
||||
#endif
|
||||
;
|
||||
spiSendBlock(token, src);
|
||||
spiSend(crc >> 8);
|
||||
spiSend(crc & 0xFF);
|
||||
|
||||
status_ = spiRec();
|
||||
if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
|
||||
@@ -643,23 +624,18 @@ bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
|
||||
*
|
||||
* \return true for success, false for failure.
|
||||
*/
|
||||
bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
|
||||
// send pre-erase count
|
||||
if (cardAcmd(ACMD23, eraseCount)) {
|
||||
bool Sd2Card::writeStart(uint32_t blockNumber, const uint32_t eraseCount) {
|
||||
bool success = false;
|
||||
if (!cardAcmd(ACMD23, eraseCount)) { // Send pre-erase count
|
||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; // Use address if not SDHC card
|
||||
success = !cardCommand(CMD25, blockNumber);
|
||||
if (!success) error(SD_CARD_ERROR_CMD25);
|
||||
}
|
||||
else
|
||||
error(SD_CARD_ERROR_ACMD23);
|
||||
goto FAIL;
|
||||
}
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
|
||||
if (cardCommand(CMD25, blockNumber)) {
|
||||
error(SD_CARD_ERROR_CMD25);
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
chipDeselect();
|
||||
return true;
|
||||
FAIL:
|
||||
chipDeselect();
|
||||
return false;
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -668,16 +644,17 @@ bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
|
||||
* \return true for success, false for failure.
|
||||
*/
|
||||
bool Sd2Card::writeStop() {
|
||||
bool success = false;
|
||||
chipSelect();
|
||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto FAIL;
|
||||
spiSend(STOP_TRAN_TOKEN);
|
||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto FAIL;
|
||||
if (waitNotBusy(SD_WRITE_TIMEOUT)) {
|
||||
spiSend(STOP_TRAN_TOKEN);
|
||||
success = waitNotBusy(SD_WRITE_TIMEOUT);
|
||||
}
|
||||
else
|
||||
error(SD_CARD_ERROR_STOP_TRAN);
|
||||
|
||||
chipDeselect();
|
||||
return true;
|
||||
FAIL:
|
||||
error(SD_CARD_ERROR_STOP_TRAN);
|
||||
chipDeselect();
|
||||
return false;
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif // SDSUPPORT
|
||||
|
Reference in New Issue
Block a user