Mise en flash

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 = 0x08000000, 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

Après un reset, le processeur va exécuter l'instruction dont l'adresse se trouve à la 2e position de votre table des vecteurs. Cette adresse doit correspondre à l'adresse d'une fonction thumb (i.e. le bit 0 doit être à 1).

Est-ce bien le cas?

Si ce n'est pas le cas, déclarer dans votre crt0.s que le symbole _start est une fonction thumb comme suit :

    .thumb_func
_start:
    ....

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).

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 :-)

Fichier attachéTaille
Fichier clocks.c1.9 Ko