Skocz do zawartości

esp32-serprog, termux, flashrom, błąd opróżniania bufora przy bezpośrednim połączeniu


Pomocna odpowiedź

Napisano

Spotkałem się ze wspomnianym w temacie problemem używając projektu "esp32-serprog"  + flashrom (termux; android). Odpalenie flashrom-a przez sudo nic nie zmienia. Aktualnie, termux nie ma dostępu do root-a (wyłączyłem).

Repo termux-a nie zawiera flashrom-a, więc skompilowałem go z github-a/paczek przy użyciu meson-a:

flashrom-kompilacja.thumb.jpg.069810af41b73a050a1e60aaf9fac079.jpg

 

Błąd "EFAULT (Bad address)" pojawia się przy bezpośrednim połączeniu "flashrom -> esp32-serprog" poprzez gniazdo. Rzadko, ale zdarza się, że zadziała, a później sypie EFAULT aż do znudzenia.

bezposrednie.thumb.jpg.5bf0e966b586b9fa1c4f012afa710da6.jpg

 

Próbowałem różnych wersji flashrom-a (1.4.0, 1.5.1, 1.6.0, 1.8.0-devel), jednak z każdą jest to samo. Kompilacja v1.7.0 wyrzucała błędy od czapy, więc dałem sobie z nią spokój.

Z ciekawości odpaliłem "emulowany" serial-port za pomocą socat-a, z pozytywnym rezultatem:

socat-serial-port.thumb.jpg.ec43e4fa941a0fb32147a3c4300229c4.jpgflashrom-socat.thumb.jpg.f5a9ace7d40f538e775f915b44067092.jpg

 

Zastanawiam się w czym jest rzecz. W "Lubuntu 24.04" (laptop) i w aktualnym "DietPi v10.3" (RPi-Zero2W) "flashrom-1.8.0-devel" we wspomnianej konfiguracji działa ok. Tyle, że są to "pełnoprawne" linuksy z aktualnym kernelem. W andku (v8.1.0) jest stare jajo 3.18.79. Czy może to jest problemem?

  • Lubię! 1

Problem "być może" rozwiązany. W głównym katalogu flashrom-a, w pliku "serial.c" jest funkcja "void sp_flush_incoming(void)". Autor zamieścił nawet krótki komentarz przy warunku po funkcji "tcflush". Mniej więcej rozumiem dlaczego z "emulowanym" portem szeregowym nie wyłożyło się. Brak "EFAULT" w nowszych, "typowo linuksowych" systemach pozostaje na razie zagadką. EINVAL dodałem testowo, być może jest zbędne.

fix.thumb.jpg.d098d8e3a43ed36853bb34375f51ba02.jpg

 

Po przekompilowaniu "tcflush()" nadal generuje EFAULT, ale przechwytuje go kod i czyści bufor po swojemu. Nie usuwałem "tcflush()", gdyby przyszło używać socat-a.

rezultat.thumb.jpg.f0491b9149abaa4b32060311341df9aa.jpg

 

Resztę obadam kiedy będę mieć klips/adapter i pamięć flash.

  • Lubię! 1

Można powiedzieć, że odczyt przez gniazdo działa, chociaż bywa kapryśny. Smartfon jest hotspotem, ESP32 ("zwykłe", nie "S3") łączy się z nim bezpośrednio. Oba urządzenia znajdują się blisko siebie. Pamięć flash (Winbond 25Q32FVSIG; 3.3V) zawiera same 0xFF (wcześniej "wyczyściłem" ją programatorem CH341A). Chociaż bywa i tak, że odczyt jest przekłamany, czasem pojawiają się losowe bajty i nawet nie ma wtedy znaczenia co podam w "spispeed", 1, 8, czy 16M.

 odczyt.thumb.jpg.e01218454e7d998be6108c8cd75a1c05.jpg

"Esp32-serprog" skompilowałem za pomocą starszego [esp-idf-v5.4.4], mniej więcej w ten sposób:

idf.py set-target esp32
idf.py menuconfig
idf.py build
idf.py flash

Lub od razu "idf.py flash", bez "build".

Plik "KConfig.projbuild" (w katalogu "main") wymagał poprawki jednej litery w nazwie na "Kconfig.projbuild". Bez tego dodatkowe menu dla wifi ("esp32-serprog") nie jest widoczne w konfiguratorze (idf.py menuconfig). W "esp-idf-v6.0.1" niby działało, ale wypluwało inne błędy, więc użyłem starszego esp-idf.

GPIO ustawiłem jak poniżej (WP i HOLD niepodłączone).

