Comme nous le savons, pour l'architecture X86: après avoir appuyé sur le bouton d'alimentation, la machine commence à exécuter le code à 0xFFFFFFF0, puis elle commence à exécuter le code dans le BIOS afin de faire l'initialisation matérielle. Après l'exécution du BIOS, il utilise le chargeur de démarrage pour charger l'image du système d'exploitation dans la mémoire. À 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 utilisation, appuyez sur le bouton d'alimentation? Merci!
Actuellement, il existe deux modèles d'exception dans l'architecture ARM (la réinitialisation est considérée comme une sorte d'exception):
Le modèle classique, utilisé dans les puces pré-Cortex et les puces Cortex-A/R actuelles. Dans ce document, 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 simplement l'exécution à partir d'un décalage spécifique, donc généralement cette table contient des branches à instruction unique vers les gestionnaires complets plus loin dans le code. Une table vectorielle classique typique ressemble à ceci:
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 déplacée vers 0xFFFF0000, qui est souvent implémentée en tant que plage de mémoire étroitement couplée pour la gestion des exceptions la plus rapide. Cependant, la réinitialisation à la mise sous tension commence généralement à 0x00000000 (mais dans certaines puces, elle peut être définie sur 0xFFFF0000 par une broche de processeur).
Le nouveau modèle de microcontrôleur est utilisé dans la gamme de puces Cortex-M. Là, la table vectorielle à 0 est en fait une table de vecteurs (pointeurs), pas d'instructions. La première entrée contient la valeur de démarrage du 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 configure la pile. Encore une fois, la table peut être déplacée au moment de l'exécution. La table vectorielle typique pour Cortex-M commence comme suit:
__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 OMAP3 ou A4 d'Apple, le premier morceau de code qui est exécuté n'est généralement pas du code utilisateur mais la ROM de démarrage sur puce. Il peut vérifier diverses conditions pour déterminer d'où charger le code utilisateur et s'il doit le charger (par exemple, il peut nécessiter une signature numérique valide). Dans de tels cas, le code utilisateur peut devoir se conformer à différentes conventions de démarrage.
... À 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 utilisation, appuyez sur le bouton d'alimentation?
Cette réponse se situe principalement dans le contexte des processeurs Cortex-A modernes; il existe une grande variété de plates-formes ARM. Cependant, pour un ARM qui ressemble à un PC (tablette, téléphone portable, etc.) ...
Le ARM CPU récupérera une instruction de 0x0 ou 0xffff0000 (pour un Cortex-M, ce sont des données par opposition à une instruction). Typique ARM SOC avoir une ROM de démarrage qui utilise ce mécanisme. Pour un utilisateur final, vous devez consulter un manuel pour déterminer comment exécuter votre code. C'est-à-dire qu'il existe un [~ # ~] bios [~ # ~] intégré à de nombreux ARM SOC qui utilisent le vecteur, mais vous devez utiliser quelque chose de différent pour exécuter votre code.
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 fusible (défini par un outil de fabrication) ou par des broches d'échantillonnage. Les broches seront des sorties CPU dans un système en cours d'exécution, mais ont été tirés vers le haut/bas pour configurer un périphérique de démarrage. Chaque périphérique de démarrage aura des détails particuliers; ROM est simple, mais flash NAND, SPI flash, MMC , etc. ont besoin de certains détails de configuration. Ils sont également souvent fournis par un fusible sur la puce et/ou des broches d'échantillonnage. Une petite partie de l'appareil peut être lue pour configurer davantage l'appareil.
Pour une puce ARM profondément intégrée, elle ne peut démarrer qu'à partir du flash intégré et ce processus est beaucoup plus simple; mais je crois que dans le contexte de la question à laquelle vous faites référence, plus avancée ARM CPU. Plus avancés ARM ont un chargeur de démarrage. Cela est dû au fait que la quantité de code a ROM que le chargeur chargera est souvent La configuration de la SDRAM est également souvent complexe et le chargeur de démarrage peut être structuré pour fonctionner à partir de la RAM statique interne, ce 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 est maintenant devicetree. Les gens peuvent coder leur propre chargeur de démarrage ou utiliser l'un des nombreux projets open source avec u-boot étant le plus courant. U-boots prend en charge vxWorks, Linux, NetBSD, Plan9, OSE, QNX, Integrity et OpenRTOS ainsi que des images binaires.
De nombreux périphériques Linux ARM Linux pris en charge un démarrage direct de Linux sans chargeur de démarrage. Cependant, Linux ne prend pas en charge cette dans la ligne principale, à l'exception de quelques très anciens ARM SOC/cores.
Après la mise sous tension Le processeur commencera à exécuter le mode d'exception Le premier est réinitialisé, car la réinitialisation doit s'exécuter en mode superviseur car le processeur ne connaît pas l'état du registre à ce moment de l'exécution, il ne peut pas passer en mode superviseur. un petit code doit être écrit (voir à la fin). après cela, d'autres exceptions peuvent être géré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