Skip to content

Commit 36ef53a

Browse files
authored
Merge pull request #267 from Sh3Rm4n/timer
Rework Timer
2 parents 47114b3 + 4ae3b73 commit 36ef53a

File tree

15 files changed

+970
-480
lines changed

15 files changed

+970
-480
lines changed

CHANGELOG.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1717
### Added
1818

1919
- Readd MonoTimer. This was accidentally removed before. ([#247])
20+
- Different to before, frequency() and now() now do not consume the MonoTimer.
21+
`&self` is used instead. ([#267])
2022
- Basic serial implementation also available for UART4 and UART5 ([#246])
2123
- Implement serial DMA also for Serial ([#246])
2224
- Add [`enumset`][] as a optional dependency, which allow more ergonomic functions
@@ -36,7 +38,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
3638
for configuration purposes. ([#253])
3739
- Add an associated const to `serial::Instance` to return the corresponding
3840
`pac::Interrupt`-number, which is useful to `unmask()` interrupts.
39-
An `nvic()` function to `Serial` was also added for convinience. ([#253])
41+
An `interrupt()` function to `Serial` was also added for convinience. ([#253])
4042
- Add a `Serial::is_busy()` function to check, if the serial device is busy.
4143
Useful to block on this function, e.g. `while serial.is_busy() {}`. ([#253])
4244
- Add `BaudTable` a convinience wrapper around `Baud` to configure the `Serial`
@@ -51,6 +53,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
5153
Almost all important types should now be supported. ([#265])
5254
- Add a `free()` function to the RTC implementation to retrieve the passed-in
5355
peripheral. ([#266])
56+
- Implement an API to return the corresponding interrupt number of timer through
57+
the newly introduced `InterruptNumber` trait, where the `Interrupt` is held
58+
as an associated const. ([#267])
59+
- Depending on the timer one `Interrupt` or a bundle of `InterruptTypes` is
60+
returned.
61+
- On the bases of these interrupts, the interrupt controller (NVIC) can
62+
be set to mask or unmask these interrupts.
63+
- Implement the `embedded-hal::timer::Cancel` trait for timers. ([#267])
64+
- Add `use_pll` to `CFGR` - the clock configuration - to force to use the PLL
65+
source for the systemclock. Also `Clocks::pllclk()` was introduced to be able
66+
to check, whether PLL is used.
5467

5568
[`enumset`]: https://crates.io/crates/enumset
5669

@@ -117,6 +130,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
117130
- Rename `CkMode` to `ClockMode` ([#266])
118131
- Rename `stm32-usbd` feature to `usb`. `stm32-usbd` is still used as a
119132
dependency. ([#271])
133+
- Rework the timer implementation: ([#267])
134+
- `PclkSrc` trait was removed in favor of generic `Instance` trait, which
135+
is a common ground for all available timers.
136+
- `Timer::tim1` and so on are renamed to `Timer::new`
137+
- The implementation of the timers are corrected to better represent the
138+
avaibilities of timers of the hardware.
139+
- `Timer::new` now does not take a timeout value. This means, that the
140+
timer will now not be started automatically and one has to explicitly call
141+
`start()`.
120142

121143
## [v0.7.0] - 2021-06-18
122144

@@ -444,6 +466,7 @@ let clocks = rcc
444466

445467
[#271]: https://github.com/stm32-rs/stm32f3xx-hal/pull/271
446468
[#270]: https://github.com/stm32-rs/stm32f3xx-hal/pull/270
469+
[#267]: https://github.com/stm32-rs/stm32f3xx-hal/pull/267
447470
[#266]: https://github.com/stm32-rs/stm32f3xx-hal/pull/266
448471
[#265]: https://github.com/stm32-rs/stm32f3xx-hal/pull/265
449472
[#264]: https://github.com/stm32-rs/stm32f3xx-hal/pull/264

examples/gpio_interrupts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn main() -> ! {
4747
syscfg.select_exti_interrupt_source(&user_button);
4848
user_button.trigger_on_edge(&mut exti, Edge::Rising);
4949
user_button.enable_interrupt(&mut exti);
50-
let interrupt_num = user_button.nvic(); // hal::pac::Interrupt::EXTI0
50+
let interrupt_num = user_button.interrupt(); // hal::pac::Interrupt::EXTI0
5151

5252
// Moving ownership to the global BUTTON so we can clear the interrupt pending bit.
5353
cortex_m::interrupt::free(|cs| *BUTTON.borrow(cs).borrow_mut() = Some(user_button));

src/gpio.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ where
592592
/// This is also useful for all other [`cortex_m::peripheral::NVIC`] functions.
593593
// TODO(Sh3rm4n): It would be cool to have this either const or have a const function.
594594
// But this is currenlty not possible, because index() is runtime defined.
595-
pub fn nvic(&self) -> Interrupt {
595+
pub fn interrupt(&self) -> Interrupt {
596596
match self.index.index() {
597597
0 => Interrupt::EXTI0,
598598
1 => Interrupt::EXTI1,

src/interrupts.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//! Common Interrupt interface defintions shared between peipherals.
2+
3+
/// A common interrupt number interface, which returns the associated interrupt
4+
/// of the peripheral.
5+
///
6+
/// Used to unmask / enable the interrupt with [`cortex_m::peripheral::NVIC::unmask()`].
7+
/// This is useful for all `cortex_m::peripheral::INTERRUPT` functions.
8+
pub trait InterruptNumber {
9+
/// The type used to represent the Interrupt Number.
10+
///
11+
/// This type of interrupt should be compatible with [`cortex_m::peripheral::NVIC`].
12+
type Interrupt;
13+
14+
/// The assocaited constant of the interrupt
15+
const INTERRUPT: Self::Interrupt;
16+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ pub mod dma;
176176
pub mod flash;
177177
pub mod gpio;
178178
pub mod i2c;
179+
pub mod interrupts;
179180
pub mod prelude;
180181
pub mod pwm;
181182
pub mod rcc;

src/prelude.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
//! use stm32f3xx-hal::prelude::*;
99
//! ```
1010
11-
#[cfg(any(feature = "stm32f302", feature = "stm32f303"))]
1211
pub use crate::dma::DmaExt as _stm32f3xx_hal_dma_DmaExt;
1312
pub use crate::flash::FlashExt as _stm32f3xx_hal_flash_FlashExt;
1413
pub use crate::gpio::GpioExt as _stm32f3xx_hal_gpio_GpioExt;

src/rcc.rs

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -261,17 +261,32 @@ impl BDCR {
261261
/// let rcc = dp.RCC.constrain();
262262
/// use_cfgr(&mut rcc.cfgr)
263263
/// ```
264-
#[derive(Default)]
265264
pub struct CFGR {
266265
hse: Option<u32>,
267266
hse_bypass: bool,
267+
pll_bypass: bool,
268268
css: bool,
269269
hclk: Option<u32>,
270270
pclk1: Option<u32>,
271271
pclk2: Option<u32>,
272272
sysclk: Option<u32>,
273273
}
274274

275+
impl Default for CFGR {
276+
fn default() -> Self {
277+
Self {
278+
hse: None,
279+
hse_bypass: false,
280+
pll_bypass: true,
281+
css: false,
282+
hclk: None,
283+
pclk1: None,
284+
pclk2: None,
285+
sysclk: None,
286+
}
287+
}
288+
}
289+
275290
pub(crate) struct PllConfig {
276291
src: cfgr::PLLSRC_A,
277292
mul: cfgr::PLLMUL_A,
@@ -350,6 +365,12 @@ impl CFGR {
350365
self
351366
}
352367

368+
/// Set this to disallow bypass the PLLCLK for the systemclock generation.
369+
pub fn use_pll(mut self) -> Self {
370+
self.pll_bypass = false;
371+
self
372+
}
373+
353374
/// Enable `HSE` bypass.
354375
///
355376
/// Uses user provided clock signal instead of an external oscillator.
@@ -464,13 +485,7 @@ impl CFGR {
464485
///
465486
/// `HSI` is simpler to calculate, but the possible system clocks are less than `HSE`, because the
466487
/// division is not configurable.
467-
#[cfg(not(any(
468-
feature = "stm32f302xd",
469-
feature = "stm32f302xe",
470-
feature = "stm32f303xd",
471-
feature = "stm32f303xe",
472-
feature = "stm32f398"
473-
)))]
488+
#[cfg(not(feature = "gpio-f303e"))]
474489
fn calc_pll(&self, sysclk: u32) -> (u32, PllConfig) {
475490
let pllsrcclk = self.hse.unwrap_or(HSI.integer() / 2);
476491
// Get the optimal value for the pll divisor (PLL_DIV) and multiplier (PLL_MUL)
@@ -540,13 +555,7 @@ impl CFGR {
540555
///
541556
/// To determine the optimal values, the greatest common divisor is calculated and the
542557
/// limitations of the possible values are taken into considiration.
543-
#[cfg(any(
544-
feature = "stm32f302xd",
545-
feature = "stm32f302xe",
546-
feature = "stm32f303xd",
547-
feature = "stm32f303xe",
548-
feature = "stm32f398",
549-
))]
558+
#[cfg(feature = "gpio-f303e")]
550559
fn calc_pll(&self, sysclk: u32) -> (u32, PllConfig) {
551560
let pllsrcclk = self.hse.unwrap_or(HSI.integer());
552561

@@ -614,9 +623,11 @@ impl CFGR {
614623
// because the two valid USB clocks, 72 Mhz and 48 Mhz, can't be generated
615624
// directly from neither the internal rc (8 Mhz) nor the external
616625
// Oscillator (max 32 Mhz), without using the PLL.
617-
(Some(sysclk), Some(hse)) if sysclk == hse => (hse, cfgr::SW_A::HSE, None),
626+
(Some(sysclk), Some(hse)) if sysclk == hse && self.pll_bypass => {
627+
(hse, cfgr::SW_A::HSE, None)
628+
}
618629
// No need to use the PLL
619-
(Some(sysclk), None) if sysclk == HSI.integer() => {
630+
(Some(sysclk), None) if sysclk == HSI.integer() && self.pll_bypass => {
620631
(HSI.integer(), cfgr::SW_A::HSI, None)
621632
}
622633
(Some(sysclk), _) => {
@@ -770,6 +781,7 @@ impl CFGR {
770781
ppre2,
771782
sysclk: Hertz(sysclk),
772783
usbclk_valid,
784+
pll_bypass: self.pll_bypass,
773785
}
774786
}
775787
}
@@ -779,7 +791,6 @@ impl CFGR {
779791
/// The existence of this value indicates that the clock configuration can no longer be changed.
780792
/// This struct can be obtained via the [freeze](CFGR::freeze) method of the [CFGR](CFGR) struct.
781793
#[derive(Debug, Clone, Copy)]
782-
// #[cfg_attr(feature = "defmt", derive(defmt::Format))]
783794
pub struct Clocks {
784795
hclk: Hertz,
785796
pclk1: Hertz,
@@ -788,6 +799,7 @@ pub struct Clocks {
788799
ppre2: u8,
789800
sysclk: Hertz,
790801
usbclk_valid: bool,
802+
pll_bypass: bool,
791803
}
792804

793805
// TODO(Sh3Rm4n) Add defmt support for embedded-time!
@@ -797,18 +809,22 @@ impl defmt::Format for Clocks {
797809
// Format as hexadecimal.
798810
defmt::write!(
799811
f,
800-
"Clocks {{ hclk: {} Hz, pclk1: {} Hz, pclk2: {} Hz, ppre1: {:b}, ppre2: {:b}, sysclk: {} Hz, usbclk_valid: {} }}",
812+
"Clocks {{ hclk: {} Hz, pclk1: {} Hz, pclk2: {} Hz, ppre1: {:b}, ppre2: {:b}, sysclk: {} Hz, usbclk_valid: {}, pll_bypass: {} }}",
801813
self.hclk.integer(),
802814
self.pclk1.integer(),
803815
self.pclk2.integer(),
804816
self.ppre1,
805817
self.ppre2,
806818
self.sysclk.integer(),
807819
self.usbclk_valid,
820+
self.pll_bypass,
808821
);
809822
}
810823
}
811824

825+
// TODO(Sh3Rm4n): Think of some way to generlize APB1 and APB2 as types to then implement a method,
826+
// with which the ppre or pclk can be obtained by passing in the type of APB.
827+
// With that in place, some places of macro magic are not needed anymore.
812828
impl Clocks {
813829
/// Returns the frequency of the AHB
814830
pub fn hclk(&self) -> Hertz {
@@ -840,6 +856,19 @@ impl Clocks {
840856
self.sysclk
841857
}
842858

859+
/// Returns the PLL clock if configured, else it returns `None`.
860+
///
861+
/// The PLL clock is a source of the system clock, but it is not necessarily configured to be one.
862+
pub fn pllclk(&self) -> Option<Hertz> {
863+
if self.pll_bypass {
864+
None
865+
} else {
866+
// The PLLCLK is the same as the sysclk, beccause
867+
// the sysclk is using it as a source.
868+
Some(self.sysclk())
869+
}
870+
}
871+
843872
/// Returns whether the USBCLK clock frequency is valid for the USB peripheral
844873
///
845874
/// If the microcontroller does support USB, 48 Mhz or 72 Mhz have to be used

src/rtc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ impl Rtc {
8686

8787
/// Release the RTC peripheral
8888
pub fn free(self) -> RTC {
89+
// TODO(Sh3Rm4n): Disable peripheral before releasing it.
8990
self.regs
9091
}
9192

src/serial.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -722,9 +722,10 @@ where
722722
self.usart.isr.read().busy().bit_is_set()
723723
}
724724

725-
/// Obtain the assocated intterupt number for the serial peripheral.
725+
/// Obtain the associated interrupt number for the serial peripheral.
726726
///
727-
/// Used to unmask / enable the interrupt with [`cortex_m::peripheral::NVIC::unmask()`]
727+
///
728+
/// Used to unmask / enable the interrupt with [`cortex_m::peripheral::NVIC::unmask()`].
728729
/// This is useful for all `cortex_m::peripheral::INTERRUPT` functions.
729730
///
730731
/// # Note
@@ -734,15 +735,15 @@ where
734735
/// ```
735736
/// use cortex_m::peripheral::INTERRUPT;
736737
/// use stm32f3xx_hal::pac::USART1;
737-
/// use stm32f3xx_hal::serial::Instance;
738+
/// use stm32f3xx_hal::interrupt::InterruptNumber;
738739
///
739-
/// const interrupt: INTERRUPT = <USART1 as Instance>::INTERRUPT;
740+
/// const INTERRUPT: Interrupt = <USART1 as InterruptNumber>::INTERRUPT;
740741
/// ```
741742
///
742743
/// though this function can not be used in a const context.
743744
#[doc(alias = "unmask")]
744-
pub fn nvic() -> Interrupt {
745-
<Usart as Instance>::INTERRUPT
745+
pub fn interrupt(&self) -> <Usart as crate::interrupts::InterruptNumber>::Interrupt {
746+
<Usart as crate::interrupts::InterruptNumber>::INTERRUPT
746747
}
747748

748749
/// Enable the interrupt for the specified [`Event`].
@@ -759,7 +760,7 @@ where
759760

760761
/// Enable or disable the interrupt for the specified [`Event`].
761762
#[inline]
762-
pub fn configure_interrupt(&mut self, event: Event, enable: impl Into<Toggle>) -> &mut Self {
763+
pub fn configure_interrupt(&mut self, event: Event, enable: impl Into<Toggle>) {
763764
// Do a round way trip to be convert Into<Toggle> -> bool
764765
let enable: Toggle = enable.into();
765766
let enable: bool = enable.into();
@@ -781,7 +782,6 @@ where
781782
// Event::EndOfBlock => self.usart.cr1.modify(|_, w| w.eobie().bit(enable)),
782783
// Event::WakeupFromStopMode => self.usart.cr3.modify(|_, w| w.wufie().bit(enable)),
783784
};
784-
self
785785
}
786786

787787
/// Enable or disable interrupt for the specified [`Event`]s.
@@ -791,15 +791,13 @@ where
791791
/// **disabled**.
792792
#[cfg(feature = "enumset")]
793793
#[cfg_attr(docsrs, doc(cfg(feature = "enumset")))]
794-
pub fn configure_interrupts(&mut self, events: EnumSet<Event>) -> &mut Self {
794+
pub fn configure_interrupts(&mut self, events: EnumSet<Event>) {
795795
for event in events.complement().iter() {
796796
self.configure_interrupt(event, false);
797797
}
798798
for event in events.iter() {
799799
self.configure_interrupt(event, true);
800800
}
801-
802-
self
803801
}
804802

805803
/// Check if an interrupt event happend.
@@ -1293,14 +1291,12 @@ impl ReceiverTimeoutExt for USART2 {}
12931291
impl ReceiverTimeoutExt for USART3 {}
12941292

12951293
/// UART instance
1296-
pub trait Instance: Deref<Target = RegisterBlock> + crate::private::Sealed {
1294+
pub trait Instance:
1295+
Deref<Target = RegisterBlock> + crate::interrupts::InterruptNumber + crate::private::Sealed
1296+
{
12971297
/// Peripheral bus instance which is responsible for the peripheral
12981298
type APB;
12991299

1300-
/// The associated interrupt number, used to unmask / enable the interrupt
1301-
/// with [`cortex_m::peripheral::NVIC::unmask()`]
1302-
const INTERRUPT: Interrupt;
1303-
13041300
#[doc(hidden)]
13051301
fn enable_clock(apb1: &mut Self::APB);
13061302
#[doc(hidden)]
@@ -1323,9 +1319,13 @@ macro_rules! usart {
13231319
) => {
13241320
$(
13251321
impl crate::private::Sealed for $USARTX {}
1322+
impl crate::interrupts::InterruptNumber for $USARTX {
1323+
type Interrupt = Interrupt;
1324+
const INTERRUPT: Interrupt = $INTERRUPT;
1325+
}
1326+
13261327
impl Instance for $USARTX {
13271328
type APB = $APB;
1328-
const INTERRUPT: Interrupt = $INTERRUPT;
13291329
fn enable_clock(apb: &mut Self::APB) {
13301330
apb.enr().modify(|_, w| w.$usartXen().enabled());
13311331
apb.rstr().modify(|_, w| w.$usartXrst().reset());

0 commit comments

Comments
 (0)