#ifdef CONFIG_IDF_TARGET_ESP32
    #define EEPROM_HOST  VSPI_HOST
    #define PIN_NUM_MISO 19
    #define PIN_NUM_MOSI 23
    #define PIN_NUM_CLK  18
    #define PIN_NUM_CS   5

 

Na linii 3.3V pamięci flash jest kondensator 100uF, zasilanie z ESP32. Poszukam dodatkowego stabilizatora 3.3V. Być może pobór prądu podczas transmisji wifu powoduje spadki napięcia, czy cuś, nie sprawdzałem. 

esp32-38pin-pinout.thumb.png.0f6e89b14cbabc15093415852da40c4b.pnggpio.thumb.jpg.8c496c83958c1d77acb17888e0aedd4e.jpg

 

Poniżej widać też rezystor 4.7kR, który łączy WP z 3.3V. Z tego co wyczytałem w dokumentacji Winbond, stan niski aktywuje "write protect". Próbowałem zapisu, ale z mizernym skutkiem, będę musiał doczytać o co chodzi. A może ktoś wie? Podpowiedzi mile widziane. W CH341A oczywiście tego problemu nie ma.

ulep.thumb.jpg.87af6165b45181af368c015b1777f139.jpg
 

Ogólnie temat jest "4fun", z ciekawości. Zachęcony całkiem stabilnym programowaniem "tcp-uart" z esp32 jako "mostem bezprzewodowym" myślałem, że tu będzie podobnie. Coś jednak kuleje. Na ESP32 działał wcześniej wspomniany most, przez ściany, sufity i jak nie przesadziłem z odległością, to flaszowanie mikrokontrolera ze smartfona na standardowym baud 115200 było praktycznie "pewniakiem".

O ile pamiętam to ~WP a nie WP. Nie bawiłem się z flashami  ale FRAM, EEprom i inne takie podłączałem to po prostu do GND.

  • Lubię! 1
(edytowany)

@ethanak, słuszna uwaga, dzięki. Przewertowałem więc dokumentację dokładniej, na większym ekranie, hehe.

Cytat

7.2 Wybór układu (/CS)
Wyprowadzenie wyboru układu SPI (/CS) włącza i wyłącza działanie urządzenia. Gdy linia /CS jest w stanie wysokim, urządzenie jest odznaczone, a wyprowadzenia szeregowego wyjścia danych (DO lub IO0, IO1, IO2, IO3) znajdują się w stanie wysokiej impedancji. Po odznaczeniu pobór prądu przez urządzenie spada do poziomu gotowości (standby), chyba że trwa wewnętrzny cykl kasowania, programowania lub zapisu rejestru stanu. Przejście linii /CS w stan niski powoduje wybranie urządzenia, pobór prądu wzrasta do poziomu aktywności, a do układu można zapisywać instrukcje i odczytywać z niego dane. Po włączeniu zasilania linia /CS musi przejść ze stanu wysokiego w niski, zanim nowa instrukcja zostanie zaakceptowana. Podczas włączania zasilania wejście /CS musi nadążać za poziomem napięcia zasilania VCC (patrz sekcja „Ochrona przed zapisem” i rysunek 30). Aby to zapewnić, można w razie potrzeby zastosować rezystor podciągający (pull-up) na linii /CS.

7.4 Ochrona przed zapisem (/WP)
Wyprowadzenie ochrony przed zapisem (/WP) służy do blokowania zapisu do rejestru stanu. W połączeniu z bitami ochrony blokowej (SEC, TB, BP2, BP1 i BP0) oraz bitami ochrony rejestru stanu (SRP) pozwala na sprzętowe zabezpieczenie części lub całości matrycy pamięci. Wyprowadzenie /WP jest aktywne w stanie niskim. Gdy bit QE w rejestrze stanu 2 jest ustawiony na tryb Quad I/O, funkcja wyprowadzenia /WP (sprzętowa ochrona przed zapisem) jest niedostępna, ponieważ pin ten służy jako IO2. Konfigurację wyprowadzeń dla trybu Quad I/O przedstawiają rysunki 1a, 1b i 1c. [1] 

7.5 Wstrzymanie (/HOLD)
Wyprowadzenie /HOLD umożliwia wstrzymanie pracy urządzenia, gdy jest ono aktywnie wybrane. Przejście linii /HOLD w stan niski przy niskim stanie linii /CS powoduje przełączenie wyprowadzenia DO w stan wysokiej impedancji oraz ignorowanie sygnałów na liniach DI i CLK. Powrót linii /HOLD do stanu wysokiego wznawia pracę urządzenia. Funkcja /HOLD jest przydatna, gdy wiele urządzeń współdzieli te same linie sygnałowe SPI. Wyprowadzenie /HOLD jest aktywne w stanie niskim. Gdy bit QE w rejestrze stanu 2 jest ustawiony na tryb Quad I/O, funkcja wyprowadzenia /HOLD jest niedostępna, ponieważ pin ten służy jako IO3. Konfigurację wyprowadzeń dla trybu Quad I/O przedstawiają rysunki 1a, 1b i 1c.

 

