Sync with the newest Embedonomicon

https://github.com/rust-embedded/embedonomicon

Closes #3
pull/4/head
Andre Richter 6 years ago
parent 1b8b78d0c8
commit 0bd363f375
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

@ -1,33 +1,37 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
* MIT License
*
* Copyright (c) 2018 Andre Richter <andre.o.richter@gmail.com>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
ENTRY(_boot_cores);
SECTIONS
{
. = 0x80000;
.text : { KEEP(*(.text.boot)) }
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
.text :
{
KEEP(*(.text.boot)) *(.text .text.*)
}
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}

@ -1,8 +1,16 @@
[[package]]
name = "cortex-a"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel8"
version = "0.1.0"
dependencies = [
"raspi3_glue 0.1.0",
"raspi3_boot 0.1.0",
]
[[package]]
@ -16,13 +24,30 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "raspi3_glue"
name = "raspi3_boot"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "register"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tock-registers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb"
"checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e"
"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
"checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479"
"checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9"

@ -4,4 +4,4 @@ version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
raspi3_glue = { path = "raspi3_glue" }
raspi3_boot = { path = "raspi3_boot" }

@ -4,7 +4,7 @@ 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**!
## Glue code
## Boot code
In order to conveniently incorporate Rust code, we are restructuring our crate a
bit.
@ -15,16 +15,16 @@ 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_glue/`: The extern crate containing glue code as presented in the
- `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!][gasm] macro.
- Therefore, `boot_cores.S` has been moved into `raspi3_glue/src/`.
- 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.
[nom]: https://japaric.github.io/embedonomicon/
[nom]: https://rust-embedded.github.io/embedonomicon/
[gasm]: https://doc.rust-lang.org/unstable-book/language-features/global-asm.html
### Changes to `boot_cores.S`
@ -36,7 +36,7 @@ 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 glue code in `raspi3_glue/src/lib.rs`. In case
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.
@ -58,7 +58,7 @@ 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 glue code in `raspi3_glue/src/lib.rs`.
zeroed out by the boot code in `raspi3_boot/src/lib.rs`.
Additionally, there is a [data segment][data] now.

Binary file not shown.

