Avoid MISO missing pull-up problem
This commit is contained in:
parent
356c5e417c
commit
37c1f2606b
4 changed files with 137 additions and 31 deletions
|
|
@ -1,5 +1,5 @@
|
|||
name=SdFat
|
||||
version=1.0.12
|
||||
version=1.0.13
|
||||
author=Bill Greiman <fat16lib@sbcglobal.net>
|
||||
maintainer=Bill Greiman <fat16lib@sbcglobal.net>
|
||||
sentence=FAT16/FAT32 file system for SD cards.
|
||||
|
|
|
|||
|
|
@ -23,11 +23,115 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "SdSpiCard.h"
|
||||
//==============================================================================
|
||||
// debug trace macro
|
||||
#define SD_TRACE(m, b)
|
||||
// #define SD_TRACE(m, b) Serial.print(m);Serial.println(b);
|
||||
#define SD_CS_DBG(m)
|
||||
// #define SD_CS_DBG(m) Serial.println(F(m));
|
||||
|
||||
#define DBG_PROFILE_TIME 0
|
||||
#if DBG_PROFILE_TIME
|
||||
|
||||
#define DBG_TAG_LIST\
|
||||
DBG_TAG(DBG_ACMD41_TIME, "ACMD41 time")\
|
||||
DBG_TAG(DBG_CMD_BUSY, "cmd busy")\
|
||||
DBG_TAG(DBG_ERASE_BUSY, "erase busy")\
|
||||
DBG_TAG(DBG_WAIT_READ, "wait read")\
|
||||
DBG_TAG(DBG_WRITE_FLASH, "write flash")\
|
||||
DBG_TAG(DBG_WRITE_BUSY, "write busy")\
|
||||
DBG_TAG(DBG_WRITE_STOP, "write stop")\
|
||||
DBG_TAG(DBG_ACMD41_COUNT, "ACMD41 count")
|
||||
|
||||
#define DBG_TIME_DIM DBG_ACMD41_COUNT
|
||||
|
||||
enum DbgTag {
|
||||
#define DBG_TAG(tag, str) tag,
|
||||
DBG_TAG_LIST
|
||||
DBG_COUNT_DIM
|
||||
#undef DBG_TAG
|
||||
};
|
||||
|
||||
static uint32_t dbgCount[DBG_COUNT_DIM];
|
||||
static uint32_t dbgBgnTime[DBG_TIME_DIM];
|
||||
static uint32_t dbgMaxTime[DBG_TIME_DIM];
|
||||
static uint32_t dbgMinTime[DBG_TIME_DIM];
|
||||
static uint32_t dbgTotalTime[DBG_TIME_DIM];
|
||||
//------------------------------------------------------------------------------
|
||||
static void dbgBeginTime(DbgTag tag) {
|
||||
dbgBgnTime[tag] = micros();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void dbgEndTime(DbgTag tag) {
|
||||
uint32_t m = micros() - dbgBgnTime[tag];
|
||||
dbgTotalTime[tag] += m;
|
||||
if (m > dbgMaxTime[tag]) {
|
||||
dbgMaxTime[tag] = m;
|
||||
}
|
||||
if (m < dbgMinTime[tag]) {
|
||||
dbgMinTime[tag] = m;
|
||||
}
|
||||
dbgCount[tag]++;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void dbgEventCount(DbgTag tag) {
|
||||
dbgCount[tag]++;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void dbgInitTime() {
|
||||
for (int i = 0; i < DBG_COUNT_DIM; i++) {
|
||||
dbgCount[i] = 0;
|
||||
if (i < DBG_TIME_DIM) {
|
||||
dbgMaxTime[i] = 0;
|
||||
dbgMinTime[i] = 9999999;
|
||||
dbgTotalTime[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void dbgPrintTagText(uint8_t tag) {
|
||||
#define DBG_TAG(e, m) case e: Serial.print(F(m)); break;
|
||||
switch (tag) {
|
||||
DBG_TAG_LIST
|
||||
}
|
||||
#undef DBG_TAG
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void dbgPrintTime() {
|
||||
Serial.println();
|
||||
Serial.println(F("======================="));
|
||||
Serial.println(F("item,event,min,max,avg"));
|
||||
Serial.println(F("tag,count,usec,usec,usec"));
|
||||
for (int i = 0; i < DBG_COUNT_DIM; i++) {
|
||||
if (dbgCount[i]) {
|
||||
dbgPrintTagText(i);
|
||||
Serial.print(',');
|
||||
Serial.print(dbgCount[i]);
|
||||
if (i < DBG_TIME_DIM) {
|
||||
Serial.print(',');
|
||||
Serial.print(dbgMinTime[i]);
|
||||
Serial.print(',');
|
||||
Serial.print(dbgMaxTime[i]);
|
||||
Serial.print(',');
|
||||
Serial.print(dbgTotalTime[i]/dbgCount[i]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
Serial.println(F("======================="));
|
||||
Serial.println();
|
||||
}
|
||||
#undef DBG_TAG_LIST
|
||||
#define DBG_BEGIN_TIME(tag) dbgBeginTime(tag)
|
||||
#define DBG_END_TIME(tag) dbgEndTime(tag)
|
||||
#define DBG_EVENT_COUNT(tag) dbgEventCount(tag)
|
||||
#else // DBG_PROFILE_TIME
|
||||
#define DBG_BEGIN_TIME(tag)
|
||||
#define DBG_END_TIME(tag)
|
||||
#define DBG_EVENT_COUNT(tag)
|
||||
void dbgInitTime() {}
|
||||
void dbgPrintTime() {}
|
||||
#endif // DBG_PROFILE_TIME
|
||||
//==============================================================================
|
||||
#if USE_SD_CRC
|
||||
// CRC functions
|
||||
|
|
@ -137,13 +241,11 @@ bool SdSpiCard::begin(SdSpiDriver* spi, uint8_t csPin, SPISettings settings) {
|
|||
spiSend(0XFF);
|
||||
}
|
||||
spiSelect();
|
||||
|
||||
// command to go idle in SPI mode
|
||||
while (cardCommand(CMD0, 0) != R1_IDLE_STATE) {
|
||||
if (isTimedOut(t0, SD_INIT_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_CMD0);
|
||||
goto fail;
|
||||
}
|
||||
delayMS(SD_CMD0_DELAY);
|
||||
if (cardCommand(CMD0, 0) != R1_IDLE_STATE) {
|
||||
error(SD_CARD_ERROR_CMD0);
|
||||
goto fail;
|
||||
}
|
||||
#if USE_SD_CRC
|
||||
if (cardCommand(CMD59, 1) != R1_IDLE_STATE) {
|
||||
|
|
@ -152,33 +254,31 @@ bool SdSpiCard::begin(SdSpiDriver* spi, uint8_t csPin, SPISettings settings) {
|
|||
}
|
||||
#endif // USE_SD_CRC
|
||||
// check SD version
|
||||
while (1) {
|
||||
if (cardCommand(CMD8, 0x1AA) == (R1_ILLEGAL_COMMAND | R1_IDLE_STATE)) {
|
||||
type(SD_CARD_TYPE_SD1);
|
||||
break;
|
||||
}
|
||||
if (cardCommand(CMD8, 0x1AA) == (R1_ILLEGAL_COMMAND | R1_IDLE_STATE)) {
|
||||
type(SD_CARD_TYPE_SD1);
|
||||
} else {
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
m_status = spiReceive();
|
||||
}
|
||||
if (m_status == 0XAA) {
|
||||
type(SD_CARD_TYPE_SD2);
|
||||
break;
|
||||
}
|
||||
if (isTimedOut(t0, SD_INIT_TIMEOUT)) {
|
||||
} else {
|
||||
error(SD_CARD_ERROR_CMD8);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
// initialize card and send host supports SDHC if SD2
|
||||
arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
|
||||
|
||||
DBG_BEGIN_TIME(DBG_ACMD41_TIME);
|
||||
while (cardAcmd(ACMD41, arg) != R1_READY_STATE) {
|
||||
DBG_EVENT_COUNT(DBG_ACMD41_COUNT);
|
||||
// check for timeout
|
||||
if (isTimedOut(t0, SD_INIT_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_ACMD41);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
DBG_END_TIME(DBG_ACMD41_TIME);
|
||||
// if SD2 read OCR register to check for SDHC card
|
||||
if (type() == SD_CARD_TYPE_SD2) {
|
||||
if (cardCommand(CMD58, 0)) {
|
||||
|
|
@ -208,8 +308,12 @@ uint8_t SdSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
|||
if (!m_spiActive) {
|
||||
spiStart();
|
||||
}
|
||||
// wait if busy
|
||||
waitNotBusy(SD_CMD_TIMEOUT);
|
||||
// wait if busy unless CMD0
|
||||
if (cmd != CMD0) {
|
||||
DBG_BEGIN_TIME(DBG_CMD_BUSY);
|
||||
waitNotBusy(SD_CMD_TIMEOUT);
|
||||
DBG_END_TIME(DBG_CMD_BUSY);
|
||||
}
|
||||
|
||||
#if USE_SD_CRC
|
||||
// form message
|
||||
|
|
@ -234,18 +338,15 @@ uint8_t SdSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
|||
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 // USE_SD_CRC
|
||||
|
||||
// skip stuff byte for stop read
|
||||
if (cmd == CMD12) {
|
||||
spiReceive();
|
||||
}
|
||||
// discard first fill byte to avoid MISO pull-up problem.
|
||||
spiReceive();
|
||||
|
||||
// wait for response
|
||||
for (uint8_t i = 0; ((m_status = spiReceive()) & 0X80) && i != 0XFF; i++) {
|
||||
// there are 1-8 fill bytes before response. fill bytes should be 0XFF.
|
||||
for (uint8_t i = 0; ((m_status = spiReceive()) & 0X80) && i < 10; i++) {
|
||||
}
|
||||
return m_status;
|
||||
}
|
||||
|
|
@ -280,10 +381,12 @@ bool SdSpiCard::erase(uint32_t firstBlock, uint32_t lastBlock) {
|
|||
error(SD_CARD_ERROR_ERASE);
|
||||
goto fail;
|
||||
}
|
||||
DBG_BEGIN_TIME(DBG_ERASE_BUSY);
|
||||
if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_ERASE_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
DBG_END_TIME(DBG_ERASE_BUSY);
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
|
|
@ -367,6 +470,7 @@ bool SdSpiCard::readData(uint8_t* dst, size_t count) {
|
|||
#if USE_SD_CRC
|
||||
uint16_t crc;
|
||||
#endif // USE_SD_CRC
|
||||
DBG_BEGIN_TIME(DBG_WAIT_READ);
|
||||
// wait for start block token
|
||||
uint16_t t0 = curTimeMS();
|
||||
while ((m_status = spiReceive()) == 0XFF) {
|
||||
|
|
@ -375,6 +479,7 @@ bool SdSpiCard::readData(uint8_t* dst, size_t count) {
|
|||
goto fail;
|
||||
}
|
||||
}
|
||||
DBG_END_TIME(DBG_WAIT_READ);
|
||||
if (m_status != DATA_START_BLOCK) {
|
||||
error(SD_CARD_ERROR_READ);
|
||||
goto fail;
|
||||
|
|
@ -543,10 +648,12 @@ bool SdSpiCard::writeBlock(uint32_t blockNumber, const uint8_t* src) {
|
|||
|
||||
#if CHECK_FLASH_PROGRAMMING
|
||||
// wait for flash programming to complete
|
||||
DBG_BEGIN_TIME(DBG_WRITE_FLASH);
|
||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_FLASH_PROGRAMMING);
|
||||
goto fail;
|
||||
}
|
||||
DBG_END_TIME(DBG_WRITE_FLASH);
|
||||
// response is r2 so get and check two bytes for nonzero
|
||||
if (cardCommand(CMD13, 0) || spiReceive()) {
|
||||
error(SD_CARD_ERROR_CMD13);
|
||||
|
|
@ -580,10 +687,12 @@ bool SdSpiCard::writeBlocks(uint32_t block, const uint8_t* src, size_t count) {
|
|||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::writeData(const uint8_t* src) {
|
||||
// wait for previous write to finish
|
||||
DBG_BEGIN_TIME(DBG_WRITE_BUSY);
|
||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_WRITE_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
DBG_END_TIME(DBG_WRITE_BUSY);
|
||||
if (!writeData(WRITE_MULTIPLE_TOKEN, src)) {
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -657,9 +766,11 @@ fail:
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::writeStop() {
|
||||
DBG_BEGIN_TIME(DBG_WRITE_STOP);
|
||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
||||
goto fail;
|
||||
}
|
||||
DBG_END_TIME(DBG_WRITE_STOP);
|
||||
spiSend(STOP_TRAN_TOKEN);
|
||||
spiStop();
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#endif // INCLUDE_SDIOS
|
||||
//------------------------------------------------------------------------------
|
||||
/** SdFat version */
|
||||
#define SD_FAT_VERSION "1.0.12"
|
||||
#define SD_FAT_VERSION "1.0.13"
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class SdBaseFile
|
||||
|
|
|
|||
|
|
@ -52,11 +52,6 @@ inline uint16_t curTimeMS() {
|
|||
return millis();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Delay milliseconds */
|
||||
inline void delayMS(uint16_t ms) {
|
||||
delay(ms);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \class SysCall
|
||||
* \brief SysCall - Class to wrap system calls.
|
||||
|
|
|
|||
Loading…
Reference in a new issue