Running Bare Metal App
When Linux kernel boots all non asigned cpus (here Core 3) remain in a loop looking it's mailbox 3 for non-zero value, with an address where to jump (read more here). Writting to that mailbox (Core3_MBOX3_SET register = 0x400000BC) the value 0x20000000 makes Core 3 to jump to the executable that we loaded at that possition.
For physical memory read/write from Linux I used devmem, so get it from http://free-electrons.com/pub/mirror/devmem2.c
Now start the loaded blinking app writing 0x20000000 to Core 3 MailBox3:
./devmem 0x400000bc w 0x20000000
Connect a LED to GPIO16.
LCM
Brian's tutorials include an C-startup assembler file "armc-0x-start.S" that is the first code to be executed.
For that armc-0x-start.S include this label:
.section ".text.startup"
That label is the first in the used linker script: rpi.x
In that examples we loose control over execution, as the used C-startup funcion start.S branches to kernel_main function and never return.
In order to have control over bare-metal execution the some changes were made to armc-0x-start.S:
.section ".text.startup"
.global _start
.global _get_stack_pointer
_start:
// Clear CORE3_MBOX3
ldr r1,=0x400000FC
ldr r3,=0xffffffff
str r3, [r1]
// Set the stack pointer, which progresses downwards through memory
// Set it at 64MB which we know our application will not crash into
// and we also know will be available to the ARM CPU. No matter what
// settings we use to split the memory between the GPU and ARM CPU
ldr sp, =(768 * 1024 * 1024) //SP to 0x3000000
// Run the c startup function - should not return and will call kernel_main
bl _cstartup
bl kernel_main //changed from b to bl
// Check CORE3_MBOX3 for jump address (not zero)
_check_loop:
ldr r1,=0x400000FC
ldr r1, [r1]
mov r3, #0
cmp r1, r3
beq _check_loop
bx r1
_get_stack_pointer:
// Return the stack pointer value
str sp, [sp]
ldr r0, [sp]
// Return from the function
mov pc, lr
Replacing the "b" kernel_main branch with "bl" (branch with link) kernel_main can return.
When kernel_main returns the core loops (_check_loop) looking for a non-zero value in mailbox 3.
Previously (when this code start) mailbox 3 is cleared.
For a tentative LCM implementation see this example.
A serious LCM requires interrups or any exception mechanism in order to take the control.
No hay comentarios:
Publicar un comentario