diff options
author | Brian Cully <bjc@kublai.com> | 2022-10-25 12:20:32 -0400 |
---|---|---|
committer | Brian Cully <bjc@kublai.com> | 2022-10-25 12:20:32 -0400 |
commit | 0c4eb964b015961e3c90e45ef498f6c7f89eddba (patch) | |
tree | b0cc3b540e7123b45da044c73d1f47f98ce010ef /src-riscv/blink.rs | |
parent | 0f80c612d59c855a99073e583db339fe6a42b883 (diff) | |
download | luchie-0c4eb964b015961e3c90e45ef498f6c7f89eddba.tar.gz luchie-0c4eb964b015961e3c90e45ef498f6c7f89eddba.zip |
convert to gd32f303 (stm32f103) bluepill variant
Diffstat (limited to 'src-riscv/blink.rs')
-rw-r--r-- | src-riscv/blink.rs | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src-riscv/blink.rs b/src-riscv/blink.rs new file mode 100644 index 0000000..967cde6 --- /dev/null +++ b/src-riscv/blink.rs @@ -0,0 +1,70 @@ +use core::convert::Infallible; + +// use gd32vf103xx_hal as hal; +use stm32f30x_hal as hal; + +use hal::{ + //eclic::{self, EclicExt}, + pac::{self, Interrupt}, + prelude::*, + time::Hertz, + timer::{Event, Timer}, +}; +use nb; +use riscv::interrupt; + +use crate::led::LED; + +pub struct Task { + timer: Timer<pac::TIMER6>, + frequency: Hertz, + led: LED, +} + +static mut TIMER_FIRED: bool = false; + +impl Task { + pub fn new(mut timer: Timer<pac::TIMER6>, frequency: Hertz, led: LED) -> Self { + // pac::ECLIC::setup(Interrupt::TIMER6, eclic::TriggerType::RisingEdge, eclic::Level::L0, eclic::Priority::P3); + // unsafe { pac::ECLIC::unmask(Interrupt::TIMER6); } + // assert!(pac::ECLIC::is_enabled(Interrupt::TIMER6)); + timer.listen(Event::Update); + + Self { timer, frequency, led } + } + + pub fn poll(&mut self) -> nb::Result<(), Infallible> { + interrupt::free(|_cs| { + if unsafe { TIMER_FIRED } { + unsafe { TIMER_FIRED = false }; + self.led.toggle(); + self.timer.start(self.frequency); + } + }); + Err(nb::Error::WouldBlock) + } +} + +/* + * because i'm using ‘wfi’ to sleep as much as possible, i need to + * actually schedule the timer to fire an interrupt. that, in turn, + * requires a handler. + * + * why? because, for efficiency reasons, ‘_irq_handler’ uses the + * bumblebee core ‘jalmnxti’ csr, and the default entry in the irq + * vector is ‘0’. so the core jumps to 0, which is the ‘_start’ entry + * point. but it does this *from the interrupt*, which masks the + * interrupt (because it's currently being serviced), so any + * subsequent firings are never triggered, nor any interrupts at lower + * priority. + * + * so it looks like the core resets every other time it's + * started. adding a real isr avoids these problems. + */ +#[export_name="TIMER6"] +fn timer6() { + // logln!("I timer6 I"); + let regs = unsafe { &*pac::TIMER6::ptr() }; + regs.intf.write(|w| w.upif().clear_bit()); + unsafe { TIMER_FIRED = true }; +} |