O
osiver
Compagnon
OK, commençons par planter le décor :
- bluepill STM32F103C8T6 + mini-programmateur ST-link V2
- Ubuntu 20.04LTS
- Arduino IDE V2.03 linux 64bits en appimage, Arduino_STM32 (St-link 1.7) branche master installé dans ~/sketchbook/hardware
- Carte sélectionnée :
Ce dont il n'est pas question ni besoin :
- ce n'est pas un STM32F103C8T6 contrefait mais un clone CH32F103C8T6 de WCH et il fonctionne
http://www.wch-ic.com/downloads/CH32xRM_PDF.html
- le STM32Fxx est obsolète mais ce n'est pas la question
- ESP32 et autres sont mieux/moins chers/wifi ... sans doute mais la question n'est pas là
- Eclipse/programino/platformio/STcube ... mieux, plus jolis, OK mais pas la question
- UART1/ bootloader USB, je sais mais pas la question
- Arduino IDE 1.8 Arduino 2.0, on aime ou pas mais pas la question
- ST-LINK de STmicro mieux que le dongle, oui mais pas la question
- R10 fait bien 1,5k
- les bluepills chinois ...
Une fois ça évacué, le st-link alimente le bluepill et la diode PC13 clignote, normal il est livré avec le classique blink déjà programmé.
Je charge le sketch à partir des exemples, je passe le cavalier BOOT0 à 1 (inutile d'ailleurs avec la programmation par ST-link) et reset.
MAIS première erreur au moment d'envoyer le sketch compilé : le Core_id n'est pas reconnu et l'upload ne sait pas quel flashloader utiliser.
Donc, je sors de l'IDE pour me pencher plus directement sur le problème avec les outils.
./st-info --probe
Found 1 stlink programmers
version: St-link V2, Jtag V29, Sw_im V7
serial: 380023000600004e51544e4e
hla-serial: "\x38\x00\x23\x00\x06\x00\x00\x4e\x51\x54\x4e\x4e"
flash: 65536 (pagesize: 1024)
sram: 20480
chipid: 0x0410
core_id: 0x2ba01477
descr: F1xx Medium-density
Le programmateur reconnu St-link V2, bonnes tailles des mémoires, processeur reconnu comme F1xxMD, chipid correct mais core_id 0x2ba01477 au lieu de 0x1ba01477 valeur des authentiques STM32F1xx.
Du coup, j'ai récupéré les sources pour voir comment ajouter mon processeur (au moins son core_id) pour qu'il soit reconnu.
Une fois modifié stm32.h et flashloader.c, la compilation me donne des utilitaires qui reconnaissent correctement mon processeur.
Ça ne s'arrête pas là car j'ai voulu voir si je pouvais lire et écrire dans la mémoire flash avec ces utilitaires. Tant que ça ne fonctionne pas, inutile de retourner à l'IDE puisque c'est ça qu'il utilise.
Et là, nouveau problème : la lecture se passe bien, l'effacement aussi mais pas l'écriture. En utilisant le mode debug, il apparaît que l'écriture d'une page se termine par un timeout.
Nouvelle plongée dans le code. Il faut comprendre le processus d'écriture de la flash utilisé par st-link :
- le programme st-flash tourne sur le PC (linux64)
- il communique avec le st-link (programmateur) par USB mais pas le protocole usb standard par des commandes brutes (raw)
- le programmateur, lui, communique avec le bluepill par les pattes swclk et swdio suivant un protocole spécifique. Il est juste capable de lire/écrire des registres et des adresses mémoire, sauf la flash qu'il ne peut que lire.
- la programmation de la flash se fait alors comme ceci : chargement dans la SRAM d'un petit fichier binaire (loader ~80 octets) puis juste au-dessus d'une page de 1K à flasher. Ensuite on passe la main au loader qui écrit la page dans la mémoire flash par mots de 16 bits. Mais on doit savoir quand il a fini pour envoyer la page suivante. La méthode retenue est qu'à la fin le loader met le cœur du processeur en HALT (par BKPT).
C'est en examinant un registre d'état que l'on constate que le processeur est en halt. Le timeout (nous y voici) c'est quand ça dure trop longtemps. Et effectivement on voit en mode debug que le processeur ne passe pas en halt malgré des dizaines d'interrogations du registre d'état.
À ce stade, j'ai commis une erreur d'interprétation du source flash_loader.c (encouragé par un commentaire juste au-dessus), j'ai cru que le timeout intervenait après 500 tours d'une boucle de 10ms soit 5 secondes. En réalité, c'est 500ms, point. Mais 5s, je voyais bien que l'erreur sortait bien plus tôt. Du coup j'ai tourné un bon moment en cherchant à savoir si oui ou non le BKPT produisait bien un halt et si on voyait bien ce halt. Au final, j'ai dû me rendre à l'évidence, je parvenais effectivement à flasher un fichier de 256 octets mais pas une page de 1k. Donc c'était bien un problème de temps.
En mettant 1500ms au lieu de 500ms, ça passe pour une page de 1k et j'arrive à flasher le total de la mémoire flash ou flasher depuis l'IDE 2.0.
Et alors, la question, ben oui il y en a une : POURQUOI ?
J'ai passé la durée des tours de timeout (intervalle entre deux lectures du registre) à 50ms. Et j'ai compté le nombre d'interrogations : 26. Ce qui nous mène à 1,3s d'où l'erreur quand on était à 500ms de timeout.
Si on ramène ça à 1 mot : 1300ms/512 = 2,5ms/mot !!
Ça semble énorme, non ?
Et pourtant dans la datasheet du CH32F1 :
Et ça se confirme par un temps de ~1mn30 pour 64k.
Par contre, si on se réfère à la doc de STmicro :
52 fois moins !! Comment est-ce possible ??
Vous avez déjà vu ça ?
Évidemment, les temps ne sont pas si énormes si on compare au temps de développement d'un logiciel mais quand même !!
- bluepill STM32F103C8T6 + mini-programmateur ST-link V2
- Ubuntu 20.04LTS
- Arduino IDE V2.03 linux 64bits en appimage, Arduino_STM32 (St-link 1.7) branche master installé dans ~/sketchbook/hardware
- Carte sélectionnée :
Ce dont il n'est pas question ni besoin :
- ce n'est pas un STM32F103C8T6 contrefait mais un clone CH32F103C8T6 de WCH et il fonctionne
http://www.wch-ic.com/downloads/CH32xRM_PDF.html
- le STM32Fxx est obsolète mais ce n'est pas la question
- ESP32 et autres sont mieux/moins chers/wifi ... sans doute mais la question n'est pas là
- Eclipse/programino/platformio/STcube ... mieux, plus jolis, OK mais pas la question
- UART1/ bootloader USB, je sais mais pas la question
- Arduino IDE 1.8 Arduino 2.0, on aime ou pas mais pas la question
- ST-LINK de STmicro mieux que le dongle, oui mais pas la question
- R10 fait bien 1,5k
- les bluepills chinois ...
Une fois ça évacué, le st-link alimente le bluepill et la diode PC13 clignote, normal il est livré avec le classique blink déjà programmé.
Je charge le sketch à partir des exemples, je passe le cavalier BOOT0 à 1 (inutile d'ailleurs avec la programmation par ST-link) et reset.
MAIS première erreur au moment d'envoyer le sketch compilé : le Core_id n'est pas reconnu et l'upload ne sait pas quel flashloader utiliser.
Donc, je sors de l'IDE pour me pencher plus directement sur le problème avec les outils.
./st-info --probe
Found 1 stlink programmers
version: St-link V2, Jtag V29, Sw_im V7
serial: 380023000600004e51544e4e
hla-serial: "\x38\x00\x23\x00\x06\x00\x00\x4e\x51\x54\x4e\x4e"
flash: 65536 (pagesize: 1024)
sram: 20480
chipid: 0x0410
core_id: 0x2ba01477
descr: F1xx Medium-density
Le programmateur reconnu St-link V2, bonnes tailles des mémoires, processeur reconnu comme F1xxMD, chipid correct mais core_id 0x2ba01477 au lieu de 0x1ba01477 valeur des authentiques STM32F1xx.
Du coup, j'ai récupéré les sources pour voir comment ajouter mon processeur (au moins son core_id) pour qu'il soit reconnu.
Une fois modifié stm32.h et flashloader.c, la compilation me donne des utilitaires qui reconnaissent correctement mon processeur.
Ça ne s'arrête pas là car j'ai voulu voir si je pouvais lire et écrire dans la mémoire flash avec ces utilitaires. Tant que ça ne fonctionne pas, inutile de retourner à l'IDE puisque c'est ça qu'il utilise.
Et là, nouveau problème : la lecture se passe bien, l'effacement aussi mais pas l'écriture. En utilisant le mode debug, il apparaît que l'écriture d'une page se termine par un timeout.
Nouvelle plongée dans le code. Il faut comprendre le processus d'écriture de la flash utilisé par st-link :
- le programme st-flash tourne sur le PC (linux64)
- il communique avec le st-link (programmateur) par USB mais pas le protocole usb standard par des commandes brutes (raw)
- le programmateur, lui, communique avec le bluepill par les pattes swclk et swdio suivant un protocole spécifique. Il est juste capable de lire/écrire des registres et des adresses mémoire, sauf la flash qu'il ne peut que lire.
- la programmation de la flash se fait alors comme ceci : chargement dans la SRAM d'un petit fichier binaire (loader ~80 octets) puis juste au-dessus d'une page de 1K à flasher. Ensuite on passe la main au loader qui écrit la page dans la mémoire flash par mots de 16 bits. Mais on doit savoir quand il a fini pour envoyer la page suivante. La méthode retenue est qu'à la fin le loader met le cœur du processeur en HALT (par BKPT).
C'est en examinant un registre d'état que l'on constate que le processeur est en halt. Le timeout (nous y voici) c'est quand ça dure trop longtemps. Et effectivement on voit en mode debug que le processeur ne passe pas en halt malgré des dizaines d'interrogations du registre d'état.
À ce stade, j'ai commis une erreur d'interprétation du source flash_loader.c (encouragé par un commentaire juste au-dessus), j'ai cru que le timeout intervenait après 500 tours d'une boucle de 10ms soit 5 secondes. En réalité, c'est 500ms, point. Mais 5s, je voyais bien que l'erreur sortait bien plus tôt. Du coup j'ai tourné un bon moment en cherchant à savoir si oui ou non le BKPT produisait bien un halt et si on voyait bien ce halt. Au final, j'ai dû me rendre à l'évidence, je parvenais effectivement à flasher un fichier de 256 octets mais pas une page de 1k. Donc c'était bien un problème de temps.
En mettant 1500ms au lieu de 500ms, ça passe pour une page de 1k et j'arrive à flasher le total de la mémoire flash ou flasher depuis l'IDE 2.0.
Et alors, la question, ben oui il y en a une : POURQUOI ?
J'ai passé la durée des tours de timeout (intervalle entre deux lectures du registre) à 50ms. Et j'ai compté le nombre d'interrogations : 26. Ce qui nous mène à 1,3s d'où l'erreur quand on était à 500ms de timeout.
Si on ramène ça à 1 mot : 1300ms/512 = 2,5ms/mot !!
Ça semble énorme, non ?
Et pourtant dans la datasheet du CH32F1 :
Et ça se confirme par un temps de ~1mn30 pour 64k.
Par contre, si on se réfère à la doc de STmicro :
52 fois moins !! Comment est-ce possible ??
Vous avez déjà vu ça ?
Évidemment, les temps ne sont pas si énormes si on compare au temps de développement d'un logiciel mais quand même !!