Skip to content

Commit 7099b07

Browse files
authored
Merge pull request #179 from burrbull/counter
Port timers from f4xx-hal
2 parents a484539 + 5c74b25 commit 7099b07

24 files changed

+2883
-339
lines changed

Cargo.toml

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ rand_core = "0.6"
2929
bxcan = "0.6"
3030
bare-metal = "1.0"
3131
fugit = "0.3.5"
32+
fugit-timer = "0.1.3"
33+
bitflags = "1.3.2"
34+
rtic-monotonic = { version = "1.0", optional = true }
3235

3336
[dependencies.time]
3437
version = "0.3"
@@ -104,6 +107,8 @@ has-can = []
104107
gpioj = []
105108
gpiok = []
106109

110+
rtic = ["rt", "rtic-monotonic"]
111+
107112
[profile.dev]
108113
incremental = false
109114
codegen-units = 1
@@ -114,12 +119,16 @@ debug = true
114119
lto = true
115120

116121
[[example]]
117-
name = "blinky_delay"
118-
required-features = ["stm32f746", "rt"]
122+
name = "blinky"
123+
required-features = ["device-selected", "rt"]
119124

120125
[[example]]
121-
name = "blinky"
122-
required-features = ["stm32f746", "rt"]
126+
name = "delay-syst-blinky"
127+
required-features = ["device-selected"]
128+
129+
[[example]]
130+
name = "delay-timer-blinky"
131+
required-features = ["device-selected"]
123132

124133
[[example]]
125134
name = "flash"
@@ -134,15 +143,15 @@ name = "hello"
134143
required-features = ["stm32f746", "rt"]
135144

136145
[[example]]
137-
name = "serial_delay"
138-
required-features = ["stm32f746", "rt"]
146+
name = "rtic-tick"
147+
required-features = ["device-selected", "rtic"]
139148

140149
[[example]]
141-
name = "serial_echo"
150+
name = "serial_delay"
142151
required-features = ["stm32f746", "rt"]
143152

144153
[[example]]
145-
name = "timer"
154+
name = "serial_echo"
146155
required-features = ["stm32f746", "rt"]
147156

148157
[[example]]

examples/blinky-timer-irq.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//! blinky timer using interrupts on TIM2, adapted from blinky_timer_irq.rs example from
2+
//! stm32f1xx-hal
3+
//!
4+
//! This assumes that a LED is connected to pa5 (sck/d13) as is the case on most nucleo board.
5+
6+
#![no_main]
7+
#![no_std]
8+
9+
use panic_halt as _;
10+
11+
use stm32f7xx_hal as hal;
12+
13+
use crate::hal::{
14+
gpio::{self, Output, PushPull},
15+
pac::{interrupt, Interrupt, Peripherals, TIM2},
16+
prelude::*,
17+
timer::{CounterUs, Event},
18+
};
19+
20+
use core::cell::RefCell;
21+
use cortex_m::interrupt::Mutex;
22+
use cortex_m_rt::entry;
23+
24+
// NOTE You can uncomment 'hprintln' here and in the code below for a bit more
25+
// verbosity at runtime, at the cost of throwing off the timing of the blink
26+
// (using 'semihosting' for printing debug info anywhere slows program
27+
// execution down)
28+
//use cortex_m_semihosting::hprintln;
29+
30+
// A type definition for the GPIO pin to be used for our LED
31+
// For the onboard nucleo LED, use PA5 or PB13 depending your model
32+
type LedPin = gpio::PA5<Output<PushPull>>;
33+
34+
// Make LED pin globally available
35+
static G_LED: Mutex<RefCell<Option<LedPin>>> = Mutex::new(RefCell::new(None));
36+
37+
// Make timer interrupt registers globally available
38+
static G_TIM: Mutex<RefCell<Option<CounterUs<TIM2>>>> = Mutex::new(RefCell::new(None));
39+
40+
// Define an interupt handler, i.e. function to call when interrupt occurs.
41+
// This specific interrupt will "trip" when the timer TIM2 times out
42+
#[interrupt]
43+
fn TIM2() {
44+
static mut LED: Option<LedPin> = None;
45+
static mut TIM: Option<CounterUs<TIM2>> = None;
46+
47+
let led = LED.get_or_insert_with(|| {
48+
cortex_m::interrupt::free(|cs| {
49+
// Move LED pin here, leaving a None in its place
50+
G_LED.borrow(cs).replace(None).unwrap()
51+
})
52+
});
53+
54+
let tim = TIM.get_or_insert_with(|| {
55+
cortex_m::interrupt::free(|cs| {
56+
// Move LED pin here, leaving a None in its place
57+
G_TIM.borrow(cs).replace(None).unwrap()
58+
})
59+
});
60+
61+
let _ = led.toggle();
62+
let _ = tim.wait();
63+
}
64+
65+
#[entry]
66+
fn main() -> ! {
67+
let dp = Peripherals::take().unwrap();
68+
69+
let rcc = dp.RCC.constrain();
70+
let clocks = rcc.cfgr.sysclk(16.MHz()).pclk1(8.MHz()).freeze();
71+
72+
// Configure PA5 pin to blink LED
73+
let gpioa = dp.GPIOA.split();
74+
let mut led = gpioa.pa5.into_push_pull_output();
75+
let _ = led.set_high(); // Turn off
76+
77+
// Move the pin into our global storage
78+
cortex_m::interrupt::free(|cs| *G_LED.borrow(cs).borrow_mut() = Some(led));
79+
80+
// Set up a timer expiring after 1s
81+
let mut timer = dp.TIM2.counter(&clocks);
82+
timer.start(1.secs()).unwrap();
83+
84+
// Generate an interrupt when the timer expires
85+
timer.listen(Event::Update);
86+
87+
// Move the timer into our global storage
88+
cortex_m::interrupt::free(|cs| *G_TIM.borrow(cs).borrow_mut() = Some(timer));
89+
90+
//enable TIM2 interrupt
91+
unsafe {
92+
cortex_m::peripheral::NVIC::unmask(Interrupt::TIM2);
93+
}
94+
95+
#[allow(clippy::empty_loop)]
96+
loop {
97+
// Uncomment if you want to make controller sleep
98+
// cortex_m::asm::wfi();
99+
}
100+
}

