Comment concevoir un chargeur d'amorçage pour les microcontrôleurs de la série STM32 ?

BootLoader est un terme courant pour beaucoup de gens, et il est même fréquemment utilisé. Par exemple, nous en avons besoin lors de la mise à niveau du système en ligne, pour exécuter le programme dans la mémoire externe. Dans cet article, nous allons vous présenter comment concevoir un programme BootLoader pour les microcontrôleurs de la série STM32.

Principe de base du BootLoader

Comme nous voulons implémenter un programme BootLOader pour STM32, nous devons d'abord comprendre les principes de base du programme BootLOader.

Comme nous le savons, le programme BootLOader doit permettre le guidage du système, ce qui est la fonction de base du programme BootLOader. Pour les microcontrôleurs de la série STM32, le programme sera exécuté à partir de l'adresse de démarrage de la mémoire Flash interne après le démarrage du système. Il faut ensuite entrer dans le programme d'application et l'exécuter selon l'ordre établi. À ce moment-là, le BootLoader et le programme d'application sont intégrés, comme le montre la figure :

BootLoader and APP start independently
BootLoader and APP start independently

Mais parfois, nous ne voulons pas que l'application s'exécute directement, par exemple lorsque nous voulons implémenter l'IAP pour le système ; ou nous ne voulons pas que l'application s'exécute dans notre mémoire Flash interne ; ou l'application s'exécute dans la mémoire Flash interne, mais nous voulons que l'application s'exécute à partir de l'adresse Flash interne que nous spécifions, etc. Dans ces cas-là, nous avons besoin d'un programme BootLoader distinct. Le système démarre d'abord le programme BootLoader, puis passe à l'exécution du programme d'application une fois que le système est prêt, comme le montre la figure :

BootLoader and APP run at the same time (APP is stored in internal Flash)
BootLoader and APP run at the same time (APP is stored in internal Flash)

Dans l'image ci-dessus, nous stockons en fait l'application à l'emplacement spécifié de la mémoire Flash interne, ce qui nous permet bien sûr de répondre à certains de nos besoins, tels que le système IAP. Bien sûr, nous pouvons également stocker le programme d'application dans la mémoire Flash externe, puis le programme BootLoader passe à la mémoire Flash externe pour exécuter le programme d'application, mais à condition que la mémoire Flash externe achète le programme d'exécution. Le processus spécifique est le suivant :

BootLoader and APP run at the same time (APP is stored in external Flash)
BootLoader and APP run at the same time (APP is stored in external Flash)

Bien sûr, ce n'est qu'un exemple, et il suffit de modifier l'adresse pour différentes mémoires. Quant aux fonctions à implémenter dans le programme BootLoader, cela dépend de l'utilisation. En principe, nous pouvons ajouter toutes les fonctions que nous voulons, telles que la détection du matériel, la mise à niveau du système, etc.

Conception du chargeur d'amorçage pour STM32

Planification éclair

Nous utilisons le STM32F407IGT6 comme microcontrôleur cible, qui dispose d'une mémoire Flash de 1 Mo et d'une mémoire SRAM de 192 Ko. Nous divisons la mémoire Flash en deux parties : l'une est la zone du programme d'amorçage (0x0800 0000 – 0x0800 3FFF) d'une taille de 16 Ko, et l'autre est la zone du programme d'application (0x0800 4000 – 0x080F FFFF). La répartition spécifique est la suivante :

Flash Division of MCU - Bootloader and APP
Flash Division of MCU - Bootloader and APP

Nous avons laissé le programme BootLoader occuper 16 Ko d'espace de stockage. Mais il peut exploiter tout l'espace de stockage Flash.

Structure du chargeur d'amorçage

Examinons la structure du programme BootLoader. L'objectif principal de notre conception du programme BootLoader est de mettre à niveau le programme d'application. Quelles sont donc les principales fonctions qui doivent être implémentées dans le programme BootLoader ? Plusieurs aspects doivent être pris en compte. L'un est la configuration de base, telle que l'horloge, etc., que nous implémentons dans le programme principal ; l'autre est le fonctionnement de la mémoire Flash, et nous vérifierons et écrirons certainement la mémoire Flash lorsque nous mettrons à niveau le programme d'application ; il s'agit du programme de contrôle de saut, nous devons exécuter le programme d'application à la fin, et la fonction de saut est essentielle. Bien sûr, il peut y avoir d'autres besoins en fonction des différents besoins. Plus précisément, comme le montre la figure ci-dessous :

BootLoader Program Functions
BootLoader Program Functions

Dans la figure ci-dessus, outre les trois implémentations de base de la signature, nous avons également ajouté la fonction d'obtention des fichiers IAP. Cette partie de la fonction est également nécessaire, mais il peut y avoir une grande différence selon les modes. En effet, les fichiers peuvent être obtenus via différents types de communication, tels que le port Ethernet, le port série, etc. Il peut également s'agir de différents types de mémoire, tels que les cartes SD, les clés USB, etc. Par conséquent, bien que cette fonction soit essentielle, la méthode de mise en œuvre est très flexible. Dans la mise en œuvre ultérieure, nous analyserons en détail les questions spécifiques.

