Add a stopwatch example

Signed-off-by: Daniel Egger <daniel@eggers-club.de>
trying.tmp
Daniel Egger 4 years ago
parent df7c6e7c8c
commit 2a561a279f

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
### Added
- Another example resembling a stop watch controlled via serial interface
### Fixed
- Incorrect PLLSRC bits when using HSE

@ -80,6 +80,10 @@ opt-level = "s"
name = "blinky_timer_irq"
required-features = ["stm32f072", "rt"]
[[example]]
name = "serial_stopwatch"
required-features = ["stm32f072", "rt"]
[[example]]
name = "dac"
required-features = ["stm32f072"]

@ -0,0 +1,121 @@
#![no_main]
#![no_std]
use panic_halt as _;
use stm32f0xx_hal as hal;
use crate::hal::{
prelude::*,
serial::Serial,
stm32::{interrupt, Interrupt, Peripherals, TIM7},
timers::{Event, Timer},
};
use core::cell::RefCell;
use core::fmt::Write as _;
use core::ops::DerefMut;
use cortex_m::{interrupt::Mutex, peripheral::Peripherals as c_m_Peripherals};
use cortex_m_rt::entry;
// Make timer interrupt registers globally available
static GINT: Mutex<RefCell<Option<Timer<TIM7>>>> = Mutex::new(RefCell::new(None));
#[derive(Copy, Clone)]
struct Time {
seconds: u32,
millis: u16,
}
static TIME: Mutex<RefCell<Time>> = Mutex::new(RefCell::new(Time {
seconds: 0,
millis: 0,
}));
// Define an interupt handler, i.e. function to call when interrupt occurs. Here if our external
// interrupt trips when the timer timed out
#[interrupt]
fn TIM7() {
cortex_m::interrupt::free(|cs| {
// Move LED pin here, leaving a None in its place
GINT.borrow(cs)
.borrow_mut()
.deref_mut()
.as_mut()
.unwrap()
.wait()
.ok();
let mut time = TIME.borrow(cs).borrow_mut();
time.millis += 1;
if time.millis == 1000 {
time.millis = 0;
time.seconds += 1;
}
});
}
#[entry]
fn main() -> ! {
if let (Some(p), Some(cp)) = (Peripherals::take(), c_m_Peripherals::take()) {
let mut serial = cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().sysclk(48.mhz()).freeze(&mut flash);
// Use USART2 with PA2 and PA3 as serial port
let gpioa = p.GPIOA.split(&mut rcc);
let tx = gpioa.pa2.into_alternate_af1(cs);
let rx = gpioa.pa3.into_alternate_af1(cs);
// Set up a timer expiring every millisecond
let mut timer = Timer::tim7(p.TIM7, 1000.hz(), &mut rcc);
// Generate an interrupt when the timer expires
timer.listen(Event::TimeOut);
// Move the timer into our global storage
*GINT.borrow(cs).borrow_mut() = Some(timer);
// Enable TIM7 IRQ, set prio 1 and clear any pending IRQs
let mut nvic = cp.NVIC;
unsafe {
nvic.set_priority(Interrupt::TIM7, 1);
cortex_m::peripheral::NVIC::unmask(Interrupt::TIM7);
}
cortex_m::peripheral::NVIC::unpend(Interrupt::TIM7);
// Set up our serial port
Serial::usart2(p.USART2, (tx, rx), 115_200.bps(), &mut rcc)
});
// Print a welcome message
writeln!(
serial,
"Welcome to the stop watch, hit any key to see the current value and 0 to reset\r",
)
.ok();
loop {
// Wait for reception of a single byte
let received = nb::block!(serial.read()).unwrap();
let time = cortex_m::interrupt::free(|cs| {
let mut time = TIME.borrow(cs).borrow_mut();
// If we received a 0, reset the time
if received == b'0' {
time.millis = 0;
time.seconds = 0;
}
*time
});
// Print the current time
writeln!(serial, "{}.{:03}s\r", time.seconds, time.millis).ok();
}
}
loop {
continue;
}
}
Loading…
Cancel
Save