Skip to content

Commit 10ea58b

Browse files
authored
Merge pull request #770 from rust-embedded/defmt
generate defmt::Format for enums
2 parents f6d0cb0 + d93f9fc commit 10ea58b

File tree

7 files changed

+65
-52
lines changed

7 files changed

+65
-52
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ jobs:
7575
- { rust: stable, vendor: Spansion, options: "--atomics" }
7676
- { rust: stable, vendor: STMicro, options: "" }
7777
- { rust: stable, vendor: STMicro, options: "--atomics" }
78-
- { rust: stable, vendor: STM32-patched, options: "--strict --pascal_enum_values --max_cluster_size --atomics --atomics_feature atomics" }
78+
- { rust: stable, vendor: STM32-patched, options: "--strict --pascal_enum_values --max_cluster_size --atomics --atomics_feature atomics --impl_debug --impl-defmt defmt" }
7979
- { rust: stable, vendor: Toshiba, options: all }
8080
- { rust: stable, vendor: Toshiba, options: "" }
8181
# Test MSRV

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
1717
- *breaking change* Always numerates field arrays from 0
1818
- Support of default value for `EnumeratedValues`
1919
- move `Config` to `config` module
20+
- add `impl-defmt` config flag
2021

2122
## [v0.30.3] - 2023-11-19
2223

