ESP32マウス(shota)マウス自作研修

ESP32マウスPart.40 ESP32のアドレスマッピングを理解する

ESP32モジュールの中身 ESP32マウス(shota)
ESP32モジュールの中身 引用元:同人誌「ESP32で動く!ロボットを作ろう!」

こんにちは、shotaです。
このシリーズではESP32を搭載したオリジナルマイクロマウスEspecialを製作します。

前回の記事ではESP-IDFのバージョンをv3.3から安定版のv4.0に移行する方法について書きました。

今回からESP32のファイルシステムの使い方について書きます。
ただ、ファイルシステムを扱うために避けて通れないのが、フラッシュメモリのパーティションとアドレスの仕組みです。

そしてESP32には、フラッシュメモリ内部のアドレスと、ESP32全体のアドレスマッピングが存在するので、いきなりフラッシュメモリの話をすると混乱してしまいます。(私が混乱しました)

ということで、今回はESP32のアドレスマッピングについて私が理解した内容をまとめます。

どのアドレスに何を格納するのか定めたものはアドレス空間(アドレススペース)と表現すべきかもしれませんが、ESP32のデータシートに習ってアドレスマッピングと記載しています

そもそもESP32って何だっけ?

まずはそもそもESP32とは何だったのか、全体像から振り返りましょう。

私のオリジナルマイクロマウスEspecialに搭載しているESP32は、正確に言うとESP32-WROOM-32Dというモジュールです。
(これをESP32モジュールと呼ぶことにします)

ESP32モジュールの中にESP32-D0WDというICや、フラッシュメモリICが内蔵されています。
外からは全く見えませんが、モジュールの中に回路基板があり、そこにESP32-D0WDとフラッシュメモリICが実装されています。

ESP32-WROOM-32Dモジュール
引用元:https://docs.espressif.com/projects/esp-idf/en/release-v3.2/hw-reference/modules-and-boards.html#esp32-wroom-32d-esp32-wroom-32u

このメインのICであるESP32-D0WDこそがESP32の本体です。
(これをESP32チップと呼ぶことにします)
ESP32チップの中にはCPUやROM、RAM等のメモリ、GPIO、SPI等のペリフェラルが内蔵されています。

ESP32チップの中身は半導体の世界なので分解しても理解できません。

ESP32-D0WD
引用元:https://www.espressif.com/en/products/socs

まとめるとこんな感じです。

ESP32モジュールの中身

ESP32モジュールの中身
引用元:同人誌「ESP32で動く!ロボットを作ろう!」

ESP32チップは何を内蔵しているの?

ESP32チップを分解しても、半導体素人の私には何も理解できないのでデータシートを読みます。

ESP32のデータシートはこちら

データシートの1.6 Block DiagramにあるFunctional Block Diagramを見てましょう。
この図にはESP32チップに内蔵された機能の全体像が描かれています。

図の中央にはCPU(2個)と、ROMSRAMがあります(Core and memory)。左側にはSPI、I2C、I2S等のペリフェラルが並んでいます。
他には無線機能(図上のBluetoothやWi-Fi)や、リアルタイムカウンタ(図下のRTC)などが見えます。
また、チップ内部にフラッシュメモリを持つESP32製品もあるようです(図左上のEmbedded flash)。

ちなみに、私が使用しているESP32-WROOM-32Dモジュールの中にあるESP32-D0WDチップには、フラッシュメモリが内蔵されていません。

※図の各機能の配置とチップ内の構造は関係していません。

ESP32チップ Functional Block Diagram

ESP32チップ Functional Block Diagram
引用元:https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf

ESP32のアドレスマッピングを知る

データシートの3.1.2 Internal MemoryにはESP32チップに内蔵されたメモリの概要が書かれています。

448 KB of ROM for booting and core functions
520 KB of on-chip SRAM for data and instructions

ESP32チップには、448 KBのROMと、520 KBのRAMが内蔵されてるようです。
そして、繰り返し言いますが、ESP32チップには4MB以上の外部フラッシュメモリが接続されます。

CPUがこれらのメモリ内にあるデータへアクセスするためには、データが格納されているアドレスを指定しなければなりません。
また、ペリフェラルにアクセスするためにもアドレスが必要です。

ESP32ではこれらのアドレスを一括で管理するために、次の図で示された構造でアドレスマッピングしています。
図の中央にある0x0000_0000 ~ 0xFFFF_FFFFが、ESP32で使われるアドレスマッピング(アドレス空間)です。

例えば0x3FF0_0000 ~ 0x3FF7_FFFFの領域にはペリフェラル(Peripheral)が割り当てられています。

Address Mapping Structure

Address Mapping Structure
引用元:https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf

アドレスマッピングを詳しく見る

アドレスマッピングの詳細は、データシートのTable 5: Memory and Peripheral Mappingに記載されています。

Memory and Peripheral Mapping Table

Memory and Peripheral Mapping Table
引用元:https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf

まずはROMについて見てみましょう。

