Skip to content

Commit a4a7c8c

Browse files
committed
Add new examples. Fix GPIO
1 parent f29cedf commit a4a7c8c

File tree

16 files changed

+300
-41
lines changed

16 files changed

+300
-41
lines changed

.cargo/config.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
[target.'cfg(all(target_arch = "riscv32", target_os = "none"))']
22
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
3+
# runner = "riscv64-unknown-elf-gdb -q -x hifive1-examples/gdb_init" # Uncomment for hardware (no semihosting)
4+
# runner = "riscv64-unknown-elf-gdb -q -x hifive1-examples/gdb_init_sh" # Uncomment for hardware (semihosting)
45
rustflags = [
5-
"-C", "link-arg=-Thifive1-link.x",
6+
# "-C", "link-arg=-Thifive1-link.x",
67
"--cfg", "portable_atomic_target_feature=\"zaamo\"",
78
]
89

e310x-hal/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
88
## [Unreleased]
99

1010
### Changed
11+
- Fix `StatefulOutputPin::is_set_high`. It now reads from `output_val`
12+
- UART traits are implemented now from `embedded-hal-nb` 1.0.0
13+
- Update `embedded-hal` to 1.0.0
1114
- Update `riscv` to 0.12.1
1215
- Remove `virq` feature. Now interrupts are handled by `e310x`
1316
- Apply clippy changes

e310x-hal/src/gpio.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,56 +80,61 @@ trait PeripheralAccess {
8080

8181
fn set_input_en(index: usize, bit: bool) {
8282
let p = Self::peripheral();
83-
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.input_en()) };
83+
let r: &AtomicU32 = unsafe { core::mem::transmute(p.input_en()) };
8484
atomic_set_bit(r, index, bit);
8585
}
8686

8787
fn set_output_en(index: usize, bit: bool) {
8888
let p = Self::peripheral();
89-
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.output_en()) };
89+
let r: &AtomicU32 = unsafe { core::mem::transmute(p.output_en()) };
9090
atomic_set_bit(r, index, bit);
9191
}
9292

93+
fn output_value(index: usize) -> bool {
94+
let p = Self::peripheral();
95+
((p.output_val().read().bits() >> (index & 31)) & 1) != 0
96+
}
97+
9398
fn set_output_value(index: usize, bit: bool) {
9499
let p = Self::peripheral();
95-
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.output_val()) };
100+
let r: &AtomicU32 = unsafe { core::mem::transmute(p.output_val()) };
96101
atomic_set_bit(r, index, bit);
97102
}
98103

99104
fn toggle_pin(index: usize) {
100105
let p = Self::peripheral();
101-
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.output_val()) };
106+
let r: &AtomicU32 = unsafe { core::mem::transmute(p.output_val()) };
102107
let mask = 1 << (index & 31);
103108
r.fetch_xor(mask, Ordering::SeqCst);
104109
}
105110

106111
fn set_pullup(index: usize, bit: bool) {
107112
let p = Self::peripheral();
108-
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.pullup()) };
113+
let r: &AtomicU32 = unsafe { core::mem::transmute(p.pullup()) };
109114
atomic_set_bit(r, index, bit);
110115
}
111116

112117
fn set_drive(index: usize, bit: bool) {
113118
let p = Self::peripheral();
114-
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.drive()) };
119+
let r: &AtomicU32 = unsafe { core::mem::transmute(p.drive()) };
115120
atomic_set_bit(r, index, bit);
116121
}
117122

118123
fn set_out_xor(index: usize, bit: bool) {
119124
let p = Self::peripheral();
120-
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.out_xor()) };
125+
let r: &AtomicU32 = unsafe { core::mem::transmute(p.out_xor()) };
121126
atomic_set_bit(r, index, bit);
122127
}
123128

124129
fn set_iof_en(index: usize, bit: bool) {
125130
let p = Self::peripheral();
126-
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.iof_en()) };
131+
let r: &AtomicU32 = unsafe { core::mem::transmute(p.iof_en()) };
127132
atomic_set_bit(r, index, bit);
128133
}
129134

