Général Bluepill & arduino IDE2

  • Auteur de la discussion osiver
  • Date de début
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 :
Capture d’écran de 2023-02-13 12-02-41.png


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,5kOMEGA
- 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 :
Capture d’écran de 2023-02-13 15-40-37.png

Et ça se confirme par un temps de ~1mn30 pour 64k.
Par contre, si on se réfère à la doc de STmicro :
Capture d’écran de 2023-02-13 15-45-12.png

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 !! :eek:
 
C

coredump

Compagnon
Les clones de STM32 n'ont pas de flash en réalité, c'est un chip flash séparé sur une interface série.
Au démarrage le code est chargé de la flash vers une ram interne, et quand on écrit dessus le contrôleur va écrire la flash externe de façon transparente.
Tu as l'impact a la programmation mais aussi sur le temps de démarrage, les modes basse consommation etc...
 
O

osiver

Compagnon
Sûrement un truc comme ça ! J'avais vu la photo d'un chip décapé sur lequel on voyait un chip supplémentaire. Il me semblait que c'était le cas pour ceux qui affichent 128k, une 64k sur le chip et une en supplément.
C'est quand-même curieux car ça voudrait dire qu'il n'y a pas de flash sur la puce mais l'équivalent en volume de SRAM. Possible que la sram soit moins gourmande en taille de puce (nb de transistors élémentaires) que la flash. :smt108
Mais alors, ça devrait plutôt être favorable en lecture ...
Je ne sais pas à quelle vitesse ça lit. Faudrait que j'écrive un petit programme pour évaluer la vitesse de lecture :wink:
 
C

coredump

Compagnon
La raison c'est que la flash interne est limité a une technologie en 90nm, et récemment 40nm (mais avec beaucoup de contraintes), et que ca coute beaucoup moins cher de faire un clone en 28nm et d'y ajouter une flash externe.
Le plus gros producteur de clone (GD) est a l'origine un fabriquant de mémoire flash série.
 
D

Doctor_itchy

Compagnon
ettonnant cette histoire de flash spéparée ? mais c'est en interne dans le chip ? donc il ont mis la puce stm et la puce flash dans le meme boitier ?

j'ai aussi eu des déboire avec les stm32f103C8 , je développe actuellement dessus !

j'ai mis un bootloader (j'ai du en tester plusieurs different avant d'en trouver un correct , je ne sais plus exactement lequel ça fait déja un moment ! ) la méthode qui a marcher c'est le dongle stm , le soft cube stm et programmé ça via le port prog

apres je communique via le port usb de la carte avec le drivers maple pour programmer mon code perso avec l'ide !

j'ai tester le dongle stm via l'ide ça ne fonctionne pas , j'ai des bug similaire au tient mais via l'usb et maple ça fonctionne parfaitement !

par contre mon ide est le 1.8.13 car le 2.0 plus moyen de programmer sans bug divers (impossible a résoudre pour ma part donc repasser en 1.8 !) et seulement les stm , carte arduino classique pas de soucis peu importe la version ! et aucune idée du pourquoi :/

aussi si ton code doit "causer" en serie il faut absolument utilisé un des port serie supplémentaire avec un ftdi vers usb et donc avoir deux port usb , un pour balancer le code venant de l'ide et un pour "causer" avec le montage (peu importe si via putty ou soft maison) sinon ça déconne

si ton code a besoin d'enregistré des donnée (style tu encode des parametres de configuration sur un code qui gere des moteur pas a pas ) je n'ai pas réussis a enregistré cela dans la flash/epprom interne du stm32 , donc j'ai mis une 24c64 en i2c externe mais c'est normalement possible mais tout mes essais on ete infructueux ( par contre mes stm32 sont peu etre des copie c'est sans doute pour ça )

je sais pas si ça peu t'aider mais c'est mon expérience avec ses ptit'e bete :)
 
D

Doctor_itchy

Compagnon
d'accord , donc mes carte ne sont pas des clone car c'est écrit stm32 :)
 
O

osiver

Compagnon
@coredump bien intéressant le lien :smt023