表のEmbedded Memory(組み込みメモリ、内部メモリ)カテゴリにある、Internal ROM 0には0x4000_0000 ~ 0x4005_FFFFのアドレスが割り当てられています。
Internal ROM 1には0x3FF9_0000 ~ 0x3FF9_FFFのアドレスが割り当てられています。
それぞれのアドレス領域のデータサイズは384 KB64 KBです。足し合わせると448 KBです。先程の説明で出てきた数値と同じですね。

448 KB of ROM for booting and core functions

続いて外部フラッシュメモリについて見てみましょう。
外部フラッシュメモリ(Externa Flash)には、4 MB11 MB+248 KBの2つの領域が割り当てられています。
4 MBの領域には0x3F40_0000 ~ 0x3F7F_FFFFのアドレスが割り当てられています。

0x3F40_0000 ~ 0x3F7F_FFFFのサイズが4 MBになる計算について。
0x3F7F_FFFF ~ 0x3F40_0000には、0x3F7F_FFFF – 0x3F40_0000 + 1より、0x0040_0000個のデータを格納できます。10進数で表すと4194304個です。
一般的に、1つのアドレスには1バイトのデータが格納されるので、この領域には4194303バイトのデータを格納できます。
コンピュータの世界では1024 (2の10乗)バイトを1 KB(または1 KiB。1 kBではない)、1048576(2の20乗)バイトを1 MB(または1 MiB)で表現する習慣があるので、
4194303 B = 4 * 1048576 B = 4 * 1 MB = 4 MBとなります。4 MBと書かれていてもピッタリ4000000バイトとなるのではありません。

ROMやRAM、外部フラッシュメモリのデータ領域には決められたアドレスが与えられている、ということが分かりました。

アドレスマッピングのより詳しい説明は、テクニカルリファレンスマニュアルの2. System and Memoryにかかれています。テクニカルリファレンスマニュアルはこちら

GPIOのアドレスマッピングとレジスタの関係を知る

このブログ記事の目的は「ESP32のファイルシステムを扱う」なので、メモリのアドレスマッピングについて何となく理解できればOKです。

とはいえ、せっかくアドレスマッピングの表を開いているので、ついでにペリフェラルも見てみましょう。
注目するのはGPIOです。

先程の表Memory and Peripheral Mappingを見ると、GPIOには0x3FF4_4000 ~ 0x3FF4_4FFFのアドレスが割り当てられていることが分かります。
このアドレスをどのように使えばGPIOを扱えるのでしょうか・・・もうちょっと詳しく見てみましょう。

Memory and Peripheral Mapping: GPIO

Memory and Peripheral Mapping: GPIO
引用元:https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf

ペリフェラルの使い方については、ESP32のテクニカルリファレンスマニュアルに詳細が書かれています。

テクニカルリファレンスマニュアルはこちら

5. IO_MUX and GPIO Matrixにある、5.12 Register Summaryを見てみましょう。

表の一番上にあるGPIO_OUT_REGは、GPIO 0~31の出力レジスタで、0x3FF4_4004というアドレスが割り当てられています。
その次にはGPIO_OUT_W1TS_REGというレジスタがあり、アドレス0x3FF4_4008が割り当てられています。
よく見ると、アドレスが4つ飛ばし(4バイト)で増えてることがわかります。

レジスタ記憶装置(記憶回路)の1つです。記憶装置と考えれば、レジスタにアドレスが割り当てられていることに違和感がなくなると思います。
GPIO Register Summary

GPIO Register Summary
引用元:https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf

GPIO_OUT_REGレジスタの詳細を見てみましょう。5.13 Registersに各レジスタの詳細が書かれています。

GPIO_OUT_REGレジスタには4バイト(32ビット)のデータ領域が割り当てられていることが分かります。

つまり、アドレス0x3FF4_4004に格納されている1バイトデータには、GPIO0 ~ GPIO7の出力値が、
アドレス0x3FF4_4005に格納されている1バイトデータにはGPIO8 ~ GPIO15の出力値が格納されているということです。

同様に、GPIOの出力(1/0)をセットするGPIO_OUT_W1TS_REGレジスタや、入力値が格納されるGPIO_IN_REGレジスタ等もあるので、気になる方はマニュアルを読んでみてください。

GPIO_OUT_REG register

GPIO_OUT_REG register
引用元:https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf

かなり前の話になりますが、このブログシリーズでGPIOを使ってLEDを点灯させる記事を書きました。

次のようなコードで、GPIO22の出力値を切り替え、LEDを点滅させていました。

今思うと、あれはGPIO_OUT_W1TS_REGレジスタ22ビット目1と0を書き込んでただけなんですね〜。

#define GPIO_OUTPUT_IO_0    22
gpio_set_level(GPIO_OUTPUT_IO_0, 0);
gpio_set_level(GPIO_OUTPUT_IO_0, 1);

まとめ

長くなりましたが、次のことを覚えておけばESP32のフラッシュメモリが扱いやすくなると思います。

  • ESP32モジュールはESP32チップフラッシュメモリを内蔵する
  • フラッシュメモリとは別に、ESP32チップはROMRAMを内蔵する
  • アドレスマッピングにより、ROM、RAM、フラッシュメモリにアクセスするためのアドレスが決まっている

次回の記事では、フラッシュメモリを使ってデータの読み書きをします。

タイトルとURLをコピーしました