Skip to content

Commit

Permalink
Add new examples. Fix GPIO
Browse files Browse the repository at this point in the history
  • Loading branch information
romancardenas committed Oct 19, 2024
1 parent 4ae89f2 commit 088dc69
Show file tree
Hide file tree
Showing 16 changed files with 300 additions and 41 deletions.
5 changes: 3 additions & 2 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
[target.'cfg(all(target_arch = "riscv32", target_os = "none"))']
runner = "qemu-system-riscv32 -machine sifive_e,revb=true -nographic -semihosting-config enable=on,target=native -kernel" # Uncomment for QEMU
# runner = "riscv64-unknown-elf-gdb -q -x gdb_init" # Uncomment for hardware
# runner = "riscv64-unknown-elf-gdb -q -x hifive1-examples/gdb_init" # Uncomment for hardware (no semihosting)
# runner = "riscv64-unknown-elf-gdb -q -x hifive1-examples/gdb_init_sh" # Uncomment for hardware (semihosting)
rustflags = [
"-C", "link-arg=-Thifive1-link.x",
# "-C", "link-arg=-Thifive1-link.x",
"--cfg", "portable_atomic_target_feature=\"zaamo\"",
]

Expand Down
3 changes: 3 additions & 0 deletions e310x-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]

### Changed
- Fix `StatefulOutputPin::is_set_high`. It now reads from `output_val`
- UART traits are implemented now from `embedded-hal-nb` 1.0.0
- Update `embedded-hal` to 1.0.0
- Update `riscv` to 0.11.1
- Apply clippy changes
- Use `portable-atomic` with `zaamo` feature to use native `amo*` operations.
Expand Down
25 changes: 15 additions & 10 deletions e310x-hal/src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,56 +80,61 @@ trait PeripheralAccess {

fn set_input_en(index: usize, bit: bool) {
let p = Self::peripheral();
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.input_en()) };
let r: &AtomicU32 = unsafe { core::mem::transmute(p.input_en()) };
atomic_set_bit(r, index, bit);
}

fn set_output_en(index: usize, bit: bool) {
let p = Self::peripheral();
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.output_en()) };
let r: &AtomicU32 = unsafe { core::mem::transmute(p.output_en()) };
atomic_set_bit(r, index, bit);
}

fn output_value(index: usize) -> bool {
let p = Self::peripheral();
((p.output_val().read().bits() >> (index & 31)) & 1) != 0
}

fn set_output_value(index: usize, bit: bool) {
let p = Self::peripheral();
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.output_val()) };
let r: &AtomicU32 = unsafe { core::mem::transmute(p.output_val()) };
atomic_set_bit(r, index, bit);
}

fn toggle_pin(index: usize) {
let p = Self::peripheral();
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.output_val()) };
let r: &AtomicU32 = unsafe { core::mem::transmute(p.output_val()) };
let mask = 1 << (index & 31);
r.fetch_xor(mask, Ordering::SeqCst);
}

fn set_pullup(index: usize, bit: bool) {
let p = Self::peripheral();
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.pullup()) };
let r: &AtomicU32 = unsafe { core::mem::transmute(p.pullup()) };
atomic_set_bit(r, index, bit);
}

fn set_drive(index: usize, bit: bool) {
let p = Self::peripheral();
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.drive()) };
let r: &AtomicU32 = unsafe { core::mem::transmute(p.drive()) };
atomic_set_bit(r, index, bit);
}

fn set_out_xor(index: usize, bit: bool) {
let p = Self::peripheral();
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.out_xor()) };
let r: &AtomicU32 = unsafe { core::mem::transmute(p.out_xor()) };
atomic_set_bit(r, index, bit);
}

fn set_iof_en(index: usize, bit: bool) {
let p = Self::peripheral();
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.iof_en()) };
let r: &AtomicU32 = unsafe { core::mem::transmute(p.iof_en()) };
atomic_set_bit(r, index, bit);
}

