1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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 };
}
|