Merge pull request #3 from robamu-org/mueller/irq-button

Update to v0.2.0
This commit is contained in:
Robin Mueller 2021-11-13 15:08:16 +01:00 committed by GitHub
commit 5078480646
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 195 additions and 15 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "vorago-reb1"
version = "0.1.1"
version = "0.2.0"
authors = ["Robin Mueller <robin.mueller.m@gmail.com>"]
edition = "2021"
description = "Board Support Crate for the Vorago REB1 development board"

View File

@ -2,17 +2,124 @@
#![no_main]
#![no_std]
use core::cell::{Cell, RefCell};
use cortex_m::interrupt::Mutex;
use cortex_m_rt::entry;
use panic_halt as _;
use rtt_target::{rprintln, rtt_init_print};
use va108xx_hal::pac::interrupt;
use va108xx_hal::{
clock::{set_clk_div_register, FilterClkSel},
gpio::{FilterType, InterruptEdge, PinsA},
pac::{self, interrupt},
prelude::*,
time::Hertz,
timer::set_up_ms_timer,
};
use vorago_reb1::button::Button;
use vorago_reb1::leds::Leds;
static LEDS: Mutex<RefCell<Option<Leds>>> = Mutex::new(RefCell::new(None));
static MS_COUNTER: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
static BUTTON: Mutex<RefCell<Option<Button>>> = Mutex::new(RefCell::new(None));
#[derive(Debug, PartialEq)]
pub enum PressMode {
Toggle,
Keep,
}
// You can change the press mode here
const PRESS_MODE: PressMode = PressMode::Keep;
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("-- Vorago Button Blinky --");
rprintln!("-- Vorago Button IRQ Example --");
let mut dp = pac::Peripherals::take().unwrap();
let pinsa = PinsA::new(&mut dp.SYSCONFIG, Some(dp.IOCONFIG), dp.PORTA);
let edge_irq = match PRESS_MODE {
PressMode::Toggle => InterruptEdge::HighToLow,
PressMode::Keep => InterruptEdge::BothEdges,
};
// Configure an edge interrupt on the button and route it to interrupt vector 15
let mut button = Button::new(pinsa.pa11.into_floating_input()).edge_irq(
edge_irq,
Some(&mut dp.SYSCONFIG),
&mut dp.IRQSEL,
pac::interrupt::OC15,
);
if PRESS_MODE == PressMode::Toggle {
// This filter debounces the switch for edge based interrupts
button = button.filter_type(FilterType::FilterFourClockCycles, FilterClkSel::Clk1);
set_clk_div_register(
&mut dp.SYSCONFIG,
FilterClkSel::Clk1,
Hertz::from(50.khz()).0,
);
}
set_up_ms_timer(
&mut dp.SYSCONFIG,
&mut dp.IRQSEL,
50.mhz().into(),
dp.TIM0,
interrupt::OC0,
);
let mut leds = Leds::new(
pinsa.pa10.into_push_pull_output(),
pinsa.pa7.into_push_pull_output(),
pinsa.pa6.into_push_pull_output(),
);
for led in leds.iter_mut() {
led.off();
}
// Activate the IRQs so the processors sees them as well
unmask_irqs();
// Make both button and LEDs accessible from the IRQ handler as well
cortex_m::interrupt::free(|cs| {
LEDS.borrow(cs).replace(Some(leds));
BUTTON.borrow(cs).replace(Some(button));
});
loop {}
}
fn unmask_irqs() {
unsafe {
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::OC0);
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::OC15);
}
}
#[interrupt]
fn OC15() {}
fn OC0() {
cortex_m::interrupt::free(|cs| {
let mut ms = MS_COUNTER.borrow(cs).get();
ms += 1;
MS_COUNTER.borrow(cs).set(ms);
});
}
#[interrupt]
fn OC15() {
cortex_m::interrupt::free(|cs| {
if PRESS_MODE == PressMode::Toggle {
if let Some(ref mut leds) = LEDS.borrow(cs).borrow_mut().as_deref_mut() {
leds[0].toggle();
}
} else {
if let (Some(ref mut leds), Some(ref button)) = (
LEDS.borrow(cs).borrow_mut().as_deref_mut(),
BUTTON.borrow(cs).borrow().as_ref(),
) {
if button.released() {
leds[0].off();
} else {
leds[0].on();
}
}
}
});
}

View File

