-
Notifications
You must be signed in to change notification settings - Fork 0
wip: gpio button example #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
/target | ||
Cargo.lock | ||
hdd.dsk | ||
hdd.dsk | ||
.gdb_history |
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); | ||
} | ||
} |
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 { | ||
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())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Kind of hilarious to set priority for all PLIC sources to 7 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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(); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
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?There was a problem hiding this comment.
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):
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?