Skip to content

Commit ce5bee6

Browse files
committed
Auto merge of #65 - japaric:singletons, r=japaric
turn peripherals into scoped singletons See this RFC for details: rust-embedded/svd2rust#157
2 parents 7e05e18 + 0b45ea4 commit ce5bee6

20 files changed

+1374
-995
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
*.org
22
*.rs.bk
3+
.#*
34
Cargo.lock
45
target

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ matrix:
1616
before_install: set -e
1717

1818
install:
19-
- sh ci/install.sh
19+
- bash ci/install.sh
2020

2121
script:
22-
- sh ci/script.sh
22+
- bash ci/script.sh
2323

2424
after_script: set +e
2525

ci/install.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
set -ex
1+
set -euxo pipefail
22

33
main() {
44
case $TARGET in

ci/script.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
set -ex
1+
set -euxo pipefail
22

33
main() {
44
case $TARGET in

src/exception.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ impl Exception {
3131
///
3232
/// Returns `None` if no exception is currently active
3333
pub fn active() -> Option<Exception> {
34-
// NOTE(safe) atomic read
35-
let icsr = unsafe { (*::peripheral::SCB.get()).icsr.read() };
34+
// NOTE(safe) atomic read with no side effects
35+
let icsr = unsafe { (*::peripheral::SCB::ptr()).icsr.read() };
3636

3737
Some(match icsr as u8 {
3838
0 => return None,

src/itm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use core::{fmt, mem, ptr, slice};
44

55
use aligned::Aligned;
66

7-
use peripheral::Stim;
7+
use peripheral::itm::Stim;
88

99
// NOTE assumes that `bytes` is 32-bit aligned
1010
unsafe fn write_words(stim: &Stim, bytes: &[u32]) {

src/peripheral/cbp.rs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
//! Cache and branch predictor maintenance operations
2+
3+
use volatile_register::WO;
4+
5+
/// Register block
6+
#[repr(C)]
7+
pub struct RegisterBlock {
8+
/// I-cache invalidate all to PoU
9+
pub iciallu: WO<u32>,
10+
reserved0: u32,
11+
/// I-cache invalidate by MVA to PoU
12+
pub icimvau: WO<u32>,
13+
/// D-cache invalidate by MVA to PoC
14+
pub dcimvac: WO<u32>,
15+
/// D-cache invalidate by set-way
16+
pub dcisw: WO<u32>,
17+
/// D-cache clean by MVA to PoU
18+
pub dccmvau: WO<u32>,
19+
/// D-cache clean by MVA to PoC
20+
pub dccmvac: WO<u32>,
21+
/// D-cache clean by set-way
22+
pub dccsw: WO<u32>,
23+
/// D-cache clean and invalidate by MVA to PoC
24+
pub dccimvac: WO<u32>,
25+
/// D-cache clean and invalidate by set-way
26+
pub dccisw: WO<u32>,
27+
/// Branch predictor invalidate all
28+
pub bpiall: WO<u32>,
29+
}
30+
31+
const CBP_SW_WAY_POS: u32 = 30;
32+
const CBP_SW_WAY_MASK: u32 = 0x3 << CBP_SW_WAY_POS;
33+
const CBP_SW_SET_POS: u32 = 5;
34+
const CBP_SW_SET_MASK: u32 = 0x1FF << CBP_SW_SET_POS;
35+
36+
impl RegisterBlock {
37+
/// I-cache invalidate all to PoU
38+
#[inline(always)]
39+
pub fn iciallu(&self) {
40+
unsafe {
41+
self.iciallu.write(0);
42+
}
43+
}
44+
45+
/// I-cache invalidate by MVA to PoU
46+
#[inline(always)]
47+
pub fn icimvau(&self, mva: u32) {
48+
unsafe {
49+
self.icimvau.write(mva);
50+
}
51+
}
52+
53+
/// D-cache invalidate by MVA to PoC
54+
#[inline(always)]
55+
pub fn dcimvac(&self, mva: u32) {
56+
unsafe {
57+
self.dcimvac.write(mva);
58+
}
59+
}
60+
61+
/// D-cache invalidate by set-way
62+
///
63+
/// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
64+
#[inline(always)]
65+
pub fn dcisw(&self, set: u16, way: u16) {
66+
// The ARMv7-M Architecture Reference Manual, as of Revision E.b, says these set/way
67+
// operations have a register data format which depends on the implementation's
68+
// associativity and number of sets. Specifically the 'way' and 'set' fields have
69+
// offsets 32-log2(ASSOCIATIVITY) and log2(LINELEN) respectively.
70+
//
71+
// However, in Cortex-M7 devices, these offsets are fixed at 30 and 5, as per the Cortex-M7
72+
// Generic User Guide section 4.8.3. Since no other ARMv7-M implementations except the
73+
// Cortex-M7 have a DCACHE or ICACHE at all, it seems safe to do the same thing as the
74+
// CMSIS-Core implementation and use fixed values.
75+
unsafe {
76+
self.dcisw.write(
77+
(((way as u32) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
78+
| (((set as u32) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
79+
);
80+
}
81+
}
82+
83+
/// D-cache clean by MVA to PoU
84+
#[inline(always)]
85+
pub fn dccmvau(&self, mva: u32) {
86+
unsafe {
87+
self.dccmvau.write(mva);
88+
}
89+
}
90+
91+
/// D-cache clean by MVA to PoC
92+
#[inline(always)]
93+
pub fn dccmvac(&self, mva: u32) {
94+
unsafe {
95+
self.dccmvac.write(mva);
96+
}
97+
}
98+
99+
/// D-cache clean by set-way
100+
///
101+
/// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
102+
#[inline(always)]
103+
pub fn dccsw(&self, set: u16, way: u16) {
104+
// See comment for dcisw() about the format here
105+
unsafe {
106+
self.dccsw.write(
107+
(((way as u32) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
108+
| (((set as u32) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
109+
);
110+
}
111+
}
112+
113+
/// D-cache clean and invalidate by MVA to PoC
114+
#[inline(always)]
115+
pub fn dccimvac(&self, mva: u32) {
116+
unsafe {
117+
self.dccimvac.write(mva);
118+
}
119+
}
120+
121+
/// D-cache clean and invalidate by set-way
122+
///
123+
/// `set` is masked to be between 0 and 3, and `way` between 0 and 511.
124+
#[inline(always)]
125+
pub fn dccisw(&self, set: u16, way: u16) {
126+
// See comment for dcisw() about the format here
127+
unsafe {
128+
self.dccisw.write(
129+
(((way as u32) & (CBP_SW_WAY_MASK >> CBP_SW_WAY_POS)) << CBP_SW_WAY_POS)
130+
| (((set as u32) & (CBP_SW_SET_MASK >> CBP_SW_SET_POS)) << CBP_SW_SET_POS),
131+
);
132+
}
133+
}
134+
135+
/// Branch predictor invalidate all
136+
#[inline(always)]
137+
pub fn bpiall(&self) {
138+
unsafe {
139+
self.bpiall.write(0);
140+
}
141+
}
142+
}

src/peripheral/cpuid.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//! CPUID
2+
3+
use volatile_register::RO;
4+
#[cfg(any(armv7m, test))]
5+
use volatile_register::RW;
6+
7+
/// Register block
8+
#[repr(C)]
9+
pub struct RegisterBlock {
10+
/// CPUID base
11+
pub base: RO<u32>,
12+
reserved0: [u32; 15],
13+
/// Processor Feature
14+
pub pfr: [RO<u32>; 2],
15+
/// Debug Feature
16+
pub dfr: RO<u32>,
17+
/// Auxiliary Feature
18+
pub afr: RO<u32>,
19+
/// Memory Model Feature
20+
pub mmfr: [RO<u32>; 4],
21+
/// Instruction Set Attribute
22+
pub isar: [RO<u32>; 5],
23+
reserved1: u32,
24+
/// Cache Level ID
25+
#[cfg(any(armv7m, test))]
26+
pub clidr: RO<u32>,
27+
/// Cache Type
28+
#[cfg(any(armv7m, test))]
29+
pub ctr: RO<u32>,
30+
/// Cache Size ID
31+
#[cfg(any(armv7m, test))]
32+
pub ccsidr: RO<u32>,
33+
/// Cache Size Selection
34+
#[cfg(any(armv7m, test))]
35+
pub csselr: RW<u32>,
36+
}
37+
38+
/// Type of cache to select on CSSELR writes.
39+
#[cfg(armv7m)]
40+
pub enum CsselrCacheType {
41+
/// Select DCache or unified cache
42+
DataOrUnified = 0,
43+
/// Select ICache
44+
Instruction = 1,
45+
}
46+
47+
#[cfg(armv7m)]
48+
impl RegisterBlock {
49+
/// Selects the current CCSIDR
50+
///
51+
/// * `level`: the required cache level minus 1, e.g. 0 for L1, 1 for L2
52+
/// * `ind`: select instruction cache or data/unified cache
53+
///
54+
/// `level` is masked to be between 0 and 7.
55+
pub fn select_cache(&self, level: u8, ind: CsselrCacheType) {
56+
const CSSELR_IND_POS: u32 = 0;
57+
const CSSELR_IND_MASK: u32 = 1 << CSSELR_IND_POS;
58+
const CSSELR_LEVEL_POS: u32 = 1;
59+
const CSSELR_LEVEL_MASK: u32 = 0x7 << CSSELR_LEVEL_POS;
60+
61+
unsafe {
62+
self.csselr.write(
63+
(((level as u32) << CSSELR_LEVEL_POS) & CSSELR_LEVEL_MASK)
64+
| (((ind as u32) << CSSELR_IND_POS) & CSSELR_IND_MASK),
65+
)
66+
}
67+
}
68+
69+
/// Returns the number of sets and ways in the selected cache
70+
pub fn cache_num_sets_ways(&self, level: u8, ind: CsselrCacheType) -> (u16, u16) {
71+
const CCSIDR_NUMSETS_POS: u32 = 13;
72+
const CCSIDR_NUMSETS_MASK: u32 = 0x7FFF << CCSIDR_NUMSETS_POS;
73+
const CCSIDR_ASSOCIATIVITY_POS: u32 = 3;
74+
const CCSIDR_ASSOCIATIVITY_MASK: u32 = 0x3FF << CCSIDR_ASSOCIATIVITY_POS;
75+
76+
self.select_cache(level, ind);
77+
::asm::dsb();
78+
let ccsidr = self.ccsidr.read();
79+
(
80+
(1 + ((ccsidr & CCSIDR_NUMSETS_MASK) >> CCSIDR_NUMSETS_POS)) as u16,
81+
(1 + ((ccsidr & CCSIDR_ASSOCIATIVITY_MASK) >> CCSIDR_ASSOCIATIVITY_POS)) as u16,
82+
)
83+
}
84+
}

src/peripheral/dcb.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//! Debug Control Block
2+
3+
use volatile_register::{RW, WO};
4+
5+
/// Register block
6+
#[repr(C)]
7+
pub struct RegisterBlock {
8+
/// Debug Halting Control and Status
9+
pub dhcsr: RW<u32>,
10+
/// Debug Core Register Selector
11+
pub dcrsr: WO<u32>,
12+
/// Debug Core Register Data
13+
pub dcrdr: RW<u32>,
14+
/// Debug Exception and Monitor Control
15+
pub demcr: RW<u32>,
16+
}

src/peripheral/dwt.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//! Data Watchpoint and Trace unit
2+
3+
use volatile_register::{RO, RW, WO};
4+
5+
/// Register block
6+
#[repr(C)]
7+
pub struct RegisterBlock {
8+
/// Control
9+
pub ctrl: RW<u32>,
10+
/// Cycle Count
11+
pub cyccnt: RW<u32>,
12+
/// CPI Count
13+
pub cpicnt: RW<u32>,
14+
/// Exception Overhead Count
15+
pub exccnt: RW<u32>,
16+
/// Sleep Count
17+
pub sleepcnt: RW<u32>,
18+
/// LSU Count
19+
pub lsucnt: RW<u32>,
20+
/// Folded-instruction Count
21+
pub foldcnt: RW<u32>,
22+
/// Program Counter Sample
23+
pub pcsr: RO<u32>,
24+
/// Comparators
25+
pub c: [Comparator; 16],
26+
reserved: [u32; 932],
27+
/// Lock Access
28+
pub lar: WO<u32>,
29+
/// Lock Status
30+
pub lsr: RO<u32>,
31+
}
32+
33+
impl RegisterBlock {
34+
/// Enables the cycle counter
35+
pub fn enable_cycle_counter(&self) {
36+
unsafe { self.ctrl.modify(|r| r | 1) }
37+
}
38+
}
39+
40+
/// Comparator
41+
#[repr(C)]
42+
pub struct Comparator {
43+
/// Comparator
44+
pub comp: RW<u32>,
45+
/// Comparator Mask
46+
pub mask: RW<u32>,
47+
/// Comparator Function
48+
pub function: RW<u32>,
49+
reserved: u32,
50+
}

src/peripheral/fpb.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//! Flash Patch and Breakpoint unit
2+
3+
use volatile_register::{RO, RW, WO};
4+
5+
/// Register block
6+
#[repr(C)]
7+
pub struct RegisterBlock {
8+
/// Control
9+
pub ctrl: RW<u32>,
10+
/// Remap
11+
pub remap: RW<u32>,
12+
/// Comparator
13+
pub comp: [RW<u32>; 127],
14+
reserved: [u32; 875],
15+
/// Lock Access
16+
pub lar: WO<u32>,
17+
/// Lock Status
18+
pub lsr: RO<u32>,
19+
}

src/peripheral/fpu.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//! Floating Point Unit
2+
3+
#[cfg(any(has_fpu, test))]
4+
use volatile_register::{RO, RW};
5+
6+
/// Register block
7+
#[repr(C)]
8+
pub struct RegisterBlock {
9+
reserved: u32,
10+
/// Floating Point Context Control
11+
#[cfg(any(has_fpu, test))]
12+
pub fpccr: RW<u32>,
13+
/// Floating Point Context Address
14+
#[cfg(any(has_fpu, test))]
15+
pub fpcar: RW<u32>,
16+
/// Floating Point Default Status Control
17+
#[cfg(any(has_fpu, test))]
18+
pub fpdscr: RW<u32>,
19+
/// Media and FP Feature
20+
#[cfg(any(has_fpu, test))]
21+
pub mvfr: [RO<u32>; 3],
22+
}

0 commit comments

Comments
 (0)