Skip to content

Commit 196fe75

Browse files
committed
add register reader/writer links
1 parent d19c646 commit 196fe75

File tree

3 files changed

+97
-45
lines changed

3 files changed

+97
-45
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
88
## [Unreleased]
99

1010
- Fix when `atomics` features is generated but not enabled
11+
- move hidden structs into module, add register reader/writer links into `SPEC` docs (#736)
1112
- removed register writer & reader wrappers, generic `REG` in field writers (#731)
1213
- Updated syn to version 2 (#732)
1314
- Let readable field fetch doc from svd description (#734)

src/generate/peripheral.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -245,20 +245,15 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result
245245

246246
/// An enum describing the derivation status of an erc, which allows for disjoint arrays to be
247247
/// implicitly derived from a common type.
248-
#[derive(Debug, PartialEq)]
248+
#[derive(Default, Debug, PartialEq)]
249249
enum DeriveInfo {
250+
#[default]
250251
Root,
251252
Explicit(RegisterPath),
252253
Implicit(RegisterPath),
253254
Cluster, // don't do anything different for clusters
254255
}
255256

256-
impl Default for DeriveInfo {
257-
fn default() -> Self {
258-
DeriveInfo::Root
259-
}
260-
}
261-
262257
impl fmt::Display for DeriveInfo {
263258
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264259
write!(f, "{self:?}")

src/generate/register.rs

Lines changed: 94 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use proc_macro2::{Ident, Punct, Spacing, Span, TokenStream};
88
use quote::{quote, ToTokens};
99
use std::borrow::Cow;
1010
use std::collections::HashSet;
11+
use std::fmt::Write;
1112
use svd_parser::expand::{
1213
derive_enumerated_values, derive_field, BlockPath, EnumPath, FieldPath, Index, RegisterPath,
1314
};
@@ -80,8 +81,24 @@ pub fn render(
8081
} else {
8182
return Err(anyhow!("Incorrect access of register {}", register.name));
8283
};
83-
let alias_doc =
84-
format!("{name} ({accs}) register accessor: an alias for `Reg<{regspec_ident}>`");
84+
85+
let mut alias_doc = format!(
86+
"{name} ({accs}) register accessor: {description}\n\n{}",
87+
api_docs(
88+
access.can_read(),
89+
access.can_write(),
90+
register.properties.reset_value.is_some(),
91+
&name_snake_case,
92+
false,
93+
register.read_action,
94+
)?
95+
);
96+
if name_snake_case != "cfg" {
97+
alias_doc += format!(
98+
"\n\nFor information about available fields see [`{name_snake_case}`] module"
99+
)
100+
.as_str();
101+
}
85102
let mut out = TokenStream::new();
86103
out.extend(quote! {
87104
#[doc = #alias_doc]
@@ -106,6 +123,68 @@ pub fn render(
106123
}
107124
}
108125

126+
fn api_docs(
127+
can_read: bool,
128+
can_write: bool,
129+
can_reset: bool,
130+
module: &Ident,
131+
inmodule: bool,
132+
read_action: Option<ReadAction>,
133+
) -> Result<String, std::fmt::Error> {
134+
fn method(s: &str) -> String {
135+
format!("[`{s}`](crate::generic::Reg::{s})")
136+
}
137+
138+
let mut doc = String::new();
139+
140+
if can_read {
141+
write!(
142+
doc,
143+
"You can {} this register and get [`{module}::R`]{}. ",
144+
method("read"),
145+
if inmodule { "(R)" } else { "" },
146+
)?;
147+
148+
if let Some(action) = read_action {
149+
doc.push_str("WARN: ");
150+
doc.push_str(match action {
151+
ReadAction::Clear => "The register is **cleared** (set to zero) following a read operation.",
152+
ReadAction::Set => "The register is **set** (set to ones) following a read operation.",
153+
ReadAction::Modify => "The register is **modified** in some way after a read operation.",
154+
ReadAction::ModifyExternal => "One or more dependent resources other than the current register are immediately affected by a read operation.",
155+
});
156+
}
157+
doc.push(' ');
158+
}
159+
160+
if can_write {
161+
let mut methods = Vec::new();
162+
if can_reset {
163+
methods.push("reset");
164+
methods.push("write");
165+
}
166+
methods.push("write_with_zero");
167+
write!(
168+
doc,
169+
"You can {} this register using [`{module}::W`]{}. ",
170+
methods
171+
.iter()
172+
.map(|m| method(m))
173+
.collect::<Vec<_>>()
174+
.join(", "),
175+
if inmodule { "(W)" } else { "" },
176+
)?;
177+
}
178+
179+
if can_read && can_write {
180+
write!(doc, "You can also {} this register. ", method("modify"),)?;
181+
}
182+
183+
doc.push_str("See [API](https://docs.rs/svd2rust/#read--modify--write-api).");
184+
185+
Ok(doc)
186+
}
187+
109188
pub fn render_register_mod(
110189
register: &Register,
111190
access: Access,
@@ -138,7 +217,6 @@ pub fn render_register_mod(
138217
);
139218

140219
let mut mod_items = TokenStream::new();
141-
let mut methods = vec![];
142220

143221
let can_read = access.can_read();
144222
let can_write = access.can_write();
@@ -150,7 +228,6 @@ pub fn render_register_mod(
150228
#[doc = #desc]
151229
pub type R = crate::R<#regspec_ident>;
152230
});
153-
methods.push("read");
154231
}
155232

156233
if can_write {
@@ -159,15 +236,6 @@ pub fn render_register_mod(
159236
#[doc = #desc]
160237
pub type W = crate::W<#regspec_ident>;
161238
});
162-
methods.push("write_with_zero");
163-
if can_reset {
164-
methods.push("reset");
165-
methods.push("write");
166-
}
167-
}
168-
169-
if can_read && can_write {
170-
methods.push("modify");
171239
}
172240

173241
let mut r_impl_items = TokenStream::new();
@@ -310,29 +378,17 @@ pub fn render_register_mod(
310378
close.to_tokens(&mut mod_items);
311379
}
312380

313-
let methods = methods
314-
.iter()
315-
.map(|s| format!("[`{s}`](crate::generic::Reg::{s})"))
316-
.collect::<Vec<_>>();
317-
let mut doc = format!("{description}\n\nThis register you can {}. See [API](https://docs.rs/svd2rust/#read--modify--write-api).", methods.join(", "));
318-
319-
if name_snake_case != "cfg" {
320-
doc += format!(
321-
"\n\nFor information about available fields see [{name_snake_case}](index.html) module"
322-
)
323-
.as_str();
324-
}
325-
326-
if can_read {
327-
if let Some(action) = register.read_action {
328-
doc += match action {
329-
ReadAction::Clear => "\n\nThe register is **cleared** (set to zero) following a read operation.",
330-
ReadAction::Set => "\n\nThe register is **set** (set to ones) following a read operation.",
331-
ReadAction::Modify => "\n\nThe register is **modified** in some way after a read operation.",
332-
ReadAction::ModifyExternal => "\n\nOne or more dependent resources other than the current register are immediately affected by a read operation.",
333-
};
334-
}
335-
}
381+
let doc = format!(
382+
"{description}\n\n{}",
383+
api_docs(
384+
can_read,
385+
can_write,
386+
can_reset,
387+
&name_snake_case,
388+
true,
389+
register.read_action,
390+
)?
391+
);
336392

337393
mod_items.extend(quote! {
338394
#[doc = #doc]
@@ -344,15 +400,15 @@ pub fn render_register_mod(
344400
});
345401

346402
if can_read {
347-
let doc = format!("`read()` method returns [{name_snake_case}::R](R) reader structure",);
403+
let doc = format!("`read()` method returns [`{name_snake_case}::R`](R) reader structure",);
348404
mod_items.extend(quote! {
349405
#[doc = #doc]
350406
impl crate::Readable for #regspec_ident {}
351407
});
352408
}
353409
if can_write {
354410
let doc =
355-
format!("`write(|w| ..)` method takes [{name_snake_case}::W](W) writer structure",);
411+
format!("`write(|w| ..)` method takes [`{name_snake_case}::W`](W) writer structure",);
356412

357413
let zero_to_modify_fields_bitmap = util::hex(zero_to_modify_fields_bitmap);
358414
let one_to_modify_fields_bitmap = util::hex(one_to_modify_fields_bitmap);

0 commit comments

Comments
 (0)