ESP32 - spustenie programu z RAM

24.12.2019 | 21:10 | Mirecove dristy | Miroslav Bendík

Po dlhšej dobe som sa vrátil k svojmu koníčku - práci s hardvérom. Pri tejto príležitosti tu budem písať krátke návody, poznámky, problémy, na ktoré som narazil, riešenia atď. Trochu neplánovane som začal už v svojom predchádzajúcom blogu, kde som riešil hello world na jednom obskurnom embedded systéme.

Predstavenie hardvéru

Ako vývojovú dosku som si kúpil TTGO-T8 V1.7. Pôvodne som chcel použiť ESP32-WROVER-IB, ale nenašiel som obchod, ktorý by mi poslal adaptér (breakout board) s lacnejším poštovným než celá vývojová doska z číny. Takže okrem samotného modulu tu mám zbytočnosti ako nabíjací obvod pre li-ion baterku, USB port, UART prevodník atď. Jednoducho hardvér, ktorý buď nepotrebujem, lebo už mám v šuflíku (UART), alebo nebudem potrebovať vôbec (li-ion).

Samotný hardvér je podľa mňa hrozný šmejd. Na prvý pohľad vyzerá dobre, ale oscilátor si kľudne tiká namiesto 40MHz na 41MHz.

esptool.py v2.9-dev
Found 1 serial ports
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP32
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz

Vstavaný USART prevodník je SIL 2104, ktorý zvláda prenos rýchlosťou 2Mbps, čo je priemernej veľkosti hello world-u vítaná vlastnosť.

TTGO-T8 V1.7
Obrázok 1: TTGO-T8 V1.7

Architektúra

ESP32 obsahuje 2 mikroprocesory Tensilica Xtensa LX6 taktovaný na 80-240 MHz. Procesor má harvardskú architektúru - kód a dáta sú adresované pomocou samostatných zberníc.

K procesoru býva cez SPI pripojená externá flash pamäť a voliteľne externá RAM. Prístup k pamätiam riadi MMU jednotka, ktorá podľa mojich informácii nie je konfigurovateľná. MMU sprístupňuje flash pamäť cez inštrukčnú aj dátovú zbernicu, takže je možné z nej spúšťať kód a zároveň aj pristupovať k dátam. Externá RAM je sprístupnená len cez dátovú zbernicu (nie je teda možné využiť túto pamäť na spúšťanie kódu).

Pre zrýchlenie prístupu k externým pamätiam sa používa cache. Mimochodom dosť deravá cache, takže nie vždy sú dáta tesne po zápise správne prečítané. Nás však externé pamäte nebudú zaujímať pretože kód nemôžme spustiť z externej RAM.

Mikrokontrolér disponuje 512kB internej RAM pamäte. Tá je pomocou MMU sprístupnená zase na rôznych zberniciach. Časť je dostupná cez dátovú zbernicu, časť cez inštrukčnú a časť je rezervovaná. Pre nahranie vlastného programu môžme využiť len 128kB pamäte na adrese 0x4008 0000. Na celý program je to síce málo, ale na napísanie a odladenie niektorej časti, napríklad ovládanie LCD je prakticky ideálna.

Prečo?

Prečo nie? ;)

Ale teraz vážne. Zápis programu do pamäte trvá určitú dobu, flash pamäť sa častým prepisovaním opotrebuje a aj keď nemusí dôjsť k jej zničeniu počas programovania môže to viesť k zníženej spoľahlivosti neskôr pri prevádzke zariadenia.

Ako na to?

V dokumentácii k možnosti nahrať program do RAM prakticky nič nie je, fóra sú tak použiteľné ako každé fórum, kde sú nadšenci do arduina, takže nezostáva nič, len skúsiť a pozrieť, čo sa bude diať ;)

Začneme skopírovaním príkladu blink z esp-idf: cp -r /cesta/k/esp-idf/examples/get-started/blink blink. V adresári blink spustíme idf.py menuconfig. V sekcii Build type / Application build type vyberieme ELF file, loadable into RAM. Kód skompilujeme štandardne príkazom idf.py build, alebo ninja -C build.

Nastavenie projektu
Obrázok 2: Nastavenie projektu

Skompilovaný program, by mal obsahovať len segmenty umiestnené v RAM. Skontrolovať to môžme pomocou príkazu xtensa-esp32-elf-objdump -h build/blink.elf, alebo disassemblerom xtensa-esp32-elf-objdump -d build/blink.elf.

Disassembly of section .iram0.vectors:

40080000 <_WindowOverflow4>:
40080000:       49c500          s32e    a0, a5, -16
40080003:       49d510          s32e    a1, a5, -12
40080006:       49e520          s32e    a2, a5, -8
40080009:       49f530          s32e    a3, a5, -4
4008000c:       003400          rfwo
        ...

40080040 <_WindowUnderflow4>:
40080040:       09c500          l32e    a0, a5, -16
40080043:       09d510          l32e    a1, a5, -12
40080046:       09e520          l32e    a2, a5, -8
40080049:       09f530          l32e    a3, a5, -4
4008004c:       003500          rfwu
        ...

ELF binárka sa musí pred nahraním konvertovať nástrojom elf2image.

esptool.py --chip esp32 elf2image build/blink.elf

Binárka sa nahraje a spustí esptool-om pomocou príkazu load_ram.

esptool.py --chip esp32 --baud 921600 --no-stub load_ram build/blink.bin

Na pripojenie k UART sa nesmie použiť idf.py monitor, pretože ten pri pripojení resetuje mikrokontrolér, kvôli čomu by sme prišli o obsah RAM. Namiesto toho sa pripojíme pomocou screenu (screen /dev/ttyUSB0 115200), alebo picocomu (picocom /dev/ttyUSB0 -b115200), alebo iného obľúbeného programu. Pripomeniem, že screen sa ukončuje pomocou skratky Ctrl+A a potom :quit. Picocom sa ukončuje skratkou Ctrl+A, Q (najskôr Ctrl, potom stlačiť A, pustiť A a stlačiť Q).

Jednoduché, nie?

Prečo na tak jednoduchý postup doteraz nikto neprišiel?

Nuž možnosť, ktorú som zvolil v menu (ELF file, loadable into RAM) je novinka, ktorá v predchádzajúcich verziách nebola dostupná. Táto možnosť zmení oblasti pamäte v linker skripte. Za bežných okolností je linker skript pomerne jednoduchý. Zvyčajne. ESP32 má dosť šialené mapovanie pamäte, takže nie je to úplne triviálne. Keď k tomu prirátame komunitu typických arduinovských lepičov, tak bolo jasné, že sa do toho nikto z komunity nepustí.

Práve keď som sa do toho chcel pustiť som aktualizoval esp-idf a jeje ono to niekto urobil predomnou ;)

    • RE: ESP32 - spustenie programu z RAM 28.12.2019 | 16:07
      Avatar debian+   Návštevník

      Rozlisuj vypnut a definitivne vypnut screen a pod. programy.

    • RE: ESP32 - spustenie programu z RAM 01.01.2020 | 21:06
      Avatar bedňa LegacyIce-antiX  Administrátor

      Musel som si to prečítať na viac krát, páč furt ma niekto vyrušoval, ale teším sa s tebou.

      Dobrý hack, to ti dosť dosiek ušetrí pri vývoji :)

      Táto správa neobsahuje vírus, pretože nepoužívam MS Windows. http://kernelultras.org