As seen, we need to tell the compiler in what `section` the interrupt "vector" (array) should go. The ARM-Cortex-M has 16 exceptions and serves a maximum of 240 interrupt sources.
- The [cortex-m-rt](https://github.com/japaric/cortex-m-rt) crate provides a minimalistic runtime and startup of the ARM Cortex M. Providing:
- Linker script, telling the linker howto generate the binary.
- The `reset` handler, initiating the memory (and FPU if available on the target), and calls the user `main` function.
- Default exception handlers.
- The user defined `main` function defines the applicaiton behavior.
- User defined interrupt handlers, in this case just dummy handlers (never returning).
As seen, we need to tell the compiler in what `section` the interrupt "vector" (array) should go. The ARM-Cortex-M architecture defines 16 exceptions and serves a maximum of 240 interrupt sources.
The target specific memory layout is given by the file `memory.x`.
...
...
@@ -176,7 +190,250 @@ MEMORY
}
```
In effect, `bare0::main` will be stored in the `FLASH` memory segment, while our
## Compilng and Debugging
First compile the example either through the `vscode` Tasks (Ctrl-Shift-B) or using the console:
``` shell
> xargo build --example bare0
```
Before running the program, we can have a look at the genertate binary.
target/thumbv7em-none-eabihf/debug/examples/bare0: file format elf32-littlearm
```
-`.vector_table` section contains the `exception` and `interrupt` handler addresses. In total 0x400 bytes (in hex), i.e., 256 word size vectors (1k byte).
-`.text` section holds the program code (code from `cortex-m-rt` and the user `main` in our case). In total 0x52e bytes (in hex).
-`.rodata` section, constants (including `X_INIT`). In total 0xb8 bytes.
-`.bss` section, zero-initated static heap variables. Here the `Y` is stored (`u32` is 4 bytes).
-`.data` section, static heap variables that is initiated at run-time (by `cortex-m-rt` before user `main` is called.
target/thumbv7em-none-eabihf/debug/examples/bare0: file format elf32-littlearm
```
Gives a raw dump of the `.vector_table`. The first 16 entries are the exception handlers, where the first entry (0x0800000) is the stack pointer (0x00800120 raw = 0x20018000 interpreted as little-endian). The stack pointer is set just outside the ram area (96kb starting at 0x20000000), recall that the stack pointer is decremented first upon stack allocations so this is "safe". The second vector (0x0800004), is the `reset` vector (0x80000401). (The odd address casts the processor into `thumb` mode using 16 bit instructions for higher code density.)
This is more informative, here we see the address as interpreted in little-endian. also we see, that the `cortex_m_rt::RESET_VECTOR` is located at address 08000004 (pointing to the handler located at 0x08000401.). The interrupt vectors all point to
0x0800055f (odd address here for `thumb` mode).
Now lets have a closer look at the user `reset` (startup code):
// If `main` returns, then we go into "reactive" mode and simply attend
// interrupts as they occur.
loop{
800045e:e7ffb.n8000460<_einterrupts+0x60>
asm!("wfi"::::"volatile");
8000460:bf30wfi
loop{
8000462:e7fdb.n8000460<_einterrupts+0x60>
```
Here we see that the `reset_handler` intitates static heap variables (by 0 or value accordingly) before calling `main` (and puts the processor in sleep mode in case `main` returns). The user `main` has the symbol `bare0::main`, which is unknown to the `cortex-m-rt` library (defining the generic `reset_handler`). Hence the, `reset_handler` calls a compiler generated (trampoline) `main`, that in turn calls `bare0::main` (the user `main`).