Pull-up (4.7kR) przy ~WP zmieniony na 10kR, identyczne dodane na liniach: ~CS, ~HOLD. Przy gpio5 (~CS) dodałem dla pewności.

gpio-pullup.thumb.png.e5c589171223a412bce20d78f02c250f.png

Rezultat, wszystko działa cacunio. Flashrom nie pokazuje już informacji "Block protection could not be disabled!"

Odczyt:

odczyt.thumb.jpg.d64b440b3ec122787b3ff0d961797109.jpg

 

Zapis:

zapis.thumb.jpg.599a48be99740915d27c22456293db5d.jpg

 

Kasowanie:

kasowanie.thumb.jpg.f47599e0226908c520b53e23528a7229.jpg

 

// 

Z pomiaru wynika, że max wartość (zarazem domyślna) dla "spispeed" wynosi 8M(Hz) w tej konfiguracji. Przykładowo, odczyt 4MB zajmuje ~25s. Bez podania parametru wynik jest identyczny. Chociaż na screenach widać "16M", niczego to nie zmienia.

Fragment kodu "main.c" z "esp32-serprog":

serprog_spi_init(8*1000*1000); //use 8M spispeed as initial value

 

Edytowano przez orb777
(edytowany)

Podsumowując temat. Potestowałem trochę "programator", tyle, że zmieniłem płytkę na "Lolin32 Lite" (+ogniwo 18650) i adapter na klips. Działa całkiem ok ze zmodyfikowanym flashrom-em. Nie muszę używać socat-a. Korzystałem z rutera wifi, a także bezpośrednio przez smartfon jako hotspot. Nie zdarzyło się, żeby przerwało odczyt/zapis z kości. Przez ruter idzie kilka sekund wolniej, ale nadal ok. Testowałem głównie z pamięciami marek: Winbond, Gigadevice, cFeon. Flashrom radzi sobie z nimi także w sposób "generyczny", tj. mimo, że nie rozpoznaje modelu kości, to jednak potrafi "dogadać się" z nią przez protokół SFDP, umożliwiajac zapis/odczyt. Część kości wymaga wylutu, tak jak i przy użyciu innych programatorów, inaczej pamięć nie jest rozpoznawana albo dane są błędne. Nie pomaga wtedy nawet dobre, zewnętrzne zasilanie. W przypadku mikrokontrolerów można jeszcze w łatwy sposób użyć EN/RST co deaktywuje procesor.

Jak za ~9 zł (tyle kosztował Lolin32), z poziomu flashrom-a (odczyt) nie widzę wielkiej różnicy w korzystaniu z programatora porównując do znanego CH341A/B. Na plus - mobilność i brak konieczności podłączania wszystkiego do PC/laptopa/... przez USB. Na minus (raczej dotyczy flashrom-a) - baza danych rozpoznawanych pamięci. Można dodać swoje modele, ale każdorazowa rekompilacja na starszym telefonie jest średnia.

Czasowo skupiłem się bardziej na odczycie kości pod kopie zapasowe, ale jest jeszcze jeden minus - zapis, wolniejszy ~4x niż na CH341A/B. Nie wiem z czego może to wynikać, z moich urządzeń wifi, konfiguracji. Autorzy "esp32-serprog" jak i "flashrom-a" wyłączyli algorytm Nagle-a dla gniazd (TCP_NODELAY). Natomiast odczyt, co dziwne, jest szybszy niż w CH341B, o ~10 sekund dla kości 4MB.

Edytowano przez orb777
  • Lubię! 1
(edytowany)

Odnośnie zapisu flasha: smartfon (hotspot wifi) z flashrom-em (192.168.43.1), ESP32-serprog (192.168.43.168).

odczyt.thumb.jpg.2a4f434f35a847b21944260b8a7846d3.jpg zapis.thumb.jpg.87a0cd81311454bdfc9112e1c1d370e0.jpg

