フラッシユの読み書き

フラッシユの読み書き

フラッシュへの書き込み

ESP32のフラッシュメモリで書いた通りフラッシュメモリに余裕がありますので読み書きしてみます。

ESP32のデフォルトのパーテション構成(Single factory app, no OTA)は以下です。

Name Type SubType Offset Size Flags
nvs data nvs 0x9000 24K
phy_init data phy 0xf000 4K
factory app factory 0x10000 1M

ここでストレージとして利用できるのはSubType=nvsのパーティションになります。
Name=nvsのパーティションがnvs_flash_init等で初期化されるデフォルトパーティションのようです。

デフォルトパーティションを使った場合

デフォルトパーティション(Name=nvs)を使った場合は以下のように読み書きできます。

プログラム

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs_flash.h"
#include "esp_log.h"

void app_main(void)
{
	// デフォルトパーティション("nvs")を初期化
    nvs_flash_init();

	// "test"というKeyでオープン
    nvs_handle_t hHandle;
    ESP_ERROR_CHECK(nvs_open("test", NVS_READWRITE, &hHandle));

    // 読み込み
    int32_t counter = 0;
    err = nvs_get_i32(hHandle, "counter", &counter);
    if (err == ESP_OK) {
        // "counter"の読み込み成功
        ESP_LOGI(APP_NAME, "READ(OK) counter=%u", (unsigned int)counter);
    } else if (err == ESP_ERR_NVS_NOT_FOUND) {
        // "counter"が存在しない
        ESP_LOGI(APP_NAME, "NOT FOUND counter");
        counter = 0;
    } else {
        ESP_ERROR_CHECK(err);
    }

    // 書き込み
    counter++;
    ESP_ERROR_CHECK(nvs_set_i32(hHandle, "counter", counter));
    ESP_LOGI(APP_NAME, "WRITE(OK) counter=%u", (unsigned int)counter);

    // コミット
    ESP_ERROR_CHECK(nvs_commit(hHandle));

    vTaskSuspend(NULL);
}

読み込みにnvs_set_i32が使用されてますが、これは型毎に用意されています。

Function
nvs_get_i8,16,32,64 int8,16,32,64
nvs_get_u8,16,32,64 uint8,16,32,64
nvs_get_str char*の文字列
nvs_get_blob バイナリ

書き込みのnvs_set_i32も上記のように用意されています。
書き込みする際は必ず nvs_commit を実行します。nvs_commitでFlashへの書き込みが実行されます。

リセットボタン(EN)を押す度にカウンタが1プラスされます。

別のnvsパーティションを利用する場合

デフォルト以外のパーティションに保存したい場合もあるでしょう。
(たぶんあるんだと思います)
その場合のやり方です。

menuConfigを開いて Serial flasher config を選択して Flash size を4MB (お手持ちのESP32のフラッシュサイズ) に変更します。

次に Partition Table を選択して Partition Table を 「Custom partition table CSV」に変更します。

プロジェクトに partitions.csv を追加します。

partitions.csv

# Name,   Type, SubType,  Offset,   Size,  Flags
nvs,      data, nvs,      0x9000,  0x6000
phy_init, data, phy,      0xf000,  0x1000
factory,  app,  factory,  ,        1M
mynvs,    data, nvs,      ,        0x1000

上記のようにmynvsパーティションを追加します。

プログラム

デフォルト以外のパーティションを使いたい場合は nvs_flash_initの代わりにnvs_flash_init_partition、nvs_openの代わりにnvs_open_from_partitionを使います。
また初期化されてない場合にnvs_flash_erase_partitionする処理も必要になつてきます。

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs_flash.h"
#include "esp_log.h"

void app_main(void)
{
	// デフォルトパーティション("nvs")を初期化
    esp_err_t err;
    err = nvs_flash_init_partition("mynvs");
    if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
        ESP_LOGI(APP_NAME, "NOT FOUND test Partition");
        ESP_ERROR_CHECK(nvs_flash_erase_partition("mynvs"));
        err = nvs_flash_init_partition("mynvs");
    }
    ESP_ERROR_CHECK(err);

	// "test"というKeyでオープン
    nvs_handle_t hHandle;
    ESP_ERROR_CHECK(nvs_open_from_partition("mynvs", "test", NVS_READWRITE, &hHandle));

    // 読み込み
    int32_t counter = 0;
    err = nvs_get_i32(hHandle, "counter", &counter);
    if (err == ESP_OK) {
        // "counter"の読み込み成功
        ESP_LOGI(APP_NAME, "READ(OK) counter=%u", (unsigned int)counter);
    } else if (err == ESP_ERR_NVS_NOT_FOUND) {
        // "counter"が存在しない
        ESP_LOGI(APP_NAME, "NOT FOUND counter");
        counter = 0;
    } else {
        ESP_ERROR_CHECK(err);
    }

    // 書き込み
    counter++;
    ESP_ERROR_CHECK(nvs_set_i32(hHandle, "counter", counter));
    ESP_LOGI(APP_NAME, "WRITE(OK) counter=%u", (unsigned int)counter);

    // コミット
    ESP_ERROR_CHECK(nvs_commit(hHandle));

    vTaskSuspend(NULL);
}

デフォルトパーティション(“nvs”)はライブラリ自体も使ってる(確証なし)ようなので24KBフルには使えないかもしれません。
プログラムが小さい内はFlashの容量も大量に余ってるので専用パーティションを作るのが吉かも。

あと不揮発性ストレージライブラリ(Non-Volatile Storage Library)は暗号化もサポートされてます。
そちらを使う場合は尚更デフォルトパーティションと分けた方がいい気がします。
暗号化については商品化する訳でもないので暇だったら試してみようかなくらいですが。

コメント

このブログの人気の投稿

(真)ESP32の開発環境をVSCodeで作る

ESP32にmicroSD接続

ESP32でデバッグ