From 0800d059da9928cb09bd1d8538176c1aa4b7407c Mon Sep 17 00:00:00 2001 From: eupn <36292692+eupn@users.noreply.github.com> Date: Fri, 22 Jun 2018 12:39:36 +0300 Subject: [PATCH 1/8] regs/macro.rs: add try_from for bitfield enum This commit will add a function `try_from` for any bitfield created with register_bitfield![] macro. This function enables optional conversion from arbitrary integer value into one of the possible enumerated values specified for the bitfield. --- libraries/tock-register-interface/src/macros.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libraries/tock-register-interface/src/macros.rs b/libraries/tock-register-interface/src/macros.rs index d5588f9ea8..bac826864a 100644 --- a/libraries/tock-register-interface/src/macros.rs +++ b/libraries/tock-register-interface/src/macros.rs @@ -96,6 +96,19 @@ macro_rules! register_bitmasks { $valname = $value, )* } + + impl Value { + pub fn try_from(v: $valtype) -> Option { + match v { + $( + $(#[$inner])* + x if x == Value::$valname as $valtype => Some(Value::$valname), + )* + + _ => None + } + } + } } }; } From ba85920b54b369f00c6f0fda39c4f5de82fcddad Mon Sep 17 00:00:00 2001 From: eupn <36292692+eupn@users.noreply.github.com> Date: Fri, 22 Jun 2018 13:39:04 +0300 Subject: [PATCH 2/8] regs/macros.rs: fix possible confusion with None --- libraries/tock-register-interface/src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/tock-register-interface/src/macros.rs b/libraries/tock-register-interface/src/macros.rs index bac826864a..d7cd1ce203 100644 --- a/libraries/tock-register-interface/src/macros.rs +++ b/libraries/tock-register-interface/src/macros.rs @@ -105,7 +105,7 @@ macro_rules! register_bitmasks { x if x == Value::$valname as $valtype => Some(Value::$valname), )* - _ => None + _ => Option::None } } } From f00b2275c38164ed1551027aa0db8035eca02a80 Mon Sep 17 00:00:00 2001 From: eupn <36292692+eupn@users.noreply.github.com> Date: Fri, 22 Jun 2018 13:41:35 +0300 Subject: [PATCH 3/8] regs/macros.rs: fmt: removed trailing spaces --- libraries/tock-register-interface/src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/tock-register-interface/src/macros.rs b/libraries/tock-register-interface/src/macros.rs index d7cd1ce203..b2982c3c67 100644 --- a/libraries/tock-register-interface/src/macros.rs +++ b/libraries/tock-register-interface/src/macros.rs @@ -96,7 +96,7 @@ macro_rules! register_bitmasks { $valname = $value, )* } - + impl Value { pub fn try_from(v: $valtype) -> Option { match v { From 80654f4df26af566b988c12514138b521ea65850 Mon Sep 17 00:00:00 2001 From: eupn <36292692+eupn@users.noreply.github.com> Date: Fri, 22 Jun 2018 22:40:10 +0300 Subject: [PATCH 4/8] macros.rs: added TryFromValue trait impl --- libraries/tock-register-interface/src/macros.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libraries/tock-register-interface/src/macros.rs b/libraries/tock-register-interface/src/macros.rs index b2982c3c67..cdd1febaf5 100644 --- a/libraries/tock-register-interface/src/macros.rs +++ b/libraries/tock-register-interface/src/macros.rs @@ -63,7 +63,7 @@ macro_rules! register_bitmasks { $(#[$outer])* pub mod $field { #[allow(unused_imports)] - use $crate::regs::FieldValue; + use $crate::regs::{ TryFromValue, FieldValue }; use super::$reg_desc; $( @@ -97,15 +97,17 @@ macro_rules! register_bitmasks { )* } - impl Value { - pub fn try_from(v: $valtype) -> Option { + impl TryFromValue<$valtype> for Value { + type EnumType = Value; + + fn try_from(v: $valtype) -> Option { match v { - $( + $( $(#[$inner])* x if x == Value::$valname as $valtype => Some(Value::$valname), - )* + )* - _ => Option::None + _ => Option::None } } } From 270d18cd3207afc64e540d8a38bba4d27b7b1e1b Mon Sep 17 00:00:00 2001 From: eupn <36292692+eupn@users.noreply.github.com> Date: Fri, 22 Jun 2018 22:44:13 +0300 Subject: [PATCH 5/8] regs.rs: add `read_as_enum()` function --- libraries/tock-register-interface/src/regs.rs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libraries/tock-register-interface/src/regs.rs b/libraries/tock-register-interface/src/regs.rs index caa91c5899..9d404148b0 100644 --- a/libraries/tock-register-interface/src/regs.rs +++ b/libraries/tock-register-interface/src/regs.rs @@ -77,6 +77,14 @@ pub trait RegisterLongName {} impl RegisterLongName for () {} +/// Conversion of raw register value into enumerated values member. +/// Implemented inside register_bitfields![] macro for each bit field. +pub trait TryFromValue { + type EnumType; + + fn try_from(v: V) -> Option; +} + /// Read/Write registers. pub struct ReadWrite { value: T, @@ -117,7 +125,14 @@ impl ReadWrite { pub fn read(&self, field: Field) -> T { (self.get() & (field.mask << field.shift)) >> field.shift } + + #[inline] + pub fn read_as_enum>(&self, field: Field) -> Option { + let val: T = self.read(field); + E::try_from(val) + } + #[inline] pub fn extract(&self) -> LocalRegisterCopy { LocalRegisterCopy::new(self.get()) @@ -172,6 +187,13 @@ impl ReadOnly { pub fn read(&self, field: Field) -> T { (self.get() & (field.mask << field.shift)) >> field.shift } + + #[inline] + pub fn read_as_enum>(&self, field: Field) -> Option { + let val: T = self.read(field); + + E::try_from(val) + } #[inline] pub fn extract(&self) -> LocalRegisterCopy { From 41c53b1da572f3eb85ab76bd69f3bdb7cbe0bcec Mon Sep 17 00:00:00 2001 From: eupn <36292692+eupn@users.noreply.github.com> Date: Sat, 23 Jun 2018 02:21:54 +0300 Subject: [PATCH 6/8] regs/README.rs: added read_as_enum() and matching Added info about read_as_enum() function and matching into Reading and Matching sections. --- libraries/tock-register-interface/README.md | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/libraries/tock-register-interface/README.md b/libraries/tock-register-interface/README.md index a02649739a..65ce1e4721 100644 --- a/libraries/tock-register-interface/README.md +++ b/libraries/tock-register-interface/README.md @@ -110,6 +110,7 @@ There are three types provided by the register interface: `ReadOnly`, ReadOnly .get() -> T // Get the raw register value .read(field: Field) -> T // Read the value of the given field +.read_as_enum(field: Field) -> Option // Read value of the given field as a enum member .is_set(field: Field) -> bool // Check if one or more bits in a field are set .matches_any(value: FieldValue) -> bool // Check if any specified parts of a field match .matches_all(value: FieldValue) -> bool // Check if all specified parts of a field match @@ -126,6 +127,7 @@ ReadWrite .get() -> T // Get the raw register value .set(value: T) // Set the raw register value .read(field: Field) -> T // Read the value of the given field +.read_as_enum(field: Field) -> Option // Read value of the given field as a enum member .write(value: FieldValue) // Write the value of one or more fields, // overwriting other fields to zero .modify(value: FieldValue) // Write the value of one or more fields, @@ -165,6 +167,17 @@ regs.cr.set(regs.cr.get() + 1); // The type annotation is not necessary, but provided for clarity here. let range: u8 = regs.cr.read(Control::RANGE); +// Or one can read `range` as a enum and `match` over it. +let range = regs.cr.read_as_enum(Control::RANGE); +match range { + Some(Control::RANGE::Value::Zero) => { /* ... */ } + Some(Control::RANGE::Value::One) => { /* ... */ } + Some(Control::RANGE::Value::Two) => { /* ... */ } + Some(Control::RANGE::Value::Three) => { /* ... */ } + + None => unreachable!("invalid value") +} + // `en` will be 0 or 1 let en: u8 = regs.cr.read(Control::EN); @@ -231,6 +244,16 @@ while !regs.s.matches_all(Status::TXCOMPLETE::SET + // Or for checking whether any interrupts are enabled: let any_ints = regs.s.matches_any(Status::TXINTERRUPT + Status::RXINTERRUPT); +// Also you can read a register with set of enumerated values as a enum and `match` over it: +let mode = regs.cr.read_as_enum(Status::MODE); + +match mode { + Some(Status::MODE::FullDuplex) => { /* ... */ } + Some(Status::MODE::HalfDuplex) => { /* ... */ } + + None => unreachable!("invalid value") +} + // ----------------------------------------------------------------------------- // LOCAL COPY // ----------------------------------------------------------------------------- From d81c6b555ac9802c8fde9222d34bcc7747e564fd Mon Sep 17 00:00:00 2001 From: eupn <36292692+eupn@users.noreply.github.com> Date: Sat, 23 Jun 2018 02:31:35 +0300 Subject: [PATCH 7/8] regs.rs: fixed formatting --- libraries/tock-register-interface/src/regs.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/tock-register-interface/src/regs.rs b/libraries/tock-register-interface/src/regs.rs index 9d404148b0..7f43867870 100644 --- a/libraries/tock-register-interface/src/regs.rs +++ b/libraries/tock-register-interface/src/regs.rs @@ -125,14 +125,14 @@ impl ReadWrite { pub fn read(&self, field: Field) -> T { (self.get() & (field.mask << field.shift)) >> field.shift } - + #[inline] - pub fn read_as_enum>(&self, field: Field) -> Option { + pub fn read_as_enum>(&self, field: Field) -> Option { let val: T = self.read(field); E::try_from(val) } - + #[inline] pub fn extract(&self) -> LocalRegisterCopy { LocalRegisterCopy::new(self.get()) @@ -187,9 +187,9 @@ impl ReadOnly { pub fn read(&self, field: Field) -> T { (self.get() & (field.mask << field.shift)) >> field.shift } - + #[inline] - pub fn read_as_enum>(&self, field: Field) -> Option { + pub fn read_as_enum>(&self, field: Field) -> Option { let val: T = self.read(field); E::try_from(val) From ca2a4055a8de491378f29acbd1688f215504454d Mon Sep 17 00:00:00 2001 From: Pat Pannuto Date: Mon, 25 Jun 2018 19:13:06 -0700 Subject: [PATCH 8/8] keep `use` formatting consistent Doesn't look like rustfmt is smart enough to enforce this in macros yet. --- libraries/tock-register-interface/src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/tock-register-interface/src/macros.rs b/libraries/tock-register-interface/src/macros.rs index cdd1febaf5..1f07175b72 100644 --- a/libraries/tock-register-interface/src/macros.rs +++ b/libraries/tock-register-interface/src/macros.rs @@ -63,7 +63,7 @@ macro_rules! register_bitmasks { $(#[$outer])* pub mod $field { #[allow(unused_imports)] - use $crate::regs::{ TryFromValue, FieldValue }; + use $crate::regs::{FieldValue, TryFromValue}; use super::$reg_desc; $(