examples/blinky_delay.rs

Lines changed: 0 additions & 37 deletions
This file was deleted.

examples/delay-syst-blinky.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//! Demonstrate the use of a blocking `Delay` using the SYST (sysclock) timer.
2+
3+
#![deny(unsafe_code)]
4+
#![allow(clippy::empty_loop)]
5+
#![no_main]
6+
#![no_std]
7+
8+
// Halt on panic
9+
use panic_halt as _; // panic handler
10+
11+
use cortex_m_rt::entry;
12+
use stm32f7xx_hal as hal;
13+
14+
use crate::hal::{pac, prelude::*};
15+
16+
#[entry]
17+
fn main() -> ! {
18+
if let (Some(dp), Some(cp)) = (
19+
pac::Peripherals::take(),
20+
cortex_m::peripheral::Peripherals::take(),
21+
) {
22+
// Set up the LED. On the Nucleo-446RE it's connected to pin PA5.
23+
let gpioa = dp.GPIOA.split();
24+
let mut led = gpioa.pa5.into_push_pull_output();
25+
26+
// Set up the system clock. We want to run at 48MHz for this one.
27+
let rcc = dp.RCC.constrain();
28+
let clocks = rcc.cfgr.sysclk(48.MHz()).freeze();
29+
30+
// Create a delay abstraction based on SysTick
31+
let mut delay = cp.SYST.delay(&clocks);
32+
33+
loop {
34+
// On for 1s, off for 1s.
35+
led.set_high();
36+
delay.delay_ms(1000_u32);
37+
led.set_low();
38+
delay.delay_ms(1000_u32);
39+
}
40+
}
41+
42+
loop {}
43+
}

examples/delay-timer-blinky.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//! Demonstrate the use of a blocking `Delay` using TIM5 general-purpose timer.
2+
3+
#![deny(unsafe_code)]
4+
#![allow(clippy::empty_loop)]
5+
#![no_main]
6+
#![no_std]
7+
8+
// Halt on panic
9+
use panic_halt as _; // panic handler
10+
11+
use cortex_m_rt::entry;
12+
use stm32f7xx_hal as hal;
13+
14+
use crate::hal::{
15+
pac,
16+
prelude::*,
17+
rcc::{HSEClock, HSEClockMode},
18+
};
19+
20+
#[entry]
21+
fn main() -> ! {
22+
if let (Some(dp), Some(_cp)) = (
23+
pac::Peripherals::take(),
24+
cortex_m::peripheral::Peripherals::take(),
25+
) {
26+
// Set up the LED. On the Mini-F4 it's connected to pin PC13.
27+
let gpioc = dp.GPIOC.split();
28+
let mut led = gpioc.pc13.into_push_pull_output();
29+
30+
// Set up the system clock. We want to run at 48MHz for this one.
31+
let rcc = dp.RCC.constrain();
32+
let clocks = rcc
33+
.cfgr
34+
.hse(HSEClock::new(25.MHz(), HSEClockMode::Bypass))
35+
.sysclk(48.MHz())
36+
.freeze();
37+
38+
// Create a delay abstraction based on general-pupose 32-bit timer TIM5
39+
let mut delay = dp.TIM5.delay_us(&clocks);
40+
41+
loop {
42+
// On for 1s, off for 3s.
43+
led.set_high();
44+
// Use `embedded_hal::DelayMs` trait
45+
delay.delay_ms(1000_u32);
46+
led.set_low();
47+
// or use `fugit::ExtU32` trait
48+
delay.delay(3.secs());
49+
}
50+
}
51+
52+
loop {}
53+
}

examples/fmc.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use core::{mem, slice};
2121
use cortex_m_rt::entry;
2222
use cortex_m_semihosting::hprintln;
2323
use stm32_fmc::devices::is42s16400j_7;
24-
use stm32f7xx_hal::{delay::Delay, gpio::Speed, pac, prelude::*};
24+
use stm32f7xx_hal::{gpio::Speed, pac, prelude::*};
2525

2626
/// Configure pins for the FMC controller
2727
macro_rules! fmc_pins {
@@ -43,8 +43,8 @@ fn main() -> ! {
4343
let dp = pac::Peripherals::take().unwrap();
4444

4545
// Get the delay provider.
46-
let clocks = dp.RCC.constrain().cfgr.sysclk(216_000_000.Hz()).freeze();
47-
let mut delay = Delay::new(cp.SYST, &clocks);
46+
let clocks = dp.RCC.constrain().cfgr.sysclk(216.MHz()).freeze();
47+
let mut delay = cp.SYST.delay(&clocks);
4848

4949
// IO
5050
let gpioc = dp.GPIOC.split();

examples/pwm-sinus.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#![deny(unsafe_code)]
2+
#![no_main]
3+
#![no_std]
4+
5+
// Halt on panic
6+
use panic_halt as _;
7+
8+
use core::f32::consts::FRAC_PI_2;
9+
use cortex_m_rt::entry;
10+
use micromath::F32Ext;
11+
use stm32f7xx_hal::{
12+
pac,
13+
prelude::*,
14+
rcc::{HSEClock, HSEClockMode},
15+
timer::Channel,
16+
};
17+
18+
#[entry]
19+
fn main() -> ! {
20+
if let Some(dp) = pac::Peripherals::take() {
21+
// Set up the system clock.
22+
let rcc = dp.RCC.constrain();
23+
let clocks = rcc
24+
.cfgr
25+
.hse(HSEClock::new(25.MHz(), HSEClockMode::Bypass))
26+
.freeze();
27+
28+
let gpioa = dp.GPIOA.split();
29+
let channels = (gpioa.pa8.into_alternate(), gpioa.pa9.into_alternate());
30+
31+
let mut pwm = dp.TIM1.pwm_us(channels, 100.micros(), &clocks);
32+
let mut counter = dp.TIM2.counter_us(&clocks);
33+
let max_duty = pwm.get_max_duty();
34+
35+
const N: usize = 50;
36+
let mut sin_a = [0_u16; N + 1];
37+
// Fill sinus array
38+
let a = FRAC_PI_2 / (N as f32);
39+
for (i, b) in sin_a.iter_mut().enumerate() {
40+
let angle = a * (i as f32);
41+
*b = (angle.sin() * (max_duty as f32)) as u16;
42+
}
43+
44+
counter.start(100.micros()).unwrap();
45+
pwm.enable(Channel::C1);
46+
pwm.enable(Channel::C2);
47+
let mut i = 0;
48+
loop {
49+
if i == 0 {
50+
pwm.set_duty(Channel::C2, 0);
51+
}
52+
if i == 2 * N {
53+
pwm.set_duty(Channel::C1, 0);
54+
}
55+
if i < N {
56+
pwm.set_duty(Channel::C1, sin_a[i]);
57+
} else if i < 2 * N {
58+
pwm.set_duty(Channel::C1, sin_a[2 * N - i]);
59+
} else if i < 3 * N {
60+
pwm.set_duty(Channel::C2, sin_a[i - 2 * N]);
61+
} else {
62+
pwm.set_duty(Channel::C2, sin_a[4 * N - i]);
63+
}
64+
nb::block!(counter.wait()).unwrap();
65+
i += 1;
66+
if i == 4 * N {
67+
i -= 4 * N;
68+
}
69+
}
70+
}
71+
72+
loop {
73+
cortex_m::asm::nop();
74+
}
75+
}

0 commit comments

Comments
 (0)