@ -84,7 +84,12 @@ fn main() -> ! {
}
}
LibType::Bsp => {
let mut leds = Leds::new(PinsA::new(&mut dp.SYSCONFIG, Some(dp.IOCONFIG), dp.PORTA));
let pinsa = PinsA::new(&mut dp.SYSCONFIG, Some(dp.IOCONFIG), dp.PORTA);
let mut leds = Leds::new(
pinsa.pa10.into_push_pull_output(),
pinsa.pa7.into_push_pull_output(),
pinsa.pa6.into_push_pull_output(),
);
loop {
for _ in 0..10 {
// Blink all LEDs quickly

65
src/button.rs Normal file
View File

@ -0,0 +1,65 @@
//! # API for the REB1 button
//!
//! ## Examples
//!
//! - [Button Blinky with Interrupts](https://github.com/robamu-org/vorago-reb1-rs/blob/main/examples/blinky-button-irq.rs)
use va108xx_hal::{
gpio::{FilterClkSel, FilterType, InputFloating, InterruptEdge, InterruptLevel, Pin, PA11},
pac,
prelude::*,
};
pub struct Button {
button: Pin<PA11, InputFloating>,
}
impl Button {
pub fn new(pin: Pin<PA11, InputFloating>) -> Button {
Button { button: pin }
}
pub fn pressed(&self) -> bool {
self.button.is_low().ok().unwrap()
}
pub fn released(&self) -> bool {
self.button.is_high().ok().unwrap()
}
/// Configures an IRQ on edge.
///
/// Please note that you still have to unpend the Cortex-M interrupt yourself
pub fn edge_irq(
mut self,
edge_type: InterruptEdge,
syscfg: Option<&mut pac::SYSCONFIG>,
irqsel: &mut pac::IRQSEL,
irq: pac::interrupt,
) -> Self {
self.button = self.button.interrupt_edge(edge_type, syscfg, irqsel, irq);
self
}
/// Configures an IRQ on level.
///
/// Please note that you still have to unpend the Cortex-M interrupt yourself
pub fn level_irq(
mut self,
level: InterruptLevel,
syscfg: Option<&mut pac::SYSCONFIG>,
irqsel: &mut pac::IRQSEL,
irq: pac::interrupt,
) -> Self {
self.button = self.button.interrupt_level(level, syscfg, irqsel, irq);
self
}
/// Configures a filter on the button. This can be useful for debouncing the switch.
///
/// Please note that you still have to set a clock divisor yourself using the
/// [`va108xx_hal::clock::set_clk_div_register`] function in order for this to work.
pub fn filter_type(mut self, filter: FilterType, clksel: FilterClkSel) -> Self {
self.button = self.button.filter_type(filter, clksel);
self
}
}

View File

@ -1,6 +1,11 @@
//! # API for using the REB1 LEDs
//!
//! ## Examples
//!
//! - [LED example](https://github.com/robamu-org/vorago-reb1-rs/blob/main/examples/blinky-leds.rs)
use va108xx_hal::{
gpio::dynpins::DynPin,
gpio::pins::{Pin, PinsA, PushPullOutput, PA10, PA6, PA7},
gpio::pins::{Pin, PushPullOutput, PA10, PA6, PA7},
prelude::*,
};
@ -13,12 +18,9 @@ pub struct Leds {
}
impl Leds {
pub fn new(led_parts: PinsA) -> Self {
let led2 = led_parts.pa10.into_push_pull_output();
let led3 = led_parts.pa7.into_push_pull_output();
let led4 = led_parts.pa6.into_push_pull_output();
pub fn new(led_pin1: LD2, led_pin2: LD3, led_pin3: LD4) -> Leds {
Leds {
leds: [led2.into(), led3.into(), led4.into()],
leds: [led_pin1.into(), led_pin2.into(), led_pin3.into()],
}
}
}
@ -72,14 +74,14 @@ macro_rules! ctor {
ctor!(LD2, LD3, LD4);
impl Led {
/// Turns the LED off
/// Turns the LED off. Setting the pin high actually turns the LED off
pub fn off(&mut self) {
self.pin.set_low().ok();
self.pin.set_high().ok();
}
/// Turns the LED on
/// Turns the LED on. Setting the pin low actually turns the LED on
pub fn on(&mut self) {
self.pin.set_high().ok();
self.pin.set_low().ok();
}
/// Toggles the LED

View File

@ -1,3 +1,4 @@
#![no_std]
pub mod button;
pub mod leds;