Fix several SD card issues (#4876)
- File might not eval to false if opened with write/append and SD is gone - Allow card to be formatted if FAT partition was not found - Mark card as gone in certain situations - Fix several logic errors in low level SD API
This commit is contained in:
parent
3fe7c2e8cd
commit
1cf1c8eb79
@ -25,7 +25,7 @@ using namespace fs;
|
|||||||
|
|
||||||
size_t File::write(uint8_t c)
|
size_t File::write(uint8_t c)
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ size_t File::write(uint8_t c)
|
|||||||
|
|
||||||
time_t File::getLastWrite()
|
time_t File::getLastWrite()
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ time_t File::getLastWrite()
|
|||||||
|
|
||||||
size_t File::write(const uint8_t *buf, size_t size)
|
size_t File::write(const uint8_t *buf, size_t size)
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ size_t File::write(const uint8_t *buf, size_t size)
|
|||||||
|
|
||||||
int File::available()
|
int File::available()
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ int File::available()
|
|||||||
|
|
||||||
int File::read()
|
int File::read()
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ int File::read()
|
|||||||
|
|
||||||
size_t File::read(uint8_t* buf, size_t size)
|
size_t File::read(uint8_t* buf, size_t size)
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ size_t File::read(uint8_t* buf, size_t size)
|
|||||||
|
|
||||||
int File::peek()
|
int File::peek()
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ int File::peek()
|
|||||||
|
|
||||||
void File::flush()
|
void File::flush()
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ void File::flush()
|
|||||||
|
|
||||||
bool File::seek(uint32_t pos, SeekMode mode)
|
bool File::seek(uint32_t pos, SeekMode mode)
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ bool File::seek(uint32_t pos, SeekMode mode)
|
|||||||
|
|
||||||
size_t File::position() const
|
size_t File::position() const
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ size_t File::position() const
|
|||||||
|
|
||||||
size_t File::size() const
|
size_t File::size() const
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,12 +140,12 @@ void File::close()
|
|||||||
|
|
||||||
File::operator bool() const
|
File::operator bool() const
|
||||||
{
|
{
|
||||||
return !!_p;
|
return _p != nullptr && *_p != false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* File::name() const
|
const char* File::name() const
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ const char* File::name() const
|
|||||||
//to implement
|
//to implement
|
||||||
boolean File::isDirectory(void)
|
boolean File::isDirectory(void)
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return _p->isDirectory();
|
return _p->isDirectory();
|
||||||
@ -163,7 +163,7 @@ boolean File::isDirectory(void)
|
|||||||
|
|
||||||
File File::openNextFile(const char* mode)
|
File File::openNextFile(const char* mode)
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return File();
|
return File();
|
||||||
}
|
}
|
||||||
return _p->openNextFile(mode);
|
return _p->openNextFile(mode);
|
||||||
@ -171,7 +171,7 @@ File File::openNextFile(const char* mode)
|
|||||||
|
|
||||||
void File::rewindDirectory(void)
|
void File::rewindDirectory(void)
|
||||||
{
|
{
|
||||||
if (!_p) {
|
if (!*this) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_p->rewindDirectory();
|
_p->rewindDirectory();
|
||||||
|
@ -22,7 +22,7 @@ using namespace fs;
|
|||||||
|
|
||||||
SDFS::SDFS(FSImplPtr impl): FS(impl), _pdrv(0xFF) {}
|
SDFS::SDFS(FSImplPtr impl): FS(impl), _pdrv(0xFF) {}
|
||||||
|
|
||||||
bool SDFS::begin(uint8_t ssPin, SPIClass &spi, uint32_t frequency, const char * mountpoint, uint8_t max_files)
|
bool SDFS::begin(uint8_t ssPin, SPIClass &spi, uint32_t frequency, const char * mountpoint, uint8_t max_files, bool format_if_empty)
|
||||||
{
|
{
|
||||||
if(_pdrv != 0xFF) {
|
if(_pdrv != 0xFF) {
|
||||||
return true;
|
return true;
|
||||||
@ -35,7 +35,7 @@ bool SDFS::begin(uint8_t ssPin, SPIClass &spi, uint32_t frequency, const char *
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!sdcard_mount(_pdrv, mountpoint, max_files)){
|
if(!sdcard_mount(_pdrv, mountpoint, max_files, format_if_empty)){
|
||||||
sdcard_unmount(_pdrv);
|
sdcard_unmount(_pdrv);
|
||||||
sdcard_uninit(_pdrv);
|
sdcard_uninit(_pdrv);
|
||||||
_pdrv = 0xFF;
|
_pdrv = 0xFF;
|
||||||
|
@ -29,7 +29,7 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
SDFS(FSImplPtr impl);
|
SDFS(FSImplPtr impl);
|
||||||
bool begin(uint8_t ssPin=SS, SPIClass &spi=SPI, uint32_t frequency=4000000, const char * mountpoint="/sd", uint8_t max_files=5);
|
bool begin(uint8_t ssPin=SS, SPIClass &spi=SPI, uint32_t frequency=4000000, const char * mountpoint="/sd", uint8_t max_files=5, bool format_if_empty=false);
|
||||||
void end();
|
void end();
|
||||||
sdcard_type_t cardType();
|
sdcard_type_t cardType();
|
||||||
uint64_t cardSize();
|
uint64_t cardSize();
|
||||||
|
@ -60,6 +60,31 @@ typedef struct {
|
|||||||
|
|
||||||
static ardu_sdcard_t* s_cards[FF_VOLUMES] = { NULL };
|
static ardu_sdcard_t* s_cards[FF_VOLUMES] = { NULL };
|
||||||
|
|
||||||
|
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
|
||||||
|
const char * fferr2str[] = {
|
||||||
|
"(0) Succeeded",
|
||||||
|
"(1) A hard error occurred in the low level disk I/O layer",
|
||||||
|
"(2) Assertion failed",
|
||||||
|
"(3) The physical drive cannot work",
|
||||||
|
"(4) Could not find the file",
|
||||||
|
"(5) Could not find the path",
|
||||||
|
"(6) The path name format is invalid",
|
||||||
|
"(7) Access denied due to prohibited access or directory full",
|
||||||
|
"(8) Access denied due to prohibited access",
|
||||||
|
"(9) The file/directory object is invalid",
|
||||||
|
"(10) The physical drive is write protected",
|
||||||
|
"(11) The logical drive number is invalid",
|
||||||
|
"(12) The volume has no work area",
|
||||||
|
"(13) There is no valid FAT volume",
|
||||||
|
"(14) The f_mkfs() aborted due to any problem",
|
||||||
|
"(15) Could not get a grant to access the volume within defined period",
|
||||||
|
"(16) The operation is rejected according to the file sharing policy",
|
||||||
|
"(17) LFN working buffer could not be allocated",
|
||||||
|
"(18) Number of open files > FF_FS_LOCK",
|
||||||
|
"(19) Given parameter is invalid"
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SD SPI
|
* SD SPI
|
||||||
* */
|
* */
|
||||||
@ -73,6 +98,9 @@ bool sdWait(uint8_t pdrv, int timeout)
|
|||||||
resp = s_cards[pdrv]->spi->transfer(0xFF);
|
resp = s_cards[pdrv]->spi->transfer(0xFF);
|
||||||
} while (resp == 0x00 && (millis() - start) < (unsigned int)timeout);
|
} while (resp == 0x00 && (millis() - start) < (unsigned int)timeout);
|
||||||
|
|
||||||
|
if (!resp) {
|
||||||
|
log_w("Wait Failed");
|
||||||
|
}
|
||||||
return (resp > 0x00);
|
return (resp > 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +119,10 @@ bool sdSelectCard(uint8_t pdrv)
|
|||||||
{
|
{
|
||||||
ardu_sdcard_t * card = s_cards[pdrv];
|
ardu_sdcard_t * card = s_cards[pdrv];
|
||||||
digitalWrite(card->ssPin, LOW);
|
digitalWrite(card->ssPin, LOW);
|
||||||
sdWait(pdrv, 300);
|
bool s = sdWait(pdrv, 300);
|
||||||
|
if (!s) {
|
||||||
|
log_e("Select Failed");
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,10 +136,11 @@ char sdCommand(uint8_t pdrv, char cmd, unsigned int arg, unsigned int* resp)
|
|||||||
token = sdCommand(pdrv, APP_CMD, 0, NULL);
|
token = sdCommand(pdrv, APP_CMD, 0, NULL);
|
||||||
sdDeselectCard(pdrv);
|
sdDeselectCard(pdrv);
|
||||||
if (token > 1) {
|
if (token > 1) {
|
||||||
return token;
|
break;
|
||||||
}
|
}
|
||||||
if(!sdSelectCard(pdrv)) {
|
if(!sdSelectCard(pdrv)) {
|
||||||
return 0xFF;
|
token = 0xFF;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +191,10 @@ char sdCommand(uint8_t pdrv, char cmd, unsigned int arg, unsigned int* resp)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (token == 0xFF) {
|
||||||
|
log_e("Card Failed! cmd: 0x%02x", cmd);
|
||||||
|
card->status = STA_NOINIT;
|
||||||
|
}
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +250,7 @@ bool sdReadSector(uint8_t pdrv, char* buffer, unsigned long long sector)
|
|||||||
{
|
{
|
||||||
for (int f = 0; f < 3; f++) {
|
for (int f = 0; f < 3; f++) {
|
||||||
if(!sdSelectCard(pdrv)) {
|
if(!sdSelectCard(pdrv)) {
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
if (!sdCommand(pdrv, READ_BLOCK_SINGLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) {
|
if (!sdCommand(pdrv, READ_BLOCK_SINGLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) {
|
||||||
bool success = sdReadBytes(pdrv, buffer, 512);
|
bool success = sdReadBytes(pdrv, buffer, 512);
|
||||||
@ -235,7 +270,7 @@ bool sdReadSectors(uint8_t pdrv, char* buffer, unsigned long long sector, int co
|
|||||||
{
|
{
|
||||||
for (int f = 0; f < 3;) {
|
for (int f = 0; f < 3;) {
|
||||||
if(!sdSelectCard(pdrv)) {
|
if(!sdSelectCard(pdrv)) {
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sdCommand(pdrv, READ_BLOCK_MULTIPLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) {
|
if (!sdCommand(pdrv, READ_BLOCK_MULTIPLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) {
|
||||||
@ -271,7 +306,7 @@ bool sdWriteSector(uint8_t pdrv, const char* buffer, unsigned long long sector)
|
|||||||
{
|
{
|
||||||
for (int f = 0; f < 3; f++) {
|
for (int f = 0; f < 3; f++) {
|
||||||
if(!sdSelectCard(pdrv)) {
|
if(!sdSelectCard(pdrv)) {
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
if (!sdCommand(pdrv, WRITE_BLOCK_SINGLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) {
|
if (!sdCommand(pdrv, WRITE_BLOCK_SINGLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) {
|
||||||
char token = sdWriteBytes(pdrv, buffer, 0xFE);
|
char token = sdWriteBytes(pdrv, buffer, 0xFE);
|
||||||
@ -307,12 +342,12 @@ bool sdWriteSectors(uint8_t pdrv, const char* buffer, unsigned long long sector,
|
|||||||
for (int f = 0; f < 3;) {
|
for (int f = 0; f < 3;) {
|
||||||
if (card->type != CARD_MMC) {
|
if (card->type != CARD_MMC) {
|
||||||
if (sdTransaction(pdrv, SET_WR_BLK_ERASE_COUNT, currentCount, NULL)) {
|
if (sdTransaction(pdrv, SET_WR_BLK_ERASE_COUNT, currentCount, NULL)) {
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!sdSelectCard(pdrv)) {
|
if(!sdSelectCard(pdrv)) {
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sdCommand(pdrv, WRITE_BLOCK_MULTIPLE, (card->type == CARD_SDHC) ? currentSector : currentSector << 9, NULL)) {
|
if (!sdCommand(pdrv, WRITE_BLOCK_MULTIPLE, (card->type == CARD_SDHC) ? currentSector : currentSector << 9, NULL)) {
|
||||||
@ -344,9 +379,8 @@ bool sdWriteSectors(uint8_t pdrv, const char* buffer, unsigned long long sector,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sdDeselectCard(pdrv);
|
|
||||||
|
|
||||||
if (token == 0x0A) {
|
if (token == 0x0A) {
|
||||||
|
sdDeselectCard(pdrv);
|
||||||
unsigned int writtenBlocks = 0;
|
unsigned int writtenBlocks = 0;
|
||||||
if (card->type != CARD_MMC && sdSelectCard(pdrv)) {
|
if (card->type != CARD_MMC && sdSelectCard(pdrv)) {
|
||||||
if (!sdCommand(pdrv, SEND_NUM_WR_BLOCKS, 0, NULL)) {
|
if (!sdCommand(pdrv, SEND_NUM_WR_BLOCKS, 0, NULL)) {
|
||||||
@ -365,7 +399,7 @@ bool sdWriteSectors(uint8_t pdrv, const char* buffer, unsigned long long sector,
|
|||||||
currentCount = count - writtenBlocks;
|
currentCount = count - writtenBlocks;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -380,7 +414,7 @@ unsigned long sdGetSectorsCount(uint8_t pdrv)
|
|||||||
{
|
{
|
||||||
for (int f = 0; f < 3; f++) {
|
for (int f = 0; f < 3; f++) {
|
||||||
if(!sdSelectCard(pdrv)) {
|
if(!sdSelectCard(pdrv)) {
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sdCommand(pdrv, SEND_CSD, 0, NULL)) {
|
if (!sdCommand(pdrv, SEND_CSD, 0, NULL)) {
|
||||||
@ -714,7 +748,7 @@ uint8_t sdcard_unmount(uint8_t pdrv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sdcard_mount(uint8_t pdrv, const char* path, uint8_t max_files)
|
bool sdcard_mount(uint8_t pdrv, const char* path, uint8_t max_files, bool format_if_empty)
|
||||||
{
|
{
|
||||||
ardu_sdcard_t * card = s_cards[pdrv];
|
ardu_sdcard_t * card = s_cards[pdrv];
|
||||||
if(pdrv >= FF_VOLUMES || card == NULL){
|
if(pdrv >= FF_VOLUMES || card == NULL){
|
||||||
@ -739,10 +773,26 @@ bool sdcard_mount(uint8_t pdrv, const char* path, uint8_t max_files)
|
|||||||
|
|
||||||
FRESULT res = f_mount(fs, drv, 1);
|
FRESULT res = f_mount(fs, drv, 1);
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
log_e("f_mount failed 0x(%x)", res);
|
log_e("f_mount failed: %s", fferr2str[res]);
|
||||||
|
if(res == 13 && format_if_empty){
|
||||||
|
BYTE work[FF_MAX_SS];
|
||||||
|
res = f_mkfs(drv, FM_ANY, 0, work, sizeof(work));
|
||||||
|
if (res != FR_OK) {
|
||||||
|
log_e("f_mkfs failed: %s", fferr2str[res]);
|
||||||
esp_vfs_fat_unregister_path(path);
|
esp_vfs_fat_unregister_path(path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
res = f_mount(fs, drv, 1);
|
||||||
|
if (res != FR_OK) {
|
||||||
|
log_e("f_mount failed: %s", fferr2str[res]);
|
||||||
|
esp_vfs_fat_unregister_path(path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
esp_vfs_fat_unregister_path(path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
AcquireSPI lock(card);
|
AcquireSPI lock(card);
|
||||||
card->sectors = sdGetSectorsCount(pdrv);
|
card->sectors = sdGetSectorsCount(pdrv);
|
||||||
return true;
|
return true;
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
uint8_t sdcard_init(uint8_t cs, SPIClass * spi, int hz);
|
uint8_t sdcard_init(uint8_t cs, SPIClass * spi, int hz);
|
||||||
uint8_t sdcard_uninit(uint8_t pdrv);
|
uint8_t sdcard_uninit(uint8_t pdrv);
|
||||||
|
|
||||||
bool sdcard_mount(uint8_t pdrv, const char* path, uint8_t max_files);
|
bool sdcard_mount(uint8_t pdrv, const char* path, uint8_t max_files, bool format_if_empty);
|
||||||
uint8_t sdcard_unmount(uint8_t pdrv);
|
uint8_t sdcard_unmount(uint8_t pdrv);
|
||||||
|
|
||||||
sdcard_type_t sdcard_type(uint8_t pdrv);
|
sdcard_type_t sdcard_type(uint8_t pdrv);
|
||||||
|
@ -35,7 +35,7 @@ SDMMCFS::SDMMCFS(FSImplPtr impl)
|
|||||||
: FS(impl), _card(NULL)
|
: FS(impl), _card(NULL)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool SDMMCFS::begin(const char * mountpoint, bool mode1bit)
|
bool SDMMCFS::begin(const char * mountpoint, bool mode1bit, bool format_if_mount_failed)
|
||||||
{
|
{
|
||||||
if(_card) {
|
if(_card) {
|
||||||
return true;
|
return true;
|
||||||
@ -68,7 +68,7 @@ bool SDMMCFS::begin(const char * mountpoint, bool mode1bit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||||
.format_if_mount_failed = false,
|
.format_if_mount_failed = format_if_mount_failed,
|
||||||
.max_files = 5,
|
.max_files = 5,
|
||||||
.allocation_unit_size = 0
|
.allocation_unit_size = 0
|
||||||
};
|
};
|
||||||
|
@ -29,7 +29,7 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
SDMMCFS(FSImplPtr impl);
|
SDMMCFS(FSImplPtr impl);
|
||||||
bool begin(const char * mountpoint="/sdcard", bool mode1bit=false);
|
bool begin(const char * mountpoint="/sdcard", bool mode1bit=false, bool format_if_mount_failed=false);
|
||||||
void end();
|
void end();
|
||||||
sdcard_type_t cardType();
|
sdcard_type_t cardType();
|
||||||
uint64_t cardSize();
|
uint64_t cardSize();
|
||||||
|
Loading…
Reference in New Issue
Block a user