From 47f4ee00c4c0ec19e925debb0cf9668e1bcef95e Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 24 Oct 2017 20:06:56 +0200 Subject: [PATCH 1/7] cargo fmt --- .rustfmt.toml | 7 - build.rs | 41 ++--- src/generate.rs | 243 +++++++++++++-------------- src/main.rs | 5 +- src/util.rs | 424 ++++++++++++++++++++++-------------------------- 5 files changed, 313 insertions(+), 407 deletions(-) delete mode 100644 .rustfmt.toml diff --git a/.rustfmt.toml b/.rustfmt.toml deleted file mode 100644 index bd7a3e01..00000000 --- a/.rustfmt.toml +++ /dev/null @@ -1,7 +0,0 @@ -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/build.rs b/build.rs index 58c48d1a..e95f20d1 100644 --- a/build.rs +++ b/build.rs @@ -33,38 +33,21 @@ fn commit_info() -> String { } fn commit_hash() -> Result { - Ok( + Ok(try!(String::from_utf8( try!( - String::from_utf8( - try!( - Command::new("git") - .args(&["rev-parse", "--short", "HEAD"]) - .output() - ) - .stdout, - ) - ), - ) + Command::new("git") + .args(&["rev-parse", "--short", "HEAD"]) + .output() + ).stdout, + ))) } fn commit_date() -> Result { - Ok( + Ok(try!(String::from_utf8( try!( - String::from_utf8( - try!( - Command::new("git") - .args( - &[ - "log", - "-1", - "--date=short", - "--pretty=format:%cd", - ], - ) - .output() - ) - .stdout, - ) - ), - ) + Command::new("git") + .args(&["log", "-1", "--date=short", "--pretty=format:%cd"]) + .output() + ).stdout, + ))) } diff --git a/src/generate.rs b/src/generate.rs index 9b949468..2eaabf91 100644 --- a/src/generate.rs +++ b/src/generate.rs @@ -2,9 +2,9 @@ use std::collections::HashMap; use std::io::{self, Write}; use cast::u64; -use quote::{Tokens, ToTokens}; -use svd::{Access, BitRange, Defaults, Device, EnumeratedValues, Field, - Peripheral, Register, Usage, WriteConstraint}; +use quote::{ToTokens, Tokens}; +use svd::{Access, BitRange, Defaults, Device, EnumeratedValues, Field, Peripheral, Register, + Usage, WriteConstraint}; use syn::{self, Ident}; use errors::*; @@ -12,11 +12,7 @@ use util::{self, ToSanitizedSnakeCase, ToSanitizedUpperCase, U32Ext, BITS_PER_BY use Target; /// Whole device generation -pub fn device( - d: &Device, - target: &Target, - items: &mut Vec, -) -> Result<()> { +pub fn device(d: &Device, target: &Target, items: &mut Vec) -> Result<()> { let doc = format!( "Peripheral access API for {0} microcontrollers \ (generated using svd2rust v{1})\n\n\ @@ -121,9 +117,7 @@ pub fn device( } for p in &d.peripherals { - if *target == Target::CortexM && - CORE_PERIPHERALS.contains(&&*p.name.to_uppercase()) - { + if *target == Target::CortexM && CORE_PERIPHERALS.contains(&&*p.name.to_uppercase()) { // Core peripherals are handled above continue; } @@ -183,8 +177,7 @@ pub fn interrupt( .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 arms = vec![]; @@ -231,19 +224,25 @@ pub fn interrupt( names.push(name_uc); } - let aliases = names.iter() - .map(|n| format!(" + let aliases = names + .iter() + .map(|n| { + format!( + " .weak {0} -{0} = DH_TRAMPOLINE", n)) - .collect::>() - .concat(); +{0} = DH_TRAMPOLINE", + n + ) + }) + .collect::>() + .concat(); let n = util::unsuffixed(u64(pos)); match *target { Target::CortexM => { let is_armv6 = match device.cpu { Some(ref cpu) => cpu.name.starts_with("CM0"), - None => true, // default to armv6 when the section is missing + None => true, // default to armv6 when the section is missing }; if is_armv6 { @@ -517,33 +516,37 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result { let mut offset = 0; let mut registers_expanded = vec![]; - // If svd register arrays can't be converted to rust arrays (non sequential adresses, non numeral indexes, or not containing all elements from 0 to size) they will be expanded + // If svd register arrays can't be converted to rust arrays (non sequential adresses, non + // numeral indexes, or not containing all elements from 0 to size) they will be expanded for register in registers { - let register_size = register.size.or(defs.size) - .ok_or_else( - || { - format!("Register {} has no `size` field", register.name) - },)?; - + let register_size = register + .size + .or(defs.size) + .ok_or_else(|| format!("Register {} has no `size` field", register.name))?; + match *register { - Register::Single(ref info) => registers_expanded.push( - RegisterBlockField{ - field: util::convert_svd_register(register), - description: info.description.clone(), - offset: info.address_offset, - size: register_size, - } - ), + Register::Single(ref info) => registers_expanded.push(RegisterBlockField { + field: util::convert_svd_register(register), + description: info.description.clone(), + offset: info.address_offset, + size: register_size, + }), Register::Array(ref info, ref array_info) => { - let sequential_adresses = register_size == array_info.dim_increment*BITS_PER_BYTE; - - let numeral_indexes = array_info.dim_index.clone() - .ok_or_else( || format!("Register {} has no `dim_index` field", register.name))? + let sequential_adresses = register_size == array_info.dim_increment * BITS_PER_BYTE; + + let numeral_indexes = array_info + .dim_index + .clone() + .ok_or_else(|| { + format!("Register {} has no `dim_index` field", register.name) + })? .iter() .all(|element| element.parse::().is_ok()); - + let sequential_indexes = if numeral_indexes && sequential_adresses { - array_info.dim_index.clone() + array_info + .dim_index + .clone() .unwrap() .iter() .map(|element| element.parse::().unwrap()) @@ -553,30 +556,29 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result { false }; - let array_convertible = sequential_indexes && numeral_indexes && sequential_adresses; + let array_convertible = + sequential_indexes && numeral_indexes && sequential_adresses; if array_convertible { - registers_expanded.push( - RegisterBlockField{ - field: util::convert_svd_register(®ister), - description: info.description.clone(), - offset: info.address_offset, - size: register_size * array_info.dim, - }); + registers_expanded.push(RegisterBlockField { + field: util::convert_svd_register(®ister), + description: info.description.clone(), + offset: info.address_offset, + size: register_size * array_info.dim, + }); } else { let mut field_num = 0; for field in util::expand_svd_register(register).iter() { - registers_expanded.push( - RegisterBlockField{ - field: field.clone(), - description: info.description.clone(), - offset: info.address_offset + field_num * array_info.dim_increment, - size: register_size, - }); + registers_expanded.push(RegisterBlockField { + field: field.clone(), + description: info.description.clone(), + offset: info.address_offset + field_num * array_info.dim_increment, + size: register_size, + }); field_num += 1; } } - }, + } } } @@ -592,18 +594,16 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result { Ignoring.", register.field.ident.unwrap(), register.offset - ) - .ok(); + ).ok(); continue; }; if pad != 0 { let name = Ident::new(format!("_reserved{}", i)); let pad = pad as usize; - fields.append( - quote! { - #name : [u8; #pad], - }); + fields.append(quote! { + #name : [u8; #pad], + }); i += 1; } @@ -611,19 +611,16 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result { "0x{:02x} - {}", register.offset, util::respace(®ister.description), - ) - [..]; - - fields.append( - quote! { - #[doc = #comment] - } - ); - + )[..]; + + fields.append(quote! { + #[doc = #comment] + }); + register.field.to_tokens(&mut fields); Ident::new(",").to_tokens(&mut fields); - - offset = register.offset + register.size/BITS_PER_BYTE; + + offset = register.offset + register.size / BITS_PER_BYTE; } Ok(quote! { @@ -635,14 +632,11 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result { }) } -fn unsafety( - write_constraint: Option<&WriteConstraint>, - width: u32, -) -> Option { +fn unsafety(write_constraint: Option<&WriteConstraint>, width: u32) -> Option { match write_constraint { Some(&WriteConstraint::Range(ref range)) - if range.min as u64 == 0 && - range.max as u64 == (1u64 << width) - 1 => { + if range.min as u64 == 0 && range.max as u64 == (1u64 << width) - 1 => + { // the SVD has acknowledged that it's safe to write // any value that can fit in the field None @@ -669,10 +663,10 @@ pub fn register( let name = util::name_of(register); let name_pc = Ident::new(&*name.to_sanitized_upper_case()); let name_sc = Ident::new(&*name.to_sanitized_snake_case()); - let rsize = register.size.or(defs.size).ok_or_else(|| { - format!("Register {} has no `size` field", - register.name) - })?; + let rsize = register + .size + .or(defs.size) + .ok_or_else(|| format!("Register {} has no `size` field", register.name))?; let rsize = if rsize < 8 { 8 } else if rsize.is_power_of_two() { @@ -757,10 +751,7 @@ pub fn register( .reset_value .or(defs.reset_value) .map(|rv| util::hex(rv)) - .ok_or_else(|| { - format!("Register {} has no reset value", - register.name) - })?; + .ok_or_else(|| format!("Register {} has no reset value", register.name))?; w_impl_items.push(quote! { /// Reset value of the register @@ -948,16 +939,15 @@ pub fn fields( ((self.bits >> OFFSET) & MASK as #rty) #cast }; - if let Some((evs, base)) = - util::lookup( - f.evs, - fields, - parent, - all_registers, - peripheral, - all_peripherals, - Usage::Read, - )? { + if let Some((evs, base)) = util::lookup( + f.evs, + fields, + parent, + all_registers, + peripheral, + all_peripherals, + Usage::Read, + )? { struct Variant<'a> { description: &'a str, pc: Ident, @@ -997,10 +987,7 @@ pub fn fields( if let Some(ref base) = base { let pc = base.field.to_sanitized_upper_case(); let base_pc_r = Ident::new(&*format!("{}R", pc)); - let desc = format!( - "Possible values of the field `{}`", - f.name, - ); + let desc = format!("Possible values of the field `{}`", f.name,); if let (Some(ref peripheral), Some(ref register)) = (base.peripheral, base.register) @@ -1041,10 +1028,7 @@ pub fn fields( }); if base.is_none() { - let desc = format!( - "Possible values of the field `{}`", - f.name, - ); + let desc = format!("Possible values of the field `{}`", f.name,); let mut vars = variants .iter() @@ -1076,8 +1060,7 @@ pub fn fields( let mut arms = variants .iter() .map(|v| { - let value = - util::hex_or_bool(v.value as u32, f.width); + let value = util::hex_or_bool(v.value as u32, f.width); let pc = &v.pc; quote! { @@ -1160,10 +1143,7 @@ pub fn fields( Ident::new(&*format!("is_{}", sc)) }; - let doc = format!( - "Checks if the value of the field is `{}`", - pc - ); + let doc = format!("Checks if the value of the field is `{}`", pc); enum_items.push(quote! { #[doc = #doc] #[inline] @@ -1192,13 +1172,15 @@ pub fn fields( } }); - let mut pc_r_impl_items = vec![quote! { - /// Value of the field as raw bits - #[inline] - pub fn #bits(&self) -> #fty { - self.bits - } - }]; + let mut pc_r_impl_items = vec![ + quote! { + /// Value of the field as raw bits + #[inline] + pub fn #bits(&self) -> #fty { + self.bits + } + }, + ]; if f.width == 1 { pc_r_impl_items.push(quote! { @@ -1227,7 +1209,6 @@ pub fn fields( } }); } - } } @@ -1246,16 +1227,15 @@ pub fn fields( let mask = &f.mask; let width = f.width; - if let Some((evs, base)) = - util::lookup( - &f.evs, - fields, - parent, - all_registers, - peripheral, - all_peripherals, - Usage::Write, - )? { + if let Some((evs, base)) = util::lookup( + &f.evs, + fields, + parent, + all_registers, + peripheral, + all_peripherals, + Usage::Write, + )? { struct Variant { doc: String, pc: Ident, @@ -1264,10 +1244,7 @@ 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 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_upper_case(); diff --git a/src/main.rs b/src/main.rs index 01064e4c..7cf1af59 100644 --- a/src/main.rs +++ b/src/main.rs @@ -107,10 +107,7 @@ 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" - ).ok(); + writeln!(stderr, "note: run with `RUST_BACKTRACE=1` for a backtrace").ok(); } process::exit(1); diff --git a/src/util.rs b/src/util.rs index 5173deb8..fb3b1edd 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,8 +1,7 @@ use std::borrow::Cow; use inflections::Inflect; -use svd::{self, Access, EnumeratedValues, Field, Peripheral, Register, - Usage}; +use svd::{self, Access, EnumeratedValues, Field, Peripheral, Register, Usage}; use syn::{self, Ident}; use quote::Tokens; @@ -141,19 +140,24 @@ pub fn respace(s: &str) -> String { /// a list of syn::Field where the register arrays have been expanded. pub fn expand_svd_register(register: &Register) -> Vec { let name_to_ty = |name: &String| -> syn::Ty { - syn::Ty::Path(None, syn::Path{ - global: false, - segments: vec![syn::PathSegment{ - ident: Ident::new(name.to_sanitized_upper_case()), - parameters: syn::PathParameters::none(), - }], - }) + syn::Ty::Path( + None, + syn::Path { + global: false, + segments: vec![ + syn::PathSegment { + ident: Ident::new(name.to_sanitized_upper_case()), + parameters: syn::PathParameters::none(), + }, + ], + }, + ) }; let mut out = vec![]; match *register { - Register::Single(ref _info) => out.push( convert_svd_register(register) ), + Register::Single(ref _info) => out.push(convert_svd_register(register)), Register::Array(ref info, ref array_info) => { let has_brackets = info.name.contains("[%s]"); @@ -161,65 +165,64 @@ pub fn expand_svd_register(register: &Register) -> Vec { .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 { info.name.replace("[%s]", format!("{}", idx).as_str()) } else { info.name.replace("%s", format!("{}", idx).as_str()) }; - + let ty_name = if has_brackets { info.name.replace("[%s]", "") } else { info.name.replace("%s", "") }; - + let ident = Ident::new(name.to_sanitized_snake_case()); let ty = name_to_ty(&ty_name); - out.push( - syn::Field{ - ident: Some(ident), - vis: syn::Visibility::Public, - attrs: vec![], - ty: ty, - } - ); + out.push(syn::Field { + ident: Some(ident), + vis: syn::Visibility::Public, + attrs: vec![], + ty: ty, + }); } - }, + } } out } pub fn convert_svd_register(register: &svd::Register) -> syn::Field { let name_to_ty = |name: &String| -> syn::Ty { - syn::Ty::Path(None, syn::Path{ - global: false, - segments: vec![syn::PathSegment{ - ident: Ident::new(name.to_sanitized_upper_case()), - parameters: syn::PathParameters::none(), - }], - }) + syn::Ty::Path( + None, + syn::Path { + global: false, + segments: vec![ + syn::PathSegment { + ident: Ident::new(name.to_sanitized_upper_case()), + parameters: syn::PathParameters::none(), + }, + ], + }, + ) }; - + match *register { - Register::Single(ref info) => { - syn::Field{ - ident: Some(Ident::new(info.name.to_sanitized_snake_case())), - vis: syn::Visibility::Public, - attrs: vec![], - ty: name_to_ty(&info.name), - } + Register::Single(ref info) => syn::Field { + ident: Some(Ident::new(info.name.to_sanitized_snake_case())), + vis: syn::Visibility::Public, + attrs: vec![], + ty: name_to_ty(&info.name), }, Register::Array(ref info, ref array_info) => { let has_brackets = info.name.contains("[%s]"); @@ -229,55 +232,49 @@ pub fn convert_svd_register(register: &svd::Register) -> syn::Field { } else { info.name.replace("%s", "") }; - + let ident = Ident::new(name.to_sanitized_snake_case()); - + let ty = syn::Ty::Array( Box::new(name_to_ty(&name)), syn::ConstExpr::Lit(syn::Lit::Int(array_info.dim as u64, syn::IntTy::Unsuffixed)), ); - syn::Field{ + syn::Field { ident: Some(ident), vis: syn::Visibility::Public, attrs: vec![], ty: ty, } - }, + } } } pub fn name_of(register: &Register) -> Cow { match *register { Register::Single(ref info) => Cow::from(&*info.name), - Register::Array(ref info, _) => { - if info.name.contains("[%s]") { - info.name.replace("[%s]", "").into() - } else { - info.name.replace("%s", "").into() - } - } + Register::Array(ref info, _) => if info.name.contains("[%s]") { + info.name.replace("[%s]", "").into() + } else { + info.name.replace("%s", "").into() + }, } } 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 - } + .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 separated hex token @@ -330,8 +327,7 @@ pub struct Base<'a> { pub field: &'a str, } -pub fn lookup<'a> - ( +pub fn lookup<'a>( evs: &'a [EnumeratedValues], fields: &'a [Field], register: &'a Register, @@ -341,42 +337,38 @@ pub fn lookup<'a> 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(), parts.next()) { - (Some(base_peripheral), Some(base_register), Some(base_field), Some(base_evs)) => { - lookup_in_peripherals( - base_peripheral, - base_register, - base_field, - base_evs, - all_peripherals, - ) - } - (Some(base_register), Some(base_field), Some(base_evs), None) => { - lookup_in_peripheral( - None, - base_register, - base_field, - base_evs, - all_registers, - peripheral, - ) - } - (Some(base_field), Some(base_evs), None, None) => { - lookup_in_fields(base_evs, base_field, fields, register) - } - (Some(base_evs), None, None, None) => { - lookup_in_register(base_evs, register) - } - _ => unreachable!(), + .map(|evs| if let Some(ref base) = evs.derived_from { + let mut parts = base.split('.'); + + match (parts.next(), parts.next(), parts.next(), parts.next()) { + (Some(base_peripheral), Some(base_register), Some(base_field), Some(base_evs)) => { + lookup_in_peripherals( + base_peripheral, + base_register, + base_field, + base_evs, + all_peripherals, + ) } - } else { - Ok((evs, None)) - }, - ) + (Some(base_register), Some(base_field), Some(base_evs), None) => { + lookup_in_peripheral( + None, + base_register, + base_field, + base_evs, + all_registers, + peripheral, + ) + } + (Some(base_field), Some(base_evs), None, None) => { + lookup_in_fields(base_evs, base_field, fields, register) + } + (Some(base_evs), None, None, None) => lookup_in_register(base_evs, register), + _ => unreachable!(), + } + } else { + Ok((evs, None)) + }) .collect::>>()?; for &(ref evs, ref base) in evs.iter() { @@ -397,18 +389,15 @@ 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, 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> - ( +fn lookup_in_peripheral<'p>( base_peripheral: Option<&'p str>, base_register: &'p str, base_field: &str, @@ -416,36 +405,29 @@ fn lookup_in_peripheral<'p> 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(register) = all_registers.iter().find(|r| r.name == base_register) { if let Some(field) = register - .fields - .as_ref() - .map(|fs| &**fs) - .unwrap_or(&[]) - .iter() - .find(|f| f.name == base_field) { + .fields + .as_ref() + .map(|fs| &**fs) + .unwrap_or(&[]) + .iter() + .find(|f| f.name == base_field) + { lookup_in_field(base_evs, Some(base_register), base_peripheral, 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 + ))? } } @@ -458,89 +440,80 @@ fn lookup_in_field<'f>( for evs in &field.enumerated_values { if evs.name.as_ref().map(|s| &**s) == Some(base_evs) { return Ok( - ((evs, - Some( - Base { + (( + evs, + Some(Base { field: &field.name, register: base_register, peripheral: base_peripheral, - }, - ))), + }), + )), ); } } - 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> - ( +fn lookup_in_register<'r>( base_evs: &str, 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)) { + 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 - ), - )? - } - Some(&(evs, field)) => { - if matches.len() == 1 { - return Ok( - (evs, - Some( - Base { - field: field, - register: None, - peripheral: None - }, - )), - ); - } else { - let fields = matches - .iter() - .map(|&(ref f, _)| &f.name) - .collect::>(); - Err( - format!( - "Fields {:?} have an \ - enumeratedValues named {}", - fields, - base_evs - ), - )? - } - } + None => 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, + peripheral: None, + }), + )); + } else { + let fields = matches + .iter() + .map(|&(ref f, _)| &f.name) + .collect::>(); + Err(format!( + "Fields {:?} have an \ + enumeratedValues named {}", + fields, + base_evs + ))? + }, } } -fn lookup_in_peripherals<'p> -( +fn lookup_in_peripherals<'p>( base_peripheral: &'p str, base_register: &'p str, base_field: &str, base_evs: &str, all_peripherals: &'p [Peripheral], ) -> Result<(&'p EnumeratedValues, Option>)> { - if let Some(peripheral) = all_peripherals - .iter() - .find(|p| { p.name == base_peripheral }) { - let all_registers = peripheral.registers + if let Some(peripheral) = all_peripherals.iter().find(|p| p.name == base_peripheral) { + let all_registers = peripheral + .registers .as_ref() .map(|x| x.as_ref()) .unwrap_or(&[][..]); @@ -550,15 +523,10 @@ fn lookup_in_peripherals<'p> base_field, base_evs, all_registers, - peripheral + peripheral, ) } else { - Err( - format!( - "No peripheral {}", - base_peripheral - ), - )? + Err(format!("No peripheral {}", base_peripheral))? } } @@ -570,40 +538,28 @@ pub trait U32Ext { impl U32Ext for u32 { fn to_ty(&self) -> Result { - Ok( - match *self { - 1 => Ident::new("bool"), - 2...8 => Ident::new("u8"), - 9...16 => Ident::new("u16"), - 17...32 => Ident::new("u32"), - _ => { - Err( - format!( - "can't convert {} bits into a Rust integral type", - *self - ), - )? - } - }, - ) + Ok(match *self { + 1 => Ident::new("bool"), + 2...8 => Ident::new("u8"), + 9...16 => Ident::new("u16"), + 17...32 => Ident::new("u32"), + _ => Err(format!( + "can't convert {} bits into a Rust integral type", + *self + ))?, + }) } fn to_ty_width(&self) -> Result { - Ok( - match *self { - 1 => 1, - 2...8 => 8, - 9...16 => 16, - 17...32 => 32, - _ => { - Err( - format!( - "can't convert {} bits into a Rust integral type width", - *self - ), - )? - } - } - ) + Ok(match *self { + 1 => 1, + 2...8 => 8, + 9...16 => 16, + 17...32 => 32, + _ => Err(format!( + "can't convert {} bits into a Rust integral type width", + *self + ))?, + }) } } From d5c07e9746de92ef4721435b3fe90a052b3b963e Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 21 Nov 2017 16:00:34 +0100 Subject: [PATCH 2/7] peripherals as scoped singletons --- src/generate.rs | 102 +++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 45 deletions(-) diff --git a/src/generate.rs b/src/generate.rs index 2eaabf91..d73ecfbc 100644 --- a/src/generate.rs +++ b/src/generate.rs @@ -38,6 +38,7 @@ pub fn device(d: &Device, target: &Target, items: &mut Vec) -> Result<() items.push(quote! { #![doc = #doc] + #![allow(private_no_mangle_statics)] #![deny(missing_docs)] #![deny(warnings)] #![allow(non_camel_case_types)] @@ -69,8 +70,7 @@ pub fn device(d: &Device, target: &Target, items: &mut Vec) -> Result<() extern crate vcell; use core::ops::Deref; - - use bare_metal::Peripheral; + use core::marker::PhantomData; }); if let Some(cpu) = d.cpu.as_ref() { @@ -101,18 +101,16 @@ pub fn device(d: &Device, target: &Target, items: &mut Vec) -> Result<() let mut fields = vec![]; let mut exprs = vec![]; if *target == Target::CortexM { + items.push(quote! { + pub use cortex_m::peripheral::Peripherals as CorePeripherals; + }); + for p in CORE_PERIPHERALS { let id = Ident::new(*p); items.push(quote! { pub use cortex_m::peripheral::#id; }); - - fields.push(quote! { - #[doc = #p] - pub #id: &'a #id - }); - exprs.push(quote!(#id: &*#id.get())); } } @@ -139,21 +137,39 @@ pub fn device(d: &Device, target: &Target, items: &mut Vec) -> Result<() let id = Ident::new(&*p); fields.push(quote! { #[doc = #p] - pub #id: &'a #id + pub #id: #id }); - exprs.push(quote!(#id: &*#id.get())); + exprs.push(quote!(#id: #id { _marker: PhantomData })); } items.push(quote! { + #[no_mangle] + static mut PERIPHERALS: bool = false; + /// All the peripherals #[allow(non_snake_case)] - pub struct Peripherals<'a> { + pub struct Peripherals { #(#fields,)* } - impl<'a> Peripherals<'a> { - /// Grants access to all the peripherals - pub unsafe fn all() -> Self { + impl Peripherals { + /// Returns all the peripherals *once* + pub fn all() -> Option { + cortex_m::interrupt::free(|_| { + if unsafe { PERIPHERALS } { + None + } else { + Some(unsafe { Peripherals::_all() }) + } + }) + } + + #[doc(hidden)] + pub unsafe fn _all() -> Self { + debug_assert!(!PERIPHERALS); + + PERIPHERALS = true; + Peripherals { #(#exprs,)* } @@ -421,36 +437,44 @@ pub fn peripheral( items: &mut Vec, defaults: &Defaults, ) -> Result<()> { - let name = Ident::new(&*p.name.to_uppercase()); let name_pc = Ident::new(&*p.name.to_sanitized_upper_case()); let address = util::hex(p.base_address); let description = util::respace(p.description.as_ref().unwrap_or(&p.name)); + let name_sc = Ident::new(&*p.name.to_sanitized_snake_case()); + let (base, derived) = if let Some(base) = p.derived_from.as_ref() { + // TODO Verify that base exists + // TODO We don't handle inheritance style `derivedFrom`, we should raise + // an error in that case + (Ident::new(&*base.to_sanitized_snake_case()), true) + } else { + (name_sc.clone(), false) + }; + items.push(quote! { #[doc = #description] - pub const #name: Peripheral<#name_pc> = - unsafe { Peripheral::new(#address) }; - }); + pub struct #name_pc { _marker: PhantomData<*const ()> } - 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 } + unsafe impl Send for #name_pc {} - impl Deref for #name_pc { - type Target = #base_sc::RegisterBlock; + impl #name_pc { + /// Returns a pointer to the register block + pub fn ptr() -> *const #base::RegisterBlock { + #address as *const _ + } + } - fn deref(&self) -> &#base_sc::RegisterBlock { - &self.register_block - } + impl Deref for #name_pc { + type Target = #base::RegisterBlock; + + fn deref(&self) -> &#base::RegisterBlock { + unsafe { &*#name_pc::ptr() } } - }); + } + }); - // TODO We don't handle inheritance style `derivedFrom`, we should raise - // an error in that case - return Ok(()); + if derived { + return Ok(()) } let registers = p.registers.as_ref().map(|x| x.as_ref()).unwrap_or(&[][..]); @@ -476,7 +500,6 @@ 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] @@ -485,17 +508,6 @@ pub fn peripheral( #(#mod_items)* } - - #[doc = #description] - pub struct #name_pc { register_block: #name_sc::RegisterBlock } - - impl Deref for #name_pc { - type Target = #name_sc::RegisterBlock; - - fn deref(&self) -> &#name_sc::RegisterBlock { - &self.register_block - } - } }); Ok(()) From e114878c9a243821789c6ef74167bc565100caa5 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 9 Dec 2017 11:21:44 +0100 Subject: [PATCH 3/7] s/all/take/g, s/_all/steal/g and tweak CI --- .travis.yml | 2 +- Cargo.toml | 2 +- ci/install.sh | 2 +- ci/script.sh | 9 ++++----- src/generate.rs | 17 ++++++++++------- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index f5c64e13..de46deef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,7 +47,7 @@ matrix: os: osx install: - - sh ci/install.sh + - bash ci/install.sh script: - bash ci/script.sh diff --git a/Cargo.toml b/Cargo.toml index 030bd2ac..d5190020 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ keywords = [ license = "MIT OR Apache-2.0" name = "svd2rust" repository = "https://github.com/japaric/svd2rust" -version = "0.11.4" +version = "0.12.0" [[bin]] doc = false diff --git a/ci/install.sh b/ci/install.sh index d235cce2..b230a6e1 100644 --- a/ci/install.sh +++ b/ci/install.sh @@ -1,4 +1,4 @@ -set -ex +set -euxo pipefail main() { local sort= diff --git a/ci/script.sh b/ci/script.sh index 7d58f62a..7e07c9e8 100644 --- a/ci/script.sh +++ b/ci/script.sh @@ -1,5 +1,4 @@ -set -ex -set -o pipefail +set -euxo pipefail test_svd() { ( @@ -15,7 +14,7 @@ test_svd() { } main() { - cross build --target $TARGET + cross check --target $TARGET if [ -z $VENDOR ]; then return @@ -35,7 +34,7 @@ main() { # test crate cargo init --name foo $td echo 'bare-metal = "0.1.0"' >> $td/Cargo.toml - echo 'cortex-m = "0.3.0"' >> $td/Cargo.toml + echo 'cortex-m = { git = "https://github.com/japaric/cortex-m" }' >> $td/Cargo.toml echo 'cortex-m-rt = "0.3.0"' >> $td/Cargo.toml echo 'vcell = "0.1.0"' >> $td/Cargo.toml @@ -609,6 +608,6 @@ main() { rm -rf $td } -if [ -z $TRAVIS_TAG ]; then +if [ -z ${TRAVIS_TAG-} ]; then main fi diff --git a/src/generate.rs b/src/generate.rs index d73ecfbc..8accd867 100644 --- a/src/generate.rs +++ b/src/generate.rs @@ -143,8 +143,11 @@ pub fn device(d: &Device, target: &Target, items: &mut Vec) -> Result<() } items.push(quote! { + // NOTE `no_mangle` is used here to prevent linking different minor versions of the device + // crate as that would let you `take` the device peripherals more than once (one per minor + // version) #[no_mangle] - static mut PERIPHERALS: bool = false; + static mut DEVICE_PERIPHERALS: bool = false; /// All the peripherals #[allow(non_snake_case)] @@ -154,21 +157,21 @@ pub fn device(d: &Device, target: &Target, items: &mut Vec) -> Result<() impl Peripherals { /// Returns all the peripherals *once* - pub fn all() -> Option { + pub fn take() -> Option { cortex_m::interrupt::free(|_| { - if unsafe { PERIPHERALS } { + if unsafe { DEVICE_PERIPHERALS } { None } else { - Some(unsafe { Peripherals::_all() }) + Some(unsafe { Peripherals::steal() }) } }) } #[doc(hidden)] - pub unsafe fn _all() -> Self { - debug_assert!(!PERIPHERALS); + pub unsafe fn steal() -> Self { + debug_assert!(!DEVICE_PERIPHERALS); - PERIPHERALS = true; + DEVICE_PERIPHERALS = true; Peripherals { #(#exprs,)* From 91499e45a086e657baf85195a148d90529277cd8 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 9 Dec 2017 11:50:41 +0100 Subject: [PATCH 4/7] docs: unhide `Peripherals::steal` --- src/generate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generate.rs b/src/generate.rs index 8accd867..f64697ad 100644 --- a/src/generate.rs +++ b/src/generate.rs @@ -167,7 +167,7 @@ pub fn device(d: &Device, target: &Target, items: &mut Vec) -> Result<() }) } - #[doc(hidden)] + /// Unchecked version of `Peripherals::take` pub unsafe fn steal() -> Self { debug_assert!(!DEVICE_PERIPHERALS); From 9c2ec7b18560b5d72f3c48eb4c7d895c9fcbb984 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 9 Dec 2017 11:50:49 +0100 Subject: [PATCH 5/7] fix CI --- ci/script.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/script.sh b/ci/script.sh index 7e07c9e8..036cf817 100644 --- a/ci/script.sh +++ b/ci/script.sh @@ -16,7 +16,7 @@ test_svd() { main() { cross check --target $TARGET - if [ -z $VENDOR ]; then + if [ -z ${VENDOR-} ]; then return fi From 92491a77281618c98690c1887c824bbfd65bd8d3 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 9 Dec 2017 13:11:54 +0100 Subject: [PATCH 6/7] inline(always) Perihperals::take --- src/generate.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/generate.rs b/src/generate.rs index f64697ad..bdec0354 100644 --- a/src/generate.rs +++ b/src/generate.rs @@ -157,6 +157,7 @@ pub fn device(d: &Device, target: &Target, items: &mut Vec) -> Result<() impl Peripherals { /// Returns all the peripherals *once* + #[inline(always)] pub fn take() -> Option { cortex_m::interrupt::free(|_| { if unsafe { DEVICE_PERIPHERALS } { From 3b2781554f02724bbbbf5c29cd40970b2cd125fc Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 9 Dec 2017 13:11:56 +0100 Subject: [PATCH 7/7] fix CI (again) --- ci/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/install.sh b/ci/install.sh index b230a6e1..345c13b4 100644 --- a/ci/install.sh +++ b/ci/install.sh @@ -19,7 +19,7 @@ main() { --git japaric/cross \ --tag $tag - if [ ! -z $VENDOR ]; then + if [ ! -z ${VENDOR-} ]; then curl -LSfs https://japaric.github.io/trust/install.sh | \ sh -s -- \ --crate rustfmt \