Pourquoi avons-nous besoin d'un programme distinct dans la même mémoire de programme flash d'un microcontrôleur, en particulier STM32F103, qui est appelé un chargeur de démarrage?
Quelle est la particularité de le garder séparé du programme d'application principal?
De manière générale, un chargeur de démarrage d'un système à microprocesseur (par exemple PowerPC MPC8270) fait-il le même travail que celui d'un microcontrôleur (par exemple ARM STM32F103) ou fait-il des travaux fondamentalement différents les uns des autres et pourtant les deux sont appelés un `` chargeur de démarrage '' ?
microcontroller
stm32
programming
flash
bootloader
alt-rose
la source
la source
Réponses:
Un chargeur de démarrage sur un microcontrôleur est responsable de la mise à jour du micrologiciel principal sur un canal de communication autre que l'en-tête de programmation. Ceci est utile pour mettre à jour le firmware sur le terrain via BLE, UART, I2C, cartes SD, USB, etc. Il serait extrêmement gênant d'exiger des clients qu'ils achètent des programmeurs juste pour mettre à jour le firmware sur leurs appareils.
La raison pour laquelle le chargeur de démarrage est conservé séparément est pour la fiabilité. Le chargeur de démarrage et le code d'application sont placés dans des sections distinctes de Flash, de sorte que le code d'application peut être effacé et réécrit par le chargeur de démarrage sans changer quoi que ce soit lié au code du chargeur de démarrage.
Si le chargeur de démarrage et l'application étaient conservés ensemble, le code du chargeur de démarrage devrait être copié dans la RAM avant de pouvoir s'exécuter, car toute mise à jour du micrologiciel effacerait le code du chargeur de démarrage en flash. Si l'alimentation était coupée avec le code du chargeur de démarrage dans la RAM et que le flash était effacé, l'appareil serait maçonné.
la source
main()
fonction. À la mise sous tension, le code de démarrage du chargeur de démarrage s'exécute et appelle le chargeur de démarragemain()
. Le programme de chargeur de démarrage recherche un programme d'application valide, puis passe au code de démarrage du programme d'application qui appelle celui-cimain()
. Le code de démarrage de chaque programme initialise l'environnement d'exécution C pour le programme respectif (c'est-à-dire initialise les variables, la pile, etc.) et généralement, aucun des programmesmain()
ne revient jamais au code de démarrage.main
du tout.Pour que le processus de chargement puisse récupérer des erreurs. Supposons qu'il y ait une erreur de communication ou une coupure d'alimentation pendant une mise à niveau. Si le chargeur de démarrage faisait partie de l'application que vous mettiez à niveau, l'utilisateur ne pourrait pas réessayer sans utiliser de matériel spécial pour reflasher le chargeur de démarrage.
Certains microcontrôleurs ne peuvent pas exécuter de code à partir de la RAM. Si le chargeur de démarrage était mélangé avec le reste du logiciel, vous ne seriez pas en mesure de mettre à niveau votre logiciel car vous ne pouvez pas effacer les pages de flash que vous exécutez actuellement. La solution consiste à graver d'abord le nouveau code dans la seconde moitié du flash, puis à y accéder. Le nouveau code se copie ensuite dans la première moitié du flash. Bien sûr, l'inconvénient est que la gravure du flash est généralement lente et maintenant que vous devez le faire deux fois, le processus de chargement peut prendre jusqu'à deux fois plus de temps. Cette solution de contournement limite également la taille de votre application à pas plus de la moitié de votre flash total.
Des chargeurs de démarrage bien écrits essaient de vérifier qu'un code valide existe sur le périphérique avant d'essayer de l'exécuter. Si le chargeur de démarrage et d'autres codes étaient mélangés, comment pourriez-vous être sûr que votre routine de validation fonctionnerait si tout le code ne se chargeait pas?
Authentification. Les chargeurs de démarrage sécurisé essaient de vérifier que l'application chargée correspond à une signature numérique avant de s'exécuter. Mais si le chargeur de démarrage et d'autres codes ont été mélangés, vous ne pouvez pas contrôler ce qui s'exécute sur l'appareil, car une fois que l'utilisateur a chargé le nouveau code, vous ne pouvez pas contrôler ce qui se passe au démarrage.
la source
Ils sont généralement là pour vous permettre de mettre à jour votre programme d'application principal.
Vous avez besoin d'un code qui sait comment effacer et reprogrammer une partie du flash interne, qui ne peut pas être le programme principal car lorsqu'il est effacé, il ne pourra pas reprogrammer.
la source
Le chargeur de démarrage permet au MCU de communiquer avec quelque chose d'autre pour accepter un nouveau programme, le stocker et l'exécuter après une réinitialisation. Si vous n'aviez pas de chargeur de démarrage, un programmeur est nécessaire pour accéder à la mémoire et mettre le programme en place.
la source
En plus des autres bonnes réponses sur la possibilité de reprogrammer le micrologiciel principal à partir du chargeur de démarrage, un autre avantage de la séparation du chargeur de démarrage est que vous pouvez logiquement séparer les tâches "ne faire qu'une fois au démarrage" du code dont vous avez besoin pendant l'exécution. Ensuite, une fois que le chargeur de démarrage a terminé ses tâches de configuration initiales, le micrologiciel principal peut expulser le chargeur de démarrage avec tout son code qui n'est plus nécessaire de la mémoire, économisant ainsi un espace RAM important. Il est possible d'y parvenir par d'autres moyens, mais la répartition chargeur de démarrage / micrologiciel facilite beaucoup les choses sur de nombreuses architectures.
la source
La réponse courte est que le logiciel est génial.
Vous pourriez avoir tout ce que le chargeur de démarrage est "purement matériel". Mais il est de loin, beaucoup, beaucoup plus facile d'avoir les tâches que le chargeur de démarrage soit écrites en tant que logiciel, puis interprétées par le matériel.
Ces tâches peuvent impliquer la configuration du matériel pour que le "vrai" logiciel s'exécute (par exemple, sur un Raspberry Pi (via @ErikF)), ayant un protocole pour remplacer le "vrai" programme avant son exécution (vérifiez une broche, si cette broche est définie puis reflasher le programme réel), ou même configurer l'environnement logiciel pour le programme "réel".
Sur des logiciels moins à petite échelle, lorsque vous exécutez un exécutable, le chargeur d'application déplace des choses comme le chargement de parties de vos données en mémoire, corrige parfois des adresses, configure des arguments sur des éléments principaux ou autres, fait tourner les bibliothèques fournies par votre système d'exploitation et saute ensuite au début du
_main
code. Certaines de ces choses peuvent être effectuées par un chargeur de démarrage.Dans un microcontrôleur, certaines des tâches effectuées par un chargeur de démarrage peuvent être réparties dans le programme. Le compilateur de votre plateforme pourrait injecter automatiquement le code "setup" dans chaque exécutable.
Mais, l'avoir dans le chargeur de démarrage signifie que le même compilateur peut fonctionner sur un matériel différent, car le chargeur de démarrage peut «masquer» la différence entre les plates-formes.
Ajoutez à cela le fait qu'un flash du programme principal ne risque pas le chargeur de démarrage (et la possibilité de reflasher le programme principal), et avoir un chargeur de démarrage non trivial est une très bonne chose.
la source
Une réponse qui n'a pas été abordée est la nécessité de séparer les préoccupations en raison des limites du langage C.
Généralement, les chargeurs de démarrage sont écrits dans un mélange d'Assembly et de C, avec le tout premier stade de démarrage dans Assembly.
Ceci est fait pour configurer certaines choses comme:
Il s'agit d'une approximation très approximative des étapes suivies et je décris le processus de démarrage ARM, il est à nouveau différent pour x86 et d'autres architectures.
Cependant, la raison principale reste la même: l'allocation de la pile C doit se faire depuis l'assemblage.
la source
Une partie de la question à laquelle on n'a pas répondu jusqu'à présent est la différence entre les chargeurs de démarrage sur les microcontrôleurs et les systèmes à microprocesseurs.
Microcontrôleur
La plupart des microcontrôleurs ont une mémoire ROM intégrée qui contient leur code de programme. La modification de ce code nécessite généralement un dispositif de programmation qui se connecte à l'interface de programmation du microcontrôleur (par exemple ISP sur ATMega). Mais ces interfaces de programmation ne sont généralement pas très pratiques à utiliser, par rapport à d'autres interfaces, car elles peuvent ne pas être facilement disponibles dans le contexte donné. Ainsi, par exemple, alors que presque tous les ordinateurs sont équipés de ports USB, l'interface SPI requise pour le FAI est beaucoup plus rare, et d'autres interfaces comme l'interface PID utilisée sur ATXMega ne sont prises en charge que par du matériel de programmation dédié.
Ainsi, par exemple, si vous souhaitez mettre à jour le logiciel à partir d'un ordinateur ordinaire sans aucun matériel externe, vous pouvez utiliser un chargeur de démarrage qui lit à partir d'un autre type d'interface (par exemple RS232, USB ou RS232 sur USB comme sur l'Arduino) pour programmer l'appareil sur des interfaces communes.
Cela dit, si vous n'avez pas besoin de cette fonctionnalité, le chargeur de démarrage est complètement facultatif. Le microcontrôleur peut toujours exécuter son code complètement sans le chargeur de démarrage.
Microprocesseur
Sur un microprocesseur, les choses sont un peu différentes. Alors que la plupart des microprocesseurs disposent d'une ROM suffisamment grande pour un chargeur de démarrage, ces ROM ne sont pas assez grandes pour contenir un système d'exploitation complet. Le but du chargeur de démarrage est donc d'initialiser le matériel, de rechercher un système d'exploitation amorçable, de le charger et de l'exécuter. Le chargeur de démarrage est donc essentiel pour chaque démarrage.
Sur les systèmes x86 / x64, ce chargeur de démarrage est soit le BIOS, soit l'UEFI (essentiellement une version plus récente d'un BIOS).
Parfois, vous pouvez même avoir plusieurs chargeurs de démarrage exécutés dans une chaîne. Par exemple, si vous avez un système à double démarrage avec Windows et Linux, vous pourriez vous retrouver avec ce qui suit:
Donc, dans ce cas, il y avait trois logiciels qui peuvent être considérés comme un chargeur de démarrage. GRUB et Windows Bootloader sont principalement là pour donner à l'utilisateur une option de sélection de démarrage plus pratique que le BIOS / UEFI ne leur donnerait. Il permet également de lancer plusieurs systèmes d'exploitation à partir du même disque dur ou même de la même partition.
TLDR
Donc, alors que dans les deux systèmes, le chargeur de démarrage fait des choses un peu similaires (aidant l'utilisateur à choisir le code à démarrer), ils diffèrent tous deux considérablement dans la façon dont ils accomplissent cela et ce qu'ils font exactement.
la source