ESP8266のSPIFFS+Reset/Restart


ESP8266ではSPIFFSと呼ばれるファイルシステムを使うことができます。
SPIFFSについてはこ ちらこ ちらで紹介されていますが、いずれもデータアップロードツールを使って
事前にファイルをアップロードし、アップロードしたファイルを読む内容です。

前回は単純にスケッチ内部でSPIFFS領域をフォーマットし、ファイルを読 み書きする方法を紹介しました。
そこで、Reset/RestartでSPIFFS領域が破棄されるのか、保持されるのか、以下のスケッチで確認してみました。
/*
* ESP.reset()/ESP.resart()でSPIFFS領域がクリアされるかどうかのテスト
*/
#include <ESP8266WiFi.h>
#include "FS.h"

//RTC memory(512Byte)の定義
struct {
  uint8_t data[512]; // User Data
} rtcData;

void listDir() {
  char cwdName[2];

  strcpy(cwdName,"/");
  Dir dir=SPIFFS.openDir(cwdName);
  while( dir.next()) {
    String fn, fs;
    fn = dir.fileName();
    fn.remove(0, 1);
    fs = String(dir.fileSize());
    Serial.println("<" + fn + "> size=" + fs);
  } // end while
}

void setup() {
  delay(1000);
  Serial.begin(115200);
  Serial.println();
  Serial.print("ESP.getResetReason()=");
  Serial.println(ESP.getResetReason());
  String resetReason = ESP.getResetReason();

  /*
  enum rst_reason {
  REANSON_DEFAULT_RST = 0, // ノーマルスタート。電源オンなど。
  REANSON_WDT_RST = 1, // ハードウェアウォッチドッグによるリセット
  REANSON_EXCEPTION_RST = 2, // 例外によるリセット。GPIO状態は変化しない
  REANSON_SOFT_WDT_RST = 3, // ソフトウェアウォッチドッグによるリセット。GPIO状態は変化しない
  REANSON_SOFT_RESTART = 4, // ソフトウェアによるリセット。GPIO状態は変化しない
  REANSON_DEEP_SLEEP_AWAKE= 5, // ディープスリープ復帰
  REANSON_EXT_SYS_RST = 6, // 外部要因(RSTピン)によるリセット。
  };
  */

  rst_info *prst = ESP.getResetInfoPtr();
  /*
  struct rst_info{
      uint32 reason;
      uint32 exccause;
      uint32 epc1;
      uint32 epc2;
      uint32 epc3;
      uint32 excvaddr;
      uint32 depc;
  };
  */
  Serial.print("reset reason=");
  Serial.println(prst->reason);

  // RTC memoryからデータを読み込む
  if (ESP.rtcUserMemoryRead(0, (uint32_t*) &rtcData, sizeof(rtcData))) {
    Serial.println("rtcUserMemoryRead Success");
    if (prst->reason != 4) { // Not Software/System restart
      for (int i = 0; i < sizeof(rtcData.data); i++) {
        rtcData.data[i] = 0;
      }
    } else {
      rtcData.data[0]++;
    }
  } else {
    Serial.println("rtcUserMemoryRead Fail");
  }

  // RTC memoryにデータを書き込む
  if (ESP.rtcUserMemoryWrite(0, (uint32_t*) &rtcData, sizeof(rtcData))) {
    Serial.println("rtcUserMemoryWrite Success");
  } else {
    Serial.println("rtcUserMemoryWrite Fail");
  }

  Serial.println("SPIFFS Started");
  SPIFFS.begin();
 
  // 初回起動時のみファイルを作成
  if (rtcData.data[0] == 0) {
    //Serial.println("SPIFFS Started");
    //SPIFFS.begin();

    // Next lines have to be done ONLY ONCE!!!!!When SPIFFS is formatted ONCE you can comment these lines out!!
    Serial.println("Please wait 30 secs for SPIFFS to be formatted");
    SPIFFS.format();
    Serial.println("Spiffs formatted");

    // open file for writing
    File f = SPIFFS.open("/f.txt", "w");
    if (!f) {
      Serial.println("file open failed");
    } else {
      Serial.println("====== Writing to SPIFFS file =========");
      for (int i=1; i<=10; i++){
        f.print("Line : ");
        f.println(i);
      } // end for
      f.close();
    } // end if

  // Reset/Restartからの復帰
  } else {
    //Serial.println("SPIFFS Started");
    //SPIFFS.begin();
   
    // list directory
    listDir();

    // open file for reading
    File f = SPIFFS.open("/f.txt", "r");
    if (!f) {
      Serial.println("file open failed");
    } else {
      Serial.println("====== Reading from SPIFFS file =======");
      for (int i=1; i<=10; i++){
        String s=f.readStringUntil('\n');
        Serial.print(i);
        Serial.print(":");
        Serial.println(s);
      } // end for
      f.close();
    } // end if   
  }

  Serial.print("rtcData.data[0]=");
  Serial.println(rtcData.data[0]);
  if ((rtcData.data[0] % 2) == 0) {
    Serial.println("Do ESP.reset");
    for(int i=0;i<20;i++) delay(1000);
    ESP.reset();
  } else {
    Serial.println("Do ESP.restart");
    for(int i=0;i<20;i++) delay(1000);
    ESP.restart();
  }
}

void loop() {
}

結果は以下の通りです。
Reset/Restartから復帰した時も、<f.txt>は読めることを確認しました。
ESP.getResetReason()=External System
reset reason=6
rtcUserMemoryRead Success
rtcUserMemoryWrite Success
SPIFFS Started
Please wait 30 secs for SPIFFS to be formatted
Spiffs formatted
====== Writing to SPIFFS file =========
rtcData.data[0]=0
Do ESP.reset

ESP.getResetReason()=Software/System restart
reset reason=4
rtcUserMemoryRead Success
rtcUserMemoryWrite Success
SPIFFS Started
<f.txt> size=101
====== Reading from SPIFFS file =======
1:Line : 1
2:Line : 2
3:Line : 3
4:Line : 4
5:Line : 5
6:Line : 6
7:Line : 7
8:Line : 8
9:Line : 9
10:Line : 10
rtcData.data[0]=1
Do ESP.restart

ESP.getResetReason()=Software/System restart
reset reason=4
rtcUserMemoryRead Success
rtcUserMemoryWrite Success
SPIFFS Started
<f.txt> size=101
====== Reading from SPIFFS file =======
1:Line : 1
2:Line : 2
3:Line : 3
4:Line : 4
5:Line : 5
6:Line : 6
7:Line : 7
8:Line : 8
9:Line : 9
10:Line : 10
rtcData.data[0]=2
Do ESP.reset

次回は、DeepSleepから復帰した時に、SPIFFS上に作られたファイルが保持されるのかどうか、確認してみます。

続く....