Skip to content

Commit

Permalink
Add examples based on semihosting
Browse files Browse the repository at this point in the history
  • Loading branch information
romancardenas committed Oct 14, 2024
1 parent f7e9e47 commit 4ae89f2
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 8 deletions.
3 changes: 3 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
[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
rustflags = [
"-C", "link-arg=-Thifive1-link.x",
"--cfg", "portable_atomic_target_feature=\"zaamo\"",
]

Expand Down
2 changes: 2 additions & 0 deletions hifive1/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
- Add examples based on semihosting
- Adapt to embedded-hal 1.0
- Replace static muts with Mutexes
- Apply clippy changes
- Bump MSRV to 1.72
Expand Down
15 changes: 13 additions & 2 deletions hifive1/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ rust-version = "1.72"
[dependencies]
critical-section = { version = "1.1.3" }
e310x-hal = { path = "../e310x-hal", version = "0.11.0" }
embedded-hal = "0.2.7"
riscv = "0.10.1"
nb = "1.0.0"
riscv = "0.11.1"

[dev-dependencies]
riscv-rt = { version = "0.12.2", features = ["single-hart"] }
semihosting = { version = "0.1", features = ["stdio", "panic-handler"] }

[features]
board-hifive1 = []
Expand All @@ -27,3 +30,11 @@ virq = ["e310x-hal/virq"]

[package.metadata.docs.rs]
features = ['board-hifive1-revb']

[[example]]
name = "led_blink"
required-features = ["board-hifive1-revb"]

[[example]]
name = "rgb_blink"
required-features = ["board-hifive1-revb"]
34 changes: 34 additions & 0 deletions hifive1/examples/hello_world.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//! Prints "hello world!" to the host console using semihosting and the on-board UART.
#![no_std]
#![no_main]

use hifive1::{
hal::{prelude::*, DeviceResources},
pin, sprintln,
};
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 = hifive1::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,
);

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

exit(0);
}
39 changes: 39 additions & 0 deletions hifive1/examples/led_blink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//! 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, Led,
};
use semihosting::println;

#[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 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);

println!("Starting blink loop");

const STEP: u32 = 1000; // 1s
loop {
Led::toggle(&mut led);
println!("LED toggled. New state: {}", led.is_on());
sleep.delay_ms(STEP);
}
}
43 changes: 43 additions & 0 deletions hifive1/examples/rgb_blink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//! 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;

#[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);

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());
sleep.delay_ms(STEP);
}
}
}
18 changes: 12 additions & 6 deletions hifive1/src/led.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//! RedV
//! - Blue = Pin 5
use core::convert::Infallible;
#[cfg(feature = "board-redv")]
use e310x_hal::gpio::gpio0::Pin5;
#[cfg(any(feature = "board-hifive1", feature = "board-hifive1-revb"))]
Expand Down Expand Up @@ -43,33 +44,38 @@ pub fn rgb<X, Y, Z>(red: Pin22<X>, green: Pin19<Y>, blue: Pin21<Z>) -> (RED, GRE
}

/// Generic LED
pub trait Led {
pub trait Led: StatefulOutputPin<Error = Infallible> {
/// Returns true if the LED is on
fn is_on(&mut self) -> bool;

/// Turns the LED off
fn off(&mut self);

/// Turns the LED on
fn on(&mut self);

/// Toggles the LED state
fn toggle(&mut self);
fn toggle(&mut self) {
StatefulOutputPin::toggle(self).unwrap();
}
}

/// Macro to implement the Led trait for each of the board LEDs
macro_rules! led_impl {
($($LEDTYPE:ident),+) => {
$(
impl Led for $LEDTYPE {
fn is_on(&mut self) -> bool {
self.is_set_high().unwrap()
}

fn off(&mut self) {
self.set_low().unwrap();
}

fn on(&mut self) {
self.set_high().unwrap();
}

fn toggle(&mut self) {
StatefulOutputPin::toggle(self).unwrap();
}
}
)+
}
Expand Down

0 comments on commit 4ae89f2

Please sign in to comment.