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
12pub type Peripheral = MaybeArray<PeripheralInfo>;
14
15#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
17pub enum Error {
18 #[error("Peripheral have `registers` tag, but it is empty")]
20 EmptyRegisters,
21}
22
23#[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 pub name: String,
34
35 #[cfg_attr(
37 feature = "serde",
38 serde(default, skip_serializing_if = "Option::is_none")
39 )]
40 pub display_name: Option<String>,
41
42 #[cfg_attr(
44 feature = "serde",
45 serde(default, skip_serializing_if = "Option::is_none")
46 )]
47 pub version: Option<String>,
48
49 #[cfg_attr(
51 feature = "serde",
52 serde(default, skip_serializing_if = "Option::is_none")
53 )]
54 pub description: Option<String>,
55
56 #[cfg_attr(
58 feature = "serde",
59 serde(default, skip_serializing_if = "Option::is_none")
60 )]
61 pub alternate_peripheral: Option<String>,
62
63 #[cfg_attr(
65 feature = "serde",
66 serde(default, skip_serializing_if = "Option::is_none")
67 )]
68 pub group_name: Option<String>,
69
70 #[cfg_attr(
72 feature = "serde",
73 serde(default, skip_serializing_if = "Option::is_none")
74 )]
75 pub prepend_to_name: Option<String>,
76
77 #[cfg_attr(
79 feature = "serde",
80 serde(default, skip_serializing_if = "Option::is_none")
81 )]
82 pub append_to_name: Option<String>,
83
84 #[cfg_attr(
86 feature = "serde",
87 serde(default, skip_serializing_if = "Option::is_none")
88 )]
89 pub header_struct_name: Option<String>,
90
91 pub base_address: u64,
93
94 #[cfg_attr(feature = "serde", serde(flatten))]
96 pub default_register_properties: RegisterProperties,
97
98 #[cfg_attr(
100 feature = "serde",
101 serde(default, skip_serializing_if = "Option::is_none")
102 )]
103 pub address_block: Option<Vec<AddressBlock>>,
104
105 #[cfg_attr(
107 feature = "serde",
108 serde(default, skip_serializing_if = "Vec::is_empty")
109 )]
110 pub interrupt: Vec<Interrupt>,
111
112 #[cfg_attr(
115 feature = "serde",
116 serde(default, skip_serializing_if = "Option::is_none")
117 )]
118 pub registers: Option<Vec<RegisterCluster>>,
119
120 #[cfg_attr(
122 feature = "serde",
123 serde(default, skip_serializing_if = "Option::is_none")
124 )]
125 pub derived_from: Option<String>,
126}
127
128pub 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
136pub 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#[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 pub fn name(mut self, value: String) -> Self {
202 self.name = Some(value);
203 self
204 }
205 pub fn display_name(mut self, value: Option<String>) -> Self {
207 self.display_name = value;
208 self
209 }
210 pub fn version(mut self, value: Option<String>) -> Self {
212 self.version = value;
213 self
214 }
215 pub fn description(mut self, value: Option<String>) -> Self {
217 self.description = value;
218 self
219 }
220 pub fn alternate_peripheral(mut self, value: Option<String>) -> Self {
222 self.alternate_peripheral = value;
223 self
224 }
225 pub fn group_name(mut self, value: Option<String>) -> Self {
227 self.group_name = value;
228 self
229 }
230 pub fn prepend_to_name(mut self, value: Option<String>) -> Self {
232 self.prepend_to_name = value;
233 self
234 }
235 pub fn append_to_name(mut self, value: Option<String>) -> Self {
237 self.append_to_name = value;
238 self
239 }
240 pub fn header_struct_name(mut self, value: Option<String>) -> Self {
242 self.header_struct_name = value;
243 self
244 }
245 pub fn base_address(mut self, value: u64) -> Self {
247 self.base_address = Some(value);
248 self
249 }
250 pub fn default_register_properties(mut self, value: RegisterProperties) -> Self {
252 self.default_register_properties = value;
253 self
254 }
255 pub fn address_block(mut self, value: Option<Vec<AddressBlock>>) -> Self {
257 self.address_block = value;
258 self
259 }
260 pub fn interrupt(mut self, value: Option<Vec<Interrupt>>) -> Self {
262 self.interrupt = value;
263 self
264 }
265 pub fn registers(mut self, value: Option<Vec<RegisterCluster>>) -> Self {
267 self.registers = value;
268 self
269 }
270 pub fn derived_from(mut self, value: Option<String>) -> Self {
272 self.derived_from = value;
273 self
274 }
275 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 pub fn builder() -> PeripheralInfoBuilder {
306 PeripheralInfoBuilder::default()
307 }
308 pub const fn single(self) -> Peripheral {
310 Peripheral::Single(self)
311 }
312 pub const fn array(self, dim: DimElement) -> Peripheral {
314 Peripheral::Array(self, dim)
315 }
316 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 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 pub fn validate(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
383 if !lvl.is_disabled() {
384 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 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 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 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 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 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 #[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 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 #[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 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 pub fn get_register(&self, name: &str) -> Option<&Register> {
494 self.registers().find(|f| f.name == name)
495 }
496
497 pub fn get_mut_register(&mut self, name: &str) -> Option<&mut Register> {
499 self.registers_mut().find(|f| f.name == name)
500 }
501
502 pub fn get_cluster(&self, name: &str) -> Option<&Cluster> {
504 self.clusters().find(|f| f.name == name)
505 }
506
507 pub fn get_mut_cluster(&mut self, name: &str) -> Option<&mut Cluster> {
509 self.clusters_mut().find(|f| f.name == name)
510 }
511
512 pub fn get_interrupt(&self, name: &str) -> Option<&Interrupt> {
514 self.interrupt.iter().find(|e| e.name == name)
515 }
516
517 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 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}