aboutsummaryrefslogtreecommitdiffstats
path: root/src-riscv/blink.rs
blob: 967cde6f4501335808c23f0ffbc14433ca0c123b (plain)
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 };
}