Eliminate the use of volatile-register crate
See related issue
https://github.com/rust-embedded/volatile-register/issues/10
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I395de4a119d5471297f0d39480e390f506e575b0
diff --git a/Cargo.lock b/Cargo.lock
index a8dccba..eac2616 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -7,7 +7,6 @@
version = "0.1.0"
dependencies = [
"bitflags",
- "volatile-register",
]
[[package]]
@@ -15,18 +14,3 @@
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
-
-[[package]]
-name = "vcell"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
-
-[[package]]
-name = "volatile-register"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc"
-dependencies = [
- "vcell",
-]
diff --git a/Cargo.toml b/Cargo.toml
index 1a359e3..db5bdf0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,4 +18,3 @@
[dependencies]
bitflags = "2.6"
-volatile-register = "0.2"
diff --git a/src/lib.rs b/src/lib.rs
index fa3e661..21bc595 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,8 +9,10 @@
#![no_std]
use bitflags::bitflags;
-use core::ops::{Deref, Range};
-use volatile_register::{RO, RW, WO};
+use core::{
+ ops::{DerefMut, Range},
+ ptr::{addr_of, addr_of_mut},
+};
bitflags! {
// Distributor Control Register
@@ -39,69 +41,69 @@
/// GIC Distributor register map
#[repr(C, align(4))]
pub struct GICDRegisters {
- ctlr: RW<u32>, // 0x0000
- typer: RO<u32>, // 0x0004
- iidr: RO<u32>, // 0x0008
- typer2: RO<u32>, // 0x000c
- statusr: RW<u32>, // 0x0010
- reserved_0014: [u32; 3], // 0x0014-0x001c
- imdef0: [u32; 8], // 0x0020-0x003c
- setspi_nsr: WO<u32>, // 0x0040
- reserved_0044: u32, // 0x0044
- clrspi_nsr: WO<u32>, // 0x0048
- reserved_004c: u32, // 0x004c
- setspi_sr: WO<u32>, // 0x0050
- reserved_0054: u32, // 0x0054
- clrspi_sr: WO<u32>, // 0x0058
- reserved_005c: [u32; 9], // 0x005c-0x007c
- igroupr: [RW<u32>; 32], // 0x0080-0x00fc
- isenabler: [RW<u32>; 32], // 0x0100-0x017c
- icenabler: [RW<u32>; 32], // 0x0180-0x01fc
- ispendr: [RW<u32>; 32], // 0x0200-0x027c
- icpendr: [RW<u32>; 32], // 0x0280-0x02fc
- isactiver: [RW<u32>; 32], // 0x0300-0x037c
- icactiver: [RW<u32>; 32], // 0x0380-0x03fc
- ipriorityr: [RW<u32>; 256], // 0x0400-0x07f8
- itargetsr: [RW<u32>; 256], // 0x0800-0x0bfc
- icfgr: [RW<u32>; 64], // 0x0c00-0x0cfc
- igrpmodr: [RW<u32>; 32], // 0x0d00-0x0d7c
- reserved_0d80: [u32; 32], // 0x0d80-0x0dfc
- nsacr: [RW<u32>; 64], // 0x0e00-0x0efc
- sgir: WO<u32>, // 0x0f00
- reserved_0f04: [u32; 3], // 0x0f04-0x0f0c
- cpendsgir: [RW<u32>; 4], // 0x0f10-0x0f1c
- spendsgir: [RW<u32>; 4], // 0x0f20-0x0f2c
- reserved_0f30: [u32; 20], // 0x0f30-0x0f7c
- inmir: [RW<u32>; 32], // 0x0f80-0x0ffc
- igroupr_e: [RW<u32>; 32], // 0x1000-0x107c
- reserved_1080: [u32; 96], // 0x1080-0x1fc
- isenabler_e: [RW<u32>; 32], // 0x1200-0x127c
- reserved_1280: [u32; 96], // 0x1280-0x13fc
- icenabler_e: [RW<u32>; 32], // 0x1400-0x147c
- reserved_1480: [u32; 96], // 0x1480-0x15fc
- ispendr_e: [RW<u32>; 32], // 0x1600-0x167c
- reserved_1680: [u32; 96], // 0x1680-0x17fc
- icpendr_e: [RW<u32>; 32], // 0x1800-0x187c
- reserved_1880: [u32; 96], // 0x1880-0x19fc
- isactive_e: [RW<u32>; 32], // 0x1a00-0x1a7c
- reserved_1a80: [u32; 96], // 0x1a80-0x1bfc
- icactive_e: [RW<u32>; 32], // 0x1c00-0x1c7c
- reserved_1c80: [u32; 224], // 0x1c80-0x1ffc
- ipriorityr_e: [RW<u32>; 256], // 0x2000-0x23fc
- reserved_2400: [u32; 768], // 0x2400-0x2ffc
- icfgr_e: [RW<u32>; 64], // 0x3000-0x30fc
- reserved_3100: [u32; 192], // 0x3100-0x33fc
- igrpmodr_e: [RW<u32>; 32], // 0x3400-0x347c
- reserved_3480: [u32; 96], // 0x3480-0x35fc
- nsacr_e: [RW<u32>; 32], // 0x3600-0x367c
- reserved_3680: [u32; 256], // 0x3680-0x3afc
- inmir_e: [RW<u32>; 64], // 0x3b00-0x3bfc
- reserved_3b80: [u32; 2400], // 0x3b80-0x60fc
- irouter: [RW<u32>; 1975], // 0x6100-0x7fd8
- reserved_7fdc: [u32; 9], // 0x7fdc-0x7ffc
- irouter_e: [RW<u32>; 2048], // 0x8000-0x9ffc
- reserved_a000: [u32; 6132], // 0xa000-0xffcc
- id_registers: [RW<u32>; 12], // 0xffd0-0xfffc
+ ctlr: u32, // 0x0000
+ typer: u32, // 0x0004
+ iidr: u32, // 0x0008
+ typer2: u32, // 0x000c
+ statusr: u32, // 0x0010
+ reserved_0014: [u32; 3], // 0x0014-0x001c
+ imdef0: [u32; 8], // 0x0020-0x003c
+ setspi_nsr: u32, // 0x0040
+ reserved_0044: u32, // 0x0044
+ clrspi_nsr: u32, // 0x0048
+ reserved_004c: u32, // 0x004c
+ setspi_sr: u32, // 0x0050
+ reserved_0054: u32, // 0x0054
+ clrspi_sr: u32, // 0x0058
+ reserved_005c: [u32; 9], // 0x005c-0x007c
+ igroupr: [u32; 32], // 0x0080-0x00fc
+ isenabler: [u32; 32], // 0x0100-0x017c
+ icenabler: [u32; 32], // 0x0180-0x01fc
+ ispendr: [u32; 32], // 0x0200-0x027c
+ icpendr: [u32; 32], // 0x0280-0x02fc
+ isactiver: [u32; 32], // 0x0300-0x037c
+ icactiver: [u32; 32], // 0x0380-0x03fc
+ ipriorityr: [u32; 256], // 0x0400-0x07f8
+ itargetsr: [u32; 256], // 0x0800-0x0bfc
+ icfgr: [u32; 64], // 0x0c00-0x0cfc
+ igrpmodr: [u32; 32], // 0x0d00-0x0d7c
+ reserved_0d80: [u32; 32], // 0x0d80-0x0dfc
+ nsacr: [u32; 64], // 0x0e00-0x0efc
+ sgir: u32, // 0x0f00
+ reserved_0f04: [u32; 3], // 0x0f04-0x0f0c
+ cpendsgir: [u32; 4], // 0x0f10-0x0f1c
+ spendsgir: [u32; 4], // 0x0f20-0x0f2c
+ reserved_0f30: [u32; 20], // 0x0f30-0x0f7c
+ inmir: [u32; 32], // 0x0f80-0x0ffc
+ igroupr_e: [u32; 32], // 0x1000-0x107c
+ reserved_1080: [u32; 96], // 0x1080-0x1fc
+ isenabler_e: [u32; 32], // 0x1200-0x127c
+ reserved_1280: [u32; 96], // 0x1280-0x13fc
+ icenabler_e: [u32; 32], // 0x1400-0x147c
+ reserved_1480: [u32; 96], // 0x1480-0x15fc
+ ispendr_e: [u32; 32], // 0x1600-0x167c
+ reserved_1680: [u32; 96], // 0x1680-0x17fc
+ icpendr_e: [u32; 32], // 0x1800-0x187c
+ reserved_1880: [u32; 96], // 0x1880-0x19fc
+ isactive_e: [u32; 32], // 0x1a00-0x1a7c
+ reserved_1a80: [u32; 96], // 0x1a80-0x1bfc
+ icactive_e: [u32; 32], // 0x1c00-0x1c7c
+ reserved_1c80: [u32; 224], // 0x1c80-0x1ffc
+ ipriorityr_e: [u32; 256], // 0x2000-0x23fc
+ reserved_2400: [u32; 768], // 0x2400-0x2ffc
+ icfgr_e: [u32; 64], // 0x3000-0x30fc
+ reserved_3100: [u32; 192], // 0x3100-0x33fc
+ igrpmodr_e: [u32; 32], // 0x3400-0x347c
+ reserved_3480: [u32; 96], // 0x3480-0x35fc
+ nsacr_e: [u32; 32], // 0x3600-0x367c
+ reserved_3680: [u32; 256], // 0x3680-0x3afc
+ inmir_e: [u32; 64], // 0x3b00-0x3bfc
+ reserved_3b80: [u32; 2400], // 0x3b80-0x60fc
+ irouter: [u32; 1975], // 0x6100-0x7fd8
+ reserved_7fdc: [u32; 9], // 0x7fdc-0x7ffc
+ irouter_e: [u32; 2048], // 0x8000-0x9ffc
+ reserved_a000: [u32; 6132], // 0xa000-0xffcc
+ id_registers: [u32; 12], // 0xffd0-0xfffc
}
/// # GIC Distributor error type
@@ -116,24 +118,24 @@
/// Redistributors and CPU interfaces that are connected to the PEs in the system.
pub struct GicDistributor<R>
where
- R: Deref<Target = GICDRegisters>,
+ R: DerefMut<Target = GICDRegisters>,
{
gicd: R,
}
impl<R> GicDistributor<R>
where
- R: Deref<Target = GICDRegisters>,
+ R: DerefMut<Target = GICDRegisters>,
{
const MAX_IT: usize = 32;
/// Create GIC Distributor instance
- pub fn new(gicd: R) -> Self {
+ pub fn new(mut gicd: R) -> Self {
unsafe {
for n in 0..Self::MAX_IT {
- gicd.icenabler[n].write(0xffffffff);
- gicd.icpendr[n].write(0xffffffff);
- gicd.igroupr[n].write(0xffffffff);
+ addr_of_mut!(gicd.icenabler[n]).write_volatile(0xffffffff);
+ addr_of_mut!(gicd.icpendr[n]).write_volatile(0xffffffff);
+ addr_of_mut!(gicd.igroupr[n]).write_volatile(0xffffffff);
}
}
@@ -141,43 +143,47 @@
}
/// Enable Group 0 interrupts
- pub fn enable_group0(&self) {
+ pub fn enable_group0(&mut self) {
unsafe {
- self.gicd
- .ctlr
- .modify(|v| v | DistributorControlRegister::EnableGrp0.bits());
+ let value = addr_of!(self.gicd.ctlr).read_volatile();
+ addr_of_mut!(self.gicd.ctlr)
+ .write_volatile(value | DistributorControlRegister::EnableGrp0.bits());
}
}
/// Enable Secure Group 1 interrupts
- pub fn enable_secure_group1(&self) {
+ pub fn enable_secure_group1(&mut self) {
unsafe {
- self.gicd
- .ctlr
- .modify(|v| v | DistributorControlRegister::EnableGrp1S.bits());
+ let value = addr_of!(self.gicd.ctlr).read_volatile();
+ addr_of_mut!(self.gicd.ctlr)
+ .write_volatile(value | DistributorControlRegister::EnableGrp1S.bits());
}
}
/// Enable Non-secure Group 1 interrupts
- pub fn enable_non_secure_group1(&self) {
+ pub fn enable_non_secure_group1(&mut self) {
unsafe {
- self.gicd
- .ctlr
- .modify(|v| v | DistributorControlRegister::EnableGrp1NS.bits());
+ let value = addr_of!(self.gicd.ctlr).read_volatile();
+ addr_of_mut!(self.gicd.ctlr)
+ .write_volatile(value | DistributorControlRegister::EnableGrp1NS.bits());
}
}
/// Select a range of interrupts for group 0
- pub fn select_group0_range(&self, range: Range<usize>) -> Result<(), GicDistributorError> {
+ pub fn select_group0_range(&mut self, range: Range<usize>) -> Result<(), GicDistributorError> {
self.modify_group_range(range, |v, mask| v & !mask)
}
/// Select a range of interrupts for group 1
- pub fn select_group1_range(&self, range: Range<usize>) -> Result<(), GicDistributorError> {
+ pub fn select_group1_range(&mut self, range: Range<usize>) -> Result<(), GicDistributorError> {
self.modify_group_range(range, |v, mask| v | mask)
}
- fn modify_group_range<F>(&self, range: Range<usize>, f: F) -> Result<(), GicDistributorError>
+ fn modify_group_range<F>(
+ &mut self,
+ range: Range<usize>,
+ f: F,
+ ) -> Result<(), GicDistributorError>
where
F: Fn(u32, u32) -> u32,
{
@@ -190,28 +196,25 @@
let (start_reg, start_bit) = Self::index_to_reg_and_bit(range.start);
let (end_reg, end_bit) = Self::index_to_reg_and_bit(range.end);
+ let mut modify_igroupr = |index, mask| unsafe {
+ let ptr: *mut u32 = addr_of_mut!(self.gicd.igroupr[index]);
+ ptr.write_volatile(f(ptr.read_volatile(), mask));
+ };
+
if start_reg == end_reg {
let mask = Self::create_mask(start_bit..end_bit);
- unsafe {
- self.gicd.igroupr[start_reg].modify(|v| f(v, mask));
- }
+ modify_igroupr(start_reg, mask);
} else {
let start_mask = Self::create_mask(start_bit..32);
- unsafe {
- self.gicd.igroupr[start_reg].modify(|v| f(v, start_mask));
- }
+ modify_igroupr(start_reg, start_mask);
for reg_index in (start_reg + 1)..end_reg {
- unsafe {
- self.gicd.igroupr[reg_index].modify(|v| f(v, 0xffff_ffff));
- }
+ modify_igroupr(reg_index, 0xffff_ffff);
}
if end_reg < Self::MAX_IT {
let end_mask = Self::create_mask(0..end_bit);
- unsafe {
- self.gicd.igroupr[end_reg].modify(|v| f(v, end_mask));
- }
+ modify_igroupr(end_reg, end_mask);
}
}
@@ -265,7 +268,7 @@
}
}
-unsafe impl<R> Sync for GicDistributor<R> where R: Deref<Target = GICDRegisters> {}
+unsafe impl<R> Sync for GicDistributor<R> where R: DerefMut<Target = GICDRegisters> {}
#[test]
fn test_gicd_size() {
@@ -276,23 +279,23 @@
fn test_bitmask() {
assert_eq!(
0x0000_0000,
- GicDistributor::<&GICDRegisters>::create_mask(0..0)
+ GicDistributor::<&mut GICDRegisters>::create_mask(0..0)
);
assert_eq!(
0x0000_0001,
- GicDistributor::<&GICDRegisters>::create_mask(0..1)
+ GicDistributor::<&mut GICDRegisters>::create_mask(0..1)
);
assert_eq!(
0x8000_0000,
- GicDistributor::<&GICDRegisters>::create_mask(31..32)
+ GicDistributor::<&mut GICDRegisters>::create_mask(31..32)
);
assert_eq!(
0x0000_00ff,
- GicDistributor::<&GICDRegisters>::create_mask(0..8)
+ GicDistributor::<&mut GICDRegisters>::create_mask(0..8)
);
assert_eq!(
0xffff_ffff,
- GicDistributor::<&GICDRegisters>::create_mask(0..32)
+ GicDistributor::<&mut GICDRegisters>::create_mask(0..32)
);
}
@@ -302,57 +305,57 @@
use alloc::vec::Vec;
let area: [u32; 0x4000] = [0; 0x4000];
- let registers: GICDRegisters = unsafe { core::mem::transmute(area) };
+ let mut registers: GICDRegisters = unsafe { core::mem::transmute(area) };
- let gic_distributor = GicDistributor::new(®isters);
+ let mut gic_distributor = GicDistributor::new(&mut registers);
gic_distributor.select_group0_range(8..16).unwrap();
- let result: Vec<u32> = registers.igroupr.iter().map(|r| r.read()).collect();
+ let result: Vec<u32> = registers.igroupr.iter().map(|r| *r).collect();
let mut expected = [0xffff_ffffu32; 32];
expected[0] = 0xffff_00ff;
assert_eq!(result.as_slice(), &expected);
- let gic_distributor = GicDistributor::new(®isters);
+ let mut gic_distributor = GicDistributor::new(&mut registers);
gic_distributor.select_group0_range(8..40).unwrap();
- let result: Vec<u32> = registers.igroupr.iter().map(|r| r.read()).collect();
+ let result: Vec<u32> = registers.igroupr.iter().map(|r| *r).collect();
let mut expected = [0xffff_ffffu32; 32];
expected[0] = 0x0000_00ff;
expected[1] = 0xffff_ff00;
assert_eq!(result.as_slice(), &expected);
- let gic_distributor = GicDistributor::new(®isters);
+ let mut gic_distributor = GicDistributor::new(&mut registers);
gic_distributor.select_group0_range(8..72).unwrap();
- let result: Vec<u32> = registers.igroupr.iter().map(|r| r.read()).collect();
+ let result: Vec<u32> = registers.igroupr.iter().map(|r| *r).collect();
let mut expected = [0xffff_ffffu32; 32];
expected[0] = 0x0000_00ff;
expected[1] = 0x0000_0000;
expected[2] = 0xffff_ff00;
assert_eq!(result.as_slice(), &expected);
- let gic_distributor = GicDistributor::new(®isters);
+ let mut gic_distributor = GicDistributor::new(&mut registers);
gic_distributor.select_group0_range(8..64).unwrap();
- let result: Vec<u32> = registers.igroupr.iter().map(|r| r.read()).collect();
+ let result: Vec<u32> = registers.igroupr.iter().map(|r| *r).collect();
let mut expected = [0xffff_ffffu32; 32];
expected[0] = 0x0000_00ff;
expected[1] = 0x0000_0000;
assert_eq!(result.as_slice(), &expected);
- let gic_distributor = GicDistributor::new(®isters);
+ let mut gic_distributor = GicDistributor::new(&mut registers);
gic_distributor.select_group0_range(1..1023).unwrap();
- let result: Vec<u32> = registers.igroupr.iter().map(|r| r.read()).collect();
+ let result: Vec<u32> = registers.igroupr.iter().map(|r| *r).collect();
let mut expected = [0x0000_0000u32; 32];
expected[0] = 0x0000_0001;
expected[31] = 0x8000_0000;
assert_eq!(result.as_slice(), &expected);
- let gic_distributor = GicDistributor::new(®isters);
+ let mut gic_distributor = GicDistributor::new(&mut registers);
gic_distributor.select_group0_range(0..1024).unwrap();
- let result: Vec<u32> = registers.igroupr.iter().map(|r| r.read()).collect();
+ let result: Vec<u32> = registers.igroupr.iter().map(|r| *r).collect();
let expected = [0x0000_0000u32; 32];
assert_eq!(result.as_slice(), &expected);
- let gic_distributor = GicDistributor::new(®isters);
+ let mut gic_distributor = GicDistributor::new(&mut registers);
assert!(gic_distributor.select_group0_range(0..2048).is_err());
- let result: Vec<u32> = registers.igroupr.iter().map(|r| r.read()).collect();
+ let result: Vec<u32> = registers.igroupr.iter().map(|r| *r).collect();
let expected = [0xffff_ffffu32; 32];
assert_eq!(result.as_slice(), &expected);
}