Linux 6.11 vero, non emulato, gira sui core Xtensa di un solo ESP32-S3 N16R8. Niente RAM aggiuntiva, niente SD card, niente secondo computer: il kernel parte dal chip, il WiFi funziona in modalità STA e c’e’ una shell Bash come login. Il firmware di Espressif resta acceso accanto a Linux sullo stesso silicio e si occupa della radio e dell’accesso alla flash. Il progetto è di paulneja e il codice sta in un repository di codice su GitHub.
La board è una DevKitC-1 con 16 MB di flash e 8 MB di PSRAM Octal. Dopo il boot la MemAvailable è passata da 1,3 MB a 3,7 MB, quindi c’e’ spazio per far girare più di un programma alla volta. La console seriale va aperta a 115200 baud, mentre il flashing usa 460800 baud con flash_freq 80m.
Kernel NOMMU, fork a 512 KiB e context switch da 21 ms
Il kernel è NOMMU, quindi non esiste protezione hardware della memoria fra i processi. Il fork() è implementato via software memory banks con copia eager della memoria privata, non copy-on-write. Il backend di fork scambia page-set a ogni context switch con gli interrupt disabilitati, e il limite di memoria privata per fork è 512 KiB. Al tetto di 512 KiB lo spostamento della memoria privata a ogni switch dura 21,5 ms, più lungo del tick da 10 ms. Un context switch può quindi tenere gli interrupt disabilitati per circa 21 ms.
I benchmark mostrano quanto pesa il fork sulle due versioni della board. Il picco di fork shadow per bash era 892 kB su 0.7 e 528 kB su 0.8; per micropython 512 kB su 0.7 e 308 kB su 0.8; per dash 560 kB su 0.7 e 280 kB su 0.8; per make 432 kB su 0.7 e 0 kB su 0.8; per socat 296 kB su 0.7 e 152 kB su 0.8; per jobq 248 kB su 0.7 e 0 kB su 0.8. Su 0.7 bash scendeva a 248 kB di MemAvailable, il minimo campionato durante i benchmark.
WiFi STA, JFFS2 scrivibile e il bug della cache flash condivisa
Il WiFi è in modalità STA, solo client: il SoftAP è stato rimosso e la board non ospita un access point. La flash scrivibile usa JFFS2 per /etc e /home, quindi si può salvare configurazione e file senza riavviare da zero. Inoltre l’acceleratore RSA hardware del chip è esposto alla Linux Crypto API tramite il driver rsa-esp32s3, con self-test all’avvio a 512 bit e 2048 bit.
Un bug del firmware ha richiesto una correzione di quattro righe. La cache flash condivisa fra i due core non veniva invalidata dopo le scritture, e questo causava kernel fault all’avvio. Dopo la correzione sono stati fatti 55 boot di fabbrica consecutivi puliti, contro 10 fault su 17 prima della correzione. La suite della board 0.8 ha eseguito 36 test con 0 falliti.
Cosa c’e’ dentro: Bash, MicroPython, Dropbear e la build da 21 GB
Sulla board girano parecchi strumenti già pronti. Bash 5.2 è la login shell, BusyBox fa da /bin/sh e c’e’ anche Dash. Poi GNU Make, MicroPython con fork e IPC, socat, nc, nano, Lua, crontab, session / dtach, nohup, jobq, programbench, NTP e curl. Per la rete ci sono Dropbear per SSH, controllato con ssh-server on|off|status, e un web-server HTTP, controllato con web-server on|off|status.
- Linux 6.11 come kernel, NOMMU
- Bash 5.2 come login shell, BusyBox come /bin/sh, Dash
- MicroPython con fork e IPC, GNU Make, socat, nc, nano, Lua
- Dropbear per SSH e web-server HTTP, con comandi on|off|status
- crontab, session / dtach, nohup, jobq, programbench, NTP, curl
- esptool, flash.sh, run.sh, build/reproduce.sh, build/plot-ram.py
Per rifare il tutto servono circa 40 minuti e circa 21 GB di spazio su disco. Le chiavi host dropbear erano condivise da ogni board, quattro in tutto: un dettaglio da sistemare se si vuole un accesso SSH davvero distinto per dispositivo. Chi vuole leggere il codice, gli script di flash e le prove sul banco trova tutto nel repository di paulneja.
