Skip to content

Commit f29cedf

Browse files
committed
Add examples based on semihosting
1 parent c9221f1 commit f29cedf

File tree

7 files changed

+146
-9
lines changed

7 files changed

+146
-9
lines changed

.cargo/config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
[target.'cfg(all(target_arch = "riscv32", target_os = "none"))']
2+
runner = "qemu-system-riscv32 -machine sifive_e,revb=true -nographic -semihosting-config enable=on,target=native -kernel" # Uncomment for QEMU
3+
# runner = "riscv64-unknown-elf-gdb -q -x gdb_init" # Uncomment for hardware
24
rustflags = [
5+
"-C", "link-arg=-Thifive1-link.x",
36
"--cfg", "portable_atomic_target_feature=\"zaamo\"",
47
]
58

hifive1/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
9-
9+
- Add examples based on semihosting
10+
- Adapt to embedded-hal 1.0
1011
- Replace static muts with Mutexes
1112
- Apply clippy changes
1213
- Bump MSRV to 1.76

hifive1/Cargo.toml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ rust-version = "1.76"
1313
[dependencies]
1414
critical-section = { version = "1.1.3" }
1515
e310x-hal = { path = "../e310x-hal", version = "0.12.0" }
16-
embedded-hal = "0.2.7"
17-
riscv = "0.12.1"
1816
nb = "1.0.0"
17+
riscv = "0.12.1"
18+
19+
[dev-dependencies]
20+
riscv-rt = { version = "0.12.2", features = ["single-hart"] }
21+
semihosting = { version = "0.1", features = ["stdio", "panic-handler"] }
1922

2023
[features]
2124
board-hifive1 = []
@@ -27,3 +30,11 @@ v-trap = ["e310x-hal/v-trap"]
2730

2831
[package.metadata.docs.rs]
2932
features = ['board-hifive1-revb']
33+
34+
[[example]]
35+
name = "led_blink"
36+
required-features = ["board-hifive1-revb"]
37+
38+
[[example]]
39+
name = "rgb_blink"
40+
required-features = ["board-hifive1-revb"]

hifive1/examples/hello_world.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//! Prints "hello world!" to the host console using semihosting and the on-board UART.
2+
3+
#![no_std]
4+
#![no_main]
5+
6+
use hifive1::{
7+
hal::{prelude::*, DeviceResources},
8+
pin, sprintln,
9+
};
10+
use semihosting::{println, process::exit};
11+
12+
#[riscv_rt::entry]
13+
fn main() -> ! {
14+
let dr = DeviceResources::take().unwrap();
15+
let p = dr.peripherals;
16+
let pins = dr.pins;
17+
18+
// Configure clocks
19+
let clocks = hifive1::clock::configure(p.PRCI, p.AONCLK, 320.mhz().into());
20+
21+
// Configure UART for stdout
22+
hifive1::stdout::configure(
23+
p.UART0,
24+
pin!(pins, uart0_tx),
25+
pin!(pins, uart0_rx),
26+
115_200.bps(),
27+
clocks,
28+
);
29+
30+
sprintln!("STDOUT: hello world!");
31+
println!("Semihosting: hello world!");
32+
33+
exit(0);
34+
}

hifive1/examples/led_blink.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//! Basic blinking LEDs example using mtime/mtimecmp registers for "sleep" in a loop.
2+
//! Blinks each led once and goes to the next one.
3+
4+
#![no_std]
5+
#![no_main]
6+
7+
use hifive1::{
8+
clock,
9+
hal::{delay::Sleep, prelude::*, DeviceResources},
10+
pin, Led,
11+
};
12+
use semihosting::println;
13+
14+
#[riscv_rt::entry]
15+
fn main() -> ! {
16+
let dr = DeviceResources::take().unwrap();
17+
let p = dr.peripherals;
18+
let pins = dr.pins;
19+
20+
// Configure clocks
21+
let clocks = clock::configure(p.PRCI, p.AONCLK, 320.mhz().into());
22+
23+
// get all 3 led pins in a tuple (each pin is it's own type here)
24+
let pin = pin!(pins, led_blue);
25+
let mut led = pin.into_inverted_output();
26+
27+
// Get the sleep struct from CLINT
28+
let clint = dr.core_peripherals.clint;
29+
let mut sleep = Sleep::new(clint.mtimecmp, clocks);
30+
31+
println!("Starting blink loop");
32+
33+
const STEP: u32 = 1000; // 1s
34+
loop {
35+
Led::toggle(&mut led);
36+
println!("LED toggled. New state: {}", led.is_on());
37+
sleep.delay_ms(STEP);
38+
}
39+
}

