Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advanced SD card reliability configuration #25340

Merged
merged 12 commits into from
Aug 13, 2023
66 changes: 45 additions & 21 deletions Marlin/src/HAL/STM32/msc_sd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@
#define BLOCK_SIZE 512
#define PRODUCT_ID 0x29

#ifndef SD_MULTIBLOCK_RETRY_CNT
#define SD_MULTIBLOCK_RETRY_CNT 1
#elif SD_MULTIBLOCK_RETRY_CNT < 1
#error "SD_MULTIBLOCK_RETRY_CNT must be greater than or equal to 1."
#endif

class Sd2CardUSBMscHandler : public USBMscHandler {
public:
DiskIODriver* diskIODriver() {
Expand All @@ -58,44 +64,62 @@ class Sd2CardUSBMscHandler : public USBMscHandler {
// single block
if (blkLen == 1) {
hal.watchdog_refresh();
sd2card->writeBlock(blkAddr, pBuf);
return true;
return sd2card->writeBlock(blkAddr, pBuf);
}

// multi block optimization
sd2card->writeStart(blkAddr, blkLen);
while (blkLen--) {
hal.watchdog_refresh();
sd2card->writeData(pBuf);
pBuf += BLOCK_SIZE;
bool done = false;
for (uint16_t rcount = SD_MULTIBLOCK_RETRY_CNT; !done && rcount--;) {
uint8_t *cBuf = pBuf;
sd2card->writeStart(blkAddr);
bool okay = true; // Assume success
for (uint32 i = blkLen; i--;) {
hal.watchdog_refresh();
if (!sd2card->writeData(cBuf)) { // Write. Did it fail?
sd2card->writeStop(); // writeStop for new writeStart
okay = false; // Failed, so retry
break; // Go to while... below
}
cBuf += BLOCK_SIZE;
}
done = okay; // Done if no error occurred
}
sd2card->writeStop();
return true;

if (done) sd2card->writeStop();
return done;
}

bool Read(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) {
auto sd2card = diskIODriver();
// single block
if (blkLen == 1) {
hal.watchdog_refresh();
sd2card->readBlock(blkAddr, pBuf);
return true;
return sd2card->readBlock(blkAddr, pBuf);
}

// multi block optimization
sd2card->readStart(blkAddr);
while (blkLen--) {
hal.watchdog_refresh();
sd2card->readData(pBuf);
pBuf += BLOCK_SIZE;
bool done = false;
for (uint16_t rcount = SD_MULTIBLOCK_RETRY_CNT; !done && rcount--;) {
uint8_t *cBuf = pBuf;
sd2card->readStart(blkAddr);
bool okay = true; // Assume success
for (uint32 i = blkLen; i--;) {
hal.watchdog_refresh();
if (!sd2card->readData(cBuf)) { // Read. Did it fail?
sd2card->readStop(); // readStop for new readStart
okay = false; // Failed, so retry
break; // Go to while... below
}
cBuf += BLOCK_SIZE;
}
done = okay; // Done if no error occurred
}
sd2card->readStop();
return true;
}

bool IsReady() {
return diskIODriver()->isReady();
if (done) sd2card->readStop();
return done;
}

bool IsReady() { return diskIODriver()->isReady(); }
};

Sd2CardUSBMscHandler usbMscHandler;
Expand Down
Loading
Loading