greiman / SdFat

Arduino FAT16/FAT32 exFAT Library
MIT License
1.07k stars 502 forks source link

File read returns -1 **Error at cacheSafeRead** #369

Closed bhupiister closed 2 years ago

bhupiister commented 2 years ago

Using library version: Latest(Master) Board: ESP32 (M5 Core2)

I am reading a .wav file of roughly around 1-2 MB and uploading it to server. While most of the time it works, but on some files i get this error and read operation returns -1. On further investigating i found the exact line where it happens. If i reinitialize SD card and try again, it gets successful.

DBG_FAIL: FatFile.cpp.972

[319321][V][ssl_client.cpp:351] send_ssl_data(): Writing HTTP request with 2048 bytes...
[319343][V][ssl_client.cpp:351] send_ssl_data(): Writing HTTP request with 2048 bytes...
Uploaded 40%
[319357][V][ssl_client.cpp:351] send_ssl_data(): Writing HTTP request with 2048 bytes...
[319368][V][ssl_client.cpp:351] send_ssl_data(): Writing HTTP request with 2048 bytes...
[319382][V][ssl_client.cpp:351] send_ssl_data(): Writing HTTP request with 2048 bytes...
[319393][V][ssl_client.cpp:351] send_ssl_data(): Writing HTTP request with 2048 bytes...
DBG_FAIL: FatFile.cpp.972
[319402][V][ssl_client.cpp:351] send_ssl_data(): Writing HTTP request with -1 bytes...
[319485][V][ssl_client.cpp:311] stop_ssl_socket(): Cleaning SSL connection.

code at FatFile.cpp line 972

n = ns << m_vol->bytesPerSectorShift();
if (!m_vol->cacheSafeRead(sector, dst, ns))
{
  DBG_FAIL_MACRO;
  goto fail;
}

My Read code

  int available = req->fileSize;
  size_t byteRead = 0;
  int bufLen = Signer.getCfg()->gcs.upload_buffer_size;
  if (bufLen < 512)
      bufLen = 512;

  if (bufLen > 1024 * 16)
      bufLen = 1024 * 16;

  uint8_t *buf = (uint8_t *)ut->newP(bufLen + 1);
  size_t read = 0;

  while (available)
  {
      if (available > bufLen)
          available = bufLen;
      read = ut->mbfs->read(mbfs_type req->storageType, buf, available);
      if (read == -1)
      {
          Serial.println("File read error in GCS.cpp");
      }
      byteRead += read;
      reportUploadProgress(fbdo, req, byteRead);
      if (fbdo->tcpClient.stream()->write(buf, read) != read)
      {
          fbdo->_ss.http_code = FIREBASE_ERROR_UPLOAD_DATA_ERRROR;
          fbdo->closeSession();
          break;
      }

      available = ut->mbfs->available(mbfs_type req->storageType);
  }
  ut->delP(&buf);
greiman commented 2 years ago

I can't help since it's a intermittent hardware read error and I can't guess what causes it.

On ESP32 this could be due to a glitch or noise on the SPI bus. I have had poor luck diagnosing ESP32 problems remotely.

bhupiister commented 2 years ago

Could this error be remotely related to available heap size? This is kind of show stopper for me. I recently shifted to SDFat because of its feature to work on half duplex mode as SPI bus is shared by tft Display as well and its much faster than standard SD library.

bhupiister commented 2 years ago

@greiman I think i have solved the problem. I am not sure though. When you said that SPI bus may have glitch or noise, it came to my mind that since display and SD card are sharing same SPI bus, it can be the case that they both are interfering. Since my UI updates progress bar when uploading files. I created semaphore between them and made sure only one of them access the SPI bus at a time and i think that made the problem go away.