donc mes carte ne sont pas des clone car c'est écrit stm32
Du coup si c'est à 2-3€ ce seraient des contrefaçons :???:
j'ai tester le dongle stm via l'ide ça ne fonctionne pas , j'ai des bug similaire au tient mais via l'usb et maple ça fonctionne parfaitement !
Pour ma part ça fonctionne avec le dongle et ma version de stlink. Que ce soit depuis l'IDE ou en direct de la ligne de commande. Pour information le d'ongle contient... un CH32f103c8t6. Le même que la bluepill 8-)
J'ai avancé sur un petit programme pour voir si la vitesse en lecture de la SRAM diffère de celle de la flash ou pas. J'implante un petit programme assembleur en sram, il fait 10000 lectures x plusieurs milliers de tours. Il me reste à faire les mesures de temps :wink:
 
D

Doctor_itchy

Compagnon
oui le dongle est aussi un "stm32" :) , cela dit pour développer je préfère le bootloader via l'usb c'est très rapide et y a moins de fil , une fois mon code correct j'en ferais un hex mis directement sur le stm sans le bootloader Arduino ( et la je pourrais utilisé l'usb interne pour communiquer avec le soft sur le pc ,chose impossible avec le bootloader Arduino et récup un peu de ram et de flash :) )

c'est étrange que toi ça tourne , moi niet , remarque je suis sous W7 , je vais migré totalement sous linux bientot , mais avec un w7 virtuel pour certaine appli :) on verra si ça va mieux !
 
D

Doctor_itchy

Compagnon
ça fait un moment que j'ai modifier la config et depuis que ça marche je n'y ai plus toucher , je ne sais plus exactement mais il me semble que la programation echouais ! possible que c'etait une histoire de timeout !
 
O

osiver

Compagnon
Il y a du progrès dans les calculs. J'utilise le systick (à plein pot, horloge AHB 72Mhz) pour voir le nombre de cycles que prend une double boucle de 5000 x 200 lectures soit 1 million de lectures.
Résultat :
À vide = sans lecture, remplacée par un NOP (1cycle) : 6 000 807 ticks
SDRAM : 8 000 834 ticks
Flash (ou son cache) : 11 000 801 ticks soit 3 cycles en plus par lecture.

Ce que je trouve un peu curieux c'est :
- remplacer la lecture (normalement 2 cycles) par un nop à 1 cycle devrait produire une différence de 1000 000 de cycles, pas de 2 000 000.
- la doc dit que la flash doit avoir 2 wait-states mais il semble y en avoir un de plus
- si on regarde et qu'on compte les cycles instruction par instruction, un tour de boucle intérieure devrait faire 7 cycles. Au total, j'ai calculé que le test complet (en SDRAM) devrait faire 7 000 000 et quelques broquilles. Il me semble qu'il y a un cycle/tour qui passe à la trappe. :smt017
 
C

coredump

Compagnon
Je n'ai pas ton code sous les yeux mais tu dois surement avoir une pénalité de branchement due au pipeline d'execution.
 
O

osiver

Compagnon
Normalement j'en ai tenu compte 3 cycles au lieu d'un pour le branchement.
Ça semble assez constant j'ai aussi testé avec AHB/8 , pile 8 fois moins de ticks.
J'ai (eu?) un doute sur LDRH en raison de l' alignement mais en décalant de +/- 2 l'adresse de départ j'ai exactement les mêmes chiffres. Par contre avec +/- 1, je vois bien la pénalité :wink:
Le code :
 
Dernière édition:
O

osiver

Compagnon
Bon, j'ai fini par trouver après pas mal de manipulations. 8-)

La dernière instruction avant BKPT, STR r7,[r6] ne consomme que 1 cycle au lieu de 2.
D'autre part, le LDRH r5,[r0] (la vraie lecture en mémoire) fait 3 cycles et pas 2 en SRAM et 6 cycles en flash.

La formule devient alors
boucle_ext = ((nb de boucles internes * 8) -2) +6
total_des_boucles = (nb de boucles externes * boucle_ext) - 2
TOTAL FINAL = total_des_boucles + 4 cycles

Et ça marche au tick près !!
8 000 802 ticks en SRAM pour 1000 000 de lectures
 

Sujets similaires

wika58
Réponses
261
Affichages
18 433
midodiy
midodiy
N
Réponses
3
Affichages
737
jpbbricole
jpbbricole
wika58
Réponses
122
Affichages
9 507
Philippe85
Philippe85
K
Réponses
33
Affichages
7 099
Doctor_itchy
D
Dudulle
Général langage MMBASIC
Réponses
8
Affichages
840
Dudulle
Dudulle
vax
Réponses
11
Affichages
12 060
vax
T
Réponses
2
Affichages
25 420
Tristan l'apprenti
T
P
Réponses
33
Affichages
16 029
wika58
wika58
Haut