Introduction
Le but de cette partie est d'obtenir une carte qui puisse fonctionner toute seule, dès qu'on la met sous tension, sans avoir besoin d'uploader un programme ni de lancer gdb. Pour cela vous allez placer votre exécutable en flash.
Mapping mémoire
On rappelle que le mapping mémoire du processeur est disponible en pages 75 et suivantes du reference manual du processeur :
- Flash : adresse de début = 0x00000000, taille = 1MB
- RAM : elle est séparée en deux blocs non contigus :
- SRAM1 : début = 0x20000000, taille = 96kB
- SRAM2 : début = 0x10000000, taille = 32kB
Attention : La zone en 0x1FFF 7000 est une zone OTP : One Time Programmable. Surtout n'écrivez rien dedans : une mauvaise écriture dedans peut mettre la carte dans un mode "sécurisé" où ne peut plus ni relire, ni modifier, ni effacer le contenu de la flash : la carte devient donc inutilisable pour les prochains TP. Nous vérifierons les cartes, si vous avez écrit dedans vous serez pénalisés.
Problème
Les sonde JLink ont actuellement un bug empêchant la reprogrammation de la flash, que ce soit depuis Linux ou Windows. Le bug a été remonté à Segger et sera bientôt corrigé.
En attendant, pour pouvoir flasher votre carte, vous devez faire les modifications suivantes à votre .gdbinit :
- remplacer la procédure
flashpar celle-ci :
dont-repeat
mon reset
set *0x40022008=0x45670123
set *0x40022008=0xCDEF89AB
set *0x40022014=0x40010004
shell sleep 1
set *0x40022010=0x000000A0
mon reset
set *0x40022008=0x45670123
set *0x40022008=0xCDEF89AB
set *0x40022014=0x40000001
load
set *0x40022010=0x000000A0
mon reset
set $sp=$msp
end
- Remplacer la ligne
target ext :2331partarget remote :2331
De plus, il ne faut plus utiliser le fichier clocks.o qui vous avait été fourni, mais le recompiler vous-même à partir de clocks.c en bas de la page, avec les mêmes options que les autres fichiers et les optimisations -Og ou -O1 (pas de -O2 ni -O3).
Enfin, n'oubliez pas de déclarer dans votre crt0.s que la fonction _start est en mode thumb ainsi :
_start:
....
Au travail !
Passage du code en XIP
En vous rappelant des étapes de boot d'un processeur et de tout ce que doit faire le crt0.s, modifiez votre linker script et votre code d'initialisation de façon à ce que la carte puisse booter et que le programme s'exécute depuis la flash.
Attention : avant de reflasher votre carte avec gdb, vérifiez bien avec objdump que vous ne touchez qu'aux zones autorisées en flash.
Fermez gdb et le driver de sonde JLink, débranchez votre carte puis rebranchez-la. Vérifiez que votre s'exécute correctement tout seul.
Recopie du code en RAM
Sur beaucoup de processeurs l'accès à la flash est plus lent que l'accès à la RAM. C'est le cas sur votre processeur.
Modifiez votre code et votre linker script de façon à ce que le code
- commence par s'exécuter en flash,
- s'auto-recopie en RAM,
- transfère son exécution à la partie située en RAM.
On laissera la section .rodata en flash. On relogera la table des vecteurs d'interruption en RAM, de façon à donner à l'utilisateur la possibilité de mettre en place ses propres handlers d'IRQ.
N'oubliez pas de mettre le tag FLASH sur votre dernier commit et de pusher le tout sur master :-)
Conclusion
Si vous êtes arrivé jusqu'ici, BRAVO ! Vous savez maintenant comment un système embarqué démarre, est configuré, comment accéder à ses périphériques et comment lancer un exécutable. Vous êtes aussi en mesure de programmer une carte from scratch, sans libC, sans qu'il n'y ait rien dessus. C'est une compétence rare, soyez en fiers !
Nous espérons que cette UE et ce TD vous ont plu et ont pu démystifier la génération des exécutables et le fonctionnement d'un système à processeur basique :-)