Running Programs on Epiphany
In the last post, we looked at the memory layout and ran a simple demo. Let's take a closer look at how a program starts running.
For starters, compile and run the program from last time. We're going to run the program again, this time manually using the low-level mechanism that e-loader
uses to start programs.
Writing a 1 (SYNC) value to the ILATST register will trigger the Sync interrupt, and cause an existing program to run on the core.
Remember that the registers from each core are memory mapped to the host.
The register addresses are defined in /opt/adapteva/esdk/tools/host/include/epiphany-hal-data.h
.
We want E_REG_ILATST, which is 0xf042C.
To see if this works, change the input values.
parallella@parallella:~$ e-write 0 0 2000 4 5 0 [0x00002000] = 0x00000004 [0x00002004] = 0x00000005 [0x00002008] = 0x00000000
Now, write the ILATST register to run the program
parallella@parallella:~$ e-write 0 0 0xf042c 1
And check the result
parallella@parallella:~$ e-read 0 0 0x2000 3 [0x00002000] = 0x00000004 [0x00002004] = 0x00000005 [0x00002008] = 0x00000009
It worked!
Okay, now let's look at the details of what happened.
The first 40 bytes of the core-local memory are reserved for the Interrupt Vector Table (IVT). Each entry is 4 bytes long, and should contain a jump (branch) instruction to the desired code. The first entry in the table is the Sync interrupt, used to start the program. (See the Epiphany Architecture Reference for the rest of the IVT entries)
We can disassemble the compiled object file with e-objdump -D
and look for address 0
(we need -D instead of -d to disassemble all the sections, not just the normal executable sections).
This looks promising. Address of 0, in a section called ivt_reset
.
Disassembly of section ivt_reset: 00000000 <_start>: 0: 2ce8 0000 b 58 <.normal_start>
After the Sync interrupt, control transfers to address 0, and then branches to location 0x58. The next section in the objdump output has that address.
Disassembly of section .reserved_crt0: 00000058 <.normal_start>: 58: 720b 0002 mov r3,0x90 5c: 600b 1002 movt r3,0x0 60: 0d52 jalr r3
This loads address 0x90 and jumps to it.
The mov
instruction loads the lower 16 bits of r3 and the movt
instruction loads the upper 16 bits.
Now look for that address
Disassembly of section .text: 00000090 <_epiphany_start>: 90: be0b 27f2 mov sp,0x7ff0 94: a00b 3002 movt sp,0x0 ...
This sets up the stack by loading the stack pointer with 0x7ff0, which is the top of the 32K local address space.
The code calls other routines, which eventually call main
, but I won't trace it all here.
Comments
Comments powered by Disqus