ci/script.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ main() {
4646
if [[ "$options" == *"--atomics"* ]]; then
4747
echo 'portable-atomic = { version = "1.4", default-features = false }' >> $td/Cargo.toml
4848
fi
49+
if [[ "$options" == *"--impl-defmt"* ]]; then
50+
echo 'defmt = { version = "0.3.5", optional = true }' >> $td/Cargo.toml
51+
fi
4952
echo '[profile.dev]' >> $td/Cargo.toml
5053
echo 'incremental = false' >> $td/Cargo.toml
5154

src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub struct Config {
1919
pub max_cluster_size: bool,
2020
pub impl_debug: bool,
2121
pub impl_debug_feature: Option<String>,
22+
pub impl_defmt: Option<String>,
2223
pub output_dir: Option<PathBuf>,
2324
pub input: Option<PathBuf>,
2425
pub source_type: SourceType,

src/generate/peripheral.rs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -622,34 +622,27 @@ fn register_or_cluster_block(
622622
});
623623
}
624624
}
625-
626-
let mut derive_debug = TokenStream::new();
627-
if config.impl_debug {
625+
let derive_debug = config.impl_debug.then(|| {
628626
if let Some(feature_name) = &config.impl_debug_feature {
629-
derive_debug.extend(quote! {
630-
#[cfg_attr(feature = #feature_name, derive(Debug))]
631-
});
627+
quote!(#[cfg_attr(feature = #feature_name, derive(Debug))])
632628
} else {
633-
derive_debug.extend(quote! {
634-
#[derive(Debug)]
635-
});
629+
quote!(#[derive(Debug)])
636630
}
637-
}
631+
});
632+
638633
let name = if let Some(name) = name {
639634
name.to_constant_case_ident(span)
640635
} else {
641636
Ident::new("RegisterBlock", span)
642637
};
643638

644-
let accessors = if !accessors.is_empty() {
639+
let accessors = (!accessors.is_empty()).then(|| {
645640
quote! {
646641
impl #name {
647642
#accessors
648643
}
649644
}
650-
} else {
651-
quote! {}
652-
};
645+
});
653646

654647
Ok(quote! {
655648
///Register block

src/generate/register.rs

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ pub fn render_register_mod(
248248
let open = Punct::new('{', Spacing::Alone);
249249
let close = Punct::new('}', Spacing::Alone);
250250

251+
let debug_feature = config
252+
.impl_debug_feature
253+
.as_ref()
254+
.map(|feature| quote!(#[cfg(feature=#feature)]));
255+
251256
if let Some(cur_fields) = register.fields.as_ref() {
252257
// filter out all reserved fields, as we should not generate code for
253258
// them
@@ -284,12 +289,8 @@ pub fn render_register_mod(
284289
)?;
285290
}
286291
} else if !access.can_read() || register.read_action.is_some() {
287-
if let Some(feature) = &config.impl_debug_feature {
288-
r_debug_impl.extend(quote! {
289-
#[cfg(feature=#feature)]
290-
});
291-
}
292292
r_debug_impl.extend(quote! {
293+
#debug_feature
293294
impl core::fmt::Debug for crate::generic::Reg<#regspec_ident> {
294295
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
295296
write!(f, "(not readable)")
@@ -298,27 +299,17 @@ pub fn render_register_mod(
298299
});
299300
} else {
300301
// no register fields are defined so implement Debug to get entire register value
301-
if let Some(feature) = &config.impl_debug_feature {
302-
r_debug_impl.extend(quote! {
303-
#[cfg(feature=#feature)]
304-
});
305-
}
306302
r_debug_impl.extend(quote! {
303+
#debug_feature
307304
impl core::fmt::Debug for R {
308305
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
309306
write!(f, "{}", self.bits())
310307
}
311308
}
312-
});
313-
if let Some(feature) = &config.impl_debug_feature {
314-
r_debug_impl.extend(quote! {
315-
#[cfg(feature=#feature)]
316-
});
317-
}
318-
r_debug_impl.extend(quote! {
309+
#debug_feature
319310
impl core::fmt::Debug for crate::generic::Reg<#regspec_ident> {
320311
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
321-
self.read().fmt(f)
312+
core::fmt::Debug::fmt(&self.read(), f)
322313
}
323314
}
324315
});
@@ -450,15 +441,15 @@ fn render_register_mod_debug(
450441
let open = Punct::new('{', Spacing::Alone);
451442
let close = Punct::new('}', Spacing::Alone);
452443
let mut r_debug_impl = TokenStream::new();
444+
let debug_feature = config
445+
.impl_debug_feature
446+
.as_ref()
447+
.map(|feature| quote!(#[cfg(feature=#feature)]));
453448

454449
// implement Debug for register readable fields that have no read side effects
455450
if access.can_read() && register.read_action.is_none() {
456-
if let Some(feature) = &config.impl_debug_feature {
457-
r_debug_impl.extend(quote! {
458-
#[cfg(feature=#feature)]
459-
});
460-
}
461451
r_debug_impl.extend(quote! {
452+
#debug_feature
462453
impl core::fmt::Debug for R #open
463454
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result #open
464455
f.debug_struct(#name)
@@ -496,25 +487,17 @@ fn render_register_mod_debug(
496487
#close
497488
#close
498489
});
499-
if let Some(feature) = &config.impl_debug_feature {
500-
r_debug_impl.extend(quote! {
501-
#[cfg(feature=#feature)]
502-
});
503-
}
504490
r_debug_impl.extend(quote! {
491+
#debug_feature
505492
impl core::fmt::Debug for crate::generic::Reg<#regspec_ident> {
506493
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
507-
self.read().fmt(f)
494+
core::fmt::Debug::fmt(&self.read(), f)
508495
}
509496
}
510497
});
511498
} else if !access.can_read() || register.read_action.is_some() {
512-
if let Some(feature) = &config.impl_debug_feature {
513-
r_debug_impl.extend(quote! {
514-
#[cfg(feature=#feature)]
515-
});
516-
}
517499
r_debug_impl.extend(quote! {
500+
#debug_feature
518501
impl core::fmt::Debug for crate::generic::Reg<#regspec_ident> {
519502
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
520503
write!(f, "(not readable)")
@@ -755,7 +738,7 @@ pub fn fields(
755738
// else, generate enumeratedValues into a Rust enum with functions for each variant.
756739
if variants.is_empty() {
757740
// generate struct VALUE_READ_TY_A(fty) and From<fty> for VALUE_READ_TY_A.
758-
add_with_no_variants(mod_items, &value_read_ty, &fty, &description, rv);
741+
add_with_no_variants(mod_items, &value_read_ty, &fty, &description, rv, config);
759742
} else {
760743
// do we have finite definition of this enumeration in svd? If not, the later code would
761744
// return an Option when the value read from field does not match any defined values.
@@ -770,6 +753,7 @@ pub fn fields(
770753
&fty,
771754
&description,
772755
rv,
756+
config,
773757
);
774758
has_reserved_variant = false;
775759
} else {
@@ -780,6 +764,7 @@ pub fn fields(
780764
&fty,
781765
&description,
782766
rv,
767+
config,
783768
);
784769
has_reserved_variant = evs.values.len() != (1 << width);
785770
}
@@ -1047,7 +1032,14 @@ pub fn fields(
10471032
// generate write value structure and From conversation if we can't reuse read value structure.
10481033
if writer_reader_different_enum {
10491034
if variants.is_empty() {
1050-
add_with_no_variants(mod_items, &value_write_ty, &fty, &description, rv);
1035+
add_with_no_variants(
1036+
mod_items,
1037+
&value_write_ty,
1038+
&fty,
1039+
&description,
1040+
rv,
1041+
config,
1042+
);
10511043
} else {
10521044
add_from_variants(
10531045
mod_items,
@@ -1056,6 +1048,7 @@ pub fn fields(
10561048
&fty,
10571049
&description,
10581050
rv,
1051+
config,
10591052
);
10601053
}
10611054
}
@@ -1324,7 +1317,13 @@ fn add_with_no_variants(
13241317
fty: &Ident,
13251318
desc: &str,
13261319
reset_value: Option<u64>,
1320+
config: &Config,
13271321
) {
1322+
let defmt = config
1323+
.impl_defmt
1324+
.as_ref()
1325+
.map(|feature| quote!(#[cfg_attr(feature = #feature, derive(defmt::Format))]));
1326+
13281327
let cast = if fty == "bool" {
13291328
quote! { val.0 as u8 != 0 }
13301329
} else {
@@ -1339,6 +1338,7 @@ fn add_with_no_variants(
13391338

13401339
mod_items.extend(quote! {
13411340
#[doc = #desc]
1341+
#defmt
13421342
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13431343
pub struct #pc(#fty);
13441344
impl From<#pc> for #fty {
@@ -1364,7 +1364,13 @@ fn add_from_variants<'a>(
13641364
fty: &Ident,
13651365
desc: &str,
13661366
reset_value: Option<u64>,
1367+
config: &Config,
13671368
) {
1369+
let defmt = config
1370+
.impl_defmt
1371+
.as_ref()
1372+
.map(|feature| quote!(#[cfg_attr(feature = #feature, derive(defmt::Format))]));
1373+
13681374
let (repr, cast) = if fty == "bool" {
13691375
(quote! {}, quote! { variant as u8 != 0 })
13701376
} else {
@@ -1392,6 +1398,7 @@ fn add_from_variants<'a>(
13921398

13931399
mod_items.extend(quote! {
13941400
#[doc = #desc]
1401+
#defmt
13951402
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13961403
#repr
13971404
pub enum #pc {

src/main.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,15 @@ fn run() -> Result<()> {
127127
.arg(
128128
Arg::new("impl_debug_feature")
129129
.long("impl_debug_feature")
130-
.help("add feature gating for block and register debug implementation")
130+
.help("Add feature gating for block and register debug implementation")
131+
.action(ArgAction::Set)
132+
.value_name("FEATURE"),
133+
)
134+
.arg(
135+
Arg::new("impl_defmt")
136+
.long("impl-defmt")
137+
.alias("impl_defmt")
138+
.help("Add automatic defmt implementation for enumerated values")
131139
.action(ArgAction::Set)
132140
.value_name("FEATURE"),
133141
)

0 commit comments

Comments
 (0)