chakokuのブログ(rev4)

テック・コミック・ごくまれにチャリ

ESP32 WROVER-B を使ってみる(SPI RAM対応版 MicroPython導入)

ESP32+MicroPythonでプログラムしているが、CMOSカメラで画像取得等をするとヒープメモリがすぐに枯渇する。組み込みプログラムではメモリとの闘いなのだが、十分なメモリ空間が簡単に手に入る、ESP32 WROVERだったらどうなのか。。と。

f:id:chakoku:20190814081140j:plain
ESP32 WROVER
ESP32 WROVERはPSRAMが内蔵されたバージョンで、メモリサイズは以下
・SRAM:520KB
・PSRAM:8MB

ファームを焼いていない状態でのブートメッセージ

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0x00
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3ffc0000,len:0
load:0x3ffc0000,len:2304
load:0x40078000,len:3788
ho 0 tail 12 room 4
load:0x40098000,len:532
entry 0x4009813c

**************************************
*       hello espressif ESP32!       *
*        2nd boot is running!        *
*            version (V0.1)          *
**************************************
compile time 18:16:58
  SPI Speed      : 40MHz
  SPI Mode       : DIO
  SPI Flash Size : 4MB
Partition Table:
## Label            Usage          Type ST Offset   Length
 0 factory          factory app      00 00 00010000 00100000
 1 rfdata           RF data          01 01 00110000 00040000
 2 wifidata         WiFi data        01 02 00150000 00040000
End of partition table
Loading app partition at offset 00010000
section 0: paddr=0x00000020 vaddr=0x00000000 size=0x0ffe8 ( 65512)
section 1: paddr=0x00010010 vaddr=0x3f400010 size=0x05b64 ( 23396) map
section 2: paddr=0x00015b7c vaddr=0x3ffba720 size=0x01378 (  4984) load
section 3: paddr=0x00016efc vaddr=0x40080000 size=0x00400 (  1024) load
section 4: paddr=0x00017304 vaddr=0x40080400 size=0x126ac ( 75436) load
section 5: paddr=0x000299b8 vaddr=0x00000000 size=0x06658 ( 26200)
section 6: paddr=0x00030018 vaddr=0x400d0018 size=0x325b4 (206260) map
start: 0x400807ac

Initializing heap allocator:
Region 19: 3FFBBA98 len 00024568 tag 0
Region 25: 3FFE8000 len 00018000 tag 1
Pro cpu up.
Pro cpu start user code
nvs_flash_init
frc2_timer_task_hdl:3ffbc564, prio:22, stack:2048
tcpip_task_hdlxxx : 3ffbeca8, prio:20,stack:2048
phy_version: 80, Aug 26 2016, 13:04:06, 0
pp_task_hdl : 3ffc34f0, prio:23, stack:8192

:>enter uart init
uart init wait fifo succeed
exit uart init

IDF version : master(db93bceb)
WIFI LIB version : master(934d079b)
ssc version : master(r283 4d376412)
!!!ready!!!
mode : softAP(32:ae:a4:cc:4d:18)
dhcp server start:(ip: 192.168.4.1, mask: 255.255.255.0, gw: 192.168.4.1)

+WIFI:AP_START


SPIRAM対応版ESP32用MicroPythonを入手
MicroPython - Python for microcontrollers
esp32spiram-20190529-v1.11.bin

ファームの焼き方(一般化ルール)

esptool.py --port <usb_port> erase_flash
esptool.py --chip esp32 --port <usb_port> write_flash -z 0x1000 <firm>

cygwinから焼く場合

esptool.py --port /dev/ttyS11 erase_flash
esptool.py --chip esp32 --port /dev/ttyS11 write_flash -z 0x1000 esp32spiram-20190529-v1.11.bin

焼く前に、ツールが正しく動ているか、無難なコマンドでちょっと確認。以下はchip_id取得コマンドの例

$ esptool.py --port /dev/ttyS11 chip_id
esptool.py v2.6
Serial port /dev/ttyS11
Connecting.....
Detecting chip type... ESP32
Chip is ESP32D0WDQ5 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, BLK3 partially reserved, Coding Scheme 3/4
MAC: 30:ae:a4:cc:4d:18
Uploading stub...
Running stub...
Stub running...
Warning: ESP32 has no Chip ID. Reading MAC instead.
MAC: 30:ae:a4:cc:4d:18
Hard resetting via RTS pin...

大丈夫なようなので、、フラッシュ消去>ファーム書き込みをやってみる。
flash消去

$ esptool.py --port /dev/ttyS11 erase_flash
esptool.py v2.6
Serial port /dev/ttyS11
Connecting.......
Detecting chip type... ESP32
Chip is ESP32D0WDQ5 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, BLK3 partially reserved, Coding Scheme 3/4
MAC: 30:ae:a4:cc:4d:18
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 9.2s
Hard resetting via RTS pin...