@ -1,44 +1,58 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
* MIT License
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* Copyright (c) 2018 Andre Richter <andre.o.richter@gmail.com>
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
ENTRY(_boot_cores);
SECTIONS
{
. = 0x80000;
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
.text :
{
KEEP(*(.text.boot)) *(.text .text.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
PROVIDE(_data = .);
.data : { *(.data .data.* .gnu.linkonce.d*) }
.bss (NOLOAD) : {
.data :
{
*(.data .data.*)
}
.bss (NOLOAD) :
{
. = ALIGN(16);
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
_end = .;
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__bss_size = (__bss_end - __bss_start)>>3;
__bss_start = ADDR(.bss);
__bss_end = ADDR(.bss) + SIZEOF(.bss);

@ -1,5 +1,5 @@
[package]
name = "raspi3_glue"
name = "raspi3_boot"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]

@ -23,50 +23,49 @@
* SOFTWARE.
*/
#![feature(lang_items)]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
#![feature(global_asm)]
//! Low-level boot of the Raspberry's processor
extern crate cortex_a;
extern crate panic_abort;
extern crate r0;
#[lang = "start"]
extern "C" fn start<T>(user_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize
where
T: Termination,
{
user_main().report() as isize
}
#[lang = "termination"]
trait Termination {
fn report(self) -> i32;
}
#[macro_export]
macro_rules! entry {
($path:path) => {
#[export_name = "main"]
pub unsafe fn __main() -> ! {
// type check the given path
let f: fn() -> ! = $path;
impl Termination for () {
fn report(self) -> i32 {
0
}
f()
}
};
}
/// Reset function.
///
/// Initializes the bss section before calling into the user's `main()`.
#[no_mangle]
pub unsafe extern "C" fn reset() -> ! {
use core::ptr;
extern "C" {
fn main(argc: isize, argv: *const *const u8) -> isize;
// Boundaries of the .bss section
static mut __bss_start: u32;
static mut __bss_end: u32;
// Boundaries of the .bss section, provided by the linker script
static mut __bss_start: u64;
static mut __bss_end: u64;
}
// Zeroes the .bss section
r0::zero_bss(&mut __bss_start, &mut __bss_end);
main(0, ptr::null());
extern "Rust" {
fn main() -> !;
}
loop {}
main();
}
// Disable all cores except core 0, and then jump to reset()

@ -1,8 +0,0 @@
[package]
name = "raspi3_glue"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
panic-abort = "0.2.0"
r0 = "0.2.2"

@ -23,9 +23,13 @@
*/
#![no_std]
#![no_main]
extern crate raspi3_glue;
#[macro_use]
extern crate raspi3_boot;
fn main() {
entry!(kernel_entry);
fn kernel_entry() -> ! {
loop {}
}

14
03_uart1/Cargo.lock generated

@ -1,8 +1,16 @@
[[package]]
name = "cortex-a"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel8"
version = "0.1.0"
dependencies = [
"raspi3_glue 0.1.0",
"raspi3_boot 0.1.0",
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -17,9 +25,10 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "raspi3_glue"
name = "raspi3_boot"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -38,6 +47,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb"
"checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e"
"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
"checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479"

@ -4,5 +4,5 @@ version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
raspi3_glue = { path = "raspi3_glue" }
raspi3_boot = { path = "raspi3_boot" }
register = "0.1.1"

Binary file not shown.

@ -1,44 +1,58 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
* MIT License
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* Copyright (c) 2018 Andre Richter <andre.o.richter@gmail.com>
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
ENTRY(_boot_cores);
SECTIONS
{
. = 0x80000;
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
.text :
{
KEEP(*(.text.boot)) *(.text .text.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
PROVIDE(_data = .);
.data : { *(.data .data.* .gnu.linkonce.d*) }
.bss (NOLOAD) : {
.data :
{
*(.data .data.*)
}
.bss (NOLOAD) :
{
. = ALIGN(16);
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
_end = .;
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__bss_size = (__bss_end - __bss_start)>>3;
__bss_start = ADDR(.bss);
__bss_end = ADDR(.bss) + SIZEOF(.bss);

@ -1,5 +1,5 @@
[package]
name = "raspi3_glue"
name = "raspi3_boot"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]

@ -23,50 +23,49 @@
* SOFTWARE.
*/
#![feature(lang_items)]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
#![feature(global_asm)]
//! Low-level boot of the Raspberry's processor
extern crate cortex_a;
extern crate panic_abort;
extern crate r0;
#[lang = "start"]
extern "C" fn start<T>(user_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize
where
T: Termination,
{
user_main().report() as isize
}
#[lang = "termination"]
trait Termination {
fn report(self) -> i32;
}
#[macro_export]
macro_rules! entry {
($path:path) => {
#[export_name = "main"]
pub unsafe fn __main() -> ! {
// type check the given path
let f: fn() -> ! = $path;
impl Termination for () {
fn report(self) -> i32 {
0
}
f()
}
};
}
/// Reset function.
///
/// Initializes the bss section before calling into the user's `main()`.
#[no_mangle]
pub unsafe extern "C" fn reset() -> ! {
use core::ptr;
extern "C" {
fn main(argc: isize, argv: *const *const u8) -> isize;
// Boundaries of the .bss section
static mut __bss_start: u32;
static mut __bss_end: u32;
// Boundaries of the .bss section, provided by the linker script
static mut __bss_start: u64;
static mut __bss_end: u64;
}
// Zeroes the .bss section
r0::zero_bss(&mut __bss_start, &mut __bss_end);
main(0, ptr::null());
extern "Rust" {
fn main() -> !;
}
loop {}
main();
}
// Disable all cores except core 0, and then jump to reset()

@ -1,8 +0,0 @@
[package]
name = "raspi3_glue"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
panic-abort = "0.2.0"
r0 = "0.2.2"

@ -23,9 +23,11 @@
*/
#![no_std]
#![no_main]
#![feature(asm)]
extern crate raspi3_glue;
#[macro_use]
extern crate raspi3_boot;
#[macro_use]
extern crate register;
@ -35,7 +37,9 @@ const MMIO_BASE: u32 = 0x3F00_0000;
mod gpio;
mod uart;
fn main() {
entry!(kernel_entry);
fn kernel_entry() -> ! {
let uart = uart::MiniUart::new();
// set up serial console

@ -1,8 +1,16 @@
[[package]]
name = "cortex-a"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel8"
version = "0.1.0"
dependencies = [
"raspi3_glue 0.1.0",
"raspi3_boot 0.1.0",
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -17,9 +25,10 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "raspi3_glue"
name = "raspi3_boot"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -38,6 +47,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb"
"checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e"
"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
"checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479"

@ -4,5 +4,5 @@ version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
raspi3_glue = { path = "raspi3_glue" }
raspi3_boot = { path = "raspi3_boot" }
register = "0.1.1"

Binary file not shown.

@ -1,44 +1,58 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
* MIT License
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* Copyright (c) 2018 Andre Richter <andre.o.richter@gmail.com>
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
ENTRY(_boot_cores);
SECTIONS
{
. = 0x80000;
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
.text :
{
KEEP(*(.text.boot)) *(.text .text.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
PROVIDE(_data = .);
.data : { *(.data .data.* .gnu.linkonce.d*) }
.bss (NOLOAD) : {
.data :
{
*(.data .data.*)
}
.bss (NOLOAD) :
{
. = ALIGN(16);
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
_end = .;
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__bss_size = (__bss_end - __bss_start)>>3;
__bss_start = ADDR(.bss);
__bss_end = ADDR(.bss) + SIZEOF(.bss);

@ -1,5 +1,5 @@
[package]
name = "raspi3_glue"
name = "raspi3_boot"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]

@ -23,50 +23,49 @@
* SOFTWARE.
*/
#![feature(lang_items)]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
#![feature(global_asm)]
//! Low-level boot of the Raspberry's processor
extern crate cortex_a;
extern crate panic_abort;
extern crate r0;
#[lang = "start"]
extern "C" fn start<T>(user_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize
where
T: Termination,
{
user_main().report() as isize
}
#[lang = "termination"]
trait Termination {
fn report(self) -> i32;
}
#[macro_export]
macro_rules! entry {
($path:path) => {
#[export_name = "main"]
pub unsafe fn __main() -> ! {
// type check the given path
let f: fn() -> ! = $path;
impl Termination for () {
fn report(self) -> i32 {
0
}
f()
}
};
}
/// Reset function.
///
/// Initializes the bss section before calling into the user's `main()`.
#[no_mangle]
pub unsafe extern "C" fn reset() -> ! {
use core::ptr;
extern "C" {
fn main(argc: isize, argv: *const *const u8) -> isize;
// Boundaries of the .bss section
static mut __bss_start: u32;
static mut __bss_end: u32;
// Boundaries of the .bss section, provided by the linker script
static mut __bss_start: u64;
static mut __bss_end: u64;
}
// Zeroes the .bss section
r0::zero_bss(&mut __bss_start, &mut __bss_end);
main(0, ptr::null());
extern "Rust" {
fn main() -> !;
}
loop {}
main();
}
// Disable all cores except core 0, and then jump to reset()

@ -1,8 +0,0 @@
[package]
name = "raspi3_glue"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
panic-abort = "0.2.0"
r0 = "0.2.2"

@ -23,9 +23,11 @@
*/
#![no_std]
#![no_main]
#![feature(asm)]
extern crate raspi3_glue;
#[macro_use]
extern crate raspi3_boot;
#[macro_use]
extern crate register;
@ -38,7 +40,9 @@ mod uart;
use core::sync::atomic::{compiler_fence, Ordering};
fn main() {
entry!(kernel_entry);
fn kernel_entry() -> ! {
let mut mbox = mbox::Mbox::new();
let uart = uart::MiniUart::new();

14
05_uart0/Cargo.lock generated

@ -1,8 +1,16 @@
[[package]]
name = "cortex-a"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel8"
version = "0.1.0"
dependencies = [
"raspi3_glue 0.1.0",
"raspi3_boot 0.1.0",
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -17,9 +25,10 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "raspi3_glue"
name = "raspi3_boot"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -38,6 +47,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb"
"checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e"
"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
"checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479"

@ -4,5 +4,5 @@ version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
raspi3_glue = { path = "raspi3_glue" }
raspi3_boot = { path = "raspi3_boot" }
register = "0.1.1"

Binary file not shown.

@ -1,44 +1,58 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
* MIT License
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* Copyright (c) 2018 Andre Richter <andre.o.richter@gmail.com>
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
ENTRY(_boot_cores);
SECTIONS
{
. = 0x80000;
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
.text :
{
KEEP(*(.text.boot)) *(.text .text.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
PROVIDE(_data = .);
.data : { *(.data .data.* .gnu.linkonce.d*) }
.bss (NOLOAD) : {
.data :
{
*(.data .data.*)
}
.bss (NOLOAD) :
{
. = ALIGN(16);
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
_end = .;
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__bss_size = (__bss_end - __bss_start)>>3;
__bss_start = ADDR(.bss);
__bss_end = ADDR(.bss) + SIZEOF(.bss);

@ -1,8 +1,9 @@
[package]
name = "raspi3_glue"
name = "raspi3_boot"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
cortex-a = "1.0.0"
panic-abort = "0.2.0"
r0 = "0.2.2"

@ -23,50 +23,49 @@
* SOFTWARE.
*/
#![feature(lang_items)]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
#![feature(global_asm)]
//! Low-level boot of the Raspberry's processor
extern crate cortex_a;
extern crate panic_abort;
extern crate r0;
#[lang = "start"]
extern "C" fn start<T>(user_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize
where
T: Termination,
{
user_main().report() as isize
}
#[lang = "termination"]
trait Termination {
fn report(self) -> i32;
}
#[macro_export]
macro_rules! entry {
($path:path) => {
#[export_name = "main"]
pub unsafe fn __main() -> ! {
// type check the given path
let f: fn() -> ! = $path;
impl Termination for () {
fn report(self) -> i32 {
0
}
f()
}
};
}
/// Reset function.
///
/// Initializes the bss section before calling into the user's `main()`.
#[no_mangle]
pub unsafe extern "C" fn reset() -> ! {
use core::ptr;
extern "C" {
fn main(argc: isize, argv: *const *const u8) -> isize;
// Boundaries of the .bss section
static mut __bss_start: u32;
static mut __bss_end: u32;
// Boundaries of the .bss section, provided by the linker script
static mut __bss_start: u64;
static mut __bss_end: u64;
}
// Zeroes the .bss section
r0::zero_bss(&mut __bss_start, &mut __bss_end);
main(0, ptr::null());
extern "Rust" {
fn main() -> !;
}
loop {}
main();
}
// Disable all cores except core 0, and then jump to reset()

@ -23,9 +23,11 @@
*/
#![no_std]
#![no_main]
#![feature(asm)]
extern crate raspi3_glue;
#[macro_use]
extern crate raspi3_boot;
#[macro_use]
extern crate register;
@ -38,13 +40,15 @@ mod uart;
use core::sync::atomic::{compiler_fence, Ordering};
fn main() {
entry!(kernel_entry);
fn kernel_entry() -> ! {
let mut mbox = mbox::Mbox::new();
let uart = uart::Uart::new();
// set up serial console
if uart.init(&mut mbox).is_err() {
return; // If UART fails, abort early
unsafe { asm!("wfe" :::: "volatile") }; // If UART fails, abort early
}
// get the board's unique serial number with a mailbox call

@ -1,8 +1,16 @@
[[package]]
name = "cortex-a"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel8"
version = "0.1.0"
dependencies = [
"raspi3_glue 0.1.0",
"raspi3_boot 0.1.0",
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -12,10 +20,17 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "raspi3_glue"
name = "r0"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "raspi3_boot"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -32,6 +47,8 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb"
"checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e"
"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
"checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479"
"checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9"

@ -4,5 +4,5 @@ version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
raspi3_glue = { path = "raspi3_glue" }
raspi3_boot = { path = "raspi3_boot" }
register = "0.1.1"

@ -71,7 +71,7 @@ firmware. Second, we added a loop to relocate our code to the address it should
have been loaded to. And last, since rustc generates RIP-relative jumps, we must
adjust the branch instruction to jump to the relocated Rust code.
## Linker and Glue Code
## Linker and Boot Code
We use a different linking address this time. We calculate our code's size to
know how many bytes we have to copy.

Binary file not shown.

@ -1,38 +1,52 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
* MIT License
*
* Copyright (c) 2018 Andre Richter <andre.o.richter@gmail.com>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
ENTRY(_boot_cores);
SECTIONS
{
. = 0x80000 - 2048;
_code = .;
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
.data : { *(.data .data.* .gnu.linkonce.d*) }
.text :
{
KEEP(*(.text.boot)) *(.text .text.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
PROVIDE(_data = .);
.data :
{
*(.data .data.*)
}
_end = .;
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__loader_size = (_end - _code)>>3;

@ -0,0 +1,9 @@
[package]
name = "raspi3_boot"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
cortex-a = "1.0.0"
panic-abort = "0.2.0"
r0 = "0.2.2"

@ -23,42 +23,40 @@
* SOFTWARE.
*/
#![feature(lang_items)]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
#![feature(global_asm)]
extern crate panic_abort;
#[lang = "start"]
extern "C" fn start<T>(user_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize
where
T: Termination,
{
user_main().report() as isize
}
#[lang = "termination"]
trait Termination {
fn report(self) -> i32;
}
//! Low-level boot of the Raspberry's processor
impl Termination for () {
fn report(self) -> i32 {
0
extern crate cortex_a;
extern crate panic_abort;
extern crate r0;
#[macro_export]
macro_rules! entry {
($path:path) => {
#[export_name = "main"]
pub unsafe fn __main() -> ! {
// type check the given path
let f: fn() -> ! = $path;
f()
}
}
}
/// Reset function.
///
/// Trampolines into the user's `main()`.
#[no_mangle]
pub unsafe extern "C" fn reset() -> ! {
use core::ptr;
extern "C" {
fn main(argc: isize, argv: *const *const u8) -> isize;
extern "Rust" {
fn main() -> !;
}
main(0, ptr::null());
loop {}
main();
}
// Disable all cores except core 0, and then jump to reset()

@ -1,7 +0,0 @@
[package]
name = "raspi3_glue"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
panic-abort = "0.2.0"

@ -23,9 +23,11 @@
*/
#![no_std]
#![no_main]
#![feature(asm)]
extern crate raspi3_glue;
#[macro_use]
extern crate raspi3_boot;
#[macro_use]
extern crate register;
@ -36,13 +38,15 @@ mod gpio;
mod mbox;
mod uart;
fn main() {
entry!(kernel_entry);
fn kernel_entry() -> ! {
let mut mbox = mbox::Mbox::new();
let uart = uart::Uart::new();
// set up serial console
if uart.init(&mut mbox).is_err() {
return; // If UART fails, abort early
unsafe { asm!("wfe" :::: "volatile") }; // If UART fails, abort early
}
// Say hello
@ -74,8 +78,8 @@ fn main() {
}
// Use black magic to get a function pointer to 0x80_000
let kernel: extern "C" fn() = unsafe { core::mem::transmute(kernel_addr as *const ()) };
let kernel: extern "C" fn() -> ! = unsafe { core::mem::transmute(kernel_addr as *const ()) };
// Jump to loaded kernel and never return!
kernel();
kernel()
}

@ -11,7 +11,7 @@ name = "kernel8"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"raspi3_glue 0.1.0",
"raspi3_boot 0.1.0",
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -26,7 +26,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "raspi3_glue"
name = "raspi3_boot"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",

@ -4,6 +4,6 @@ version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
raspi3_glue = { path = "raspi3_glue" }
raspi3_boot = { path = "raspi3_boot" }
cortex-a = "1.0.0"
register = "0.1.1"

@ -5,7 +5,7 @@ important Rust principles are introduced: Abstraction and modularity.
From a functional perspective, this tutorial is the same as `05_uart0`, but with
the key difference that we threw out all manually crafted assembler. Both the
main and the glue crate do not use `#![feature(global_asm)]` or
main and the boot crate do not use `#![feature(global_asm)]` or
`#![feature(asm)]` anymore. Instead, we pulled in the [cortex-a][crate] crate,
which now provides `cortex-a` specific features like register access or safe
wrappers around assembly instructions.
@ -55,7 +55,7 @@ introduce abstraction on different levels of the system. Check out the [Awesome
Embedded Rust](https://github.com/rust-embedded/awesome-embedded-rust) list for
an overview.
## Glue Code
## Boot Code
Like mentioned above, we threw out the `boot_cores.S` assembler file and
replaced it with a Rust function. Why? Because we can, for the fun of it.
@ -63,13 +63,16 @@ replaced it with a Rust function. Why? Because we can, for the fun of it.
```rust
#[link_section = ".text.boot"]
#[no_mangle]
pub extern "C" fn _boot_cores() -> ! {
pub unsafe extern "C" fn _boot_cores() -> ! {
use cortex_a::{asm, regs::mpidr_el1::*, regs::sp::*};
match MPIDR_EL1.get() & 0x3 {
const CORE_MASK: u64 = 0x3;
const STACK_START: u64 = 0x80_0000;
match MPIDR_EL1.get() & CORE_MASK {
0 => {
SP.set(0x80_000);
unsafe { reset() }
SP.set(STACK_START);
reset()
}
_ => loop {
// if not core0, infinitely wait for events
@ -95,14 +98,14 @@ pointer is not used apart from ourselves setting it.
[...] (Some output omitted)
_boot_cores:
80000: a8 00 38 d5 mrs x8, MPIDR_EL1
80004: 1f 05 40 f2 tst x8, #0x3
80008: 60 00 00 54 b.eq #0xc
8000c: 5f 20 03 d5 wfe
80010: ff ff ff 17 b #-0x4
80014: e8 03 0d 32 orr w8, wzr, #0x80000
80018: 1f 01 00 91 mov sp, x8
8001c: 5d 01 00 94 bl #0x574
80000: a8 00 38 d5 mrs x8, MPIDR_EL1
80004: 1f 05 40 f2 tst x8, #0x3
80008: 60 00 00 54 b.eq #0xc <_boot_cores+0x14>
8000c: 5f 20 03 d5 wfe
80010: ff ff ff 17 b #-0x4 <_boot_cores+0xc>
80014: e8 03 09 32 orr w8, wzr, #0x800000
80018: 1f 01 00 91 mov sp, x8
8001c: 35 02 00 94 bl #0x8d4 <raspi3_boot::reset::h90bc56752de44d1b>
```
It is important to always manually check this, and not blindly rely on the

Binary file not shown.

@ -1,44 +1,58 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
* MIT License
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* Copyright (c) 2018 Andre Richter <andre.o.richter@gmail.com>
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
ENTRY(_boot_cores);
SECTIONS
{
. = 0x80000;
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
.text :
{
KEEP(*(.text.boot)) *(.text .text.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
PROVIDE(_data = .);
.data : { *(.data .data.* .gnu.linkonce.d*) }
.bss (NOLOAD) : {
.data :
{
*(.data .data.*)
}
.bss (NOLOAD) :
{
. = ALIGN(16);
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
_end = .;
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__bss_size = (__bss_end - __bss_start)>>3;
__bss_start = ADDR(.bss);
__bss_end = ADDR(.bss) + SIZEOF(.bss);

@ -0,0 +1,9 @@
[package]
name = "raspi3_boot"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
cortex-a = "1.0.0"
panic-abort = "0.2.0"
r0 = "0.2.2"

@ -23,65 +23,65 @@
* SOFTWARE.
*/
#![feature(lang_items)]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
//! Low-level boot of the Raspberry's processor
extern crate cortex_a;
extern crate panic_abort;
extern crate r0;
#[lang = "start"]
extern "C" fn start<T>(user_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize
where
T: Termination,
{
user_main().report() as isize
}
#[macro_export]
macro_rules! entry {
($path:path) => {
#[export_name = "main"]
pub unsafe fn __main() -> ! {
// type check the given path
let f: fn() -> ! = $path;
#[lang = "termination"]
trait Termination {
fn report(self) -> i32;
}
impl Termination for () {
fn report(self) -> i32 {
0
f()
}
}
}
/// Reset function.
///
/// Initializes the bss section before calling into the user's `main()`.
unsafe fn reset() -> ! {
use core::ptr;
extern "C" {
fn main(argc: isize, argv: *const *const u8) -> isize;
// Boundaries of the .bss section
static mut __bss_start: u32;
static mut __bss_end: u32;
// Boundaries of the .bss section, provided by the linker script
static mut __bss_start: u64;
static mut __bss_end: u64;
}
// Zeroes the .bss section
r0::zero_bss(&mut __bss_start, &mut __bss_end);
main(0, ptr::null());
extern "Rust" {
fn main() -> !;
}
loop {}
main();
}
/// Entrypoint of the RPi3.
/// Entrypoint of the processor.
///
/// Parks all cores except core0, and then jumps to the internal
/// `reset()` function, which will call the user's `main()` after
/// initializing the `bss` section.
/// `reset()` function.
#[link_section = ".text.boot"]
#[no_mangle]
pub extern "C" fn _boot_cores() -> ! {
pub unsafe extern "C" fn _boot_cores() -> ! {
use cortex_a::{asm, regs::mpidr_el1::*, regs::sp::*};
match MPIDR_EL1.get() & 0x3 {
const CORE_MASK: u64 = 0x3;
const STACK_START: u64 = 0x80_0000;
match MPIDR_EL1.get() & CORE_MASK {
0 => {
SP.set(0x80_000);
unsafe { reset() }
SP.set(STACK_START);
reset()
}
_ => loop {
// if not core0, infinitely wait for events

@ -23,9 +23,12 @@
*/
#![no_std]
#![no_main]
extern crate cortex_a;
extern crate raspi3_glue;
#[macro_use]
extern crate raspi3_boot;
#[macro_use]
extern crate register;
@ -38,13 +41,15 @@ mod uart;
use core::sync::atomic::{compiler_fence, Ordering};
fn main() {
entry!(kernel_entry);
fn kernel_entry() -> ! {
let mut mbox = mbox::Mbox::new();
let uart = uart::Uart::new();
// set up serial console
if uart.init(&mut mbox).is_err() {
return; // If UART fails, abort early
loop { cortex_a::asm::wfe() }; // If UART fails, abort early
}
// get the board's unique serial number with a mailbox call

@ -11,7 +11,7 @@ name = "kernel8"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"raspi3_glue 0.1.0",
"raspi3_boot 0.1.0",
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -26,7 +26,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "raspi3_glue"
name = "raspi3_boot"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",

@ -4,6 +4,6 @@ version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
raspi3_glue = { path = "raspi3_glue" }
raspi3_boot = { path = "raspi3_boot" }
cortex-a = "1.0.0"
register = "0.1.1"

Binary file not shown.

@ -1,44 +1,58 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
* MIT License
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* Copyright (c) 2018 Andre Richter <andre.o.richter@gmail.com>
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
ENTRY(_boot_cores);
SECTIONS
{
. = 0x80000;
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
.text :
{
KEEP(*(.text.boot)) *(.text .text.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
PROVIDE(_data = .);
.data : { *(.data .data.* .gnu.linkonce.d*) }
.bss (NOLOAD) : {
.data :
{
*(.data .data.*)
}
.bss (NOLOAD) :
{
. = ALIGN(16);
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
_end = .;
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__bss_size = (__bss_end - __bss_start)>>3;
__bss_start = ADDR(.bss);
__bss_end = ADDR(.bss) + SIZEOF(.bss);

@ -0,0 +1,9 @@
[package]
name = "raspi3_boot"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
cortex-a = "1.0.0"
panic-abort = "0.2.0"
r0 = "0.2.2"

@ -23,65 +23,65 @@
* SOFTWARE.
*/
#![feature(lang_items)]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
//! Low-level boot of the Raspberry's processor
extern crate cortex_a;
extern crate panic_abort;
extern crate r0;
#[lang = "start"]
extern "C" fn start<T>(user_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize
where
T: Termination,
{
user_main().report() as isize
}
#[macro_export]
macro_rules! entry {
($path:path) => {
#[export_name = "main"]
pub unsafe fn __main() -> ! {
// type check the given path
let f: fn() -> ! = $path;
#[lang = "termination"]
trait Termination {
fn report(self) -> i32;
}
impl Termination for () {
fn report(self) -> i32 {
0
f()
}
}
}
/// Reset function.
///
/// Initializes the bss section before calling into the user's `main()`.
unsafe fn reset() -> ! {
use core::ptr;
extern "C" {
fn main(argc: isize, argv: *const *const u8) -> isize;
// Boundaries of the .bss section
static mut __bss_start: u32;
static mut __bss_end: u32;
// Boundaries of the .bss section, provided by the linker script
static mut __bss_start: u64;
static mut __bss_end: u64;
}
// Zeroes the .bss section
r0::zero_bss(&mut __bss_start, &mut __bss_end);
main(0, ptr::null());
extern "Rust" {
fn main() -> !;
}
loop {}
main();
}
/// Entrypoint of the RPi3.
/// Entrypoint of the processor.
///
/// Parks all cores except core0, and then jumps to the internal
/// `reset()` function, which will call the user's `main()` after
/// initializing the `bss` section.
/// `reset()` function.
#[link_section = ".text.boot"]
#[no_mangle]
pub extern "C" fn _boot_cores() -> ! {
pub unsafe extern "C" fn _boot_cores() -> ! {
use cortex_a::{asm, regs::mpidr_el1::*, regs::sp::*};
match MPIDR_EL1.get() & 0x3 {
const CORE_MASK: u64 = 0x3;
const STACK_START: u64 = 0x80_0000;
match MPIDR_EL1.get() & CORE_MASK {
0 => {
SP.set(0x80_000);
unsafe { reset() }
SP.set(STACK_START);
reset()
}
_ => loop {
// if not core0, infinitely wait for events

@ -23,9 +23,12 @@
*/
#![no_std]
#![no_main]
extern crate cortex_a;
extern crate raspi3_glue;
#[macro_use]
extern crate raspi3_boot;
#[macro_use]
extern crate register;
@ -37,13 +40,15 @@ mod mbox;
mod rand;
mod uart;
fn main() {
entry!(kernel_entry);
fn kernel_entry() -> ! {
let mut mbox = mbox::Mbox::new();
let uart = uart::Uart::new();
// set up serial console
if uart.init(&mut mbox).is_err() {
return; // If UART fails, abort early
loop { cortex_a::asm::wfe() }; // If UART fails, abort early
}
uart.getc(); // Press a key first before being greeted

@ -11,7 +11,7 @@ name = "kernel8"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"raspi3_glue 0.1.0",
"raspi3_boot 0.1.0",
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -26,7 +26,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "raspi3_glue"
name = "raspi3_boot"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",

@ -4,6 +4,6 @@ version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
raspi3_glue = { path = "raspi3_glue" }
raspi3_boot = { path = "raspi3_boot" }
cortex-a = "1.0.0"
register = "0.1.1"

Binary file not shown.

@ -1,44 +1,58 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
* MIT License
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* Copyright (c) 2018 Andre Richter <andre.o.richter@gmail.com>
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
ENTRY(_boot_cores);
SECTIONS
{
. = 0x80000;
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
.text :
{
KEEP(*(.text.boot)) *(.text .text.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
PROVIDE(_data = .);
.data : { *(.data .data.* .gnu.linkonce.d*) }
.bss (NOLOAD) : {
.data :
{
*(.data .data.*)
}
.bss (NOLOAD) :
{
. = ALIGN(16);
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
_end = .;
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__bss_size = (__bss_end - __bss_start)>>3;
__bss_start = ADDR(.bss);
__bss_end = ADDR(.bss) + SIZEOF(.bss);

@ -0,0 +1,9 @@
[package]
name = "raspi3_boot"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
cortex-a = "1.0.0"
panic-abort = "0.2.0"
r0 = "0.2.2"

@ -23,65 +23,65 @@
* SOFTWARE.
*/
#![feature(lang_items)]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
//! Low-level boot of the Raspberry's processor
extern crate cortex_a;
extern crate panic_abort;
extern crate r0;
#[lang = "start"]
extern "C" fn start<T>(user_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize
where
T: Termination,
{
user_main().report() as isize
}
#[macro_export]
macro_rules! entry {
($path:path) => {
#[export_name = "main"]
pub unsafe fn __main() -> ! {
// type check the given path
let f: fn() -> ! = $path;
#[lang = "termination"]
trait Termination {
fn report(self) -> i32;
}
impl Termination for () {
fn report(self) -> i32 {
0
f()
}
}
}
/// Reset function.
///
/// Initializes the bss section before calling into the user's `main()`.
unsafe fn reset() -> ! {
use core::ptr;
extern "C" {
fn main(argc: isize, argv: *const *const u8) -> isize;
// Boundaries of the .bss section
static mut __bss_start: u32;
static mut __bss_end: u32;
// Boundaries of the .bss section, provided by the linker script
static mut __bss_start: u64;
static mut __bss_end: u64;
}
// Zeroes the .bss section
r0::zero_bss(&mut __bss_start, &mut __bss_end);
main(0, ptr::null());
extern "Rust" {
fn main() -> !;
}
loop {}
main();
}
/// Entrypoint of the RPi3.
/// Entrypoint of the processor.
///
/// Parks all cores except core0, and then jumps to the internal
/// `reset()` function, which will call the user's `main()` after
/// initializing the `bss` section.
/// `reset()` function.
#[link_section = ".text.boot"]
#[no_mangle]
pub extern "C" fn _boot_cores() -> ! {
pub unsafe extern "C" fn _boot_cores() -> ! {
use cortex_a::{asm, regs::mpidr_el1::*, regs::sp::*};
match MPIDR_EL1.get() & 0x3 {
const CORE_MASK: u64 = 0x3;
const STACK_START: u64 = 0x80_0000;
match MPIDR_EL1.get() & CORE_MASK {
0 => {
SP.set(0x80_000);
unsafe { reset() }
SP.set(STACK_START);
reset()
}
_ => loop {
// if not core0, infinitely wait for events

@ -23,9 +23,12 @@
*/
#![no_std]
#![no_main]
extern crate cortex_a;
extern crate raspi3_glue;
#[macro_use]
extern crate raspi3_boot;
#[macro_use]
extern crate register;
@ -37,13 +40,15 @@ mod gpio;
mod mbox;
mod uart;
fn main() {
entry!(kernel_entry);
fn kernel_entry() -> ! {
let mut mbox = mbox::Mbox::new();
let uart = uart::Uart::new();
// set up serial console
if uart.init(&mut mbox).is_err() {
return; // If UART fails, abort early
loop { cortex_a::asm::wfe() }; // If UART fails, abort early
}
uart.getc(); // Press a key first before being greeted

24
0A_power/Cargo.lock generated

@ -1,11 +1,3 @@
[[package]]
name = "cortex-a"
version = "1.0.0"
source = "git+https://github.com/andre-richter/cortex-a.git?branch=registers#aae179e34af014725706bb1821e9e285674db97b"
dependencies = [
"register 0.1.1 (git+https://github.com/andre-richter/register-rs.git)",
]
[[package]]
name = "cortex-a"
version = "1.0.0"
@ -19,7 +11,7 @@ name = "kernel8"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"raspi3_glue 0.1.0",
"raspi3_boot 0.1.0",
"register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -34,22 +26,14 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "raspi3_glue"
name = "raspi3_boot"
version = "0.1.0"
dependencies = [
"cortex-a 1.0.0 (git+https://github.com/andre-richter/cortex-a.git?branch=registers)",
"cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "register"
version = "0.1.1"
source = "git+https://github.com/andre-richter/register-rs.git#e0fdae3f2dc1e9691bbe4d57519e746f0d9aada0"
dependencies = [
"tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "register"
version = "0.1.1"
@ -64,10 +48,8 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum cortex-a 1.0.0 (git+https://github.com/andre-richter/cortex-a.git?branch=registers)" = "<none>"
"checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb"
"checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e"
"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
"checksum register 0.1.1 (git+https://github.com/andre-richter/register-rs.git)" = "<none>"
"checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479"
"checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9"

@ -4,6 +4,6 @@ version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
raspi3_glue = { path = "raspi3_glue" }
raspi3_boot = { path = "raspi3_boot" }
cortex-a = "1.0.0"
register = "0.1.1"

Binary file not shown.

@ -1,44 +1,58 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
* MIT License
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* Copyright (c) 2018 Andre Richter <andre.o.richter@gmail.com>
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
ENTRY(_boot_cores);
SECTIONS
{
. = 0x80000;
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
.text :
{
KEEP(*(.text.boot)) *(.text .text.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
PROVIDE(_data = .);
.data : { *(.data .data.* .gnu.linkonce.d*) }
.bss (NOLOAD) : {
.data :
{
*(.data .data.*)
}
.bss (NOLOAD) :
{
. = ALIGN(16);
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
_end = .;
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__bss_size = (__bss_end - __bss_start)>>3;
__bss_start = ADDR(.bss);
__bss_end = ADDR(.bss) + SIZEOF(.bss);

@ -0,0 +1,9 @@
[package]
name = "raspi3_boot"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
cortex-a = "1.0.0"
panic-abort = "0.2.0"
r0 = "0.2.2"

@ -23,65 +23,65 @@
* SOFTWARE.
*/
#![feature(lang_items)]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
//! Low-level boot of the Raspberry's processor
extern crate cortex_a;
extern crate panic_abort;
extern crate r0;
#[lang = "start"]
extern "C" fn start<T>(user_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize
where
T: Termination,
{
user_main().report() as isize
}
#[macro_export]
macro_rules! entry {
($path:path) => {
#[export_name = "main"]
pub unsafe fn __main() -> ! {
// type check the given path
let f: fn() -> ! = $path;
#[lang = "termination"]
trait Termination {
fn report(self) -> i32;
}
impl Termination for () {
fn report(self) -> i32 {
0
f()
}
}
}
/// Reset function.
///
/// Initializes the bss section before calling into the user's `main()`.
unsafe fn reset() -> ! {
use core::ptr;
extern "C" {
fn main(argc: isize, argv: *const *const u8) -> isize;
// Boundaries of the .bss section
static mut __bss_start: u32;
static mut __bss_end: u32;
// Boundaries of the .bss section, provided by the linker script
static mut __bss_start: u64;
static mut __bss_end: u64;
}
// Zeroes the .bss section
r0::zero_bss(&mut __bss_start, &mut __bss_end);
main(0, ptr::null());
extern "Rust" {
fn main() -> !;
}
loop {}
main();
}
/// Entrypoint of the RPi3.
/// Entrypoint of the processor.
///
/// Parks all cores except core0, and then jumps to the internal
/// `reset()` function, which will call the user's `main()` after
/// initializing the `bss` section.
/// `reset()` function.
#[link_section = ".text.boot"]
#[no_mangle]
pub extern "C" fn _boot_cores() -> ! {
pub unsafe extern "C" fn _boot_cores() -> ! {
use cortex_a::{asm, regs::mpidr_el1::*, regs::sp::*};
match MPIDR_EL1.get() & 0x3 {
const CORE_MASK: u64 = 0x3;
const STACK_START: u64 = 0x80_0000;
match MPIDR_EL1.get() & CORE_MASK {
0 => {
SP.set(0x80_000);
unsafe { reset() }
SP.set(STACK_START);
reset()
}
_ => loop {
// if not core0, infinitely wait for events

@ -1,9 +0,0 @@
[package]
name = "raspi3_glue"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
[dependencies]
cortex-a = { git = "https://github.com/andre-richter/cortex-a.git", branch = "registers" }
panic-abort = "0.2.0"
r0 = "0.2.2"

@ -23,9 +23,12 @@
*/
#![no_std]
#![no_main]
extern crate cortex_a;
extern crate raspi3_glue;
#[macro_use]
extern crate raspi3_boot;
#[macro_use]
extern crate register;
@ -38,7 +41,9 @@ mod mbox;
mod power;
mod uart;
fn main() {
entry!(kernel_entry);
fn kernel_entry() -> ! {
let gpio = gpio::GPIO::new();
let mut mbox = mbox::Mbox::new();
let uart = uart::Uart::new();
@ -46,7 +51,7 @@ fn main() {
// set up serial console
if uart.init(&mut mbox, &gpio).is_err() {
return; // If UART fails, abort early
loop { cortex_a::asm::wfe() }; // If UART fails, abort early
}
uart.getc(); // Press a key first before being greeted

@ -9,13 +9,13 @@ in the [Rust] systems programming language.
It is basically a combination of two awesome resources.
1. First of all, it is a fork of [Zoltan Baldaszti]'s awesome [tutorial] on bare metal programming on RPi3 in `C`.
1. Rust code will be based on his files, READMEs will be adapted, and I might change things here and there if I think it is beneficial. However, credits to this guy plz!
2. The second props go to [Jorge Aparicio] for ["The Embedonomicon"], from which the glue code is taken.
2. The second props go to [Jorge Aparicio] for ["The Embedonomicon"], from which the boot code is taken.
[Rust]: https://www.rust-lang.org
[Zoltan Baldaszti]: https://github.com/bztsrc
[tutorial]: https://github.com/bztsrc/raspi3-tutorial
[Jorge Aparicio]: https://github.com/japaric
["The Embedonomicon"]: https://github.com/japaric/embedonomicon
["The Embedonomicon"]: https://rust-embedded.github.io/embedonomicon/
## Environment

@ -3,7 +3,7 @@
crates = Dir["**/Cargo.toml"].sort!
crates.each do |x|
next if x.include?('raspi3_glue')
next if x.include?('raspi3_boot')
x = File.dirname(x)
puts "\n\n" + x.to_s + "\n\n"

@ -3,7 +3,7 @@
crates = Dir["**/Cargo.toml"].sort!
crates.each do |x|
next if x.include?('raspi3_glue')
next if x.include?('raspi3_boot')
x = File.dirname(x)
puts "\n\n" + x.to_s + "\n\n"

Loading…
Cancel
Save