hifive1/examples/rgb_blink.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//! Basic blinking LEDs example using mtime/mtimecmp registers for "sleep" in a loop.
2+
//! Blinks each led once and goes to the next one.
3+
4+
#![no_std]
5+
#![no_main]
6+
7+
use hifive1::{
8+
clock,
9+
hal::{delay::Sleep, prelude::*, DeviceResources},
10+
pins, Led,
11+
};
12+
use semihosting::println;
13+
14+
#[riscv_rt::entry]
15+
fn main() -> ! {
16+
let dr = DeviceResources::take().unwrap();
17+
let p = dr.peripherals;
18+
let pins = dr.pins;
19+
20+
// Configure clocks
21+
let clocks = clock::configure(p.PRCI, p.AONCLK, 320.mhz().into());
22+
23+
// get all 3 led pins in a tuple (each pin is it's own type here)
24+
let rgb_pins = pins!(pins, (led_red, led_green, led_blue));
25+
let mut tleds = hifive1::rgb(rgb_pins.0, rgb_pins.1, rgb_pins.2);
26+
// get leds as the Led trait in an array so we can index them
27+
let mut ileds: [&mut dyn Led; 3] = [&mut tleds.0, &mut tleds.1, &mut tleds.2];
28+
29+
// Get the sleep struct from CLINT
30+
let clint = dr.core_peripherals.clint;
31+
let mut sleep = Sleep::new(clint.mtimecmp, clocks);
32+
33+
println!("Starting blink loop");
34+
35+
const STEP: u32 = 1000; // 1s
36+
loop {
37+
for (i, led) in ileds.iter_mut().enumerate() {
38+
led.toggle().unwrap();
39+
println!("LED {i} toggled. New state: {}", led.is_on());
40+
sleep.delay_ms(STEP);
41+
}
42+
}
43+
}

hifive1/src/led.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//! RedV
99
//! - Blue = Pin 5
1010
11+
use core::convert::Infallible;
1112
#[cfg(feature = "board-redv")]
1213
use e310x_hal::gpio::gpio0::Pin5;
1314
#[cfg(any(feature = "board-hifive1", feature = "board-hifive1-revb"))]
@@ -43,33 +44,38 @@ pub fn rgb<X, Y, Z>(red: Pin22<X>, green: Pin19<Y>, blue: Pin21<Z>) -> (RED, GRE
4344
}
4445

4546
/// Generic LED
46-
pub trait Led {
47+
pub trait Led: StatefulOutputPin<Error = Infallible> {
48+
/// Returns true if the LED is on
49+
fn is_on(&mut self) -> bool;
50+
4751
/// Turns the LED off
4852
fn off(&mut self);
4953

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

5357
/// Toggles the LED state
54-
fn toggle(&mut self);
58+
fn toggle(&mut self) {
59+
StatefulOutputPin::toggle(self).unwrap();
60+
}
5561
}
5662

5763
/// Macro to implement the Led trait for each of the board LEDs
5864
macro_rules! led_impl {
5965
($($LEDTYPE:ident),+) => {
6066
$(
6167
impl Led for $LEDTYPE {
68+
fn is_on(&mut self) -> bool {
69+
self.is_set_high().unwrap()
70+
}
71+
6272
fn off(&mut self) {
6373
self.set_low().unwrap();
6474
}
6575

6676
fn on(&mut self) {
6777
self.set_high().unwrap();
6878
}
69-
70-
fn toggle(&mut self) {
71-
StatefulOutputPin::toggle(self).unwrap();
72-
}
7379
}
7480
)+
7581
}

0 commit comments

Comments
 (0)