2018-04-03 20:45:21 +00:00
|
|
|
# Tutorial 02 - Multicore Rust
|
|
|
|
|
|
|
|
Now let's try something more complex, shall we? By complex I mean stopping the
|
|
|
|
CPU cores just like in the first tutorial, but this time stop one of them from
|
|
|
|
**Rust**!
|
|
|
|
|
2018-08-12 13:40:11 +00:00
|
|
|
## Boot code
|
2018-04-03 20:45:21 +00:00
|
|
|
|
2018-04-04 18:41:17 +00:00
|
|
|
In order to conveniently incorporate Rust code, we are restructuring our crate a
|
|
|
|
bit.
|
2018-04-03 20:45:21 +00:00
|
|
|
|
2018-04-04 18:41:17 +00:00
|
|
|
We reuse a lot of steps that are explained in great detail in [The
|
|
|
|
Embedonomicon][nom], so please take your time and read up on it. Afterwards, you
|
|
|
|
can compare to the files in this crate and see what we actually kept to get our
|
|
|
|
Raspberry Pi 3 tutorial going. Here's a short summary of the new structure of
|
|
|
|
the crate:
|
2018-04-03 20:45:21 +00:00
|
|
|
|
2018-08-12 13:40:11 +00:00
|
|
|
- `raspi3_boot/`: The extern crate containing boot code as presented in the
|
2018-04-03 20:45:21 +00:00
|
|
|
Embedonomicon.
|
|
|
|
- In a small deviation to the Embedonomicon, `lib.rs` also includes
|
2018-04-04 18:41:17 +00:00
|
|
|
`boot_cores.S` from the previous tutorial, still with the
|
|
|
|
[global_asm!][gasm] macro.
|
2018-08-12 13:40:11 +00:00
|
|
|
- Therefore, `boot_cores.S` has been moved into `raspi3_boot/src/`.
|
2018-04-04 18:41:17 +00:00
|
|
|
- `src`: Source code of our actual Rust code, currently only containing
|
|
|
|
`main.rs` executing an endless loop.
|
2018-04-03 20:45:21 +00:00
|
|
|
|
2018-08-12 13:40:11 +00:00
|
|
|
[nom]: https://rust-embedded.github.io/embedonomicon/
|
2018-04-03 20:45:21 +00:00
|
|
|
[gasm]: https://doc.rust-lang.org/unstable-book/language-features/global-asm.html
|
|
|
|
|
2018-04-04 18:41:17 +00:00
|
|
|
### Changes to `boot_cores.S`
|
2018-04-03 20:45:21 +00:00
|
|
|
|
2018-04-04 18:41:17 +00:00
|
|
|
In contrast to the previous tutorial, we are now [distinguishing the
|
|
|
|
cores][dist]. To do so, we read the [mpidr_el1][mpdir] system register. If it is
|
|
|
|
not zero, we enter the former infinite waiting loop, aka stopping the respective
|
|
|
|
CPU core.
|
2018-04-03 20:45:21 +00:00
|
|
|
|
2018-10-29 21:33:17 +00:00
|
|
|
If the result of the read from `mpidr_el1` is zero, which means we are executing
|
|
|
|
on core0, we set up the stack for that core, and afterwards call the Rust
|
|
|
|
`reset()` function of the boot code in `raspi3_boot/src/lib.rs`. In case the
|
|
|
|
Rust code returns (which it never should), we also jump to the same infinite
|
|
|
|
loop the other CPU cores are running.
|
|
|
|
|
|
|
|
The Rust `reset()`, in turn, will then zero-out the `bss section` (the next
|
|
|
|
section explains what that is) and finally call our `main()` function from
|
|
|
|
`main.rs`.
|
2018-04-03 20:45:21 +00:00
|
|
|
|
|
|
|
[dist]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/CFHCIDCH.html
|
|
|
|
[mpdir]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500g/BABHBJCI.html
|
2018-04-04 18:41:17 +00:00
|
|
|
|
|
|
|
## Changes to `link.ld`
|
|
|
|
|
|
|
|
Since we are using a high-level language now in the form of Rust, we also take
|
|
|
|
precautions to have eventual space reserved in memory for the [bss
|
|
|
|
segment][bss], which is needed in case zero-initialized static variables are
|
|
|
|
allocated in the Rust code.
|
|
|
|
|
2018-04-03 20:45:21 +00:00
|
|
|
[bss]: https://en.wikipedia.org/wiki/.bss
|
|
|
|
|
2018-04-04 18:41:17 +00:00
|
|
|
Therefore, we added the `bss` segment to the linker script and export its
|
|
|
|
properties via `__bss_start` and `__bss_size`, which will be picked up and
|
2018-08-12 13:40:11 +00:00
|
|
|
zeroed out by the boot code in `raspi3_boot/src/lib.rs`.
|
2018-04-04 18:41:17 +00:00
|
|
|
|
|
|
|
Additionally, there is a [data segment][data] now.
|
|
|
|
|
|
|
|
[data]: https://en.wikipedia.org/wiki/Data_segment
|
|
|
|
|
|
|
|
Finally, we need to take care that we still start the text segment with the
|
|
|
|
assembly code and not the newly added Rust code. This is taken care of by
|
|
|
|
placing the `.text.boot` section before all other new text sections
|
|
|
|
`KEEP(*(.text.boot)) *(.text .text.* ...`.
|
|
|
|
|
|
|
|
This way, the assembly stays at the `0x80_000` address, which is the entry point
|
|
|
|
of the RPi3 CPU.
|
|
|
|
|
2018-04-03 20:45:21 +00:00
|
|
|
## Changes to `Makefile`
|
|
|
|
|
2018-04-04 18:41:17 +00:00
|
|
|
We've added one more target:
|
2018-04-03 20:45:21 +00:00
|
|
|
- [clippy] is Rust's linter, and can give you useful advise to improve your
|
|
|
|
code. Invoke with `make clippy`.
|
|
|
|
|
|
|
|
[clippy]: https://github.com/rust-lang-nursery/rust-clippy
|
|
|
|
|
|
|
|
From now on, we can use the same Makefile for every tutorial, regardless of the
|
|
|
|
number of Rust sources, and we won't discuss it any further.
|
|
|
|
|
|
|
|
## main.rs
|
|
|
|
|
|
|
|
Finally, our first Rust code. Just an empty loop, but still! :-)
|