diff options
Diffstat (limited to 'src/peripheral')
-rw-r--r-- | src/peripheral/cpuid.rs | 30 | ||||
-rw-r--r-- | src/peripheral/dcb.rs | 16 | ||||
-rw-r--r-- | src/peripheral/dwt.rs | 43 | ||||
-rw-r--r-- | src/peripheral/fpb.rs | 19 | ||||
-rw-r--r-- | src/peripheral/fpu.rs | 17 | ||||
-rw-r--r-- | src/peripheral/itm.rs | 54 | ||||
-rw-r--r-- | src/peripheral/mod.rs | 494 | ||||
-rw-r--r-- | src/peripheral/mpu.rs | 30 | ||||
-rw-r--r-- | src/peripheral/nvic.rs | 119 | ||||
-rw-r--r-- | src/peripheral/scb.rs | 37 | ||||
-rw-r--r-- | src/peripheral/syst.rs | 16 | ||||
-rw-r--r-- | src/peripheral/test.rs | 243 | ||||
-rw-r--r-- | src/peripheral/tpiu.rs | 26 |
13 files changed, 522 insertions, 622 deletions
diff --git a/src/peripheral/cpuid.rs b/src/peripheral/cpuid.rs deleted file mode 100644 index 0dc140f..0000000 --- a/src/peripheral/cpuid.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! CPUID - -use volatile_register::RO; - -/// Registers -#[repr(C)] -pub struct Registers { - /// CPUID base - pub base: RO<u32>, - reserved0: [u32; 15], - /// Processor Feature - pub pfr: [RO<u32>; 2], - /// Debug Feature - pub dfr: RO<u32>, - /// Auxiliary Feature - pub afr: RO<u32>, - /// Memory Model Feature - pub mmfr: [RO<u32>; 4], - /// Instruction Set Attribute - pub isar: [RO<u32>; 5], - reserved1: u32, - /// Cache Level ID - pub clidr: RO<u32>, - /// Cache Type - pub ctr: RO<u32>, - /// Cache Size ID - pub ccsidr: RO<u32>, - /// Cache Size Selection - pub csselr: RO<u32>, -} diff --git a/src/peripheral/dcb.rs b/src/peripheral/dcb.rs deleted file mode 100644 index 93a056b..0000000 --- a/src/peripheral/dcb.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Debug Control Block - -use volatile_register::{RW, WO}; - -/// Registers -#[repr(C)] -pub struct Registers { - /// Debug Halting Control and Status - pub dhcsr: RW<u32>, - /// Debug Core Register Selector - pub dcrsr: WO<u32>, - /// Debug Core Register Data - pub dcrdr: RW<u32>, - /// Debug Exception and Monitor Control - pub demcr: RW<u32>, -} diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs deleted file mode 100644 index ecd214e..0000000 --- a/src/peripheral/dwt.rs +++ /dev/null @@ -1,43 +0,0 @@ -//! Data Watchpoint and Trace unit - -use volatile_register::{RO, RW, WO}; - -/// Registers -#[repr(C)] -pub struct Registers { - /// Control - pub ctrl: RW<u32>, - /// Cycle Count - pub cyccnt: RW<u32>, - /// CPI Count - pub cpicnt: RW<u32>, - /// Exception Overhead Count - pub exccnt: RW<u32>, - /// Sleep Count - pub sleepcnt: RW<u32>, - /// LSU Count - pub lsucnt: RW<u32>, - /// Folded-instruction Count - pub foldcnt: RW<u32>, - /// Program Counter Sample - pub pcsr: RO<u32>, - /// Comparators - pub c: [Comparator; 16], - reserved: [u32; 932], - /// Lock Access - pub lar: WO<u32>, - /// Lock Status - pub lsr: RO<u32>, -} - -/// Comparator -#[repr(C)] -pub struct Comparator { - /// Comparator - pub comp: RW<u32>, - /// Comparator Mask - pub mask: RW<u32>, - /// Comparator Function - pub function: RW<u32>, - reserved: u32, -} diff --git a/src/peripheral/fpb.rs b/src/peripheral/fpb.rs deleted file mode 100644 index 6aa6fbb..0000000 --- a/src/peripheral/fpb.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! Flash Patch and Breakpoint unit - -use volatile_register::{RO, RW, WO}; - -/// Registers -#[repr(C)] -pub struct Registers { - /// Control - pub ctrl: RW<u32>, - /// Remap - pub remap: RW<u32>, - /// Comparator - pub comp: [RW<u32>; 127], - reserved: [u32; 875], - /// Lock Access - pub lar: WO<u32>, - /// Lock Status - pub lsr: RO<u32>, -} diff --git a/src/peripheral/fpu.rs b/src/peripheral/fpu.rs deleted file mode 100644 index 5bbf352..0000000 --- a/src/peripheral/fpu.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Floating Point Unit - -use volatile_register::{RO, RW}; - -/// Registers -#[repr(C)] -pub struct Registers { - reserved: u32, - /// Floating Point Context Control - pub fpccr: RW<u32>, - /// Floating Point Context Address - pub fpcar: RW<u32>, - /// Floating Point Default Status Control - pub fpdscr: RW<u32>, - /// Media and FP Feature - pub mvfr: [RO<u32>; 3], -} diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs deleted file mode 100644 index b56d1b5..0000000 --- a/src/peripheral/itm.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Instrumentation Trace Macrocell - -use volatile_register::{RO, RW, WO}; - -use core::cell::UnsafeCell; -use core::ptr; - -/// Registers -#[repr(C)] -pub struct Registers { - /// Stimulus Port - pub stim: [Stim; 256], - reserved0: [u32; 640], - /// Trace Enable - pub ter: [RW<u32>; 8], - reserved1: [u32; 8], - /// Trace Privilege - pub tpr: RW<u32>, - reserved2: [u32; 15], - /// Trace Control - pub tcr: RW<u32>, - reserved3: [u32; 75], - /// Lock Access - pub lar: WO<u32>, - /// Lock Status - pub lsr: RO<u32>, -} - -/// Stimulus Port -pub struct Stim { - register: UnsafeCell<u32>, -} - -impl Stim { - /// Writes an `u8` payload into the stimulus port - pub fn write_u8(&self, value: u8) { - unsafe { ptr::write_volatile(self.register.get() as *mut u8, value) } - } - - /// Writes an `u16` payload into the stimulus port - pub fn write_u16(&self, value: u16) { - unsafe { ptr::write_volatile(self.register.get() as *mut u16, value) } - } - - /// Writes an `u32` payload into the stimulus port - pub fn write_u32(&self, value: u32) { - unsafe { ptr::write_volatile(self.register.get(), value) } - } - - /// Returns `true` if the stimulus port is ready to accept more data - pub fn is_fifo_ready(&self) -> bool { - unsafe { ptr::read_volatile(self.register.get()) == 1 } - } -} diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index c0cb299..c6e8faa 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -1,144 +1,446 @@ //! Core peripherals //! -//! # Notes -//! -//! - Although the `*_mut()` functions always return a valid/live reference, the API doesn't prevent -//! the user from creating multiple mutable aliases. It's up to the user to ensure that no -//! unsynchonized concurrent access is performed through these references. -//! -//! # Caveats -//! -//! - The API doesn't check if the value passed to `write` is valid (e.g. reserved bits are not -//! modified) or not. It's up to the user to verify that. -//! //! # References //! //! - ARMv7-M Architecture Reference Manual (Issue E.b) - Chapter B3 -pub mod cpuid; -pub mod dcb; -pub mod dwt; -pub mod fpb; -pub mod fpu; -pub mod itm; -pub mod mpu; -pub mod nvic; -pub mod scb; -pub mod syst; -pub mod tpiu; +use core::cell::UnsafeCell; +use core::marker::PhantomData; +use core::ptr; + +use volatile_register::{RO, RW, WO}; +use interrupt::Nr; + +#[cfg(test)] mod test; -const CPUID: usize = 0xE000_ED00; -const DCB: usize = 0xE000_EDF0; -const DWT: usize = 0xE000_1000; -const FPB: usize = 0xE000_2000; -const FPU: usize = 0xE000_EF30; -const ITM: usize = 0xE000_0000; -const MPU: usize = 0xE000_ED90; -const NVIC: usize = 0xE000_E100; -const SCB: usize = 0xE000_ED04; -const SYST: usize = 0xE000_E010; -const TPIU: usize = 0xE004_0000; +/// CPUID +pub const CPUID: Peripheral<Cpuid> = unsafe { Peripheral::new(0xE000_ED00) }; + +/// Debug Control Block +pub const DCB: Peripheral<Dcb> = unsafe { Peripheral::new(0xE000_EDF0) }; + +/// Data Watchpoint and Trace unit +pub const DWT: Peripheral<Dwt> = unsafe { Peripheral::new(0xE000_1000) }; + +/// Flash Patch and Breakpoint unit +pub const FPB: Peripheral<Fpb> = unsafe { Peripheral::new(0xE000_2000) }; + +/// Floating Point Unit +pub const FPU: Peripheral<Fpu> = unsafe { Peripheral::new(0xE000_EF30) }; + +/// Instrumentation Trace Macrocell +pub const ITM: Peripheral<Itm> = unsafe { Peripheral::new(0xE000_0000) }; + +/// Memory Protection Unit +pub const MPU: Peripheral<Mpu> = unsafe { Peripheral::new(0xE000_ED90) }; + +/// Nested Vector Interrupt Controller +pub const NVIC: Peripheral<Nvic> = unsafe { Peripheral::new(0xE000_E100) }; + +/// System Control Block +pub const SCB: Peripheral<Scb> = unsafe { Peripheral::new(0xE000_ED04) }; + +/// SysTick: System Timer +pub const SYST: Peripheral<Syst> = unsafe { Peripheral::new(0xE000_E010) }; + +/// Trace Port Interface Unit; +pub const TPIU: Peripheral<Tpiu> = unsafe { Peripheral::new(0xE004_0000) }; // TODO stand-alone registers: ICTR, ACTLR and STIR -/// `&cpuid::Registers` -pub fn cpuid() -> &'static cpuid::Registers { - unsafe { ::deref(CPUID) } +/// A peripheral +pub struct Peripheral<T> + where T: 'static +{ + address: usize, + _marker: PhantomData<&'static mut T>, } -/// `&dcb::Registers` -pub fn dcb() -> &'static dcb::Registers { - unsafe { ::deref(DCB) } -} +impl<T> Peripheral<T> { + /// Creates a new peripheral + /// + /// `address` is the base address of the register block + pub const unsafe fn new(address: usize) -> Self { + Peripheral { + address: address, + _marker: PhantomData, + } + } -/// `&mut dcb::Registers` -pub unsafe fn dcb_mut() -> &'static mut dcb::Registers { - ::deref_mut(DCB) + /// Returns a pointer to the register block + pub fn get(&self) -> *mut T { + self.address as *mut T + } } -/// `&dwt::Registers` -pub fn dwt() -> &'static dwt::Registers { - unsafe { ::deref(DWT) } +/// CPUID register block +#[repr(C)] +pub struct Cpuid { + /// CPUID base + pub base: RO<u32>, + reserved0: [u32; 15], + /// Processor Feature + pub pfr: [RO<u32>; 2], + /// Debug Feature + pub dfr: RO<u32>, + /// Auxiliary Feature + pub afr: RO<u32>, + /// Memory Model Feature + pub mmfr: [RO<u32>; 4], + /// Instruction Set Attribute + pub isar: [RO<u32>; 5], + reserved1: u32, + /// Cache Level ID + pub clidr: RO<u32>, + /// Cache Type + pub ctr: RO<u32>, + /// Cache Size ID + pub ccsidr: RO<u32>, + /// Cache Size Selection + pub csselr: RO<u32>, } -/// `&mut dwt::Registers` -pub unsafe fn dwt_mut() -> &'static mut dwt::Registers { - ::deref_mut(DWT) +/// DCB register block +#[repr(C)] +pub struct Dcb { + /// Debug Halting Control and Status + pub dhcsr: RW<u32>, + /// Debug Core Register Selector + pub dcrsr: WO<u32>, + /// Debug Core Register Data + pub dcrdr: RW<u32>, + /// Debug Exception and Monitor Control + pub demcr: RW<u32>, } -/// `&fpb::Registers` -pub fn fpb() -> &'static fpb::Registers { - unsafe { ::deref(FPB) } +/// DWT register block +#[repr(C)] +pub struct Dwt { + /// Control + pub ctrl: RW<u32>, + /// Cycle Count + pub cyccnt: RW<u32>, + /// CPI Count + pub cpicnt: RW<u32>, + /// Exception Overhead Count + pub exccnt: RW<u32>, + /// Sleep Count + pub sleepcnt: RW<u32>, + /// LSU Count + pub lsucnt: RW<u32>, + /// Folded-instruction Count + pub foldcnt: RW<u32>, + /// Program Counter Sample + pub pcsr: RO<u32>, + /// Comparators + pub c: [Comparator; 16], + reserved: [u32; 932], + /// Lock Access + pub lar: WO<u32>, + /// Lock Status + pub lsr: RO<u32>, } -/// `&mut fpb::Registers` -pub unsafe fn fpb_mut() -> &'static mut fpb::Registers { - ::deref_mut(FPB) +/// Comparator +#[repr(C)] +pub struct Comparator { + /// Comparator + pub comp: RW<u32>, + /// Comparator Mask + pub mask: RW<u32>, + /// Comparator Function + pub function: RW<u32>, + reserved: u32, } -/// `&fpu::Registers` -pub fn fpu() -> &'static fpu::Registers { - unsafe { ::deref(FPU) } +/// FPB register block +#[repr(C)] +pub struct Fpb { + /// Control + pub ctrl: RW<u32>, + /// Remap + pub remap: RW<u32>, + /// Comparator + pub comp: [RW<u32>; 127], + reserved: [u32; 875], + /// Lock Access + pub lar: WO<u32>, + /// Lock Status + pub lsr: RO<u32>, } -/// `&mut fpu::Registers` -pub unsafe fn fpu_mut() -> &'static mut fpu::Registers { - ::deref_mut(FPU) +/// FPU register block +#[repr(C)] +pub struct Fpu { + reserved: u32, + /// Floating Point Context Control + pub fpccr: RW<u32>, + /// Floating Point Context Address + pub fpcar: RW<u32>, + /// Floating Point Default Status Control + pub fpdscr: RW<u32>, + /// Media and FP Feature + pub mvfr: [RO<u32>; 3], } -/// `&itm::Registers` -pub fn itm() -> &'static itm::Registers { - unsafe { ::deref(ITM) } +/// ITM register block +#[repr(C)] +pub struct Itm { + /// Stimulus Port + pub stim: [Stim; 256], + reserved0: [u32; 640], + /// Trace Enable + pub ter: [RW<u32>; 8], + reserved1: [u32; 8], + /// Trace Privilege + pub tpr: RW<u32>, + reserved2: [u32; 15], + /// Trace Control + pub tcr: RW<u32>, + reserved3: [u32; 75], + /// Lock Access + pub lar: WO<u32>, + /// Lock Status + pub lsr: RO<u32>, } -/// `&mut itm::Registers` -pub unsafe fn itm_mut() -> &'static mut itm::Registers { - ::deref_mut(ITM) +/// Stimulus Port +pub struct Stim { + register: UnsafeCell<u32>, } -/// `&mpu::Registers` -pub fn mpu() -> &'static mpu::Registers { - unsafe { ::deref(MPU) } -} +impl Stim { + /// Writes an `u8` payload into the stimulus port + pub fn write_u8(&self, value: u8) { + unsafe { ptr::write_volatile(self.register.get() as *mut u8, value) } + } -/// `&mut mpu::Registers` -pub unsafe fn mpu_mut() -> &'static mut mpu::Registers { - ::deref_mut(MPU) -} + /// Writes an `u16` payload into the stimulus port + pub fn write_u16(&self, value: u16) { + unsafe { ptr::write_volatile(self.register.get() as *mut u16, value) } + } -/// `&mut nvic::Registers` -pub fn nvic() -> &'static mut nvic::Registers { - unsafe { ::deref_mut(NVIC) } + /// Writes an `u32` payload into the stimulus port + pub fn write_u32(&self, value: u32) { + unsafe { ptr::write_volatile(self.register.get(), value) } + } + + /// Returns `true` if the stimulus port is ready to accept more data + pub fn is_fifo_ready(&self) -> bool { + unsafe { ptr::read_volatile(self.register.get()) == 1 } + } } -/// `&scb::Registers` -pub fn scb() -> &'static scb::Registers { - unsafe { ::deref(SCB) } +/// MPU register block +#[repr(C)] +pub struct Mpu { + /// Type + pub _type: RO<u32>, + /// Control + pub ctrl: RW<u32>, + /// Region Number + pub rnr: RW<u32>, + /// Region Base Address + pub rbar: RW<u32>, + /// Region Attribute and Size + pub rasr: RW<u32>, + /// Alias 1 of RBAR + pub rbar_a1: RW<u32>, + /// Alias 1 of RSAR + pub rsar_a1: RW<u32>, + /// Alias 2 of RBAR + pub rbar_a2: RW<u32>, + /// Alias 2 of RSAR + pub rsar_a2: RW<u32>, + /// Alias 3 of RBAR + pub rbar_a3: RW<u32>, + /// Alias 3 of RSAR + pub rsar_a3: RW<u32>, } -/// `&mut scb::Registers` -pub unsafe fn scb_mut() -> &'static mut scb::Registers { - ::deref_mut(SCB) +/// NVIC register block +#[repr(C)] +pub struct Nvic { + /// Interrupt Set-Enable + pub iser: [RW<u32>; 8], + reserved0: [u32; 24], + /// Interrupt Clear-Enable + pub icer: [RW<u32>; 8], + reserved1: [u32; 24], + /// Interrupt Set-Pending + pub ispr: [RW<u32>; 8], + reserved2: [u32; 24], + /// Interrupt Clear-Pending + pub icpr: [RW<u32>; 8], + reserved3: [u32; 24], + /// Interrupt Active Bit + pub iabr: [RO<u32>; 8], + reserved4: [u32; 56], + /// Interrupt Priority + pub ipr: [RW<u8>; 240], } -/// `&syst::Registers` -pub fn syst() -> &'static syst::Registers { - unsafe { ::deref(SYST) } +impl Nvic { + /// Clears `interrupt`'s pending state + pub fn clear_pending<I>(&self, interrupt: I) + where I: Nr + { + let nr = interrupt.nr(); + + unsafe { self.icpr[usize::from(nr / 32)].write(1 << (nr % 32)) } + } + + /// Disables `interrupt` + pub fn disable<I>(&self, interrupt: I) + where I: Nr + { + let nr = interrupt.nr(); + + unsafe { self.icer[usize::from(nr / 32)].write(1 << (nr % 32)) } + } + + /// Enables `interrupt` + pub fn enable<I>(&self, interrupt: I) + where I: Nr + { + let nr = interrupt.nr(); + + unsafe { self.iser[usize::from(nr / 32)].write(1 << (nr % 32)) } + } + + /// Gets the "priority" of `interrupt` + /// + /// NOTE NVIC encodes priority in the highest bits of a byte so values like + /// `1` and `2` have the same priority. Also for NVIC priorities, a lower + /// value (e.g. `16`) has higher priority than a larger value (e.g. `32`). + pub fn get_priority<I>(&self, interrupt: I) -> u8 + where I: Nr + { + let nr = interrupt.nr(); + + self.ipr[usize::from(nr)].read() + } + + /// Is `interrupt` active or pre-empted and stacked + pub fn is_active<I>(&self, interrupt: I) -> bool + where I: Nr + { + let nr = interrupt.nr(); + let mask = 1 << (nr % 32); + + (self.iabr[usize::from(nr / 32)].read() & mask) == mask + } + + /// Checks if `interrupt` is enabled + pub fn is_enabled<I>(&self, interrupt: I) -> bool + where I: Nr + { + let nr = interrupt.nr(); + let mask = 1 << (nr % 32); + + (self.iser[usize::from(nr / 32)].read() & mask) == mask + } + + /// Checks if `interrupt` is pending + pub fn is_pending<I>(&self, interrupt: I) -> bool + where I: Nr + { + let nr = interrupt.nr(); + let mask = 1 << (nr % 32); + + (self.ispr[usize::from(nr / 32)].read() & mask) == mask + } + + /// Forces `interrupt` into pending state + pub fn set_pending<I>(&self, interrupt: I) + where I: Nr + { + let nr = interrupt.nr(); + + unsafe { self.ispr[usize::from(nr / 32)].write(1 << (nr % 32)) } + } + + /// Sets the "priority" of `interrupt` to `prio` + /// + /// NOTE See `get_priority` method for an explanation of how NVIC priorities + /// work. + pub fn set_priority<I>(&self, interrupt: I, prio: u8) + where I: Nr + { + let nr = interrupt.nr(); + + unsafe { self.ipr[usize::from(nr)].write(prio) } + } } -/// `&mut syst::Registers` -pub unsafe fn syst_mut() -> &'static mut syst::Registers { - ::deref_mut(SYST) +/// SCB register block +#[repr(C)] +pub struct Scb { + /// Interrupt Control and State + pub icsr: RW<u32>, + /// Vector Table Offset + pub vtor: RW<u32>, + /// Application Interrupt and Reset Control + pub aircr: RW<u32>, + /// System Control + pub scr: RW<u32>, + /// Configuration and Control + pub ccr: RW<u32>, + /// System Handler Priority + pub shpr: [RW<u8>; 12], + /// System Handler Control and State + pub shpcrs: RW<u32>, + /// Configurable Fault Status + pub cfsr: RW<u32>, + /// HardFault Status + pub hfsr: RW<u32>, + /// Debug Fault Status + pub dfsr: RW<u32>, + /// MemManage Fault Address + pub mmar: RW<u32>, + /// BusFault Address + pub bfar: RW<u32>, + /// Auxiliary Fault Status + pub afsr: RW<u32>, + reserved: [u32; 18], + /// Coprocessor Access Control + pub cpacr: RW<u32>, } -/// `&tpiu::Registers` -pub fn tpiu() -> &'static tpiu::Registers { - unsafe { ::deref(TPIU) } +/// SysTick register block +#[repr(C)] +pub struct Syst { + /// Control and Status + pub csr: RW<u32>, + /// Reload Value + pub rvr: RW<u32>, + /// Current Value + pub cvr: RW<u32>, + /// Calibration Value + pub calib: RO<u32>, } -/// `&mut tpiu::Registers` -pub unsafe fn tpiu_mut() -> &'static mut tpiu::Registers { - ::deref_mut(TPIU) +/// TPIU register block +#[repr(C)] +pub struct Tpiu { + /// Supported Parallel Port Sizes + pub sspsr: RO<u32>, + /// Current Parallel Port Size + pub cspsr: RW<u32>, + reserved0: [u32; 2], + /// Asynchronous Clock Prescaler + pub acpr: RW<u32>, + reserved1: [u32; 55], + /// Selected Pin Control + pub sppr: RW<u32>, + reserved2: [u32; 943], + /// Lock Access + pub lar: WO<u32>, + /// Lock Status + pub lsr: RO<u32>, + reserved3: [u32; 4], + /// TPIU Type + pub _type: RO<u32>, } diff --git a/src/peripheral/mpu.rs b/src/peripheral/mpu.rs deleted file mode 100644 index e024e62..0000000 --- a/src/peripheral/mpu.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! Memory Protection Unit - -use volatile_register::{RO, RW}; - -/// Registers -#[repr(C)] -pub struct Registers { - /// Type - pub _type: RO<u32>, - /// Control - pub ctrl: RW<u32>, - /// Region Number - pub rnr: RW<u32>, - /// Region Base Address - pub rbar: RW<u32>, - /// Region Attribute and Size - pub rasr: RW<u32>, - /// Alias 1 of RBAR - pub rbar_a1: RW<u32>, - /// Alias 1 of RSAR - pub rsar_a1: RW<u32>, - /// Alias 2 of RBAR - pub rbar_a2: RW<u32>, - /// Alias 2 of RSAR - pub rsar_a2: RW<u32>, - /// Alias 3 of RBAR - pub rbar_a3: RW<u32>, - /// Alias 3 of RSAR - pub rsar_a3: RW<u32>, -} diff --git a/src/peripheral/nvic.rs b/src/peripheral/nvic.rs deleted file mode 100644 index 8c12698..0000000 --- a/src/peripheral/nvic.rs +++ /dev/null @@ -1,119 +0,0 @@ -//! Nested Vector Interrupt Controller - -use interrupt::Nr; -use volatile_register::{RO, RW}; - -/// Registers -#[repr(C)] -pub struct Registers { - /// Interrupt Set-Enable - iser: [RW<u32>; 8], - reserved0: [u32; 24], - /// Interrupt Clear-Enable - icer: [RW<u32>; 8], - reserved1: [u32; 24], - /// Interrupt Set-Pending - ispr: [RW<u32>; 8], - reserved2: [u32; 24], - /// Interrupt Clear-Pending - icpr: [RW<u32>; 8], - reserved3: [u32; 24], - /// Interrupt Active Bit - iabr: [RO<u32>; 8], - reserved4: [u32; 56], - /// Interrupt Priority - ipr: [RW<u8>; 240], -} - -impl Registers { - /// Clears `interrupt` pending state - pub fn clear_pending<I>(&mut self, interrupt: I) - where I: Nr - { - let nr = interrupt.nr(); - - self.icpr[usize::from(nr / 32)].write(1 << (nr % 32)); - } - - /// Disables `interrupt` - pub fn disable<I>(&mut self, interrupt: I) - where I: Nr - { - let nr = interrupt.nr(); - - self.icer[usize::from(nr / 32)].write(1 << (nr % 32)); - } - - /// Enables `interrupt` - pub fn enable<I>(&mut self, interrupt: I) - where I: Nr - { - let nr = interrupt.nr(); - - self.iser[usize::from(nr / 32)].write(1 << (nr % 32)); - } - - /// Gets the "priority" of `interrupt` - /// - /// NOTE NVIC encodes priority in the highest bits of a byte so values like - /// `1` and `2` have the same priority. Also for NVIC priorities, a lower - /// value (e.g. `16`) has higher priority than a larger value (e.g. `32`). - pub fn get_priority<I>(&mut self, interrupt: I) -> u8 - where I: Nr - { - let nr = interrupt.nr(); - - self.ipr[usize::from(nr)].read() - } - - /// Is `interrupt` active or pre-empted and stacked - pub fn is_active<I>(&self, interrupt: I) -> bool - where I: Nr - { - let nr = interrupt.nr(); - let mask = 1 << (nr % 32); - - (self.iabr[usize::from(nr / 32)].read() & mask) == mask - } - - /// Checks if `interrupt` is enabled - pub fn is_enabled<I>(&self, interrupt: I) -> bool - where I: Nr - { - let nr = interrupt.nr(); - let mask = 1 << (nr % 32); - - (self.iser[usize::from(nr / 32)].read() & mask) == mask - } - - /// Checks if `interrupt` is pending - pub fn is_pending<I>(&self, interrupt: I) -> bool - where I: Nr - { - let nr = interrupt.nr(); - let mask = 1 << (nr % 32); - - (self.ispr[usize::from(nr / 32)].read() & mask) == mask - } - - /// Forces `interrupt` into pending state - pub fn set_pending<I>(&mut self, interrupt: I) - where I: Nr - { - let nr = interrupt.nr(); - - self.ispr[usize::from(nr / 32)].write(1 << (nr % 32)); - } - - /// Sets the "priority" of `interrupt` to `prio` - /// - /// NOTE See `get_priority` method for an explanation of how NVIC priorities - /// work. - pub fn set_priority<I>(&mut self, interrupt: I, prio: u8) - where I: Nr - { - let nr = interrupt.nr(); - - self.ipr[usize::from(nr)].write(prio); - } -} diff --git a/src/peripheral/scb.rs b/src/peripheral/scb.rs deleted file mode 100644 index d2b204a..0000000 --- a/src/peripheral/scb.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! System Control Block - -use volatile_register::RW; - -/// Registers -#[repr(C)] -pub struct Registers { - /// Interrupt Control and State - pub icsr: RW<u32>, - /// Vector Table Offset - pub vtor: RW<u32>, - /// Application Interrupt and Reset Control - pub aircr: RW<u32>, - /// System Control - pub scr: RW<u32>, - /// Configuration and Control - pub ccr: RW<u32>, - /// System Handler Priority - pub shpr: [RW<u8>; 12], - /// System Handler Control and State - pub shpcrs: RW<u32>, - /// Configurable Fault Status - pub cfsr: RW<u32>, - /// HardFault Status - pub hfsr: RW<u32>, - /// Debug Fault Status - pub dfsr: RW<u32>, - /// MemManage Fault Address - pub mmar: RW<u32>, - /// BusFault Address - pub bfar: RW<u32>, - /// Auxiliary Fault Status - pub afsr: RW<u32>, - reserved: [u32; 18], - /// Coprocessor Access Control - pub cpacr: RW<u32>, -} diff --git a/src/peripheral/syst.rs b/src/peripheral/syst.rs deleted file mode 100644 index 8ee70a1..0000000 --- a/src/peripheral/syst.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! SysTick: System Timer - -use volatile_register::{RO, RW}; - -/// Registers -#[repr(C)] -pub struct Registers { - /// Control and Status - pub csr: RW<u32>, - /// Reload Value - pub rvr: RW<u32>, - /// Current Value - pub cvr: RW<u32>, - /// Calibration Value - pub calib: RO<u32>, -} diff --git a/src/peripheral/test.rs b/src/peripheral/test.rs index c291b16..1770e03 100644 --- a/src/peripheral/test.rs +++ b/src/peripheral/test.rs @@ -1,162 +1,167 @@ #[test] fn cpuid() { - let cpuid = ::peripheral::cpuid(); - - assert_eq!(::address(&cpuid.base), 0xE000_ED00); - assert_eq!(::address(&cpuid.pfr), 0xE000_ED40); - assert_eq!(::address(&cpuid.dfr), 0xE000_ED48); - assert_eq!(::address(&cpuid.afr), 0xE000_ED4C); - assert_eq!(::address(&cpuid.mmfr), 0xE000_ED50); - assert_eq!(::address(&cpuid.isar), 0xE000_ED60); - assert_eq!(::address(&cpuid.clidr), 0xE000_ED78); - assert_eq!(::address(&cpuid.ctr), 0xE000_ED7C); - assert_eq!(::address(&cpuid.ccsidr), 0xE000_ED80); - assert_eq!(::address(&cpuid.csselr), 0xE000_ED84); + let cpuid = unsafe { &*::peripheral::CPUID.get() }; + + assert_eq!(address(&cpuid.base), 0xE000_ED00); + assert_eq!(address(&cpuid.pfr), 0xE000_ED40); + assert_eq!(address(&cpuid.dfr), 0xE000_ED48); + assert_eq!(address(&cpuid.afr), 0xE000_ED4C); + assert_eq!(address(&cpuid.mmfr), 0xE000_ED50); + assert_eq!(address(&cpuid.isar), 0xE000_ED60); + assert_eq!(address(&cpuid.clidr), 0xE000_ED78); + assert_eq!(address(&cpuid.ctr), 0xE000_ED7C); + assert_eq!(address(&cpuid.ccsidr), 0xE000_ED80); + assert_eq!(address(&cpuid.csselr), 0xE000_ED84); } #[test] fn dcb() { - for dcb in &[::peripheral::dcb(), unsafe { ::peripheral::dcb_mut() }] { - assert_eq!(::address(&dcb.dhcsr), 0xE000_EDF0); - assert_eq!(::address(&dcb.dcrsr), 0xE000_EDF4); - assert_eq!(::address(&dcb.dcrdr), 0xE000_EDF8); - assert_eq!(::address(&dcb.demcr), 0xE000_EDFC); - } + let dcb = unsafe { &*::peripheral::DCB.get() }; + + assert_eq!(address(&dcb.dhcsr), 0xE000_EDF0); + assert_eq!(address(&dcb.dcrsr), 0xE000_EDF4); + assert_eq!(address(&dcb.dcrdr), 0xE000_EDF8); + assert_eq!(address(&dcb.demcr), 0xE000_EDFC); } #[test] fn dwt() { - for dwt in &[::peripheral::dwt(), unsafe { ::peripheral::dwt_mut() }] { - assert_eq!(::address(&dwt.ctrl), 0xE000_1000); - assert_eq!(::address(&dwt.cyccnt), 0xE000_1004); - assert_eq!(::address(&dwt.cpicnt), 0xE000_1008); - assert_eq!(::address(&dwt.exccnt), 0xE000_100C); - assert_eq!(::address(&dwt.sleepcnt), 0xE000_1010); - assert_eq!(::address(&dwt.lsucnt), 0xE000_1014); - assert_eq!(::address(&dwt.foldcnt), 0xE000_1018); - assert_eq!(::address(&dwt.pcsr), 0xE000_101C); - assert_eq!(::address(&dwt.c[0].comp), 0xE000_1020); - assert_eq!(::address(&dwt.c[0].mask), 0xE000_1024); - assert_eq!(::address(&dwt.c[0].function), 0xE000_1028); - assert_eq!(::address(&dwt.c[1].comp), 0xE000_1030); - assert_eq!(::address(&dwt.c[1].mask), 0xE000_1034); - assert_eq!(::address(&dwt.c[1].function), 0xE000_1038); - assert_eq!(::address(&dwt.lar), 0xE000_1FB0); - assert_eq!(::address(&dwt.lsr), 0xE000_1FB4); - } + let dwt = unsafe { &*::peripheral::DWT.get() }; + + assert_eq!(address(&dwt.ctrl), 0xE000_1000); + assert_eq!(address(&dwt.cyccnt), 0xE000_1004); + assert_eq!(address(&dwt.cpicnt), 0xE000_1008); + assert_eq!(address(&dwt.exccnt), 0xE000_100C); + assert_eq!(address(&dwt.sleepcnt), 0xE000_1010); + assert_eq!(address(&dwt.lsucnt), 0xE000_1014); + assert_eq!(address(&dwt.foldcnt), 0xE000_1018); + assert_eq!(address(&dwt.pcsr), 0xE000_101C); + assert_eq!(address(&dwt.c[0].comp), 0xE000_1020); + assert_eq!(address(&dwt.c[0].mask), 0xE000_1024); + assert_eq!(address(&dwt.c[0].function), 0xE000_1028); + assert_eq!(address(&dwt.c[1].comp), 0xE000_1030); + assert_eq!(address(&dwt.c[1].mask), 0xE000_1034); + assert_eq!(address(&dwt.c[1].function), 0xE000_1038); + assert_eq!(address(&dwt.lar), 0xE000_1FB0); + assert_eq!(address(&dwt.lsr), 0xE000_1FB4); } #[test] fn fpb() { - for fpb in &[::peripheral::fpb(), unsafe { ::peripheral::fpb_mut() }] { - assert_eq!(::address(&fpb.ctrl), 0xE000_2000); - assert_eq!(::address(&fpb.remap), 0xE000_2004); - assert_eq!(::address(&fpb.comp), 0xE000_2008); - assert_eq!(::address(&fpb.comp[1]), 0xE000_200C); - assert_eq!(::address(&fpb.lar), 0xE000_2FB0); - assert_eq!(::address(&fpb.lsr), 0xE000_2FB4); - } + let fpb = unsafe { &*::peripheral::FPB.get() }; + + assert_eq!(address(&fpb.ctrl), 0xE000_2000); + assert_eq!(address(&fpb.remap), 0xE000_2004); + assert_eq!(address(&fpb.comp), 0xE000_2008); + assert_eq!(address(&fpb.comp[1]), 0xE000_200C); + assert_eq!(address(&fpb.lar), 0xE000_2FB0); + assert_eq!(address(&fpb.lsr), 0xE000_2FB4); } #[test] fn fpu() { - for fpu in &[::peripheral::fpu(), unsafe { ::peripheral::fpu_mut() }] { - assert_eq!(::address(&fpu.fpccr), 0xE000_EF34); - assert_eq!(::address(&fpu.fpcar), 0xE000_EF38); - assert_eq!(::address(&fpu.fpdscr), 0xE000_EF3C); - assert_eq!(::address(&fpu.mvfr), 0xE000_EF40); - assert_eq!(::address(&fpu.mvfr[1]), 0xE000_EF44); - assert_eq!(::address(&fpu.mvfr[2]), 0xE000_EF48); - } + let fpu = unsafe { &*::peripheral::FPU.get() }; + + assert_eq!(address(&fpu.fpccr), 0xE000_EF34); + assert_eq!(address(&fpu.fpcar), 0xE000_EF38); + assert_eq!(address(&fpu.fpdscr), 0xE000_EF3C); + assert_eq!(address(&fpu.mvfr), 0xE000_EF40); + assert_eq!(address(&fpu.mvfr[1]), 0xE000_EF44); + assert_eq!(address(&fpu.mvfr[2]), 0xE000_EF48); } #[test] fn itm() { - for itm in &[::peripheral::itm(), unsafe { ::peripheral::itm_mut() }] { - assert_eq!(::address(&itm.stim), 0xE000_0000); - assert_eq!(::address(&itm.ter), 0xE000_0E00); - assert_eq!(::address(&itm.tpr), 0xE000_0E40); - assert_eq!(::address(&itm.tcr), 0xE000_0E80); - assert_eq!(::address(&itm.lar), 0xE000_0FB0); - assert_eq!(::address(&itm.lsr), 0xE000_0FB4); - } + let itm = unsafe { &*::peripheral::ITM.get() }; + + assert_eq!(address(&itm.stim), 0xE000_0000); + assert_eq!(address(&itm.ter), 0xE000_0E00); + assert_eq!(address(&itm.tpr), 0xE000_0E40); + assert_eq!(address(&itm.tcr), 0xE000_0E80); + assert_eq!(address(&itm.lar), 0xE000_0FB0); + assert_eq!(address(&itm.lsr), 0xE000_0FB4); } #[test] fn mpu() { - for mpu in &[::peripheral::mpu(), unsafe { ::peripheral::mpu_mut() }] { - assert_eq!(::address(&mpu._type), 0xE000ED90); - assert_eq!(::address(&mpu.ctrl), 0xE000ED94); - assert_eq!(::address(&mpu.rnr), 0xE000ED98); - assert_eq!(::address(&mpu.rbar), 0xE000ED9C); - assert_eq!(::address(&mpu.rasr), 0xE000EDA0); - assert_eq!(::address(&mpu.rbar_a1), 0xE000EDA4); - assert_eq!(::address(&mpu.rsar_a1), 0xE000EDA8); - assert_eq!(::address(&mpu.rbar_a2), 0xE000EDAC); - assert_eq!(::address(&mpu.rsar_a2), 0xE000EDB0); - assert_eq!(::address(&mpu.rbar_a3), 0xE000EDB4); - assert_eq!(::address(&mpu.rsar_a3), 0xE000EDB8); - } + let mpu = unsafe { &*::peripheral::MPU.get() }; + + assert_eq!(address(&mpu._type), 0xE000ED90); + assert_eq!(address(&mpu.ctrl), 0xE000ED94); + assert_eq!(address(&mpu.rnr), 0xE000ED98); + assert_eq!(address(&mpu.rbar), 0xE000ED9C); + assert_eq!(address(&mpu.rasr), 0xE000EDA0); + assert_eq!(address(&mpu.rbar_a1), 0xE000EDA4); + assert_eq!(address(&mpu.rsar_a1), 0xE000EDA8); + assert_eq!(address(&mpu.rbar_a2), 0xE000EDAC); + assert_eq!(address(&mpu.rsar_a2), 0xE000EDB0); + assert_eq!(address(&mpu.rbar_a3), 0xE000EDB4); + assert_eq!(address(&mpu.rsar_a3), 0xE000EDB8); } #[test] fn nvic() { - for nvic in &[::peripheral::nvic(), unsafe { ::peripheral::nvic_mut() }] { - assert_eq!(::address(&nvic.iser), 0xE000E100); - assert_eq!(::address(&nvic.iser[15]), 0xE000E13C); - assert_eq!(::address(&nvic.icer), 0xE000E180); - assert_eq!(::address(&nvic.icer[7]), 0xE000E19C); - assert_eq!(::address(&nvic.icer[15]), 0xE000E1BC); - assert_eq!(::address(&nvic.ispr), 0xE000E200); - assert_eq!(::address(&nvic.ispr[15]), 0xE000E23C); - assert_eq!(::address(&nvic.icpr), 0xE000E280); - assert_eq!(::address(&nvic.icpr[15]), 0xE000E2BC); - assert_eq!(::address(&nvic.iabr), 0xE000E300); - assert_eq!(::address(&nvic.iabr[15]), 0xE000E33C); - assert_eq!(::address(&nvic.ipr), 0xE000E400); - assert_eq!(::address(&nvic.ipr[59]), 0xE000E4EC); - } + let nvic = unsafe { &*::peripheral::NVIC.get() }; + + assert_eq!(address(&nvic.iser), 0xE000E100); + assert_eq!(address(&nvic.iser[7]), 0xE000E11C); + assert_eq!(address(&nvic.icer), 0xE000E180); + assert_eq!(address(&nvic.icer[7]), 0xE000E19C); + assert_eq!(address(&nvic.ispr), 0xE000E200); + assert_eq!(address(&nvic.ispr[7]), 0xE000E21C); + assert_eq!(address(&nvic.icpr), 0xE000E280); + assert_eq!(address(&nvic.icpr[7]), 0xE000E29C); + assert_eq!(address(&nvic.iabr), 0xE000E300); + assert_eq!(address(&nvic.iabr[7]), 0xE000E31C); + assert_eq!(address(&nvic.ipr), 0xE000E400); + assert_eq!(address(&nvic.ipr[239]), 0xE000E4eF); } #[test] fn scb() { - for scb in &[::peripheral::scb(), unsafe { ::peripheral::scb_mut() }] { - assert_eq!(::address(&scb.icsr), 0xE000_ED04); - assert_eq!(::address(&scb.vtor), 0xE000_ED08); - assert_eq!(::address(&scb.aircr), 0xE000_ED0C); - assert_eq!(::address(&scb.scr), 0xE000_ED10); - assert_eq!(::address(&scb.ccr), 0xE000_ED14); - assert_eq!(::address(&scb.shpr), 0xE000_ED18); - assert_eq!(::address(&scb.shpcrs), 0xE000_ED24); - assert_eq!(::address(&scb.cfsr), 0xE000_ED28); - assert_eq!(::address(&scb.hfsr), 0xE000_ED2C); - assert_eq!(::address(&scb.dfsr), 0xE000_ED30); - assert_eq!(::address(&scb.mmar), 0xE000_ED34); - assert_eq!(::address(&scb.bfar), 0xE000_ED38); - assert_eq!(::address(&scb.afsr), 0xE000_ED3C); - assert_eq!(::address(&scb.cpacr), 0xE000_ED88); - } + let scb = unsafe { &*::peripheral::SCB.get() }; + + assert_eq!(address(&scb.icsr), 0xE000_ED04); + assert_eq!(address(&scb.vtor), 0xE000_ED08); + assert_eq!(address(&scb.aircr), 0xE000_ED0C); + assert_eq!(address(&scb.scr), 0xE000_ED10); + assert_eq!(address(&scb.ccr), 0xE000_ED14); + assert_eq!(address(&scb.shpr), 0xE000_ED18); + assert_eq!(address(&scb.shpcrs), 0xE000_ED24); + assert_eq!(address(&scb.cfsr), 0xE000_ED28); + assert_eq!(address(&scb.hfsr), 0xE000_ED2C); + assert_eq!(address(&scb.dfsr), 0xE000_ED30); + assert_eq!(address(&scb.mmar), 0xE000_ED34); + assert_eq!(address(&scb.bfar), 0xE000_ED38); + assert_eq!(address(&scb.afsr), 0xE000_ED3C); + assert_eq!(address(&scb.cpacr), 0xE000_ED88); + } #[test] fn syst() { - for syst in &[::peripheral::syst(), unsafe { ::peripheral::syst_mut() }] { - assert_eq!(::address(&syst.csr), 0xE000_E010); - assert_eq!(::address(&syst.rvr), 0xE000_E014); - assert_eq!(::address(&syst.cvr), 0xE000_E018); - assert_eq!(::address(&syst.calib), 0xE000_E01C); - } + let syst = unsafe { &*::peripheral::SYST.get() }; + + assert_eq!(address(&syst.csr), 0xE000_E010); + assert_eq!(address(&syst.rvr), 0xE000_E014); + assert_eq!(address(&syst.cvr), 0xE000_E018); + assert_eq!(address(&syst.calib), 0xE000_E01C); + } #[test] fn tpiu() { - for tpiu in &[::peripheral::tpiu(), unsafe { ::peripheral::tpiu_mut() }] { - assert_eq!(::address(&tpiu.sspsr), 0xE004_0000); - assert_eq!(::address(&tpiu.cspsr), 0xE004_0004); - assert_eq!(::address(&tpiu.acpr), 0xE004_0010); - assert_eq!(::address(&tpiu.sppr), 0xE004_00F0); - assert_eq!(::address(&tpiu.lar), 0xE004_0FB0); - assert_eq!(::address(&tpiu.lsr), 0xE004_0FB4); - assert_eq!(::address(&tpiu._type), 0xE004_0FC8); - } + let tpiu = unsafe { &*::peripheral::TPIU.get() }; + + assert_eq!(address(&tpiu.sspsr), 0xE004_0000); + assert_eq!(address(&tpiu.cspsr), 0xE004_0004); + assert_eq!(address(&tpiu.acpr), 0xE004_0010); + assert_eq!(address(&tpiu.sppr), 0xE004_00F0); + assert_eq!(address(&tpiu.lar), 0xE004_0FB0); + assert_eq!(address(&tpiu.lsr), 0xE004_0FB4); + assert_eq!(address(&tpiu._type), 0xE004_0FC8); +} + +fn address<T>(r: *const T) -> usize { + r as usize } diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs deleted file mode 100644 index 5047351..0000000 --- a/src/peripheral/tpiu.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Trace Port Interface Unit - -use volatile_register::{RO, RW, WO}; - -/// Registers -#[repr(C)] -pub struct Registers { - /// Supported Parallel Port Sizes - pub sspsr: RO<u32>, - /// Current Parallel Port Size - pub cspsr: RW<u32>, - reserved0: [u32; 2], - /// Asynchronous Clock Prescaler - pub acpr: RW<u32>, - reserved1: [u32; 55], - /// Selected Pin Control - pub sppr: RW<u32>, - reserved2: [u32; 943], - /// Lock Access - pub lar: WO<u32>, - /// Lock Status - pub lsr: RO<u32>, - reserved3: [u32; 4], - /// TPIU Type - pub _type: RO<u32>, -} |