Skip to content

Commit

Permalink
add ReadAction
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Nov 7, 2021
1 parent 0044fb7 commit fcc459c
Show file tree
Hide file tree
Showing 20 changed files with 146 additions and 8 deletions.
1 change: 1 addition & 0 deletions svd-encoder/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased

- Add `readAction` encoding
- Add array support for peripherals

## [v0.11.0] - 2021-10-02
Expand Down
4 changes: 4 additions & 0 deletions svd-encoder/src/fieldinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ impl Encode for FieldInfo {
elem.children.push(v.encode_node()?);
}

if let Some(v) = &self.read_action {
elem.children.push(v.encode_node()?);
}

let enumerated_values: Result<Vec<XMLNode>, EncodeError> = self
.enumerated_values
.iter()
Expand Down
1 change: 1 addition & 0 deletions svd-encoder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ mod interrupt;
mod modifiedwritevalues;
mod peripheral;
mod peripheralinfo;
mod readaction;
mod register;
mod registercluster;
mod registerinfo;
Expand Down
11 changes: 11 additions & 0 deletions svd-encoder/src/readaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use super::{Element, Encode, EncodeError, XMLNode};

impl Encode for crate::svd::ReadAction {
type Error = EncodeError;

fn encode(&self) -> Result<Element, EncodeError> {
let mut elem = Element::new("readAction");
elem.children.push(XMLNode::Text(self.as_str().to_string()));
Ok(elem)
}
}
4 changes: 4 additions & 0 deletions svd-encoder/src/registerinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ impl Encode for RegisterInfo {
elem.children.push(v.encode_node()?);
}

if let Some(v) = &self.read_action {
elem.children.push(v.encode_node()?);
}

