aboutsummaryrefslogtreecommitdiff
path: root/tests/macros.rs
diff options
context:
space:
mode:
authorIan McIntyre <me@mciantyre.dev>2025-04-12 18:37:30 -0400
committerIan McIntyre <me@mciantyre.dev>2025-09-28 10:32:16 -0400
commit495fbc58b6f4d2e751b16883a2c5cee3c598fd79 (patch)
tree733294d810dbd02dba79c156d47cdee246a88aec /tests/macros.rs
parent7bf03005703186667623bfc681e10c44f7f8923d (diff)
Prototype a v0.2HEADv0.2
Needs to be documented. The gist: remove references to MMIO, and add support for nested structures. Drop the reset_reg! macro.
Diffstat (limited to 'tests/macros.rs')
-rw-r--r--tests/macros.rs719
1 files changed, 408 insertions, 311 deletions
diff --git a/tests/macros.rs b/tests/macros.rs
index 7f84221..211c7bc 100644
--- a/tests/macros.rs
+++ b/tests/macros.rs
@@ -1,414 +1,511 @@
-//! Tests that read, write, modify, and reset macros
-//! work with
-//!
-//! - scalar register syntax
-//! - array register syntax
-//!
-//! when supplied with
-//!
-//! - a reference to a register block.
-//! - an "instance" type that derefs to a register block.
-//! - a pointer to a register block.
-
#![allow(non_upper_case_globals, non_snake_case)] // Macro conventions.
-use ral_registers as ral;
+use ral_registers::{self as ral, Instance};
/// A peripheral module.
mod periph {
#[repr(C)]
pub struct RegisterBlock {
- pub MY_SCALAR: ral_registers::RWRegister<u32>,
- pub MY_ARRAY: [ral_registers::RWRegister<u32>; 3],
+ pub MY_SCALAR: u32,
+ pub MY_ARRAY: [u32; 3],
+ pub MY_2D_ARRAY: [[u32; 3]; 3],
+ pub MY_BLOCK: MY_BLOCK::RegisterBlock,
+ pub MY_BLOCKS: [MY_BLOCK::RegisterBlock; 4],
}
- pub mod MY_SCALAR {
- pub mod FIELD_A {
- pub const offset: u32 = 0;
- pub const mask: u32 = 0x7F << offset;
- pub mod R {}
- pub mod W {}
- pub mod RW {}
- }
- pub mod FIELD_B {
- pub const offset: u32 = 27;
- pub const mask: u32 = 0b11 << offset;
- pub mod R {}
- pub mod W {}
- pub mod RW {}
+ ral_registers::register!(pub MY_SCALAR<u32> RW [
+ FIELD_A start(0) width(7) RW {}
+ /// Field B documentation.
+ ///
+ /// It's a field.
+ FIELD_B start(27) width(2) RW {
+ /// This is some magic number.
+ ///
+ /// It's three.
+ MAGIC = 0b11,
}
- }
+ ]);
- /// The register array module resembles the register module for
- /// a scalar register. The macros distinguish the index
- /// operator from the register name to look up items in
- /// this module.
pub mod MY_ARRAY {
- // For testing convenience, we're pretending that MY_ARRAY
- // has the same fields as MY_SCALAR.
pub use super::MY_SCALAR::*;
}
- /// Reset values are always expressed as a scalar, no matter
- /// the register plurality.
- pub struct ResetValues {
- pub MY_SCALAR: u32,
- pub MY_ARRAY: u32,
+ pub mod MY_2D_ARRAY {
+ pub use super::MY_SCALAR::*;
}
- pub mod INST {
- pub const reset: super::ResetValues = super::ResetValues {
- MY_SCALAR: 42,
- MY_ARRAY: 42,
- };
- }
-}
+ pub mod MY_BLOCK {
+ #[repr(C)]
+ pub struct RegisterBlock {
+ pub BLOCK_SCALAR: u32,
+ pub BLOCK_ARRAY: [u32; 4],
+ pub BLOCK_SUBBLOCKS: [[BLOCK_SUBBLOCKS::RegisterBlock; 2]; 2],
+ }
-fn register_block() -> periph::RegisterBlock {
- // Safety: bitpattern of zero is fine.
- use std::mem::MaybeUninit;
- unsafe { MaybeUninit::zeroed().assume_init() }
-}
+ ral_registers::register!(pub BLOCK_SCALAR<u32> RW [
+ BLOCK_FIELD_A start(0) width(7) RW {}
+ BLOCK_FIELD_B start(27) width(2) RW { MAGIC = 0b11 }
+ ]);
-struct Instance<'a> {
- rb: &'a periph::RegisterBlock,
-}
+ pub mod BLOCK_ARRAY {
+ pub use super::BLOCK_SCALAR::*;
+ }
-impl<'a> Instance<'a> {
- fn new(rb: &'a periph::RegisterBlock) -> Self {
- Self { rb }
+ pub mod BLOCK_SUBBLOCKS {
+ #[repr(C)]
+ pub struct RegisterBlock {
+ pub SUBBLOCK_SCALAR: u32,
+ pub SUBBLOCK_ARRAY: [u32; 3],
+ }
+
+ ral_registers::register!(pub SUBBLOCK_SCALAR<u32> RW [
+ SUBBLOCK_FIELD_A start(0) width(7) RW {}
+ SUBBLOCK_FIELD_B start(27) width(2) RW { MAGIC = 0b11 }
+
+ ]);
+ pub mod SUBBLOCK_ARRAY {
+ pub use super::SUBBLOCK_SCALAR::*;
+ }
+ }
}
-}
-impl std::ops::Deref for Instance<'_> {
- type Target = periph::RegisterBlock;
- fn deref(&self) -> &Self::Target {
- self.rb
+ pub mod MY_BLOCKS {
+ pub use super::MY_BLOCK::*;
}
}
-/// Defines the base cases for read_reg.
-///
-/// The goal is to have one macro path that supports both scalar
-/// and array tests cases. To achieve that, there's always a register
-/// identifier. There's optionally a bracket that has an offset.
-macro_rules! read_reg_test_cases {
- ($instance:expr, $register:ident $([$offset:expr])*) => {
- // Setup:
- (*$instance).$register $([$offset])*.write(u32::MAX);
-
- assert_eq!(ral::read_reg!(periph, $instance, $register $([$offset])*), u32::MAX, "Direct read");
-
- assert_eq!(ral::read_reg!(periph, $instance, $register $([$offset])*, FIELD_A), 0x7F, "Individual field read (A)");
- assert_eq!(ral::read_reg!(periph, $instance, $register $([$offset])*, FIELD_B), 0b11, "Individual field read (B)");
- assert_eq!(ral::read_reg!(periph, $instance, $register $([$offset])*, FIELD_A,), 0x7F, "Individual field read with trailing comma");
-
- assert_eq!(
- ral::read_reg!(periph, $instance, $register $([$offset])*, FIELD_A, FIELD_B),
- (0x7F, 0b11),
- "Tuple field reads"
- );
-
- assert!(ral::read_reg!(
- periph,
- $instance,
- $register $([$offset])*,
- FIELD_A == 0x7F
- ), "Boolean expressions");
- };
+fn zeroed() -> periph::RegisterBlock {
+ unsafe { std::mem::MaybeUninit::zeroed().assume_init() }
}
#[test]
-fn read_scalar_ref() {
- let rb = register_block();
- read_reg_test_cases!(&rb, MY_SCALAR);
-}
+fn read_scalar() {
+ let mut block = zeroed();
+ block.MY_SCALAR = 4;
-#[test]
-fn read_scalar_deref() {
- let rb = register_block();
- let inst = Instance::new(&rb);
- read_reg_test_cases!(inst, MY_SCALAR);
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ assert_eq!(ral::read_reg!(periph, inst, MY_SCALAR), 4);
}
#[test]
-fn read_scalar_ptr() {
- let ptr: *const _ = &register_block();
- unsafe {
- read_reg_test_cases!(ptr, MY_SCALAR);
- }
-}
+fn read_array() {
+ let mut block = zeroed();
+ block.MY_ARRAY[1] = 4;
-#[test]
-fn read_array_ref() {
- let rb = register_block();
- read_reg_test_cases!(&rb, MY_ARRAY[1]);
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ assert_eq!(ral::read_reg!(periph, inst, MY_ARRAY[1]), 4);
}
#[test]
-fn read_array_deref() {
- let rb = register_block();
- let inst = Instance::new(&rb);
- read_reg_test_cases!(inst, MY_ARRAY[1]);
-}
+fn read_2d_array() {
+ let mut block = zeroed();
+ block.MY_2D_ARRAY[1][1] = 4;
-#[test]
-fn read_array_ptr() {
- let ptr: *const _ = &register_block();
- unsafe {
- read_reg_test_cases!(ptr, MY_ARRAY[1]);
- }
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ assert_eq!(ral::read_reg!(periph, inst, MY_2D_ARRAY[1][1]), 4);
}
-#[should_panic]
#[test]
-fn read_array_out_of_bounds() {
- let rb = register_block();
- ral::read_reg!(periph, &rb, MY_ARRAY[42]);
-}
+fn read_block_scalar() {
+ let mut block = zeroed();
+ block.MY_BLOCK.BLOCK_SCALAR = 4;
-/// Base test cases for write_reg.
-///
-/// See [read_reg_test_cases] for more information.
-macro_rules! write_reg_test_cases {
- ($instance:expr, $register:ident $([$offset:expr])*) => {
- ral::write_reg!(periph, $instance, $register $([$offset])*, FIELD_A: u32::MAX);
- assert_eq!((*$instance).$register $([$offset])*.read(), 0x7F, "1:1 write:field (A)");
- ral::write_reg!(periph, $instance, $register $([$offset])*, FIELD_B: u32::MAX);
- assert_eq!((*$instance).$register $([$offset])*.read(), 0b11 << 27, "1:1 write:field (B)");
- ral::write_reg!(periph, $instance, $register $([$offset])*, FIELD_A: u32::MAX,);
- assert_eq!((*$instance).$register $([$offset])*.read(), 0x7F, "write with trailing comma");
-
- ral::write_reg!(
- periph,
- $instance,
- $register $([$offset])*,
- FIELD_A: u32::MAX,
- FIELD_B: u32::MAX
- );
- assert_eq!((*$instance).$register $([$offset])*.read(), (0b11 << 27) | 0x7F, "1:N write:field");
-
- ral::write_reg!(periph, $instance, $register $([$offset])*, 0xAAAAAAAA);
- assert_eq!((*$instance).$register $([$offset])*.read(), 0xAAAAAAAA, "Direct write");
-
- // Make sure that local variables mask, offset don't shadow macro details.
- #[deny(warnings)]
- {
- let mask = 7;
- let offset = 8;
- ral::write_reg!(periph, $instance, $register $([$offset])*, FIELD_A: mask, FIELD_B: offset);
- }
- };
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ assert_eq!(ral::read_reg!(periph, inst, MY_BLOCK.BLOCK_SCALAR), 4);
}
#[test]
-fn write_scalar_ref() {
- let rb = register_block();
- write_reg_test_cases!(&rb, MY_SCALAR);
+fn read_block_array() {
+ let mut block = zeroed();
+ block.MY_BLOCK.BLOCK_ARRAY[1] = 4;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ assert_eq!(ral::read_reg!(periph, inst, MY_BLOCK.BLOCK_ARRAY[1]), 4);
}
#[test]
-fn write_scalar_deref() {
- let rb = register_block();
- let inst = Instance::new(&rb);
- write_reg_test_cases!(inst, MY_SCALAR);
+fn read_block_subblock_array() {
+ let mut block = zeroed();
+ block.MY_BLOCK.BLOCK_SUBBLOCKS[1][1].SUBBLOCK_SCALAR = 4;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ assert_eq!(
+ ral::read_reg!(periph, inst, MY_BLOCK.BLOCK_SUBBLOCKS[1][1].SUBBLOCK_SCALAR),
+ 4
+ );
}
#[test]
-fn write_scalar_ptr() {
- let ptr: *const _ = &register_block();
- unsafe {
- write_reg_test_cases!(ptr, MY_SCALAR);
- }
+fn read_scalar_fields() {
+ let mut block = zeroed();
+ block.MY_SCALAR = u32::MAX;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+
+ let a = ral::read_reg!(periph, &&&&&&&&&&inst, MY_SCALAR, FIELD_A);
+ assert_eq!(a, 0x7F);
+
+ let b = ral::read_reg!(periph, inst, MY_SCALAR, FIELD_B);
+ assert_eq!(b, 0b11);
+
+ let (a, b) = ral::read_reg!(periph, inst, MY_SCALAR, FIELD_A, FIELD_B);
+ assert_eq!(a, 0x7F);
+ assert_eq!(b, 0b11);
}
#[test]
-fn write_array_ref() {
- let rb = register_block();
- write_reg_test_cases!(&rb, MY_ARRAY[1]);
+fn read_array_fields() {
+ let mut block = zeroed();
+ block.MY_ARRAY[1] = u32::MAX;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+
+ let a = ral::read_reg!(periph, inst, MY_ARRAY[1], FIELD_A);
+ assert_eq!(a, 0x7F);
+
+ let b = ral::read_reg!(periph, inst, MY_ARRAY[1], FIELD_B);
+ assert_eq!(b, 0b11);
+
+ let (a, b) = ral::read_reg!(periph, inst, MY_ARRAY[1], FIELD_A, FIELD_B);
+ assert_eq!(a, 0x7F);
+ assert_eq!(b, 0b11);
}
#[test]
-fn write_array_deref() {
- let rb = register_block();
- let inst = Instance::new(&rb);
- write_reg_test_cases!(inst, MY_ARRAY[1]);
+fn read_2d_array_fields() {
+ let mut block = zeroed();
+ block.MY_2D_ARRAY[1][1] = u32::MAX;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+
+ let a = ral::read_reg!(::self::periph, inst, MY_2D_ARRAY[1][1], FIELD_A);
+ assert_eq!(a, 0x7F);
+
+ let b = ral::read_reg!(periph, inst, MY_2D_ARRAY[1][1], FIELD_B);
+ assert_eq!(b, 0b11);
+
+ let (a, b) = ral::read_reg!(periph, inst, MY_2D_ARRAY[1][1], FIELD_A, FIELD_B);
+ assert_eq!(a, 0x7F);
+ assert_eq!(b, 0b11);
}
#[test]
-fn write_array_ptr() {
- let ptr: *const _ = &register_block();
- unsafe {
- write_reg_test_cases!(ptr, MY_ARRAY[1]);
- }
+fn read_block_scalar_fields() {
+ let mut block = zeroed();
+ block.MY_BLOCK.BLOCK_SCALAR = u32::MAX;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+
+ let a = ral::read_reg!(periph, inst, MY_BLOCK.BLOCK_SCALAR, BLOCK_FIELD_A);
+ assert_eq!(a, 0x7F);
+
+ let b = ral::read_reg!(periph, inst, MY_BLOCK.BLOCK_SCALAR, BLOCK_FIELD_B);
+ assert_eq!(b, 0b11);
+
+ let (a, b) = ral::read_reg!(
+ periph,
+ inst,
+ MY_BLOCK.BLOCK_SCALAR,
+ BLOCK_FIELD_A,
+ BLOCK_FIELD_B
+ );
+ assert_eq!(a, 0x7F);
+ assert_eq!(b, 0b11);
}
-#[should_panic]
#[test]
-fn write_array_out_of_bounds() {
- let rb = register_block();
- ral::write_reg!(periph, &rb, MY_ARRAY[42], 7);
-}
+fn read_block_array_fields() {
+ let mut block = zeroed();
+ block.MY_BLOCK.BLOCK_ARRAY[1] = u32::MAX;
-/// Base test cases for modify_reg.
-///
-/// See [read_reg_test_cases] for more information.
-macro_rules! modify_reg_test_cases {
- ($instance:expr, $register:ident $([$offset:expr])*) => {
- ral::modify_reg!(periph, $instance, $register $([$offset])*, FIELD_A: u32::MAX);
- assert_eq!((*$instance).$register $([$offset])*.read(), 0x7F, "RMW individual fields (A)");
- ral::modify_reg!(periph, $instance, $register $([$offset])*, FIELD_B: u32::MAX);
- assert_eq!((*$instance).$register $([$offset])*.read(), 0x7F | (0b11 << 27), "RMW individual fields (B)");
- ral::modify_reg!(periph, $instance, $register $([$offset])*, FIELD_A: u32::MIN,);
- assert_eq!((*$instance).$register $([$offset])*.read(), (0b11 << 27), "RMW with trailing comma");
-
- ral::modify_reg!(periph, $instance, $register $([$offset])*, FIELD_A: 2, FIELD_B: 2);
- assert_eq!((*$instance).$register $([$offset])*.read(), 2 | (2 << 27), "RMW multiple fields");
-
- ral::modify_reg!(periph, $instance, $register $([$offset])*, |reg| {
- assert_eq!(reg, 2 | (2 << 27));
- reg | u32::MAX
- });
- assert_eq!((*$instance).$register $([$offset])*.read(), u32::MAX, "RMW whole register");
-
- // Make sure that local variables mask, offset don't shadow macro details.
- #[deny(warnings)]
- {
- let mask = 7;
- let offset = 8;
- ral::modify_reg!(periph, $instance, $register $([$offset])*, FIELD_A: mask, FIELD_B: offset);
- }
- };
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+
+ let a = ral::read_reg!(periph, inst, MY_BLOCK.BLOCK_ARRAY[1], BLOCK_FIELD_A);
+ assert_eq!(a, 0x7F);
+
+ let b = ral::read_reg!(periph, inst, MY_BLOCK.BLOCK_ARRAY[1], BLOCK_FIELD_B);
+ assert_eq!(b, 0b11);
+
+ let (a, b) = ral::read_reg!(
+ periph,
+ inst,
+ MY_BLOCK.BLOCK_ARRAY[1],
+ BLOCK_FIELD_A,
+ BLOCK_FIELD_B
+ );
+ assert_eq!(a, 0x7F);
+ assert_eq!(b, 0b11);
}
#[test]
-fn modify_scalar_ref() {
- let rb = register_block();
- modify_reg_test_cases!(&rb, MY_SCALAR);
+fn read_block_subblock_scalar_fields() {
+ let mut block = zeroed();
+ block.MY_BLOCK.BLOCK_SUBBLOCKS[1][1].SUBBLOCK_SCALAR = u32::MAX;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+
+ let a = ral::read_reg!(
+ periph,
+ inst,
+ MY_BLOCK.BLOCK_SUBBLOCKS[1][1].SUBBLOCK_SCALAR,
+ SUBBLOCK_FIELD_A
+ );
+ assert_eq!(a, 0x7F);
+
+ let b = ral::read_reg!(
+ periph,
+ inst,
+ MY_BLOCK.BLOCK_SUBBLOCKS[1][1].SUBBLOCK_SCALAR,
+ SUBBLOCK_FIELD_B
+ );
+ assert_eq!(b, 0b11);
+
+ let (a, b) = ral::read_reg!(
+ periph,
+ inst,
+ MY_BLOCK.BLOCK_SUBBLOCKS[1][1].SUBBLOCK_SCALAR,
+ SUBBLOCK_FIELD_A,
+ SUBBLOCK_FIELD_B
+ );
+ assert_eq!(a, 0x7F);
+ assert_eq!(b, 0b11);
}
#[test]
-fn modify_scalar_deref() {
- let rb = register_block();
- let inst = Instance::new(&rb);
- modify_reg_test_cases!(inst, MY_SCALAR);
+fn read_blocks_subblock_array_fields() {
+ let mut block = zeroed();
+ block.MY_BLOCKS[0].BLOCK_SUBBLOCKS[1][1].SUBBLOCK_ARRAY[0] = u32::MAX;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+
+ let a = ral::read_reg!(
+ periph,
+ inst,
+ MY_BLOCKS[0].BLOCK_SUBBLOCKS[1][1].SUBBLOCK_ARRAY[0],
+ SUBBLOCK_FIELD_A
+ );
+ assert_eq!(a, 0x7F);
+
+ let b = ral::read_reg!(
+ periph,
+ inst,
+ MY_BLOCKS[0].BLOCK_SUBBLOCKS[1][1].SUBBLOCK_ARRAY[0],
+ SUBBLOCK_FIELD_B
+ );
+ assert_eq!(b, 0b11);
+
+ let (a, b) = ral::read_reg!(
+ periph,
+ inst,
+ MY_BLOCKS[0].BLOCK_SUBBLOCKS[1][1].SUBBLOCK_ARRAY[0],
+ SUBBLOCK_FIELD_A,
+ SUBBLOCK_FIELD_B
+ );
+ assert_eq!(a, 0x7F);
+ assert_eq!(b, 0b11);
}
#[test]
-fn modify_scalar_ptr() {
- let ptr: *const _ = &register_block();
- unsafe {
- modify_reg_test_cases!(ptr, MY_SCALAR);
- }
+fn read_scalar_field_cmp() {
+ let mut block = zeroed();
+ block.MY_SCALAR = u32::MAX;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ assert!(ral::read_reg!(periph, inst, MY_SCALAR, FIELD_A == 0x7f));
+ assert!(ral::read_reg!(periph, inst, MY_SCALAR, FIELD_B == MAGIC));
}
#[test]
-fn modify_array_ref() {
- let rb = register_block();
- modify_reg_test_cases!(&rb, MY_ARRAY[1]);
+fn read_array_field_cmp() {
+ let mut block = zeroed();
+ block.MY_ARRAY[1] = u32::MAX;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ assert!(ral::read_reg!(periph, inst, MY_ARRAY[1], FIELD_A == 0x7f));
+ assert!(ral::read_reg!(periph, inst, MY_ARRAY[1], FIELD_B == MAGIC));
}
#[test]
-fn modify_array_deref() {
- let rb = register_block();
- let inst = Instance::new(&rb);
- modify_reg_test_cases!(inst, MY_ARRAY[1]);
+fn read_2d_array_field_cmp() {
+ let mut block = zeroed();
+ block.MY_2D_ARRAY[0][1] = u32::MAX;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ assert!(ral::read_reg!(
+ periph,
+ inst,
+ MY_2D_ARRAY[0][1],
+ FIELD_A == 0x7f
+ ));
+ assert!(ral::read_reg!(
+ periph,
+ inst,
+ MY_2D_ARRAY[0][1],
+ FIELD_B == MAGIC
+ ));
}
#[test]
-fn modify_array_ptr() {
- let ptr: *const _ = &register_block();
- unsafe {
- modify_reg_test_cases!(ptr, MY_ARRAY[1]);
- }
+fn read_blocks_subblock_array_fields_cmp() {
+ let mut block = zeroed();
+ block.MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0] = u32::MAX;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ assert!(ral::read_reg!(
+ periph,
+ inst,
+ MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ SUBBLOCK_FIELD_A == 0x7f
+ ));
+ assert!(ral::read_reg!(
+ periph,
+ inst,
+ MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ SUBBLOCK_FIELD_B == MAGIC
+ ));
}
-#[should_panic]
#[test]
-fn modify_array_out_of_bounds() {
- let rb = register_block();
- ral::modify_reg!(periph, &rb, MY_ARRAY[42], |_| 7);
-}
+fn write_blocks_subblock_array() {
+ let mut block = zeroed();
-/// Base test cases for reset_reg.
-///
-/// See [read_reg_test_cases] for more information.
-macro_rules! reset_reg_test_cases {
- ($instance:expr, $register:ident $([$offset:expr])*) => {
- (*$instance).$register $([$offset])*.write(u32::MAX);
- ral::reset_reg!(periph, $instance, INST, $register $([$offset])*);
- assert_eq!((*$instance).$register $([$offset])*.read(), 42, "Entire register");
-
- (*$instance).$register $([$offset])*.write(u32::MAX);
- ral::reset_reg!(periph, $instance, INST, $register $([$offset])*, FIELD_B);
- assert_eq!((*$instance).$register $([$offset])*.read(), u32::MAX & !(0b11 << 27), "Field in register (B)");
- ral::reset_reg!(periph, $instance, INST, $register $([$offset])*, FIELD_A);
- assert_eq!(
- (*$instance).$register $([$offset])*.read(),
- u32::MAX & !(0b11 << 27) & !0x7F | 42,
- "Field in register (A)"
- );
-
- (*$instance).$register $([$offset])*.write(u32::MAX);
- ral::reset_reg!(periph, $instance, INST, $register $([$offset])*, FIELD_B,);
- assert_eq!((*$instance).$register $([$offset])*.read(), u32::MAX & !(0b11 << 27), "With trailing comma");
-
-
- (*$instance).$register $([$offset])*.write(u32::MAX);
- ral::reset_reg!(periph, $instance, INST, $register $([$offset])*, FIELD_B, FIELD_A);
- assert_eq!(
- (*$instance).$register $([$offset])*.read(),
- u32::MAX & !(0b11 << 27) & !0x7F | 42,
- "Fields in register"
- );
- };
-}
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ ral::write_reg!(
+ periph,
+ inst,
+ MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ 42
+ );
-#[test]
-fn reset_scalar_ref() {
- let rb = register_block();
- reset_reg_test_cases!(&rb, MY_SCALAR);
+ assert_eq!(
+ block.MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ 42
+ );
}
#[test]
-fn reset_scalar_deref() {
- let rb = register_block();
- let inst = Instance::new(&rb);
- reset_reg_test_cases!(inst, MY_SCALAR);
+fn write_blocks_subblock_array_fields() {
+ let mut block = zeroed();
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+
+ ral::write_reg!(
+ periph,
+ &&&&&&inst,
+ MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ SUBBLOCK_FIELD_A: u32::MAX,
+ SUBBLOCK_FIELD_B: u32::MAX,
+ );
+
+ assert_eq!(
+ block.MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ (0b11 << 27) | 0x7f
+ );
+
+ let get_inst = || inst;
+
+ ral::write_reg!(
+ periph,
+ get_inst(),
+ MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ SUBBLOCK_FIELD_A: u32::MAX,
+ );
+
+ assert_eq!(
+ block.MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ 0x7f
+ );
+
+ ral::write_reg!(
+ crate::periph,
+ &&&inst,
+ MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ SUBBLOCK_FIELD_B: MAGIC,
+ );
+
+ assert_eq!(
+ block.MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ 0b11 << 27
+ );
}
#[test]
-fn reset_scalar_ptr() {
- let ptr: *const _ = &register_block();
- unsafe {
- reset_reg_test_cases!(ptr, MY_SCALAR);
- }
-}
+fn modify_blocks_subblock_array() {
+ let mut block = zeroed();
+ block.MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0] = u32::MAX;
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ ral::modify_reg!(
+ periph,
+ &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&inst,
+ MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ |v| {
+ let x = !0xAAAA_AAAA;
+ v & x
+ }
+ );
-#[test]
-fn reset_array_ref() {
- let rb = register_block();
- reset_reg_test_cases!(&rb, MY_ARRAY[1]);
+ assert_eq!(
+ block.MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ 0x5555_5555
+ );
}
#[test]
-fn reset_array_deref() {
- let rb = register_block();
- let inst = Instance::new(&rb);
- reset_reg_test_cases!(inst, MY_ARRAY[1]);
+fn modify_blocks_subblock_array_fields() {
+ let mut block = zeroed();
+
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+ ral::modify_reg!(
+ ::periph,
+ inst,
+ MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ SUBBLOCK_FIELD_A: u32::MAX,
+ SUBBLOCK_FIELD_B: MAGIC,
+ );
+
+ assert_eq!(
+ block.MY_BLOCKS[0].BLOCK_SUBBLOCKS[0][0].SUBBLOCK_ARRAY[0],
+ (0b11 << 27) | 0x7F,
+ );
}
#[test]
-fn reset_array_ptr() {
- let ptr: *const _ = &register_block();
- unsafe {
- reset_reg_test_cases!(ptr, MY_ARRAY[1]);
- }
+#[deny(warnings)]
+fn mask_offset_access_shadowing() {
+ let mut block = zeroed();
+ let inst = unsafe { Instance::new_unchecked(&mut block) };
+
+ let mask = 1;
+ let offset = 2;
+ let access = 3;
+
+ ral::write_reg!(::periph, inst, MY_SCALAR, FIELD_A: (mask | offset | access));
+ ral::modify_reg!(::periph, inst, MY_ARRAY[0], FIELD_A: mask, FIELD_B: offset);
+ ral::modify_reg!(::periph, inst, MY_SCALAR, FIELD_A: access);
}
-#[should_panic]
#[test]
-fn reset_array_out_of_bounds() {
- let rb = register_block();
- ral::reset_reg!(periph, &rb, INST, MY_ARRAY[42]);
+#[deny(warnings)]
+fn macro_unsafe_inline() {
+ let mut block = zeroed();
+ ral::read_reg!(
+ periph,
+ unsafe { Instance::new_unchecked(&mut block) },
+ MY_SCALAR
+ );
+ ral::write_reg!(
+ periph,
+ unsafe { Instance::new_unchecked(&mut block) },
+ MY_SCALAR,
+ 5
+ );
+ ral::modify_reg!(
+ periph, unsafe { Instance::new_unchecked(&mut block) }, MY_SCALAR, FIELD_A: 5
+ );
+ ral::modify_reg!(
+ periph,
+ unsafe { Instance::new_unchecked(&mut block) },
+ MY_SCALAR,
+ |_| 5
+ );
}