7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ESP-WROOM-32の外部フラッシュメモリにアクセスする(ESP32's spi_flash API)

Last updated at Posted at 2018-11-08

#概要
 この記事はESP-WROOM-32の外部SPIフラッシュメモリ(4MB)にアクセスする方法を記述しています。
 今回はSPIフラッシュメモリにアクセスするAPIを使用しています。progmemやファイルシステム(SPIFFS)を使用していません。

>>>>>>>>>>>>>>>>>>>>>>>>>>>
2019/4/24追記
 ファイルシステム(SPIFFS)を使用したSPIフラッシュメモリアクセスのライブラリを作りました。
次の記事でサンプルコードを公開しています。
「ESP32のSPIFFSサンプルコードをライブラリ化しました」
>>>>>>>>>>>>>>>>>>>>>>>>>>>

 作成したスケッチファイルはGitHubで公開しています。ライセンスはフリーです。

 外部メモリにアクセスするので処理時間が気になりますが、今回は処理時間の計測を省いて動作のみ行っています。

#開発環境
 開発環境:Arduino-IDE(Arduino-ESP32)
 使用ボード:ESP-32-DevKit
 ライブラリ:esp_spi_flash.h ※1

※1:Arduino-IDEでESP-WROOM-32の開発環境が整っていればデフォルトで用意されています。

ESP-WROOM-32の外部SPIフラッシュメモリについて

 ESP-WROOM-32の外部フラッシュメモリは4MBあります。このメモリ空間は用途によって区切られています。(パーティションテーブル)
デフォルトのパーティションテーブル(default.csv)は次のように設定されています。

Name Type SubType Offset Size
nvs data nvs 0x9000 0x5000
otadata data ota 0xe000 0x2000
app0 app ota_0 0x10000 0x140000
app1 app ota_1 0x150000 0x140000
eeprom data 0x99 0x290000 0x1000
spiffs data spiffs 0x291000 0x16F000

 パーティションテーブルの詳しい説明をすると長くなるので、主観での簡単な説明にします。
システムが「nvs」、「otadata」、「app0」、「app1」を使用しています。
「eeprom」はスケッチの中でprogmemを使用すると使われる領域のようです。
「spiffs」はファイルシステムSPIFFSを利用するときの領域です。

 今回はパーティションテーブルをデフォルト(default.csv)とし、フラッシュメモリの「spiffs」領域にアクセスしています。

ソースコード

 大まかな処理フローは次のとおりです。
1.SPIフラッシュからデータを4kB(1セクタ)読み出す
2.シリアルログに読み出したデータの先頭データを出力
3.シリアルフラッシュの指定アドレスから4kB(1セクタ)を消去
4.読み出したデータをインクリメントして、書き込み用の配列に格納
5.シリアルログに書き込むデータを出力
6.シリアルフラッシュに1byteデータを書き込む
7.1秒wait

serialflash.ino
#include "esp_spi_flash.h"
#define SPIFFS_BASE_ADDR 0x291000 // SPIFFS領域のベースアドレス

uint32_t chip_size = 0;
uint8_t w_buf[SPI_FLASH_SEC_SIZE];
uint8_t r_buf[SPI_FLASH_SEC_SIZE];

void setup() { 
  Serial.begin(115200, SERIAL_8N1);
  w_buf[0] = 0x00;
}

void loop() {
  // SPI flashから読み込み
  spi_flash_read(SPIFFS_BASE_ADDR,r_buf,SPI_FLASH_SEC_SIZE);
  Serial.printf("Read SPI flash data = %x\n",r_buf[0]);

  w_buf[0] = r_buf[0] + 1;

  // SPI flashの指定アドレスから指定サイズだけデータを消去する
  spi_flash_erase_range(SPIFFS_BASE_ADDR,SPI_FLASH_SEC_SIZE);

  // SPI flashへ書き込み
  Serial.printf("Write to SPI flash = %x\n\n",w_buf[0]);
  spi_flash_write(SPIFFS_BASE_ADDR,w_buf,1);

  delay(1000);
}

 スケッチファイルをボードに書き込み、シリアルモニタを起動すると次のようなログが表示されます。
serialflash_demo.PNG

 読み込むたびにデータがインクリメントされてることが確認できます。
また、電源を落として起動しなおしてみると、前回の続きからデータがインクリメントされていきます。

以下spi_flash APIの説明です。

SPIフラッシュメモリから読み込み

// SPI flashから読み込み
spi_flash_read(SPIFFS_BASE_ADDR,r_buf,SPI_FLASH_SEC_SIZE);

このAPIはSPIフラッシュメモリからRAMに読み込みます。
APIは次のように定義されています。

esp_err_t spi_flash_read(size_t src_addr, void *dest, size_t size)

src_addr
 フラッシュメモリ内の読み込みたいデータが格納されている先頭アドレスを指定します。
 今回はデフォルトのパーティションテーブルでSPIFFS領域の先頭アドレスを指定しています。
*dest
 フラッシュメモリから読み込んだデータの格納先ポインタを指定します。
 今回はuint8_t型配列の先頭アドレスを指定しています。
size
 フラッシュメモリから読み込むデータのサイズを指定します。
 今回は1セクタ(4kB)を指定しています。

####SPIフラッシュメモリの内容を削除(フラッシュ)する

// SPI flashの指定アドレスから指定サイズだけデータを消去する
spi_flash_erase_range(SPIFFS_BASE_ADDR,SPI_FLASH_SEC_SIZE);

このAPIはフラッシュメモリの指定アドレスから、指定したサイズのデータを削除(フラッシュ)します。
APIは次のように定義されています。

esp_err_t spi_flash_erase_range(size_t start_address, size_t size)

start_address
 フラッシュメモリ内の削除したいデータが格納されている先頭アドレスを指定します。
 今回はspiffs領域の先頭アドレスを指定しています。
size
 削除するデータサイズを指定します。
 今回は1セクタ(4kB)を指定しています。

####SPIフラッシュメモリに書き込む

// SPI flashへ書き込み
spi_flash_write(SPIFFS_BASE_ADDR,w_buf,1);

このAPIはフラッシュメモリの指定したアドレスから、指定したサイズだけデータを書き込みます。
APIは次のように定義されています。

esp_err_t spi_flash_write(size_t dest_addr, const void *src, size_t size)

dest_addr
 フラッシュメモリの書き込み先アドレスを指定します。
 今回はspiff領域の先頭アドレスを指定しています。
*src
 書き込むデータが格納されているポインタを指定します。
 今回はuint8_t型配列の先頭アドレスを指定しています。
size
 書き込むデータのサイズを指定します。
 今回は1byteを指定しています。

#あとがき
 SPIフラッシュのアクセスはセクタ単位が便利そうです。spi flash APIの中に

esp_err_t spi_flash_erase_sector(size_t sector)

といった、セクタ単位で処理するAPIを使う事ができるからです。
 spi_flash_mmap()というAPIでも外部SPIフラッシュにアクセスできそうです。試していないので動作は分かりませんが、SPIフラッシュメモリから領域を指定して内部メモリ(SRAM)上に展開するようです。
 その他にファイルシステム(FATやSPIFFS)を利用した方法もあります。こちらのほうが直感的に扱いやすいかと思いますが、こういった方法もある事が分かりました。

#参考
 ESPRESSIF ESP-IDE Programming Guide SPI Flash APIs
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/spi_flash.html

7
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?