65 votes

Quel est le processus de démarrage pour ARM ?

Comme nous le savons, pour l'architecture X86 : Après avoir appuyé sur le bouton d'alimentation, la machine commence à exécuter du code à 0xFFFFFFF0, puis elle commence à exécuter du code dans le BIOS afin d'effectuer l'initialisation du matériel. Après l'exécution du BIOS, il utilise le bootloader pour charger l'image du système d'exploitation dans la mémoire. Enfin, le code du système d'exploitation commence à s'exécuter. Pour l'architecture ARM, quel est le processus de démarrage après avoir appuyé sur le bouton d'alimentation ? Merci !

72voto

Igor Skochinsky Points 13292

Actuellement, il existe deux modèles d'exception dans l'architecture ARM (la réinitialisation est considérée comme un type d'exception) :

Le modèle classique, utilisé dans les puces pré-Cortex et les puces Cortex-A/R actuelles. Dans celui-ci, la mémoire à 0 contient plusieurs gestionnaires d'exceptions :

 Offset  Handler
 ===============
 00      Reset 
 04      Undefined Instruction
 08      Supervisor Call (SVC)
 0C      Prefetch Abort
 10      Data Abort
 14      (Reserved)
 18      Interrupt (IRQ)
 1C      Fast Interrupt (FIQ)

Lorsque l'exception se produit, le processeur commence l'exécution à partir d'un décalage spécifique, donc généralement cette table contient des branchements à instruction unique vers les gestionnaires complets plus loin dans le code. Une table vectorielle classique typique ressemble à ce qui suit :

00000000   LDR   PC, =Reset
00000004   LDR   PC, =Undef
00000008   LDR   PC, =SVC
0000000C   LDR   PC, =PrefAbort
00000010   LDR   PC, =DataAbort
00000014   NOP
00000018   LDR   PC, =IRQ
0000001C   LDR   PC, =FIQ

Au moment de l'exécution, la table vectorielle peut être relocalisée à 0xFFFF0000, qui est souvent implémentée comme une plage de mémoire à couplage étroit pour le traitement le plus rapide des exceptions. Cependant, la réinitialisation à la mise sous tension commence généralement à 0x00000000 (mais dans certaines puces, elle peut être fixée à 0xFFFF0000 par une broche du processeur).

Le nouveau modèle de microcontrôleur est utilisé dans la gamme de puces Cortex-M. Là, la table de vecteurs à 0 est en fait une table de vecteurs (pointeurs), et non d'instructions. La première entrée contient la valeur de démarrage pour le registre SP, la seconde est le vecteur de réinitialisation. Cela permet d'écrire le gestionnaire de réinitialisation directement en C, puisque le processeur met en place la pile. Encore une fois, la table peut être déplacée au moment de l'exécution. La table de vecteurs typique pour Cortex-M commence comme ceci :

__Vectors       DCD     __initial_sp              ; Top of Stack
                DCD     Reset_Handler             ; Reset Handler
                DCD     NMI_Handler               ; NMI Handler
                DCD     HardFault_Handler         ; Hard Fault Handler
                DCD     MemManage_Handler         ; MPU Fault Handler
                DCD     BusFault_Handler          ; Bus Fault Handler
                DCD     UsageFault_Handler        ; Usage Fault Handler
                [...more vectors...]

Notez que dans les puces complexes modernes telles que l'OMAP3 ou l'A4 d'Apple, le premier morceau de code exécuté n'est généralement pas du code utilisateur mais la ROM de démarrage de la puce. Elle peut vérifier diverses conditions pour déterminer d'où charger le code utilisateur et s'il faut le charger tout court (par exemple, elle peut exiger une signature numérique valide). Dans ce cas, le code utilisateur peut devoir se conformer à différentes conventions de démarrage.

3voto

artless noise Points 7110

... A la fin, le code du système d'exploitation commence à s'exécuter. Pour l'architecture ARM, quel est le processus de démarrage après avoir appuyé sur le bouton d'alimentation ?

Cette réponse s'inscrit principalement dans le contexte des CPU Cortex-A modernes ; il existe une grande variété de plateformes ARM. Cependant, pour un ARM qui ressemble à un PC (tablette, téléphone portable, etc.) ...

Le CPU ARM va chercher une instruction à partir de 0x0 ou 0xffff0000 (pour un Cortex-M, il s'agit de données plutôt que d'une instruction). Les SOC ARM typiques ont une rom de démarrage qui utilise ce mécanisme. Pour un utilisateur final, vous devez consulter un manuel pour déterminer comment faire fonctionner votre code. En d'autres termes, il existe un BIOS intégré dans de nombreux SOC ARM qui utilisent le vecteur, mais vous devez utiliser quelque chose de différent pour que votre code s'exécute.

En général, le SOC ARM prend en charge plusieurs périphériques de démarrage. Le périphérique est déterminé par un FUSE (défini par un outil de fabrication) ou par des broches d'échantillonnage. Les broches seront des sorties du CPU dans un système en cours d'exécution, mais ont été tirées vers le haut/bas pour configurer un dispositif d'amorçage. Chaque dispositif d'amorçage aura des détails particuliers ; la ROM est simple, mais la flash NAND, la flash SPI, la MMC, etc. nécessitent des détails de configuration. Ceux-ci sont souvent fournis par un FUSE intégré et/ou des broches d'échantillonnage. Une petite partie du dispositif peut être lue pour configurer davantage le dispositif.

Dans le cas d'une puce ARM profondément intégrée, il se peut qu'elle ne s'amorce qu'à partir de la mémoire flash embarquée et que ce processus soit beaucoup plus simple ; mais je pense que, d'après le contexte de la question, vous faites référence à des CPU ARM plus avancés. Les systèmes ARM plus avancés ont un chargeur de démarrage. En effet, la quantité de code qu'un chargeur ROM peut charger est souvent limitée et/ou restreinte. Il est également souvent complexe de configurer la SDRAM et le chargeur de démarrage peut être structuré pour fonctionner à partir de la RAM statique interne, qui configure la SDRAM.

Voir : Pourquoi nous avons besoin d'un chargeur de démarrage

L'exécution du système d'exploitation a ses propres problèmes particuliers. Pour ARM Linux, c'était ATAGS et c'est maintenant devicetree. Les gens peuvent coder leur propre chargeur de démarrage ou utiliser l'un des nombreux projets open-source, u-boot étant le plus courant. U-boots supporte vxWorks, Linux, NetBSD, Plan9, OSE, QNX, Integrity, et OpenRTOS ainsi que les images binaires.

De nombreux périphériques Linux ARM originaux supportaient un démarrage direct de Linux sans chargeur de démarrage. Cependant, Linux ne prend pas en charge cette fonctionnalité dans la gamme principale, sauf pour quelques très vieux SOC/cores ARM.

3voto

user1813332 Points 14

Après la mise sous tension, le processeur commencera à exécuter un mode d'exception, le premier étant la réinitialisation. Comme la réinitialisation doit se faire en mode superviseur, puisque le processeur ne connaît pas l'état du registre à ce moment de l'exécution, il ne peut pas passer en mode superviseur. Pour cela, un petit code doit être écrit (voir à la fin). Après cela, d'autres exceptions peuvent être traitées en chargeant l'adresse dans le PC.

.globl _start
 _start: b       reset
    ldr     pc, _undefined_instruction
    ldr     pc, _software_interrupt
    ldr     pc, _prefetch_abort
    ldr     pc, _data_abort
    ldr     pc, _not_used
    ldr     pc, _irq
    ldr     pc, _fiq

reset:
    mrs     r0,cpsr                 /* set the cpu to SVC32 mode        */
    bic     r0,r0,#0x1f             /* (superviser mode, M=10011)       */
    orr     r0,r0,#0x13
    msr     cpsr,r0

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X