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, frequency: Hertz, led: LED, } static mut TIMER_FIRED: bool = false; impl Task { pub fn new(mut timer: Timer, 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 }; }