Zapis ma ciut większy narzut pakietów sterujących (serprog), poza tym dane wysyłane są zawsze w paczkach po 266 bajtów. Podczas odczytu idą przeważnie 2 pakiety po sobie, tj. 1440 + 607 bajtów. Retransmisje też bywają. Na routerze wifu podobna sytuacja + częstsze retransmisje. Tęgie głowy nad tymi programami myślały, co ja mogę bidny żuczek od kulki gnoju oderwany narobić, żeby je przyspieszyć. Tak się zastanawiam.

Edytowano przez orb777

@_LM_, dzięki za link, poczytam.

Odnośnie spi, teoretycznie "spispeed" ustawia czestotliwość w ESP32-serprog, domyślnie wynosi 8M(Hz). Sterowanie przez parametr raczej działa, np. "spispeed=1M" zauważalnie wydłuża czas odczytu. Pogrzebię w konfigu, może faktycznie jest tam limit i nie pociśnie więcej niż 8M. Chociaż log z flashrom-a pokazuje niby, że dogadał się z ESP32-serprog na 16M.

flashrom was built with LLVM Clang 21.1.8 , little endian
Command line (6 args): flashrom -p serprog:ip=192.168.43.168:8888,spispeed=16M -r dump.bin --verbose --progress
Initializing serprog programmer
serprog: IP 192.168.43.168 port 8888
serprog: connected - attempting to synchronize
.
serprog: Synchronized
serprog: Interface version ok.
serprog: Bus support: parallel=off, LPC=off, FWH=off, SPI=on
serprog: Maximum write-n length is 2047
serprog: Maximum read-n length is 2047
serprog: Requested to set SPI clock frequency to 16000000 Hz. It was actually set to 16000000 Hz
serprog: Programmer name is "esp32-serprog"
serprog: Serial buffer size is 65535
serprog: Warning: Programmer does not support toggling its output drivers
The following protocols are supported: SPI.

 

Problemowy wydaje się być flashrom, który "pcha" małe pakiety w kierunku ESP32 podczas zapisu. Odczyt każdorazowo dostaje ~2KB danych w dwóch pakietach za koleją, zapis tylko 266B w dłuższym interwale czasowym, co dosyć dobrze widać w wiresharku. Nie wiem, może taka jest specyfika przesyłania pakietów w tym protokole i bezprzewodowo bardziej kuleje.

(edytowany)

dobrze myślę że to jest to? https://github.com/thisiseth/esp32-serprog/blob/main/README.md#use-with-flashrom chwalą się że nawet 80Mhz pociągnie. Tylko własnie, musisz zmienić w sdk config, albo wpisać inny parametr. Sorry jak ględzę

patrzę jeszcze czy i jak zmienić wielkość bufora, bo partycja ma 4kB czemu to na takie małe kawałki podzielili? 266B..

Edytowano przez _LM_

@_LM_, dokładnie to, link jest też w pierwszym wpisie, pewnie słabo widoczny.

 

14 minut temu, _LM_ napisał:

Tylko własnie, musisz zmienić w sdk config, albo wpisać inny parametr.

Tak, z tym będę kombinował na lapku.

 

11 minut temu, _LM_ napisał:

patrzę jeszcze czy i jak zmienić wielkość bufora, bo partycja ma 4kB czemu to na takie małe kawałki podzielili? 266B..

I to jest dziwne, ponieważ ESP32-serprog zgłasza do flashrom-a, że ma duży bufor, a ten mu odsyła małe wypierdki.

Dobra, już wiem, zwiększenie pojemności bufora pewnie będzie wiązało się z jakąś grubszą modyfikacją ponieważ rozmiar strony to 256Bajtów:

Cytat

The W25Q32JV array is organized into 16,384 programmable pages of 256-bytes each. Up to 256 bytes can be programmed at a time. Pages can be erased in groups of 16 (4KB sector erase), groups of 128 (32KB block erase), groups of 256 (64KB block erase) or the entire chip (chip erase). The W25Q32JV has 1,024 erasable sectors and 64 erasable blocks respectively. The small 4KB sectors allow for greater flexibility in applications that require data and parameter storage.

https://docs.rs-online.com/dede/0900766b81622f8f.pdf

nie wiem czy ma sens - choć technicznie jest możliwe - przesyłanie większej ilości za jednym podejściem bo programator i tak musi to podzielić.

OT

Kiedyś napisałem na swój użytek program który robił aktualizację przez UDP (esp8266 non - os) poza tym że niekiedy zapis nie udawał się z powodu błędów protokołu to raczej chodziło to dosyć szybko
EOT

  • Lubię! 1

@_LM_, na kablu pewnie lepiej to działa czasowo.

