uint8_t buf[BUF_DIM]; | uint8_t buf[BUF_DIM]; | ||||
const uint32_t FILE_SIZE = 1000000; | const uint32_t FILE_SIZE = 1000000; | ||||
const uint16_t NWRITE = FILE_SIZE/BUF_DIM; | |||||
const uint32_t NWRITE = FILE_SIZE/BUF_DIM; | |||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
// print error msg, any SD error codes, and halt. | // print error msg, any SD error codes, and halt. | ||||
// store messages in flash | // store messages in flash | ||||
Serial.println(F("Writing test.bin to sd1")); | Serial.println(F("Writing test.bin to sd1")); | ||||
// write data to /Dir1/test.bin on sd1 | // write data to /Dir1/test.bin on sd1 | ||||
for (uint16_t i = 0; i < NWRITE; i++) { | |||||
for (uint32_t i = 0; i < NWRITE; i++) { | |||||
if (file1.write(buf, sizeof(buf)) != sizeof(buf)) { | if (file1.write(buf, sizeof(buf)) != sizeof(buf)) { | ||||
error("file1.write"); | error("file1.write"); | ||||
} | } |
} | } | ||||
// fill buf with known data | // fill buf with known data | ||||
for (uint16_t i = 0; i < (BUF_SIZE-2); i++) { | |||||
buf[i] = 'A' + (i % 26); | |||||
if (BUF_SIZE > 1) { | |||||
for (size_t i = 0; i < (BUF_SIZE - 2); i++) { | |||||
buf[i] = 'A' + (i % 26); | |||||
} | |||||
buf[BUF_SIZE-2] = '\r'; | |||||
} | } | ||||
buf[BUF_SIZE-2] = '\r'; | |||||
buf[BUF_SIZE-1] = '\n'; | buf[BUF_SIZE-1] = '\n'; | ||||
cout << F("FILE_SIZE_MB = ") << FILE_SIZE_MB << endl; | cout << F("FILE_SIZE_MB = ") << FILE_SIZE_MB << endl; | ||||
cout << F("BUF_SIZE = ") << BUF_SIZE << F(" bytes\n"); | cout << F("BUF_SIZE = ") << BUF_SIZE << F(" bytes\n"); | ||||
cout << F("Starting write test, please wait.") << endl << endl; | cout << F("Starting write test, please wait.") << endl << endl; | ||||
m = micros() - m; | m = micros() - m; | ||||
totalLatency += m; | totalLatency += m; | ||||
if (buf[BUF_SIZE-1] != '\n') { | if (buf[BUF_SIZE-1] != '\n') { | ||||
error("data check error"); | error("data check error"); | ||||
} | } | ||||
if (skipLatency) { | if (skipLatency) { |
} | } | ||||
// fill buf with known data | // fill buf with known data | ||||
for (uint16_t i = 0; i < (BUF_SIZE-2); i++) { | |||||
for (size_t_t i = 0; i < (BUF_SIZE-2); i++) { | |||||
buf[i] = 'A' + (i % 26); | buf[i] = 'A' + (i % 26); | ||||
} | } | ||||
buf[BUF_SIZE-2] = '\r'; | buf[BUF_SIZE-2] = '\r'; |
uint8_t buf[BUF_DIM]; | uint8_t buf[BUF_DIM]; | ||||
const uint32_t FILE_SIZE = 1000000; | const uint32_t FILE_SIZE = 1000000; | ||||
const uint16_t NWRITE = FILE_SIZE/BUF_DIM; | |||||
const uint32_t NWRITE = FILE_SIZE/BUF_DIM; | |||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
// print error msg, any SD error codes, and halt. | // print error msg, any SD error codes, and halt. | ||||
// store messages in flash | // store messages in flash | ||||
Serial.println(F("Writing test.bin to sd1")); | Serial.println(F("Writing test.bin to sd1")); | ||||
// write data to /Dir1/test.bin on sd1 | // write data to /Dir1/test.bin on sd1 | ||||
for (uint16_t i = 0; i < NWRITE; i++) { | |||||
for (uint32_t i = 0; i < NWRITE; i++) { | |||||
if (file1.write(buf, sizeof(buf)) != sizeof(buf)) { | if (file1.write(buf, sizeof(buf)) != sizeof(buf)) { | ||||
sd1.errorExit("sd1.write"); | sd1.errorExit("sd1.write"); | ||||
} | } |
name=SdFat | name=SdFat | ||||
version=2.0.0-beta.3 | |||||
version=2.0.0-beta.4 | |||||
license=MIT | license=MIT | ||||
author=Bill Greiman <fat16lib@sbcglobal.net> | author=Bill Greiman <fat16lib@sbcglobal.net> | ||||
maintainer=Bill Greiman <fat16lib@sbcglobal.net> | maintainer=Bill Greiman <fat16lib@sbcglobal.net> |
#if USE_MULTI_SECTOR_IO | #if USE_MULTI_SECTOR_IO | ||||
} else if (toRead >= 2*m_vol->bytesPerSector()) { | } else if (toRead >= 2*m_vol->bytesPerSector()) { | ||||
uint32_t ns = toRead >> m_vol->bytesPerSectorShift(); | uint32_t ns = toRead >> m_vol->bytesPerSectorShift(); | ||||
if (!isContiguous()) { | |||||
uint32_t maxNs = m_vol->sectorsPerCluster() | |||||
- (clusterOffset >> m_vol->bytesPerSectorShift()); | |||||
if (ns > maxNs) { | |||||
ns = maxNs; | |||||
} | |||||
// Limit writes to current cluster. | |||||
uint32_t maxNs = m_vol->sectorsPerCluster() | |||||
- (clusterOffset >> m_vol->bytesPerSectorShift()); | |||||
if (ns > maxNs) { | |||||
ns = maxNs; | |||||
} | } | ||||
n = ns << m_vol->bytesPerSectorShift(); | n = ns << m_vol->bytesPerSectorShift(); | ||||
if (m_vol->dataCacheSector() <= sector | |||||
// Check for cache sector in read range. | |||||
if (sector <= m_vol->dataCacheSector() | |||||
&& m_vol->dataCacheSector() < (sector + ns)) { | && m_vol->dataCacheSector() < (sector + ns)) { | ||||
// flush cache if a sector is in the cache | |||||
// Flush cache if a cache sector is in the range. | |||||
if (!m_vol->dataCacheSync()) { | if (!m_vol->dataCacheSync()) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; |
ns = maxNs; | ns = maxNs; | ||||
} | } | ||||
n = ns << m_vol->bytesPerSectorShift(); | n = ns << m_vol->bytesPerSectorShift(); | ||||
if (m_vol->dataCacheSector() <= sector | |||||
// Check for cache sector in write range. | |||||
if (sector <= m_vol->dataCacheSector() | |||||
&& m_vol->dataCacheSector() < (sector + ns)) { | && m_vol->dataCacheSector() < (sector + ns)) { | ||||
// invalidate cache if sector is in cache | |||||
// Invalidate cache if cache sector is in the range. | |||||
m_vol->dataCacheInvalidate(); | m_vol->dataCacheInvalidate(); | ||||
} | } | ||||
if (!m_vol->writeSectors(sector, src, ns)) { | if (!m_vol->writeSectors(sector, src, ns)) { |
memcpy(dst, src, n); | memcpy(dst, src, n); | ||||
#if USE_MULTI_SECTOR_IO | #if USE_MULTI_SECTOR_IO | ||||
} else if (toRead >= 2*m_vol->bytesPerSector()) { | } else if (toRead >= 2*m_vol->bytesPerSector()) { | ||||
uint8_t ns = toRead >> m_vol->bytesPerSectorShift(); | |||||
uint32_t ns = toRead >> m_vol->bytesPerSectorShift(); | |||||
if (!isRootFixed()) { | if (!isRootFixed()) { | ||||
uint8_t mb = m_vol->sectorsPerCluster() - sectorOfCluster; | |||||
uint32_t mb = m_vol->sectorsPerCluster() - sectorOfCluster; | |||||
if (mb < ns) { | if (mb < ns) { | ||||
ns = mb; | ns = mb; | ||||
} | } | ||||
} | } | ||||
n = ns << m_vol->bytesPerSectorShift(); | n = ns << m_vol->bytesPerSectorShift(); | ||||
if (m_vol->cacheSectorNumber() <= sector | |||||
// Check for cache sector in read range. | |||||
if (sector <= m_vol->cacheSectorNumber() | |||||
&& sector < (m_vol->cacheSectorNumber() + ns)) { | && sector < (m_vol->cacheSectorNumber() + ns)) { | ||||
// flush cache if a sector is in the cache | |||||
// Flush cache if a cache sector is in the range. | |||||
if (!m_vol->cacheSyncData()) { | if (!m_vol->cacheSyncData()) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; | ||||
#if USE_MULTI_SECTOR_IO | #if USE_MULTI_SECTOR_IO | ||||
} else if (nToWrite >= 2*m_vol->bytesPerSector()) { | } else if (nToWrite >= 2*m_vol->bytesPerSector()) { | ||||
// use multiple sector write command | // use multiple sector write command | ||||
uint8_t maxSectors = m_vol->sectorsPerCluster() - sectorOfCluster; | |||||
uint8_t nSector = nToWrite >> m_vol->bytesPerSectorShift(); | |||||
uint32_t maxSectors = m_vol->sectorsPerCluster() - sectorOfCluster; | |||||
uint32_t nSector = nToWrite >> m_vol->bytesPerSectorShift(); | |||||
if (nSector > maxSectors) { | if (nSector > maxSectors) { | ||||
nSector = maxSectors; | nSector = maxSectors; | ||||
} | } | ||||
n = nSector << m_vol->bytesPerSectorShift(); | n = nSector << m_vol->bytesPerSectorShift(); | ||||
if (m_vol->cacheSectorNumber() <= sector | |||||
// Check for cache sector in write range. | |||||
if (sector <= m_vol->cacheSectorNumber() | |||||
&& sector < (m_vol->cacheSectorNumber() + nSector)) { | && sector < (m_vol->cacheSectorNumber() + nSector)) { | ||||
// invalidate cache if sector is in cache | |||||
// Invalidate cache if cache sector is in the range. | |||||
m_vol->cacheInvalidate(); | m_vol->cacheInvalidate(); | ||||
} | } | ||||
if (!m_vol->writeSectors(sector, src, nSector)) { | if (!m_vol->writeSectors(sector, src, nSector)) { |
*/ | */ | ||||
#define FREE_STACK_CPP | #define FREE_STACK_CPP | ||||
#include "FreeStack.h" | #include "FreeStack.h" | ||||
#if HAS_UNUSED_STACK | |||||
#ifdef __AVR__ | |||||
inline char* heapEnd() { | |||||
#if defined(HAS_UNUSED_STACK) && HAS_UNUSED_STACK | |||||
//------------------------------------------------------------------------------ | |||||
inline char* stackBegin() { | |||||
#if defined(__AVR__) | |||||
return __brkval ? __brkval : &__bss_end; | return __brkval ? __brkval : &__bss_end; | ||||
} | |||||
inline char* stackPointer() { | |||||
return reinterpret_cast<char*>(SP); | |||||
} | |||||
#elif defined(__IMXRT1062__) | |||||
return reinterpret_cast<char*>(&_ebss); | |||||
#elif defined(__arm__) | #elif defined(__arm__) | ||||
inline char* heapEnd() { | |||||
return reinterpret_cast<char*>(sbrk(0)); | return reinterpret_cast<char*>(sbrk(0)); | ||||
#else // defined(__AVR__) | |||||
#error "undefined stackBegin" | |||||
#endif // defined(__AVR__) | |||||
} | } | ||||
//------------------------------------------------------------------------------ | |||||
inline char* stackPointer() { | inline char* stackPointer() { | ||||
#if defined(__AVR__) | |||||
return reinterpret_cast<char*>(SP); | |||||
#elif defined(__arm__) | |||||
register uint32_t sp asm("sp"); | register uint32_t sp asm("sp"); | ||||
return reinterpret_cast<char*>(sp); | return reinterpret_cast<char*>(sp); | ||||
#else // defined(__AVR__) | |||||
#error "undefined stackPointer" | |||||
#endif // defined(__AVR__) | |||||
} | } | ||||
#endif // #elif define(__arm__) | |||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
/** Stack fill pattern. */ | /** Stack fill pattern. */ | ||||
const char FILL = 0x55; | const char FILL = 0x55; | ||||
void FillStack() { | void FillStack() { | ||||
char* p = heapEnd(); | |||||
char* p = stackBegin(); | |||||
char* top = stackPointer(); | char* top = stackPointer(); | ||||
while (p < top) { | while (p < top) { | ||||
*p++ = FILL; | *p++ = FILL; | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
// May fail if malloc or new is used. | // May fail if malloc or new is used. | ||||
int UnusedStack() { | int UnusedStack() { | ||||
char* h = heapEnd(); | |||||
char* h = stackBegin(); | |||||
char* top = stackPointer(); | char* top = stackPointer(); | ||||
int n; | int n; | ||||
} | } | ||||
return n; | return n; | ||||
} | } | ||||
#endif // HAS_UNUSED_STACK | |||||
#endif // defined(HAS_UNUSED_STACK) && HAS_UNUSED_STACK |
inline int FreeStack() { | inline int FreeStack() { | ||||
return System.freeMemory(); | return System.freeMemory(); | ||||
} | } | ||||
#elif defined(__arm__) && !defined(__IMXRT1062__) | |||||
#elif defined(__IMXRT1062__) | |||||
#define HAS_UNUSED_STACK 1 | |||||
extern uint8_t _ebss; | |||||
inline int FreeStack() { | |||||
register uint32_t sp asm("sp"); | |||||
return reinterpret_cast<char*>(sp) - reinterpret_cast<char*>(&_ebss); | |||||
} | |||||
#elif defined(__arm__) | |||||
#define HAS_UNUSED_STACK 1 | #define HAS_UNUSED_STACK 1 | ||||
extern "C" char* sbrk(int incr); | extern "C" char* sbrk(int incr); | ||||
inline int FreeStack() { | inline int FreeStack() { | ||||
return 0; | return 0; | ||||
} | } | ||||
#endif // defined(__AVR__) || defined(DOXYGEN) | #endif // defined(__AVR__) || defined(DOXYGEN) | ||||
#ifdef HAS_UNUSED_STACK | |||||
#if defined(HAS_UNUSED_STACK) || defined(DOXYGEN) | |||||
/** Fill stack with 0x55 pattern */ | /** Fill stack with 0x55 pattern */ | ||||
void FillStack(); | void FillStack(); | ||||
/** | /** | ||||
#define HAS_UNUSED_STACK 0 | #define HAS_UNUSED_STACK 0 | ||||
inline void FillStack() {} | inline void FillStack() {} | ||||
inline int UnusedStack() {return 0;} | inline int UnusedStack() {return 0;} | ||||
#endif // HAS_UNUSED_STACK | |||||
#endif // defined(HAS_UNUSED_STACK) | |||||
#endif // FreeStack_h | #endif // FreeStack_h |
const uint8_t CMD9 = 0X09; | const uint8_t CMD9 = 0X09; | ||||
/** SEND_CID - read the card identification information (CID register) */ | /** SEND_CID - read the card identification information (CID register) */ | ||||
const uint8_t CMD10 = 0X0A; | const uint8_t CMD10 = 0X0A; | ||||
/** VOLTAGE_SWITCH -Switch to 1.8V bus signaling level. */ | |||||
const uint8_t CMD11 = 0X0B; | |||||
/** STOP_TRANSMISSION - end multiple sector read sequence */ | /** STOP_TRANSMISSION - end multiple sector read sequence */ | ||||
const uint8_t CMD12 = 0X0C; | const uint8_t CMD12 = 0X0C; | ||||
/** SEND_STATUS - read the card status register */ | /** SEND_STATUS - read the card status register */ |
const uint32_t CMD10_XFERTYP = SDHC_XFERTYP_CMDINX(CMD10) | CMD_RESP_R2; | const uint32_t CMD10_XFERTYP = SDHC_XFERTYP_CMDINX(CMD10) | CMD_RESP_R2; | ||||
const uint32_t CMD11_XFERTYP = SDHC_XFERTYP_CMDINX(CMD11) | CMD_RESP_R1; | |||||
const uint32_t CMD12_XFERTYP = SDHC_XFERTYP_CMDINX(CMD12) | CMD_RESP_R1b | | const uint32_t CMD12_XFERTYP = SDHC_XFERTYP_CMDINX(CMD12) | CMD_RESP_R1b | | ||||
SDHC_XFERTYP_CMDTYP(3); | SDHC_XFERTYP_CMDTYP(3); | ||||