Skip to content

Commit

Permalink
Merge pull request #848 from rust-embedded/html
Browse files Browse the repository at this point in the history
Html
  • Loading branch information
Emilgardis authored Jun 15, 2024
2 parents 5f8950f + 68d69b6 commit 0671417
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 89 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

- Add `html-url` option to access `svdtools html` files from docs
- Move `Reg` in separate file
- Use `warning` class in docs
- Refactor `Accessor`
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ serde_json = { version = "1.0.85", optional = true }
serde_yaml = { version = "0.9.11", optional = true }
regex = "1.10.0"
html-escape = "0.2"
url = { version = "2.5", features = ["serde"] }

[dependencies.svd-parser]
features = ["expand"]
Expand Down
1 change: 1 addition & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub struct Config {
pub ident_formats_theme: Option<IdentFormatsTheme>,
pub field_names_for_enums: bool,
pub base_address_shift: u64,
pub html_url: Option<url::Url>,
}

#[allow(clippy::upper_case_acronyms)]
Expand Down
150 changes: 71 additions & 79 deletions src/generate/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::fmt;
use svd_parser::expand::{
derive_cluster, derive_peripheral, derive_register, BlockPath, Index, RegisterPath,
};
use syn::LitInt;

use crate::config::Config;
use crate::svd::{
Expand Down Expand Up @@ -80,6 +81,60 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result
}
};

let phtml = config.html_url.as_ref().map(|url| {
let doc = format!("See peripheral [structure]({url}#{})", &path.peripheral);
quote!(#[doc = ""] #[doc = #doc])
});

let per_to_tokens = |out: &mut TokenStream,
feature_attribute: &TokenStream,
description: &str,
p_ty: &Ident,
doc_alias: Option<TokenStream>,
address: LitInt| {
out.extend(quote! {
#[doc = #description]
#phtml
#doc_alias
#feature_attribute
pub struct #p_ty { _marker: PhantomData<*const ()> }

#feature_attribute
unsafe impl Send for #p_ty {}

#feature_attribute
impl #p_ty {
///Pointer to the register block
pub const PTR: *const #base::RegisterBlock = #address as *const _;

///Return the pointer to the register block
#[inline(always)]
pub const fn ptr() -> *const #base::RegisterBlock {
Self::PTR
}

#steal_fn
}

#feature_attribute
impl Deref for #p_ty {
type Target = #base::RegisterBlock;

#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*Self::PTR }
}
}

#feature_attribute
impl core::fmt::Debug for #p_ty {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct(#name_str).finish()
}
}
});
};

match &p {
Peripheral::Array(p, dim) => {
let mut feature_names = Vec::with_capacity(dim.dim as _);
Expand All @@ -97,46 +152,14 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result
feature_attribute_n.extend(quote! { #[cfg(feature = #p_feature)] })
};
// Insert the peripherals structure
out.extend(quote! {
#[doc = #description]
#doc_alias
#feature_attribute_n
pub struct #p_ty { _marker: PhantomData<*const ()> }

#feature_attribute_n
unsafe impl Send for #p_ty {}

#feature_attribute_n
impl #p_ty {
///Pointer to the register block
pub const PTR: *const #base::RegisterBlock = #address as *const _;

///Return the pointer to the register block
#[inline(always)]
pub const fn ptr() -> *const #base::RegisterBlock {
Self::PTR
}

#steal_fn
}

#feature_attribute_n
impl Deref for #p_ty {
type Target = #base::RegisterBlock;

#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*Self::PTR }
}
}

#feature_attribute_n
impl core::fmt::Debug for #p_ty {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct(#name_str).finish()
}
}
});
per_to_tokens(
&mut out,
&feature_attribute_n,
description,
&p_ty,
doc_alias,
address,
);
}

let feature_any_attribute = quote! {#[cfg(any(#(feature = #feature_names),*))]};
Expand All @@ -159,45 +182,14 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result
feature_attribute.extend(quote! { #[cfg(feature = #p_feature)] })
};
// Insert the peripheral structure
out.extend(quote! {
#[doc = #description]
#feature_attribute
pub struct #p_ty { _marker: PhantomData<*const ()> }

#feature_attribute
unsafe impl Send for #p_ty {}

#feature_attribute
impl #p_ty {
///Pointer to the register block
pub const PTR: *const #base::RegisterBlock = #address as *const _;

///Return the pointer to the register block
#[inline(always)]
pub const fn ptr() -> *const #base::RegisterBlock {
Self::PTR
}

#steal_fn
}

#feature_attribute
impl Deref for #p_ty {
type Target = #base::RegisterBlock;

#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*Self::PTR }
}
}