Myślałem nad tym, żeby zrobić coś swojego, co przyjmie przez http .bin po wifu, umieści na karcie sd i dopiero wtedy będzie komunikowało się przez spi z pamięcią, ale to więcej roboty. W zasadzie musiałbym pisać obsługę całej komunikacji z różnymi pamięciami, co tutaj jest już gotowe. Na pewno byłoby stabilniejsze i szybsze.

Kolejny test, tym razem na lapku z Linux-em. Pamięć "Winbond W25Q32FVSIG" + Lolin32 Lite + esp32-serprog + UART0 (przez kabel USB, nie wifi), baud 1500000. Tyle udało się wycisnąć jako "stabilny max" dla wbudowanego konwertera CH340C. Standardowa sekwencja: odczyt bieżącej zawartości, zapis (4MB losowych danych), weryfikacja zapisu. Całość trwała ~11 minut, log poniżej. Jak widać flashrom z czasem nie ściemnia. Szybciej już chyba (?) nie będzie.

time flashrom --progress --verbose -p serprog:dev=/dev/ttyUSB0:1500000,spispeed=24M -c W25Q32FV -w los.bin

flashrom v1.8.0-devel (git:v1.7.0-36-gcb86133a) on Linux 6.8.0-117-generic (x86_64)
flashrom is free software, get the source code at https://flashrom.org

flashrom was built with GCC 13.3.0, little endian
Command line (8 args): flashrom --progress --verbose -p serprog:dev=/dev/ttyUSB0:1500000,spispeed=24M -c W25Q32FV -w los.bin
Initializing serprog programmer
serprog: connected - attempting to synchronize
.
serprog: Synchronized
serprog: Interface version ok.
serprog: Bus support: parallel=off, LPC=off, FWH=off, SPI=on
serprog: Maximum write-n length is 2047
serprog: Maximum read-n length is 2047
serprog: Requested to set SPI clock frequency to 24000000 Hz. It was actually set to 26666000 Hz
serprog: Programmer name is "esp32-serprog"
serprog: Serial buffer size is 4096
serprog: Warning: Programmer does not support toggling its output drivers
The following protocols are supported: SPI.
Probing for Winbond W25Q32FV, 4096 kB: compare_id: id1 0xef, id2 0x4016
Added layout entry 00000000 - 003fffff named complete flash
Found Winbond flash chip "W25Q32FV" (4096 kB, SPI) on serprog.
Chip status register is 0x00.
Chip status register: Status Register Write Disable (SRWD, SRP, ...) is not set
Chip status register: Sector Protect Size (SEC) is 64 KB
Chip status register: Top/Bottom (TB) is top
Chip status register: Block Protect 2 (BP2) is not set
Chip status register: Block Protect 1 (BP1) is not set
Chip status register: Block Protect 0 (BP0) is not set
Chip status register: Write Enable Latch (WEL) is not set
Chip status register: Write In Progress (WIP/BUSY) is not set
Chip status register 2 is NOT decoded!
This chip may contain one-time programmable memory. flashrom cannot read
and may never be able to write it, hence it may not be able to completely
clone the contents of this chip (see man page for details).
===
This flash part has status UNTESTED for operations: WP
The test status of this chip may have been updated in the latest development
version of flashrom. If you are running the latest development version,
please email a report to flashrom@flashrom.org if any of the above operations
work correctly for you with this flash chip. Please include the flashrom log
file for all operations you tested (see the man page for details), and mention
which mainboard or programmer you tested in the subject line.
You can also try to follow the instructions here:
https://www.flashrom.org/contrib_howtos/how_to_mark_chip_tested.html
Thanks for your help!
Reading old flash chip contents... 
read_flash:  region (00000000..0x3fffff) is readable, reading range (00000000..0x3fffff).
[READ: 100%]...done.
Updating flash chip contents... 
erase_write:  region (00000000..0x3fffff) is writable, erasing range (00000000..0x3fffff).
write_flash:  region (00000000..0x3fffff) is writable, writing range (00000000..0x3fffff).
[WRITE: 100%]...W(0:3fffff)Erase/write done from 0 to 3fffff
Verifying flash... 
read_flash:  region (00000000..0x3fffff) is readable, reading range (00000000..0x3fffff).
[READ: 100%]...VERIFIED.
Runtime from programmer init to shutdown: 10min58sec

real    10m57,356s
user    0m1,525s
sys     0m9,320s

 

Poniżej zamieszczam paczkę ze wstępnie skonfigurowanym "esp32-serprog" (baud 1500000). Kompilacja za pomocą wspomnianego [esp-idf-v5.4.4], układ gpio jak wcześniej.

idf.py build erase-flash flash

esp32-serprog-uart-b1500000.zip

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...