if let Some(v) = &self.fields {
let children = v
.iter()
Expand Down
1 change: 1 addition & 0 deletions svd-parser/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased

- Add `readAction` parsing
- Add array support for peripherals

## [v0.11.0] - 2021-10-02
Expand Down
3 changes: 2 additions & 1 deletion svd-parser/src/fieldinfo.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::*;
use crate::svd::{
Access, BitRange, EnumeratedValues, FieldInfo, ModifiedWriteValues, WriteConstraint,
Access, BitRange, EnumeratedValues, FieldInfo, ModifiedWriteValues, ReadAction, WriteConstraint,
};

impl Parse for FieldInfo {
Expand Down Expand Up @@ -29,6 +29,7 @@ impl Parse for FieldInfo {
tree,
config,
)?)
.read_action(optional::<ReadAction>("readAction", tree, config)?)
.enumerated_values({
let values: Result<Vec<_>, _> = tree
.children()
Expand Down
3 changes: 3 additions & 0 deletions svd-parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ mod interrupt;
mod modifiedwritevalues;
mod peripheral;
mod peripheralinfo;
mod readaction;
mod register;
mod registercluster;
mod registerinfo;
Expand Down Expand Up @@ -201,6 +202,8 @@ pub enum SVDError {
InvalidRegisterCluster(String),
#[error("Invalid modifiedWriteValues variant, found {0}")]
InvalidModifiedWriteValues(String),
#[error("Invalid readAction variant, found {0}")]
InvalidReadAction(String),
#[error("The content of the element could not be parsed to a boolean value {0}: {1}")]
InvalidBooleanValue(String, core::str::ParseBoolError),
#[error("dimIndex tag must contain {0} indexes, found {1}")]
Expand Down
14 changes: 14 additions & 0 deletions svd-parser/src/readaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use super::*;

use crate::svd::ReadAction;
impl Parse for ReadAction {
type Object = Self;
type Error = SVDErrorAt;
type Config = Config;

fn parse(tree: &Node, _config: &Self::Config) -> Result<Self, Self::Error> {
let text = tree.get_text()?;

Self::parse_str(text).ok_or_else(|| SVDError::InvalidReadAction(text.into()).at(tree.id()))
}
}
5 changes: 4 additions & 1 deletion svd-parser/src/registerinfo.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use super::*;
use crate::svd::{Field, ModifiedWriteValues, RegisterInfo, RegisterProperties, WriteConstraint};
use crate::svd::{
Field, ModifiedWriteValues, ReadAction, RegisterInfo, RegisterProperties, WriteConstraint,
};

impl Parse for RegisterInfo {
type Object = Self;
Expand All @@ -25,6 +27,7 @@ impl Parse for RegisterInfo {
tree,
config,
)?)
.read_action(optional::<ReadAction>("readAction", tree, config)?)
.fields({
if let Some(fields) = tree.get_child("fields") {
let fs: Result<Vec<_>, _> = fields
Expand Down
1 change: 1 addition & 0 deletions svd-rs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased

- Add `readAction` to `RegisterInfo` and `FieldInfo`
- Add `single` and `array` for `Info` types,
`is_single` and `is_array` for `Peripheral`, `Cluster`, `Register` and `Field`
- Add array support for peripherals
Expand Down
2 changes: 1 addition & 1 deletion svd-rs/src/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl Default for Access {
}

impl Access {
/// Parse a string into an [Access] value, returning [`Option::None`] if the string is not valid.
/// Parse a string into an [`Access`] value, returning [`Option::None`] if the string is not valid.
pub fn parse_str(s: &str) -> Option<Self> {
match s {
"read-only" => Some(Self::ReadOnly),
Expand Down
2 changes: 1 addition & 1 deletion svd-rs/src/addressblock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl Default for AddressBlockUsage {
}

impl AddressBlockUsage {
/// Parse a string into an [AddressBlockUsage] value, returning [`Option::None`] if the string is not valid.
/// Parse a string into an [`AddressBlockUsage`] value, returning [`Option::None`] if the string is not valid.
pub fn parse_str(s: &str) -> Option<Self> {
match s {
"registers" => Some(Self::Registers),
Expand Down
2 changes: 2 additions & 0 deletions svd-rs/src/derive_from.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ impl DeriveFrom for RegisterInfo {
derived.properties = derived.properties.derive_from(&other.properties);
derived.fields = derived.fields.or_else(|| other.fields.clone());
derived.write_constraint = derived.write_constraint.or(other.write_constraint);
derived.read_action = derived.read_action.or(other.read_action);
derived.modified_write_values = derived
.modified_write_values
.or(other.modified_write_values);
Expand Down Expand Up @@ -87,6 +88,7 @@ impl DeriveFrom for FieldInfo {
derived.enumerated_values = other.enumerated_values.clone();
}
derived.write_constraint = derived.write_constraint.or(other.write_constraint);
derived.read_action = derived.read_action.or(other.read_action);
derived.modified_write_values = derived
.modified_write_values
.or(other.modified_write_values);
Expand Down
21 changes: 20 additions & 1 deletion svd-rs/src/fieldinfo.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{
bitrange, Access, BitRange, BuildError, DimElement, EmptyToNone, EnumeratedValues, Field,
ModifiedWriteValues, SvdError, Usage, ValidateLevel, WriteConstraint,
ModifiedWriteValues, ReadAction, SvdError, Usage, ValidateLevel, WriteConstraint,
};

/// Errors for [`FieldInfo::validate`]
Expand Down Expand Up @@ -54,6 +54,14 @@ pub struct FieldInfo {
)]
pub write_constraint: Option<WriteConstraint>,

/// If set, it specifies the side effect following a read operation.
/// If not set, the field is not modified
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
)]
pub read_action: Option<ReadAction>,

/// Describes the field
#[cfg_attr(
feature = "serde",
Expand Down Expand Up @@ -82,6 +90,7 @@ pub struct FieldInfoBuilder {
access: Option<Access>,
modified_write_values: Option<ModifiedWriteValues>,
write_constraint: Option<WriteConstraint>,
read_action: Option<ReadAction>,
enumerated_values: Option<Vec<EnumeratedValues>>,
derived_from: Option<String>,
}
Expand All @@ -97,6 +106,7 @@ impl From<FieldInfo> for FieldInfoBuilder {
access: f.access,
modified_write_values: f.modified_write_values,
write_constraint: f.write_constraint,
read_action: f.read_action,
enumerated_values: Some(f.enumerated_values),
derived_from: f.derived_from,
}
Expand Down Expand Up @@ -160,6 +170,11 @@ impl FieldInfoBuilder {
self.write_constraint = value;
self
}
/// Set the read action of the register.
pub fn read_action(mut self, value: Option<ReadAction>) -> Self {
self.read_action = value;
self
}
/// Set the enumerated values of the field
pub fn enumerated_values(mut self, value: Vec<EnumeratedValues>) -> Self {
self.enumerated_values = Some(value);
Expand All @@ -183,6 +198,7 @@ impl FieldInfoBuilder {
access: self.access,
modified_write_values: self.modified_write_values,
write_constraint: self.write_constraint,
read_action: self.read_action,
enumerated_values: self.enumerated_values.unwrap_or_default(),
derived_from: self.derived_from,
};
Expand Down Expand Up @@ -242,6 +258,9 @@ impl FieldInfo {
if builder.write_constraint.is_some() {
self.write_constraint = builder.write_constraint;
}
if builder.read_action.is_some() {
self.read_action = builder.read_action;
}
if let Some(enumerated_values) = builder.enumerated_values {
self.enumerated_values = enumerated_values;
}
Expand Down
4 changes: 4 additions & 0 deletions svd-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ pub use self::device::{Device, DeviceBuilder};
pub mod modifiedwritevalues;
pub use self::modifiedwritevalues::ModifiedWriteValues;

/// Read Action objects
pub mod readaction;
pub use self::readaction::ReadAction;

/// Level of validation
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ValidateLevel {
Expand Down
2 changes: 1 addition & 1 deletion svd-rs/src/modifiedwritevalues.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl Default for ModifiedWriteValues {
}

impl ModifiedWriteValues {
/// Parse a string into an [ModifiedWriteValues] value, returning [`Option::None`] if the string is not valid.
/// Parse a string into an [`ModifiedWriteValues`] value, returning [`Option::None`] if the string is not valid.
pub fn parse_str(s: &str) -> Option<Self> {
use self::ModifiedWriteValues::*;
match s {
Expand Down
50 changes: 50 additions & 0 deletions svd-rs/src/readaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/// Specifies the side effect following a read operation
#[cfg_attr(
feature = "serde",
derive(serde::Deserialize, serde::Serialize),
serde(rename_all = "camelCase")
)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ReadAction {
/// The register/field is cleared (set to zero) following a read operation
Clear,

/// The register/field is set (set to ones) following a read operation
Set,

/// The register/field is modified in some way after a read operation
Modify,

/// One or more dependent resources other than the current register/field are immediately affected by a read operation
ModifyExternal,
}

impl Default for ReadAction {
fn default() -> Self {
Self::Modify
}
}

impl ReadAction {
/// Parse a string into an [`ReadAction`] value, returning [`Option::None`] if the string is not valid.
pub fn parse_str(s: &str) -> Option<Self> {
use self::ReadAction::*;
match s {
"clear" => Some(Clear),
"set" => Some(Set),
"modify" => Some(Modify),
"modifyExternal" => Some(ModifyExternal),
_ => None,
}
}

/// Convert this [`ReadAction`] into a static string.
pub const fn as_str(self) -> &'static str {
match self {
Self::Clear => "clear",
Self::Set => "set",
Self::Modify => "modify",
Self::ModifyExternal => "modifyExternal",
}
}
}
21 changes: 20 additions & 1 deletion svd-rs/src/registerinfo.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{
Access, BuildError, DimElement, EmptyToNone, Field, ModifiedWriteValues, Register,
Access, BuildError, DimElement, EmptyToNone, Field, ModifiedWriteValues, ReadAction, Register,
RegisterProperties, SvdError, ValidateLevel, WriteConstraint,
};

Expand Down Expand Up @@ -74,6 +74,14 @@ pub struct RegisterInfo {
)]
pub write_constraint: Option<WriteConstraint>,

/// If set, it specifies the side effect following a read operation.
/// If not set, the register is not modified
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
)]
pub read_action: Option<ReadAction>,

/// `None` indicates that the `<fields>` node is not present
#[cfg_attr(
feature = "serde",
Expand Down Expand Up @@ -102,6 +110,7 @@ pub struct RegisterInfoBuilder {
properties: RegisterProperties,
modified_write_values: Option<ModifiedWriteValues>,
write_constraint: Option<WriteConstraint>,
read_action: Option<ReadAction>,
fields: Option<Vec<Field>>,
derived_from: Option<String>,
}
Expand All @@ -118,6 +127,7 @@ impl From<RegisterInfo> for RegisterInfoBuilder {
properties: r.properties,
modified_write_values: r.modified_write_values,
write_constraint: r.write_constraint,
read_action: r.read_action,
fields: r.fields,
derived_from: r.derived_from,
}
Expand Down Expand Up @@ -190,6 +200,11 @@ impl RegisterInfoBuilder {
self.write_constraint = value;
self
}
/// Set the read action of the register.
pub fn read_action(mut self, value: Option<ReadAction>) -> Self {
self.read_action = value;
self
}
/// Set the fields of the register.
pub fn fields(mut self, value: Option<Vec<Field>>) -> Self {
self.fields = value;
Expand All @@ -216,6 +231,7 @@ impl RegisterInfoBuilder {
properties: self.properties.build(lvl)?,
modified_write_values: self.modified_write_values,
write_constraint: self.write_constraint,
read_action: self.read_action,
fields: self.fields,
derived_from: self.derived_from,
};
Expand Down Expand Up @@ -277,6 +293,9 @@ impl RegisterInfo {
if builder.write_constraint.is_some() {
self.write_constraint = builder.write_constraint;
}
if builder.read_action.is_some() {
self.read_action = builder.read_action;
}
if builder.fields.is_some() {
self.fields = builder.fields.empty_to_none();
}
Expand Down
2 changes: 1 addition & 1 deletion svd-rs/src/usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl Default for Usage {
}

impl Usage {
/// Parse a string into an [Usage] value, returning [`Option::None`] if the string is not valid.
/// Parse a string into an [`Usage`] value, returning [`Option::None`] if the string is not valid.
pub fn parse_str(s: &str) -> Option<Self> {
match s {
"read" => Some(Self::Read),
Expand Down

0 comments on commit fcc459c

Please sign in to comment.