Skip to content

Commit a9738ef

Browse files
committed
Added base ISA env; added examples with interrupts
1 parent 34ed527 commit a9738ef

File tree

5 files changed

+165
-2
lines changed

5 files changed

+165
-2
lines changed

e310x/build.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ fn main() {
1212
.unwrap();
1313
println!("cargo:rustc-link-search={}", out.display());
1414
println!("cargo:rerun-if-changed=device.x");
15-
println!("cargo:rustc-env=RISCV_MTVEC_ALIGN={}", 64usize);
15+
println!("cargo:rustc-env=RISCV_RT_BASE_ISA=rv32i");
16+
println!("cargo:rerun-if-env-changed=RISCV_RT_BASE_ISA");
17+
println!("cargo:rustc-env=RISCV_MTVEC_ALIGN=64");
1618
println!("cargo:rerun-if-env-changed=RISCV_MTVEC_ALIGN");
1719
}
1820
println!("cargo:rerun-if-changed=build.rs");

e310x/settings.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,5 @@ riscv_config:
5050
core_interrupt: "MachineExternal"
5151
hart_id: "H0"
5252

53+
base_isa: "rv32i"
5354
mtvec_align: 64

e310x/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![doc = "Peripheral access API for FE310 microcontrollers (generated using svd2rust v0.36.1 (698a318 2025-06-08))\n\nYou can find an overview of the generated API [here].\n\nAPI features to be included in the [next] svd2rust release can be generated by cloning the svd2rust [repository], checking out the above commit, and running `cargo doc --open`.\n\n[here]: https://docs.rs/svd2rust/0.36.1/svd2rust/#peripheral-api\n[next]: https://github.com/rust-embedded/svd2rust/blob/master/CHANGELOG.md#unreleased\n[repository]: https://github.com/rust-embedded/svd2rust"]
1+
#![doc = "Peripheral access API for FE310 microcontrollers (generated using svd2rust v0.36.1 (6b2dd03 2025-06-26))\n\nYou can find an overview of the generated API [here].\n\nAPI features to be included in the [next] svd2rust release can be generated by cloning the svd2rust [repository], checking out the above commit, and running `cargo doc --open`.\n\n[here]: https://docs.rs/svd2rust/0.36.1/svd2rust/#peripheral-api\n[next]: https://github.com/rust-embedded/svd2rust/blob/master/CHANGELOG.md#unreleased\n[repository]: https://github.com/rust-embedded/svd2rust"]
22
#![allow(non_camel_case_types)]
33
#![allow(non_snake_case)]
44
#![no_std]
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//! Demonstration on how to configure the GPIO9 interrupt on HiFive boards.
2+
#![no_main]
3+
#![no_std]
4+
5+
use hifive1::{
6+
clock,
7+
hal::DeviceResources,
8+
hal::{e310x::Gpio0, prelude::*},
9+
pin, sprintln, stdout, Led,
10+
};
11+
extern crate panic_halt;
12+
13+
/* Handler for the GPIO9 interrupt */
14+
#[riscv_rt::external_interrupt(ExternalInterrupt::GPIO9)]
15+
fn gpio9_handler() {
16+
sprintln!("GPIO9 interrupt!");
17+
// Clear the GPIO pending interrupt
18+
let gpio_block = unsafe { Gpio0::steal() };
19+
let _prev_fall = gpio_block.fall_ip().read().pin9().bit_is_set();
20+
let _prev_rise = gpio_block.rise_ip().read().pin9().bit_is_set();
21+
// Clear the interrupt by writing 1 to the pending bit
22+
gpio_block.fall_ip().write(|w| w.pin9().set_bit());
23+
gpio_block.rise_ip().write(|w| w.pin9().set_bit());
24+
let _post_fall = gpio_block.fall_ip().read().pin9().bit_is_set();
25+
let _post_rise = gpio_block.rise_ip().read().pin9().bit_is_set();
26+
let _ok = _prev_fall || _prev_rise; // Ensure we cleared the interrupt
27+
}
28+
29+
#[riscv_rt::entry]
30+
fn main() -> ! {
31+
let dr = DeviceResources::take().unwrap();
32+
let cp = dr.core_peripherals;
33+
let p = dr.peripherals;
34+
let pins = dr.pins;
35+
36+
// Configure clocks
37+
let clocks = clock::configure(p.PRCI, p.AONCLK, 320.mhz().into());
38+
39+
// Configure UART for stdout
40+
stdout::configure(
41+
p.UART0,
42+
pin!(pins, uart0_tx),
43+
pin!(pins, uart0_rx),
44+
115_200.bps(),
45+
clocks,
46+
);
47+
48+
sprintln!("Configuring GPIOs...");
49+
// Configure button pin (GPIO9) as pull-up input
50+
let mut button = pins.pin9.into_pull_up_input();
51+
// Configure blue LED pin (GPIO21) as inverted output
52+
let mut led = pin!(pins, led_blue).into_inverted_output();
53+
54+
sprintln!("Configuring external interrupts...");
55+
// Set button interrupt source priority
56+
let plic = cp.plic;
57+
let priorities = plic.priorities();
58+
priorities.reset::<ExternalInterrupt>();
59+
unsafe { priorities.set_priority(ExternalInterrupt::GPIO9, Priority::P1) };
60+
61+
// Enable GPIO9 interrupt for both edges
62+
let gpio_block = unsafe { Gpio0::steal() };
63+
unsafe {
64+
// Clear pending interrupts from previous states
65+
gpio_block.low_ie().write(|w| w.bits(0x00000000));
66+
gpio_block.high_ie().write(|w| w.bits(0x00000000));
67+
gpio_block.fall_ie().write(|w| w.bits(0x00000000));
68+
gpio_block.rise_ie().write(|w| w.bits(0x00000000));
69+
gpio_block.low_ip().write(|w| w.bits(0xffffffff));
70+
gpio_block.high_ip().write(|w| w.bits(0xffffffff));
71+
gpio_block.fall_ip().write(|w| w.bits(0xffffffff));
72+
gpio_block.rise_ip().write(|w| w.bits(0xffffffff));
73+
}
74+
gpio_block.fall_ie().write(|w| w.pin9().set_bit());
75+
gpio_block.rise_ie().write(|w| w.pin9().set_bit());
76+
77+
sprintln!("Enabling external interrupts...");
78+
// Enable GPIO9 interrupt in PLIC
79+
let ctx = plic.ctx0();
80+
unsafe {
81+
ctx.enables().disable_all::<ExternalInterrupt>();
82+
ctx.threshold().set_threshold(Priority::P0);
83+
ctx.enables().enable(ExternalInterrupt::GPIO9);
84+
riscv::interrupt::enable();
85+
plic.enable();
86+
}
87+
88+
loop {
89+
if button.is_low().unwrap() {
90+
sprintln!("Button pressed");
91+
led.on();
92+
} else {
93+
sprintln!("Button released");
94+
led.off();
95+
}
96+
sprintln!("LED is on: {}", led.is_on());
97+
riscv::asm::wfi();
98+
}
99+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//! Basic blinking LED example using mtime/mtimecmp registers for "sleep" in a loop.
2+
//! Blinks the blue LED of RED-V board.
3+
4+
#![no_std]
5+
#![no_main]
6+
7+
use hifive1::{
8+
clock,
9+
hal::{e310x::Clint, prelude::*, DeviceResources},
10+
pin, sprintln, stdout, Led,
11+
};
12+
extern crate panic_halt;
13+
14+
#[riscv_rt::core_interrupt(CoreInterrupt::MachineTimer)]
15+
fn mtimer_handler() {
16+
let clint = unsafe { Clint::steal() };
17+
let mtimer = clint.mtimer();
18+
mtimer
19+
.mtimecmp0()
20+
.modify(|prev| *prev += mtimer.mtime_freq() as u64);
21+
}
22+
23+
#[riscv_rt::entry]
24+
fn main() -> ! {
25+
let dr = DeviceResources::take().unwrap();
26+
let cp = dr.core_peripherals;
27+
let p = dr.peripherals;
28+
let pins = dr.pins;
29+
30+
// Configure clocks
31+
let clocks = clock::configure(p.PRCI, p.AONCLK, 320.mhz().into());
32+
33+
// Configure UART for stdout
34+
stdout::configure(
35+
p.UART0,
36+
pin!(pins, uart0_tx),
37+
pin!(pins, uart0_rx),
38+
115_200.bps(),
39+
clocks,
40+
);
41+
42+
// get blue LED pin
43+
let pin = pin!(pins, led_blue);
44+
let mut led = pin.into_inverted_output();
45+
46+
// Get the MTIMER peripheral from CLINT
47+
let mtimer = cp.clint.mtimer();
48+
mtimer.mtime().write(0);
49+
mtimer.mtimecmp0().write(mtimer.mtime_freq() as u64); // Set the first compare value
50+
51+
unsafe {
52+
mtimer.enable();
53+
riscv::interrupt::enable();
54+
}
55+
56+
loop {
57+
Led::toggle(&mut led);
58+
sprintln!("LED toggled. New state: {}", led.is_on());
59+
riscv::asm::wfi();
60+
}
61+
}

0 commit comments

Comments
 (0)