fn set_iof_sel(index: usize, bit: bool) {
let p = Self::peripheral();
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.iof_sel()) };
let r: &AtomicU32 = unsafe { core::mem::transmute(p.iof_sel()) };
atomic_set_bit(r, index, bit);
}
}
Expand Down Expand Up @@ -310,7 +315,7 @@ macro_rules! gpio {
impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
#[inline]
fn is_set_high(&mut self) -> Result<bool, Infallible> {
Ok($GPIOX::input_value(Self::INDEX))
Ok($GPIOX::output_value(Self::INDEX))
}

#[inline]
Expand Down
11 changes: 11 additions & 0 deletions hifive1-examples/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[target.'cfg(all(target_arch = "riscv32", target_os = "none"))']
runner = "qemu-system-riscv32 -machine sifive_e,revb=true -nographic -semihosting-config enable=on,target=native -kernel" # Uncomment for QEMU
# runner = "riscv64-unknown-elf-gdb -q -x hifive1-examples/gdb_init" # Uncomment for hardware (no semihosting)
# runner = "riscv64-unknown-elf-gdb -q -x hifive1-examples/gdb_init_sh" # Uncomment for hardware (semihosting)
rustflags = [
"-C", "link-arg=-Thifive1-link.x",
"--cfg", "portable_atomic_target_feature=\"zaamo\"",
]

[build]
target = "riscv32imc-unknown-none-elf"
35 changes: 35 additions & 0 deletions hifive1-examples/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[package]
name = "hifive1-examples"
version = "0.1.0"
repository = "https://github.com/riscv-rust/e310x"
authors = ["David Craven <[email protected]>"]
categories = ["embedded", "hardware-support", "no-std"]
description = "Running examples for HiFive1 and LoFive boards"
keywords = ["riscv", "register", "peripheral"]
license = "ISC"
edition = "2021"
rust-version = "1.72"

[workspace]

[dependencies]
critical-section = { version = "1.1.3" }
hifive1 = { path = "../hifive1", version = "0.13.0", features = ["board-hifive1-revb"] } # Change to your board
riscv-rt = { version = "0.12.2", features = ["single-hart"] }
panic-halt = "0.2.0"
semihosting = { version = "0.1", features = ["stdio", "panic-handler"], optional = true }

[features]
virq = ["hifive1/virq"]

[[example]]
name = "sh_hello_world"
required-features = ["semihosting"]

[[example]]
name = "sh_led_blink"
required-features = ["semihosting"]

[[example]]
name = "sh_rgb_blink"
required-features = ["semihosting"]
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
//! Prints "hello world!" to the host console using semihosting and the on-board UART.
//! Prints "hello world!" to the host console.
//!
//! If "semihosting" feature is enabled, the message is printed using semihosting.
//! Otherwise, the message is printed using the UART0 peripheral.
#![no_std]
#![no_main]

extern crate panic_halt;
use hifive1::{
hal::{prelude::*, DeviceResources},
pin, sprintln,
pin, sprintln as println,
};
use semihosting::{println, process::exit};

#[riscv_rt::entry]
fn main() -> ! {
Expand All @@ -27,8 +30,6 @@ fn main() -> ! {
clocks,
);

sprintln!("STDOUT: hello world!");
println!("Semihosting: hello world!");

exit(0);
println!("Hello, world!");
loop {}
}
46 changes: 46 additions & 0 deletions hifive1-examples/examples/led_blink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//! Basic blinking LEDs example using mtime/mtimecmp registers for "sleep" in a loop.
//! Blinks each led once and goes to the next one.
#![no_std]
#![no_main]

use hifive1::{
clock,
hal::{delay::Sleep, prelude::*, DeviceResources},
pin, sprintln, Led,
};
extern crate panic_halt;

#[riscv_rt::entry]
fn main() -> ! {
let dr = DeviceResources::take().unwrap();
let p = dr.peripherals;
let pins = dr.pins;

// Configure clocks
let clocks = clock::configure(p.PRCI, p.AONCLK, 320.mhz().into());

// Configure UART for stdout
hifive1::stdout::configure(
p.UART0,
pin!(pins, uart0_tx),
pin!(pins, uart0_rx),
115_200.bps(),
clocks,
);

// get all 3 led pins in a tuple (each pin is it's own type here)
let pin = pin!(pins, led_blue);
let mut led = pin.into_inverted_output();

// Get the sleep struct from CLINT
let clint = dr.core_peripherals.clint;
let mut sleep = Sleep::new(clint.mtimecmp, clocks);

const STEP: u32 = 1000; // 1s
loop {
Led::toggle(&mut led);
sprintln!("LED toggled. New state: {}", led.is_on());
sleep.delay_ms(STEP);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
use hifive1::{
clock,
hal::{delay::Sleep, prelude::*, DeviceResources},
pins, Led,
pin, pins, sprintln, Led,
};
use semihosting::println;
extern crate panic_halt;

#[riscv_rt::entry]
fn main() -> ! {
Expand All @@ -20,6 +20,15 @@ fn main() -> ! {
// Configure clocks
let clocks = clock::configure(p.PRCI, p.AONCLK, 320.mhz().into());

// Configure UART for stdout
hifive1::stdout::configure(
p.UART0,
pin!(pins, uart0_tx),
pin!(pins, uart0_rx),
115_200.bps(),
clocks,
);

// get all 3 led pins in a tuple (each pin is it's own type here)
let rgb_pins = pins!(pins, (led_red, led_green, led_blue));
let mut tleds = hifive1::rgb(rgb_pins.0, rgb_pins.1, rgb_pins.2);
Expand All @@ -30,13 +39,11 @@ fn main() -> ! {
let clint = dr.core_peripherals.clint;
let mut sleep = Sleep::new(clint.mtimecmp, clocks);

println!("Starting blink loop");

const STEP: u32 = 1000; // 1s
loop {
for (i, led) in ileds.iter_mut().enumerate() {
led.toggle().unwrap();
println!("LED {i} toggled. New state: {}", led.is_on());
sprintln!("LED {} toggled. New state: {}", i, led.is_on());
sleep.delay_ms(STEP);
}
}
Expand Down
12 changes: 12 additions & 0 deletions hifive1-examples/examples/sh_hello_world.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! Prints "hello world!" to the host console using semihosting.
#![no_std]
#![no_main]

use semihosting::{println, process::exit};

#[riscv_rt::entry]
fn main() -> ! {
println!("Hello, world!");
exit(0);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use hifive1::{
hal::{delay::Sleep, prelude::*, DeviceResources},
pin, Led,
};
use semihosting::println;
use semihosting::{println, process::exit};

#[riscv_rt::entry]
fn main() -> ! {
Expand All @@ -28,12 +28,15 @@ fn main() -> ! {
let clint = dr.core_peripherals.clint;
let mut sleep = Sleep::new(clint.mtimecmp, clocks);

println!("Starting blink loop");
const N_TOGGLE: usize = 4;
const STEP: u32 = 500; // 500 ms

const STEP: u32 = 1000; // 1s
loop {
println!("Toggling LED {} times", N_TOGGLE);
for _ in 0..N_TOGGLE {
Led::toggle(&mut led);
println!("LED toggled. New state: {}", led.is_on());
sleep.delay_ms(STEP);
}
println!("Done toggling LED");
exit(0);
}
46 changes: 46 additions & 0 deletions hifive1-examples/examples/sh_rgb_blink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//! Basic blinking LEDs example using mtime/mtimecmp registers for "sleep" in a loop.
//! Blinks each led once and goes to the next one.
#![no_std]
#![no_main]

use hifive1::{
clock,
hal::{delay::Sleep, prelude::*, DeviceResources},
pins, Led,
};
use semihosting::{println, process::exit};

#[riscv_rt::entry]
fn main() -> ! {
let dr = DeviceResources::take().unwrap();
let p = dr.peripherals;
let pins = dr.pins;

// Configure clocks
let clocks = clock::configure(p.PRCI, p.AONCLK, 320.mhz().into());

// get all 3 led pins in a tuple (each pin is it's own type here)
let rgb_pins = pins!(pins, (led_red, led_green, led_blue));
let mut tleds = hifive1::rgb(rgb_pins.0, rgb_pins.1, rgb_pins.2);
// get leds as the Led trait in an array so we can index them
let mut ileds: [&mut dyn Led; 3] = [&mut tleds.0, &mut tleds.1, &mut tleds.2];

// Get the sleep struct from CLINT
let clint = dr.core_peripherals.clint;
let mut sleep = Sleep::new(clint.mtimecmp, clocks);

const N_TOGGLES: usize = 4;
const STEP: u32 = 500; // 500ms

println!("Toggling LEDs {} times", N_TOGGLES);
for _ in 0..N_TOGGLES {
for (i, led) in ileds.iter_mut().enumerate() {
led.toggle().unwrap();
println!("LED {i} toggled. New state: {}", led.is_on());
sleep.delay_ms(STEP);
}
}
println!("Done toggling LEDs");
exit(0);
}
12 changes: 12 additions & 0 deletions hifive1-examples/gdb_init
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# GDB init file for HiFive1 boards

# set history save on # uncomment to save history
set confirm off
set remotetimeout 240
set print asm-demangle on

target extended-remote :3333
monitor reset halt
load
continue # uncomment to start running after loading
# quit # uncomment to exit after loading
13 changes: 13 additions & 0 deletions hifive1-examples/gdb_init_sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# GDB init file for HiFive1 boards (including semihosting)

# set history save on # uncomment to save history
set confirm off
set remotetimeout 240
set print asm-demangle on

target extended-remote :3333
monitor reset halt
monitor arm semihosting enable
load
continue # uncomment to start running after loading
# quit # uncomment to exit after loading
Loading

0 comments on commit 088dc69

Please sign in to comment.