rust-raspberrypi-OS-tutorials/02_multicore_rust/README.md

89 lines
3.5 KiB
Markdown
Raw Normal View History

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**!
## Boot code
2018-04-03 20:45:21 +00:00
In order to conveniently incorporate Rust code, we are restructuring our crate a
bit.
2018-04-03 20:45:21 +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
- `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
`boot_cores.S` from the previous tutorial, still with the
[global_asm!][gasm] macro.
- Therefore, `boot_cores.S` has been moved into `raspi3_boot/src/`.
- `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
[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
### Changes to `boot_cores.S`
2018-04-03 20:45:21 +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
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
## 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
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
zeroed out by the boot code in `raspi3_boot/src/lib.rs`.
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`
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! :-)