Cómo grabar U-boot en una tarjeta SD
De s5pv210_irom_applicationnote_preliminary_20091126.pdf sabemos que el inicio de s5pv210 se divide en tres etapas: BL0, BL1 y BL2. BL0 es el código solidificado de la IROM interna de s5pv210. Este código selecciona desde qué dispositivo de almacenamiento externo cargar el código del segmento BL1 de acuerdo con el estado de configuración del pin OM (de hecho, el código del segmento BL1 es el primer código de 8K escrito por. nuestro UBOOT. Este código contiene una copia completa de la segunda mitad del código UBOOT y borra las funciones de la parte bss. Por supuesto, queremos iniciar desde la tarjeta SD grabada arriba) (Por supuesto, si queremos iniciar UBOOT desde la SD. tarjeta, el pin OM debe configurarse para arrancar desde la tarjeta SD).
Figura 1
Como se puede ver en la figura anterior, al arrancar desde la tarjeta SD, el código cargado por BL0 comienza a cargar el código desde el byte 512. ¿Por qué se hace esto? ? Debido a la necesidad de una futura expansión, el ingeniero de software de Samsung escribió el código BL0 solidificado en la IROM en el byte 512 del BL1 cargado desde la tarjeta SD. Esto es lo que escribió correspondientemente en la posición de UBOOT en la tarjeta SD. se moverá hacia atrás 512 bytes. Aquí hay una descripción de cómo especificar cómo escribir uboot en la tarjeta SD en la ubicación de comando especificada.
Y asegúrese de prestar atención a los siguientes puntos:
Figura 2
Hay 16 bytes de información de encabezado antes de BL1. En otras palabras, se deben agregar 16 bytes de información de encabezado antes de la primera instrucción del UBOOT real, por lo que hay una parte de definición de macro en el código de uboot y podemos ver el siguiente contenido:
[ cpp ] ver copia simple
#if definido (CONFIG_EVT1) amp; definir(CONFIG_FUSED)
.word 0x2000
.word 0x0
.word 0x0
.word 0x0
#endif
.globl _start
_start.b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
donde
.word 0x2000 representa el tamaño BL1 (8K de longitud), .word 0x0 es un byte reservado, .word 0x0 es una suma de comprobación (más adelante mkbl1 La herramienta se utilizará para calcular la suma de verificación de BL1 y completar esta posición), la última palabra 0x0 también es un byte reservado.
Mire la parte de uboot a continuación. Si bl0 lee bl1 normalmente, el código ingresará a la siguiente sección:
[cpp] ver copia simple
/* Leer. información de arranque */
ldr r0, =PRO_ID_BASE <
ldr r1, [r0, #OMR_OFFSET] // Leer el estado de configuración del pin OM
bic r2 , r1,
#ifdef CONFIG_VOGUES
/* PS_HOLD(GPH0_0) está configurado para generar un nivel alto*/
ldr r0, =ELFIN_GPIO_BASE
ldr r1, =0x00000001
str r1, [r0, #GPH0CON_OFFSET]
ldr r1, =0x5500
str r1, [r0, # GPH0PUD_OFFSET]
str r1, [r0, #GPH0CON_OFFSET GPH0PUD_OFFSET]
ldr r1, =0x01
str r1, [r0, #GPH0DAT_OFFSET]
#endif
/* NAND BOOT */
cmp r2, #0x0 @ 512B 4 ciclos
moveq r3, #BOOT_NAND //según El estado de configuración del pin OM asigna un valor de configuración al registro R3, que representa dónde comienza el sistema.
cmp r2, #0x2 @ 2KB 5 ciclos
moveq r3, #BOOT_NAND
cmp r2, #0x4 @ 4KB 5 ciclos 8 bits ECC p >
moveq r3, #BOOT_NAND
cmp r2, #0x6 @ 4KB ECC de 5 ciclos y 8 bits
moveq r3,
cmp r2 , #0x6 @ 4KB ECC de 5 ciclos y 16 bits
moveq r3, #BOOT_NAND
cmp r2, #0x8 @ OneNAND Mux
moveq r3, # BOOT_ONENAND
/* SD/MMC BOOT */
cmp r2, #0xclt; pre name="code" class="cpp"gt; _TEXT_PHY_BASE /* Establecer puntero de pila temporal*/
sub sp, sp, #12
mov fp, #0 /* No hay un fotograma anterior, por lo que fp=0 */
/* Cuando Ya estamos ejecutando RAM, no necesitamos reubicar U-Boot.
*De hecho, el controlador de memoria debe configurarse antes de que U-Boot pueda ejecutarse en la memoria.
*/
ldr r0, =0xff000fff
bic r1, pc, r0 /* r0 lt - la dirección base actual del código */ <; /p >
ldr r2, _TEXT_BASE /* r1 lt; - la dirección base original en la memoria */
bic r2, r2, r0 /* r0 lt - la dirección base actual del código. */ p>
bic r2, r2, r0 /* r0 lt - dirección base original en memoria - dirección base del código actual */
cmp r1, r2 /* comparar r0, r1 */
beq after_copy /* r0 == r1 luego omite la copia flash */lt;/pregt;lt;brgt;
moveq r3, #BOOT_MMCSD/* NOR BOOT * / cmp r2, #0x14moveq r3, # BOOT_NOR#if 0 /* ¡Android C110 BSP arranca con OneNAND! *//* Para el arranque del segundo dispositivo*//* Error en el BOOTONG de OneNAND*/cmp r2, #0x8moveq r3, #BOOT_SEC_DEV #endif/* Error en el BOOTONG de Uart*/cmp r2, #(0x1lt;lt;4)moveq
r3, #BOOT_SEC_DEVldr r0, =INF_REG_BASEstr r3, [r0, #INF_REG3_OFFSET] //Guarda el valor de configuración en
lt;pregt;lt;/pregt;
lt;pgt;lt;/pgt;
lt;pgt;lt;/pgt;
lt;pregt;lt;/pgt; pregt;lt;/pregt;
lt;pre name="code" class="cpp"gt;
ldr sp, =0xd0035400 //pila donde está la función en el segmento BL1 realiza su operación Aquí modifico la pila a 0xd0035400 porque el código BL0 inicializa su propia pila de código como se muestra en la Figura 2 y la parte más baja del montón del área RW/ZI está en 0xd0035400, esto se hace para no modificar la pila BL0 y. algunas funciones que el código BL0 ha escrito (se usarán a continuación), modifiqué la pila a 0xd0035400
sub sp, sp, #12 /* set stack */
mov fp , #0
bl lowlevel_init /* go setup pll, mux, memoria */ //Aquí estará siempre, memoria, inicialización en serie lt;/pre gt
lt;pgt; ; y luego ejecute lt;/pgt;
lt;pgt;lt;/pgt;
lt;pre name="code" class="cpp"gt ;ldr sp. , _TEXT_PHY_BASE /* Establecer puntero de pila temporal*/ // Debido a DRAM
Se ha inicializado en el paso anterior, por lo que la pila posterior se configurará en la ubicación en DRAM aquí (las funciones en el código BL2 posterior se basan en esta pila)
sub sp, sp, #12
mov fp, #0 /* No hay fotograma anterior, por lo que fp=0 */
/* No necesitamos reubicar U-Boot cuando ya estamos ejecutando en carnero.
* De hecho, el controlador de memoria debe configurarse antes de que U-Boot pueda ejecutarse en la memoria.
*/
ldr r0, =0xff000fff
bic r1, pc, r0 /* r0 lt - la dirección base actual del código */ <; /p >
ldr r2, _TEXT_ BASE /* r1 lt - la dirección base original en la memoria */ // Carga la dirección de ejecución del programa compilado y compárala con la dirección de ejecución del programa actual
bic r2, r2, r0 /* r0 lt; - la dirección base del código actual */
cmp r1, r2 /* comparar r0, r1 */
beq after_copy /* r0 = = r1, luego omita la copia de la memoria flash*/ // Si las dos direcciones son iguales, significa que el programa de código ya se está ejecutando en DRAM y no es necesario copiarlo nuevamente si no son iguales; Significa que el programa no se ha ejecutado en la dirección compilada y el código debe copiarse a la dirección de compilación y finalmente saltar a la dirección de compilación correspondiente para ejecutar el código. El último paso es saltar a la dirección compilada correspondiente para ejecutar el código.
lt;/pregt;lt;pre nombre="código" clase="cpp"gt; ldr r0, =INF_REG_BASE
ldr r1, [r0, #INF_REG3_OFFSET]
cmp r1 , #BOOT_NAND /* 0x0 =gt; El dispositivo de arranque es nand */
beq nand_boot
cmp r1, #BOOT_ONENAND /* 0x1 =gt; p>
beq onenand_boot
cmp r1, #BOOT_MMCSD /* 0x1 =gt #BOOT_MMCSD
beq mmcsd_boot
cmp r1, #BOOT_NOR
beq nor_boot
cmp r1, #BOOT_SEC_DEV
beq mmcsd_boot
// El código funciona leyendo un registro de usuario previamente almacenado (en este (caso del valor en la tarjeta SD), determine desde qué dispositivo de almacenamiento externo arrancar y luego determine cuál se copiará
// El código funciona leyendo el valor previamente almacenado en el registro de usuario ( en este caso, la tarjeta SD) El valor determina desde qué dispositivo de almacenamiento externo arrancar
~~~~~ Algunos códigos se omiten~~~~~~~~
mmcsd_boot :
#if BORRAR
ldr sp, _TEXT_PHY_BASE <
sub sp, sp, #12
mov fp, #0
#endif
bl movi_bl2_copy //El último código BL1 copiará el resto del código de la tarjeta SD aquí
b after_copylt;/pregt;lt;br gt;
lt;pregt;lt;/pregt;
lt;pre nombre="código" class="cpp"gt;lt;/pregt;