ESP32でMicro SDカードへのSPIでの書き込み速度の調査

ESP32でマイクから収集した録音データをMicro SDカードに記録する際に、どの程度のバッファが必要かを見積もるために、書き込み速度を計測した。

ハードウェア

利用するボードによって、SPI制御に使うピンの指定を変更する必要がある。。

開発環境

PlatformIO IDE for Visual Studio Code を利用した ESP32 用開発については、PlatformIO IDE for VSCode でESP32のプログラム開発 の設定を参照のこと。

プログラム

次にある、ESP-IDFのSDカード制御のサンプルプログラムを修正した。

https://github.com/espressif/esp-idf/tree/master/examples/storage/sd_card

16kiBのデータの書き込みに要した時間を計測する。1万回繰り返し、それから書き込み時間の平均値、最悪値を求め、それらから書き込み速度を求める単純なプログラムである。

次のGitHubに、Platform IDE for VSCodeでの開発用ファイルを置いてある。

https://github.com/kunsen-an/espidf_sd_card_write_test.git

実行結果例

ある時点での実行結果は以下のようであった。1万回実行しているので150秒以上かかっている。

平均的には1MB/s以上で書き込みが可能であるが、この例での最悪値は、約21kB/s であった。

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:4952
load:0x40078000,len:7760
ho 0 tail 12 room 4
load:0x40080000,len:5892
entry 0x40080318
I (30) boot: ESP-IDF 3.30100.0 2nd stage bootloader
I (30) boot: compile time 16:09:50
I (30) boot: Enabling RNG early entropy source...
I (32) boot: SPI Speed      : 40MHz
I (35) boot: SPI Mode       : DIO
I (38) boot: SPI Flash Size : 4MB
I (42) boot: Partition Table:
I (44) boot: ## Label            Usage          Type ST Offset   Length
I (51) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (57) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (64) boot:  2 factory          factory app      00 00 00010000 00100000
I (70) boot: End of partition table
I (73) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x08cb4 ( 36020) map
I (94) esp_image: segment 1: paddr=0x00018cdc vaddr=0x3ffc0000 size=0x01fd8 (  8152) load
I (97) esp_image: segment 2: paddr=0x0001acbc vaddr=0x3ffc1fd8 size=0x00000 (     0) load
I (99) esp_image: segment 3: paddr=0x0001acc4 vaddr=0x40080000 size=0x00400 (  1024) load
I (108) esp_image: segment 4: paddr=0x0001b0cc vaddr=0x40080400 size=0x04f44 ( 20292) load
I (123) esp_image: segment 5: paddr=0x00020018 vaddr=0x400d0018 size=0x18f7c (102268) map
I (160) esp_image: segment 6: paddr=0x00038f9c vaddr=0x40085344 size=0x03328 ( 13096) load
I (165) esp_image: segment 7: paddr=0x0003c2cc vaddr=0x400c0000 size=0x00000 (     0) load
I (165) esp_image: segment 8: paddr=0x0003c2d4 vaddr=0x50000000 size=0x00000 (     0) load
I (178) boot: Loaded app from partition at offset 0x10000
I (178) boot: Disabling RNG early entropy source...
I (183) cpu_start: Pro cpu up.
I (185) cpu_start: Starting app cpu, entry point is 0x40081828
I (0) cpu_start: App cpu up.
I (194) heap_init: Initializing. RAM available for dynamic allocation:
I (199) heap_init: At 3FFAFF10 len 000000F0 (0 KiB): DRAM
I (204) heap_init: At 3FFDA938 len 000056C8 (21 KiB): DRAM
I (210) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (215) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (220) heap_init: At 4008866C len 00017994 (94 KiB): IRAM
I (226) cpu_start: Pro cpu start user code
I (243) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (244) example: Initializing SD card
I (244) example: Using SPI peripheral
I (244) gpio: GPIO[5]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
Name: SA16G
Type: SDHC/SDXC
Speed: default speed
Size: 14832MB
CSD: ver=1, sector_size=512, capacity=30375936 read_bl_len=9
SCR: sd_spec=2, bus_width=5
I (304) example: Opening file
I (155204) example: File written
write buffer size = 16384
sum=154883085 microseconds, average=15488 microseconds
maximum=757276 microseconds, minimum=14308 microseconds
highest write speed = 1145093 byte/s
average write speed = 1057851 byte/s
lowest write speed = 21635 byte/s
I (155424) example: Renaming file
I (155434) example: Reading file
I (155434) example: Read from file: ' !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^'
I (155434) gpio: GPIO[23]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (155444) gpio: GPIO[19]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (155454) gpio: GPIO[18]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (155454) example: Card unmounted

バッファの大きさ

録音データを連続して書き込む場合にはバッファを十分に用意しておかないと、バッファがオーバーフローする。最悪の書き込み速度が16kB/sと仮定し、 192kB/s 程度で連続して書き込みを行うなら12ブロック以上のバッファを用意しておかないとデータが失われる可能性がある。プログラムでは16kiB/ブロックなので、192KiB以上のバッファが必要であろう。