Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
Cargo.lock
hdd.dsk
hdd.dsk
.gdb_history
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ panic-halt = "0.2.0"
riscv = "0.6.0"
riscv-rt = "0.8.0"
spin = "0.9.0"
bare-metal = "0.2"

[dependencies.lazy_static]
version = "1.0"
Expand Down
68 changes: 68 additions & 0 deletions examples/gpio_button.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#![no_std]
#![no_main]

/*
* TODO comment
*/

extern crate panic_halt;

use hifive1::hal::delay::Sleep;
use hifive1::hal::prelude::*;
use hifive1::hal::DeviceResources;
use hifive1::sprint;
use hifive1::Led;
use hifive1::{pin, pins};
use riscv_rt::entry;

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

// GPIO PIN1 -> DIG9 physical on board (both hifive1 and hifive1-revB)
let button = pin!(pins, dig9).into_pull_up_input();

// 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);

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

sprint!("hello button {:?}\n", button.is_low());

// // get the local interrupts struct
let clint = dr.core_peripherals.clint;

// // get the sleep struct
let mut sleep = Sleep::new(clint.mtimecmp, clocks);

const PERIOD: u32 = 1000; // 1s
loop {
if let Ok(b) = button.is_low() {
if b {
tleds.0.on();
tleds.1.off();
tleds.2.off();
} else {
tleds.0.off();
tleds.1.off();
tleds.2.on();
}
}

// sleep for 1s
sleep.delay_ms(PERIOD);
}
}
133 changes: 133 additions & 0 deletions examples/gpio_button_interrupt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#![no_std]
#![no_main]

/*
* TODO comment
*/

extern crate panic_halt;

use bare_metal::Nr;
use hifive1::hal::core::plic::Priority;
use hifive1::hal::core::CorePeripherals;
use hifive1::hal::e310x::Interrupt;
use hifive1::hal::e310x::GPIO0;
use hifive1::hal::gpio::{gpio0::Pin1, Input, PullUp};
use hifive1::hal::prelude::*;
use hifive1::hal::DeviceResources;
use hifive1::Led;
use hifive1::{pin, pins};
use hifive1::{sprint, sprintln};
use riscv_rt::entry;

#[no_mangle]
pub unsafe extern "C" fn MachineExternal() {
let mut plic = CorePeripherals::steal().plic;
let intr = plic.claim.claim().unwrap();
match intr {
Interrupt::GPIO1 => {
sprintln!("Hi!");
let dr = DeviceResources::steal();
let pins = dr.pins;

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

if BUTTON
.as_ref()
.expect("interrupt enabled after replace")
.is_low()
.expect("infallable")
{
tleds.0.on();
tleds.1.off();
tleds.2.off();
} else {
tleds.0.off();
tleds.1.off();
tleds.2.on();
}
}
_ => {
sprintln!("Unknown interrupt #{}!", intr.nr());
// panic!("Unknown interrupt");
}
}
plic.claim.complete(intr);
}

static mut BUTTON: Option<Pin1<Input<PullUp>>> = None;

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

// GPIO PIN1 -> DIG9 physical on board (both hifive1 and hifive1-revB)
let button = pin!(pins, dig9).into_pull_up_input();

sprint!("hello world {:?}\n", button.is_low());

unsafe {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surely your gpio into_pull_up_input() should have configured the GPIO memory correctly like you're doing in this block here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think so. It looks like it sets pullup and input_en (and disables iof_en):

/// Configures the pin to operate as a pulled down input pin
pub fn into_pull_up_input(self) -> $PXi<Input<PullUp>> {
    $GPIOX::set_pullup(Self::INDEX, true);
    $GPIOX::set_input_en(Self::INDEX, true);
    $GPIOX::set_iof_en(Self::INDEX, false);
    $PXi { _mode: PhantomData }
}

but I'd still need to configure the "*_ie" (interrupt enable) stuff here. In order to toggle the state of the LED while the button is pressed, I was thinking I could trigger on rising and falling signal edges and just check the value of the input when interrupted, but I've currently got it set up to interrupt when the pin is high or low, thinking that would be "always."

However, I'm beginning to suspect my problem is electrical: I'm not sure I'm reading the diagram correctly, but I think the internal pull-up resistor isn't "part of" (whatever the appropriate term is) the interrupt circuit. So even though when I read the button's input I get a coherent value, the interrupt state is actually floating.

I think this means I need my own pull-up resistor attached to the pin and to not use the internal pull-up?

let rgpio = &*hifive1::hal::e310x::GPIO0::ptr();
// rgpio.rise_ie.write(|w| w.pin1().set_bit());
// rgpio.fall_ie.write(|w| w.pin1().set_bit());
rgpio.input_en.write(|w| w.pin1().set_bit());
rgpio.pullup.write(|w| w.pin1().set_bit());
rgpio.high_ie.write(|w| w.pin1().set_bit());
rgpio.low_ie.write(|w| w.pin1().set_bit());

// rgpio.low_ip.read()
}

unsafe {
BUTTON.replace(button);
}

// 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);
tleds.0.off();
tleds.1.on();
tleds.2.off();

unsafe {
let rplic = &*hifive1::hal::e310x::PLIC::ptr();
for p in rplic.priority.iter() {
// p.write(|w| w.bits(0));
p.write(|w| w.bits(Priority::P7.into()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of hilarious to set priority for all PLIC sources to 7

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, yeah: that was my attempt to answer "well, am I even getting interrupts at ALL? Which ones?"

}
rplic.priority[1].write(|w| w.bits(Priority::P0.into()));
rplic.priority[46].write(|w| w.bits(Priority::P0.into())); // TODO: vas ist das?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh but you're setting 46 (which is a PWM pin I guess?) and the watchdog to 0, so it'll never interrupt.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the answers to the "which ones" question: At first all I saw was a wall of watchdog interrupts as fast as the serial line could print, and when I turned those off then it was all interrupt no. 46. With that disabled, though, I get nothin', despite having set the GPIO to interrupt on every logically coherent state.


// rplic.priority[9].write(|w| w.bits(Priority::P7.into()));
rplic.enable[0].write(|w| w.bits(0b1 << 9));
// rplic.enable[1].write(|w| w.bits(0b1 << 9));

let mut plic = CorePeripherals::steal().plic;

plic.threshold.set(Priority::P0);
plic.mext.enable();

riscv::register::mstatus::set_mie();
}

loop {
unsafe {
riscv::asm::wfi();
}
}
}
1 change: 1 addition & 0 deletions gdb_init
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
set history save on
set confirm off
set remotetimeout 240
set pagination off
target extended-remote :3333
set print asm-demangle on
monitor reset halt
Expand Down