Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
inicializacion_de_procesador_cortex-a8 [2023/04/24 15:23]
cnigri exception set parte i
inicializacion_de_procesador_cortex-a8 [2024/05/17 11:16] (actual)
cnigri Correccion de descripcion
Línea 45: Línea 45:
 |[[https://developer.arm.com/documentation/dui0417/d/hardware-description/northbridge?lang=en | Northbridge]]| 0x70000000-0x8FFFFFFF| [[https://developer.arm.com/documentation/dui0417/d/programmer-s-reference/dynamic-memory-controller--dmc?lang=en | Dinamic Memory Controller]]| 512MB | |[[https://developer.arm.com/documentation/dui0417/d/hardware-description/northbridge?lang=en | Northbridge]]| 0x70000000-0x8FFFFFFF| [[https://developer.arm.com/documentation/dui0417/d/programmer-s-reference/dynamic-memory-controller--dmc?lang=en | Dinamic Memory Controller]]| 512MB |
  
-De la tabla se desprende que la memoria RAM se direcciona en el rango 0x70000000-0x8FFFFFFF, y que la parte superior del mismo (256MB) se encuentra espejado en 0x00000000-0x0FFFFFFF. Sin embargo se debe recordar que al estar en la etapa //Inicialización del SoC//, el DMC no se encuentra configurado por lo que no es posible emplear dicha memoria y por ende cualquier rango asociado a la misma.+De la tabla se desprende que la memoria RAM se direcciona en el rango 0x70000000-0x8FFFFFFF, y que el rango de direcciones numéricamente inferiores del mismo (256MB) se encuentra espejado en 0x00000000-0x0FFFFFFF. Sin embargo se debe recordar que al estar en la etapa //Inicialización del SoC//, el DMC no se encuentra configurado por lo que no es posible emplear dicha memoria y por ende cualquier rango asociado a la misma.
  
 Por su parte la ROM se direcciona en el rango 0x40000000- 0x5FFFFFFF y el controlador de este tipo de memorias no requiere inicialización, justamente para poder leer el código que permita satisfacer los requerimientos de la etapa //Inicialización del SoC//. Al parecer ya se encuentra resuelto el dilema sobre donde leer el código, pero al lector astuto seguramente le surgirá interrogante ¿Cómo puede ser esto posible, si la [[https://developer.arm.com/documentation/ddi0406/b/System-Level-Architecture/The-System-Level-Programmers--Model/Exceptions/Reset | Reset Vector Address]] es 0x00000000 o 0xFFFF0000?\\ Por su parte la ROM se direcciona en el rango 0x40000000- 0x5FFFFFFF y el controlador de este tipo de memorias no requiere inicialización, justamente para poder leer el código que permita satisfacer los requerimientos de la etapa //Inicialización del SoC//. Al parecer ya se encuentra resuelto el dilema sobre donde leer el código, pero al lector astuto seguramente le surgirá interrogante ¿Cómo puede ser esto posible, si la [[https://developer.arm.com/documentation/ddi0406/b/System-Level-Architecture/The-System-Level-Programmers--Model/Exceptions/Reset | Reset Vector Address]] es 0x00000000 o 0xFFFF0000?\\
-Para resolver esta duda perfectamente válida apelamos a la //"magia"// del [[https://developer.arm.com/documentation/dui0417/d/hardware-description/northbridge?lang=en | Northbridge]], este ASIC específico de esta placa se encarga de [[https://developer.arm.com/documentation/dui0417/d/programmer-s-reference/configuration-and-initialization/remapping-of-boot-memory?lang=en | remapear]] la NOR de 0x40000000- 0x40FFFFFF a 0x00000000-0x00FFFFFF. Si bien esto ya brinda cierta claridad sobre donde debe situarse el código, es importante observar que el rango remapeado es tan solo de 16MB, frente a los 512MB disponibles en el mapa de memoria, esto significa que si bien la placa puede disponer de una NOR de hasta 512MB el código de arranque en la misma solo puede estar alojado en los primeros 16MB, quedando el restante espacio para disponible para el código complementario. Esto es importante tenerlo presente al momento de generar el mapa de memoria del código por lo general mediante el [[guiasupervivenciald|linker script]]+Para resolver esta duda perfectamente válida apelamos a la //"magia"// del [[https://developer.arm.com/documentation/dui0417/d/hardware-description/northbridge?lang=en | Northbridge]], este ASIC específico de esta placa se encarga de [[https://developer.arm.com/documentation/dui0417/d/programmer-s-reference/configuration-and-initialization/remapping-of-boot-memory?lang=en | remapear]] la NOR de 0x40000000- 0x40FFFFFF a 0x00000000-0x00FFFFFF. Si bien esto ya brinda cierta claridad sobre donde debe situarse el código, es importante observar que el rango remapeado es tan solo de 16MB, frente a los 512MB disponibles en el mapa de memoria, esto significa que si bien la placa puede disponer de una NOR de hasta 512MB el código de arranque en la misma solo puede estar alojado en los primeros 16MB, quedando el restante espacio para disponible para el código complementario. Esto es importante tenerlo presente al momento de generar el mapa de memoria del código por lo general mediante el [[guiasupervivenciald_arm|linker script]]
  
  
Línea 80: Línea 80:
  
 La primer acción que se debe realizar es garantizar que el procesador se encuentra en el modo y privilegio de operación que permita el acceso a los recursos del mismo.\\ La primer acción que se debe realizar es garantizar que el procesador se encuentra en el modo y privilegio de operación que permita el acceso a los recursos del mismo.\\
-En ARMv7 este modo se denomina //Supervisor// normalmente se referencia como //svc//. Si bien por [[https://developer.arm.com/documentation/ddi0406/c/System-Level-Architecture/The-System-Level-Programmers--Model/Exception-descriptions/Reset | manual se especifica]] que este es el modo que el procesador arranca luego de un reinicio, se debe asegurarlo, para lo cual se emplean los 5 bits menos significativos del [[https://developer.arm.com/documentation/ddi0601/2022-12/AArch32-Registers/CPSR--Current-Program-Status-Register?lang=en | Current Program Status Register]], denominados campo de modo (CPSR.M -> CPSR[4:0]).+En ARMv7 este modo se denomina //Supervisor// normalmente se referencia como //svc//. Si bien por [[https://developer.arm.com/documentation/ddi0406/c/System-Level-Architecture/The-System-Level-Programmers--Model/Exception-descriptions/Reset | manual se especifica]] que este es el modo en el que el procesador arranca luego de un reinicio, se debe asegurarlo, para lo cual se emplean los 5 bits menos significativos del [[https://developer.arm.com/documentation/ddi0601/2022-12/AArch32-Registers/CPSR--Current-Program-Status-Register?lang=en | Current Program Status Register]], denominados campo de modo (CPSR.M -> CPSR[4:0]).
 Dado que el estado del SoC y sobre todo de los periféricos de la placa no es conocido, se debe evitar que algún estimulo externo perturbe la secuencia de inicialización, es decir se deben deshabilitar las interrupciones, que en el caso de ARMv7 son IRQ y FIQ.\ Dado que el estado del SoC y sobre todo de los periféricos de la placa no es conocido, se debe evitar que algún estimulo externo perturbe la secuencia de inicialización, es decir se deben deshabilitar las interrupciones, que en el caso de ARMv7 son IRQ y FIQ.\
 En el caso de ARMv7 la deshabilitación de las interrupciones se realiza con el mismo registro (CPSR.I -> CPSR[7], CPSR.F -> CPSR[6]) que se emplea para configurar el modo de operación por lo cual en un paso se realizan dos subetapas En el caso de ARMv7 la deshabilitación de las interrupciones se realiza con el mismo registro (CPSR.I -> CPSR[7], CPSR.F -> CPSR[6]) que se emplea para configurar el modo de operación por lo cual en un paso se realizan dos subetapas
Línea 156: Línea 156:
      mov pc, lr      mov pc, lr
 </code> </code>
 +Empleando [[https://keleshev.com/ldm-my-favorite-arm-instruction/ | loadmultiple]] y [[https://azeria-labs.com/load-and-store-multiple-part-5/ | storemultiple]]
 <code asm> <code asm>
 ldr r0, _direccion_origen ldr r0, _direccion_origen
Línea 163: Línea 163:
 bl mem_cpy bl mem_cpy
  
-@ Opcion B con incremento de a double word veces (r3 a r10+@ Opcion B con incremento de a double word veces (r3 a r10
 mem_cpy: mem_cpy:
     add r2, r2, r0     add r2, r2, r0
Línea 191: Línea 191:
 stack_setup: stack_setup:
     ldr r0, #CONFIG_PILA_LIMITE_DIRECCION     ldr r0, #CONFIG_PILA_LIMITE_DIRECCION
-    sub r0, r0, #(CONFIG_PILA_IRQ_LARGO + CONFIG_PILA_FIQ_LARGO)+    sub r0, r0, #(CONFIG_PILA_SVC_LARGO + CONFIG_PILA_IRQ_LARGO + CONFIG_PILA_FIQ_LARGO)
     sub sp, r0, #12   @ 3 words para abort-stack     sub sp, r0, #12   @ 3 words para abort-stack
     bic sp, sp, #7    @ 8-byte ajuste para satisfacer alineacion requerida por ABI     bic sp, sp, #7    @ 8-byte ajuste para satisfacer alineacion requerida por ABI
Línea 198: Línea 198:
  
 <code asm> <code asm>
-ldr r0, #(CONFIG_PILA_LIMITE_DIRECCION - CONFIG_PILA_IRQ_LARGO - CONFIG_PILA_FIQ_LARGO - 12)+ldr r0, #(CONFIG_PILA_LIMITE_DIRECCION - CONFIG_PILA_SVC_LARGO - CONFIG_PILA_IRQ_LARGO - CONFIG_PILA_FIQ_LARGO - 12)
 bl stack_validate bl stack_validate
  
 stack_validate: stack_validate:
-    ldr r2, 0xA5A5A5A5 +    ldr r2, =0xA5A5A5A5 
-    ldr r3, 0xA5A5A5A5 +    ldr r3, =0xA5A5A5A5 
-    ldr r4, 0xA5A5A5A5 +    ldr r4, =0xA5A5A5A5 
-    ldr r5, 0xA5A5A5A5 +    ldr r5, =0xA5A5A5A5 
-    ldr r6, 0xA5A5A5A5 +    ldr r6, =0xA5A5A5A5 
-    ldr r7, 0xA5A5A5A5 +    ldr r7, =0xA5A5A5A5 
-    ldr r8, 0xA5A5A5A5 +    ldr r8, =0xA5A5A5A5 
-    ldr r9, 0xA5A5A5A5 +    ldr r9, =0xA5A5A5A5 
-    ldr r10, 0xA5A5A5A5+    ldr r10, =0xA5A5A5A5
     stack_write_fast:     stack_write_fast:
         sub r1, sp, #(CONFIG_PILA_LIMITE_DIRECCION - 36)         sub r1, sp, #(CONFIG_PILA_LIMITE_DIRECCION - 36)
Línea 263: Línea 263:
 Habiendo comprendido las restricciones de acceso a memoria específicas de cada uno de los casos de uso, se brinda a continuación el código básico de implementación de la [[https://developer.arm.com/documentation/den0013/d/Exception-Handling/Exception-priorities?lang=en#CEGHDCAE | tabla de vectores]], así como también el preámbulo y el epílogo de las excepciones estandar. Habiendo comprendido las restricciones de acceso a memoria específicas de cada uno de los casos de uso, se brinda a continuación el código básico de implementación de la [[https://developer.arm.com/documentation/den0013/d/Exception-Handling/Exception-priorities?lang=en#CEGHDCAE | tabla de vectores]], así como también el preámbulo y el epílogo de las excepciones estandar.
  
-El siguiente fragmento muestra las dos variantes para direccionar el controlador de excepción:+El siguiente fragmento muestra las [[https://developer.arm.com/documentation/den0013/d/Exception-Handling/Exception-priorities/The-Vector-table | dos variantes para direccionar]],en la  [[https://developer.arm.com/documentation/den0013/d/Exception-Handling/Exception-priorities?lang=en#CEGHDCAE | tabla de vectores]], el controlador de excepción:
   * **b**: para bifurfaciones/saltos de hasta 32MB   * **b**: para bifurfaciones/saltos de hasta 32MB
   * **ldr pc**: bifurfaciones sin restricciones de rango por fuera de la propia arquitectura   * **ldr pc**: bifurfaciones sin restricciones de rango por fuera de la propia arquitectura
 <code asm> <code asm>
-.globl _start_generic +.global _start_generic 
-_start:_generic                           @ Etiqueta para referencia punto de entrada y tabla  +_start_generic                            @ Etiqueta para referencia punto de entrada y tabla  
-    b reset                                     @ Configuracion de modo y deshabilitacion de interrupciones+    b reset                                 @ Configuracion de modo y deshabilitacion de interrupciones
     ldr pc, _undefined_instruction     ldr pc, _undefined_instruction
     ldr pc, _software_interrupt     ldr pc, _software_interrupt
     ldr pc, _prefetch_abort     ldr pc, _prefetch_abort
     ldr pc, _data_abort     ldr pc, _data_abort
-    ldr pc, _not_used+    nop                                     @ No usado 
 +    ;En forma mas profesional se podria implementar ldr pc, _not_used donde se trata con preambulo y epilogo;
     ldr pc, _irq     ldr pc, _irq
     ldr pc, _fiq     ldr pc, _fiq
 </code> </code>
-En el código prec 
  
 +Una vez que la excepción es [[https://developer.arm.com/documentation/den0013/d/Exception-Handling/Exception-handling | manejada/vectorizada]] por el procesador, es decir se alcanza a la bifucarción correspondiente de la tabla precedente, es responsabilidad del desarrollador establecer la pila del modo de operación, resguardar la información que generó la excepción y establecer al procesador en modo Supervisor, esto se conoce como preambulo y a continuación se propone un ejemplo
 +
 +<code asm>
 +.align 5
 +_undefined_instruction
 +    ldr r13, #CONFIG_POR_MODE_PILA_LIMITE_DIRECCION
 +    str lr, [r13]   @ resguarda direccion de instruccion genero exepcion
 +    mrs lr, spsr          @ Move to Register lr from Special register spsr
 +    str lr, [r13, #4]   @ resguardo del State Program Status Register
 +    mov r13, 0xd3         @ Prepara la conmutacion a modo Supervisor (xIQ deshabilitadas)
 +    msr spsr, r13
 +    mov lr, pc
 +    movs pc, lr           @ Conmuta de modo
 +</code>
 +
 +En la excepciones _prefetch_abort y _data_abort el preambulo es equivalente, solo el valor de //**lr**//, referencia en el primer caso [[https://developer.arm.com/documentation/ddi0406/c/System-Level-Architecture/The-System-Level-Programmers--Model/Exception-descriptions/Prefetch-Abort-exception | sub lr, lr, #4 ]], mientras que en el segundo [[ https://developer.arm.com/documentation/ddi0406/c/System-Level-Architecture/The-System-Level-Programmers--Model/Exception-descriptions/Data-Abort-exception | sub lr, lr, #8]]
 +
 +El siguiente paso es preservar los registros //"no banqueados"// a fin de disponer de la información (foto de estado) completa que pudo producir la excepción, y recuperar de la pila del modo previo (Abort o Undef) los valores del **//lr//** y **//spsr//**. En pocas palabras se dispone de dos modos de operación que requieren acceder a la misma información, sin que se pierda en el acceso o la conmutación, siendo el recurso común/compartido la memoria. En SoC donde existe un procesador principal (proposito general) y otro dedicado (RealTime, Grafico, etc), la técnica de compartir memoria se suele llamar //carveaout// y emplearemos una variante para satisfacer el requerimiento planteado.
 +El concepto es simple, establecer un marco (no importa la posición absoluta de inicio) de referencia con desplazamientos bien definidos (relativos)
 +
 +<code asm>
 +#define REGISTER_SIZE 4
 +#define FRAME_R0    0
 +#define FRAME_R1    FRAME_R0 + REGISTER_SIZE                @4
 +#define FRAME_R2    FRAME_R1 + REGISTER_SIZE                @8
 +#define FRAME_R3    FRAME_R2 + REGISTER_SIZE                @12
 +#define FRAME_R4    FRAME_R3 + REGISTER_SIZE                @16
 +#define FRAME_R5    FRAME_R4 + REGISTER_SIZE                @20
 +#define FRAME_R6    FRAME_R5 + REGISTER_SIZE                @24
 +#define FRAME_R7    FRAME_R6 + REGISTER_SIZE                @28
 +#define FRAME_R8    FRAME_R7 + REGISTER_SIZE                @32
 +#define FRAME_R9    FRAME_R8 + REGISTER_SIZE                @36
 +#define FRAME_R10   FRAME_R9 + REGISTER_SIZE                @40
 +#define FRAME_FP    FRAME_R10 + REGISTER_SIZE               @44
 +#define FRAME_IP     FRAME_FP + REGISTER_SIZE               @48
 +#define FRAME_SP    FRAME_IP + REGISTER_SIZE                @52
 +#define FRAME_LR    FRAME_SP + REGISTER_SIZE                @56
 +#define FRAME_PC    FRAME_LR + REGISTER_SIZE                @60
 +#define FRAME_PSR  FRAME_PC + REGISTER_SIZE                 @64
 +#define FRAME_R0_BCKP  FRAME_PSR + REGISTER_SIZE            @68
 +#define FRAME_SIZE  FRAME_R0_BCKP + FRAME_R0_BCKP           @72
 +</code>
 +
 +En código se puede emplear una macro equivalente a la siguiente propuesta
 +<code asm>
 +.macro pseudo_context_get
 +    sub sp, sp, #FRAME_SIZE   @ Posiciono el marco
 +    stmia sp, {r0 - r12}      @ resguarda r0-r12 en pila de SVC
 +    ldr  r2, #CONFIG_POR_MODE_PILA_LIMITE_DIRECCION
 +    ldmia r2, {r2 - r3}       @ recupera de pila de modo anterior lr y spsr
 +    add r0, sp, #FRAME_SIZE   @ reseguarda la pila original
 +    add r5, sp, #FRAME_SP
 +    mov r1, lr
 +    stmia   r5, {r0 - r3}     @ resguarda sp y lr de SVC, y lr, spsr de modo anterior
 +    mov r0, sp
 +    .endm
 +</code>
 +
 +Esto permite implementar los controladores de excepción en C
 +
 +<code asm>
 +.align 5
 +_prefetch_abort
 +    ldr r13, #CONFIG_POR_MODE_PILA_LIMITE_DIRECCION
 +    str lr, [r13]   @ resguarda direccion de instruccion genero exepcion
 +    mrs lr, spsr          @ Move to Register lr from Special register spsr
 +    str lr, [r13, #4]   @ resguardo del State Program Status Register
 +    mov r13, 0xd3         @ Prepara la conmutacion a modo Supervisor (xIQ deshabilitadas)
 +    msr spsr, r13
 +    mov lr, pc
 +    movs pc, lr           @ Conmuta de modo
 +    pseudo_context_get
 +    bl prefetch_abort_handler
 +</code>
 +
 +Siendo el prototipo de la funcion en C acorde a [[https://github.com/ARM-software/abi-aa/releases | ARM Architecture Procedure Call Standard]]
 +<code c>
 +void prefetch_abort_handler(unsigned long *frame_ptr);
 +</code>
 <html><b><u><span style="color:orange;font-size:150%;">core reset</span></u></b></html> <html><b><u><span style="color:orange;font-size:150%;">core reset</span></u></b></html>
  
Línea 294: Línea 373:
 </code> </code>
  
- --- //[[cnigri@frba.utn.edu.ar|ChristiaN]] 2023/04/24 15:22//+ --- //[[cnigri@frba.utn.edu.ar|ChristiaN]] 2024/05/17 11:17//