Skip to content

Commit 42dc60e

Browse files
committed
Extend format and debug support
1 parent 18dc489 commit 42dc60e

File tree

13 files changed

+223
-7
lines changed

13 files changed

+223
-7
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
4747
register without throwing any event. ([#253]).
4848
- Lift generic constraint of most `Serial` method on `TxPin` and `RxPin`.
4949
This should make it easier to generically use the `Serial` peripheral. ([#253])
50+
- Greatly increase coverage of `Debug` and `defmt::Format` implementations.
51+
Almost all important types should now be supported. ([#265])
5052

5153
[`enumset`]: https://crates.io/crates/enumset
5254

@@ -426,6 +428,7 @@ let clocks = rcc
426428
[defmt]: https://github.com/knurling-rs/defmt
427429
[filter]: https://defmt.ferrous-systems.com/filtering.html
428430

431+
[#265]: https://github.com/stm32-rs/stm32f3xx-hal/pull/265
429432
[#264]: https://github.com/stm32-rs/stm32f3xx-hal/pull/264
430433
[#263]: https://github.com/stm32-rs/stm32f3xx-hal/pull/263
431434
[#262]: https://github.com/stm32-rs/stm32f3xx-hal/pull/262

src/adc.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ pub struct Adc<ADC> {
4545
/// There is always an overhead of 13 ADC clock cycles.
4646
/// E.g. For Sampletime T_19 the total conversion time (in ADC clock cycles) is
4747
/// 13 + 19 = 32 ADC Clock Cycles
48+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
49+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
4850
pub enum SampleTime {
4951
/// 1.5 ADC clock cycles
5052
T_1,
@@ -87,9 +89,10 @@ impl SampleTime {
8789
}
8890
}
8991

90-
#[derive(Clone, Copy, PartialEq)]
9192
/// ADC operation mode
9293
// TODO: Implement other modes (DMA, Differential,…)
94+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
95+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9396
pub enum OperationMode {
9497
/// OneShot Mode
9598
OneShot,
@@ -128,6 +131,8 @@ impl From<CkMode> for CKMODE_A {
128131
}
129132

130133
/// ADC data register alignment
134+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
135+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
131136
pub enum Align {
132137
/// Right alignment of output data
133138
Right,

src/delay.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//! [DelayUs]: embedded_hal::blocking::delay::DelayUs
77
88
use core::convert::From;
9+
use core::fmt;
910

1011
use cortex_m::peripheral::syst::SystClkSource;
1112
use cortex_m::peripheral::SYST;
@@ -21,6 +22,22 @@ pub struct Delay {
2122
syst: SYST,
2223
}
2324

25+
#[cfg(feature = "defmt")]
26+
impl defmt::Format for Delay {
27+
fn format(&self, f: defmt::Formatter) {
28+
defmt::write!(f, "Delay {{ clocks: {} , syst: SYST }}", self.clocks);
29+
}
30+
}
31+
32+
impl fmt::Debug for Delay {
33+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34+
f.debug_struct("Delay")
35+
.field("clocks", &self.clocks)
36+
.field("syst", &"SYST")
37+
.finish()
38+
}
39+
}
40+
2441
impl Delay {
2542
/// Configures the system timer (SysTick) as a delay provider
2643
///

src/gpio.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,19 @@ pub mod marker {
177177
}
178178

179179
/// Runtime defined GPIO port (type state)
180+
#[derive(Debug)]
180181
pub struct Gpiox {
181182
ptr: *const dyn GpioRegExt,
182183
index: u8,
183184
}
184185

186+
#[cfg(feature = "defmt")]
187+
impl defmt::Format for Gpiox {
188+
fn format(&self, f: defmt::Formatter) {
189+
defmt::write!(f, "Gpiox {{ ptr: GpioRegExt , index: {:?} }}", self.index);
190+
}
191+
}
192+
185193
// # SAFETY
186194
// As Gpiox uses `dyn GpioRegExt` pointer internally, `Send` is not auto-implemented.
187195
// But since GpioExt does only do atomic operations without side-effects we can assume
@@ -212,6 +220,8 @@ impl marker::Gpio for Gpiox {}
212220
// TODO(Sh3Rm4n): If the pin number wouldn't be runtime defined, the implementation for all
213221
// statically defined pins would be much easier (and withless overhead). What could be the
214222
// solution?
223+
#[derive(Debug)]
224+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
215225
pub struct Ux(u8);
216226

217227
impl marker::Index for Ux {
@@ -221,6 +231,8 @@ impl marker::Index for Ux {
221231
}
222232

223233
/// Compile time defined pin number (type state)
234+
#[derive(Debug)]
235+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
224236
pub struct U<const X: u8>;
225237

226238
impl<const X: u8> marker::Index for U<X> {
@@ -231,17 +243,29 @@ impl<const X: u8> marker::Index for U<X> {
231243
}
232244

233245
/// Input mode (type state)
246+
#[derive(Debug)]
247+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
234248
pub struct Input;
235249
/// Output mode (type state)
250+
#[derive(Debug)]
251+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
236252
pub struct Output<Otype>(PhantomData<Otype>);
237253
/// Alternate function (type state)
254+
#[derive(Debug)]
255+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
238256
pub struct Alternate<Otype, const AF: u8>(PhantomData<Otype>);
239257
/// Analog mode (type state)
258+
#[derive(Debug)]
259+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
240260
pub struct Analog;
241261

242262
/// Push-pull output (type state)
263+
#[derive(Debug)]
264+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
243265
pub struct PushPull;
244266
/// Open-drain output (type state)
267+
#[derive(Debug)]
268+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
245269
pub struct OpenDrain;
246270

247271
impl marker::Readable for Input {}
@@ -277,7 +301,7 @@ pub enum Resistor {
277301
}
278302

279303
/// GPIO interrupt trigger edge selection
280-
#[derive(Copy, Clone, PartialEq, Eq)]
304+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
281305
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
282306
pub enum Edge {
283307
/// Rising edge of voltage
@@ -289,6 +313,8 @@ pub enum Edge {
289313
}
290314

291315
/// Generic pin
316+
#[derive(Debug)]
317+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
292318
pub struct Pin<Gpio, Index, Mode> {
293319
pub(crate) gpio: Gpio,
294320
pub(crate) index: Index,
@@ -769,6 +795,8 @@ macro_rules! gpio {
769795
}) => {
770796
paste::paste! {
771797
#[doc = "GPIO port " $GPIOX " (type state)"]
798+
#[derive(Debug)]
799+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
772800
pub struct $Gpiox;
773801

774802
impl private::Gpio for $Gpiox {

src/pwm.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,37 +208,61 @@ use crate::gpio::gpioe;
208208
use crate::gpio::{gpioc, gpiof};
209209

210210
/// Output Compare Channel 1 of Timer 1 (type state)
211+
#[derive(Debug)]
212+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
211213
pub struct TIM2_CH1 {}
212214
/// Output Compare Channel 2 of Timer 1 (type state)
215+
#[derive(Debug)]
216+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
213217
pub struct TIM2_CH2 {}
214218
/// Output Compare Channel 3 of Timer 1 (type state)
219+
#[derive(Debug)]
220+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
215221
pub struct TIM2_CH3 {}
216222
/// Output Compare Channel 4 of Timer 1 (type state)
223+
#[derive(Debug)]
224+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
217225
pub struct TIM2_CH4 {}
218226

219227
/// Output Compare Channel 1 of Timer 15 (type state)
228+
#[derive(Debug)]
229+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
220230
pub struct TIM15_CH1 {}
221231
/// Output Compare Channel 2 of Timer 15 (type state)
232+
#[derive(Debug)]
233+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
222234
pub struct TIM15_CH2 {}
223235

224236
/// Output Compare Channel 1 of Timer 16 (type state)
237+
#[derive(Debug)]
238+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
225239
pub struct TIM16_CH1 {}
226240

227241
/// Output Compare Channel 1 of Timer 17 (type state)
242+
#[derive(Debug)]
243+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
228244
pub struct TIM17_CH1 {}
229245

230246
/// Type state used to represent a channel that has no pins yet
247+
#[derive(Debug)]
248+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
231249
pub struct NoPins {}
232250
/// Type state used to represent a channel is using regular pins
251+
#[derive(Debug)]
252+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
233253
pub struct WithPins {}
234254
/// Type state used to represent a channel is using (only) complementary pins
255+
#[derive(Debug)]
256+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
235257
pub struct WithNPins {}
236258

237259
/// Representation of a Channel for an abritary timer channel,
238260
/// that also holds a type state for whether or not this channel
239261
/// is using any pins yet.
240262
///
241263
/// If there are no pins supplied, it cannot be enabled.
264+
#[derive(Debug)]
265+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
242266
pub struct PwmChannel<X, T> {
243267
timx_chy: PhantomData<X>,
244268
pin_status: PhantomData<T>,

src/rcc.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,8 @@ impl CFGR {
778778
///
779779
/// The existence of this value indicates that the clock configuration can no longer be changed.
780780
/// This struct can be obtained via the [freeze](CFGR::freeze) method of the [CFGR](CFGR) struct.
781-
#[derive(Clone, Copy)]
781+
#[derive(Debug, Clone, Copy)]
782+
// #[cfg_attr(feature = "defmt", derive(defmt::Format))]
782783
pub struct Clocks {
783784
hclk: Hertz,
784785
pclk1: Hertz,
@@ -789,6 +790,25 @@ pub struct Clocks {
789790
usbclk_valid: bool,
790791
}
791792

793+
// TODO(Sh3Rm4n) Add defmt support for embedded-time!
794+
#[cfg(feature = "defmt")]
795+
impl defmt::Format for Clocks {
796+
fn format(&self, f: defmt::Formatter) {
797+
// Format as hexadecimal.
798+
defmt::write!(
799+
f,
800+
"Clocks {{ hclk: {} Hz, pclk1: {} Hz, pclk2: {} Hz, ppre1: {:b}, ppre2: {:b}, sysclk: {} Hz, usbclk_valid: {} }}",
801+
self.hclk.integer(),
802+
self.pclk1.integer(),
803+
self.pclk2.integer(),
804+
self.ppre1,
805+
self.ppre2,
806+
self.sysclk.integer(),
807+
self.usbclk_valid,
808+
);
809+
}
810+
}
811+
792812
impl Clocks {
793813
/// Returns the frequency of the AHB
794814
pub fn hclk(&self) -> Hertz {

src/rtc.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
use crate::pac::{PWR, RTC};
99
use crate::rcc::{APB1, BDCR};
1010
use core::convert::TryInto;
11+
use core::fmt;
1112
use rtcc::{Datelike, Hours, NaiveDate, NaiveDateTime, NaiveTime, Rtcc, Timelike};
1213

1314
/// RTC error type
14-
#[derive(Debug)]
15+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
16+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1517
pub enum Error {
1618
/// Invalid input error
1719
InvalidInputData,
@@ -23,6 +25,19 @@ pub struct Rtc {
2325
pub regs: RTC,
2426
}
2527

28+
#[cfg(feature = "defmt")]
29+
impl defmt::Format for Rtc {
30+
fn format(&self, f: defmt::Formatter) {
31+
defmt::write!(f, "Rtc {{ rtc: RTC }}");
32+
}
33+
}
34+
35+
impl fmt::Debug for Rtc {
36+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37+
f.debug_struct("Rtc").field("rtc", &"RTC").finish()
38+
}
39+
}
40+
2641
impl Rtc {
2742
/// Create and enable a new RTC, and configure its clock source and prescalers.
2843
/// From AN4759, Table 7, when using the LSE (The only clock source this module

src/serial.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
1010
use core::{
1111
convert::{Infallible, TryFrom},
12+
fmt,
1213
ops::Deref,
1314
};
1415

@@ -424,12 +425,16 @@ pub struct Serial<Usart, Pins> {
424425
mod split {
425426
use super::Instance;
426427
/// Serial receiver
428+
#[derive(Debug)]
429+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
427430
pub struct Rx<Usart, Pin> {
428431
usart: Usart,
429432
pub(crate) pin: Pin,
430433
}
431434

432435
/// Serial transmitter
436+
#[derive(Debug)]
437+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
433438
pub struct Tx<Usart, Pin> {
434439
usart: Usart,
435440
pub(crate) pin: Pin,
@@ -1308,6 +1313,31 @@ macro_rules! usart {
13081313
(split::Tx::new(tx, self.pins.0), split::Rx::new(rx, self.pins.1))
13091314
}
13101315
}
1316+
1317+
#[cfg(feature = "defmt")]
1318+
impl<Pins> defmt::Format for Serial<$USARTX, Pins> {
1319+
fn format(&self, f: defmt::Formatter) {
1320+
// Omitting pins makes it:
1321+
// 1. Easier.
1322+
// 2. Not to specialized to use it ergonimically for users
1323+
// even in a generic context.
1324+
// 3. Not require specialization.
1325+
defmt::write!(
1326+
f,
1327+
"Serial {{ usart: {}, pins: ? }}",
1328+
stringify!($USARTX),
1329+
);
1330+
}
1331+
}
1332+
1333+
impl<Pins> fmt::Debug for Serial<$USARTX, Pins> {
1334+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1335+
f.debug_struct(stringify!(Serial))
1336+
.field("usart", &stringify!($USARTX))
1337+
.field("pins", &"?")
1338+
.finish()
1339+
}
1340+
}
13111341
)+
13121342
};
13131343

src/spi.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ use crate::time::rate::*;
137137
use core::marker::PhantomData;
138138

139139
/// SPI error
140-
#[derive(Debug)]
140+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
141+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
141142
#[non_exhaustive]
142143
pub enum Error {
143144
/// Overrun occurred

src/syscfg.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! # System configuration controller
22
3+
use core::fmt;
34
use core::ops::Deref;
45

56
use crate::gpio::{marker, Pin};
@@ -32,6 +33,19 @@ impl SysCfgExt for SYSCFG {
3233
/// ```
3334
pub struct SysCfg(SYSCFG);
3435

36+
#[cfg(feature = "defmt")]
37+
impl defmt::Format for SysCfg {
38+
fn format(&self, f: defmt::Formatter) {
39+
defmt::write!(f, "SysCfg(SYSCFG)");
40+
}
41+
}
42+
43+
impl fmt::Debug for SysCfg {
44+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45+
f.debug_struct("SysCfg").finish()
46+
}
47+
}
48+
3549
impl Deref for SysCfg {
3650
type Target = SYSCFG;
3751

0 commit comments

Comments
 (0)