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
|
name=SdFat
|
||||||
version=1.0.12
|
version=1.0.13
|
||||||
author=Bill Greiman <fat16lib@sbcglobal.net>
|
author=Bill Greiman <fat16lib@sbcglobal.net>
|
||||||
maintainer=Bill Greiman <fat16lib@sbcglobal.net>
|
maintainer=Bill Greiman <fat16lib@sbcglobal.net>
|
||||||
sentence=FAT16/FAT32 file system for SD cards.
|
sentence=FAT16/FAT32 file system for SD cards.
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,115 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include "SdSpiCard.h"
|
#include "SdSpiCard.h"
|
||||||
|
//==============================================================================
|
||||||
// debug trace macro
|
// debug trace macro
|
||||||
#define SD_TRACE(m, b)
|
#define SD_TRACE(m, b)
|
||||||
// #define SD_TRACE(m, b) Serial.print(m);Serial.println(b);
|
// #define SD_TRACE(m, b) Serial.print(m);Serial.println(b);
|
||||||
#define SD_CS_DBG(m)
|
#define SD_CS_DBG(m)
|
||||||
// #define SD_CS_DBG(m) Serial.println(F(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
|
#if USE_SD_CRC
|
||||||
// CRC functions
|
// CRC functions
|
||||||
|
|
@ -137,13 +241,11 @@ bool SdSpiCard::begin(SdSpiDriver* spi, uint8_t csPin, SPISettings settings) {
|
||||||
spiSend(0XFF);
|
spiSend(0XFF);
|
||||||
}
|
}
|
||||||
spiSelect();
|
spiSelect();
|
||||||
|
|
||||||
// command to go idle in SPI mode
|
// command to go idle in SPI mode
|
||||||
while (cardCommand(CMD0, 0) != R1_IDLE_STATE) {
|
if (cardCommand(CMD0, 0) != R1_IDLE_STATE) {
|
||||||
if (isTimedOut(t0, SD_INIT_TIMEOUT)) {
|
error(SD_CARD_ERROR_CMD0);
|
||||||
error(SD_CARD_ERROR_CMD0);
|
goto fail;
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
delayMS(SD_CMD0_DELAY);
|
|
||||||
}
|
}
|
||||||
#if USE_SD_CRC
|
#if USE_SD_CRC
|
||||||
if (cardCommand(CMD59, 1) != R1_IDLE_STATE) {
|
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
|
#endif // USE_SD_CRC
|
||||||
// check SD version
|
// check SD version
|
||||||
while (1) {
|
if (cardCommand(CMD8, 0x1AA) == (R1_ILLEGAL_COMMAND | R1_IDLE_STATE)) {
|
||||||
if (cardCommand(CMD8, 0x1AA) == (R1_ILLEGAL_COMMAND | R1_IDLE_STATE)) {
|
type(SD_CARD_TYPE_SD1);
|
||||||
type(SD_CARD_TYPE_SD1);
|
} else {
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (uint8_t i = 0; i < 4; i++) {
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
m_status = spiReceive();
|
m_status = spiReceive();
|
||||||
}
|
}
|
||||||
if (m_status == 0XAA) {
|
if (m_status == 0XAA) {
|
||||||
type(SD_CARD_TYPE_SD2);
|
type(SD_CARD_TYPE_SD2);
|
||||||
break;
|
} else {
|
||||||
}
|
|
||||||
if (isTimedOut(t0, SD_INIT_TIMEOUT)) {
|
|
||||||
error(SD_CARD_ERROR_CMD8);
|
error(SD_CARD_ERROR_CMD8);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 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;
|
arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
|
||||||
|
DBG_BEGIN_TIME(DBG_ACMD41_TIME);
|
||||||
while (cardAcmd(ACMD41, arg) != R1_READY_STATE) {
|
while (cardAcmd(ACMD41, arg) != R1_READY_STATE) {
|
||||||
|
DBG_EVENT_COUNT(DBG_ACMD41_COUNT);
|
||||||
// check for timeout
|
// check for timeout
|
||||||
if (isTimedOut(t0, SD_INIT_TIMEOUT)) {
|
if (isTimedOut(t0, SD_INIT_TIMEOUT)) {
|
||||||
error(SD_CARD_ERROR_ACMD41);
|
error(SD_CARD_ERROR_ACMD41);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DBG_END_TIME(DBG_ACMD41_TIME);
|
||||||
// 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 (type() == SD_CARD_TYPE_SD2) {
|
||||||
if (cardCommand(CMD58, 0)) {
|
if (cardCommand(CMD58, 0)) {
|
||||||
|
|
@ -208,8 +308,12 @@ uint8_t SdSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
||||||
if (!m_spiActive) {
|
if (!m_spiActive) {
|
||||||
spiStart();
|
spiStart();
|
||||||
}
|
}
|
||||||
// wait if busy
|
// wait if busy unless CMD0
|
||||||
waitNotBusy(SD_CMD_TIMEOUT);
|
if (cmd != CMD0) {
|
||||||
|
DBG_BEGIN_TIME(DBG_CMD_BUSY);
|
||||||
|
waitNotBusy(SD_CMD_TIMEOUT);
|
||||||
|
DBG_END_TIME(DBG_CMD_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
#if USE_SD_CRC
|
#if USE_SD_CRC
|
||||||
// form message
|
// form message
|
||||||
|
|
@ -234,18 +338,15 @@ uint8_t SdSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
||||||
for (int8_t i = 3; i >= 0; i--) {
|
for (int8_t i = 3; i >= 0; i--) {
|
||||||
spiSend(pa[i]);
|
spiSend(pa[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// send CRC - correct for CMD0 with arg zero or CMD8 with arg 0X1AA
|
// send CRC - correct for CMD0 with arg zero or CMD8 with arg 0X1AA
|
||||||
spiSend(cmd == CMD0 ? 0X95 : 0X87);
|
spiSend(cmd == CMD0 ? 0X95 : 0X87);
|
||||||
#endif // USE_SD_CRC
|
#endif // USE_SD_CRC
|
||||||
|
|
||||||
// skip stuff byte for stop read
|
// discard first fill byte to avoid MISO pull-up problem.
|
||||||
if (cmd == CMD12) {
|
spiReceive();
|
||||||
spiReceive();
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for response
|
// there are 1-8 fill bytes before response. fill bytes should be 0XFF.
|
||||||
for (uint8_t i = 0; ((m_status = spiReceive()) & 0X80) && i != 0XFF; i++) {
|
for (uint8_t i = 0; ((m_status = spiReceive()) & 0X80) && i < 10; i++) {
|
||||||
}
|
}
|
||||||
return m_status;
|
return m_status;
|
||||||
}
|
}
|
||||||
|
|
@ -280,10 +381,12 @@ bool SdSpiCard::erase(uint32_t firstBlock, uint32_t lastBlock) {
|
||||||
error(SD_CARD_ERROR_ERASE);
|
error(SD_CARD_ERROR_ERASE);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
DBG_BEGIN_TIME(DBG_ERASE_BUSY);
|
||||||
if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
|
if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
|
||||||
error(SD_CARD_ERROR_ERASE_TIMEOUT);
|
error(SD_CARD_ERROR_ERASE_TIMEOUT);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
DBG_END_TIME(DBG_ERASE_BUSY);
|
||||||
spiStop();
|
spiStop();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
@ -367,6 +470,7 @@ bool SdSpiCard::readData(uint8_t* dst, size_t count) {
|
||||||
#if USE_SD_CRC
|
#if USE_SD_CRC
|
||||||
uint16_t crc;
|
uint16_t crc;
|
||||||
#endif // USE_SD_CRC
|
#endif // USE_SD_CRC
|
||||||
|
DBG_BEGIN_TIME(DBG_WAIT_READ);
|
||||||
// wait for start block token
|
// wait for start block token
|
||||||
uint16_t t0 = curTimeMS();
|
uint16_t t0 = curTimeMS();
|
||||||
while ((m_status = spiReceive()) == 0XFF) {
|
while ((m_status = spiReceive()) == 0XFF) {
|
||||||
|
|
@ -375,6 +479,7 @@ bool SdSpiCard::readData(uint8_t* dst, size_t count) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DBG_END_TIME(DBG_WAIT_READ);
|
||||||
if (m_status != DATA_START_BLOCK) {
|
if (m_status != DATA_START_BLOCK) {
|
||||||
error(SD_CARD_ERROR_READ);
|
error(SD_CARD_ERROR_READ);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -543,10 +648,12 @@ bool SdSpiCard::writeBlock(uint32_t blockNumber, const uint8_t* src) {
|
||||||
|
|
||||||
#if CHECK_FLASH_PROGRAMMING
|
#if CHECK_FLASH_PROGRAMMING
|
||||||
// wait for flash programming to complete
|
// wait for flash programming to complete
|
||||||
|
DBG_BEGIN_TIME(DBG_WRITE_FLASH);
|
||||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
||||||
error(SD_CARD_ERROR_FLASH_PROGRAMMING);
|
error(SD_CARD_ERROR_FLASH_PROGRAMMING);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
DBG_END_TIME(DBG_WRITE_FLASH);
|
||||||
// response is r2 so get and check two bytes for nonzero
|
// response is r2 so get and check two bytes for nonzero
|
||||||
if (cardCommand(CMD13, 0) || spiReceive()) {
|
if (cardCommand(CMD13, 0) || spiReceive()) {
|
||||||
error(SD_CARD_ERROR_CMD13);
|
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) {
|
bool SdSpiCard::writeData(const uint8_t* src) {
|
||||||
// wait for previous write to finish
|
// wait for previous write to finish
|
||||||
|
DBG_BEGIN_TIME(DBG_WRITE_BUSY);
|
||||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
||||||
error(SD_CARD_ERROR_WRITE_TIMEOUT);
|
error(SD_CARD_ERROR_WRITE_TIMEOUT);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
DBG_END_TIME(DBG_WRITE_BUSY);
|
||||||
if (!writeData(WRITE_MULTIPLE_TOKEN, src)) {
|
if (!writeData(WRITE_MULTIPLE_TOKEN, src)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
@ -657,9 +766,11 @@ fail:
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool SdSpiCard::writeStop() {
|
bool SdSpiCard::writeStop() {
|
||||||
|
DBG_BEGIN_TIME(DBG_WRITE_STOP);
|
||||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
DBG_END_TIME(DBG_WRITE_STOP);
|
||||||
spiSend(STOP_TRAN_TOKEN);
|
spiSend(STOP_TRAN_TOKEN);
|
||||||
spiStop();
|
spiStop();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
#endif // INCLUDE_SDIOS
|
#endif // INCLUDE_SDIOS
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** SdFat version */
|
/** SdFat version */
|
||||||
#define SD_FAT_VERSION "1.0.12"
|
#define SD_FAT_VERSION "1.0.13"
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/**
|
/**
|
||||||
* \class SdBaseFile
|
* \class SdBaseFile
|
||||||
|
|
|
||||||
|
|
@ -52,11 +52,6 @@ inline uint16_t curTimeMS() {
|
||||||
return millis();
|
return millis();
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Delay milliseconds */
|
|
||||||
inline void delayMS(uint16_t ms) {
|
|
||||||
delay(ms);
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
/**
|
/**
|
||||||
* \class SysCall
|
* \class SysCall
|
||||||
* \brief SysCall - Class to wrap system calls.
|
* \brief SysCall - Class to wrap system calls.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue