Skip to content

Commit 13e04bd

Browse files
bors[bot]Disasm
andauthored
Merge #257
257: Provide a delay driver based on SysTick r=thalesfragoso a=Disasm Co-authored-by: Vadim Kaushan <[email protected]>
2 parents 6dcd9f4 + 2b50dce commit 13e04bd

File tree

5 files changed

+126
-0
lines changed

5 files changed

+126
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1313
various NVIC functions, replacing the previous use of `Nr` from bare-metal.
1414
- Associated const `PTR` is introduced to Core Peripherals to
1515
eventually replace the existing `ptr()` API.
16+
- A delay driver based on SysTick.
1617

1718
## [v0.6.2] - 2020-01-12
1819

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ links = "cortex-m" # prevent multiple versions of this crate to be linked toget
1919
bare-metal = { version = "0.2.0", features = ["const-fn"] }
2020
volatile-register = "0.2.0"
2121
bitfield = "0.13.2"
22+
embedded-hal = "0.2.4"
2223

2324
[package.metadata.docs.rs]
2425
targets = [

src/delay.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
//! A delay driver based on SysTick.
2+
3+
use crate::peripheral::{syst::SystClkSource, SYST};
4+
use embedded_hal::blocking::delay::{DelayMs, DelayUs};
5+
6+
/// System timer (SysTick) as a delay provider.
7+
pub struct Delay {
8+
syst: SYST,
9+
ahb_frequency: u32,
10+
}
11+
12+
impl Delay {
13+
/// Configures the system timer (SysTick) as a delay provider.
14+
///
15+
/// `ahb_frequency` is a frequency of the AHB bus in Hz.
16+
#[inline]
17+
pub fn new(mut syst: SYST, ahb_frequency: u32) -> Self {
18+
syst.set_clock_source(SystClkSource::Core);
19+
20+
Delay { syst, ahb_frequency }
21+
}
22+
23+
/// Releases the system timer (SysTick) resource.
24+
#[inline]
25+
pub fn free(self) -> SYST {
26+
self.syst
27+
}
28+
29+
fn _delay_us(&mut self, us: u32) {
30+
let ticks = (us as u64) * (self.ahb_frequency as u64) / 1_000_000;
31+
32+
let full_cycles = ticks >> 24;
33+
if full_cycles > 0 {
34+
self.syst.set_reload(0xffffff);
35+
self.syst.clear_current();
36+
self.syst.enable_counter();
37+
38+
for _ in 0..full_cycles {
39+
while !self.syst.has_wrapped() {}
40+
}
41+
}
42+
43+
let ticks = (ticks & 0xffffff) as u32;
44+
if ticks > 1 {
45+
self.syst.set_reload(ticks - 1);
46+
self.syst.clear_current();
47+
self.syst.enable_counter();
48+
49+
while !self.syst.has_wrapped() {}
50+
}
51+
52+
self.syst.disable_counter();
53+
}
54+
}
55+
56+
impl DelayMs<u32> for Delay {
57+
#[inline]
58+
fn delay_ms(&mut self, mut ms: u32) {
59+
// 4294967 is the highest u32 value which you can multiply by 1000 without overflow
60+
while ms > 4294967 {
61+
self.delay_us(4294967000u32);
62+
ms -= 4294967;
63+
}
64+
self.delay_us(ms * 1_000);
65+
}
66+
}
67+
68+
// This is a workaround to allow `delay_ms(42)` construction without specifying a type.
69+
impl DelayMs<i32> for Delay {
70+
#[inline(always)]
71+
fn delay_ms(&mut self, ms: i32) {
72+
assert!(ms >= 0);
73+
self.delay_ms(ms as u32);
74+
}
75+
}
76+
77+
impl DelayMs<u16> for Delay {
78+
#[inline(always)]
79+
fn delay_ms(&mut self, ms: u16) {
80+
self.delay_ms(u32::from(ms));
81+
}
82+
}
83+
84+
impl DelayMs<u8> for Delay {
85+
#[inline(always)]
86+
fn delay_ms(&mut self, ms: u8) {
87+
self.delay_ms(u32::from(ms));
88+
}
89+
}
90+
91+
impl DelayUs<u32> for Delay {
92+
#[inline]
93+
fn delay_us(&mut self, us: u32) {
94+
self._delay_us(us);
95+
}
96+
}
97+
98+
// This is a workaround to allow `delay_us(42)` construction without specifying a type.
99+
impl DelayUs<i32> for Delay {
100+
#[inline(always)]
101+
fn delay_us(&mut self, us: i32) {
102+
assert!(us >= 0);
103+
self.delay_us(us as u32);
104+
}
105+
}
106+
107+
impl DelayUs<u16> for Delay {
108+
#[inline(always)]
109+
fn delay_us(&mut self, us: u16) {
110+
self.delay_us(u32::from(us))
111+
}
112+
}
113+
114+
impl DelayUs<u8> for Delay {
115+
#[inline(always)]
116+
fn delay_us(&mut self, us: u8) {
117+
self.delay_us(u32::from(us))
118+
}
119+
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,12 @@ mod macros;
6161
pub mod asm;
6262
#[cfg(armv8m)]
6363
pub mod cmse;
64+
pub mod delay;
6465
pub mod interrupt;
6566
#[cfg(all(not(armv6m), not(armv8m_base)))]
6667
pub mod itm;
6768
pub mod peripheral;
69+
pub mod prelude;
6870
pub mod register;
6971

7072
pub use crate::peripheral::Peripherals;

src/prelude.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
//! Prelude
2+
3+
pub use embedded_hal::prelude::*;

0 commit comments

Comments
 (0)