Skip to content

Commit 763135a

Browse files
authored
Merge pull request #225 from simpkins/write_constraints
Support defining write constraints for newly created fields
2 parents 3930839 + 49eeebc commit 763135a

File tree

2 files changed

+83
-13
lines changed

2 files changed

+83
-13
lines changed

res/add_register/patch.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
_svd: ../add/stm32l4x2.svd
2+
3+
DAC1:
4+
_add:
5+
ANOTHER_REG:
6+
addressOffset: 0x04
7+
size: 32
8+
fields:
9+
MPS:
10+
bitOffset: 0
11+
bitWidth: 5
12+
access: read-write
13+
writeConstraint: [0, 0x1f]

src/patch/mod.rs

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,8 @@ fn make_field(fadd: &Hash, rpath: Option<&RegisterPath>) -> Result<FieldInfoBuil
473473
fadd.get_str("modifiedWriteValues")?
474474
.and_then(ModifiedWriteValues::parse_str),
475475
)
476-
.read_action(fadd.get_str("readAction")?.and_then(ReadAction::parse_str));
476+
.read_action(fadd.get_str("readAction")?.and_then(ReadAction::parse_str))
477+
.write_constraint(get_write_constraint(fadd)?);
477478

478479
if let Some(name) = fadd.get_str("name")? {
479480
fnew = fnew.name(name.into());
@@ -503,6 +504,7 @@ fn make_register(radd: &Hash, path: Option<&BlockPath>) -> Result<RegisterInfoBu
503504
.alternate_group(radd.get_string("alternateGroup")?)
504505
.alternate_register(radd.get_string("alternateRegister")?)
505506
.properties(get_register_properties(radd)?)
507+
.write_constraint(get_write_constraint(radd)?)
506508
.fields(match radd.get_hash("fields")? {
507509
Some(h) => {
508510
let mut fields = Vec::new();
@@ -526,32 +528,35 @@ fn make_register(radd: &Hash, path: Option<&BlockPath>) -> Result<RegisterInfoBu
526528
rnew = rnew.address_offset(address_offset as u32);
527529
}
528530

529-
if let Some(write_constraint) = radd
531+
Ok(rnew)
532+
}
533+
534+
fn get_write_constraint(h: &Hash) -> Result<Option<WriteConstraint>> {
535+
if let Some(write_constraint) = h
530536
.get_yaml("_write_constraint")
531-
.or_else(|| radd.get_yaml("writeConstraint"))
537+
.or_else(|| h.get_yaml("writeConstraint"))
532538
{
533-
let wc = match write_constraint {
539+
match write_constraint {
534540
Yaml::String(s) if s == "none" => {
535541
// Completely remove the existing writeConstraint
536-
None
542+
Ok(None)
537543
}
538544
Yaml::String(s) if s == "enum" => {
539545
// Only allow enumerated values
540-
Some(WriteConstraint::UseEnumeratedValues(true))
546+
Ok(Some(WriteConstraint::UseEnumeratedValues(true)))
541547
}
542548
Yaml::Array(a) => {
543549
// Allow a certain range
544-
Some(WriteConstraint::Range(WriteConstraintRange {
550+
Ok(Some(WriteConstraint::Range(WriteConstraintRange {
545551
min: a[0].i64()? as u64,
546552
max: a[1].i64()? as u64,
547-
}))
553+
})))
548554
}
549-
_ => return Err(anyhow!("Unknown writeConstraint type {write_constraint:?}")),
550-
};
551-
rnew = rnew.write_constraint(wc);
555+
_ => Err(anyhow!("Unknown writeConstraint type {write_constraint:?}")),
556+
}
557+
} else {
558+
Ok(None)
552559
}
553-
554-
Ok(rnew)
555560
}
556561

557562
fn make_cluster(cadd: &Hash, path: Option<&BlockPath>) -> Result<ClusterInfoBuilder> {
@@ -856,3 +861,55 @@ impl Interpolate for FieldPath {
856861
cow
857862
}
858863
}
864+
865+
#[cfg(test)]
866+
mod tests {
867+
use super::*;
868+
use crate::test_utils;
869+
use std::path::Path;
870+
871+
#[test]
872+
fn add_register() -> Result<()> {
873+
let (mut device, yaml) = test_utils::get_patcher(Path::new("add_register")).unwrap();
874+
assert_eq!(device.peripherals.len(), 1);
875+
let registers = device.peripherals[0]
876+
.registers
877+
.as_ref()
878+
.ok_or(anyhow!("no registers"))?;
879+
assert_eq!(registers.len(), 1);
880+
881+
device.process(&yaml, &Default::default()).unwrap();
882+
assert_eq!(device.peripherals.len(), 1);
883+
let periph1 = &device.peripherals[0];
884+
assert_eq!(periph1.name, "DAC1");
885+
let registers = device.peripherals[0]
886+
.registers
887+
.as_ref()
888+
.ok_or(anyhow!("no registers"))?;
889+
assert_eq!(registers.len(), 2);
890+
let reg2 = match &registers[1] {
891+
RegisterCluster::Register(r) => r,
892+
RegisterCluster::Cluster(_) => return Err(anyhow!("expected register, found cluster")),
893+
};
894+
assert_eq!(reg2.name, "ANOTHER_REG");
895+
assert_eq!(reg2.address_offset, 4);
896+
assert_eq!(reg2.properties.size, Some(32));
897+
assert_eq!(reg2.write_constraint, None);
898+
let fields = reg2.fields.as_ref().ok_or(anyhow!("no fields"))?;
899+
assert_eq!(fields.len(), 1);
900+
let field1 = &fields[0];
901+
assert_eq!(field1.name, "MPS");
902+
assert_eq!(field1.bit_offset(), 0);
903+
assert_eq!(field1.bit_width(), 5);
904+
assert_eq!(field1.access, Some(Access::ReadWrite));
905+
assert_eq!(
906+
field1.write_constraint,
907+
Some(WriteConstraint::Range(WriteConstraintRange {
908+
min: 0,
909+
max: 0x1f
910+
}))
911+
);
912+
913+
Ok(())
914+
}
915+
}

0 commit comments

Comments
 (0)