Stm32-usb

Caricare firmware su un stm32f103 "blue pill" via porta USB

OCCHIO La procedura con stlink non sembra funzionare su tutti i computer. Non sappiamo perché. La prova si ha quando, dopo aver fatto st-flash, non vediamo il caratteristico lampeggio. Inoltre il device non si presenta in USB (da lsusb non lo vediamo; su dmesg ci sono solo errori). Incrocia le dita!
La procedura con usb-ttl per ora è stata testata su un solo computer.

Un po’ di teoria

In generale per caricare un programma su un stm32 serve usare il programmatore st-link v2. Il programmatore costa poco e funziona bene, ma magari vogliamo farne a meno.

Questo si può fare sfruttando la porta USB. Prima però è necessario mettere un bootloader adatto. Ovvero:

si mette usando l’stlink (in teoria se ne può fare a meno, ancora non ci sono riuscito) un programma sul chip. Questo programma fa così: quando parte fa un pattern coi led molto riconoscibile; poi rimane in ascolto sulla porta usb per alcuni secondi(www.onetransistor.eu/2017/11/stm32-blue...; se nessuno gli dice niente, fa partire un secondo programma che ha in memoria.

Questo secondo programma dovrà quindi essere scritto sull’indirizzo 0x8002000, e dovrà pertanto essere a conoscenza che questo è l’indirizzo da cui parte.

Come fare

Caricare il bootloader

Metodo con ST-LINK

wget 'https://github.com/rogerclarkmelbourne/STM32duino-bootloader/blob/master/binaries/generic_boot20_pc13.bin?raw=true'
st-flash write generic_boot20_pc13.bin 0x8000000

Dovreste vedere che il led verde fa un blink caratteristico per meno di un secondo. Lo rifà ogni volta che premete reset o che staccate e riattaccate la corrente. Se lo fa, ha funzionato tutto.
Se non lo fa… capita. Da alcuni computer questa procedura non ci funziona e non capiamo perché. Prova con il metodo successivo.

Se funziona, scollega l’stlink e collega il cavo microusb

Per sicurezza, lo sha1sum è 4c863edb4512a7d520c26f89dfd2c531f7d91908

Metodo con usb-ttl

se non avete un stlink, o se sul vostro computer non funziona bene, potete usare un usb-ttl (esempi: cp2102, ft232, pl2303). In questo caso il programma che vi serve è stm32flash (apt-get install stm32flash).

Collegate il tx del vostro usb-ttl al pin A9 e l’rx al pin A10. Collegate anche la massa. Collegate l’usb-ttl al computer. Dovrebbe comparire il device /dev/ttyUSB0.

Spostate il jumper BOOT0 al valore 1, premete reset, quindi fate

wget 'https://github.com/rogerclarkmelbourne/STM32duino-bootloader/blob/master/binaries/generic_boot20_pc13.bin?raw=true'
stm32flash -w generic_boot20_pc13.bin  -v /dev/ttyUSB0

a questo punto spostate il jumper BOOT0 al valore 0, ri-premete reset.
Dovreste vedere il led verde sulla board blinkare in modo “caratteristico” per meno di un secondo. Ci siete riusciti!

Staccate l’usb-ttl e collegate il cavo microusb

Caricare il programma vero

Attaccando il cavo microusb dovreste vedere /dev/ttyACM0.
Scaricate il linker script usb stm32f103c8t6-usb.ld, dalla directory di un qualsiasi vostro progetto fate

questo vi fa un file main.bin che è adatto ad essere messo sull’USB.

a questo punto lanciamo lo script upload-usb main.bin

make LDSCRIPT=../../stm32f103c8t6-usb.ld clobber all && sudo ../upload-usb main.bin

Subito dopo aver lanciato lo script dobbiamo premere reset (comunque lo script ci dovrebbe guidare un minimo).

Caricarlo senza essere root

nell’esempio di prima serve fare sudo. è meglio se invece vi date i permessi per le cose giuste. Create un file /etc/udev/rules.d/70-dfu-util-stm32.rules con contenuto:

ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="1eaf", ATTRS{idProduct}=="0003", MODE="664", GROUP="plugdev"

ora fate sudo udevadm control --reload-rules

e ora potrete fare tutto senza sudo!

Come ci siamo arrivati

La maggior parte delle guide spiegano solo come fare a caricare il bootloader, e non come si prosegue dopo: danno per scontato che si voglia usare l’IDE di arduino. A parte che anche in quel caso non è per nulla ovvio, il problema è che non spiegano come fare altrimenti.

Questo mi sembra l’unico post un po’ utile: www.onetransistor.eu/2017/11/stm32-blue...

Caricare il bootloader

In teoria si dovrebbe poter caricare tutto anche via usb-ttl. Noi all’inizio non ci siamo riusciti, e abbiamo usato l’stlink. Dopo siamo riusciti anche con un semplice usb-ttl

L’indirizzo su cui caricare (0x8000000) l’abbiamo copiato facendo make -n flash da un makefile precedente che ci funzionava con l’stlink.

Interagire col bootloader

Quando facciamo così vediamo che all’avvio i led fanno un blink caratteristico, segno che il bootloader è partito. Bene.
Vediamo anche che esiste /dev/ttyACM0, ma se ci andiamo con picocom ci spara un messaggio di benvenuto inutile. Fanculo.

Copiare da arduino

dato che tutti usano arduino, seguiamo i passi fatti da arduino. Questo post (già citato) spiega bene: www.onetransistor.eu/2017/11/stm32-blue...

Durante l’"upload sketch" ho lanciato ps in modo aggressivo finché non ho beccato il comando che girava:

/home/gordo/.arduino15/packages/stm32duino/tools/stm32tools/2018.9.24/linux/maple_upload ttyACM0 2 1EAF:0003 /tmp/arduino_build_27355/Blink.ino.bin

vado a guardare il file, che è uno script bash, e vedo che lancia il dfu-util con i comandi che poi ho inserito anche in upload-usb.

Provo a lanciarlo e però non mi funziona. Poi noto (sempre sull’articolo di prima):

When you reset the board, for a short moment of time while bootloader is running, it appears as DFU device, then switches to serial port.

che chiarisce che il tempismo è importante! Bisogna premere reset e subito dopo lanciare il comando, così funziona!

A quel punto si tratta solo di fare uno scriptino che automatizzi il tutto, cioè upload-usb

Abbiamo fatto anche un altro scriptino più adatto ad essere usato durante lo sviluppo chiamato upload-usb-auto

Il linker!

I programmi così non funzionano! Serve fare come dice questo: http://kevincuzner.com/2018/06/28/building-a-usb-bootloader-for-an-stm32/

Ovvero cambiare di poco il file .ld

Risultati e limiti

Il tutto è stato testato con freertos (almeno cose semplici).
Tra le cose testate con successo, riportiamo con giubilo la programmazione di un PWM che pilota un servo motore sg90, il cui codice e’ in un tgz in allegato a questa pagina, insieme alla documentazione filmografica.
Tra le cose testate con successo, riportiamo con giubilo il prelievo della temperatura da un termometro, il cui codice e’ in un tgz in allegato a questa pagina, insieme alla documentazione filmografica.

della correttezza del linker script non sono sicuro (in particolare sulla ram: l’ho riaumentata a 20k e “funziona”, ma poi magari esplode tutto chi lo sa).