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

Timestamp SDFS does not work correctly with 2GB SD card. #6981

Closed
6 tasks done
NicoZuid opened this issue Jan 4, 2020 · 2 comments · Fixed by #6985
Closed
6 tasks done

Timestamp SDFS does not work correctly with 2GB SD card. #6981

NicoZuid opened this issue Jan 4, 2020 · 2 comments · Fixed by #6985

Comments

@NicoZuid
Copy link

NicoZuid commented Jan 4, 2020

Basic Infos

  • This issue complies with the issue POLICY doc.
  • I have read the documentation at readthedocs and the issue is not addressed there.
  • I have tested that the issue is present in current master branch (aka latest git).
  • I have searched the issue tracker for a similar issue.
  • If there is a stack dump, I have decoded it.
  • I have filled out all fields below.

Platform

  • Hardware: [ESP-12]
  • Core Version: [2.6.3]
  • Development Env: [Arduino IDE]
  • Operating System: [Windows]

Settings in IDE

  • Module: [Wemos D1 r2 or mini]
  • Flash Mode: [?]
  • Flash Size: [4MB]
  • lwip Variant: [v2 Lower Memory]
  • Reset Method: [?}
  • Flash Frequency: [40Mhz]
  • CPU Frequency: [80Mhz]
  • Upload Using: [SERIAL]
  • Upload Speed: [115200)

Problem Description

Timestamp SDFS does not work correctly with 2GB SD card.
(I currently have no hardware available for larger SD cards)

dir.next also gives the "Volume information entry"
Timestamp not set:
dir.fileTime () returns 1970-01-01 00:00:00 always
file.getLastWrite () returns 2000-01-01 1:00:00 or correct time if set.

fsInfo.pageSize returns 0 (zero)

MCVE Sketch

#include <Arduino.h>

#include <FS.h>
#include <SDFS.h>
#include <time.h>
#include <ESP8266WiFi.h>

#ifndef STASSID
#define STASSID "groen4ZUID"
#define STAPSK  "pasword"
#endif

const char *ssid = STASSID;
const char *pass = STAPSK;

long timezone = 1;
byte daysavetime = 0;


bool getLocalTime(struct tm * info, uint32_t ms) {
  uint32_t count = ms / 10;
  time_t now;

  time(&now);
  localtime_r(&now, info);

  if (info->tm_year > (2016 - 1900)) {
    return true;
  }

  while (count--) {
    delay(10);
    time(&now);
    localtime_r(&now, info);
    if (info->tm_year > (2016 - 1900)) {
      return true;
    }
  }
  return false;
}