ファームを焼いた

$ esptool.py --chip esp32 --port /dev/ttyS11 write_flash -z 0x1000 firm/esp32spiram-20190529-v1.11.bin
esptool.py v2.6
Serial port /dev/ttyS11
Connecting....
Chip is ESP32D0WDQ5 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, BLK3 partially reserved, Coding Scheme 3/4
MAC: 30:ae:a4:cc:4d:18
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 1221600 bytes to 743973...
Wrote 1221600 bytes (743973 compressed) at 0x00001000 in 66.1 seconds (effective 147.9 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

ボードをリセットしてブートメッセージを確認、SPI RAM 40mとなっている。こ、、これは、40MBか!!(追記:そんなことはない)

$  cat /dev/ttyS11
ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:4928
ho 0 tail 12 room 4
load:0x40078000,len:10188
load:0x40080400,len:6736
entry 0x400806e8
I (500) spiram: Found 64MBit SPI RAM device
I (500) spiram: SPI RAM mode: flash 40m sram 40m
I (500) spiram: PSRAM initialized, cache is in low/high (2-core) mode.
I (506) cpu_start: Pro cpu up.
I (510) cpu_start: Application information:
I (515) cpu_start: Compile time:     07:47:57
I (520) cpu_start: Compile date:     May 29 2019
I (525) cpu_start: ESP-IDF:          v3.3-beta1-268-g5c88c5996
I (532) cpu_start: Starting app cpu, entry point is 0x40082e48
I (0) cpu_start: App cpu up.
I (1397) spiram: SPI SRAM memory test OK
I (1398) heap_init: Initializing. RAM available for dynamic allocation:
I (1398) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (1404) heap_init: At 3FFB9DD0 len 00026230 (152 KiB): DRAM
I (1411) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (1417) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (1424) heap_init: At 40097B1C len 000084E4 (33 KiB): IRAM
I (1430) cpu_start: Pro cpu start user code
I (106) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
MicroPython v1.11 on 2019-05-29; ESP32 module with ESP32
Type "help()" for more information.
>>>

replから再確認

>>> gc.mem_free()
4093248
>>> gc.collect()
>>> gc.mem_free()
4093344

409K?? 40MのRAMはどこに割り当てられているのやら。。
(追記:あまりに気が焦って桁を間違っている。
(/ 4093344.0 1024 1024) // lisp S式 (Emacs使ってるので)
3.903717041015625
3.9MBで、約4MB使える状態で立ち上がっている。)

起動した直後のヒープの状態

>>> micropython.mem_info(1)
stack: 752 out of 15360
GC: total: 4098240, used: 5776, free: 4092464
 No. of 1-blocks: 45, 2-blocks: 13, max blk sz: 264, max free sz: 255770
GC memory layout; from 3f817740:
00000: h=hhhhMh=DBhhDBBBBhhh===h===hhh==h==============================
00400: ================================================================
00800: ================================================================
00c00: ================================================================
01000: =========================================Bhhh=BDhhLhhhBh===h=h=B
01400: ShTh=h=h===hhh=h=BSh===hThh=h=BhBhh==...h=......h=..............
       (3996 lines all free)
e8800: ............

マークの意味は以下

.	フリーブロック
h	ヘッドブロック
=	テイルブロック
m	マーク付きヘッドブロック
T	タプル
L	リスト
D	辞書
F	浮動小数点
B	バイトコード
M	モジュール

引用元:
https://micropython-docs-ja.readthedocs.io/ja/latest/reference/constrained.html#reporting

ESP32のFlashファイルシステムにファイルを転送する。ampyを使ってみる。

GitHub - pycampers/ampy: Adafruit MicroPython Tool - Utility to interact with a MicroPython board over a serial connection.
これまではIDEでファイル転送を行っていたけど大がかりなので、コマンドラインでさくっと使えるampyでファイル転送等を行う予定。テスト操作

 pip3 install adafruit-ampy

$ ampy -p /dev/ttyS11  get boot.py
# This file is executed on every boot (including wake-boot from deepsleep)
#import esp
#esp.osdebug(None)
#import webrepl
#webrepl.start()


■ご参考
cygwinでシリアルポートのデバイス名の判断方法
cygwinで/devと打ち込むとデバイス一覧が出て、ttyS11だろうとあたりを付ける。合っているか確認のため、cat /dev/ttyS11としてボードをリセット、起動メッセージがずらずら出たのこれでよし

$ ls  /dev
clipboard  dsp     null    scd0  sda3  sdb3    stdin   urandom
conin      fd      ptmx    sda   sdb   shm     stdout  windows
conout     full    pty0    sda1  sdb1  sr0     tty     zero
console    mqueue  random  sda2  sdb2  stderr  ttyS11

cat /dev/ttyS11


https://micropython-docs-ja.readthedocs.io/ja/latest/index.html