Implémentation du chargeur d'amorçage

Maintenant que nous avons déterminé la division de Flash et compris le fonctionnement de base du BootLoader, je vais vous expliquer comment implémenter un programme BootLoader.

Encodage du chargeur d'amorçage

Nous savons que lorsque la puce est mise sous tension, elle exécute d'abord le programme BootLoader, puis passe à la zone du programme d'application pour exécuter le programme d'application. Par conséquent, lorsque nous écrivons le programme BootLoader, nous déterminons d'abord si le système a des exigences IAP. S'il y a une demande IAP, il passe en mode IAP. Une fois cette opération terminée, il passe au programme d'application pour l'exécuter. S'il n'y a pas de demande IAP, il passe directement au programme d'application pour l'exécuter. Le processus spécifique est le suivant :

Flow Chart of IAP Mode in BootLoader Operation
Flow Chart of IAP Mode in BootLoader Operation

En ce qui concerne le traitement de l'IAP, il existe différentes méthodes de traitement selon les situations. Nous nous intéressons ici principalement au programme de contrôle de saut. Définissez d'abord la première adresse de l'application et déclarez un type de pointeur de fonction. Les détails sont les suivants :

				
					#define ApplicationAddress 0x08004000 //Application first address definition

typedef void (*pFunction)(void); //Define the jump function pointer type
				
			

Certaines personnes pourraient se demander ce qui définit un tel type de pointeur de fonction, car nous finissons par sauter à la fonction Reset_Handler, nous devons donc disposer d'un pointeur de fonction capable de pointer vers cette fonction. Nous pouvons ensuite implémenter le programme de saut.

				
					/*jump to application processing function*/
static void JumpToApplication(void)
{
   uint32_tStackAddr; //Application stack address
   uint32_tResetVector; //The address of the application interrupt vector table
 
   pFunctionJumpToApp; //Define the jump function pointer
 
  __set_PRIMASK(1); //Turn off global interrupt
 
   StackAddr= *(__IO uint32_t*)ApplicationAddress; //0x08004000;
  ResetVector = *(__IO uint32_t*)(ApplicationAddress + 4); //0x08004004;
 
  if((StackAddr&0x2FFC0000)==0x20000000) //Check whether the stack top address is legal.
   {
    __set_MSP(StackAddr); //Initialize the application stack pointer
 
    JumpToApp = (pFunction)ResetVector;
    JumpToApp();
   }
}
				
			

Traitement des applications

Après avoir réalisé le codage du BootLoader, si nous voulons passer à l'application pour qu'elle s'exécute correctement, nous devons modifier l'application en conséquence. Il y a deux changements importants. Si l'application est un programme bare-metal, nous devons activer le midrange global avant de configurer l'horloge.

				
					/*Enable global interrupt, closed in BootLoader*/
 __set_PRIMASK(0);
				
			

Dans le même temps, l'adresse de décalage de la table de vecteurs mi-fin doit également être modifiée. Pour le STM32F07 que nous utilisons, elle peut être modifiée directement dans le fichier system_stm32f4xx.c.

				
					#define VECT_TAB_OFFSET  0x4000 /*!< Vector Table base offsetfield.
				
			

Ensuite, nous devons également apporter les modifications nécessaires à l'environnement de développement, en prenant comme exemple l'IAR EWARM V8.4 que nous utilisons. Modifiez les paramètres de la table des vecteurs d'interruption et de la zone de stockage Flash dans le fichier icf. Les détails sont les suivants :

Linker configuration file editor - Vector Table
Linker configuration file editor - Vector Table
Linker configuration file editor - Memory Regions
Linker configuration file editor - Memory Regions

Une fois la configuration ci-dessus terminée, nous pouvons télécharger le programme d'application et le programme BootLoader pour réaliser le saut correct.

Résumé

Dans cet article, nous venons de mettre en œuvre un programme BootLoader simple. Après le téléchargement vers le microcontrôleur cible, le saut est réalisé et le programme d'application fonctionne également normalement, ce qui montre que notre conception est correcte et que diverses fonctions peuvent être ajoutées sur cette base pour réaliser l'application IAP correspondante.

Il convient de noter que nous avons désactivé l'interruption globale dans le programme BootLoader. N'oubliez pas d'activer l'interruption globale avant que l'application n'initialise l'horloge système, sinon SystemTick ne pourra pas fonctionner et une erreur matérielle (hardfault) se produira. Cependant, si l'application s'exécute sur le RTOS, il peut être erroné d'activer l'interruption, ce qui nécessite une attention particulière.

Part à:

Retour en haut

Instant Quote