1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
//! Expands arrays and resolves inheritance chains in CMSIS-SVD specifications. //! //! ## Example usage: //! //! ```rust //! use svd_expander::DeviceSpec; //! //! fn main() { //! let xml = r##" //! <device> //! <name>CORTEX_DEVICE</name> //! <peripherals> //! //! <peripheral> //! <name>GPIOA</name> //! <baseAddress>0x40010000</baseAddress> //! <registers> //! <register> //! <name>IDR</name> //! <description>Input Data Register</description> //! <addressOffset>0x00</addressOffset> //! <fields> //! //! <!-- //! This field is a template that will be expanded //! out to 16 input fields named D1 through D16. //! --> //! //! <field> //! <name>D%s</name> //! <bitWidth>1</bitWidth> //! <bitOffset>0</bitOffset> //! <dim>16</dim> //! <dimIndex>1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16</dimIndex> //! <dimIncrement>1</dimIncrement> //! </field> //! //! </fields> //! </register> //! </registers> //! </peripheral> //! //! <!-- //! GPIOA will be copied to make GPIOB below, which is identical //! except for any overridden properties (just name and //! baseAddress in this case). //! --> //! //! <peripheral derivedFrom="GPIOA"> //! <name>GPIOB</name> //! <baseAddress>0x40010100</baseAddress> //! </peripheral> //! //! </peripherals> //! </device> //! "##; //! //! let device = DeviceSpec::from_xml(xml).unwrap(); //! //! // The IDR register on GPIOA has been expanded to 16 fields. //! assert_eq!(16, device.get_register("GPIOA.IDR").unwrap().fields.len()); //! //! // Those fields each had their bit offset (location in the register) //! // incremented appropriately. //! assert_eq!(0, device.get_field("GPIOA.IDR.D1").unwrap().offset); //! assert_eq!(1, device.get_field("GPIOA.IDR.D2").unwrap().offset); //! // ...etc... //! assert_eq!(9, device.get_field("GPIOA.IDR.D10").unwrap().offset); //! // ...etc... //! //! // GPIOB also has an IDR register with 16 fields, which was inherited //! // from GPIOA. //! assert_eq!(16, device.get_register("GPIOB.IDR").unwrap().fields.len()); //! //! // GPIOB kept its name and base address when it inherited properties //! // from GPIOA. //! assert_eq!("GPIOB", device.get_peripheral("GPIOB").unwrap().name); //! assert_eq!( //! 0x40010100, //! device.get_peripheral("GPIOB").unwrap().base_address //! ); //! } //! ``` //! //! This crate is intended for use in code generators. It is under active development and bug //! reports and feature requests are welcome. use svd_parser::Access; mod cluster; mod device; mod error; mod field; mod peripheral; mod register; mod value; pub use cluster::ClusterSpec; pub use device::{CpuSpec, DeviceSpec, EndianSpec}; pub use error::{SvdExpanderError, SvdExpanderResult}; pub use field::FieldSpec; pub use peripheral::{AddressBlockSpec, InterruptSpec, PeripheralSpec}; pub use register::RegisterSpec; pub use value::{ EnumeratedValueSetSpec, EnumeratedValueSpec, EnumeratedValueUsageSpec, EnumeratedValueValueSpec, ModifiedWriteValuesSpec, WriteConstraintRangeSpec, WriteConstraintSpec, }; /// Defines access rights for fields on the device, though it may be specified at a /// higher level than individual fields. /// /// # Values /// /// * `ReadOnly` = Read access is permitted. Write operations have an undefined effect. /// * `ReadWrite` = Read and write accesses are permitted. /// * `ReadWriteOnce` = Read access is always permitted. Only the first write after a reset will /// affect the content. Following writes have an undefined effect. /// * `WriteOnce` = Read operations have undefined results. Only the first write after a reset will /// affect the content. /// * `WriteOnly` = Read operations have an undefined result. Write access is permitted. #[derive(Clone, Copy, PartialEq, Debug)] pub enum AccessSpec { /// Read access is permitted. Write operations have an undefined effect. ReadOnly, /// Read and write accesses are permitted. ReadWrite, /// Read access is always permitted. Only the first write after a reset will affect the content. /// Following writes have an undefined effect. ReadWriteOnce, /// Read operations have undefined results. Only the first write after a reset will affect the /// content. WriteOnce, /// Read operations have an undefined result. Write access is permitted. WriteOnly, } impl AccessSpec { pub(crate) fn new(access: &Access) -> AccessSpec { match access { Access::ReadOnly => AccessSpec::ReadOnly, Access::ReadWrite => AccessSpec::ReadWrite, Access::ReadWriteOnce => AccessSpec::ReadWriteOnce, Access::WriteOnce => AccessSpec::WriteOnce, Access::WriteOnly => AccessSpec::WriteOnly, } } /// Whether the field is readable at least once. pub fn can_read(&self) -> bool { match self { AccessSpec::ReadOnly | AccessSpec::ReadWrite | AccessSpec::ReadWriteOnce => true, _ => false, } } /// Whether the field is writable at least once. pub fn can_write(&self) -> bool { match self { AccessSpec::ReadWrite | AccessSpec::ReadWriteOnce | AccessSpec::WriteOnce | AccessSpec::WriteOnly => true, _ => false, } } }