Skip to content

Commit 0ff6b0c

Browse files
authored
Merge pull request #100 from stm32-rs/stopwatch-example
Stopwatch example
2 parents e6ae626 + 2a561a2 commit 0ff6b0c

File tree

4 files changed

+133
-3
lines changed

4 files changed

+133
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Another example resembling a stop watch controlled via serial interface
13+
1014
### Fixed
1115

1216
- Incorrect PLLSRC bits when using HSE

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ opt-level = "s"
8080
name = "blinky_timer_irq"
8181
required-features = ["stm32f072", "rt"]
8282

83+
[[example]]
84+
name = "serial_stopwatch"
85+
required-features = ["stm32f072", "rt"]
86+
8387
[[example]]
8488
name = "dac"
8589
required-features = ["stm32f072"]

examples/flash_systick_fancier.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use cortex_m::{interrupt::Mutex, peripheral::syst::SystClkSource::Core, Peripher
1111
use cortex_m_rt::{entry, exception};
1212

1313
use core::cell::RefCell;
14+
use core::mem::swap;
1415

1516
// A type definition for the GPIO pin to be used for our LED
1617
type LEDPIN = gpiob::PB3<Output<PushPull>>;
@@ -31,7 +32,7 @@ fn main() -> ! {
3132
let led = gpioa.pb3.into_push_pull_output(cs);
3233

3334
// Transfer GPIO into a shared structure
34-
*GPIO.borrow(cs).borrow_mut() = Some(led);
35+
swap(&mut Some(led), &mut GPIO.borrow(cs).borrow_mut());
3536

3637
let mut syst = cp.SYST;
3738

@@ -88,8 +89,8 @@ fn SysTick() {
8889
else {
8990
// Enter critical section
9091
cortex_m::interrupt::free(|cs| {
91-
// Move LED pin here, leaving a None in its place
92-
LED.replace(GPIO.borrow(cs).replace(None).unwrap());
92+
// Swap globally stored data with SysTick private data
93+
swap(LED, &mut GPIO.borrow(cs).borrow_mut());
9394
});
9495
}
9596
}

examples/serial_stopwatch.rs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
use panic_halt as _;
5+
6+
use stm32f0xx_hal as hal;
7+
8+
use crate::hal::{
9+
prelude::*,
10+
serial::Serial,
11+
stm32::{interrupt, Interrupt, Peripherals, TIM7},
12+
timers::{Event, Timer},
13+
};
14+
use core::cell::RefCell;
15+
use core::fmt::Write as _;
16+
use core::ops::DerefMut;
17+
18+
use cortex_m::{interrupt::Mutex, peripheral::Peripherals as c_m_Peripherals};
19+
use cortex_m_rt::entry;
20+
21+
// Make timer interrupt registers globally available
22+
static GINT: Mutex<RefCell<Option<Timer<TIM7>>>> = Mutex::new(RefCell::new(None));
23+
24+
#[derive(Copy, Clone)]
25+
struct Time {
26+
seconds: u32,
27+
millis: u16,
28+
}
29+
30+
static TIME: Mutex<RefCell<Time>> = Mutex::new(RefCell::new(Time {
31+
seconds: 0,
32+
millis: 0,
33+
}));
34+
35+
// Define an interupt handler, i.e. function to call when interrupt occurs. Here if our external
36+
// interrupt trips when the timer timed out
37+
#[interrupt]
38+
fn TIM7() {
39+
cortex_m::interrupt::free(|cs| {
40+
// Move LED pin here, leaving a None in its place
41+
GINT.borrow(cs)
42+
.borrow_mut()
43+
.deref_mut()
44+
.as_mut()
45+
.unwrap()
46+
.wait()
47+
.ok();
48+
let mut time = TIME.borrow(cs).borrow_mut();
49+
time.millis += 1;
50+
if time.millis == 1000 {
51+
time.millis = 0;
52+
time.seconds += 1;
53+
}
54+
});
55+
}
56+
57+
#[entry]
58+
fn main() -> ! {
59+
if let (Some(p), Some(cp)) = (Peripherals::take(), c_m_Peripherals::take()) {
60+
let mut serial = cortex_m::interrupt::free(move |cs| {
61+
let mut flash = p.FLASH;
62+
let mut rcc = p.RCC.configure().sysclk(48.mhz()).freeze(&mut flash);
63+
64+
// Use USART2 with PA2 and PA3 as serial port
65+
let gpioa = p.GPIOA.split(&mut rcc);
66+
let tx = gpioa.pa2.into_alternate_af1(cs);
67+
let rx = gpioa.pa3.into_alternate_af1(cs);
68+
69+
// Set up a timer expiring every millisecond
70+
let mut timer = Timer::tim7(p.TIM7, 1000.hz(), &mut rcc);
71+
72+
// Generate an interrupt when the timer expires
73+
timer.listen(Event::TimeOut);
74+
75+
// Move the timer into our global storage
76+
*GINT.borrow(cs).borrow_mut() = Some(timer);
77+
78+
// Enable TIM7 IRQ, set prio 1 and clear any pending IRQs
79+
let mut nvic = cp.NVIC;
80+
unsafe {
81+
nvic.set_priority(Interrupt::TIM7, 1);
82+
cortex_m::peripheral::NVIC::unmask(Interrupt::TIM7);
83+
}
84+
cortex_m::peripheral::NVIC::unpend(Interrupt::TIM7);
85+
86+
// Set up our serial port
87+
Serial::usart2(p.USART2, (tx, rx), 115_200.bps(), &mut rcc)
88+
});
89+
90+
// Print a welcome message
91+
writeln!(
92+
serial,
93+
"Welcome to the stop watch, hit any key to see the current value and 0 to reset\r",
94+
)
95+
.ok();
96+
97+
loop {
98+
// Wait for reception of a single byte
99+
let received = nb::block!(serial.read()).unwrap();
100+
101+
let time = cortex_m::interrupt::free(|cs| {
102+
let mut time = TIME.borrow(cs).borrow_mut();
103+
104+
// If we received a 0, reset the time
105+
if received == b'0' {
106+
time.millis = 0;
107+
time.seconds = 0;
108+
}
109+
110+
*time
111+
});
112+
113+
// Print the current time
114+
writeln!(serial, "{}.{:03}s\r", time.seconds, time.millis).ok();
115+
}
116+
}
117+
118+
loop {
119+
continue;
120+
}
121+
}

0 commit comments

Comments
 (0)