void listDir(const char * dirname) {
  Serial.printf("Listing directory: %s\n", dirname);

  Dir root = SDFS.openDir(dirname);

  while (root.next()) {
    File file = root.openFile("r");
    Serial.print("  FILE: ");
    Serial.print(root.fileName());
    Serial.print("  SIZE: ");
    Serial.print(root.fileSize());
    Serial.print("  SIZE: ");
    Serial.print(file.size());
    time_t t = file.getLastWrite();
    struct tm * tmstruct = localtime(&t);
    Serial.printf("  LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec);

    Serial.print("  FILE: ");
    Serial.print(root.fileName());
    Serial.print("  SIZE: ");
    Serial.print(root.fileSize());
    Serial.print("  SIZE: ");
    Serial.print(file.size());
    t = root.fileTime();
    tmstruct = localtime(&t);
    Serial.printf("  FILE TIME: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec);
    
    file.close();
  }

}
void readFile(const char * path) {
  Serial.printf("Reading file: %s\n", path);

  File file = SDFS.open(path, "r");
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }

  Serial.print("Read from file: ");
  while (file.available()) {
    Serial.write(file.read());
  }
  file.close();
}

void writeFile(const char * path, const char * message) {
  Serial.printf("Writing file: %s\n", path);

  File file = SDFS.open(path, "w");
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  if (file.print(message)) {
    Serial.println("File written");
  } else {
    Serial.println("Write failed");
  }
  file.close();
}

void appendFile(const char * path, const char * message) {
  Serial.printf("Appending to file: %s\n", path);

  File file = SDFS.open(path, "a");
  if (!file) {
    Serial.println("Failed to open file for appending");
    return;
  }
  if (file.print(message)) {
    Serial.println("Message appended");
  } else {
    Serial.println("Append failed");
  }
  file.close();
}

void renameFile(const char * path1, const char * path2) {
  Serial.printf("Renaming file %s to %s\n", path1, path2);
  if (SDFS.rename(path1, path2)) {
    Serial.println("File renamed");
  } else {
    Serial.println("Rename failed");
  }
}

void deleteFile(const char * path) {
  Serial.printf("Deleting file: %s\n", path);
  if (SDFS.remove(path)) {
    Serial.println("File deleted");
  } else {
    Serial.println("Delete failed");
  }
}

void setup() {
  Serial.begin(115200);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println("Contacting Time Server");
  configTime(3600 * timezone, daysavetime * 3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
  struct tm tmstruct ;
  delay(2000);
  tmstruct.tm_year = 0;
  getLocalTime(&tmstruct, 5000);
  Serial.printf("\nNow is : %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct.tm_year) + 1900, (tmstruct.tm_mon) + 1, tmstruct.tm_mday, tmstruct.tm_hour, tmstruct.tm_min, tmstruct.tm_sec);
  Serial.println("");
  //Serial.println("Formatting SDFS filesystem");
  //SDFS.format();
  Serial.println("Mount SDFS");
  if (!SDFS.begin()) {
    Serial.println("SDFS mount failed");
    return;
  }
  listDir("/");
  deleteFile("/hello.txt");
  writeFile("/hello.txt", "Hello ");
  appendFile("/hello.txt", "World!\n");
  listDir("/");

  Serial.println("The timestamp should be valid above");

  Serial.println("Now unmount and remount and perform the same operation.");
  Serial.println("Timestamp should be valid, data should be good.");

  Serial.println("Now mount it");
  if (!SDFS.begin()) {
    Serial.println("SDFS mount failed");
    return;
  }
  readFile("/hello.txt");
  listDir("/");

  Serial.print("Wait a moment");
  delay(55000);
  readFile("/hello.txt");
  listDir("/");


  //FSInfo64 fsInfo;  // 2gb SD false info!
  FSInfo fsInfo;
  SDFS.info(fsInfo);
  Serial.print(F("FS Bytes used: "));
  Serial.println(formatSize(fsInfo.usedBytes));
  Serial.print(F("FS Bytes total: "));
  Serial.println(formatSize(fsInfo.totalBytes));
  Serial.print(F("FS block size: "));
  Serial.println(fsInfo.blockSize);
  Serial.print(F("FS page size: "));
  Serial.println(fsInfo.pageSize);


  SDFS.end();
}
//format size  =====================================================
String formatSize(size_t bytes) {
  if (bytes < 1024) {
    return String(bytes) + "  B";
  } else if (bytes < (1024 * 1024)) {
    return String(bytes / 1024.0) + " KB";
  } else if (bytes < (1024 * 1024 * 1024)) {
    return String(bytes / 1024.0 / 1024.0) + " MB";
  } else {
    return String(bytes / 1024.0 / 1024.0 / 1024.0) + " GB";
  }
}
//===================================================================
void loop() { }

Debug Messages

SDFS_Timestamp


Connecting to groen4ZUID
........WiFi connected
IP address: 
192.168.2.4
Contacting Time Server

Now is : 2020-01-04 06:33:15

Mount SDFS
Listing directory: /
  FILE: System Volume Information  SIZE: 0  SIZE: 0  LAST WRITE: 2020-01-03 18:45:00
  FILE: System Volume Information  SIZE: 0  SIZE: 0  FILE TIME: 1970-01-01 00:00:00
  FILE: hello.txt  SIZE: 13  SIZE: 13  LAST WRITE: 2000-01-01 01:00:00
  FILE: hello.txt  SIZE: 13  SIZE: 13  FILE TIME: 1970-01-01 00:00:00
  FILE: Windows.txt  SIZE: 13  SIZE: 13  LAST WRITE: 2020-01-04 06:29:58
  FILE: Windows.txt  SIZE: 13  SIZE: 13  FILE TIME: 1970-01-01 00:00:00
Deleting file: /hello.txt
File deleted
Writing file: /hello.txt
File written
Appending to file: /hello.txt
Message appended
Listing directory: /
  FILE: System Volume Information  SIZE: 0  SIZE: 0  LAST WRITE: 2020-01-03 18:45:00
  FILE: System Volume Information  SIZE: 0  SIZE: 0  FILE TIME: 1970-01-01 00:00:00
  FILE: hello.txt  SIZE: 13  SIZE: 13  LAST WRITE: 2000-01-01 01:00:00
  FILE: hello.txt  SIZE: 13  SIZE: 13  FILE TIME: 1970-01-01 00:00:00
  FILE: Windows.txt  SIZE: 13  SIZE: 13  LAST WRITE: 2020-01-04 06:29:58
  FILE: Windows.txt  SIZE: 13  SIZE: 13  FILE TIME: 1970-01-01 00:00:00
The timestamp should be valid above
Now unmount and remount and perform the same operation.
Timestamp should be valid, data should be good.
Now mount it
Reading file: /hello.txt
Read from file: Hello World!
Listing directory: /
  FILE: System Volume Information  SIZE: 0  SIZE: 0  LAST WRITE: 2020-01-03 18:45:00
  FILE: System Volume Information  SIZE: 0  SIZE: 0  FILE TIME: 1970-01-01 00:00:00
  FILE: hello.txt  SIZE: 13  SIZE: 13  LAST WRITE: 2000-01-01 01:00:00
  FILE: hello.txt  SIZE: 13  SIZE: 13  FILE TIME: 1970-01-01 00:00:00
  FILE: Windows.txt  SIZE: 13  SIZE: 13  LAST WRITE: 2020-01-04 06:29:58
  FILE: Windows.txt  SIZE: 13  SIZE: 13  FILE TIME: 1970-01-01 00:00:00
Wait a momentReading file: /hello.txt
Read from file: Hello World!
Listing directory: /
  FILE: System Volume Information  SIZE: 0  SIZE: 0  LAST WRITE: 2020-01-03 18:45:00
  FILE: System Volume Information  SIZE: 0  SIZE: 0  FILE TIME: 1970-01-01 00:00:00
  FILE: hello.txt  SIZE: 13  SIZE: 13  LAST WRITE: 2000-01-01 01:00:00
  FILE: hello.txt  SIZE: 13  SIZE: 13  FILE TIME: 1970-01-01 00:00:00
  FILE: Windows.txt  SIZE: 13  SIZE: 13  LAST WRITE: 2020-01-04 06:29:58
  FILE: Windows.txt  SIZE: 13  SIZE: 13  FILE TIME: 1970-01-01 00:00:00
FS Bytes used: 160.00 KB
FS Bytes total: 1.84 GB
FS block size: 32768
FS page size: 0

@earlephilhower
Copy link
Collaborator

Thanks for the detailed report. It's funny, I can't even find new uSD cards under 4GB (but have used a 128MB one leftover from a Palm PDA for testing).

The only difference between 2GB and larger cards would be the FAT, not the directory/LFN stuff, so I think that's immaterial here.

The "System Volume Information" really is on the card, it's not making it up. Looks like the card was used on a Windows PC at one point. SDFS isn't making that up, so I don't see a problem there. The attribute should be HIDDEN,SYSTEM, but there's no concept of attributes in the Arduino File so it's kind of a black box.

fs page size is 0 because it doesn't really make any sense. There are no pages on a SD card, it has 512b accessible sectors. Are you suggesting it should be set to the block size (FAT allocation size)?

File access time, I'll have to check. I don't think the SD would want to update it (wear out the flash on repeated reads causing multiple directory rewrites), but I'll take a look.

earlephilhower added a commit to earlephilhower/Arduino that referenced this issue Jan 4, 2020
Forgot to add a Dir->fileTime override, resulting in it always returning
(time_t)0, or Jan 1, 1970.

Add the override, returning the proper lastWriteTime.

Fixes esp8266#6981
@earlephilhower
Copy link
Collaborator

Well, pretty obvious. I forgot to provide the Dir->fileTime callback. I was even reading out the file time and caching it in the Dir structure...just never returning it. PR #6985 should fix this.

earlephilhower added a commit that referenced this issue Jan 4, 2020
Forgot to add a Dir->fileTime override, resulting in it always returning
(time_t)0, or Jan 1, 1970.

Add the override, returning the proper lastWriteTime.

Fixes #6981
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants