├── doc └── wiring.png ├── 03_uart1 ├── kernel8.img ├── Cargo.toml ├── raspi3_boot │ ├── Cargo.toml │ └── src │ │ ├── boot_cores.S │ │ └── lib.rs ├── aarch64-raspi3-none-elf.json ├── README.md ├── src │ ├── main.rs │ └── gpio.rs ├── link.ld ├── Cargo.lock └── Makefile ├── 05_uart0 ├── kernel8.img ├── Cargo.toml ├── raspi3_boot │ ├── Cargo.toml │ └── src │ │ ├── boot_cores.S │ │ └── lib.rs ├── README.md ├── aarch64-raspi3-none-elf.json ├── link.ld ├── Cargo.lock ├── Makefile └── src │ ├── gpio.rs │ └── main.rs ├── 0A_power ├── kernel8.img ├── raspi3_boot │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── Cargo.toml ├── aarch64-raspi3-none-elf.json ├── README.md ├── link.ld ├── Cargo.lock ├── Makefile └── src │ ├── main.rs │ ├── delays.rs │ └── gpio.rs ├── 08_random ├── kernel8.img ├── raspi3_boot │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── Cargo.toml ├── README.md ├── aarch64-raspi3-none-elf.json ├── link.ld ├── Cargo.lock ├── src │ ├── main.rs │ ├── gpio.rs │ ├── rand.rs │ └── mbox.rs └── Makefile ├── 09_delays ├── kernel8.img ├── raspi3_boot │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── Cargo.toml ├── README.md ├── aarch64-raspi3-none-elf.json ├── link.ld ├── Cargo.lock ├── Makefile └── src │ ├── main.rs │ ├── gpio.rs │ ├── delays.rs │ └── mbox.rs ├── 04_mailboxes ├── kernel8.img ├── Cargo.toml ├── raspi3_boot │ ├── Cargo.toml │ └── src │ │ ├── boot_cores.S │ │ └── lib.rs ├── aarch64-raspi3-none-elf.json ├── link.ld ├── Cargo.lock ├── Makefile ├── src │ ├── gpio.rs │ ├── main.rs │ └── mbox.rs └── README.md ├── 01_bareminimum ├── kernel8.img ├── Cargo.toml ├── Cargo.lock ├── aarch64-raspi3-none-elf.json ├── src │ ├── main.rs │ └── boot_cores.S ├── link.ld ├── Makefile └── README.md ├── 06_raspbootin64 ├── kernel8.img ├── Cargo.toml ├── raspi3_boot │ ├── Cargo.toml │ └── src │ │ ├── boot_cores.S │ │ └── lib.rs ├── aarch64-raspi3-none-elf.json ├── link.ld ├── Cargo.lock ├── Makefile ├── src │ ├── main.rs │ ├── gpio.rs │ └── mbox.rs └── README.md ├── 07_abstraction ├── kernel8.img ├── raspi3_boot │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── Cargo.toml ├── aarch64-raspi3-none-elf.json ├── link.ld ├── Cargo.lock ├── Makefile └── src │ ├── gpio.rs │ └── main.rs ├── 02_multicore_rust ├── kernel8.img ├── Cargo.toml ├── raspi3_boot │ ├── Cargo.toml │ └── src │ │ ├── boot_cores.S │ │ └── lib.rs ├── aarch64-raspi3-none-elf.json ├── src │ └── main.rs ├── link.ld ├── Cargo.lock ├── Makefile └── README.md ├── utils ├── fmt_all.rb ├── clippy_all.rb ├── make_all.rb └── clean_all.rb ├── .travis.yml └── LICENSE /doc/wiring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizofe/rust-raspi3-tutorial/HEAD/doc/wiring.png -------------------------------------------------------------------------------- /03_uart1/kernel8.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizofe/rust-raspi3-tutorial/HEAD/03_uart1/kernel8.img -------------------------------------------------------------------------------- /05_uart0/kernel8.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizofe/rust-raspi3-tutorial/HEAD/05_uart0/kernel8.img -------------------------------------------------------------------------------- /0A_power/kernel8.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizofe/rust-raspi3-tutorial/HEAD/0A_power/kernel8.img -------------------------------------------------------------------------------- /08_random/kernel8.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizofe/rust-raspi3-tutorial/HEAD/08_random/kernel8.img -------------------------------------------------------------------------------- /09_delays/kernel8.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizofe/rust-raspi3-tutorial/HEAD/09_delays/kernel8.img -------------------------------------------------------------------------------- /04_mailboxes/kernel8.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizofe/rust-raspi3-tutorial/HEAD/04_mailboxes/kernel8.img -------------------------------------------------------------------------------- /01_bareminimum/kernel8.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizofe/rust-raspi3-tutorial/HEAD/01_bareminimum/kernel8.img -------------------------------------------------------------------------------- /06_raspbootin64/kernel8.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizofe/rust-raspi3-tutorial/HEAD/06_raspbootin64/kernel8.img -------------------------------------------------------------------------------- /07_abstraction/kernel8.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizofe/rust-raspi3-tutorial/HEAD/07_abstraction/kernel8.img -------------------------------------------------------------------------------- /02_multicore_rust/kernel8.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizofe/rust-raspi3-tutorial/HEAD/02_multicore_rust/kernel8.img -------------------------------------------------------------------------------- /01_bareminimum/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kernel8" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | panic-abort = "0.2.0" 8 | -------------------------------------------------------------------------------- /02_multicore_rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kernel8" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | raspi3_boot = { path = "raspi3_boot" } 8 | -------------------------------------------------------------------------------- /utils/fmt_all.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | crates = Dir["**/Cargo.toml"] 4 | 5 | crates.each do |x| 6 | x = File.dirname(x) 7 | 8 | Dir.chdir(x) do 9 | `cargo fmt` 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /03_uart1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kernel8" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | raspi3_boot = { path = "raspi3_boot" } 8 | register = "0.1.1" 9 | -------------------------------------------------------------------------------- /05_uart0/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kernel8" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | raspi3_boot = { path = "raspi3_boot" } 8 | register = "0.1.1" 9 | -------------------------------------------------------------------------------- /04_mailboxes/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kernel8" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | raspi3_boot = { path = "raspi3_boot" } 8 | register = "0.1.1" 9 | -------------------------------------------------------------------------------- /06_raspbootin64/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kernel8" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | raspi3_boot = { path = "raspi3_boot" } 8 | register = "0.1.1" 9 | -------------------------------------------------------------------------------- /03_uart1/raspi3_boot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "raspi3_boot" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | cortex-a = "1.0.0" 8 | panic-abort = "0.2.0" 9 | r0 = "0.2.2" 10 | -------------------------------------------------------------------------------- /05_uart0/raspi3_boot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "raspi3_boot" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | cortex-a = "1.0.0" 8 | panic-abort = "0.2.0" 9 | r0 = "0.2.2" 10 | -------------------------------------------------------------------------------- /08_random/raspi3_boot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "raspi3_boot" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | cortex-a = "1.0.0" 8 | panic-abort = "0.2.0" 9 | r0 = "0.2.2" 10 | -------------------------------------------------------------------------------- /09_delays/raspi3_boot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "raspi3_boot" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | cortex-a = "1.0.0" 8 | panic-abort = "0.2.0" 9 | r0 = "0.2.2" 10 | -------------------------------------------------------------------------------- /0A_power/raspi3_boot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "raspi3_boot" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | cortex-a = "1.0.0" 8 | panic-abort = "0.2.0" 9 | r0 = "0.2.2" 10 | -------------------------------------------------------------------------------- /04_mailboxes/raspi3_boot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "raspi3_boot" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | cortex-a = "1.0.0" 8 | panic-abort = "0.2.0" 9 | r0 = "0.2.2" 10 | -------------------------------------------------------------------------------- /07_abstraction/raspi3_boot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "raspi3_boot" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | cortex-a = "1.0.0" 8 | panic-abort = "0.2.0" 9 | r0 = "0.2.2" 10 | -------------------------------------------------------------------------------- /02_multicore_rust/raspi3_boot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "raspi3_boot" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | cortex-a = "1.0.0" 8 | panic-abort = "0.2.0" 9 | r0 = "0.2.2" 10 | -------------------------------------------------------------------------------- /06_raspbootin64/raspi3_boot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "raspi3_boot" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | cortex-a = "1.0.0" 8 | panic-abort = "0.2.0" 9 | r0 = "0.2.2" 10 | -------------------------------------------------------------------------------- /08_random/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kernel8" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | raspi3_boot = { path = "raspi3_boot" } 8 | cortex-a = "1.0.0" 9 | register = "0.1.1" 10 | -------------------------------------------------------------------------------- /09_delays/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kernel8" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | raspi3_boot = { path = "raspi3_boot" } 8 | cortex-a = "1.0.0" 9 | register = "0.1.1" 10 | -------------------------------------------------------------------------------- /0A_power/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kernel8" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | raspi3_boot = { path = "raspi3_boot" } 8 | cortex-a = "1.0.0" 9 | register = "0.1.1" 10 | -------------------------------------------------------------------------------- /07_abstraction/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kernel8" 3 | version = "0.1.0" 4 | authors = ["Andre Richter "] 5 | 6 | [dependencies] 7 | raspi3_boot = { path = "raspi3_boot" } 8 | cortex-a = "1.0.0" 9 | register = "0.1.1" 10 | -------------------------------------------------------------------------------- /utils/clippy_all.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | crates = Dir["*/Cargo.toml"] 4 | crates.delete_if { |x| x.include?('bareminimum') } 5 | 6 | crates.each do |x| 7 | x = File.dirname(x) 8 | 9 | Dir.chdir(x) do 10 | `make clippy` 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /utils/make_all.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | crates = Dir["**/Cargo.toml"].sort! 4 | 5 | crates.each do |x| 6 | next if x.include?('raspi3_boot') 7 | 8 | x = File.dirname(x) 9 | puts "\n\n" + x.to_s + "\n\n" 10 | Dir.chdir(x) do 11 | unless system('make') 12 | puts "\n\nBuild failed!" 13 | exit(1) # Exit with error code 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /utils/clean_all.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | crates = Dir["**/Cargo.toml"].sort! 4 | 5 | crates.each do |x| 6 | next if x.include?('raspi3_boot') 7 | 8 | x = File.dirname(x) 9 | puts "\n\n" + x.to_s + "\n\n" 10 | Dir.chdir(x) do 11 | unless system('make clean') 12 | puts "\n\nBuild failed!" 13 | exit(1) # Exit with error code 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /01_bareminimum/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "kernel8" 3 | version = "0.1.0" 4 | dependencies = [ 5 | "panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 6 | ] 7 | 8 | [[package]] 9 | name = "panic-abort" 10 | version = "0.2.0" 11 | source = "registry+https://github.com/rust-lang/crates.io-index" 12 | 13 | [metadata] 14 | "checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e" 15 | -------------------------------------------------------------------------------- /05_uart0/README.md: -------------------------------------------------------------------------------- 1 | # Tutorial 05 - UART0, PL011 2 | 3 | This tutorial does the same as tutorial 04, but it prints the serial number on 4 | UART0. As such, it can be used easily with qemu, like 5 | 6 | ```sh 7 | $ make # To build the kernel 8 | $ make qemu 9 | 10 | Hello Rustacean! 11 | My serial number is: 0000000000000000 12 | ``` 13 | 14 | ## uart.rs 15 | 16 | Before we could use a rate divisor value, we must establish a valid clock rate 17 | for the PL011. It's done via mailboxes, with the same property channel we used 18 | earlier. Otherwise this interface is identical to the UART1 one. 19 | 20 | ## main.rs 21 | 22 | We query the board's serial number and then we display it on the serial console. 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | 3 | # sudo: required 4 | 5 | # services: 6 | # - docker 7 | 8 | notifications: 9 | email: 10 | on_success: never 11 | on_failure: change 12 | 13 | addons: 14 | apt: 15 | packages: 16 | - ruby 17 | 18 | rust: 19 | - nightly 20 | 21 | os: 22 | - linux 23 | 24 | cache: cargo 25 | 26 | before_script: 27 | - rustup component add rust-src llvm-tools-preview 28 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 29 | - (test -x $HOME/.cargo/bin/xargo || cargo install xargo) 30 | - (test -x $HOME/.cargo/bin/cargo-objcopy || cargo install cargo-binutils) 31 | - cargo install-update -a 32 | 33 | script: 34 | - ruby utils/make_all.rb 35 | -------------------------------------------------------------------------------- /08_random/README.md: -------------------------------------------------------------------------------- 1 | # Tutorial 08 - Hardware Random Number Generator 2 | 3 | This going to be an easy tutorial. We query a number from the (undocumented) 4 | hardware random number generator. You can use this to implement a simple, but 5 | accurate dice throw in any game. It is important as without hardware support you 6 | can only generate pseudo-random numbers. 7 | 8 | ## rand.s 9 | 10 | Due to lack of documentation, we [mimic the respective Linux driver] 11 | (https://github.com/torvalds/linux/blob/master/drivers/char/hw_random/bcm2835-rng.c). 12 | 13 | `Rng::init(&self)` initializes the hardware. 14 | 15 | `Rng::rand(&self, min: u32, max: u32)` returns a random number between min and 16 | max. 17 | 18 | ## main.rs 19 | 20 | Press a key to query a random value and then display it on the serial console. 21 | -------------------------------------------------------------------------------- /09_delays/README.md: -------------------------------------------------------------------------------- 1 | # Tutorial 09 - Delays 2 | 3 | It is very important to wait precise amounts of time while you are interfacing 4 | with low level hardware. In this tutorial, we'll cover thee ways. One is CPU 5 | frequency dependent (and useful if wait time is given in CPU clock cycles), the 6 | other two are µs based. 7 | 8 | ## delays.rs 9 | 10 | `delays::wait_cycles(cyc: u32)` this is very straightforward, we execute the 11 | `nop` instruction n times. 12 | 13 | `delays::wait_msec(n: u32)` this implementation uses ARM system registers 14 | (available on all AArch64 CPUs). 15 | 16 | `delays::SysTmr::wait_msec_st(&self, n: u64)` is a BCM specific implementation, 17 | which uses the System Timer peripheral (not available on qemu). 18 | 19 | ## uart.rs 20 | 21 | We can now conveniently use `delays::wait_cycles()` in `Uart::init()`. 22 | 23 | ## main.rs 24 | 25 | We test our different wait implementations. 26 | -------------------------------------------------------------------------------- /03_uart1/aarch64-raspi3-none-elf.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "aarch64", 3 | "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", 4 | "executables": true, 5 | "linker-flavor": "ld.lld", 6 | "linker": "rust-lld", 7 | "linker-is-gnu": true, 8 | "pre-link-args": { 9 | "ld.lld": [ 10 | "--script=link.ld" 11 | ] 12 | }, 13 | "llvm-target": "aarch64-unknown-none", 14 | "no-compiler-rt": true, 15 | "features": "+a53,+strict-align", 16 | "max-atomic-width": 128, 17 | "os": "none", 18 | "panic": "abort", 19 | "panic-strategy": "abort", 20 | "relocation-model": "pic", 21 | "target-c-int-width": "32", 22 | "target-endian": "little", 23 | "target-pointer-width": "64", 24 | "disable-redzone": true, 25 | "abi-blacklist": [ 26 | "stdcall", 27 | "fastcall", 28 | "vectorcall", 29 | "thiscall", 30 | "win64", 31 | "sysv64" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /05_uart0/aarch64-raspi3-none-elf.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "aarch64", 3 | "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", 4 | "executables": true, 5 | "linker-flavor": "ld.lld", 6 | "linker": "rust-lld", 7 | "linker-is-gnu": true, 8 | "pre-link-args": { 9 | "ld.lld": [ 10 | "--script=link.ld" 11 | ] 12 | }, 13 | "llvm-target": "aarch64-unknown-none", 14 | "no-compiler-rt": true, 15 | "features": "+a53,+strict-align", 16 | "max-atomic-width": 128, 17 | "os": "none", 18 | "panic": "abort", 19 | "panic-strategy": "abort", 20 | "relocation-model": "pic", 21 | "target-c-int-width": "32", 22 | "target-endian": "little", 23 | "target-pointer-width": "64", 24 | "disable-redzone": true, 25 | "abi-blacklist": [ 26 | "stdcall", 27 | "fastcall", 28 | "vectorcall", 29 | "thiscall", 30 | "win64", 31 | "sysv64" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /0A_power/aarch64-raspi3-none-elf.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "aarch64", 3 | "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", 4 | "executables": true, 5 | "linker-flavor": "ld.lld", 6 | "linker": "rust-lld", 7 | "linker-is-gnu": true, 8 | "pre-link-args": { 9 | "ld.lld": [ 10 | "--script=link.ld" 11 | ] 12 | }, 13 | "llvm-target": "aarch64-unknown-none", 14 | "no-compiler-rt": true, 15 | "features": "+a53,+strict-align", 16 | "max-atomic-width": 128, 17 | "os": "none", 18 | "panic": "abort", 19 | "panic-strategy": "abort", 20 | "relocation-model": "pic", 21 | "target-c-int-width": "32", 22 | "target-endian": "little", 23 | "target-pointer-width": "64", 24 | "disable-redzone": true, 25 | "abi-blacklist": [ 26 | "stdcall", 27 | "fastcall", 28 | "vectorcall", 29 | "thiscall", 30 | "win64", 31 | "sysv64" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /04_mailboxes/aarch64-raspi3-none-elf.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "aarch64", 3 | "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", 4 | "executables": true, 5 | "linker-flavor": "ld.lld", 6 | "linker": "rust-lld", 7 | "linker-is-gnu": true, 8 | "pre-link-args": { 9 | "ld.lld": [ 10 | "--script=link.ld" 11 | ] 12 | }, 13 | "llvm-target": "aarch64-unknown-none", 14 | "no-compiler-rt": true, 15 | "features": "+a53,+strict-align", 16 | "max-atomic-width": 128, 17 | "os": "none", 18 | "panic": "abort", 19 | "panic-strategy": "abort", 20 | "relocation-model": "pic", 21 | "target-c-int-width": "32", 22 | "target-endian": "little", 23 | "target-pointer-width": "64", 24 | "disable-redzone": true, 25 | "abi-blacklist": [ 26 | "stdcall", 27 | "fastcall", 28 | "vectorcall", 29 | "thiscall", 30 | "win64", 31 | "sysv64" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /08_random/aarch64-raspi3-none-elf.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "aarch64", 3 | "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", 4 | "executables": true, 5 | "linker-flavor": "ld.lld", 6 | "linker": "rust-lld", 7 | "linker-is-gnu": true, 8 | "pre-link-args": { 9 | "ld.lld": [ 10 | "--script=link.ld" 11 | ] 12 | }, 13 | "llvm-target": "aarch64-unknown-none", 14 | "no-compiler-rt": true, 15 | "features": "+a53,+strict-align", 16 | "max-atomic-width": 128, 17 | "os": "none", 18 | "panic": "abort", 19 | "panic-strategy": "abort", 20 | "relocation-model": "pic", 21 | "target-c-int-width": "32", 22 | "target-endian": "little", 23 | "target-pointer-width": "64", 24 | "disable-redzone": true, 25 | "abi-blacklist": [ 26 | "stdcall", 27 | "fastcall", 28 | "vectorcall", 29 | "thiscall", 30 | "win64", 31 | "sysv64" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /09_delays/aarch64-raspi3-none-elf.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "aarch64", 3 | "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", 4 | "executables": true, 5 | "linker-flavor": "ld.lld", 6 | "linker": "rust-lld", 7 | "linker-is-gnu": true, 8 | "pre-link-args": { 9 | "ld.lld": [ 10 | "--script=link.ld" 11 | ] 12 | }, 13 | "llvm-target": "aarch64-unknown-none", 14 | "no-compiler-rt": true, 15 | "features": "+a53,+strict-align", 16 | "max-atomic-width": 128, 17 | "os": "none", 18 | "panic": "abort", 19 | "panic-strategy": "abort", 20 | "relocation-model": "pic", 21 | "target-c-int-width": "32", 22 | "target-endian": "little", 23 | "target-pointer-width": "64", 24 | "disable-redzone": true, 25 | "abi-blacklist": [ 26 | "stdcall", 27 | "fastcall", 28 | "vectorcall", 29 | "thiscall", 30 | "win64", 31 | "sysv64" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /01_bareminimum/aarch64-raspi3-none-elf.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "aarch64", 3 | "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", 4 | "executables": true, 5 | "linker-flavor": "ld.lld", 6 | "linker": "rust-lld", 7 | "linker-is-gnu": true, 8 | "pre-link-args": { 9 | "ld.lld": [ 10 | "--script=link.ld" 11 | ] 12 | }, 13 | "llvm-target": "aarch64-unknown-none", 14 | "no-compiler-rt": true, 15 | "features": "+a53,+strict-align", 16 | "max-atomic-width": 128, 17 | "os": "none", 18 | "panic": "abort", 19 | "panic-strategy": "abort", 20 | "relocation-model": "pic", 21 | "target-c-int-width": "32", 22 | "target-endian": "little", 23 | "target-pointer-width": "64", 24 | "disable-redzone": true, 25 | "abi-blacklist": [ 26 | "stdcall", 27 | "fastcall", 28 | "vectorcall", 29 | "thiscall", 30 | "win64", 31 | "sysv64" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /02_multicore_rust/aarch64-raspi3-none-elf.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "aarch64", 3 | "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", 4 | "executables": true, 5 | "linker-flavor": "ld.lld", 6 | "linker": "rust-lld", 7 | "linker-is-gnu": true, 8 | "pre-link-args": { 9 | "ld.lld": [ 10 | "--script=link.ld" 11 | ] 12 | }, 13 | "llvm-target": "aarch64-unknown-none", 14 | "no-compiler-rt": true, 15 | "features": "+a53,+strict-align", 16 | "max-atomic-width": 128, 17 | "os": "none", 18 | "panic": "abort", 19 | "panic-strategy": "abort", 20 | "relocation-model": "pic", 21 | "target-c-int-width": "32", 22 | "target-endian": "little", 23 | "target-pointer-width": "64", 24 | "disable-redzone": true, 25 | "abi-blacklist": [ 26 | "stdcall", 27 | "fastcall", 28 | "vectorcall", 29 | "thiscall", 30 | "win64", 31 | "sysv64" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /06_raspbootin64/aarch64-raspi3-none-elf.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "aarch64", 3 | "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", 4 | "executables": true, 5 | "linker-flavor": "ld.lld", 6 | "linker": "rust-lld", 7 | "linker-is-gnu": true, 8 | "pre-link-args": { 9 | "ld.lld": [ 10 | "--script=link.ld" 11 | ] 12 | }, 13 | "llvm-target": "aarch64-unknown-none", 14 | "no-compiler-rt": true, 15 | "features": "+a53,+strict-align", 16 | "max-atomic-width": 128, 17 | "os": "none", 18 | "panic": "abort", 19 | "panic-strategy": "abort", 20 | "relocation-model": "pic", 21 | "target-c-int-width": "32", 22 | "target-endian": "little", 23 | "target-pointer-width": "64", 24 | "disable-redzone": true, 25 | "abi-blacklist": [ 26 | "stdcall", 27 | "fastcall", 28 | "vectorcall", 29 | "thiscall", 30 | "win64", 31 | "sysv64" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /07_abstraction/aarch64-raspi3-none-elf.json: -------------------------------------------------------------------------------- 1 | { 2 | "arch": "aarch64", 3 | "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", 4 | "executables": true, 5 | "linker-flavor": "ld.lld", 6 | "linker": "rust-lld", 7 | "linker-is-gnu": true, 8 | "pre-link-args": { 9 | "ld.lld": [ 10 | "--script=link.ld" 11 | ] 12 | }, 13 | "llvm-target": "aarch64-unknown-none", 14 | "no-compiler-rt": true, 15 | "features": "+a53,+strict-align", 16 | "max-atomic-width": 128, 17 | "os": "none", 18 | "panic": "abort", 19 | "panic-strategy": "abort", 20 | "relocation-model": "pic", 21 | "target-c-int-width": "32", 22 | "target-endian": "little", 23 | "target-pointer-width": "64", 24 | "disable-redzone": true, 25 | "abi-blacklist": [ 26 | "stdcall", 27 | "fastcall", 28 | "vectorcall", 29 | "thiscall", 30 | "win64", 31 | "sysv64" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2017 bzt (bztsrc@github) 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, copy, 7 | modify, merge, publish, distribute, sublicense, and/or sell copies 8 | of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 18 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /01_bareminimum/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #![no_std] 26 | #![no_main] 27 | #![feature(global_asm)] 28 | 29 | extern crate panic_abort; 30 | 31 | global_asm!(include_str!("boot_cores.S")); 32 | -------------------------------------------------------------------------------- /01_bareminimum/src/boot_cores.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 bzt (bztsrc@github) 3 | * Copyright (c) 2018 Andre Richter 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, copy, 9 | * modify, merge, publish, distribute, sublicense, and/or sell copies 10 | * of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | * 25 | */ 26 | 27 | .section ".text.boot" 28 | 29 | .global _boot_cores 30 | 31 | _boot_cores: 32 | 1: wfe 33 | b 1b 34 | -------------------------------------------------------------------------------- /02_multicore_rust/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #![no_std] 26 | #![no_main] 27 | 28 | #[macro_use] 29 | extern crate raspi3_boot; 30 | 31 | entry!(kernel_entry); 32 | 33 | fn kernel_entry() -> ! { 34 | loop {} 35 | } 36 | -------------------------------------------------------------------------------- /01_bareminimum/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot_cores); 26 | 27 | SECTIONS 28 | { 29 | . = 0x80000; 30 | 31 | .text : 32 | { 33 | KEEP(*(.text.boot)) *(.text .text.*) 34 | } 35 | 36 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } 37 | } 38 | -------------------------------------------------------------------------------- /03_uart1/README.md: -------------------------------------------------------------------------------- 1 | # Tutorial 03 - UART1, Auxilary mini UART 2 | 3 | It is time for the famous Hello World example. We're going to write on the UART1 4 | first, as it's easier to program as it has a fixed clocked frequency. 5 | 6 | NOTE: qemu does not redirect UART1 to terminal by default, only UART0! 7 | 8 | ## gpio.rs 9 | 10 | We have a new file that defines the GPIO controller addresses. It is going to be 11 | very popular, as many device will need it in the future. 12 | 13 | We are using the [register][register] crate to modify MMIO addresses, because it 14 | allows easy wrapping of addresses to volatile types. It will also be used for 15 | UART registers. 16 | 17 | [register]: https://crates.io/crates/register 18 | 19 | ## uart.rs 20 | 21 | A very minimal implementation. 22 | 23 | `MiniUart::init(&self)` initializes the device and maps it to the GPIO ports. 24 | 25 | `MiniUart::send(&self, c: char)` sends a character over the serial line. 26 | 27 | `MiniUart::getc(&self)` receives a character. The carrige return character (13) 28 | will be converted into a newline character (10). 29 | 30 | `MiniUart::puts(&self, string: &str)` prints out a string. On newline, a carrige 31 | return character will also be sent (13 + 10). 32 | 33 | ## main.rs 34 | 35 | First we have to call the uart initialization code. Then we wait for the first 36 | keypress from the user before we say "Hello Rustacean!". If you've purchased an 37 | USB serial cable, you should see it on `screen`'s screen. After that, every 38 | character typed in `screen` will be echoed back. If you haven't turned off local 39 | echo, that means you'll see every pressed key twice. 40 | -------------------------------------------------------------------------------- /06_raspbootin64/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot_cores); 26 | 27 | SECTIONS 28 | { 29 | . = 0x80000 - 2048; 30 | 31 | _code = .; 32 | .text : 33 | { 34 | KEEP(*(.text.boot)) *(.text .text.*) 35 | } 36 | 37 | .rodata : 38 | { 39 | *(.rodata .rodata.*) 40 | } 41 | 42 | PROVIDE(_data = .); 43 | .data : 44 | { 45 | *(.data .data.*) 46 | } 47 | _end = .; 48 | 49 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } 50 | } 51 | 52 | __loader_size = (_end - _code)>>3; 53 | -------------------------------------------------------------------------------- /0A_power/README.md: -------------------------------------------------------------------------------- 1 | # Tutorial 0A - Power management 2 | 3 | For embedded systems, power consumption is critical. The Raspberry Pi 3 has a 4 | very sophisticated PM interface. You can turn each device on and off 5 | independently. There's a catch though. The GPIO VCC pins are hardwired, there's 6 | no way to turn them off programmatically. This means if you connect some devices 7 | to them, you'll have to implement a way to turn those devices off (with a 8 | transistor connected to a data GPIO pin for example). 9 | 10 | ## power.rs 11 | 12 | Unfortunately, the documentation about the PM interface is very very rare. We 13 | will therefore more or less implement a carbon copy of respective functions of 14 | Linux' 15 | [bcm2835_wdt.c](https://github.com/torvalds/linux/blob/master/drivers/watchdog/bcm2835_wdt.c) 16 | driver. 17 | 18 | The power management controller is one of the peripherals that are not emulated 19 | properly by QEMU. Our implementation therefore works on real hardware only. 20 | 21 | `Power::off(&self, mbox: &mut mbox::Mbox, gpio: &gpio::GPIO)` shuts down the 22 | board to an almost zero power consumption state. 23 | 24 | `Power::reset(&self)` reboots the machine. Also handled by the PMC, and since 25 | the Raspberry Pi does not have a hardware reset button, it's very useful. 26 | 27 | When using `make raspboot` and choosing `reset()`, you can see your code in 28 | action nicely as you generate a boot-loop. 29 | 30 | 31 | ## gpio.rs 32 | 33 | We introduce a lot of new GPIO pins. It's a good time to refactor the GPIO MMIO 34 | interface into its own type with the common `RegisterBlock` implementation that 35 | you already know from the other components. 36 | 37 | ## main.rs 38 | 39 | We display a simple menu, and wait for user input. Depending on the input, we 40 | reboot the system or power it off. 41 | -------------------------------------------------------------------------------- /03_uart1/raspi3_boot/src/boot_cores.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 bzt (bztsrc@github) 3 | * Copyright (c) 2018 Andre Richter 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, copy, 9 | * modify, merge, publish, distribute, sublicense, and/or sell copies 10 | * of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | * 25 | */ 26 | 27 | .section ".text.boot" 28 | 29 | .global _boot_cores 30 | 31 | _boot_cores: 32 | // read cpu id, stop slave cores 33 | mrs x1, mpidr_el1 34 | and x1, x1, #3 35 | cbz x1, 2f 36 | // cpu id > 0, stop 37 | 1: wfe 38 | b 1b 39 | 2: // cpu id == 0 40 | 41 | // set stack before our code 42 | ldr x1, =_boot_cores 43 | mov sp, x1 44 | 45 | // jump to Rust code, should not return 46 | bl reset 47 | // for failsafe, halt this core too 48 | b 1b 49 | -------------------------------------------------------------------------------- /04_mailboxes/raspi3_boot/src/boot_cores.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 bzt (bztsrc@github) 3 | * Copyright (c) 2018 Andre Richter 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, copy, 9 | * modify, merge, publish, distribute, sublicense, and/or sell copies 10 | * of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | * 25 | */ 26 | 27 | .section ".text.boot" 28 | 29 | .global _boot_cores 30 | 31 | _boot_cores: 32 | // read cpu id, stop slave cores 33 | mrs x1, mpidr_el1 34 | and x1, x1, #3 35 | cbz x1, 2f 36 | // cpu id > 0, stop 37 | 1: wfe 38 | b 1b 39 | 2: // cpu id == 0 40 | 41 | // set stack before our code 42 | ldr x1, =_boot_cores 43 | mov sp, x1 44 | 45 | // jump to Rust code, should not return 46 | bl reset 47 | // for failsafe, halt this core too 48 | b 1b 49 | -------------------------------------------------------------------------------- /05_uart0/raspi3_boot/src/boot_cores.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 bzt (bztsrc@github) 3 | * Copyright (c) 2018 Andre Richter 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, copy, 9 | * modify, merge, publish, distribute, sublicense, and/or sell copies 10 | * of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | * 25 | */ 26 | 27 | .section ".text.boot" 28 | 29 | .global _boot_cores 30 | 31 | _boot_cores: 32 | // read cpu id, stop slave cores 33 | mrs x1, mpidr_el1 34 | and x1, x1, #3 35 | cbz x1, 2f 36 | // cpu id > 0, stop 37 | 1: wfe 38 | b 1b 39 | 2: // cpu id == 0 40 | 41 | // set stack before our code 42 | ldr x1, =_boot_cores 43 | mov sp, x1 44 | 45 | // jump to Rust code, should not return 46 | bl reset 47 | // for failsafe, halt this core too 48 | b 1b 49 | -------------------------------------------------------------------------------- /02_multicore_rust/raspi3_boot/src/boot_cores.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 bzt (bztsrc@github) 3 | * Copyright (c) 2018 Andre Richter 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, copy, 9 | * modify, merge, publish, distribute, sublicense, and/or sell copies 10 | * of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | * 25 | */ 26 | 27 | .section ".text.boot" 28 | 29 | .global _boot_cores 30 | 31 | _boot_cores: 32 | // read cpu id, stop slave cores 33 | mrs x1, mpidr_el1 34 | and x1, x1, #3 35 | cbz x1, 2f 36 | // cpu id > 0, stop 37 | 1: wfe 38 | b 1b 39 | 2: // cpu id == 0 40 | 41 | // set stack before our code 42 | ldr x1, =_boot_cores 43 | mov sp, x1 44 | 45 | // jump to Rust code, should not return 46 | bl reset 47 | // for failsafe, halt this core too 48 | b 1b 49 | -------------------------------------------------------------------------------- /03_uart1/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #![no_std] 26 | #![no_main] 27 | #![feature(asm)] 28 | 29 | #[macro_use] 30 | extern crate raspi3_boot; 31 | 32 | #[macro_use] 33 | extern crate register; 34 | 35 | const MMIO_BASE: u32 = 0x3F00_0000; 36 | 37 | mod gpio; 38 | mod uart; 39 | 40 | entry!(kernel_entry); 41 | 42 | fn kernel_entry() -> ! { 43 | let uart = uart::MiniUart::new(); 44 | 45 | // set up serial console 46 | uart.init(); 47 | 48 | uart.getc(); // Press a key first before being greeted 49 | uart.puts("Hello Rustacean!\n"); 50 | 51 | // echo everything back 52 | loop { 53 | uart.send(uart.getc()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /03_uart1/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot_cores); 26 | 27 | SECTIONS 28 | { 29 | . = 0x80000; 30 | 31 | .text : 32 | { 33 | KEEP(*(.text.boot)) *(.text .text.*) 34 | } 35 | 36 | .rodata : 37 | { 38 | *(.rodata .rodata.*) 39 | } 40 | 41 | PROVIDE(_data = .); 42 | .data : 43 | { 44 | *(.data .data.*) 45 | } 46 | 47 | .bss (NOLOAD) : 48 | { 49 | . = ALIGN(16); 50 | *(.bss .bss.*) 51 | *(COMMON) 52 | } 53 | 54 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } 55 | } 56 | 57 | __bss_start = ADDR(.bss); 58 | __bss_end = ADDR(.bss) + SIZEOF(.bss); 59 | -------------------------------------------------------------------------------- /05_uart0/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot_cores); 26 | 27 | SECTIONS 28 | { 29 | . = 0x80000; 30 | 31 | .text : 32 | { 33 | KEEP(*(.text.boot)) *(.text .text.*) 34 | } 35 | 36 | .rodata : 37 | { 38 | *(.rodata .rodata.*) 39 | } 40 | 41 | PROVIDE(_data = .); 42 | .data : 43 | { 44 | *(.data .data.*) 45 | } 46 | 47 | .bss (NOLOAD) : 48 | { 49 | . = ALIGN(16); 50 | *(.bss .bss.*) 51 | *(COMMON) 52 | } 53 | 54 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } 55 | } 56 | 57 | __bss_start = ADDR(.bss); 58 | __bss_end = ADDR(.bss) + SIZEOF(.bss); 59 | -------------------------------------------------------------------------------- /08_random/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot_cores); 26 | 27 | SECTIONS 28 | { 29 | . = 0x80000; 30 | 31 | .text : 32 | { 33 | KEEP(*(.text.boot)) *(.text .text.*) 34 | } 35 | 36 | .rodata : 37 | { 38 | *(.rodata .rodata.*) 39 | } 40 | 41 | PROVIDE(_data = .); 42 | .data : 43 | { 44 | *(.data .data.*) 45 | } 46 | 47 | .bss (NOLOAD) : 48 | { 49 | . = ALIGN(16); 50 | *(.bss .bss.*) 51 | *(COMMON) 52 | } 53 | 54 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } 55 | } 56 | 57 | __bss_start = ADDR(.bss); 58 | __bss_end = ADDR(.bss) + SIZEOF(.bss); 59 | -------------------------------------------------------------------------------- /09_delays/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot_cores); 26 | 27 | SECTIONS 28 | { 29 | . = 0x80000; 30 | 31 | .text : 32 | { 33 | KEEP(*(.text.boot)) *(.text .text.*) 34 | } 35 | 36 | .rodata : 37 | { 38 | *(.rodata .rodata.*) 39 | } 40 | 41 | PROVIDE(_data = .); 42 | .data : 43 | { 44 | *(.data .data.*) 45 | } 46 | 47 | .bss (NOLOAD) : 48 | { 49 | . = ALIGN(16); 50 | *(.bss .bss.*) 51 | *(COMMON) 52 | } 53 | 54 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } 55 | } 56 | 57 | __bss_start = ADDR(.bss); 58 | __bss_end = ADDR(.bss) + SIZEOF(.bss); 59 | -------------------------------------------------------------------------------- /0A_power/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot_cores); 26 | 27 | SECTIONS 28 | { 29 | . = 0x80000; 30 | 31 | .text : 32 | { 33 | KEEP(*(.text.boot)) *(.text .text.*) 34 | } 35 | 36 | .rodata : 37 | { 38 | *(.rodata .rodata.*) 39 | } 40 | 41 | PROVIDE(_data = .); 42 | .data : 43 | { 44 | *(.data .data.*) 45 | } 46 | 47 | .bss (NOLOAD) : 48 | { 49 | . = ALIGN(16); 50 | *(.bss .bss.*) 51 | *(COMMON) 52 | } 53 | 54 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } 55 | } 56 | 57 | __bss_start = ADDR(.bss); 58 | __bss_end = ADDR(.bss) + SIZEOF(.bss); 59 | -------------------------------------------------------------------------------- /04_mailboxes/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot_cores); 26 | 27 | SECTIONS 28 | { 29 | . = 0x80000; 30 | 31 | .text : 32 | { 33 | KEEP(*(.text.boot)) *(.text .text.*) 34 | } 35 | 36 | .rodata : 37 | { 38 | *(.rodata .rodata.*) 39 | } 40 | 41 | PROVIDE(_data = .); 42 | .data : 43 | { 44 | *(.data .data.*) 45 | } 46 | 47 | .bss (NOLOAD) : 48 | { 49 | . = ALIGN(16); 50 | *(.bss .bss.*) 51 | *(COMMON) 52 | } 53 | 54 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } 55 | } 56 | 57 | __bss_start = ADDR(.bss); 58 | __bss_end = ADDR(.bss) + SIZEOF(.bss); 59 | -------------------------------------------------------------------------------- /07_abstraction/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot_cores); 26 | 27 | SECTIONS 28 | { 29 | . = 0x80000; 30 | 31 | .text : 32 | { 33 | KEEP(*(.text.boot)) *(.text .text.*) 34 | } 35 | 36 | .rodata : 37 | { 38 | *(.rodata .rodata.*) 39 | } 40 | 41 | PROVIDE(_data = .); 42 | .data : 43 | { 44 | *(.data .data.*) 45 | } 46 | 47 | .bss (NOLOAD) : 48 | { 49 | . = ALIGN(16); 50 | *(.bss .bss.*) 51 | *(COMMON) 52 | } 53 | 54 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } 55 | } 56 | 57 | __bss_start = ADDR(.bss); 58 | __bss_end = ADDR(.bss) + SIZEOF(.bss); 59 | -------------------------------------------------------------------------------- /02_multicore_rust/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | ENTRY(_boot_cores); 26 | 27 | SECTIONS 28 | { 29 | . = 0x80000; 30 | 31 | .text : 32 | { 33 | KEEP(*(.text.boot)) *(.text .text.*) 34 | } 35 | 36 | .rodata : 37 | { 38 | *(.rodata .rodata.*) 39 | } 40 | 41 | PROVIDE(_data = .); 42 | .data : 43 | { 44 | *(.data .data.*) 45 | } 46 | 47 | .bss (NOLOAD) : 48 | { 49 | . = ALIGN(16); 50 | *(.bss .bss.*) 51 | *(COMMON) 52 | } 53 | 54 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } 55 | } 56 | 57 | __bss_start = ADDR(.bss); 58 | __bss_end = ADDR(.bss) + SIZEOF(.bss); 59 | -------------------------------------------------------------------------------- /06_raspbootin64/raspi3_boot/src/boot_cores.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 bzt (bztsrc@github) 3 | * Copyright (c) 2018 Andre Richter 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, copy, 9 | * modify, merge, publish, distribute, sublicense, and/or sell copies 10 | * of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | * 25 | */ 26 | 27 | .section ".text.boot" 28 | 29 | .global _boot_cores 30 | 31 | _boot_cores: 32 | // read cpu id, stop slave cores 33 | mrs x1, mpidr_el1 34 | and x1, x1, #3 35 | cbz x1, 2f 36 | // cpu id > 0, stop 37 | 1: wfe 38 | b 1b 39 | 2: // cpu id == 0 40 | 41 | // relocate our code from load address to link address 42 | ldr x1, =0x80000 43 | ldr x2, =_boot_cores 44 | ldr w3, =__loader_size 45 | 3: ldr x4, [x1], #8 46 | str x4, [x2], #8 47 | sub w3, w3, #1 48 | cbnz w3, 3b 49 | 50 | // set stack before our code 51 | ldr x1, =_boot_cores 52 | mov sp, x1 53 | 54 | // jump to relocated Rust code, should not return 55 | bl reset-2048 56 | // for failsafe, halt this core too 57 | b 1b 58 | -------------------------------------------------------------------------------- /02_multicore_rust/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "cortex-a" 3 | version = "1.0.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "kernel8" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "raspi3_boot 0.1.0", 14 | ] 15 | 16 | [[package]] 17 | name = "panic-abort" 18 | version = "0.2.0" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | 21 | [[package]] 22 | name = "r0" 23 | version = "0.2.2" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | 26 | [[package]] 27 | name = "raspi3_boot" 28 | version = "0.1.0" 29 | dependencies = [ 30 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 31 | "panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 32 | "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 33 | ] 34 | 35 | [[package]] 36 | name = "register" 37 | version = "0.1.1" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | dependencies = [ 40 | "tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 41 | ] 42 | 43 | [[package]] 44 | name = "tock-registers" 45 | version = "0.1.0" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | 48 | [metadata] 49 | "checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb" 50 | "checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e" 51 | "checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" 52 | "checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479" 53 | "checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9" 54 | -------------------------------------------------------------------------------- /01_bareminimum/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # MIT License 3 | # 4 | # Copyright (c) 2018 Andre Richter 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | 25 | TARGET = aarch64-raspi3-none-elf 26 | 27 | OBJCOPY = cargo objcopy -- 28 | OBJCOPY_PARAMS = --strip-all -O binary 29 | 30 | UTILS_CONTAINER = andrerichter/raspi3-utils 31 | DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work 32 | QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img 33 | 34 | all: clean kernel8.img 35 | 36 | target/$(TARGET)/debug/kernel8: src/main.rs 37 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) 38 | cp $@ . 39 | 40 | target/$(TARGET)/release/kernel8: src/main.rs 41 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) --release 42 | cp $@ . 43 | 44 | ifeq ($(DEBUG),1) 45 | kernel8: target/$(TARGET)/debug/kernel8 46 | else 47 | kernel8: target/$(TARGET)/release/kernel8 48 | endif 49 | 50 | kernel8.img: kernel8 51 | $(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img 52 | 53 | qemu: 54 | $(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -d in_asm 55 | 56 | clean: 57 | cargo clean 58 | rm -f kernel8 59 | -------------------------------------------------------------------------------- /03_uart1/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "cortex-a" 3 | version = "1.0.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "kernel8" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "raspi3_boot 0.1.0", 14 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 15 | ] 16 | 17 | [[package]] 18 | name = "panic-abort" 19 | version = "0.2.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | 22 | [[package]] 23 | name = "r0" 24 | version = "0.2.2" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | 27 | [[package]] 28 | name = "raspi3_boot" 29 | version = "0.1.0" 30 | dependencies = [ 31 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 32 | "panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 33 | "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 34 | ] 35 | 36 | [[package]] 37 | name = "register" 38 | version = "0.1.1" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | dependencies = [ 41 | "tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 42 | ] 43 | 44 | [[package]] 45 | name = "tock-registers" 46 | version = "0.1.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | 49 | [metadata] 50 | "checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb" 51 | "checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e" 52 | "checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" 53 | "checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479" 54 | "checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9" 55 | -------------------------------------------------------------------------------- /05_uart0/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "cortex-a" 3 | version = "1.0.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "kernel8" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "raspi3_boot 0.1.0", 14 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 15 | ] 16 | 17 | [[package]] 18 | name = "panic-abort" 19 | version = "0.2.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | 22 | [[package]] 23 | name = "r0" 24 | version = "0.2.2" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | 27 | [[package]] 28 | name = "raspi3_boot" 29 | version = "0.1.0" 30 | dependencies = [ 31 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 32 | "panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 33 | "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 34 | ] 35 | 36 | [[package]] 37 | name = "register" 38 | version = "0.1.1" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | dependencies = [ 41 | "tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 42 | ] 43 | 44 | [[package]] 45 | name = "tock-registers" 46 | version = "0.1.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | 49 | [metadata] 50 | "checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb" 51 | "checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e" 52 | "checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" 53 | "checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479" 54 | "checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9" 55 | -------------------------------------------------------------------------------- /06_raspbootin64/raspi3_boot/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Jorge Aparicio 5 | * Copyright (c) 2018 Andre Richter 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #![deny(missing_docs)] 27 | #![deny(warnings)] 28 | #![no_std] 29 | #![feature(global_asm)] 30 | 31 | //! Low-level boot of the Raspberry's processor 32 | 33 | extern crate cortex_a; 34 | extern crate panic_abort; 35 | extern crate r0; 36 | 37 | #[macro_export] 38 | macro_rules! entry { 39 | ($path:path) => { 40 | #[export_name = "main"] 41 | pub unsafe fn __main() -> ! { 42 | // type check the given path 43 | let f: fn() -> ! = $path; 44 | 45 | f() 46 | } 47 | } 48 | } 49 | 50 | /// Reset function. 51 | /// 52 | /// Trampolines into the user's `main()`. 53 | #[no_mangle] 54 | pub unsafe extern "C" fn reset() -> ! { 55 | extern "Rust" { 56 | fn main() -> !; 57 | } 58 | 59 | main(); 60 | } 61 | 62 | // Disable all cores except core 0, and then jump to reset() 63 | global_asm!(include_str!("boot_cores.S")); 64 | -------------------------------------------------------------------------------- /04_mailboxes/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "cortex-a" 3 | version = "1.0.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "kernel8" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "raspi3_boot 0.1.0", 14 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 15 | ] 16 | 17 | [[package]] 18 | name = "panic-abort" 19 | version = "0.2.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | 22 | [[package]] 23 | name = "r0" 24 | version = "0.2.2" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | 27 | [[package]] 28 | name = "raspi3_boot" 29 | version = "0.1.0" 30 | dependencies = [ 31 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 32 | "panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 33 | "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 34 | ] 35 | 36 | [[package]] 37 | name = "register" 38 | version = "0.1.1" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | dependencies = [ 41 | "tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 42 | ] 43 | 44 | [[package]] 45 | name = "tock-registers" 46 | version = "0.1.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | 49 | [metadata] 50 | "checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb" 51 | "checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e" 52 | "checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" 53 | "checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479" 54 | "checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9" 55 | -------------------------------------------------------------------------------- /06_raspbootin64/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "cortex-a" 3 | version = "1.0.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "kernel8" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "raspi3_boot 0.1.0", 14 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 15 | ] 16 | 17 | [[package]] 18 | name = "panic-abort" 19 | version = "0.2.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | 22 | [[package]] 23 | name = "r0" 24 | version = "0.2.2" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | 27 | [[package]] 28 | name = "raspi3_boot" 29 | version = "0.1.0" 30 | dependencies = [ 31 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 32 | "panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 33 | "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 34 | ] 35 | 36 | [[package]] 37 | name = "register" 38 | version = "0.1.1" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | dependencies = [ 41 | "tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 42 | ] 43 | 44 | [[package]] 45 | name = "tock-registers" 46 | version = "0.1.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | 49 | [metadata] 50 | "checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb" 51 | "checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e" 52 | "checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" 53 | "checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479" 54 | "checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9" 55 | -------------------------------------------------------------------------------- /03_uart1/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # MIT License 3 | # 4 | # Copyright (c) 2018 Andre Richter 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | 25 | TARGET = aarch64-raspi3-none-elf 26 | 27 | OBJCOPY = cargo objcopy -- 28 | OBJCOPY_PARAMS = --strip-all -O binary 29 | 30 | UTILS_CONTAINER = andrerichter/raspi3-utils 31 | DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work 32 | QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img 33 | 34 | all: clean kernel8.img 35 | 36 | target/$(TARGET)/debug/kernel8: src/main.rs 37 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) 38 | cp $@ . 39 | 40 | target/$(TARGET)/release/kernel8: src/main.rs 41 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) --release 42 | cp $@ . 43 | 44 | ifeq ($(DEBUG),1) 45 | kernel8: target/$(TARGET)/debug/kernel8 46 | else 47 | kernel8: target/$(TARGET)/release/kernel8 48 | endif 49 | 50 | kernel8.img: kernel8 51 | $(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img 52 | 53 | qemu: 54 | $(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio 55 | 56 | clippy: 57 | RUSTFLAGS="-C panic=abort" xargo clippy 58 | 59 | clean: 60 | cargo clean 61 | rm -f kernel8 62 | -------------------------------------------------------------------------------- /04_mailboxes/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # MIT License 3 | # 4 | # Copyright (c) 2018 Andre Richter 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | 25 | TARGET = aarch64-raspi3-none-elf 26 | 27 | OBJCOPY = cargo objcopy -- 28 | OBJCOPY_PARAMS = --strip-all -O binary 29 | 30 | UTILS_CONTAINER = andrerichter/raspi3-utils 31 | DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work 32 | QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img 33 | 34 | all: clean kernel8.img 35 | 36 | target/$(TARGET)/debug/kernel8: src/main.rs 37 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) 38 | cp $@ . 39 | 40 | target/$(TARGET)/release/kernel8: src/main.rs 41 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) --release 42 | cp $@ . 43 | 44 | ifeq ($(DEBUG),1) 45 | kernel8: target/$(TARGET)/debug/kernel8 46 | else 47 | kernel8: target/$(TARGET)/release/kernel8 48 | endif 49 | 50 | kernel8.img: kernel8 51 | $(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img 52 | 53 | qemu: 54 | $(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio 55 | 56 | clippy: 57 | RUSTFLAGS="-C panic=abort" xargo clippy 58 | 59 | clean: 60 | cargo clean 61 | rm -f kernel8 62 | -------------------------------------------------------------------------------- /05_uart0/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # MIT License 3 | # 4 | # Copyright (c) 2018 Andre Richter 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | 25 | TARGET = aarch64-raspi3-none-elf 26 | 27 | OBJCOPY = cargo objcopy -- 28 | OBJCOPY_PARAMS = --strip-all -O binary 29 | 30 | UTILS_CONTAINER = andrerichter/raspi3-utils 31 | DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work 32 | QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img 33 | 34 | all: clean kernel8.img 35 | 36 | target/$(TARGET)/debug/kernel8: src/main.rs 37 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) 38 | cp $@ . 39 | 40 | target/$(TARGET)/release/kernel8: src/main.rs 41 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) --release 42 | cp $@ . 43 | 44 | ifeq ($(DEBUG),1) 45 | kernel8: target/$(TARGET)/debug/kernel8 46 | else 47 | kernel8: target/$(TARGET)/release/kernel8 48 | endif 49 | 50 | kernel8.img: kernel8 51 | $(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img 52 | 53 | qemu: 54 | $(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio 55 | 56 | clippy: 57 | RUSTFLAGS="-C panic=abort" xargo clippy 58 | 59 | clean: 60 | cargo clean 61 | rm -f kernel8 62 | -------------------------------------------------------------------------------- /02_multicore_rust/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # MIT License 3 | # 4 | # Copyright (c) 2018 Andre Richter 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | 25 | TARGET = aarch64-raspi3-none-elf 26 | 27 | OBJCOPY = cargo objcopy -- 28 | OBJCOPY_PARAMS = --strip-all -O binary 29 | 30 | UTILS_CONTAINER = andrerichter/raspi3-utils 31 | DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work 32 | QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img 33 | 34 | all: clean kernel8.img 35 | 36 | target/$(TARGET)/debug/kernel8: src/main.rs 37 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) 38 | cp $@ . 39 | 40 | target/$(TARGET)/release/kernel8: src/main.rs 41 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) --release 42 | cp $@ . 43 | 44 | ifeq ($(DEBUG),1) 45 | kernel8: target/$(TARGET)/debug/kernel8 46 | else 47 | kernel8: target/$(TARGET)/release/kernel8 48 | endif 49 | 50 | kernel8.img: kernel8 51 | $(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img 52 | 53 | qemu: 54 | $(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -d in_asm 55 | 56 | clippy: 57 | RUSTFLAGS="-C panic=abort" xargo clippy 58 | 59 | clean: 60 | cargo clean 61 | rm -f kernel8 62 | -------------------------------------------------------------------------------- /06_raspbootin64/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # MIT License 3 | # 4 | # Copyright (c) 2018 Andre Richter 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | 25 | TARGET = aarch64-raspi3-none-elf 26 | 27 | OBJCOPY = cargo objcopy -- 28 | OBJCOPY_PARAMS = --strip-all -O binary 29 | 30 | UTILS_CONTAINER = andrerichter/raspi3-utils 31 | DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work 32 | QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img 33 | 34 | all: clean kernel8.img 35 | 36 | target/$(TARGET)/debug/kernel8: src/main.rs 37 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) 38 | cp $@ . 39 | 40 | target/$(TARGET)/release/kernel8: src/main.rs 41 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) --release 42 | cp $@ . 43 | 44 | ifeq ($(DEBUG),1) 45 | kernel8: target/$(TARGET)/debug/kernel8 46 | else 47 | kernel8: target/$(TARGET)/release/kernel8 48 | endif 49 | 50 | kernel8.img: kernel8 51 | $(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img 52 | 53 | qemu: 54 | $(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio 55 | 56 | clippy: 57 | RUSTFLAGS="-C panic=abort" xargo clippy 58 | 59 | clean: 60 | cargo clean 61 | rm -f kernel8 62 | -------------------------------------------------------------------------------- /0A_power/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "cortex-a" 3 | version = "1.0.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "kernel8" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 14 | "raspi3_boot 0.1.0", 15 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 16 | ] 17 | 18 | [[package]] 19 | name = "panic-abort" 20 | version = "0.2.0" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | 23 | [[package]] 24 | name = "r0" 25 | version = "0.2.2" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | 28 | [[package]] 29 | name = "raspi3_boot" 30 | version = "0.1.0" 31 | dependencies = [ 32 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 33 | "panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 34 | "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 35 | ] 36 | 37 | [[package]] 38 | name = "register" 39 | version = "0.1.1" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | dependencies = [ 42 | "tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 43 | ] 44 | 45 | [[package]] 46 | name = "tock-registers" 47 | version = "0.1.0" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | 50 | [metadata] 51 | "checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb" 52 | "checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e" 53 | "checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" 54 | "checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479" 55 | "checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9" 56 | -------------------------------------------------------------------------------- /08_random/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "cortex-a" 3 | version = "1.0.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "kernel8" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 14 | "raspi3_boot 0.1.0", 15 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 16 | ] 17 | 18 | [[package]] 19 | name = "panic-abort" 20 | version = "0.2.0" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | 23 | [[package]] 24 | name = "r0" 25 | version = "0.2.2" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | 28 | [[package]] 29 | name = "raspi3_boot" 30 | version = "0.1.0" 31 | dependencies = [ 32 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 33 | "panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 34 | "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 35 | ] 36 | 37 | [[package]] 38 | name = "register" 39 | version = "0.1.1" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | dependencies = [ 42 | "tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 43 | ] 44 | 45 | [[package]] 46 | name = "tock-registers" 47 | version = "0.1.0" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | 50 | [metadata] 51 | "checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb" 52 | "checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e" 53 | "checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" 54 | "checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479" 55 | "checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9" 56 | -------------------------------------------------------------------------------- /09_delays/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "cortex-a" 3 | version = "1.0.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "kernel8" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 14 | "raspi3_boot 0.1.0", 15 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 16 | ] 17 | 18 | [[package]] 19 | name = "panic-abort" 20 | version = "0.2.0" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | 23 | [[package]] 24 | name = "r0" 25 | version = "0.2.2" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | 28 | [[package]] 29 | name = "raspi3_boot" 30 | version = "0.1.0" 31 | dependencies = [ 32 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 33 | "panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 34 | "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 35 | ] 36 | 37 | [[package]] 38 | name = "register" 39 | version = "0.1.1" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | dependencies = [ 42 | "tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 43 | ] 44 | 45 | [[package]] 46 | name = "tock-registers" 47 | version = "0.1.0" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | 50 | [metadata] 51 | "checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb" 52 | "checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e" 53 | "checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" 54 | "checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479" 55 | "checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9" 56 | -------------------------------------------------------------------------------- /07_abstraction/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "cortex-a" 3 | version = "1.0.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "kernel8" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 14 | "raspi3_boot 0.1.0", 15 | "register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 16 | ] 17 | 18 | [[package]] 19 | name = "panic-abort" 20 | version = "0.2.0" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | 23 | [[package]] 24 | name = "r0" 25 | version = "0.2.2" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | 28 | [[package]] 29 | name = "raspi3_boot" 30 | version = "0.1.0" 31 | dependencies = [ 32 | "cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 33 | "panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 34 | "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 35 | ] 36 | 37 | [[package]] 38 | name = "register" 39 | version = "0.1.1" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | dependencies = [ 42 | "tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 43 | ] 44 | 45 | [[package]] 46 | name = "tock-registers" 47 | version = "0.1.0" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | 50 | [metadata] 51 | "checksum cortex-a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24174fbfe16d46844856c0f5e16ee15f7adbacfd87cb0148d34463dd34b54eeb" 52 | "checksum panic-abort 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc796c620f27056d4ffe7c558533fd67ae5af0fd8e919fbe38de803368af73e" 53 | "checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" 54 | "checksum register 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e985243ba7e1c336b62444ef2a10d7bd87cf41a222285ae3de605c859006479" 55 | "checksum tock-registers 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2acc33f980e23cee18d234a32d0637fbc1ea55e13ab04012fa857b899fa1b7a9" 56 | -------------------------------------------------------------------------------- /08_random/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #![no_std] 26 | #![no_main] 27 | 28 | extern crate cortex_a; 29 | 30 | #[macro_use] 31 | extern crate raspi3_boot; 32 | 33 | #[macro_use] 34 | extern crate register; 35 | 36 | const MMIO_BASE: u32 = 0x3F00_0000; 37 | 38 | mod gpio; 39 | mod mbox; 40 | mod rand; 41 | mod uart; 42 | 43 | entry!(kernel_entry); 44 | 45 | fn kernel_entry() -> ! { 46 | let mut mbox = mbox::Mbox::new(); 47 | let uart = uart::Uart::new(); 48 | 49 | // set up serial console 50 | if uart.init(&mut mbox).is_err() { 51 | loop { cortex_a::asm::wfe() }; // If UART fails, abort early 52 | } 53 | 54 | uart.getc(); // Press a key first before being greeted 55 | uart.puts("Hello Rustacean!\n"); 56 | 57 | // set up random number generator 58 | let rng = rand::Rng::new(); 59 | rng.init(); 60 | 61 | uart.puts("Press any key to generate random numbers.\n"); 62 | 63 | // echo everything back 64 | loop { 65 | uart.getc(); 66 | 67 | uart.puts("0x"); 68 | uart.hex(rng.rand(0, 4_294_967_295)); 69 | uart.puts("\n"); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /08_random/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # MIT License 3 | # 4 | # Copyright (c) 2018 Andre Richter 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | 25 | TARGET = aarch64-raspi3-none-elf 26 | 27 | OBJCOPY = cargo objcopy -- 28 | OBJCOPY_PARAMS = --strip-all -O binary 29 | 30 | UTILS_CONTAINER = andrerichter/raspi3-utils 31 | DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work 32 | DOCKER_TTY = --privileged -v /dev:/dev 33 | QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img 34 | RASPBOOT_CMD = raspbootcom /dev/ttyUSB0 kernel8.img 35 | 36 | all: clean kernel8.img 37 | 38 | target/$(TARGET)/debug/kernel8: src/main.rs 39 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) 40 | cp $@ . 41 | 42 | target/$(TARGET)/release/kernel8: src/main.rs 43 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) --release 44 | cp $@ . 45 | 46 | ifeq ($(DEBUG),1) 47 | kernel8: target/$(TARGET)/debug/kernel8 48 | else 49 | kernel8: target/$(TARGET)/release/kernel8 50 | endif 51 | 52 | kernel8.img: kernel8 53 | $(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img 54 | 55 | qemu: 56 | $(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio 57 | 58 | raspboot: 59 | $(DOCKER_CMD) $(DOCKER_TTY) $(UTILS_CONTAINER) $(RASPBOOT_CMD) 60 | 61 | clippy: 62 | RUSTFLAGS="-C panic=abort" xargo clippy 63 | 64 | clean: 65 | cargo clean 66 | rm -f kernel8 67 | -------------------------------------------------------------------------------- /09_delays/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # MIT License 3 | # 4 | # Copyright (c) 2018 Andre Richter 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | 25 | TARGET = aarch64-raspi3-none-elf 26 | 27 | OBJCOPY = cargo objcopy -- 28 | OBJCOPY_PARAMS = --strip-all -O binary 29 | 30 | UTILS_CONTAINER = andrerichter/raspi3-utils 31 | DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work 32 | DOCKER_TTY = --privileged -v /dev:/dev 33 | QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img 34 | RASPBOOT_CMD = raspbootcom /dev/ttyUSB0 kernel8.img 35 | 36 | all: clean kernel8.img 37 | 38 | target/$(TARGET)/debug/kernel8: src/main.rs 39 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) 40 | cp $@ . 41 | 42 | target/$(TARGET)/release/kernel8: src/main.rs 43 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) --release 44 | cp $@ . 45 | 46 | ifeq ($(DEBUG),1) 47 | kernel8: target/$(TARGET)/debug/kernel8 48 | else 49 | kernel8: target/$(TARGET)/release/kernel8 50 | endif 51 | 52 | kernel8.img: kernel8 53 | $(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img 54 | 55 | qemu: 56 | $(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio 57 | 58 | raspboot: 59 | $(DOCKER_CMD) $(DOCKER_TTY) $(UTILS_CONTAINER) $(RASPBOOT_CMD) 60 | 61 | clippy: 62 | RUSTFLAGS="-C panic=abort" xargo clippy 63 | 64 | clean: 65 | cargo clean 66 | rm -f kernel8 67 | -------------------------------------------------------------------------------- /0A_power/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # MIT License 3 | # 4 | # Copyright (c) 2018 Andre Richter 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | 25 | TARGET = aarch64-raspi3-none-elf 26 | 27 | OBJCOPY = cargo objcopy -- 28 | OBJCOPY_PARAMS = --strip-all -O binary 29 | 30 | UTILS_CONTAINER = andrerichter/raspi3-utils 31 | DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work 32 | DOCKER_TTY = --privileged -v /dev:/dev 33 | QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img 34 | RASPBOOT_CMD = raspbootcom /dev/ttyUSB0 kernel8.img 35 | 36 | all: clean kernel8.img 37 | 38 | target/$(TARGET)/debug/kernel8: src/main.rs 39 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) 40 | cp $@ . 41 | 42 | target/$(TARGET)/release/kernel8: src/main.rs 43 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) --release 44 | cp $@ . 45 | 46 | ifeq ($(DEBUG),1) 47 | kernel8: target/$(TARGET)/debug/kernel8 48 | else 49 | kernel8: target/$(TARGET)/release/kernel8 50 | endif 51 | 52 | kernel8.img: kernel8 53 | $(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img 54 | 55 | qemu: 56 | $(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio 57 | 58 | raspboot: 59 | $(DOCKER_CMD) $(DOCKER_TTY) $(UTILS_CONTAINER) $(RASPBOOT_CMD) 60 | 61 | clippy: 62 | RUSTFLAGS="-C panic=abort" xargo clippy 63 | 64 | clean: 65 | cargo clean 66 | rm -f kernel8 67 | -------------------------------------------------------------------------------- /07_abstraction/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # MIT License 3 | # 4 | # Copyright (c) 2018 Andre Richter 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | 25 | TARGET = aarch64-raspi3-none-elf 26 | 27 | OBJCOPY = cargo objcopy -- 28 | OBJCOPY_PARAMS = --strip-all -O binary 29 | 30 | UTILS_CONTAINER = andrerichter/raspi3-utils 31 | DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work 32 | DOCKER_TTY = --privileged -v /dev:/dev 33 | QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img 34 | RASPBOOT_CMD = raspbootcom /dev/ttyUSB0 kernel8.img 35 | 36 | all: clean kernel8.img 37 | 38 | target/$(TARGET)/debug/kernel8: src/main.rs 39 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) 40 | cp $@ . 41 | 42 | target/$(TARGET)/release/kernel8: src/main.rs 43 | RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET) --release 44 | cp $@ . 45 | 46 | ifeq ($(DEBUG),1) 47 | kernel8: target/$(TARGET)/debug/kernel8 48 | else 49 | kernel8: target/$(TARGET)/release/kernel8 50 | endif 51 | 52 | kernel8.img: kernel8 53 | $(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img 54 | 55 | qemu: 56 | $(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio 57 | 58 | raspboot: 59 | $(DOCKER_CMD) $(DOCKER_TTY) $(UTILS_CONTAINER) $(RASPBOOT_CMD) 60 | 61 | clippy: 62 | RUSTFLAGS="-C panic=abort" xargo clippy 63 | 64 | clean: 65 | cargo clean 66 | rm -f kernel8 67 | -------------------------------------------------------------------------------- /03_uart1/raspi3_boot/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Jorge Aparicio 5 | * Copyright (c) 2018 Andre Richter 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #![deny(missing_docs)] 27 | #![deny(warnings)] 28 | #![no_std] 29 | #![feature(global_asm)] 30 | 31 | //! Low-level boot of the Raspberry's processor 32 | 33 | extern crate cortex_a; 34 | extern crate panic_abort; 35 | extern crate r0; 36 | 37 | #[macro_export] 38 | macro_rules! entry { 39 | ($path:path) => { 40 | #[export_name = "main"] 41 | pub unsafe fn __main() -> ! { 42 | // type check the given path 43 | let f: fn() -> ! = $path; 44 | 45 | f() 46 | } 47 | }; 48 | } 49 | 50 | /// Reset function. 51 | /// 52 | /// Initializes the bss section before calling into the user's `main()`. 53 | #[no_mangle] 54 | pub unsafe extern "C" fn reset() -> ! { 55 | extern "C" { 56 | // Boundaries of the .bss section, provided by the linker script 57 | static mut __bss_start: u64; 58 | static mut __bss_end: u64; 59 | } 60 | 61 | // Zeroes the .bss section 62 | r0::zero_bss(&mut __bss_start, &mut __bss_end); 63 | 64 | extern "Rust" { 65 | fn main() -> !; 66 | } 67 | 68 | main(); 69 | } 70 | 71 | // Disable all cores except core 0, and then jump to reset() 72 | global_asm!(include_str!("boot_cores.S")); 73 | -------------------------------------------------------------------------------- /05_uart0/raspi3_boot/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Jorge Aparicio 5 | * Copyright (c) 2018 Andre Richter 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #![deny(missing_docs)] 27 | #![deny(warnings)] 28 | #![no_std] 29 | #![feature(global_asm)] 30 | 31 | //! Low-level boot of the Raspberry's processor 32 | 33 | extern crate cortex_a; 34 | extern crate panic_abort; 35 | extern crate r0; 36 | 37 | #[macro_export] 38 | macro_rules! entry { 39 | ($path:path) => { 40 | #[export_name = "main"] 41 | pub unsafe fn __main() -> ! { 42 | // type check the given path 43 | let f: fn() -> ! = $path; 44 | 45 | f() 46 | } 47 | }; 48 | } 49 | 50 | /// Reset function. 51 | /// 52 | /// Initializes the bss section before calling into the user's `main()`. 53 | #[no_mangle] 54 | pub unsafe extern "C" fn reset() -> ! { 55 | extern "C" { 56 | // Boundaries of the .bss section, provided by the linker script 57 | static mut __bss_start: u64; 58 | static mut __bss_end: u64; 59 | } 60 | 61 | // Zeroes the .bss section 62 | r0::zero_bss(&mut __bss_start, &mut __bss_end); 63 | 64 | extern "Rust" { 65 | fn main() -> !; 66 | } 67 | 68 | main(); 69 | } 70 | 71 | // Disable all cores except core 0, and then jump to reset() 72 | global_asm!(include_str!("boot_cores.S")); 73 | -------------------------------------------------------------------------------- /04_mailboxes/raspi3_boot/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Jorge Aparicio 5 | * Copyright (c) 2018 Andre Richter 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #![deny(missing_docs)] 27 | #![deny(warnings)] 28 | #![no_std] 29 | #![feature(global_asm)] 30 | 31 | //! Low-level boot of the Raspberry's processor 32 | 33 | extern crate cortex_a; 34 | extern crate panic_abort; 35 | extern crate r0; 36 | 37 | #[macro_export] 38 | macro_rules! entry { 39 | ($path:path) => { 40 | #[export_name = "main"] 41 | pub unsafe fn __main() -> ! { 42 | // type check the given path 43 | let f: fn() -> ! = $path; 44 | 45 | f() 46 | } 47 | }; 48 | } 49 | 50 | /// Reset function. 51 | /// 52 | /// Initializes the bss section before calling into the user's `main()`. 53 | #[no_mangle] 54 | pub unsafe extern "C" fn reset() -> ! { 55 | extern "C" { 56 | // Boundaries of the .bss section, provided by the linker script 57 | static mut __bss_start: u64; 58 | static mut __bss_end: u64; 59 | } 60 | 61 | // Zeroes the .bss section 62 | r0::zero_bss(&mut __bss_start, &mut __bss_end); 63 | 64 | extern "Rust" { 65 | fn main() -> !; 66 | } 67 | 68 | main(); 69 | } 70 | 71 | // Disable all cores except core 0, and then jump to reset() 72 | global_asm!(include_str!("boot_cores.S")); 73 | -------------------------------------------------------------------------------- /0A_power/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #![no_std] 26 | #![no_main] 27 | 28 | extern crate cortex_a; 29 | 30 | #[macro_use] 31 | extern crate raspi3_boot; 32 | 33 | #[macro_use] 34 | extern crate register; 35 | 36 | const MMIO_BASE: u32 = 0x3F00_0000; 37 | 38 | mod delays; 39 | mod gpio; 40 | mod mbox; 41 | mod power; 42 | mod uart; 43 | 44 | entry!(kernel_entry); 45 | 46 | fn kernel_entry() -> ! { 47 | let gpio = gpio::GPIO::new(); 48 | let mut mbox = mbox::Mbox::new(); 49 | let uart = uart::Uart::new(); 50 | let power = power::Power::new(); 51 | 52 | // set up serial console 53 | if uart.init(&mut mbox, &gpio).is_err() { 54 | loop { cortex_a::asm::wfe() }; // If UART fails, abort early 55 | } 56 | 57 | uart.getc(); // Press a key first before being greeted 58 | uart.puts("Hello Rustacean!\n\n"); 59 | 60 | loop { 61 | uart.puts("\n 1 - power off\n 2 - reset\nChoose one: "); 62 | let c = uart.getc(); 63 | uart.send(c); 64 | 65 | match c { 66 | '1' => { 67 | if power.off(&mut mbox, &gpio).is_err() { 68 | uart.puts("Mailbox error in Power::off()"); 69 | } 70 | } 71 | '2' => power.reset(), 72 | _ => {} 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /02_multicore_rust/raspi3_boot/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Jorge Aparicio 5 | * Copyright (c) 2018 Andre Richter 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #![deny(missing_docs)] 27 | #![deny(warnings)] 28 | #![no_std] 29 | #![feature(global_asm)] 30 | 31 | //! Low-level boot of the Raspberry's processor 32 | 33 | extern crate cortex_a; 34 | extern crate panic_abort; 35 | extern crate r0; 36 | 37 | #[macro_export] 38 | macro_rules! entry { 39 | ($path:path) => { 40 | #[export_name = "main"] 41 | pub unsafe fn __main() -> ! { 42 | // type check the given path 43 | let f: fn() -> ! = $path; 44 | 45 | f() 46 | } 47 | }; 48 | } 49 | 50 | /// Reset function. 51 | /// 52 | /// Initializes the bss section before calling into the user's `main()`. 53 | #[no_mangle] 54 | pub unsafe extern "C" fn reset() -> ! { 55 | extern "C" { 56 | // Boundaries of the .bss section, provided by the linker script 57 | static mut __bss_start: u64; 58 | static mut __bss_end: u64; 59 | } 60 | 61 | // Zeroes the .bss section 62 | r0::zero_bss(&mut __bss_start, &mut __bss_end); 63 | 64 | extern "Rust" { 65 | fn main() -> !; 66 | } 67 | 68 | main(); 69 | } 70 | 71 | // Disable all cores except core 0, and then jump to reset() 72 | global_asm!(include_str!("boot_cores.S")); 73 | -------------------------------------------------------------------------------- /09_delays/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #![no_std] 26 | #![no_main] 27 | 28 | extern crate cortex_a; 29 | 30 | #[macro_use] 31 | extern crate raspi3_boot; 32 | 33 | #[macro_use] 34 | extern crate register; 35 | 36 | const MMIO_BASE: u32 = 0x3F00_0000; 37 | 38 | mod delays; 39 | mod gpio; 40 | mod mbox; 41 | mod uart; 42 | 43 | entry!(kernel_entry); 44 | 45 | fn kernel_entry() -> ! { 46 | let mut mbox = mbox::Mbox::new(); 47 | let uart = uart::Uart::new(); 48 | 49 | // set up serial console 50 | if uart.init(&mut mbox).is_err() { 51 | loop { cortex_a::asm::wfe() }; // If UART fails, abort early 52 | } 53 | 54 | uart.getc(); // Press a key first before being greeted 55 | uart.puts("Hello Rustacean!\n"); 56 | 57 | uart.puts("Waiting 1_000_000 CPU cycles (ARM CPU): "); 58 | delays::wait_cycles(1_000_000); 59 | uart.puts("OK\n"); 60 | 61 | uart.puts("Waiting 1000 microsec (ARM CPU): "); 62 | delays::wait_msec(1000); 63 | uart.puts("OK\n"); 64 | 65 | let t = delays::SysTmr::new(); 66 | if t.get_system_timer() != 0 { 67 | uart.puts("Waiting 1000 microsec (BCM System Timer): "); 68 | t.wait_msec_st(1000); 69 | uart.puts("OK\n"); 70 | } 71 | 72 | uart.puts("Looping forever now!\n"); 73 | loop { 74 | delays::wait_msec(1000); 75 | uart.puts("Tick: 1s\n"); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /03_uart1/src/gpio.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use register::mmio::ReadWrite; 27 | 28 | // Descriptions taken from 29 | // https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf 30 | register_bitfields! { 31 | u32, 32 | 33 | /// GPIO Function Select 1 34 | GPFSEL1 [ 35 | /// Pin 15 36 | FSEL15 OFFSET(15) NUMBITS(3) [ 37 | Input = 0b000, 38 | Output = 0b001, 39 | RXD1 = 0b010 // Mini UART - Alternate function 5 40 | 41 | ], 42 | 43 | /// Pin 14 44 | FSEL14 OFFSET(12) NUMBITS(3) [ 45 | Input = 0b000, 46 | Output = 0b001, 47 | TXD1 = 0b010 // Mini UART - Alternate function 5 48 | ] 49 | ], 50 | 51 | /// GPIO Pull-up/down Clock Register 0 52 | GPPUDCLK0 [ 53 | /// Pin 15 54 | PUDCLK15 OFFSET(15) NUMBITS(1) [ 55 | NoEffect = 0, 56 | AssertClock = 1 57 | ], 58 | 59 | /// Pin 14 60 | PUDCLK14 OFFSET(14) NUMBITS(1) [ 61 | NoEffect = 0, 62 | AssertClock = 1 63 | ] 64 | ] 65 | } 66 | 67 | 68 | pub const GPFSEL1: *const ReadWrite = 69 | (MMIO_BASE + 0x0020_0004) as *const ReadWrite; 70 | 71 | pub const GPPUD: *const ReadWrite = (MMIO_BASE + 0x0020_0094) as *const ReadWrite; 72 | 73 | pub const GPPUDCLK0: *const ReadWrite = 74 | (MMIO_BASE + 0x0020_0098) as *const ReadWrite; 75 | -------------------------------------------------------------------------------- /04_mailboxes/src/gpio.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use register::mmio::ReadWrite; 27 | 28 | // Descriptions taken from 29 | // https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf 30 | register_bitfields! { 31 | u32, 32 | 33 | /// GPIO Function Select 1 34 | GPFSEL1 [ 35 | /// Pin 15 36 | FSEL15 OFFSET(15) NUMBITS(3) [ 37 | Input = 0b000, 38 | Output = 0b001, 39 | RXD1 = 0b010 // Mini UART - Alternate function 5 40 | 41 | ], 42 | 43 | /// Pin 14 44 | FSEL14 OFFSET(12) NUMBITS(3) [ 45 | Input = 0b000, 46 | Output = 0b001, 47 | TXD1 = 0b010 // Mini UART - Alternate function 5 48 | ] 49 | ], 50 | 51 | /// GPIO Pull-up/down Clock Register 0 52 | GPPUDCLK0 [ 53 | /// Pin 15 54 | PUDCLK15 OFFSET(15) NUMBITS(1) [ 55 | NoEffect = 0, 56 | AssertClock = 1 57 | ], 58 | 59 | /// Pin 14 60 | PUDCLK14 OFFSET(14) NUMBITS(1) [ 61 | NoEffect = 0, 62 | AssertClock = 1 63 | ] 64 | ] 65 | } 66 | 67 | 68 | pub const GPFSEL1: *const ReadWrite = 69 | (MMIO_BASE + 0x0020_0004) as *const ReadWrite; 70 | 71 | pub const GPPUD: *const ReadWrite = (MMIO_BASE + 0x0020_0094) as *const ReadWrite; 72 | 73 | pub const GPPUDCLK0: *const ReadWrite = 74 | (MMIO_BASE + 0x0020_0098) as *const ReadWrite; 75 | -------------------------------------------------------------------------------- /06_raspbootin64/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #![no_std] 26 | #![no_main] 27 | #![feature(asm)] 28 | 29 | #[macro_use] 30 | extern crate raspi3_boot; 31 | 32 | #[macro_use] 33 | extern crate register; 34 | 35 | const MMIO_BASE: u32 = 0x3F00_0000; 36 | 37 | mod gpio; 38 | mod mbox; 39 | mod uart; 40 | 41 | entry!(kernel_entry); 42 | 43 | fn kernel_entry() -> ! { 44 | let mut mbox = mbox::Mbox::new(); 45 | let uart = uart::Uart::new(); 46 | 47 | // set up serial console 48 | if uart.init(&mut mbox).is_err() { 49 | unsafe { asm!("wfe" :::: "volatile") }; // If UART fails, abort early 50 | } 51 | 52 | // Say hello 53 | for c in "RBIN64\r\n".chars() { 54 | uart.send(c); 55 | } 56 | 57 | // Notify raspbootcom to send the kernel 58 | uart.send(3 as char); 59 | uart.send(3 as char); 60 | uart.send(3 as char); 61 | 62 | // Read the kernel's size 63 | let mut size: u32 = u32::from(uart.getc()); 64 | size |= u32::from(uart.getc()) << 8; 65 | size |= u32::from(uart.getc()) << 16; 66 | size |= u32::from(uart.getc()) << 24; 67 | 68 | // For now, blindly trust it's not too big 69 | uart.send('O'); 70 | uart.send('K'); 71 | 72 | let kernel_addr: *mut u8 = 0x80_000 as *mut u8; 73 | unsafe { 74 | // Read the kernel byte by byte 75 | for i in 0..size { 76 | *kernel_addr.offset(i as isize) = uart.getc(); 77 | } 78 | } 79 | 80 | // Use black magic to get a function pointer to 0x80_000 81 | let kernel: extern "C" fn() -> ! = unsafe { core::mem::transmute(kernel_addr as *const ()) }; 82 | 83 | // Jump to loaded kernel and never return! 84 | kernel() 85 | } 86 | -------------------------------------------------------------------------------- /05_uart0/src/gpio.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use register::mmio::ReadWrite; 27 | 28 | // Descriptions taken from 29 | // https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf 30 | register_bitfields! { 31 | u32, 32 | 33 | /// GPIO Function Select 1 34 | GPFSEL1 [ 35 | /// Pin 15 36 | FSEL15 OFFSET(15) NUMBITS(3) [ 37 | Input = 0b000, 38 | Output = 0b001, 39 | RXD0 = 0b100, // UART0 - Alternate function 0 40 | RXD1 = 0b010 // Mini UART - Alternate function 5 41 | 42 | ], 43 | 44 | /// Pin 14 45 | FSEL14 OFFSET(12) NUMBITS(3) [ 46 | Input = 0b000, 47 | Output = 0b001, 48 | TXD0 = 0b100, // UART0 - Alternate function 0 49 | TXD1 = 0b010 // Mini UART - Alternate function 5 50 | ] 51 | ], 52 | 53 | /// GPIO Pull-up/down Clock Register 0 54 | GPPUDCLK0 [ 55 | /// Pin 15 56 | PUDCLK15 OFFSET(15) NUMBITS(1) [ 57 | NoEffect = 0, 58 | AssertClock = 1 59 | ], 60 | 61 | /// Pin 14 62 | PUDCLK14 OFFSET(14) NUMBITS(1) [ 63 | NoEffect = 0, 64 | AssertClock = 1 65 | ] 66 | ] 67 | } 68 | 69 | 70 | pub const GPFSEL1: *const ReadWrite = 71 | (MMIO_BASE + 0x0020_0004) as *const ReadWrite; 72 | 73 | pub const GPPUD: *const ReadWrite = (MMIO_BASE + 0x0020_0094) as *const ReadWrite; 74 | 75 | pub const GPPUDCLK0: *const ReadWrite = 76 | (MMIO_BASE + 0x0020_0098) as *const ReadWrite; 77 | -------------------------------------------------------------------------------- /08_random/src/gpio.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use register::mmio::ReadWrite; 27 | 28 | // Descriptions taken from 29 | // https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf 30 | register_bitfields! { 31 | u32, 32 | 33 | /// GPIO Function Select 1 34 | GPFSEL1 [ 35 | /// Pin 15 36 | FSEL15 OFFSET(15) NUMBITS(3) [ 37 | Input = 0b000, 38 | Output = 0b001, 39 | RXD0 = 0b100, // UART0 - Alternate function 0 40 | RXD1 = 0b010 // Mini UART - Alternate function 5 41 | 42 | ], 43 | 44 | /// Pin 14 45 | FSEL14 OFFSET(12) NUMBITS(3) [ 46 | Input = 0b000, 47 | Output = 0b001, 48 | TXD0 = 0b100, // UART0 - Alternate function 0 49 | TXD1 = 0b010 // Mini UART - Alternate function 5 50 | ] 51 | ], 52 | 53 | /// GPIO Pull-up/down Clock Register 0 54 | GPPUDCLK0 [ 55 | /// Pin 15 56 | PUDCLK15 OFFSET(15) NUMBITS(1) [ 57 | NoEffect = 0, 58 | AssertClock = 1 59 | ], 60 | 61 | /// Pin 14 62 | PUDCLK14 OFFSET(14) NUMBITS(1) [ 63 | NoEffect = 0, 64 | AssertClock = 1 65 | ] 66 | ] 67 | } 68 | 69 | 70 | pub const GPFSEL1: *const ReadWrite = 71 | (MMIO_BASE + 0x0020_0004) as *const ReadWrite; 72 | 73 | pub const GPPUD: *const ReadWrite = (MMIO_BASE + 0x0020_0094) as *const ReadWrite; 74 | 75 | pub const GPPUDCLK0: *const ReadWrite = 76 | (MMIO_BASE + 0x0020_0098) as *const ReadWrite; 77 | -------------------------------------------------------------------------------- /09_delays/src/gpio.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use register::mmio::ReadWrite; 27 | 28 | // Descriptions taken from 29 | // https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf 30 | register_bitfields! { 31 | u32, 32 | 33 | /// GPIO Function Select 1 34 | GPFSEL1 [ 35 | /// Pin 15 36 | FSEL15 OFFSET(15) NUMBITS(3) [ 37 | Input = 0b000, 38 | Output = 0b001, 39 | RXD0 = 0b100, // UART0 - Alternate function 0 40 | RXD1 = 0b010 // Mini UART - Alternate function 5 41 | 42 | ], 43 | 44 | /// Pin 14 45 | FSEL14 OFFSET(12) NUMBITS(3) [ 46 | Input = 0b000, 47 | Output = 0b001, 48 | TXD0 = 0b100, // UART0 - Alternate function 0 49 | TXD1 = 0b010 // Mini UART - Alternate function 5 50 | ] 51 | ], 52 | 53 | /// GPIO Pull-up/down Clock Register 0 54 | GPPUDCLK0 [ 55 | /// Pin 15 56 | PUDCLK15 OFFSET(15) NUMBITS(1) [ 57 | NoEffect = 0, 58 | AssertClock = 1 59 | ], 60 | 61 | /// Pin 14 62 | PUDCLK14 OFFSET(14) NUMBITS(1) [ 63 | NoEffect = 0, 64 | AssertClock = 1 65 | ] 66 | ] 67 | } 68 | 69 | 70 | pub const GPFSEL1: *const ReadWrite = 71 | (MMIO_BASE + 0x0020_0004) as *const ReadWrite; 72 | 73 | pub const GPPUD: *const ReadWrite = (MMIO_BASE + 0x0020_0094) as *const ReadWrite; 74 | 75 | pub const GPPUDCLK0: *const ReadWrite = 76 | (MMIO_BASE + 0x0020_0098) as *const ReadWrite; 77 | -------------------------------------------------------------------------------- /06_raspbootin64/src/gpio.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use register::mmio::ReadWrite; 27 | 28 | // Descriptions taken from 29 | // https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf 30 | register_bitfields! { 31 | u32, 32 | 33 | /// GPIO Function Select 1 34 | GPFSEL1 [ 35 | /// Pin 15 36 | FSEL15 OFFSET(15) NUMBITS(3) [ 37 | Input = 0b000, 38 | Output = 0b001, 39 | RXD0 = 0b100, // UART0 - Alternate function 0 40 | RXD1 = 0b010 // Mini UART - Alternate function 5 41 | 42 | ], 43 | 44 | /// Pin 14 45 | FSEL14 OFFSET(12) NUMBITS(3) [ 46 | Input = 0b000, 47 | Output = 0b001, 48 | TXD0 = 0b100, // UART0 - Alternate function 0 49 | TXD1 = 0b010 // Mini UART - Alternate function 5 50 | ] 51 | ], 52 | 53 | /// GPIO Pull-up/down Clock Register 0 54 | GPPUDCLK0 [ 55 | /// Pin 15 56 | PUDCLK15 OFFSET(15) NUMBITS(1) [ 57 | NoEffect = 0, 58 | AssertClock = 1 59 | ], 60 | 61 | /// Pin 14 62 | PUDCLK14 OFFSET(14) NUMBITS(1) [ 63 | NoEffect = 0, 64 | AssertClock = 1 65 | ] 66 | ] 67 | } 68 | 69 | 70 | pub const GPFSEL1: *const ReadWrite = 71 | (MMIO_BASE + 0x0020_0004) as *const ReadWrite; 72 | 73 | pub const GPPUD: *const ReadWrite = (MMIO_BASE + 0x0020_0094) as *const ReadWrite; 74 | 75 | pub const GPPUDCLK0: *const ReadWrite = 76 | (MMIO_BASE + 0x0020_0098) as *const ReadWrite; 77 | -------------------------------------------------------------------------------- /07_abstraction/src/gpio.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use register::mmio::ReadWrite; 27 | 28 | // Descriptions taken from 29 | // https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf 30 | register_bitfields! { 31 | u32, 32 | 33 | /// GPIO Function Select 1 34 | GPFSEL1 [ 35 | /// Pin 15 36 | FSEL15 OFFSET(15) NUMBITS(3) [ 37 | Input = 0b000, 38 | Output = 0b001, 39 | RXD0 = 0b100, // UART0 - Alternate function 0 40 | RXD1 = 0b010 // Mini UART - Alternate function 5 41 | 42 | ], 43 | 44 | /// Pin 14 45 | FSEL14 OFFSET(12) NUMBITS(3) [ 46 | Input = 0b000, 47 | Output = 0b001, 48 | TXD0 = 0b100, // UART0 - Alternate function 0 49 | TXD1 = 0b010 // Mini UART - Alternate function 5 50 | ] 51 | ], 52 | 53 | /// GPIO Pull-up/down Clock Register 0 54 | GPPUDCLK0 [ 55 | /// Pin 15 56 | PUDCLK15 OFFSET(15) NUMBITS(1) [ 57 | NoEffect = 0, 58 | AssertClock = 1 59 | ], 60 | 61 | /// Pin 14 62 | PUDCLK14 OFFSET(14) NUMBITS(1) [ 63 | NoEffect = 0, 64 | AssertClock = 1 65 | ] 66 | ] 67 | } 68 | 69 | 70 | pub const GPFSEL1: *const ReadWrite = 71 | (MMIO_BASE + 0x0020_0004) as *const ReadWrite; 72 | 73 | pub const GPPUD: *const ReadWrite = (MMIO_BASE + 0x0020_0094) as *const ReadWrite; 74 | 75 | pub const GPPUDCLK0: *const ReadWrite = 76 | (MMIO_BASE + 0x0020_0098) as *const ReadWrite; 77 | -------------------------------------------------------------------------------- /08_random/raspi3_boot/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Jorge Aparicio 5 | * Copyright (c) 2018 Andre Richter 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #![deny(missing_docs)] 27 | #![deny(warnings)] 28 | #![no_std] 29 | 30 | //! Low-level boot of the Raspberry's processor 31 | 32 | extern crate cortex_a; 33 | extern crate panic_abort; 34 | extern crate r0; 35 | 36 | #[macro_export] 37 | macro_rules! entry { 38 | ($path:path) => { 39 | #[export_name = "main"] 40 | pub unsafe fn __main() -> ! { 41 | // type check the given path 42 | let f: fn() -> ! = $path; 43 | 44 | f() 45 | } 46 | } 47 | } 48 | 49 | /// Reset function. 50 | /// 51 | /// Initializes the bss section before calling into the user's `main()`. 52 | unsafe fn reset() -> ! { 53 | extern "C" { 54 | // Boundaries of the .bss section, provided by the linker script 55 | static mut __bss_start: u64; 56 | static mut __bss_end: u64; 57 | } 58 | 59 | // Zeroes the .bss section 60 | r0::zero_bss(&mut __bss_start, &mut __bss_end); 61 | 62 | extern "Rust" { 63 | fn main() -> !; 64 | } 65 | 66 | main(); 67 | } 68 | 69 | /// Entrypoint of the processor. 70 | /// 71 | /// Parks all cores except core0, and then jumps to the internal 72 | /// `reset()` function. 73 | #[link_section = ".text.boot"] 74 | #[no_mangle] 75 | pub unsafe extern "C" fn _boot_cores() -> ! { 76 | use cortex_a::{asm, regs::mpidr_el1::*, regs::sp::*}; 77 | 78 | const CORE_MASK: u64 = 0x3; 79 | const STACK_START: u64 = 0x80_0000; 80 | 81 | match MPIDR_EL1.get() & CORE_MASK { 82 | 0 => { 83 | SP.set(STACK_START); 84 | reset() 85 | } 86 | _ => loop { 87 | // if not core0, infinitely wait for events 88 | asm::wfe(); 89 | }, 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /09_delays/raspi3_boot/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Jorge Aparicio 5 | * Copyright (c) 2018 Andre Richter 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #![deny(missing_docs)] 27 | #![deny(warnings)] 28 | #![no_std] 29 | 30 | //! Low-level boot of the Raspberry's processor 31 | 32 | extern crate cortex_a; 33 | extern crate panic_abort; 34 | extern crate r0; 35 | 36 | #[macro_export] 37 | macro_rules! entry { 38 | ($path:path) => { 39 | #[export_name = "main"] 40 | pub unsafe fn __main() -> ! { 41 | // type check the given path 42 | let f: fn() -> ! = $path; 43 | 44 | f() 45 | } 46 | } 47 | } 48 | 49 | /// Reset function. 50 | /// 51 | /// Initializes the bss section before calling into the user's `main()`. 52 | unsafe fn reset() -> ! { 53 | extern "C" { 54 | // Boundaries of the .bss section, provided by the linker script 55 | static mut __bss_start: u64; 56 | static mut __bss_end: u64; 57 | } 58 | 59 | // Zeroes the .bss section 60 | r0::zero_bss(&mut __bss_start, &mut __bss_end); 61 | 62 | extern "Rust" { 63 | fn main() -> !; 64 | } 65 | 66 | main(); 67 | } 68 | 69 | /// Entrypoint of the processor. 70 | /// 71 | /// Parks all cores except core0, and then jumps to the internal 72 | /// `reset()` function. 73 | #[link_section = ".text.boot"] 74 | #[no_mangle] 75 | pub unsafe extern "C" fn _boot_cores() -> ! { 76 | use cortex_a::{asm, regs::mpidr_el1::*, regs::sp::*}; 77 | 78 | const CORE_MASK: u64 = 0x3; 79 | const STACK_START: u64 = 0x80_0000; 80 | 81 | match MPIDR_EL1.get() & CORE_MASK { 82 | 0 => { 83 | SP.set(STACK_START); 84 | reset() 85 | } 86 | _ => loop { 87 | // if not core0, infinitely wait for events 88 | asm::wfe(); 89 | }, 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /0A_power/raspi3_boot/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Jorge Aparicio 5 | * Copyright (c) 2018 Andre Richter 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #![deny(missing_docs)] 27 | #![deny(warnings)] 28 | #![no_std] 29 | 30 | //! Low-level boot of the Raspberry's processor 31 | 32 | extern crate cortex_a; 33 | extern crate panic_abort; 34 | extern crate r0; 35 | 36 | #[macro_export] 37 | macro_rules! entry { 38 | ($path:path) => { 39 | #[export_name = "main"] 40 | pub unsafe fn __main() -> ! { 41 | // type check the given path 42 | let f: fn() -> ! = $path; 43 | 44 | f() 45 | } 46 | } 47 | } 48 | 49 | /// Reset function. 50 | /// 51 | /// Initializes the bss section before calling into the user's `main()`. 52 | unsafe fn reset() -> ! { 53 | extern "C" { 54 | // Boundaries of the .bss section, provided by the linker script 55 | static mut __bss_start: u64; 56 | static mut __bss_end: u64; 57 | } 58 | 59 | // Zeroes the .bss section 60 | r0::zero_bss(&mut __bss_start, &mut __bss_end); 61 | 62 | extern "Rust" { 63 | fn main() -> !; 64 | } 65 | 66 | main(); 67 | } 68 | 69 | /// Entrypoint of the processor. 70 | /// 71 | /// Parks all cores except core0, and then jumps to the internal 72 | /// `reset()` function. 73 | #[link_section = ".text.boot"] 74 | #[no_mangle] 75 | pub unsafe extern "C" fn _boot_cores() -> ! { 76 | use cortex_a::{asm, regs::mpidr_el1::*, regs::sp::*}; 77 | 78 | const CORE_MASK: u64 = 0x3; 79 | const STACK_START: u64 = 0x80_0000; 80 | 81 | match MPIDR_EL1.get() & CORE_MASK { 82 | 0 => { 83 | SP.set(STACK_START); 84 | reset() 85 | } 86 | _ => loop { 87 | // if not core0, infinitely wait for events 88 | asm::wfe(); 89 | }, 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /07_abstraction/raspi3_boot/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Jorge Aparicio 5 | * Copyright (c) 2018 Andre Richter 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #![deny(missing_docs)] 27 | #![deny(warnings)] 28 | #![no_std] 29 | 30 | //! Low-level boot of the Raspberry's processor 31 | 32 | extern crate cortex_a; 33 | extern crate panic_abort; 34 | extern crate r0; 35 | 36 | #[macro_export] 37 | macro_rules! entry { 38 | ($path:path) => { 39 | #[export_name = "main"] 40 | pub unsafe fn __main() -> ! { 41 | // type check the given path 42 | let f: fn() -> ! = $path; 43 | 44 | f() 45 | } 46 | } 47 | } 48 | 49 | /// Reset function. 50 | /// 51 | /// Initializes the bss section before calling into the user's `main()`. 52 | unsafe fn reset() -> ! { 53 | extern "C" { 54 | // Boundaries of the .bss section, provided by the linker script 55 | static mut __bss_start: u64; 56 | static mut __bss_end: u64; 57 | } 58 | 59 | // Zeroes the .bss section 60 | r0::zero_bss(&mut __bss_start, &mut __bss_end); 61 | 62 | extern "Rust" { 63 | fn main() -> !; 64 | } 65 | 66 | main(); 67 | } 68 | 69 | /// Entrypoint of the processor. 70 | /// 71 | /// Parks all cores except core0, and then jumps to the internal 72 | /// `reset()` function. 73 | #[link_section = ".text.boot"] 74 | #[no_mangle] 75 | pub unsafe extern "C" fn _boot_cores() -> ! { 76 | use cortex_a::{asm, regs::mpidr_el1::*, regs::sp::*}; 77 | 78 | const CORE_MASK: u64 = 0x3; 79 | const STACK_START: u64 = 0x80_0000; 80 | 81 | match MPIDR_EL1.get() & CORE_MASK { 82 | 0 => { 83 | SP.set(STACK_START); 84 | reset() 85 | } 86 | _ => loop { 87 | // if not core0, infinitely wait for events 88 | asm::wfe(); 89 | }, 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /04_mailboxes/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #![no_std] 26 | #![no_main] 27 | #![feature(asm)] 28 | 29 | #[macro_use] 30 | extern crate raspi3_boot; 31 | 32 | #[macro_use] 33 | extern crate register; 34 | 35 | const MMIO_BASE: u32 = 0x3F00_0000; 36 | 37 | mod gpio; 38 | mod mbox; 39 | mod uart; 40 | 41 | use core::sync::atomic::{compiler_fence, Ordering}; 42 | 43 | entry!(kernel_entry); 44 | 45 | fn kernel_entry() -> ! { 46 | let mut mbox = mbox::Mbox::new(); 47 | let uart = uart::MiniUart::new(); 48 | 49 | // set up serial console 50 | uart.init(); 51 | 52 | // get the board's unique serial number with a mailbox call 53 | mbox.buffer[0] = 8 * 4; // length of the message 54 | mbox.buffer[1] = mbox::REQUEST; // this is a request message 55 | mbox.buffer[2] = mbox::tag::GETSERIAL; // get serial number command 56 | mbox.buffer[3] = 8; // buffer size 57 | mbox.buffer[4] = 8; 58 | mbox.buffer[5] = 0; // clear output buffer 59 | mbox.buffer[6] = 0; 60 | mbox.buffer[7] = mbox::tag::LAST; 61 | 62 | // Insert a compiler fence that ensures that all stores to the 63 | // mbox buffer are finished before the GPU is signaled (which is 64 | // done by a store operation as well). 65 | compiler_fence(Ordering::Release); 66 | 67 | // send the message to the GPU and receive answer 68 | let serial_avail = match mbox.call(mbox::channel::PROP) { 69 | Err(_) => false, 70 | Ok(()) => true, 71 | }; 72 | 73 | uart.getc(); // Press a key first before being greeted 74 | uart.puts("Hello Rustacean!\n"); 75 | 76 | if serial_avail { 77 | uart.puts("My serial number is: "); 78 | uart.hex(mbox.buffer[6]); 79 | uart.hex(mbox.buffer[5]); 80 | uart.puts("\n"); 81 | } else { 82 | uart.puts("Unable to query serial!\n"); 83 | } 84 | 85 | // echo everything back 86 | loop { 87 | uart.send(uart.getc()); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /05_uart0/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #![no_std] 26 | #![no_main] 27 | #![feature(asm)] 28 | 29 | #[macro_use] 30 | extern crate raspi3_boot; 31 | 32 | #[macro_use] 33 | extern crate register; 34 | 35 | const MMIO_BASE: u32 = 0x3F00_0000; 36 | 37 | mod gpio; 38 | mod mbox; 39 | mod uart; 40 | 41 | use core::sync::atomic::{compiler_fence, Ordering}; 42 | 43 | entry!(kernel_entry); 44 | 45 | fn kernel_entry() -> ! { 46 | let mut mbox = mbox::Mbox::new(); 47 | let uart = uart::Uart::new(); 48 | 49 | // set up serial console 50 | if uart.init(&mut mbox).is_err() { 51 | unsafe { asm!("wfe" :::: "volatile") }; // If UART fails, abort early 52 | } 53 | 54 | // get the board's unique serial number with a mailbox call 55 | mbox.buffer[0] = 8 * 4; // length of the message 56 | mbox.buffer[1] = mbox::REQUEST; // this is a request message 57 | mbox.buffer[2] = mbox::tag::GETSERIAL; // get serial number command 58 | mbox.buffer[3] = 8; // buffer size 59 | mbox.buffer[4] = 8; 60 | mbox.buffer[5] = 0; // clear output buffer 61 | mbox.buffer[6] = 0; 62 | mbox.buffer[7] = mbox::tag::LAST; 63 | 64 | // Insert a compiler fence that ensures that all stores to the 65 | // mbox buffer are finished before the GPU is signaled (which is 66 | // done by a store operation as well). 67 | compiler_fence(Ordering::Release); 68 | 69 | // send the message to the GPU and receive answer 70 | let serial_avail = match mbox.call(mbox::channel::PROP) { 71 | Err(_) => false, 72 | Ok(()) => true, 73 | }; 74 | 75 | uart.getc(); // Press a key first before being greeted 76 | uart.puts("Hello Rustacean!\n"); 77 | 78 | if serial_avail { 79 | uart.puts("My serial number is: "); 80 | uart.hex(mbox.buffer[6]); 81 | uart.hex(mbox.buffer[5]); 82 | uart.puts("\n"); 83 | } else { 84 | uart.puts("Unable to query serial!\n"); 85 | } 86 | 87 | // echo everything back 88 | loop { 89 | uart.send(uart.getc()); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /07_abstraction/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #![no_std] 26 | #![no_main] 27 | 28 | extern crate cortex_a; 29 | 30 | #[macro_use] 31 | extern crate raspi3_boot; 32 | 33 | #[macro_use] 34 | extern crate register; 35 | 36 | const MMIO_BASE: u32 = 0x3F00_0000; 37 | 38 | mod gpio; 39 | mod mbox; 40 | mod uart; 41 | 42 | use core::sync::atomic::{compiler_fence, Ordering}; 43 | 44 | entry!(kernel_entry); 45 | 46 | fn kernel_entry() -> ! { 47 | let mut mbox = mbox::Mbox::new(); 48 | let uart = uart::Uart::new(); 49 | 50 | // set up serial console 51 | if uart.init(&mut mbox).is_err() { 52 | loop { cortex_a::asm::wfe() }; // If UART fails, abort early 53 | } 54 | 55 | // get the board's unique serial number with a mailbox call 56 | mbox.buffer[0] = 8 * 4; // length of the message 57 | mbox.buffer[1] = mbox::REQUEST; // this is a request message 58 | mbox.buffer[2] = mbox::tag::GETSERIAL; // get serial number command 59 | mbox.buffer[3] = 8; // buffer size 60 | mbox.buffer[4] = 8; 61 | mbox.buffer[5] = 0; // clear output buffer 62 | mbox.buffer[6] = 0; 63 | mbox.buffer[7] = mbox::tag::LAST; 64 | 65 | // Insert a compiler fence that ensures that all stores to the 66 | // mbox buffer are finished before the GPU is signaled (which is 67 | // done by a store operation as well). 68 | compiler_fence(Ordering::Release); 69 | 70 | // send the message to the GPU and receive answer 71 | let serial_avail = match mbox.call(mbox::channel::PROP) { 72 | Err(_) => false, 73 | Ok(()) => true, 74 | }; 75 | 76 | uart.getc(); // Press a key first before being greeted 77 | uart.puts("Hello Rustacean!\n"); 78 | 79 | if serial_avail { 80 | uart.puts("My serial number is: "); 81 | uart.hex(mbox.buffer[6]); 82 | uart.hex(mbox.buffer[5]); 83 | uart.puts("\n"); 84 | } else { 85 | uart.puts("Unable to query serial!\n"); 86 | } 87 | 88 | // echo everything back 89 | loop { 90 | uart.send(uart.getc()); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /08_random/src/rand.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use core::ops; 27 | use cortex_a::asm; 28 | use register::mmio::*; 29 | 30 | register_bitfields! { 31 | u32, 32 | 33 | CTRL [ 34 | ENABLE OFFSET(0) NUMBITS(1) [ 35 | True = 1, 36 | False = 0 37 | ] 38 | ], 39 | 40 | INT_MASK [ 41 | INT_OFF OFFSET(0) NUMBITS(1) [ 42 | True = 1, 43 | False = 0 44 | ] 45 | ] 46 | } 47 | 48 | const RNG_BASE: u32 = MMIO_BASE + 0x104_000; 49 | const RNG_WARMUP_COUNT: u32 = 0x40_000; 50 | 51 | #[allow(non_snake_case)] 52 | #[repr(C)] 53 | pub struct RegisterBlock { 54 | CTRL: ReadWrite, // 0x00 55 | STATUS: ReadWrite, // 0x04 56 | DATA: ReadOnly, // 0x08 57 | __reserved_0: u32, // 0x0c 58 | INT_MASK: ReadWrite, // 0x10 59 | } 60 | 61 | /// Public interface to the RNG 62 | pub struct Rng; 63 | 64 | impl ops::Deref for Rng { 65 | type Target = RegisterBlock; 66 | 67 | fn deref(&self) -> &Self::Target { 68 | unsafe { &*Self::ptr() } 69 | } 70 | } 71 | 72 | impl Rng { 73 | pub fn new() -> Rng { 74 | Rng 75 | } 76 | 77 | /// Returns a pointer to the register block 78 | fn ptr() -> *const RegisterBlock { 79 | RNG_BASE as *const _ 80 | } 81 | 82 | /// Initialize the RNG 83 | pub fn init(&self) { 84 | // Disable interrupts 85 | self.INT_MASK.modify(INT_MASK::INT_OFF::True); 86 | 87 | // Set warm-up count and enable 88 | self.STATUS.set(RNG_WARMUP_COUNT); 89 | self.CTRL.modify(CTRL::ENABLE::True); 90 | } 91 | 92 | /// Return a random number between [min..max] 93 | pub fn rand(&self, min: u32, max: u32) -> u32 { 94 | // wait for gaining some entropy 95 | loop { 96 | if (self.STATUS.get() >> 24) != 0 { 97 | break; 98 | } 99 | 100 | asm::nop(); 101 | } 102 | 103 | let r = self.DATA.get(); 104 | 105 | r % (max - min) + min 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /01_bareminimum/README.md: -------------------------------------------------------------------------------- 1 | # Tutorial 01 - Bare Minimum 2 | 3 | Okay, we're not going to do much here, just test our toolchain. The resulting 4 | kernel8.img should boot on the Raspberry Pi 3, and stop all CPU cores in an 5 | infinite waiting loop. You can check that by running 6 | 7 | ```bash 8 | $ make qemu 9 | ... some output removed for clearity: ... 10 | ---------------- 11 | IN: 12 | 0x00080000: d503205f wfe 13 | 0x00080004: 17ffffff b #0x80000 14 | ``` 15 | 16 | ## Crate setup 17 | 18 | In this tutorial, we are compiling a kernel that is in the end only executing a 19 | single assembly instruction which we program with an assembly file. 20 | 21 | However, since we want to use the toolchain that is delivered with `rustup` as 22 | much as possible, we are already setting up a Rust crate. This allows us to use 23 | `rustc` and LLVM's `lld.ld` linker to process our assembly file. 24 | 25 | ## main.rs 26 | 27 | We define the crate to not use the standard library (`#![no_std]`), indicate 28 | that it does not have a main function via `#![no_main]`, and also define a stub 29 | for the `panic_fmt()` handler, which is a requirement for `no_std` crates. We do 30 | this by pulling in the [panic-abort][pa] crate. 31 | 32 | [pa]: https://crates.io/crates/panic-abort 33 | 34 | In summary, we (mis)use `main.rs` as a wrapper to process our assembly file via 35 | `rustc`. The assembly file iself is included with the [global_asm!()][gasm] 36 | macro. 37 | 38 | [gasm]: https://doc.rust-lang.org/unstable-book/language-features/global-asm.html 39 | 40 | ## boot_cores.S 41 | 42 | When the control is passed to kernel8.img, the environment is not ready yet for 43 | Rust. Therefore we must implement a small preamble in assembly, no Rust for now. 44 | 45 | All we do is executing [wfe][wfe], an instruction that puts the CPU cores to 46 | sleep until an asynchronous event occurs. If that happens, we jump right back to 47 | `wfe` again. 48 | 49 | [wfe]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0360e/CHDBGCFH.html 50 | 51 | Note that the CPU has 4 cores. All of them will execute the same infinite loop 52 | for now. 53 | 54 | ## aarch64-raspi3-none-elf.json 55 | 56 | This is our custom target definition of the RPi3 for [Xargo][xargo]. It also 57 | includes a directive to use the `link.ld` linker script. 58 | 59 | ```json 60 | "pre-link-args": { 61 | "ld.lld": [ 62 | "--script=link.ld" 63 | ] 64 | }, 65 | ``` 66 | 67 | [xargo]: https://github.com/japaric/xargo 68 | 69 | ## Makefile 70 | 71 | Our Makefile has a few useful targets: 72 | - `kernel8` compiles the crate either in release or debug mode. For the latter, 73 | add `DEBUG=1` before invoking make, e.g. `DEBUG=1 make` 74 | - `kernel8.img` uses our cross-toolchain's `objcopy` in the docker container to 75 | generate our kernel binary. Citing the [binutils documentation][butils]: 76 | - "_When objcopy generates a raw binary file, it will essentially produce a 77 | memory dump of the contents of the input object file. All symbols and 78 | relocation information will be discarded. The memory dump will start at 79 | the load address of the lowest section copied into the output file._" 80 | - `qemu` loads our kernel into an emulated RPi3, and shows as output the 81 | assembler blocks that are executed. This happens in another docker container. 82 | 83 | [butils]: https://sourceware.org/binutils/docs/binutils/objcopy.html 84 | 85 | ## Linker script `link.ld` 86 | 87 | We just set the base address where our kernel8.img will be loaded, and we put 88 | the only section we have there, which is `.text.boot`. Important note, for 89 | AArch64 the load address is **0x80_000**, and not **0x80_00** as with AArch32. 90 | -------------------------------------------------------------------------------- /04_mailboxes/README.md: -------------------------------------------------------------------------------- 1 | # Tutorial 04 - Mailboxes 2 | 3 | Before we could go on with UART0, we need mailboxes. So in this tutorial we 4 | introduce the mailbox interface. We'll use it to query the board's serial 5 | number and print that out on UART1. 6 | 7 | NOTE: qemu does not redirect UART1 to terminal by default, only UART0! 8 | 9 | ## uart.rs 10 | 11 | `MiniUart::hex(&self, d: u32)` prints out a binary value in hexadecimal format. 12 | 13 | ## mbox.rs 14 | 15 | The mailbox interface. First we fill up the message in the `mbox.buffer` array, 16 | then we call `Mbox::call(&mut self, channel: u32)` to pass it to the GPU, 17 | specifying the mailbox channel. In this example we have used the [property 18 | channel], which requires the message to be formatted as: 19 | 20 | [property channel]: (https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface) 21 | 22 | ``` 23 | 0. size of the message in bytes, (x+1)*4 24 | 1. mbox::REQUEST magic value, indicates request message 25 | 2-x. tags 26 | x+1. mbox::tag::LAST magic value, indicates no more tags 27 | ``` 28 | 29 | Where each tag looks like: 30 | 31 | ``` 32 | n+0. tag identifier 33 | n+1. value buffer size in bytes 34 | n+2. must be zero 35 | n+3. optional value buffer 36 | ``` 37 | 38 | ### Synchronization 39 | 40 | When signaling the GPU about a new mailbox message, we need to take care that 41 | mailbox buffer setup has really finished. Both setting up mailbox contents and 42 | signaling the GPU is done with store operations to independent memory locations 43 | (RAM and MMIO). Since compilers are free to reorder instructions without 44 | control-flow or data-dependencies for optimization purposes, we need to take 45 | care that signaling the GPU really takes place _after_ all of the contents have 46 | been written to the mailbox buffer. 47 | 48 | One way to do this would be to define the whole mailbox buffer as `volatile`, as 49 | well as the location that we write to to signal the GPU. The compiler is not 50 | allowed to reorder memory operations tagged with the `volatile` keyword with 51 | each other. But this is not needed here. We don't care if the compiler optimizes 52 | the buffer setup code as long as signaling the GPU takes place afterwards. 53 | 54 | Therefore, we prevent premature signaling by inserting an explicit [compiler 55 | fence] after the buffer preparation code. Since we signal the CPU by calling 56 | another function, the fence would only be effective if that function was a) 57 | inlined and b) the inlined instructions then reordered with buffer setup 58 | code. Otherwise the compiler has to assume that the called function has 59 | dependencies on previous memory operations and not reorder here. Although there 60 | is little chance that the reordering scenario happens, I'll leave the fence 61 | there nonetheless for academic purposes :-) 62 | 63 | Please note that such reordering might also be done by CPUs that feature 64 | [out-of-order execution]. Lucky us, although the Rasperry Pi 3 features 65 | `ARMv8.0-A` CPU cores, the `Cortex-A53` variant is used, [which does not support 66 | this feature]. Otherwise, a [fence] that additionally [emits corresponding CPU 67 | instructions] to prevent this behavior would be needed. 68 | 69 | [compiler fence]: https://doc.rust-lang.org/beta/core/sync/atomic/fn.compiler_fence.html 70 | [out-of-order execution]: https://en.wikipedia.org/wiki/Out-of-order_execution 71 | [which does not support this feature]: https://en.wikipedia.org/wiki/Comparison_of_ARMv8-A_cores 72 | [fence]: https://doc.rust-lang.org/std/sync/atomic/fn.fence.html 73 | [emits corresponding CPU instructions]: https://developer.arm.com/products/architecture/a-profile/docs/100941/latest/barriers 74 | 75 | ## main.rs 76 | 77 | We query the board's serial number and then we display it on the serial console. 78 | -------------------------------------------------------------------------------- /06_raspbootin64/README.md: -------------------------------------------------------------------------------- 1 | # Tutorial 06 - Raspbootin64 2 | 3 | We are now at a point where we have a running serial connection, but for each 4 | new feature we want to try, we still have to write and exchange the SD card 5 | every time. 6 | 7 | As this tends to get very annoying and also to avoid potential SD card damage, 8 | we create a kernel8.img that will load the real kernel8.img over serial. 9 | 10 | This tutorial is a rewrite of the well known serial boot loader 11 | [raspbootin][bootin] in 64-bit. We only provide one part of the loader, the 12 | kernel receiver, which runs on the RPi. For the other part, the sender, which 13 | runs on your PC, we will rely on the original [raspbootcom][bootcom] utility. 14 | 15 | [bootin]:(https://github.com/mrvn/raspbootin) 16 | [bootcom]:(https://github.com/mrvn/raspbootin/blob/master/raspbootcom/raspbootcom.cc) 17 | 18 | For convenience, it is already packaged in our `raspi3-utils` docker 19 | container. So if you are running a Linux host, it will be as easy as calling 20 | another Makefile target. It will be included starting with the next tutorial, 21 | `07_abstraction`. You can invoke it with 22 | 23 | ```bash 24 | make raspboot 25 | ``` 26 | 27 | If you want to use it with earlier versions of this tutorial, here is a bash 28 | command to invoke it: 29 | 30 | ```bash 31 | docker run -it --rm \ 32 | --privileged -v /dev/:/dev/ \ 33 | -v $PWD:/work -w /work \ 34 | raspi3-utils \ 35 | raspbootcom /dev/ttyUSB0 kernel8.img 36 | ``` 37 | 38 | In any case, if your USB device is enumerated differently, adapt accordingly. 39 | 40 | If you want to send kernels from a Windows machine, I suggest to take a look at 41 | John Cronin's rewrite, [raspbootin-server][w32] which can be compiled for the 42 | Win32 API. Even more, [@milanvidakovic](https://github.com/milanvidakovic) was 43 | so kind to share a [Java version][java] of the kernel sender with you. 44 | 45 | [w32]:(https://github.com/jncronin/rpi-boot/blob/master/raspbootin-server.c) 46 | [java]:(https://github.com/milanvidakovic/Raspbootin64Client) 47 | 48 | ## Chain Loading 49 | 50 | In order to load the new kernel to the same address, we have to move ourself out 51 | of the way. It's called `chain loading`: One code loads the next code to the 52 | same position in memory, therefore the latter thinks it was loaded by the 53 | firmware. To implement that, we use a different linking address this time, and 54 | since the GPU loads us to `0x80_000` regardless, we have to copy our code to 55 | that link address. When we're done, the memory at `0x80_000` is free to use. You 56 | can check that with: 57 | 58 | ```sh 59 | $ cargo nm -- kernel8 | grep reset 60 | 000000000007ffc0 T reset 61 | ``` 62 | 63 | We also should minimize the size of the loader, since it will be overwritten by 64 | the newly loaded code anyway. By removing `Uart::puts()` and other functions, 65 | we've managed to shrink the loader's size to 1024 bytes. 66 | 67 | ## boot_cores.S 68 | 69 | First, we have to save the arguments in registers passed by the 70 | firmware. Second, we added a loop to relocate our code to the address it should 71 | have been loaded to. And last, since rustc generates RIP-relative jumps, we must 72 | adjust the branch instruction to jump to the relocated Rust code. 73 | 74 | ## Linker and Boot Code 75 | 76 | We use a different linking address this time. We calculate our code's size to 77 | know how many bytes we have to copy. 78 | 79 | Additionally, we can remove the `bss section` entirely, since our loader does 80 | not use any static variables. 81 | 82 | ## main.rs 83 | 84 | We print 'RBIN64', receive the new kernel over serial and save it at the memory 85 | address where the start.elf would have been loaded it. When finished, we restore 86 | the arguments and jump to the new kernel using an absolute address. 87 | -------------------------------------------------------------------------------- /02_multicore_rust/README.md: -------------------------------------------------------------------------------- 1 | # Tutorial 02 - Multicore Rust 2 | 3 | Now let's try something more complex, shall we? By complex I mean stopping the 4 | CPU cores just like in the first tutorial, but this time stop one of them from 5 | **Rust**! 6 | 7 | ## Boot code 8 | 9 | In order to conveniently incorporate Rust code, we are restructuring our crate a 10 | bit. 11 | 12 | We reuse a lot of steps that are explained in great detail in [The 13 | Embedonomicon][nom], so please take your time and read up on it. Afterwards, you 14 | can compare to the files in this crate and see what we actually kept to get our 15 | Raspberry Pi 3 tutorial going. Here's a short summary of the new structure of 16 | the crate: 17 | 18 | - `raspi3_boot/`: The extern crate containing boot code as presented in the 19 | Embedonomicon. 20 | - In a small deviation to the Embedonomicon, `lib.rs` also includes 21 | `boot_cores.S` from the previous tutorial, still with the 22 | [global_asm!][gasm] macro. 23 | - Therefore, `boot_cores.S` has been moved into `raspi3_boot/src/`. 24 | - `src`: Source code of our actual Rust code, currently only containing 25 | `main.rs` executing an endless loop. 26 | 27 | [nom]: https://rust-embedded.github.io/embedonomicon/ 28 | [gasm]: https://doc.rust-lang.org/unstable-book/language-features/global-asm.html 29 | 30 | ### Changes to `boot_cores.S` 31 | 32 | In contrast to the previous tutorial, we are now [distinguishing the 33 | cores][dist]. To do so, we read the [mpidr_el1][mpdir] system register. If it is 34 | not zero, we enter the former infinite waiting loop, aka stopping the respective 35 | CPU core. 36 | 37 | If the result of the read from `mpidr_el1` is zero, which means we are 38 | executing on core0, we set up the stack for that core, and afterwards call the 39 | Rust `reset()` function of the boot code in `raspi3_boot/src/lib.rs`. In case 40 | the Rust code returns (which it never should), we also jump to the same 41 | infinite loop the other CPU cores are running. 42 | 43 | The Rust `reset()`, in turn, will then zero-out the `bss section` (the next 44 | section explains what that is) and finally call our `main()` function from 45 | `main.rs`. 46 | 47 | [dist]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/CFHCIDCH.html 48 | [mpdir]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500g/BABHBJCI.html 49 | 50 | ## Changes to `link.ld` 51 | 52 | Since we are using a high-level language now in the form of Rust, we also take 53 | precautions to have eventual space reserved in memory for the [bss 54 | segment][bss], which is needed in case zero-initialized static variables are 55 | allocated in the Rust code. 56 | 57 | [bss]: https://en.wikipedia.org/wiki/.bss 58 | 59 | Therefore, we added the `bss` segment to the linker script and export its 60 | properties via `__bss_start` and `__bss_size`, which will be picked up and 61 | zeroed out by the boot code in `raspi3_boot/src/lib.rs`. 62 | 63 | Additionally, there is a [data segment][data] now. 64 | 65 | [data]: https://en.wikipedia.org/wiki/Data_segment 66 | 67 | Finally, we need to take care that we still start the text segment with the 68 | assembly code and not the newly added Rust code. This is taken care of by 69 | placing the `.text.boot` section before all other new text sections 70 | `KEEP(*(.text.boot)) *(.text .text.* ...`. 71 | 72 | This way, the assembly stays at the `0x80_000` address, which is the entry point 73 | of the RPi3 CPU. 74 | 75 | ## Changes to `Makefile` 76 | 77 | We've added one more target: 78 | - [clippy] is Rust's linter, and can give you useful advise to improve your 79 | code. Invoke with `make clippy`. 80 | 81 | [clippy]: https://github.com/rust-lang-nursery/rust-clippy 82 | 83 | From now on, we can use the same Makefile for every tutorial, regardless of the 84 | number of Rust sources, and we won't discuss it any further. 85 | 86 | ## main.rs 87 | 88 | Finally, our first Rust code. Just an empty loop, but still! :-) 89 | -------------------------------------------------------------------------------- /09_delays/src/delays.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use core::ops; 27 | use cortex_a::{ 28 | asm, 29 | regs::{cntfrq_el0::*, cntp_ctl_el0::*, cntp_tval_el0::*}, 30 | }; 31 | use register::mmio::*; 32 | 33 | const DELAY_BASE: u32 = MMIO_BASE + 0x3004; 34 | 35 | /* 36 | * 37 | * Using the RPi3 SoC's system timer peripheral 38 | * 39 | */ 40 | #[allow(non_snake_case)] 41 | #[repr(C)] 42 | pub struct RegisterBlock { 43 | SYSTMR_LO: ReadOnly, // 0x00 44 | SYSTMR_HI: ReadOnly, // 0x04 45 | } 46 | 47 | /// Public interface to the BCM System Timer 48 | pub struct SysTmr; 49 | 50 | impl ops::Deref for SysTmr { 51 | type Target = RegisterBlock; 52 | 53 | fn deref(&self) -> &Self::Target { 54 | unsafe { &*Self::ptr() } 55 | } 56 | } 57 | 58 | impl SysTmr { 59 | pub fn new() -> SysTmr { 60 | SysTmr 61 | } 62 | 63 | /// Returns a pointer to the register block 64 | fn ptr() -> *const RegisterBlock { 65 | DELAY_BASE as *const _ 66 | } 67 | 68 | /// Get System Timer's counter 69 | pub fn get_system_timer(&self) -> u64 { 70 | // Since it is MMIO, we must emit two separate 32 bit reads 71 | let mut hi = self.SYSTMR_HI.get(); 72 | let mut lo = self.SYSTMR_LO.get(); 73 | 74 | // We have to repeat if high word changed during read. This 75 | // will emit a clippy warning that needs be ignored, or you 76 | // lose an MMIO read. 77 | if hi != self.SYSTMR_HI.get() { 78 | hi = self.SYSTMR_HI.get(); 79 | lo = self.SYSTMR_LO.get(); 80 | } 81 | 82 | // Compose long int value 83 | (u64::from(hi) << 32) | u64::from(lo) 84 | } 85 | 86 | /// Wait N microsec (with BCM System Timer) 87 | pub fn wait_msec_st(&self, n: u64) { 88 | let t = self.get_system_timer(); 89 | 90 | // We must check if it's non-zero, because qemu does not 91 | // emulate system timer, and returning constant zero would 92 | // mean infinite loop 93 | if t > 0 { 94 | loop { 95 | if self.get_system_timer() < (t + n) { 96 | break; 97 | } 98 | } 99 | } 100 | } 101 | } 102 | 103 | /* 104 | * 105 | * Using the CPU's counter registers 106 | * 107 | */ 108 | /// Wait N microsec (ARM CPU only) 109 | pub fn wait_msec(n: u32) { 110 | // Get the counter frequency 111 | let frq = CNTFRQ_EL0.get(); 112 | 113 | // Calculate number of ticks 114 | let tval = (frq as u32 / 1000) * n; 115 | 116 | // Set the compare value register 117 | CNTP_TVAL_EL0.set(tval); 118 | 119 | // Kick off the counting // Disable timer interrupt 120 | CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET); 121 | 122 | loop { 123 | // ISTATUS will be one when cval ticks have passed. Continuously check it. 124 | if CNTP_CTL_EL0.is_set(CNTP_CTL_EL0::ISTATUS) { 125 | break; 126 | } 127 | } 128 | 129 | // Disable counting again 130 | CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::CLEAR); 131 | } 132 | 133 | /* 134 | * 135 | * Using the CPU's cycles 136 | * 137 | */ 138 | /// Wait N CPU cycles (ARM CPU only) 139 | pub fn wait_cycles(cyc: u32) { 140 | for _ in 0..cyc { 141 | asm::nop(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /0A_power/src/delays.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use core::ops; 27 | use cortex_a::{ 28 | asm, 29 | regs::{cntfrq_el0::*, cntp_ctl_el0::*, cntp_tval_el0::*}, 30 | }; 31 | use register::mmio::*; 32 | 33 | const DELAY_BASE: u32 = MMIO_BASE + 0x3004; 34 | 35 | /* 36 | * 37 | * Using the RPi3 SoC's system timer peripheral 38 | * 39 | */ 40 | #[allow(non_snake_case)] 41 | #[repr(C)] 42 | pub struct RegisterBlock { 43 | SYSTMR_LO: ReadOnly, // 0x00 44 | SYSTMR_HI: ReadOnly, // 0x04 45 | } 46 | 47 | /// Public interface to the BCM System Timer 48 | pub struct SysTmr; 49 | 50 | impl ops::Deref for SysTmr { 51 | type Target = RegisterBlock; 52 | 53 | fn deref(&self) -> &Self::Target { 54 | unsafe { &*Self::ptr() } 55 | } 56 | } 57 | 58 | impl SysTmr { 59 | pub fn new() -> SysTmr { 60 | SysTmr 61 | } 62 | 63 | /// Returns a pointer to the register block 64 | fn ptr() -> *const RegisterBlock { 65 | DELAY_BASE as *const _ 66 | } 67 | 68 | /// Get System Timer's counter 69 | pub fn get_system_timer(&self) -> u64 { 70 | // Since it is MMIO, we must emit two separate 32 bit reads 71 | let mut hi = self.SYSTMR_HI.get(); 72 | let mut lo = self.SYSTMR_LO.get(); 73 | 74 | // We have to repeat if high word changed during read. This 75 | // will emit a clippy warning that needs be ignored, or you 76 | // lose an MMIO read. 77 | if hi != self.SYSTMR_HI.get() { 78 | hi = self.SYSTMR_HI.get(); 79 | lo = self.SYSTMR_LO.get(); 80 | } 81 | 82 | // Compose long int value 83 | (u64::from(hi) << 32) | u64::from(lo) 84 | } 85 | 86 | /// Wait N microsec (with BCM System Timer) 87 | pub fn wait_msec_st(&self, n: u64) { 88 | let t = self.get_system_timer(); 89 | 90 | // We must check if it's non-zero, because qemu does not 91 | // emulate system timer, and returning constant zero would 92 | // mean infinite loop 93 | if t > 0 { 94 | loop { 95 | if self.get_system_timer() < (t + n) { 96 | break; 97 | } 98 | } 99 | } 100 | } 101 | } 102 | 103 | /* 104 | * 105 | * Using the CPU's counter registers 106 | * 107 | */ 108 | /// Wait N microsec (ARM CPU only) 109 | pub fn wait_msec(n: u32) { 110 | // Get the counter frequency 111 | let frq = CNTFRQ_EL0.get(); 112 | 113 | // Calculate number of ticks 114 | let tval = (frq as u32 / 1000) * n; 115 | 116 | // Set the compare value register 117 | CNTP_TVAL_EL0.set(tval); 118 | 119 | // Kick off the counting // Disable timer interrupt 120 | CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET); 121 | 122 | loop { 123 | // ISTATUS will be one when cval ticks have passed. Continuously check it. 124 | if CNTP_CTL_EL0.is_set(CNTP_CTL_EL0::ISTATUS) { 125 | break; 126 | } 127 | } 128 | 129 | // Disable counting again 130 | CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::CLEAR); 131 | } 132 | 133 | /* 134 | * 135 | * Using the CPU's cycles 136 | * 137 | */ 138 | /// Wait N CPU cycles (ARM CPU only) 139 | pub fn wait_cycles(cyc: u32) { 140 | for _ in 0..cyc { 141 | asm::nop(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /0A_power/src/gpio.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use core::ops; 27 | use register::mmio::ReadWrite; 28 | 29 | // Descriptions taken from 30 | // https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf 31 | register_bitfields! { 32 | u32, 33 | 34 | /// GPIO Function Select 1 35 | GPFSEL1 [ 36 | /// Pin 15 37 | FSEL15 OFFSET(15) NUMBITS(3) [ 38 | Input = 0b000, 39 | Output = 0b001, 40 | RXD0 = 0b100, // UART0 - Alternate function 0 41 | RXD1 = 0b010 // Mini UART - Alternate function 5 42 | 43 | ], 44 | 45 | /// Pin 14 46 | FSEL14 OFFSET(12) NUMBITS(3) [ 47 | Input = 0b000, 48 | Output = 0b001, 49 | TXD0 = 0b100, // UART0 - Alternate function 0 50 | TXD1 = 0b010 // Mini UART - Alternate function 5 51 | ] 52 | ], 53 | 54 | /// GPIO Pull-up/down Clock Register 0 55 | GPPUDCLK0 [ 56 | /// Pin 15 57 | PUDCLK15 OFFSET(15) NUMBITS(1) [ 58 | NoEffect = 0, 59 | AssertClock = 1 60 | ], 61 | 62 | /// Pin 14 63 | PUDCLK14 OFFSET(14) NUMBITS(1) [ 64 | NoEffect = 0, 65 | AssertClock = 1 66 | ] 67 | ] 68 | } 69 | 70 | const GPIO_BASE: u32 = MMIO_BASE + 0x200_000; 71 | 72 | #[allow(non_snake_case)] 73 | #[repr(C)] 74 | pub struct RegisterBlock { 75 | pub GPFSEL0: ReadWrite, // 0x00 76 | pub GPFSEL1: ReadWrite, // 0x04 77 | pub GPFSEL2: ReadWrite, // 0x08 78 | pub GPFSEL3: ReadWrite, // 0x0C 79 | pub GPFSEL4: ReadWrite, // 0x10 80 | pub GPFSEL5: ReadWrite, // 0x14 81 | __reserved_0: u32, // 0x18 82 | GPSET0: ReadWrite, // 0x1C 83 | GPSET1: ReadWrite, // 0x20 84 | __reserved_1: u32, // 85 | GPCLR0: ReadWrite, // 0x28 86 | __reserved_2: [u32; 2], // 87 | GPLEV0: ReadWrite, // 0x34 88 | GPLEV1: ReadWrite, // 0x38 89 | __reserved_3: u32, // 90 | GPEDS0: ReadWrite, // 0x40 91 | GPEDS1: ReadWrite, // 0x44 92 | __reserved_4: [u32; 7], // 93 | GPHEN0: ReadWrite, // 0x64 94 | GPHEN1: ReadWrite, // 0x68 95 | __reserved_5: [u32; 10], // 96 | pub GPPUD: ReadWrite, // 0x94 97 | pub GPPUDCLK0: ReadWrite, // 0x98 98 | pub GPPUDCLK1: ReadWrite, // 0x9C 99 | } 100 | 101 | /// Public interface to the GPIO MMIO area 102 | pub struct GPIO; 103 | 104 | impl ops::Deref for GPIO { 105 | type Target = RegisterBlock; 106 | 107 | fn deref(&self) -> &Self::Target { 108 | unsafe { &*Self::ptr() } 109 | } 110 | } 111 | 112 | impl GPIO { 113 | pub fn new() -> GPIO { 114 | GPIO 115 | } 116 | 117 | /// Returns a pointer to the register block 118 | fn ptr() -> *const RegisterBlock { 119 | GPIO_BASE as *const _ 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /04_mailboxes/src/mbox.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use core::ops; 27 | use register::mmio::{ReadOnly, WriteOnly}; 28 | 29 | register_bitfields! { 30 | u32, 31 | 32 | STATUS [ 33 | FULL OFFSET(31) NUMBITS(1) [], 34 | EMPTY OFFSET(30) NUMBITS(1) [] 35 | ] 36 | } 37 | 38 | const VIDEOCORE_MBOX: u32 = MMIO_BASE + 0xB880; 39 | 40 | #[allow(non_snake_case)] 41 | #[repr(C)] 42 | pub struct RegisterBlock { 43 | READ: ReadOnly, // 0x00 44 | __reserved_0: [u32; 5], // 0x04 45 | STATUS: ReadOnly, // 0x18 46 | __reserved_1: u32, // 0x1C 47 | WRITE: WriteOnly, // 0x20 48 | } 49 | 50 | // Custom errors 51 | pub enum MboxError { 52 | ResponseError, 53 | UnknownError, 54 | } 55 | pub type Result = ::core::result::Result; 56 | 57 | // Channels 58 | pub mod channel { 59 | pub const PROP: u32 = 8; 60 | } 61 | 62 | // Tags 63 | pub mod tag { 64 | pub const GETSERIAL: u32 = 0x10004; 65 | pub const LAST: u32 = 0; 66 | } 67 | 68 | // Responses 69 | mod response { 70 | pub const SUCCESS: u32 = 0x8000_0000; 71 | pub const ERROR: u32 = 0x8000_0001; // error parsing request buffer (partial response) 72 | } 73 | 74 | pub const REQUEST: u32 = 0; 75 | 76 | // Public interface to the mailbox 77 | #[repr(C)] 78 | #[repr(align(16))] 79 | pub struct Mbox { 80 | // The address for buffer needs to be 16-byte aligned so that the 81 | // Videcore can handle it properly. 82 | pub buffer: [u32; 36], 83 | } 84 | 85 | /// Deref to RegisterBlock 86 | /// 87 | /// Allows writing 88 | /// ``` 89 | /// self.STATUS.read() 90 | /// ``` 91 | /// instead of something along the lines of 92 | /// ``` 93 | /// unsafe { (*Mbox::ptr()).STATUS.read() } 94 | /// ``` 95 | impl ops::Deref for Mbox { 96 | type Target = RegisterBlock; 97 | 98 | fn deref(&self) -> &Self::Target { 99 | unsafe { &*Self::ptr() } 100 | } 101 | } 102 | 103 | impl Mbox { 104 | pub fn new() -> Mbox { 105 | Mbox { buffer: [0; 36] } 106 | } 107 | 108 | /// Returns a pointer to the register block 109 | fn ptr() -> *const RegisterBlock { 110 | VIDEOCORE_MBOX as *const _ 111 | } 112 | 113 | /// Make a mailbox call. Returns Err(MboxError) on failure, Ok(()) success 114 | pub fn call(&self, channel: u32) -> Result<()> { 115 | // wait until we can write to the mailbox 116 | loop { 117 | if !self.STATUS.is_set(STATUS::FULL) { 118 | break; 119 | } 120 | 121 | unsafe { asm!("nop" :::: "volatile") }; 122 | } 123 | 124 | let buf_ptr = self.buffer.as_ptr() as u32; 125 | 126 | // write the address of our message to the mailbox with channel identifier 127 | self.WRITE.set((buf_ptr & !0xF) | (channel & 0xF)); 128 | 129 | // now wait for the response 130 | loop { 131 | // is there a response? 132 | loop { 133 | if !self.STATUS.is_set(STATUS::EMPTY) { 134 | break; 135 | } 136 | 137 | unsafe { asm!("nop" :::: "volatile") }; 138 | } 139 | 140 | let resp: u32 = self.READ.get(); 141 | 142 | // is it a response to our message? 143 | if ((resp & 0xF) == channel) && ((resp & !0xF) == buf_ptr) { 144 | // is it a valid successful response? 145 | return match self.buffer[1] { 146 | response::SUCCESS => Ok(()), 147 | response::ERROR => Err(MboxError::ResponseError), 148 | _ => Err(MboxError::UnknownError), 149 | }; 150 | } 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /08_random/src/mbox.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use core::ops; 27 | use cortex_a::asm; 28 | use register::mmio::{ReadOnly, WriteOnly}; 29 | 30 | register_bitfields! { 31 | u32, 32 | 33 | STATUS [ 34 | FULL OFFSET(31) NUMBITS(1) [], 35 | EMPTY OFFSET(30) NUMBITS(1) [] 36 | ] 37 | } 38 | 39 | const VIDEOCORE_MBOX: u32 = MMIO_BASE + 0xB880; 40 | 41 | #[allow(non_snake_case)] 42 | #[repr(C)] 43 | pub struct RegisterBlock { 44 | READ: ReadOnly, // 0x00 45 | __reserved_0: [u32; 5], // 0x04 46 | STATUS: ReadOnly, // 0x18 47 | __reserved_1: u32, // 0x1C 48 | WRITE: WriteOnly, // 0x20 49 | } 50 | 51 | // Custom errors 52 | pub enum MboxError { 53 | ResponseError, 54 | UnknownError, 55 | } 56 | pub type Result = ::core::result::Result; 57 | 58 | // Channels 59 | pub mod channel { 60 | pub const PROP: u32 = 8; 61 | } 62 | 63 | // Tags 64 | pub mod tag { 65 | pub const SETCLKRATE: u32 = 0x38002; 66 | pub const LAST: u32 = 0; 67 | } 68 | 69 | // Clocks 70 | pub mod clock { 71 | pub const UART: u32 = 0x0_0000_0002; 72 | } 73 | 74 | // Responses 75 | mod response { 76 | pub const SUCCESS: u32 = 0x8000_0000; 77 | pub const ERROR: u32 = 0x8000_0001; // error parsing request buffer (partial response) 78 | } 79 | 80 | pub const REQUEST: u32 = 0; 81 | 82 | // Public interface to the mailbox 83 | #[repr(C)] 84 | #[repr(align(16))] 85 | pub struct Mbox { 86 | // The address for buffer needs to be 16-byte aligned so that the 87 | // Videcore can handle it properly. 88 | pub buffer: [u32; 36], 89 | } 90 | 91 | /// Deref to RegisterBlock 92 | /// 93 | /// Allows writing 94 | /// ``` 95 | /// self.STATUS.read() 96 | /// ``` 97 | /// instead of something along the lines of 98 | /// ``` 99 | /// unsafe { (*Mbox::ptr()).STATUS.read() } 100 | /// ``` 101 | impl ops::Deref for Mbox { 102 | type Target = RegisterBlock; 103 | 104 | fn deref(&self) -> &Self::Target { 105 | unsafe { &*Self::ptr() } 106 | } 107 | } 108 | 109 | impl Mbox { 110 | pub fn new() -> Mbox { 111 | Mbox { buffer: [0; 36] } 112 | } 113 | 114 | /// Returns a pointer to the register block 115 | fn ptr() -> *const RegisterBlock { 116 | VIDEOCORE_MBOX as *const _ 117 | } 118 | 119 | /// Make a mailbox call. Returns Err(MboxError) on failure, Ok(()) success 120 | pub fn call(&self, channel: u32) -> Result<()> { 121 | // wait until we can write to the mailbox 122 | loop { 123 | if !self.STATUS.is_set(STATUS::FULL) { 124 | break; 125 | } 126 | 127 | asm::nop(); 128 | } 129 | 130 | let buf_ptr = self.buffer.as_ptr() as u32; 131 | 132 | // write the address of our message to the mailbox with channel identifier 133 | self.WRITE.set((buf_ptr & !0xF) | (channel & 0xF)); 134 | 135 | // now wait for the response 136 | loop { 137 | // is there a response? 138 | loop { 139 | if !self.STATUS.is_set(STATUS::EMPTY) { 140 | break; 141 | } 142 | 143 | asm::nop(); 144 | } 145 | 146 | let resp: u32 = self.READ.get(); 147 | 148 | // is it a response to our message? 149 | if ((resp & 0xF) == channel) && ((resp & !0xF) == buf_ptr) { 150 | // is it a valid successful response? 151 | return match self.buffer[1] { 152 | response::SUCCESS => Ok(()), 153 | response::ERROR => Err(MboxError::ResponseError), 154 | _ => Err(MboxError::UnknownError), 155 | }; 156 | } 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /09_delays/src/mbox.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use core::ops; 27 | use cortex_a::asm; 28 | use register::mmio::{ReadOnly, WriteOnly}; 29 | 30 | register_bitfields! { 31 | u32, 32 | 33 | STATUS [ 34 | FULL OFFSET(31) NUMBITS(1) [], 35 | EMPTY OFFSET(30) NUMBITS(1) [] 36 | ] 37 | } 38 | 39 | const VIDEOCORE_MBOX: u32 = MMIO_BASE + 0xB880; 40 | 41 | #[allow(non_snake_case)] 42 | #[repr(C)] 43 | pub struct RegisterBlock { 44 | READ: ReadOnly, // 0x00 45 | __reserved_0: [u32; 5], // 0x04 46 | STATUS: ReadOnly, // 0x18 47 | __reserved_1: u32, // 0x1C 48 | WRITE: WriteOnly, // 0x20 49 | } 50 | 51 | // Custom errors 52 | pub enum MboxError { 53 | ResponseError, 54 | UnknownError, 55 | } 56 | pub type Result = ::core::result::Result; 57 | 58 | // Channels 59 | pub mod channel { 60 | pub const PROP: u32 = 8; 61 | } 62 | 63 | // Tags 64 | pub mod tag { 65 | pub const SETCLKRATE: u32 = 0x38002; 66 | pub const LAST: u32 = 0; 67 | } 68 | 69 | // Clocks 70 | pub mod clock { 71 | pub const UART: u32 = 0x0_0000_0002; 72 | } 73 | 74 | // Responses 75 | mod response { 76 | pub const SUCCESS: u32 = 0x8000_0000; 77 | pub const ERROR: u32 = 0x8000_0001; // error parsing request buffer (partial response) 78 | } 79 | 80 | pub const REQUEST: u32 = 0; 81 | 82 | // Public interface to the mailbox 83 | #[repr(C)] 84 | #[repr(align(16))] 85 | pub struct Mbox { 86 | // The address for buffer needs to be 16-byte aligned so that the 87 | // Videcore can handle it properly. 88 | pub buffer: [u32; 36], 89 | } 90 | 91 | /// Deref to RegisterBlock 92 | /// 93 | /// Allows writing 94 | /// ``` 95 | /// self.STATUS.read() 96 | /// ``` 97 | /// instead of something along the lines of 98 | /// ``` 99 | /// unsafe { (*Mbox::ptr()).STATUS.read() } 100 | /// ``` 101 | impl ops::Deref for Mbox { 102 | type Target = RegisterBlock; 103 | 104 | fn deref(&self) -> &Self::Target { 105 | unsafe { &*Self::ptr() } 106 | } 107 | } 108 | 109 | impl Mbox { 110 | pub fn new() -> Mbox { 111 | Mbox { buffer: [0; 36] } 112 | } 113 | 114 | /// Returns a pointer to the register block 115 | fn ptr() -> *const RegisterBlock { 116 | VIDEOCORE_MBOX as *const _ 117 | } 118 | 119 | /// Make a mailbox call. Returns Err(MboxError) on failure, Ok(()) success 120 | pub fn call(&self, channel: u32) -> Result<()> { 121 | // wait until we can write to the mailbox 122 | loop { 123 | if !self.STATUS.is_set(STATUS::FULL) { 124 | break; 125 | } 126 | 127 | asm::nop(); 128 | } 129 | 130 | let buf_ptr = self.buffer.as_ptr() as u32; 131 | 132 | // write the address of our message to the mailbox with channel identifier 133 | self.WRITE.set((buf_ptr & !0xF) | (channel & 0xF)); 134 | 135 | // now wait for the response 136 | loop { 137 | // is there a response? 138 | loop { 139 | if !self.STATUS.is_set(STATUS::EMPTY) { 140 | break; 141 | } 142 | 143 | asm::nop(); 144 | } 145 | 146 | let resp: u32 = self.READ.get(); 147 | 148 | // is it a response to our message? 149 | if ((resp & 0xF) == channel) && ((resp & !0xF) == buf_ptr) { 150 | // is it a valid successful response? 151 | return match self.buffer[1] { 152 | response::SUCCESS => Ok(()), 153 | response::ERROR => Err(MboxError::ResponseError), 154 | _ => Err(MboxError::UnknownError), 155 | }; 156 | } 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /06_raspbootin64/src/mbox.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2018 Andre Richter 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | use super::MMIO_BASE; 26 | use core::ops; 27 | use register::mmio::{ReadOnly, WriteOnly}; 28 | 29 | register_bitfields! { 30 | u32, 31 | 32 | STATUS [ 33 | FULL OFFSET(31) NUMBITS(1) [], 34 | EMPTY OFFSET(30) NUMBITS(1) [] 35 | ] 36 | } 37 | 38 | const VIDEOCORE_MBOX: u32 = MMIO_BASE + 0xB880; 39 | 40 | #[allow(non_snake_case)] 41 | #[repr(C)] 42 | pub struct RegisterBlock { 43 | READ: ReadOnly, // 0x00 44 | __reserved_0: [u32; 5], // 0x04 45 | STATUS: ReadOnly, // 0x18 46 | __reserved_1: u32, // 0x1C 47 | WRITE: WriteOnly, // 0x20 48 | } 49 | 50 | // Custom errors 51 | pub enum MboxError { 52 | ResponseError, 53 | UnknownError, 54 | } 55 | pub type Result = ::core::result::Result; 56 | 57 | // Channels 58 | pub mod channel { 59 | pub const PROP: u32 = 8; 60 | } 61 | 62 | // Tags 63 | pub mod tag { 64 | pub const SETCLKRATE: u32 = 0x38002; 65 | pub const LAST: u32 = 0; 66 | } 67 | 68 | // Clocks 69 | pub mod clock { 70 | pub const UART: u32 = 0x0_0000_0002; 71 | } 72 | 73 | // Responses 74 | mod response { 75 | pub const SUCCESS: u32 = 0x8000_0000; 76 | pub const ERROR: u32 = 0x8000_0001; // error parsing request buffer (partial response) 77 | } 78 | 79 | pub const REQUEST: u32 = 0; 80 | 81 | // Public interface to the mailbox 82 | #[repr(C)] 83 | #[repr(align(16))] 84 | pub struct Mbox { 85 | // The address for buffer needs to be 16-byte aligned so that the 86 | // Videcore can handle it properly. 87 | pub buffer: [u32; 36], 88 | } 89 | 90 | /// Deref to RegisterBlock 91 | /// 92 | /// Allows writing 93 | /// ``` 94 | /// self.STATUS.read() 95 | /// ``` 96 | /// instead of something along the lines of 97 | /// ``` 98 | /// unsafe { (*Mbox::ptr()).STATUS.read() } 99 | /// ``` 100 | impl ops::Deref for Mbox { 101 | type Target = RegisterBlock; 102 | 103 | fn deref(&self) -> &Self::Target { 104 | unsafe { &*Self::ptr() } 105 | } 106 | } 107 | 108 | impl Mbox { 109 | pub fn new() -> Mbox { 110 | Mbox { buffer: [0; 36] } 111 | } 112 | 113 | /// Returns a pointer to the register block 114 | fn ptr() -> *const RegisterBlock { 115 | VIDEOCORE_MBOX as *const _ 116 | } 117 | 118 | /// Make a mailbox call. Returns Err(MboxError) on failure, Ok(()) success 119 | pub fn call(&self, channel: u32) -> Result<()> { 120 | // wait until we can write to the mailbox 121 | loop { 122 | if !self.STATUS.is_set(STATUS::FULL) { 123 | break; 124 | } 125 | 126 | unsafe { asm!("nop" :::: "volatile") }; 127 | } 128 | 129 | let buf_ptr = self.buffer.as_ptr() as u32; 130 | 131 | // write the address of our message to the mailbox with channel identifier 132 | self.WRITE.set((buf_ptr & !0xF) | (channel & 0xF)); 133 | 134 | // now wait for the response 135 | loop { 136 | // is there a response? 137 | loop { 138 | if !self.STATUS.is_set(STATUS::EMPTY) { 139 | break; 140 | } 141 | 142 | unsafe { asm!("nop" :::: "volatile") }; 143 | } 144 | 145 | let resp: u32 = self.READ.get(); 146 | 147 | // is it a response to our message? 148 | if ((resp & 0xF) == channel) && ((resp & !0xF) == buf_ptr) { 149 | // is it a valid successful response? 150 | return match self.buffer[1] { 151 | response::SUCCESS => Ok(()), 152 | response::ERROR => Err(MboxError::ResponseError), 153 | _ => Err(MboxError::UnknownError), 154 | }; 155 | } 156 | } 157 | } 158 | } 159 | --------------------------------------------------------------------------------