diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index ec43636..a59eb01 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -15,11 +15,13 @@ jobs: runs-on: ubuntu-latest steps: - - name: Set up Rust toolchain - run: rustup target add armv7a-none-eabi - uses: actions/checkout@v3 + - name: Set up Rust toolchain + run: rustup target add armv7a-none-eabi + -name: Check + run: cargo clippy -- -D clippy::pedantic - name: Build - run: cargo build --verbose + run: cargo build --verbose - name: Run tests - run: cargo test --verbose + run: cargo test --verbose diff --git a/.gitignore b/.gitignore index ea8c4bf..f43ed7b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +/kernel7.img diff --git a/Cargo.toml b/Cargo.toml index f53ef25..58d2ccd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustberrypie" -version = "0.1.0" +version = "0.2.0" license = "MIT OR Apache-2.0" edition = "2021" diff --git a/Makefile b/Makefile index ac14f76..9b82fe4 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,26 @@ + +RUSTFLAGS_PEDANTIC = -D warnings + all: kernel7.img kernel7.img: target/armv7a-none-eabi/release/kernel +<<<<<<< Updated upstream arm-none-eabi-objcopy -O binary target/armv7a-none-eabi/release/kernel ./kernel7.img target/armv7a-none-eabi/release/kernel: +======= + rust-objcopy -O binary target/armv7a-none-eabi/release/kernel ./kernel7.img +target/armv7a-none-eabi/release/kernel: clippy +>>>>>>> Stashed changes cargo build --release clean: cargo clean rm -f kernel7.img +<<<<<<< Updated upstream +======= +objdump: target/armv7a-none-eabi/release/kernel + cargo objdump --bin kernel --release -- --disassemble --no-show-raw-insn --print-imm-hex + +clippy: + cargo clippy -- -D clippy::pedantic +doc: + cargo doc --open +>>>>>>> Stashed changes diff --git a/kernel7.img b/kernel7.img index 5692d56..a4a2d0d 100755 Binary files a/kernel7.img and b/kernel7.img differ diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..5f9d389 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +# channel = "nightly-2022-10-13" +components = ["rust-src", "llvm-tools-preview", "rustfmt", "rust-analyzer"] +targets = ["armv7a-none-eabi"] diff --git a/src/cpu.rs b/src/cpu.rs new file mode 100644 index 0000000..9609666 --- /dev/null +++ b/src/cpu.rs @@ -0,0 +1,22 @@ +use core::{arch::asm, panic::PanicInfo}; + +pub fn wait_forever() -> ! { + loop { + unsafe { + asm!("wfe", options(nomem, nostack)); + } + } +} + +pub fn spin_for_cycles(n: usize) { + for _ in 0..n { + unsafe { + asm!("nop", options(nomem, nostack)); + } + } +} + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + wait_forever() +} diff --git a/src/gpio_pins.rs b/src/gpio_pins.rs new file mode 100644 index 0000000..1e1f8a7 --- /dev/null +++ b/src/gpio_pins.rs @@ -0,0 +1,64 @@ +use core::ptr::read_volatile as read32; +use core::ptr::write_volatile as write32; +// 0x3F20 0008 fsel2 1<<3 turn pin into an output. +// 0x3F20 001C gpio1_set 1<<21 turn pin 21 on. +// 0x3F20 0028 gpio1_clear 1<<21 turn 21 off. +// Constants + +/// This GPIO struct is use to interface with the gpio pin in +/// the Broadcom BCM2835 cpu in the raspberrypi w +#[allow(clippy::upper_case_acronyms)] +pub struct GPIO; + +use crate::memory::mmio::{GPIO_CLEAR0, GPIO_FSEL0, GPIO_FSEL1, GPIO_FSEL2, GPIO_SET0}; +impl GPIO { + pub fn set_output(pin: u32) { + let reg = pin / 10; + let register = match reg { + 0 => GPIO_FSEL0, + 1 => GPIO_FSEL1, + 2 => GPIO_FSEL2, + _ => panic!("Something went wrong."), + }; + let mut val: u32; + unsafe { + val = read32(register as *mut u32); + } + // Create a mask. + let mut mask: u32 = 0b111; + // Shift the mask to the right loocation. + let pinnum = pin % 10; + mask <<= pinnum * 3; + // and in the not of the mask. + val &= !(mask); + // Set OUR value. + val |= 1 << (pinnum * 3); + + unsafe { + write32(register as *mut u32, val); + } + } + pub fn set_high(pin: u32) { + let bitpos = pin; + let mut val: u32; + unsafe { + val = read32(GPIO_SET0 as *mut u32); + } + val |= 1 << bitpos; + unsafe { + write32(GPIO_SET0 as *mut u32, val); + } + } + + pub fn clear(pin: u32) { + let bitpos = pin; + let mut val: u32; + unsafe { + val = read32(GPIO_CLEAR0 as *mut u32); + } + val |= 1 << bitpos; + unsafe { + write32(GPIO_CLEAR0 as *mut u32, val); + } + } +} diff --git a/src/main.rs b/src/main.rs index b6a015b..f82000b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,105 +1,30 @@ -//! This is a flat binary that blinks an led light -//! in the specified port. - #![no_std] #![no_main] -use core::arch::asm; -use core::panic::PanicInfo; -use core::ptr::read_volatile as read32; -use core::ptr::write_volatile as write32; -// 0x3F20 0008 fsel2 1<<3 turn pin into an output. -// 0x3F20 001C gpio1_set 1<<21 turn pin 21 on. -// 0x3F20 0028 gpio1_clear 1<<21 turn 21 off. -// Constants -const GPIO_FSEL0: u32 = 0x3F20_0000; -const GPIO_FSEL1: u32 = 0x3F20_0004; -const GPIO_FSEL2: u32 = 0x3F20_0008; - -const GPIO_SET0: u32 = 0x3F20_001C; -const GPIO_CLEAR0: u32 = 0x3F20_0028; - -/// This GPIO struct is use to interface with the gpio pin in -/// the Broadcom BCM2835 cpu in the raspberrypi w -#[allow(clippy::upper_case_acronyms)] -struct GPIO; +//! This is a flat binary that blinks an led light +//! in the specified port. -impl GPIO { - pub fn set_output(pin: u32) { - let reg = pin / 10; - let register = match reg { - 0 => GPIO_FSEL0, - 1 => GPIO_FSEL1, - 2 => GPIO_FSEL2, - _ => panic!("Something went wrong."), - }; - let mut val: u32; - unsafe { - val = read32(register as *mut u32); - } - // Create a mask. - let mut mask: u32 = 0b111; - // Shift the mask to the right loocation. - let pinnum = pin % 10; - mask <<= pinnum * 3; - // and in the not of the mask. - val &= !(mask); - // Set OUR value. - val |= 1 << (pinnum * 3); +mod cpu; +mod gpio_pins; +mod memory; - unsafe { - write32(register as *mut u32, val); - } - } - pub fn set_high(pin: u32) { - let bitpos = pin; - let mut val: u32; - unsafe { - val = read32(GPIO_SET0 as *mut u32); - } - val |= 1 << bitpos; - unsafe { - write32(GPIO_SET0 as *mut u32, val); - } - } +use gpio_pins::GPIO; - pub fn clear(pin: u32) { - let bitpos = pin; - let mut val: u32; - unsafe { - val = read32(GPIO_CLEAR0 as *mut u32); - } - val |= 1 << bitpos; - unsafe { - write32(GPIO_CLEAR0 as *mut u32, val); - } - } -} #[no_mangle] #[link_section = ".text._start"] pub extern "C" fn _start() -> ! { - const TIME: u32 = 0xC350; // about 1 second + const TIME: usize = 0xC350; // about 1 second const PIN: u32 = 0x15; // pin 21 // Set pin into output. GPIO::set_output(PIN); loop { // turn pin 21 on GPIO::set_high(PIN); - unsafe { - for _ in 1..TIME { - asm!("nop"); - } - } + + cpu::spin_for_cycles(TIME); + // turn pin 21 off GPIO::clear(PIN); - unsafe { - for _ in 1..TIME { - asm!("nop"); - } - } - } -} -#[panic_handler] -fn panic(_info: &PanicInfo) -> ! { - loop {} + cpu::spin_for_cycles(TIME); + } } diff --git a/src/memory.rs b/src/memory.rs new file mode 100644 index 0000000..641adb6 --- /dev/null +++ b/src/memory.rs @@ -0,0 +1,9 @@ +pub mod mmio { + + pub const GPIO_FSEL0: u32 = 0x3F20_0000; + pub const GPIO_FSEL1: u32 = 0x3F20_0004; + pub const GPIO_FSEL2: u32 = 0x3F20_0008; + + pub const GPIO_SET0: u32 = 0x3F20_001C; + pub const GPIO_CLEAR0: u32 = 0x3F20_0028; +}