You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Andre Richter f13e6e4513
Change to new aarch64-unknown-none-softloat target.
Also, add safety docs where demanded by clippy.
5 years ago
..
.cargo Change to new aarch64-unknown-none-softloat target. 5 years ago
raspi3_boot Change to new aarch64-unknown-none-softloat target. 5 years ago
src Streamlining, cleanup, and minor fixes. 6 years ago
Cargo.lock Update toolchain and bump dependency versions 5 years ago
Cargo.toml 🎉 Update to Rust 2018 🎉 6 years ago
Makefile Change to new aarch64-unknown-none-softloat target. 5 years ago
README.md UART1 output on QEMU. Rework some Readmes. 6 years ago
kernel8 Change to new aarch64-unknown-none-softloat target. 5 years ago
kernel8.img Update toolchain and bump dependency versions 5 years ago
link.ld Alignment. Binaries from newer Rust version. 6 years ago

README.md

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

In order to conveniently incorporate Rust code, we are restructuring our crate a bit.

We reuse a lot of steps that are explained in great detail in The Embedonomicon, 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:

  • raspi3_boot/: The extern crate containing boot code as presented in the Embedonomicon.
    • In a small deviation to the Embedonomicon, lib.rs also includes boot_cores.S from the previous tutorial, still with the global_asm! 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.

Changes to boot_cores.S

In contrast to the previous tutorial, we are now distinguishing the cores. To do so, we read the mpidr_el1 system register. If it is not zero, we enter the former infinite waiting loop, aka stopping the respective CPU core.

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.

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, which is needed in case zero-initialized static variables are allocated in the Rust code.

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 now.

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.

Changes to Makefile

We've added one more target:

  • clippy is Rust's linter, and can give you useful advise to improve your code. Invoke with make 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! :-)