Skip to content

Commit

Permalink
Auto merge of #65 - japaric:singletons, r=japaric
Browse files Browse the repository at this point in the history
turn peripherals into scoped singletons

See this RFC for details: rust-embedded/svd2rust#157
  • Loading branch information
homunkulus committed Dec 9, 2017
2 parents 7e05e18 + 9bab417 commit e5c7f14
Show file tree
Hide file tree
Showing 16 changed files with 1,359 additions and 981 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*.org
*.rs.bk
.#*
Cargo.lock
target
4 changes: 2 additions & 2 deletions src/exception.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ impl Exception {
///
/// Returns `None` if no exception is currently active
pub fn active() -> Option<Exception> {
// NOTE(safe) atomic read
let icsr = unsafe { (*::peripheral::SCB.get()).icsr.read() };
// NOTE(safe) atomic read with no side effects
let icsr = unsafe { (*::peripheral::SCB::ptr()).icsr.read() };

Some(match icsr as u8 {
0 => return None,
Expand Down
2 changes: 1 addition & 1 deletion src/itm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use core::{fmt, mem, ptr, slice};

use aligned::Aligned;

use peripheral::Stim;
use peripheral::itm::Stim;

// NOTE assumes that `bytes` is 32-bit aligned
unsafe fn write_words(stim: &Stim, bytes: &[u32]) {
Expand Down
142 changes: 142 additions & 0 deletions src/peripheral/cbp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//! Cache and branch predictor maintenance operations
use volatile_register::WO;

/// Register block
#[repr(C)]
pub struct RegisterBlock {
/// I-cache invalidate all to PoU
pub iciallu: WO<u32>,
reserved0: u32,
/// I-cache invalidate by MVA to PoU
pub icimvau: WO<u32>,
/// D-cache invalidate by MVA to PoC
pub dcimvac: WO<u32>,
/// D-cache invalidate by set-way
pub dcisw: WO<u32>,
/// D-cache clean by MVA to PoU
pub dccmvau: WO<u32>,
/// D-cache clean by MVA to PoC
pub dccmvac: WO<u32>,
/// D-cache clean by set-way
pub dccsw: WO<u32>,
/// D-cache clean and invalidate by MVA to PoC
pub dccimvac: WO<u32>,
/// D-cache clean and invalidate by set-way
pub dccisw: WO<u32>,
/// Branch predictor invalidate all
pub bpiall: WO<u32>,
}

const CBP_SW_WAY_POS: u32 = 30;
const CBP_SW_WAY_MASK: u32 = 0x3 << CBP_SW_WAY_POS;
const CBP_SW_SET_POS: u32 = 5;
const CBP_SW_SET_MASK: u32 = 0x1FF << CBP_SW_SET_POS;

impl RegisterBlock {
/// I-cache invalidate all to PoU
#[inline(always)]
pub fn iciallu(&self) {
unsafe {
self.iciallu.write(0);
}
}

/// I-cache invalidate by MVA to PoU
#[inline(always)]
pub fn icimvau(&self, mva: u32) {
unsafe {
self.icimvau.write(mva);
}
}

/// D-cache invalidate by MVA to PoC
#[inline(always)]
pub fn dcimvac(&self, mva: u32) {
unsafe {
self.dcimvac.write(mva);
}
}

/// D-cache invalidate by set-way
///
/// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
#[inline(always)]
pub fn dcisw(&self, set: u16, way: u16) {
// The ARMv7-M Architecture Reference Manual, as of Revision E.b, says these set/way
// operations have a register data format which depends on the implementation's
// associativity and number of sets. Specifically the 'way' and 'set' fields have
// offsets 32-log2(ASSOCIATIVITY) and log2(LINELEN) respectively.
//
// However, in Cortex-M7 devices, these offsets are fixed at 30 and 5, as per the Cortex-M7
// Generic User Guide section 4.8.3. Since no other ARMv7-M implementations except the
// Cortex-M7 have a DCACHE or ICACHE at all, it seems safe to do the same thing as the
// CMSIS-Core implementation and use fixed values.
unsafe {
self.dcisw.write(
(((way as u32) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
| (((set as u32) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
);
}
}

/// D-cache clean by MVA to PoU
#[inline(always)]
pub fn dccmvau(&self, mva: u32) {
unsafe {
self.dccmvau.write(mva);
}
}

/// D-cache clean by MVA to PoC
#[inline(always)]
pub fn dccmvac(&self, mva: u32) {
unsafe {
self.dccmvac.write(mva);
}
}

/// D-cache clean by set-way
///
/// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
#[inline(always)]
pub fn dccsw(&self, set: u16, way: u16) {
// See comment for dcisw() about the format here
unsafe {
self.dccsw.write(
(((way as u32) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
| (((set as u32) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
);
}
}

/// D-cache clean and invalidate by MVA to PoC
#[inline(always)]
pub fn dccimvac(&self, mva: u32) {
unsafe {
self.dccimvac.write(mva);
}
}

/// D-cache clean and invalidate by set-way
///
/// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
#[inline(always)]
pub fn dccisw(&self, set: u16, way: u16) {
// See comment for dcisw() about the format here
unsafe {
self.dccisw.write(
(((way as u32) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
| (((set as u32) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
);
}
}

/// Branch predictor invalidate all
#[inline(always)]
pub fn bpiall(&self) {
unsafe {
self.bpiall.write(0);
}
}
}
84 changes: 84 additions & 0 deletions src/peripheral/cpuid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//! CPUID
use volatile_register::RO;
#[cfg(any(armv7m, test))]
use volatile_register::RW;

/// Register block
#[repr(C)]
pub struct RegisterBlock {
/// 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
#[cfg(any(armv7m, test))]
pub clidr: RO<u32>,
/// Cache Type
#[cfg(any(armv7m, test))]
pub ctr: RO<u32>,
/// Cache Size ID
#[cfg(any(armv7m, test))]
pub ccsidr: RO<u32>,
/// Cache Size Selection
#[cfg(any(armv7m, test))]
pub csselr: RW<u32>,
}

/// Type of cache to select on CSSELR writes.
#[cfg(armv7m)]
pub enum CsselrCacheType {
/// Select DCache or unified cache
DataOrUnified = 0,
/// Select ICache
Instruction = 1,
}

#[cfg(armv7m)]
impl RegisterBlock {
/// Selects the current CCSIDR
///
/// * `level`: the required cache level minus 1, e.g. 0 for L1, 1 for L2
/// * `ind`: select instruction cache or data/unified cache
///
/// `level` is masked to be between 0 and 7.
pub fn select_cache(&self, level: u8, ind: CsselrCacheType) {
const CSSELR_IND_POS: u32 = 0;
const CSSELR_IND_MASK: u32 = 1 << CSSELR_IND_POS;
const CSSELR_LEVEL_POS: u32 = 1;
const CSSELR_LEVEL_MASK: u32 = 0x7 << CSSELR_LEVEL_POS;

unsafe {
self.csselr.write(
(((level as u32) << CSSELR_LEVEL_POS) & CSSELR_LEVEL_MASK)
| (((ind as u32) << CSSELR_IND_POS) & CSSELR_IND_MASK),
)
}
}

/// Returns the number of sets and ways in the selected cache
pub fn cache_num_sets_ways(&self, level: u8, ind: CsselrCacheType) -> (u16, u16) {
const CCSIDR_NUMSETS_POS: u32 = 13;
const CCSIDR_NUMSETS_MASK: u32 = 0x7FFF << CCSIDR_NUMSETS_POS;
const CCSIDR_ASSOCIATIVITY_POS: u32 = 3;
const CCSIDR_ASSOCIATIVITY_MASK: u32 = 0x3FF << CCSIDR_ASSOCIATIVITY_POS;

self.select_cache(level, ind);
::asm::dsb();
let ccsidr = self.ccsidr.read();
(
(1 + ((ccsidr & CCSIDR_NUMSETS_MASK) >> CCSIDR_NUMSETS_POS)) as u16,
(1 + ((ccsidr & CCSIDR_ASSOCIATIVITY_MASK) >> CCSIDR_ASSOCIATIVITY_POS)) as u16,
)
}
}
16 changes: 16 additions & 0 deletions src/peripheral/dcb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//! Debug Control Block
use volatile_register::{RW, WO};

/// Register block
#[repr(C)]
pub struct RegisterBlock {
/// 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>,
}
50 changes: 50 additions & 0 deletions src/peripheral/dwt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//! Data Watchpoint and Trace unit
use volatile_register::{RO, RW, WO};

/// Register block
#[repr(C)]
pub struct RegisterBlock {
/// 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>,
}

impl RegisterBlock {
/// Enables the cycle counter
pub fn enable_cycle_counter(&self) {
unsafe { self.ctrl.modify(|r| r | 1) }
}
}

/// 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,
}
19 changes: 19 additions & 0 deletions src/peripheral/fpb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//! Flash Patch and Breakpoint unit
use volatile_register::{RO, RW, WO};

/// Register block
#[repr(C)]
pub struct RegisterBlock {
/// 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>,
}
22 changes: 22 additions & 0 deletions src/peripheral/fpu.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//! Floating Point Unit
#[cfg(any(has_fpu, test))]
use volatile_register::{RO, RW};

/// Register block
#[repr(C)]
pub struct RegisterBlock {
reserved: u32,
/// Floating Point Context Control
#[cfg(any(has_fpu, test))]
pub fpccr: RW<u32>,
/// Floating Point Context Address
#[cfg(any(has_fpu, test))]
pub fpcar: RW<u32>,
/// Floating Point Default Status Control
#[cfg(any(has_fpu, test))]
pub fpdscr: RW<u32>,
/// Media and FP Feature
#[cfg(any(has_fpu, test))]
pub mvfr: [RO<u32>; 3],
}
Loading

0 comments on commit e5c7f14

Please sign in to comment.