svd_rs/
peripheral.rs

1use super::{
2    array::{descriptions, names},
3    registercluster::{
4        AllRegistersIter, AllRegistersIterMut, ClusterIter, ClusterIterMut, RegisterIter,
5        RegisterIterMut,
6    },
7    AddressBlock, BuildError, Cluster, Description, DimElement, EmptyToNone, Interrupt, MaybeArray,
8    Name, Register, RegisterCluster, RegisterProperties, SvdError, ValidateLevel,
9};
10use std::ops::Deref;
11
12/// A single peripheral or array of peripherals
13pub type Peripheral = MaybeArray<PeripheralInfo>;
14
15/// Errors from [Peripheral::validate]
16#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
17pub enum Error {
18    /// The peripheral has no registers, but specified a `<registers>` tag.
19    #[error("Peripheral have `registers` tag, but it is empty")]
20    EmptyRegisters,
21}
22
23/// A description of a peripheral in the [device](crate::Device), describing, for example, the [memory mappings](crate::RegisterInfo).
24#[cfg_attr(
25    feature = "serde",
26    derive(serde::Deserialize, serde::Serialize),
27    serde(rename_all = "camelCase")
28)]
29#[derive(Clone, Debug, PartialEq)]
30#[non_exhaustive]
31pub struct PeripheralInfo {
32    /// The string identifies the peripheral. Peripheral names are required to be unique for a device
33    pub name: String,
34
35    /// Specifies a register name without the restrictions of an ANSI C identifier.
36    #[cfg_attr(
37        feature = "serde",
38        serde(default, skip_serializing_if = "Option::is_none")
39    )]
40    pub display_name: Option<String>,
41
42    /// The string specifies the version of this peripheral description
43    #[cfg_attr(
44        feature = "serde",
45        serde(default, skip_serializing_if = "Option::is_none")
46    )]
47    pub version: Option<String>,
48
49    /// The string provides an overview of the purpose and functionality of the peripheral
50    #[cfg_attr(
51        feature = "serde",
52        serde(default, skip_serializing_if = "Option::is_none")
53    )]
54    pub description: Option<String>,
55
56    /// Specifies peripheral assigned to the same address blocks
57    #[cfg_attr(
58        feature = "serde",
59        serde(default, skip_serializing_if = "Option::is_none")
60    )]
61    pub alternate_peripheral: Option<String>,
62
63    /// Assigns this peripheral to a group of peripherals. This is only used bye the System View
64    #[cfg_attr(
65        feature = "serde",
66        serde(default, skip_serializing_if = "Option::is_none")
67    )]
68    pub group_name: Option<String>,
69
70    /// Define a string as prefix. All register names of this peripheral get this prefix
71    #[cfg_attr(
72        feature = "serde",
73        serde(default, skip_serializing_if = "Option::is_none")
74    )]
75    pub prepend_to_name: Option<String>,
76
77    /// Define a string as suffix. All register names of this peripheral get this suffix
78    #[cfg_attr(
79        feature = "serde",
80        serde(default, skip_serializing_if = "Option::is_none")
81    )]
82    pub append_to_name: Option<String>,
83
84    /// Specify the struct type name created in the device header file
85    #[cfg_attr(
86        feature = "serde",
87        serde(default, skip_serializing_if = "Option::is_none")
88    )]
89    pub header_struct_name: Option<String>,
90
91    /// Lowest address reserved or used by the peripheral
92    pub base_address: u64,
93
94    /// Default properties for all registers
95    #[cfg_attr(feature = "serde", serde(flatten))]
96    pub default_register_properties: RegisterProperties,
97
98    /// Specify an address range uniquely mapped to this peripheral
99    #[cfg_attr(
100        feature = "serde",
101        serde(default, skip_serializing_if = "Option::is_none")
102    )]
103    pub address_block: Option<Vec<AddressBlock>>,
104
105    /// A peripheral can have multiple associated interrupts
106    #[cfg_attr(
107        feature = "serde",
108        serde(default, skip_serializing_if = "Vec::is_empty")
109    )]
110    pub interrupt: Vec<Interrupt>,
111
112    /// Group to enclose register definitions.
113    /// `None` indicates that the `<registers>` node is not present
114    #[cfg_attr(
115        feature = "serde",
116        serde(default, skip_serializing_if = "Option::is_none")
117    )]
118    pub registers: Option<Vec<RegisterCluster>>,
119
120    /// Specify the peripheral name from which to inherit data. Elements specified subsequently override inherited values
121    #[cfg_attr(
122        feature = "serde",
123        serde(default, skip_serializing_if = "Option::is_none")
124    )]
125    pub derived_from: Option<String>,
126}
127
128/// Return iterator over base addresses of each peripheral in array
129pub fn base_addresses<'a>(
130    info: &'a PeripheralInfo,
131    dim: &'a DimElement,
132) -> impl Iterator<Item = u64> + 'a {
133    (0..dim.dim as u64).map(|i| info.base_address + i * dim.dim_increment as u64)
134}
135
136/// Extract `PeripheralInfo` items from array
137pub fn expand<'a>(
138    info: &'a PeripheralInfo,
139    dim: &'a DimElement,
140) -> impl Iterator<Item = PeripheralInfo> + 'a {
141    dim.indexes()
142        .zip(names(info, dim))
143        .zip(descriptions(info, dim))
144        .zip(base_addresses(info, dim))
145        .map(|(((idx, name), description), base_address)| {
146            let mut info = info.clone();
147            info.name = name;
148            info.description = description;
149            info.base_address = base_address;
150            info.display_name = info
151                .display_name
152                .map(|d| d.replace("[%s]", &idx).replace("%s", &idx));
153            info
154        })
155}
156
157/// Builder for [`Peripheral`]
158#[derive(Clone, Debug, Default, PartialEq)]
159pub struct PeripheralInfoBuilder {
160    name: Option<String>,
161    display_name: Option<String>,
162    version: Option<String>,
163    description: Option<String>,
164    alternate_peripheral: Option<String>,
165    group_name: Option<String>,
166    prepend_to_name: Option<String>,
167    append_to_name: Option<String>,
168    header_struct_name: Option<String>,
169    base_address: Option<u64>,
170    default_register_properties: RegisterProperties,
171    address_block: Option<Vec<AddressBlock>>,
172    interrupt: Option<Vec<Interrupt>>,
173    registers: Option<Vec<RegisterCluster>>,
174    derived_from: Option<String>,
175}
176
177impl From<PeripheralInfo> for PeripheralInfoBuilder {
178    fn from(p: PeripheralInfo) -> Self {
179        Self {
180            name: Some(p.name),
181            display_name: p.display_name,
182            version: p.version,
183            description: p.description,
184            alternate_peripheral: p.alternate_peripheral,
185            group_name: p.group_name,
186            prepend_to_name: p.prepend_to_name,
187            append_to_name: p.append_to_name,
188            header_struct_name: p.header_struct_name,
189            base_address: Some(p.base_address),
190            default_register_properties: p.default_register_properties,
191            address_block: p.address_block,
192            interrupt: Some(p.interrupt),
193            registers: p.registers,
194            derived_from: p.derived_from,
195        }
196    }
197}
198
199impl PeripheralInfoBuilder {
200    /// Set the name of the peripheral
201    pub fn name(mut self, value: String) -> Self {
202        self.name = Some(value);
203        self
204    }
205    /// Set the display name of the peripheral
206    pub fn display_name(mut self, value: Option<String>) -> Self {
207        self.display_name = value;
208        self
209    }
210    /// Set the version of the peripheral
211    pub fn version(mut self, value: Option<String>) -> Self {
212        self.version = value;
213        self
214    }
215    /// Set the description of the peripheral
216    pub fn description(mut self, value: Option<String>) -> Self {
217        self.description = value;
218        self
219    }
220    /// Set the alternate peripheral
221    pub fn alternate_peripheral(mut self, value: Option<String>) -> Self {
222        self.alternate_peripheral = value;
223        self
224    }
225    /// Set the group name of the peripheral
226    pub fn group_name(mut self, value: Option<String>) -> Self {
227        self.group_name = value;
228        self
229    }
230    /// Set the prefix for names of all registers of the peripheral
231    pub fn prepend_to_name(mut self, value: Option<String>) -> Self {
232        self.prepend_to_name = value;
233        self
234    }
235    /// Set the suffix for names of all registers of the peripheral
236    pub fn append_to_name(mut self, value: Option<String>) -> Self {
237        self.append_to_name = value;
238        self
239    }
240    /// Set the header struct name of the peripheral
241    pub fn header_struct_name(mut self, value: Option<String>) -> Self {
242        self.header_struct_name = value;
243        self
244    }
245    /// Set the base address of the peripheral
246    pub fn base_address(mut self, value: u64) -> Self {
247        self.base_address = Some(value);
248        self
249    }
250    /// Set the default register properties of the peripheral
251    pub fn default_register_properties(mut self, value: RegisterProperties) -> Self {
252        self.default_register_properties = value;
253        self
254    }
255    /// Set the address block of the peripheral
256    pub fn address_block(mut self, value: Option<Vec<AddressBlock>>) -> Self {
257        self.address_block = value;
258        self
259    }
260    /// Set the interrupts of the peripheral
261    pub fn interrupt(mut self, value: Option<Vec<Interrupt>>) -> Self {
262        self.interrupt = value;
263        self
264    }
265    /// Set the registers of the peripheral
266    pub fn registers(mut self, value: Option<Vec<RegisterCluster>>) -> Self {
267        self.registers = value;
268        self
269    }
270    /// Set the derived_from attribute of the peripheral
271    pub fn derived_from(mut self, value: Option<String>) -> Self {
272        self.derived_from = value;
273        self
274    }
275    /// Validate and build a [`PeripheralInfo`].
276    pub fn build(self, lvl: ValidateLevel) -> Result<PeripheralInfo, SvdError> {
277        let per = PeripheralInfo {
278            name: self
279                .name
280                .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?,
281            display_name: self.display_name.empty_to_none(),
282            version: self.version.empty_to_none(),
283            description: self.description.empty_to_none(),
284            alternate_peripheral: self.alternate_peripheral.empty_to_none(),
285            group_name: self.group_name.empty_to_none(),
286            prepend_to_name: self.prepend_to_name.empty_to_none(),
287            append_to_name: self.append_to_name.empty_to_none(),
288            header_struct_name: self.header_struct_name.empty_to_none(),
289            base_address: self
290                .base_address
291                .ok_or_else(|| BuildError::Uninitialized("base_address".to_string()))?,
292            default_register_properties: self.default_register_properties.build(lvl)?,
293            address_block: self.address_block,
294            interrupt: self.interrupt.unwrap_or_default(),
295            registers: self.registers,
296            derived_from: self.derived_from,
297        };
298        per.validate(lvl)?;
299        Ok(per)
300    }
301}
302
303impl PeripheralInfo {
304    /// Make a builder for [`PeripheralInfo`]
305    pub fn builder() -> PeripheralInfoBuilder {
306        PeripheralInfoBuilder::default()
307    }
308    /// Construct single [`Peripheral`]
309    pub const fn single(self) -> Peripheral {
310        Peripheral::Single(self)
311    }
312    /// Construct [`Peripheral`] array
313    pub const fn array(self, dim: DimElement) -> Peripheral {
314        Peripheral::Array(self, dim)
315    }
316    /// Construct single [`Peripheral`] or array
317    pub fn maybe_array(self, dim: Option<DimElement>) -> Peripheral {
318        if let Some(dim) = dim {
319            self.array(dim)
320        } else {
321            self.single()
322        }
323    }
324    /// Modify an existing [`Peripheral`] based on a [builder](PeripheralInfoBuilder).
325    pub fn modify_from(
326        &mut self,
327        builder: PeripheralInfoBuilder,
328        lvl: ValidateLevel,
329    ) -> Result<(), SvdError> {
330        if let Some(name) = builder.name {
331            self.name = name;
332        }
333        if builder.display_name.is_some() {
334            self.display_name = builder.display_name.empty_to_none();
335        }
336        if builder.version.is_some() {
337            self.version = builder.version.empty_to_none();
338        }
339        if builder.description.is_some() {
340            self.description = builder.description.empty_to_none();
341        }
342        if builder.alternate_peripheral.is_some() {
343            self.alternate_peripheral = builder.alternate_peripheral.empty_to_none();
344        }
345        if builder.group_name.is_some() {
346            self.group_name = builder.group_name.empty_to_none();
347        }
348        if builder.prepend_to_name.is_some() {
349            self.prepend_to_name = builder.prepend_to_name.empty_to_none();
350        }
351        if builder.append_to_name.is_some() {
352            self.append_to_name = builder.append_to_name.empty_to_none();
353        }
354        if builder.header_struct_name.is_some() {
355            self.header_struct_name = builder.header_struct_name.empty_to_none();
356        }
357        if let Some(base_address) = builder.base_address {
358            self.base_address = base_address;
359        }
360        if let Some(interrupt) = builder.interrupt {
361            self.interrupt = interrupt;
362        }
363        if builder.derived_from.is_some() {
364            self.derived_from = builder.derived_from;
365            self.registers = None;
366            self.address_block = None;
367            self.default_register_properties = RegisterProperties::default();
368        } else {
369            if builder.address_block.is_some() {
370                self.address_block = builder.address_block;
371            }
372            self.default_register_properties
373                .modify_from(builder.default_register_properties, lvl)?;
374            if builder.registers.is_some() {
375                self.registers = builder.registers.empty_to_none();
376            }
377        }
378        self.validate(lvl)
379    }
380
381    /// Validate the [`PeripheralInfo`]
382    pub fn validate(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
383        if !lvl.is_disabled() {
384            // TODO
385            if lvl.is_strict() {
386                super::check_dimable_name(&self.name, "name")?;
387            }
388            if let Some(name) = self.derived_from.as_ref() {
389                if lvl.is_strict() {
390                    super::check_dimable_name(name, "derivedFrom")?;
391                }
392            } else if let Some(registers) = self.registers.as_ref() {
393                if registers.is_empty() && lvl.is_strict() {
394                    return Err(Error::EmptyRegisters.into());
395                }
396            }
397        }
398        Ok(())
399    }
400    /// Validate the [`PeripheralInfo`] recursively
401    pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
402        if let Some(abs) = self.address_block.as_ref() {
403            for ab in abs {
404                ab.validate(lvl)?;
405            }
406        }
407        for i in &self.interrupt {
408            i.validate(lvl)?;
409        }
410        self.default_register_properties.validate(lvl)?;
411        for r in self.registers() {
412            r.validate_all(lvl)?;
413        }
414        for c in self.clusters() {
415            c.validate_all(lvl)?;
416        }
417        self.validate(lvl)
418    }
419
420    /// Returns iterator over child registers
421    pub fn registers(&self) -> RegisterIter {
422        RegisterIter {
423            all: match &self.registers {
424                Some(regs) => regs.iter(),
425                None => [].iter(),
426            },
427        }
428    }
429
430    /// Returns mutable iterator over child registers
431    pub fn registers_mut(&mut self) -> RegisterIterMut {
432        RegisterIterMut {
433            all: match &mut self.registers {
434                Some(regs) => regs.iter_mut(),
435                None => [].iter_mut(),
436            },
437        }
438    }
439
440    /// Returns iterator over child clusters
441    pub fn clusters(&self) -> ClusterIter {
442        ClusterIter {
443            all: match &self.registers {
444                Some(regs) => regs.iter(),
445                None => [].iter(),
446            },
447        }
448    }
449
450    /// Returns mutable iterator over child clusters
451    pub fn clusters_mut(&mut self) -> ClusterIterMut {
452        ClusterIterMut {
453            all: match &mut self.registers {
454                Some(regs) => regs.iter_mut(),
455                None => [].iter_mut(),
456            },
457        }
458    }
459
460    /// Returns iterator over all descendant registers
461    #[deprecated(since = "0.12.1", note = "Please use `all_registers` instead")]
462    pub fn reg_iter(&self) -> AllRegistersIter {
463        self.all_registers()
464    }
465
466    /// Returns iterator over all descendant registers
467    pub fn all_registers(&self) -> AllRegistersIter {
468        AllRegistersIter {
469            rem: match &self.registers {
470                Some(regs) => regs.iter().rev().collect(),
471                None => Vec::new(),
472            },
473        }
474    }
475
476    /// Returns mutable iterator over all descendant registers
477    #[deprecated(since = "0.12.1", note = "Please use `all_registers_mut` instead")]
478    pub fn reg_iter_mut(&mut self) -> AllRegistersIterMut {
479        self.all_registers_mut()
480    }
481
482    /// Returns mutable iterator over all descendant registers
483    pub fn all_registers_mut(&mut self) -> AllRegistersIterMut {
484        AllRegistersIterMut {
485            rem: match &mut self.registers {
486                Some(regs) => regs.iter_mut().rev().collect(),
487                None => Vec::new(),
488            },
489        }
490    }
491
492    /// Get register by name
493    pub fn get_register(&self, name: &str) -> Option<&Register> {
494        self.registers().find(|f| f.name == name)
495    }
496
497    /// Get mutable register by name
498    pub fn get_mut_register(&mut self, name: &str) -> Option<&mut Register> {
499        self.registers_mut().find(|f| f.name == name)
500    }
501
502    /// Get cluster by name
503    pub fn get_cluster(&self, name: &str) -> Option<&Cluster> {
504        self.clusters().find(|f| f.name == name)
505    }
506
507    /// Get mutable cluster by name
508    pub fn get_mut_cluster(&mut self, name: &str) -> Option<&mut Cluster> {
509        self.clusters_mut().find(|f| f.name == name)
510    }
511
512    /// Get interrupt by name
513    pub fn get_interrupt(&self, name: &str) -> Option<&Interrupt> {
514        self.interrupt.iter().find(|e| e.name == name)
515    }
516
517    /// Get mutable enumeratedValue by name
518    pub fn get_mut_interrupt(&mut self, name: &str) -> Option<&mut Interrupt> {
519        self.interrupt.iter_mut().find(|e| e.name == name)
520    }
521}
522
523impl Peripheral {
524    /// Validate the [`Peripheral`] recursively
525    pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
526        if let Self::Array(_, dim) = self {
527            dim.validate(lvl)?;
528        }
529        self.deref().validate_all(lvl)
530    }
531}
532
533impl Name for PeripheralInfo {
534    fn name(&self) -> &str {
535        &self.name
536    }
537}
538
539impl Description for PeripheralInfo {
540    fn description(&self) -> Option<&str> {
541        self.description.as_deref()
542    }
543}