diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 00000000..bd7a3e01 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,7 @@ +array_layout = "Block" +fn_args_layout = "Block" +fn_call_style = "Block" +generics_indent = "Block" +max_width = 80 +where_style = "Rfc" +write_mode = "overwrite" \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bc4074c..4aa39a18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Changed + +- [breaking-change]. svd2rust no longer generates an API for core peripherals + like NVIC. Instead, it just re-exports the cortex-m crate's API. + ## [v0.6.2] - 2017-04-23 ### Changed diff --git a/Cargo.lock b/Cargo.lock index 10acdcb3..370ce91a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "svd2rust" -version = "0.6.1" +version = "0.7.0" dependencies = [ "cast 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index a0f809e1..c6e219c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ keywords = ["arm", "cortex-m", "register", "map", "generator"] license = "MIT OR Apache-2.0" name = "svd2rust" repository = "https://github.com/japaric/svd2rust" -version = "0.6.2" +version = "0.7.0" [dependencies] cast = "0.2.0" diff --git a/build.rs b/build.rs index 34624247..58c48d1a 100644 --- a/build.rs +++ b/build.rs @@ -8,7 +8,8 @@ use std::process::Command; struct IgnoredError {} impl From for IgnoredError - where E: Error +where + E: Error, { fn from(_: E) -> IgnoredError { IgnoredError {} @@ -32,15 +33,38 @@ fn commit_info() -> String { } fn commit_hash() -> Result { - Ok(try!(String::from_utf8(try!(Command::new("git") - .args(&["rev-parse", "--short", "HEAD"]) - .output()) - .stdout))) + Ok( + try!( + String::from_utf8( + try!( + Command::new("git") + .args(&["rev-parse", "--short", "HEAD"]) + .output() + ) + .stdout, + ) + ), + ) } fn commit_date() -> Result { - Ok(try!(String::from_utf8(try!(Command::new("git") - .args(&["log", "-1", "--date=short", "--pretty=format:%cd"]) - .output()) - .stdout))) + Ok( + try!( + String::from_utf8( + try!( + Command::new("git") + .args( + &[ + "log", + "-1", + "--date=short", + "--pretty=format:%cd", + ], + ) + .output() + ) + .stdout, + ) + ), + ) } diff --git a/src/generate.rs b/src/generate.rs index 87cef448..06f9d130 100644 --- a/src/generate.rs +++ b/src/generate.rs @@ -13,28 +13,61 @@ use util::{self, ToSanitizedPascalCase, ToSanitizedSnakeCase, U32Ext}; /// Whole device generation pub fn device(d: &Device, items: &mut Vec) -> Result<()> { - let doc = format!("Peripheral access API for {} microcontrollers \ - (generated using svd2rust v{})", - d.name.to_uppercase(), - env!("CARGO_PKG_VERSION")); - items.push(quote! { - #![doc = #doc] - #![deny(missing_docs)] - #![deny(warnings)] - #![feature(const_fn)] - #![no_std] + let doc = format!( + "Peripheral access API for {} microcontrollers \ + (generated using svd2rust v{})", + d.name.to_uppercase(), + env!("CARGO_PKG_VERSION") + ); + items.push( + quote! { + #![doc = #doc] + #![deny(missing_docs)] + #![deny(warnings)] + #![feature(const_fn)] + #![no_std] + + extern crate cortex_m; + extern crate vcell; + + use core::ops::Deref; + + use cortex_m::peripheral::Peripheral; + }, + ); - extern crate cortex_m; - extern crate vcell; - - use core::ops::Deref; + ::generate::interrupt(&d.peripherals, items); - use cortex_m::peripheral::Peripheral; - }); + const CORE_PERIPHERALS: &'static [&'static str] = &[ + "CPUID", + "DCB", + "DWT", + "FPB", + "FPU", + "ITM", + "MPU", + "NVIC", + "SCB", + "SYST", + "TPIU", + ]; + + for p in CORE_PERIPHERALS { + let ty_ = Ident::new(p.to_sanitized_pascal_case()); + let p = Ident::new(*p); - ::generate::interrupt(&d.peripherals, items); + items.push(quote! { + pub use cortex_m::peripheral::#ty_; + pub use cortex_m::peripheral::#p; + }); + } for p in &d.peripherals { + if CORE_PERIPHERALS.contains(&&*p.name.to_uppercase()) { + // Core peripherals are handled above + continue; + } + ::generate::peripheral(p, items, &d.defaults)?; } @@ -43,13 +76,16 @@ pub fn device(d: &Device, items: &mut Vec) -> Result<()> { /// Generates code for `src/interrupt.rs` pub fn interrupt(peripherals: &[Peripheral], items: &mut Vec) { - let interrupts = peripherals.iter() + let interrupts = peripherals + .iter() .flat_map(|p| p.interrupt.iter()) .map(|i| (i.value, i)) .collect::>(); - let mut interrupts = - interrupts.into_iter().map(|(_, v)| v).collect::>(); + let mut interrupts = interrupts + .into_iter() + .map(|(_, v)| v) + .collect::>(); interrupts.sort_by_key(|i| i.value); let mut fields = vec![]; @@ -63,11 +99,13 @@ pub fn interrupt(peripherals: &[Peripheral], items: &mut Vec) { let mut res = 0; let mut uses_reserved = false; let mut mod_items = vec![]; - mod_items.push(quote! { - use cortex_m::ctxt::Context; - use cortex_m::exception; - use cortex_m::interrupt::Nr; - }); + mod_items.push( + quote! { + use cortex_m::ctxt::Context; + use cortex_m::exception; + use cortex_m::interrupt::Nr; + }, + ); for interrupt in &interrupts { if pos < interrupt.value { let name = Ident::new(&*format!("_reserved{}", res)); @@ -75,98 +113,120 @@ pub fn interrupt(peripherals: &[Peripheral], items: &mut Vec) { let n = util::unsuffixed(u64(interrupt.value - pos)); uses_reserved = true; - fields.push(quote! { - /// Reserved spot in the vector table - pub #name: [Reserved; #n], - }); - - exprs.push(quote! { - #name: [Reserved::Vector; #n], - }); + fields.push( + quote! { + /// Reserved spot in the vector table + pub #name: [Reserved; #n], + }, + ); + + exprs.push( + quote! { + #name: [Reserved::Vector; #n], + }, + ); } let name_pc = Ident::new(interrupt.name.to_sanitized_pascal_case()); - let description = - format!("{} - {}", - interrupt.value, - interrupt.description - .as_ref() - .map(|s| util::respace(s)) - .unwrap_or_else(|| interrupt.name.clone())); - fields.push(quote! { - #[doc = #description] - pub #name_pc: extern "C" fn(#name_pc), - }); + let description = format!( + "{} - {}", + interrupt.value, + interrupt + .description + .as_ref() + .map(|s| util::respace(s)) + .unwrap_or_else(|| interrupt.name.clone()) + ); + fields.push( + quote! { + #[doc = #description] + pub #name_pc: extern "C" fn(#name_pc), + }, + ); let value = util::unsuffixed(u64(interrupt.value)); - mod_items.push(quote! { - #[doc = #description] - pub struct #name_pc { _0: () } - unsafe impl Context for #name_pc {} - unsafe impl Nr for #name_pc { - #[inline(always)] - fn nr(&self) -> u8 { - #value + mod_items.push( + quote! { + #[doc = #description] + pub struct #name_pc { _0: () } + unsafe impl Context for #name_pc {} + unsafe impl Nr for #name_pc { + #[inline(always)] + fn nr(&self) -> u8 { + #value + } } - } - }); + }, + ); - exprs.push(quote! { - #name_pc: exception::default_handler, - }); + exprs.push( + quote! { + #name_pc: exception::default_handler, + }, + ); - variants.push(quote! { - #[doc = #description] - #name_pc, - }); + variants.push( + quote! { + #[doc = #description] + #name_pc, + }, + ); - arms.push(quote! { - Interrupt::#name_pc => #value, - }); + arms.push( + quote! { + Interrupt::#name_pc => #value, + }, + ); pos = interrupt.value + 1; } if uses_reserved { - mod_items.push(quote! { - use cortex_m::Reserved; - }); + mod_items.push( + quote! { + use cortex_m::Reserved; + }, + ); } - mod_items.push(quote! { - /// Interrupt handlers - #[allow(non_snake_case)] - #[repr(C)] - pub struct Handlers { - #(#fields)* - } + mod_items.push( + quote! { + /// Interrupt handlers + #[allow(non_snake_case)] + #[repr(C)] + pub struct Handlers { + #(#fields)* + } - /// Default interrupt handlers - pub const DEFAULT_HANDLERS: Handlers = Handlers { - #(#exprs)* - }; + /// Default interrupt handlers + pub const DEFAULT_HANDLERS: Handlers = Handlers { + #(#exprs)* + }; - /// Enumeration of all the interrupts - pub enum Interrupt { - #(#variants)* - } + /// Enumeration of all the interrupts + pub enum Interrupt { + #(#variants)* + } - unsafe impl Nr for Interrupt { - #[inline(always)] - fn nr(&self) -> u8 { - match *self { - #(#arms)* + unsafe impl Nr for Interrupt { + #[inline(always)] + fn nr(&self) -> u8 { + match *self { + #(#arms)* + } } } - } - }); - - items.push(quote! { - /// Interrupts - pub mod interrupt { - #(#mod_items)* - } - }); + }, + ); + + items.push( + quote! { + /// Interrupts + pub mod interrupt { + #(#mod_items)* + } + }, + ); } pub fn peripheral( @@ -177,30 +237,33 @@ pub fn peripheral( let name = Ident::new(&*p.name.to_uppercase()); let name_pc = Ident::new(&*p.name.to_sanitized_pascal_case()); let address = util::unsuffixed(u64(p.base_address)); - let description = - util::respace(p.description.as_ref().unwrap_or(&p.name)); + let description = util::respace(p.description.as_ref().unwrap_or(&p.name)); - items.push(quote! { - #[doc = #description] - pub const #name: Peripheral<#name_pc> = - unsafe { Peripheral::new(#address) }; - }); + items.push( + quote! { + #[doc = #description] + pub const #name: Peripheral<#name_pc> = + unsafe { Peripheral::new(#address) }; + }, + ); if let Some(base) = p.derived_from.as_ref() { // TODO Verify that base exists let base_sc = Ident::new(&*base.to_sanitized_snake_case()); - items.push(quote! { - /// Register block - pub struct #name_pc { register_block: #base_sc::RegisterBlock } + items.push( + quote! { + /// Register block + pub struct #name_pc { register_block: #base_sc::RegisterBlock } - impl Deref for #name_pc { - type Target = #base_sc::RegisterBlock; + impl Deref for #name_pc { + type Target = #base_sc::RegisterBlock; - fn deref(&self) -> &#base_sc::RegisterBlock { - &self.register_block + fn deref(&self) -> &#base_sc::RegisterBlock { + &self.register_block + } } - } - }); + }, + ); // TODO We don't handle inheritance style `derivedFrom`, we should raise // an error in that case @@ -229,27 +292,28 @@ pub fn peripheral( } let name_sc = Ident::new(&*p.name.to_sanitized_snake_case()); - let description = - util::respace(p.description.as_ref().unwrap_or(&p.name)); - items.push(quote! { - #[doc = #description] - pub mod #name_sc { - use vcell::VolatileCell; - - #(#mod_items)* - } + let description = util::respace(p.description.as_ref().unwrap_or(&p.name)); + items.push( + quote! { + #[doc = #description] + pub mod #name_sc { + use vcell::VolatileCell; - #[doc = #description] - pub struct #name_pc { register_block: #name_sc::RegisterBlock } + #(#mod_items)* + } + + #[doc = #description] + pub struct #name_pc { register_block: #name_sc::RegisterBlock } - impl Deref for #name_pc { - type Target = #name_sc::RegisterBlock; + impl Deref for #name_pc { + type Target = #name_sc::RegisterBlock; - fn deref(&self) -> &#name_sc::RegisterBlock { - &self.register_block + fn deref(&self) -> &#name_sc::RegisterBlock { + &self.register_block + } } - } - }); + }, + ); Ok(()) } @@ -264,11 +328,13 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result { let pad = if let Some(pad) = register.offset.checked_sub(offset) { pad } else { - writeln!(io::stderr(), - "WARNING {} overlaps with another register at offset \ - {}. Ignoring.", - register.name, - register.offset) + writeln!( + io::stderr(), + "WARNING {} overlaps with another register at offset {}. \ + Ignoring.", + register.name, + register.offset + ) .ok(); continue; }; @@ -276,15 +342,19 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result { if pad != 0 { let name = Ident::new(format!("_reserved{}", i)); let pad = pad as usize; - fields.push(quote! { - #name : [u8; #pad], - }); + fields.push( + quote! { + #name : [u8; #pad], + }, + ); i += 1; } - let comment = &format!("0x{:02x} - {}", - register.offset, - util::respace(®ister.info.description)) + let comment = &format!( + "0x{:02x} - {}", + register.offset, + util::respace(®ister.info.description) + ) [..]; let rty = match register.ty { @@ -292,28 +362,34 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result { Either::Right(ref ty) => Ident::from(&***ty), }; let reg_name = Ident::new(&*register.name.to_sanitized_snake_case()); - fields.push(quote! { - #[doc = #comment] - pub #reg_name : #rty, - }); + fields.push( + quote! { + #[doc = #comment] + pub #reg_name : #rty, + }, + ); offset = register.offset + - register.info + register + .info .size .or(defs.size) - .ok_or_else(|| { - format!("Register {} has no `size` field", - register.name) - })? / 8; + .ok_or_else( + || { + format!("Register {} has no `size` field", register.name) + }, + )? / 8; } - Ok(quote! { - /// Register block - #[repr(C)] - pub struct RegisterBlock { - #(#fields)* - } - }) + Ok( + quote! { + /// Register block + #[repr(C)] + pub struct RegisterBlock { + #(#fields)* + } + }, + ) } pub fn register( @@ -342,67 +418,79 @@ pub fn register( let mut w_impl_items = vec![]; if access == Access::ReadWrite { - reg_impl_items.push(quote! { - /// Modifies the contents of the register - #[inline(always)] - pub fn modify(&self, f: F) - where - for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W - { - let bits = self.register.get(); - let r = R { bits: bits }; - let mut w = W { bits: bits }; - f(&r, &mut w); - self.register.set(w.bits); - } - }); + reg_impl_items.push( + quote! { + /// Modifies the contents of the register + #[inline(always)] + pub fn modify(&self, f: F) + where + for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W + { + let bits = self.register.get(); + let r = R { bits: bits }; + let mut w = W { bits: bits }; + f(&r, &mut w); + self.register.set(w.bits); + } + }, + ); } if access == Access::ReadOnly || access == Access::ReadWrite { - reg_impl_items.push(quote! { - /// Reads the contents of the register - #[inline(always)] - pub fn read(&self) -> R { - R { bits: self.register.get() } - } - }); - - mod_items.push(quote! { - /// Value read from the register - pub struct R { - bits: #rty, - } - }); + reg_impl_items.push( + quote! { + /// Reads the contents of the register + #[inline(always)] + pub fn read(&self) -> R { + R { bits: self.register.get() } + } + }, + ); + + mod_items.push( + quote! { + /// Value read from the register + pub struct R { + bits: #rty, + } + }, + ); - r_impl_items.push(quote! { - /// Value of the register as raw bits - #[inline(always)] - pub fn bits(&self) -> #rty { - self.bits - } - }); + r_impl_items.push( + quote! { + /// Value of the register as raw bits + #[inline(always)] + pub fn bits(&self) -> #rty { + self.bits + } + }, + ); } if access == Access::WriteOnly || access == Access::ReadWrite { - reg_impl_items.push(quote! { - /// Writes to the register - #[inline(always)] - pub fn write(&self, f: F) - where - F: FnOnce(&mut W) -> &mut W - { - let mut w = W::reset_value(); - f(&mut w); - self.register.set(w.bits); - } - }); - - mod_items.push(quote! { - /// Value to write to the register - pub struct W { - bits: #rty, - } - }); + reg_impl_items.push( + quote! { + /// Writes to the register + #[inline(always)] + pub fn write(&self, f: F) + where + F: FnOnce(&mut W) -> &mut W + { + let mut w = W::reset_value(); + f(&mut w); + self.register.set(w.bits); + } + }, + ); + + mod_items.push( + quote! { + /// Value to write to the register + pub struct W { + bits: #rty, + } + }, + ); let rv = register.reset_value .or(defs.reset_value) @@ -412,69 +500,81 @@ pub fn register( register.name) })?; - w_impl_items.push(quote! { - /// Reset value of the register - #[inline(always)] - pub fn reset_value() -> W { - W { bits: #rv } - } + w_impl_items.push( + quote! { + /// Reset value of the register + #[inline(always)] + pub fn reset_value() -> W { + W { bits: #rv } + } - /// Writes raw bits to the register - #[inline(always)] - pub unsafe fn bits(&mut self, bits: #rty) -> &mut Self { - self.bits = bits; - self - } - }); + /// Writes raw bits to the register + #[inline(always)] + pub unsafe fn bits(&mut self, bits: #rty) -> &mut Self { + self.bits = bits; + self + } + }, + ); } - mod_items.push(quote! { - impl super::#name_pc { - #(#reg_impl_items)* - } - }); + mod_items.push( + quote! { + impl super::#name_pc { + #(#reg_impl_items)* + } + }, + ); if let Some(fields) = register.fields.as_ref() { if !fields.is_empty() { - ::generate::fields(fields, - register, - all_registers, - peripheral, - &rty, - access, - &mut mod_items, - &mut r_impl_items, - &mut w_impl_items)?; + ::generate::fields( + fields, + register, + all_registers, + peripheral, + &rty, + access, + &mut mod_items, + &mut r_impl_items, + &mut w_impl_items, + )?; } } if access == Access::ReadOnly || access == Access::ReadWrite { - mod_items.push(quote! { - impl R { - #(#r_impl_items)* - } - }); + mod_items.push( + quote! { + impl R { + #(#r_impl_items)* + } + }, + ); } if access == Access::WriteOnly || access == Access::ReadWrite { - mod_items.push(quote! { - impl W { - #(#w_impl_items)* - } - }); + mod_items.push( + quote! { + impl W { + #(#w_impl_items)* + } + }, + ); } - items.push(quote! { - #[doc = #description] - pub struct #name_pc { - register: VolatileCell<#rty> - } + items.push( + quote! { + #[doc = #description] + pub struct #name_pc { + register: VolatileCell<#rty> + } - #[doc = #description] - pub mod #name_sc { - #(#mod_items)* - } - }); + #[doc = #description] + pub mod #name_sc { + #(#mod_items)* + } + }, + ); Ok(()) } @@ -525,28 +625,28 @@ pub fn fields( description.push_str(" - "); description.push_str(&*util::respace(d)); } - Ok(F { - _pc_w: _pc_w, - _sc: _sc, - description: description, - pc_r: pc_r, - pc_w: pc_w, - width: width, - access: f.access, - evs: &f.enumerated_values, - sc: Ident::new(&*sc), - mask: util::unsuffixed((1 << width) - 1), - name: &f.name, - offset: util::unsuffixed(u64(f.bit_range.offset)), - ty: width.to_ty()?, - write_constraint: f.write_constraint.as_ref(), - }) + Ok( + F { + _pc_w: _pc_w, + _sc: _sc, + description: description, + pc_r: pc_r, + pc_w: pc_w, + width: width, + access: f.access, + evs: &f.enumerated_values, + sc: Ident::new(&*sc), + mask: util::unsuffixed((1 << width) - 1), + name: &f.name, + offset: util::unsuffixed(u64(f.bit_range.offset)), + ty: width.to_ty()?, + write_constraint: f.write_constraint.as_ref(), + }, + ) } } - let fs = fields.iter() - .map(F::from) - .collect::>>()?; + let fs = fields.iter().map(F::from).collect::>>()?; // TODO enumeratedValues if access == Access::ReadOnly || access == Access::ReadWrite { @@ -566,12 +666,14 @@ pub fn fields( }; if let Some((evs, base)) = - util::lookup(f.evs, - fields, - parent, - all_registers, - peripheral, - Usage::Read)? { + util::lookup( + f.evs, + fields, + parent, + all_registers, + peripheral, + Usage::Read, + )? { struct Variant<'a> { description: &'a str, pc: Ident, @@ -608,122 +710,150 @@ pub fn fields( if let Some(ref base) = base { let pc = base.field.to_sanitized_pascal_case(); let base_pc_r = Ident::new(&*format!("{}R", pc)); - let description = format!("Possible values of \ - the field `{}`", - f.name); + let description = + format!("Possible values of the field `{}`", f.name); if let Some(ref register) = base.register { - let mod_ = - Ident::new(&*register.to_sanitized_snake_case()); + let mod_ = register.to_sanitized_snake_case(); + let mod_ = Ident::new(&*mod_); - mod_items.push(quote! { - #[doc = #description] - pub type #pc_r = super::#mod_::#base_pc_r; - }); + mod_items.push( + quote! { + #[doc = #description] + pub type #pc_r = super::#mod_::#base_pc_r; + }, + ); } else { - mod_items.push(quote! { - #[doc = #description] - pub type #pc_r = #base_pc_r; - }); + mod_items.push( + quote! { + #[doc = #description] + pub type #pc_r = #base_pc_r; + }, + ); } } let description = &f.description; let sc = &f.sc; - r_impl_items.push(quote! { - #[doc = #description] - #[inline(always)] - pub fn #sc(&self) -> #pc_r { - #pc_r::_from({ #bits }) - } - }); + r_impl_items.push( + quote! { + #[doc = #description] + #[inline(always)] + pub fn #sc(&self) -> #pc_r { + #pc_r::_from({ #bits }) + } + }, + ); if base.is_none() { - let desc = format!("Possible values of the field `{}`", - f.name); - - let mut vars = variants.iter() - .map(|v| { - let desc = v.description; - let pc = &v.pc; - quote! { - #[doc = #desc] - #pc - } - }) + let desc = + format!("Possible values of the field `{}`", f.name); + + let mut vars = variants + .iter() + .map( + |v| { + let desc = v.description; + let pc = &v.pc; + quote! { + #[doc = #desc] + #pc + } + }, + ) .collect::>(); if has_reserved_variant { - vars.push(quote! { - /// Reserved - _Reserved(#fty) - }); + vars.push( + quote! { + /// Reserved + _Reserved(#fty) + }, + ); } - mod_items.push(quote! { - #[doc = #desc] - #[derive(Clone, Copy, Debug, PartialEq)] - pub enum #pc_r { - #(#vars),* - } - }); + mod_items.push( + quote! { + #[doc = #desc] + #[derive(Clone, Copy, Debug, PartialEq)] + pub enum #pc_r { + #(#vars),* + } + }, + ); let mut enum_items = vec![]; - let mut arms = variants.iter() - .map(|v| { - let value = util::unsuffixed(v.value); - let pc = &v.pc; + let mut arms = variants + .iter() + .map( + |v| { + let value = util::unsuffixed(v.value); + let pc = &v.pc; - quote! { - #pc_r::#pc => #value - } - }) + quote! { + #pc_r::#pc => #value + } + }, + ) .collect::>(); if has_reserved_variant { - arms.push(quote! { - #pc_r::_Reserved(bits) => bits - }); - } - enum_items.push(quote! { - /// Value of the field as raw bits - #[inline(always)] - pub fn bits(&self) -> #fty { - match *self { - #(#arms),* - } - } - }); - - let mut arms = variants.iter() - .map(|v| { - let i = util::unsuffixed(v.value); - let pc = &v.pc; - + arms.push( quote! { - #i => #pc_r::#pc + #pc_r::_Reserved(bits) => bits + }, + ); + } + enum_items.push( + quote! { + /// Value of the field as raw bits + #[inline(always)] + pub fn bits(&self) -> #fty { + match *self { + #(#arms),* + } } - }) + }, + ); + + let mut arms = variants + .iter() + .map( + |v| { + let i = util::unsuffixed(v.value); + let pc = &v.pc; + + quote! { + #i => #pc_r::#pc + } + }, + ) .collect::>(); if has_reserved_variant { - arms.push(quote! { - i => #pc_r::_Reserved(i) - }); + arms.push( + quote! { + i => #pc_r::_Reserved(i) + }, + ); } else { - arms.push(quote! { - _ => unreachable!() - }); + arms.push( + quote! { + _ => unreachable!() + }, + ); } - enum_items.push(quote! { - #[allow(missing_docs)] - #[doc(hidden)] - #[inline(always)] - pub fn _from(bits: #fty) -> #pc_r { - match bits { - #(#arms),*, + enum_items.push( + quote! { + #[allow(missing_docs)] + #[doc(hidden)] + #[inline(always)] + pub fn _from(bits: #fty) -> #pc_r { + match bits { + #(#arms),*, + } } - } - }); + }, + ); for v in &variants { let pc = &v.pc; @@ -735,52 +865,60 @@ pub fn fields( Ident::new(&*format!("is_{}", sc)) }; - let doc = format!("Checks if \ - the value of the field \ - is `{}`", - pc); - enum_items.push(quote! { - #[doc = #doc] - #[inline(always)] - pub fn #is_variant(&self) -> bool { - *self == #pc_r::#pc - } - }); + let doc = format!( + "Checks if the value of the field is `{}`", + pc + ); + enum_items.push( + quote! { + #[doc = #doc] + #[inline(always)] + pub fn #is_variant(&self) -> bool { + *self == #pc_r::#pc + } + }, + ); } - mod_items.push(quote! { - impl #pc_r { - #(#enum_items)* - } - }); + mod_items.push( + quote! { + impl #pc_r { + #(#enum_items)* + } + }, + ); } } else { let description = &f.description; let pc_r = &f.pc_r; let sc = &f.sc; - r_impl_items.push(quote! { - #[doc = #description] - #[inline(always)] - pub fn #sc(&self) -> #pc_r { - let bits = { # bits }; - #pc_r { bits } - } - }); + r_impl_items.push( + quote! { + #[doc = #description] + #[inline(always)] + pub fn #sc(&self) -> #pc_r { + let bits = { # bits }; + #pc_r { bits } + } + }, + ); - mod_items.push(quote! { - /// Value of the field - pub struct #pc_r { - bits: #fty, - } + mod_items.push( + quote! { + /// Value of the field + pub struct #pc_r { + bits: #fty, + } - impl #pc_r { - /// Value of the field as raw bits - #[inline(always)] - pub fn bits(&self) -> #fty { - self.bits + impl #pc_r { + /// Value of the field as raw bits + #[inline(always)] + pub fn bits(&self) -> #fty { + self.bits + } } - } - }); + }, + ); } } @@ -798,13 +936,12 @@ pub fn fields( if let Some(write_constraint) = f.write_constraint { match *write_constraint { WriteConstraint::Range(ref range) => { - if range.min == 0 && - range.max == (1 << f.width) - 1 { + if range.min == 0 && range.max == (1 << f.width) - 1 { // the SVD has acknowledged that it's safe to write // any value that can fit in the bitfield safety = None; } - }, + } _ => {} } } @@ -813,12 +950,14 @@ pub fn fields( let mask = &f.mask; if let Some((evs, base)) = - util::lookup(&f.evs, - fields, - parent, - all_registers, - peripheral, - Usage::Write)? { + util::lookup( + &f.evs, + fields, + parent, + all_registers, + peripheral, + Usage::Write, + )? { struct Variant { doc: String, pc: Ident, @@ -827,46 +966,56 @@ pub fn fields( } let pc_w = &f.pc_w; - let pc_w_doc = format!("Values that can be written to \ - the field `{}`", - f.name); - - let base_pc_w = base.as_ref().map(|base| { - let pc = base.field.to_sanitized_pascal_case(); - let base_pc_w = Ident::new(&*format!("{}W", pc)); - - if let Some(ref register) = base.register { - let mod_ = - Ident::new(&*register.to_sanitized_snake_case()); - - mod_items.push(quote! { - #[doc = #pc_w_doc] - pub type #pc_w = super::#mod_::#base_pc_w; - }); - - quote! { - super::#mod_::#base_pc_w - } - } else { - mod_items.push(quote! { - #[doc = #pc_w_doc] - pub type #pc_w = #base_pc_w; - }); - - quote! { - #base_pc_w - } - } - }); + let pc_w_doc = format!( + "Values that can be written to the field `{}`", + f.name + ); + + let base_pc_w = base.as_ref() + .map( + |base| { + let pc = base.field.to_sanitized_pascal_case(); + let base_pc_w = Ident::new(&*format!("{}W", pc)); + + if let Some(ref register) = base.register { + let mod_ = register.to_sanitized_snake_case(); + let mod_ = Ident::new(&*mod_); + + mod_items.push( + quote! { + #[doc = #pc_w_doc] + pub type #pc_w = + super::#mod_::#base_pc_w; + }, + ); + + quote! { + super::#mod_::#base_pc_w + } + } else { + mod_items.push( + quote! { + #[doc = #pc_w_doc] + pub type #pc_w = #base_pc_w; + }, + ); + + quote! { + #base_pc_w + } + } + }, + ); let variants = evs.values .iter() - .map(|ev| { - let value = u64(ev.value.ok_or_else(|| { + .map( + |ev| { + let value = u64(ev.value.ok_or_else(|| { format!("EnumeratedValue {} has no `` field", ev.name)})?); - Ok(Variant { + Ok(Variant { doc: ev.description .clone() .unwrap_or_else(|| { @@ -878,7 +1027,8 @@ pub fn fields( .to_sanitized_snake_case()), value: value, }) - }) + }, + ) .collect::>>()?; if variants.len() == 1 << f.width { @@ -888,47 +1038,57 @@ pub fn fields( if base.is_none() { let variants_pc = variants.iter().map(|v| &v.pc); let variants_doc = variants.iter().map(|v| &*v.doc); - mod_items.push(quote! { - #[doc = #pc_w_doc] - pub enum #pc_w { - #(#[doc = #variants_doc] - #variants_pc),* - } - }); - - let arms = variants.iter().map(|v| { - let pc = &v.pc; - let value = util::unsuffixed(v.value); - + mod_items.push( quote! { - #pc_w::#pc => #value - } - }); + #[doc = #pc_w_doc] + pub enum #pc_w { + #(#[doc = #variants_doc] + #variants_pc),* + } + }, + ); + + let arms = variants + .iter() + .map( + |v| { + let pc = &v.pc; + let value = util::unsuffixed(v.value); + + quote! { + #pc_w::#pc => #value + } + }, + ); - mod_items.push(quote! { - impl #pc_w { - #[allow(missing_docs)] - #[doc(hidden)] - #[inline(always)] - pub fn _bits(&self) -> #fty { - match *self { - #(#arms),* + mod_items.push( + quote! { + impl #pc_w { + #[allow(missing_docs)] + #[doc(hidden)] + #[inline(always)] + pub fn _bits(&self) -> #fty { + match *self { + #(#arms),* + } } } - } - }); + }, + ); } - proxy_items.push(quote! { - /// Writes `variant` to the field - #[inline(always)] - pub fn variant(self, variant: #pc_w) -> &'a mut W { - #safety { - self.bits(variant._bits()) + proxy_items.push( + quote! { + /// Writes `variant` to the field + #[inline(always)] + pub fn variant(self, variant: #pc_w) -> &'a mut W { + #safety { + self.bits(variant._bits()) + } } - } - }); + }, + ); for v in &variants { let pc = &v.pc; @@ -936,59 +1096,69 @@ pub fn fields( let doc = util::respace(&v.doc); if let Some(enum_) = base_pc_w.as_ref() { - proxy_items.push(quote! { - #[doc = #doc] - #[inline(always)] - pub fn #sc(self) -> &'a mut W { - self.variant(#enum_::#pc) - } - }); + proxy_items.push( + quote! { + #[doc = #doc] + #[inline(always)] + pub fn #sc(self) -> &'a mut W { + self.variant(#enum_::#pc) + } + }, + ); } else { - proxy_items.push(quote! { - #[doc = #doc] - #[inline(always)] - pub fn #sc(self) -> &'a mut W { - self.variant(#pc_w::#pc) - } - }); + proxy_items.push( + quote! { + #[doc = #doc] + #[inline(always)] + pub fn #sc(self) -> &'a mut W { + self.variant(#pc_w::#pc) + } + }, + ); } } } - proxy_items.push(quote! { - /// Writes raw bits to the field - #[inline(always)] - pub #safety fn bits(self, bits: #fty) -> &'a mut W { - const MASK: #fty = #mask; - const OFFSET: u8 = #offset; + proxy_items.push( + quote! { + /// Writes raw bits to the field + #[inline(always)] + pub #safety fn bits(self, bits: #fty) -> &'a mut W { + const MASK: #fty = #mask; + const OFFSET: u8 = #offset; - self.w.bits &= !((MASK as #rty) << OFFSET); - self.w.bits |= ((bits & MASK) as #rty) << OFFSET; - self.w - } - }); + self.w.bits &= !((MASK as #rty) << OFFSET); + self.w.bits |= ((bits & MASK) as #rty) << OFFSET; + self.w + } + }, + ); let _pc_w = &f._pc_w; - mod_items.push(quote! { - /// Proxy - pub struct #_pc_w<'a> { - w: &'a mut W, - } + mod_items.push( + quote! { + /// Proxy + pub struct #_pc_w<'a> { + w: &'a mut W, + } - impl<'a> #_pc_w<'a> { - #(#proxy_items)* - } - }); + impl<'a> #_pc_w<'a> { + #(#proxy_items)* + } + }, + ); let description = &f.description; let sc = &f.sc; - w_impl_items.push(quote! { - #[doc = #description] - #[inline(always)] - pub fn #sc(&mut self) -> #_pc_w { - #_pc_w { w: self } - } - }) + w_impl_items.push( + quote! { + #[doc = #description] + #[inline(always)] + pub fn #sc(&mut self) -> #_pc_w { + #_pc_w { w: self } + } + }, + ) } } diff --git a/src/main.rs b/src/main.rs index f394f69d..0a83da74 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,15 +27,20 @@ fn run() -> Result<()> { let matches = App::new("svd2rust") .about("Generate a Rust API from SVD files") - .arg(Arg::with_name("input") - .help("Input SVD file") - .required(true) - .short("i") - .takes_value(true) - .value_name("FILE")) - .version(concat!(env!("CARGO_PKG_VERSION"), - include_str!(concat!(env!("OUT_DIR"), - "/commit-info.txt")))) + .arg( + Arg::with_name("input") + .help("Input SVD file") + .required(true) + .short("i") + .takes_value(true) + .value_name("FILE"), + ) + .version( + concat!( + env!("CARGO_PKG_VERSION"), + include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")) + ), + ) .get_matches(); let xml = &mut String::new(); @@ -49,10 +54,12 @@ fn run() -> Result<()> { let mut items = vec![]; generate::device(&device, &mut items)?; - println!("{}", - quote! { - #(#items)* - }); + println!( + "{}", + quote! { + #(#items)* + } + ); Ok(()) } @@ -73,8 +80,10 @@ fn main() { if let Some(backtrace) = e.backtrace() { writeln!(stderr, "backtrace: {:?}", backtrace).ok(); } else { - writeln!(stderr, - "note: run with `RUST_BACKTRACE=1` for a backtrace") + writeln!( + stderr, + "note: run with `RUST_BACKTRACE=1` for a backtrace" + ) .ok(); } diff --git a/src/util.rs b/src/util.rs index 39f9479f..fa75cdfa 100644 --- a/src/util.rs +++ b/src/util.rs @@ -131,14 +131,18 @@ pub fn expand(registers: &[Register]) -> Vec { for r in registers { match *r { Register::Single(ref info) => { - out.push(ExpandedRegister { - info: info, - name: info.name.to_sanitized_snake_case().into_owned(), - offset: info.address_offset, - ty: Either::Left(info.name - .to_sanitized_pascal_case() - .into_owned()), - }) + out.push( + ExpandedRegister { + info: info, + name: info.name.to_sanitized_snake_case().into_owned(), + offset: info.address_offset, + ty: Either::Left( + info.name + .to_sanitized_pascal_case() + .into_owned(), + ), + }, + ) } Register::Array(ref info, ref array_info) => { let has_brackets = info.name.contains("[%s]"); @@ -151,14 +155,19 @@ pub fn expand(registers: &[Register]) -> Vec { let ty = Rc::new(ty.to_sanitized_pascal_case().into_owned()); - let indices = array_info.dim_index + let indices = array_info + .dim_index .as_ref() .map(|v| Cow::from(&**v)) - .unwrap_or_else(|| { - Cow::from((0..array_info.dim) - .map(|i| i.to_string()) - .collect::>()) - }); + .unwrap_or_else( + || { + Cow::from( + (0..array_info.dim) + .map(|i| i.to_string()) + .collect::>(), + ) + }, + ); for (idx, i) in indices.iter().zip(0..) { let name = if has_brackets { @@ -170,13 +179,14 @@ pub fn expand(registers: &[Register]) -> Vec { let offset = info.address_offset + i * array_info.dim_increment; - out.push(ExpandedRegister { - info: info, - name: name.to_sanitized_snake_case() - .into_owned(), - offset: offset, - ty: Either::Right(ty.clone()), - }); + out.push( + ExpandedRegister { + info: info, + name: name.to_sanitized_snake_case().into_owned(), + offset: offset, + ty: Either::Right(ty.clone()), + }, + ); } } } @@ -201,23 +211,23 @@ pub fn name_of(register: &Register) -> Cow { } pub fn access_of(register: &Register) -> Access { - register.access.unwrap_or_else(|| if let Some(ref fields) = - register.fields { - if fields.iter().all(|f| { - f.access == - Some(Access::ReadOnly) - }) { - Access::ReadOnly - } else if fields.iter().all(|f| { - f.access == Some(Access::WriteOnly) - }) { - Access::WriteOnly - } else { - Access::ReadWrite - } - } else { - Access::ReadWrite - }) + register + .access + .unwrap_or_else( + || if let Some(ref fields) = register.fields { + if fields.iter().all(|f| f.access == Some(Access::ReadOnly)) { + Access::ReadOnly + } else if fields + .iter() + .all(|f| f.access == Some(Access::WriteOnly),) { + Access::WriteOnly + } else { + Access::ReadWrite + } + } else { + Access::ReadWrite + }, + ) } /// Turns `n` into an unsuffixed literal @@ -234,40 +244,39 @@ pub struct Base<'a> { pub fn lookup<'a> ( evs: &'a [EnumeratedValues], - fields: &'a [Field], - register: &'a Register, - all_registers: &'a [Register], - peripheral: &'a Peripheral, - usage: Usage, + fields: &'a [Field], + register: &'a Register, + all_registers: &'a [Register], + peripheral: &'a Peripheral, + usage: Usage, ) -> Result>)>> { let evs = evs.iter() - .map(|evs| if let Some(ref base) = evs.derived_from { - let mut parts = base.split('.'); - - match (parts.next(), parts.next(), parts.next()) { - (Some(base_register), - Some(base_field), - Some(base_evs)) => { - lookup_in_peripheral(base_register, - base_field, - base_evs, - all_registers, - peripheral) - } - (Some(base_field), Some(base_evs), None) => { - lookup_in_fields(base_evs, - base_field, - fields, - register) - } - (Some(base_evs), None, None) => { - lookup_in_register(base_evs, register) - } - _ => unreachable!(), - } - } else { - Ok((evs, None)) - }) + .map( + |evs| if let Some(ref base) = evs.derived_from { + let mut parts = base.split('.'); + + match (parts.next(), parts.next(), parts.next()) { + (Some(base_register), Some(base_field), Some(base_evs)) => { + lookup_in_peripheral( + base_register, + base_field, + base_evs, + all_registers, + peripheral, + ) + } + (Some(base_field), Some(base_evs), None) => { + lookup_in_fields(base_evs, base_field, fields, register) + } + (Some(base_evs), None, None) => { + lookup_in_register(base_evs, register) + } + _ => unreachable!(), + } + } else { + Ok((evs, None)) + }, + ) .collect::>>()?; for &(ref evs, ref base) in evs.iter() { @@ -288,25 +297,31 @@ fn lookup_in_fields<'f>( if let Some(base_field) = fields.iter().find(|f| f.name == base_field) { return lookup_in_field(base_evs, None, base_field); } else { - Err(format!("Field {} not found in register {}", - base_field, - register.name))? + Err( + format!( + "Field {} not found in register {}", + base_field, + register.name + ), + )? } } fn lookup_in_peripheral<'p> ( base_register: &'p str, - base_field: &str, - base_evs: &str, - all_registers: &'p [Register], - peripheral: &'p Peripheral, + base_field: &str, + base_evs: &str, + all_registers: &'p [Register], + peripheral: &'p Peripheral, ) -> Result<(&'p EnumeratedValues, Option>)> { - if let Some(register) = all_registers.iter().find(|r| { - r.name == - base_register - }) { - if let Some(field) = register.fields + if let Some(register) = all_registers.iter().find( + |r| { + r.name == base_register + }, + ) { + if let Some(field) = register + .fields .as_ref() .map(|fs| &**fs) .unwrap_or(&[]) @@ -314,14 +329,22 @@ fn lookup_in_peripheral<'p> .find(|f| f.name == base_field) { lookup_in_field(base_evs, Some(base_register), field) } else { - Err(format!("No field {} in register {}", - base_field, - register.name))? + Err( + format!( + "No field {} in register {}", + base_field, + register.name + ), + )? } } else { - Err(format!("No register {} in peripheral {}", - base_register, - peripheral.name))? + Err( + format!( + "No register {} in peripheral {}", + base_register, + peripheral.name + ), + )? } } @@ -332,59 +355,71 @@ fn lookup_in_field<'f>( ) -> Result<(&'f EnumeratedValues, Option>)> { for evs in &field.enumerated_values { if evs.name.as_ref().map(|s| &**s) == Some(base_evs) { - return Ok(((evs, - Some(Base { - field: &field.name, - register: base_register, - })))); + return Ok( + ((evs, + Some( + Base { + field: &field.name, + register: base_register, + }, + ))), + ); } } - Err(format!("No EnumeratedValues {} in field {}", base_evs, field.name))? + Err(format!("No EnumeratedValues {} in field {}", base_evs, field.name),)? } fn lookup_in_register<'r> ( base_evs: &str, - register: &'r Register, + register: &'r Register, ) -> Result<(&'r EnumeratedValues, Option>)> { let mut matches = vec![]; - for f in register.fields - .as_ref() - .map(|v| &**v) - .unwrap_or(&[]) { - if let Some(evs) = f.enumerated_values.iter().find(|evs| { - evs.name - .as_ref() - .map(|s| &**s) == - Some(base_evs) - }) { + for f in register.fields.as_ref().map(|v| &**v).unwrap_or(&[]) { + if let Some(evs) = + f.enumerated_values + .iter() + .find(|evs| evs.name.as_ref().map(|s| &**s) == Some(base_evs)) { matches.push((evs, &f.name)) } } match matches.first() { None => { - Err(format!("EnumeratedValues {} not found in register {}", - base_evs, - register.name))? + Err( + format!( + "EnumeratedValues {} not found in register {}", + base_evs, + register.name + ), + )? } Some(&(evs, field)) => { if matches.len() == 1 { - return Ok((evs, - Some(Base { - field: field, - register: None, - }))); + return Ok( + (evs, + Some( + Base { + field: field, + register: None, + }, + )), + ); } else { - let fields = matches.iter() + let fields = matches + .iter() .map(|&(ref f, _)| &f.name) .collect::>(); - Err(format!("Fields {:?} have an \ + Err( + format!( + "Fields {:?} have an \ enumeratedValues named {}", - fields, - base_evs))? + fields, + base_evs + ), + )? } } } @@ -396,14 +431,20 @@ pub trait U32Ext { impl U32Ext for u32 { fn to_ty(&self) -> Result { - Ok(match *self { - 1...8 => Ident::new("u8"), - 9...16 => Ident::new("u16"), - 17...32 => Ident::new("u32"), - _ => { - Err(format!("can't convert {} bits into a Rust integer type", - *self))? - } - }) + Ok( + match *self { + 1...8 => Ident::new("u8"), + 9...16 => Ident::new("u16"), + 17...32 => Ident::new("u32"), + _ => { + Err( + format!( + "can't convert {} bits into a Rust integer type", + *self + ), + )? + } + }, + ) } }