130135
fn set_iof_sel(index: usize, bit: bool) {
131136
let p = Self::peripheral();
132-
let r: &AtomicU32 = unsafe { core::mem::transmute(&p.iof_sel()) };
137+
let r: &AtomicU32 = unsafe { core::mem::transmute(p.iof_sel()) };
133138
atomic_set_bit(r, index, bit);
134139
}
135140
}
@@ -310,7 +315,7 @@ macro_rules! gpio {
310315
impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
311316
#[inline]
312317
fn is_set_high(&mut self) -> Result<bool, Infallible> {
313-
Ok($GPIOX::input_value(Self::INDEX))
318+
Ok($GPIOX::output_value(Self::INDEX))
314319
}
315320

316321
#[inline]

hifive1-examples/.cargo/config.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[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 hifive1-examples/gdb_init" # Uncomment for hardware (no semihosting)
4+
# runner = "riscv64-unknown-elf-gdb -q -x hifive1-examples/gdb_init_sh" # Uncomment for hardware (semihosting)
5+
rustflags = [
6+
"-C", "link-arg=-Thifive1-link.x",
7+
"--cfg", "portable_atomic_target_feature=\"zaamo\"",
8+
]
9+
10+
[build]
11+
target = "riscv32imc-unknown-none-elf"

hifive1-examples/Cargo.toml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
[package]
2+
name = "hifive1-examples"
3+
version = "0.1.0"
4+
repository = "https://github.com/riscv-rust/e310x"
5+
authors = ["David Craven <[email protected]>"]
6+
categories = ["embedded", "hardware-support", "no-std"]
7+
description = "Running examples for HiFive1 and LoFive boards"
8+
keywords = ["riscv", "register", "peripheral"]
9+
license = "ISC"
10+
edition = "2021"
11+
rust-version = "1.72"
12+
13+
[workspace]
14+
15+
[dependencies]
16+
critical-section = { version = "1.1.3" }
17+
hifive1 = { path = "../hifive1", version = "0.13.0", features = ["board-hifive1-revb"] } # Change to your board
18+
riscv-rt = { version = "0.12.2", features = ["single-hart"] }
19+
panic-halt = "0.2.0"
20+
semihosting = { version = "0.1", features = ["stdio", "panic-handler"], optional = true }
21+
22+
[features]
23+
virq = ["hifive1/virq"]
24+
25+
[[example]]
26+
name = "sh_hello_world"
27+
required-features = ["semihosting"]
28+
29+
[[example]]
30+
name = "sh_led_blink"
31+
required-features = ["semihosting"]
32+
33+
[[example]]
34+
name = "sh_rgb_blink"
35+
required-features = ["semihosting"]

hifive1/examples/hello_world.rs renamed to hifive1-examples/examples/hello_world.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
//! Prints "hello world!" to the host console using semihosting and the on-board UART.
1+
//! Prints "hello world!" to the host console.
2+
//!
3+
//! If "semihosting" feature is enabled, the message is printed using semihosting.
4+
//! Otherwise, the message is printed using the UART0 peripheral.
25
36
#![no_std]
47
#![no_main]
58

9+
extern crate panic_halt;
610
use hifive1::{
711
hal::{prelude::*, DeviceResources},
8-
pin, sprintln,
12+
pin, sprintln as println,
913
};
10-
use semihosting::{println, process::exit};
1114

1215
#[riscv_rt::entry]
1316
fn main() -> ! {
@@ -27,8 +30,6 @@ fn main() -> ! {
2730
clocks,
2831
);
2932

30-
sprintln!("STDOUT: hello world!");
31-
println!("Semihosting: hello world!");
32-
33-
exit(0);
33+
println!("Hello, world!");
34+
loop {}
3435
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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, sprintln, Led,
11+
};
12+
extern crate panic_halt;
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+
// Configure UART for stdout
24+
hifive1::stdout::configure(
25+
p.UART0,
26+
pin!(pins, uart0_tx),
27+
pin!(pins, uart0_rx),
28+
115_200.bps(),
29+
clocks,
30+
);
31+
32+
// get all 3 led pins in a tuple (each pin is it's own type here)
33+
let pin = pin!(pins, led_blue);
34+
let mut led = pin.into_inverted_output();
35+
36+
// Get the sleep struct from CLINT
37+
let clint = dr.core_peripherals.clint;
38+
let mut sleep = Sleep::new(clint.mtimecmp, clocks);
39+
40+
const STEP: u32 = 1000; // 1s
41+
loop {
42+
Led::toggle(&mut led);
43+
sprintln!("LED toggled. New state: {}", led.is_on());
44+
sleep.delay_ms(STEP);
45+
}
46+
}

hifive1/examples/rgb_blink.rs renamed to hifive1-examples/examples/rgb_blink.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
use hifive1::{
88
clock,
99
hal::{delay::Sleep, prelude::*, DeviceResources},
10-
pins, Led,
10+
pin, pins, sprintln, Led,
1111
};
12-
use semihosting::println;
12+
extern crate panic_halt;
1313

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

23+
// Configure UART for stdout
24+
hifive1::stdout::configure(
25+
p.UART0,
26+
pin!(pins, uart0_tx),
27+
pin!(pins, uart0_rx),
28+
115_200.bps(),
29+
clocks,
30+
);
31+
2332
// get all 3 led pins in a tuple (each pin is it's own type here)
2433
let rgb_pins = pins!(pins, (led_red, led_green, led_blue));
2534
let mut tleds = hifive1::rgb(rgb_pins.0, rgb_pins.1, rgb_pins.2);
@@ -30,13 +39,11 @@ fn main() -> ! {
3039
let clint = dr.core_peripherals.clint;
3140
let mut sleep = Sleep::new(clint.mtimecmp, clocks);
3241

33-
println!("Starting blink loop");
34-
3542
const STEP: u32 = 1000; // 1s
3643
loop {
3744
for (i, led) in ileds.iter_mut().enumerate() {
3845
led.toggle().unwrap();
39-
println!("LED {i} toggled. New state: {}", led.is_on());
46+
sprintln!("LED {} toggled. New state: {}", i, led.is_on());
4047
sleep.delay_ms(STEP);
4148
}
4249
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//! Prints "hello world!" to the host console using semihosting.
2+
3+
#![no_std]
4+
#![no_main]
5+
6+
use semihosting::{println, process::exit};
7+
8+
#[riscv_rt::entry]
9+
fn main() -> ! {
10+
println!("Hello, world!");
11+
exit(0);
12+
}

hifive1/examples/led_blink.rs renamed to hifive1-examples/examples/sh_led_blink.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use hifive1::{
99
hal::{delay::Sleep, prelude::*, DeviceResources},
1010
pin, Led,
1111
};
12-
use semihosting::println;
12+
use semihosting::{println, process::exit};
1313

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

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

33-
const STEP: u32 = 1000; // 1s
34-
loop {
34+
println!("Toggling LED {} times", N_TOGGLE);
35+
for _ in 0..N_TOGGLE {
3536
Led::toggle(&mut led);
3637
println!("LED toggled. New state: {}", led.is_on());
3738
sleep.delay_ms(STEP);
3839
}
40+
println!("Done toggling LED");
41+
exit(0);
3942
}

0 commit comments

Comments
 (0)