#feature_attribute
impl core::fmt::Debug for #p_ty {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct(#name_str).finish()
}
}
});
per_to_tokens(
&mut out,
&feature_attribute,
&description,
&p_ty,
None,
address,
);

// Derived peripherals may not require re-implementation, and will instead
// use a single definition of the non-derived version.
Expand Down
43 changes: 33 additions & 10 deletions src/generate/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ pub fn render(
return Err(anyhow!("Incorrect access of register {}", register.name));
};

let rpath = path.new_register(&register.name);
let mut alias_doc = format!(
"{name} ({accs}) register accessor: {description}{}{}",
api_docs(
Expand All @@ -116,6 +117,9 @@ pub fn render(
register.properties.reset_value.is_some(),
&mod_ty,
false,
&register,
&rpath,
config,
)?,
read_action_docs(access.can_read(), register.read_action),
);
Expand All @@ -128,13 +132,7 @@ pub fn render(
#doc_alias
pub type #reg_ty = crate::Reg<#mod_ty::#regspec_ty>;
});
let mod_items = render_register_mod(
register,
access,
&path.new_register(&register.name),
index,
config,
)?;
let mod_items = render_register_mod(register, access, &rpath, index, config)?;

out.extend(quote! {
#[doc = #description]
Expand Down Expand Up @@ -170,6 +168,9 @@ fn api_docs(
can_reset: bool,
module: &Ident,
inmodule: bool,
register: &Register,
rpath: &RegisterPath,
config: &Config,
) -> Result<String, std::fmt::Error> {
fn method(s: &str) -> String {
format!("[`{s}`](crate::Reg::{s})")
Expand Down Expand Up @@ -211,13 +212,35 @@ fn api_docs(

doc.push_str("See [API](https://docs.rs/svd2rust/#read--modify--write-api).");

if let Some(url) = config.html_url.as_ref() {
let first_idx = if let Register::Array(_, dim) = &register {
dim.indexes().next()
} else {
None
};
let rname = if let Some(idx) = first_idx {
let idx = format!("[{idx}]");
rpath.name.replace("[%s]", &idx).replace("%s", &idx)
} else {
rpath.name.to_string()
};
// TODO: support html_urls for registers in cluster
if rpath.block.path.is_empty() {
doc.push_str(&format!(
"\n\nSee register [structure]({url}#{}:{})",
rpath.peripheral(),
rname
));
}
}

Ok(doc)
}

pub fn render_register_mod(
register: &Register,
access: Access,
path: &RegisterPath,
rpath: &RegisterPath,
index: &Index,
config: &Config,
) -> Result<TokenStream> {
Expand Down Expand Up @@ -312,7 +335,7 @@ pub fn render_register_mod(
access,
properties,
&mut mod_items,
path,
rpath,
index,
config,
)?;
Expand Down Expand Up @@ -361,7 +384,7 @@ pub fn render_register_mod(

let doc = format!(
"{description}{}{}",
api_docs(can_read, can_write, can_reset, &mod_ty, true)?,
api_docs(can_read, can_write, can_reset, &mod_ty, true, register, rpath, config)?,
read_action_docs(access.can_read(), register.read_action),
);

Expand Down
8 changes: 8 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,14 @@ Allowed cases are `unchanged` (''), `pascal` ('p'), `constant` ('c') and `snake`
Useful for soft-cores where the peripheral address range isn't necessarily fixed.
Ignore this option if you are not building your own FPGA based soft-cores."),
)
.arg(
Arg::new("html_url")
.long("html-url")
.alias("html_url")
.help("Path to chip HTML generated by svdtools")
.action(ArgAction::Set)
.value_name("URL"),
)
.arg(
Arg::new("log_level")
.long("log")
Expand Down

0 comments on commit 0671417

Please sign in to comment.