Skip to content

Commit 358be5d

Browse files
bors[bot]cbifflePTaylor-ushug-devjonas-schievink
authored
Merge #249
249: More v0.6.3 backports r=jonas-schievink a=adamgreig I think this includes the remainder of the non-breaking changes since v0.6.2, with a couple of exceptions: * #240 seemed low-impact but had loads of separate commits to cherry-pick * #220 is I think non-breaking but was quite a substantial change, perhaps I could still include it ~~I did include #226 which adds a new field to `Peripherals`, but as I understand it that should be a non-breaking change since it's non-exhaustive.~~ I've updated the CHANGELOG with all the changes from this PR and the previous #248. Co-authored-by: Cliff L. Biffle <[email protected]> Co-authored-by: Peter Taylor <[email protected]> Co-authored-by: Hugues de Valon <[email protected]> Co-authored-by: Jonas Schievink <[email protected]> Co-authored-by: Adam Greig <[email protected]>
2 parents 00d16c3 + 6717d4b commit 358be5d

13 files changed

+122
-62
lines changed

CHANGELOG.md

+19-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
## [v0.6.3] - 2020-07-20
11+
12+
### Added
13+
14+
- Initial Cortex-M Security Extension support for armv8m
15+
- `UDF` intrinsic
16+
- Methods to enable/disable exceptions in SCB
17+
18+
### Fixed
19+
20+
- Fix bug in `asm::delay` not updating status clobber flags
21+
- Swapped to `llvm_asm!` to support inline assembly on new nightlies
22+
- Our precompiled assembly routines have additional debug information
23+
- ITM `is_fifo_ready` improved to support armv8
24+
- Cache enabling moved to pre-built assembly routines to prevent possible
25+
undefined behaviour
26+
1027
## [v0.6.2] - 2020-01-12
1128

1229
### Added
@@ -572,7 +589,8 @@ fn main() {
572589
- Functions to get the vector table
573590
- Wrappers over miscellaneous instructions like `bkpt`
574591

575-
[Unreleased]: https://github.com/rust-embedded/cortex-m/compare/v0.6.2...HEAD
592+
[Unreleased]: https://github.com/rust-embedded/cortex-m/compare/v0.6.3...HEAD
593+
[v0.6.3]: https://github.com/rust-embedded/cortex-m/compare/v0.6.2...v0.6.3
576594
[v0.6.2]: https://github.com/rust-embedded/cortex-m/compare/v0.6.1...v0.6.2
577595
[v0.6.1]: https://github.com/rust-embedded/cortex-m/compare/v0.6.0...v0.6.1
578596
[v0.6.0]: https://github.com/rust-embedded/cortex-m/compare/v0.5.8...v0.6.0

asm-v7.s

+37
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.syntax unified
12
.cfi_sections .debug_frame
23

34
.section .text.__basepri_max
@@ -39,3 +40,39 @@ __faultmask:
3940
bx lr
4041
.cfi_endproc
4142
.size __faultmask, . - __faultmask
43+
44+
.section .text.__enable_icache
45+
.global __enable_icache
46+
.thumb_func
47+
.cfi_startproc
48+
__enable_icache:
49+
ldr r0, =0xE000ED14 @ CCR
50+
mrs r2, PRIMASK @ save critical nesting info
51+
cpsid i @ mask interrupts
52+
ldr r1, [r0] @ read CCR
53+
orr.w r1, r1, #(1 << 17) @ Set bit 17, IC
54+
str r1, [r0] @ write it back
55+
dsb @ ensure store completes
56+
isb @ synchronize pipeline
57+
msr PRIMASK, r2 @ unnest critical section
58+
bx lr
59+
.cfi_endproc
60+
.size __enable_icache, . - __enable_icache
61+
62+
.section .text.__enable_dcache
63+
.global __enable_dcache
64+
.thumb_func
65+
.cfi_startproc
66+
__enable_dcache:
67+
ldr r0, =0xE000ED14 @ CCR
68+
mrs r2, PRIMASK @ save critical nesting info
69+
cpsid i @ mask interrupts
70+
ldr r1, [r0] @ read CCR
71+
orr.w r1, r1, #(1 << 16) @ Set bit 16, DC
72+
str r1, [r0] @ write it back
73+
dsb @ ensure store completes
74+
isb @ synchronize pipeline
75+
msr PRIMASK, r2 @ unnest critical section
76+
bx lr
77+
.cfi_endproc
78+
.size __enable_dcache, . - __enable_dcache

bin/thumbv6m-none-eabi.a

16 Bytes
Binary file not shown.

bin/thumbv7em-none-eabi.a

688 Bytes
Binary file not shown.

bin/thumbv7em-none-eabihf.a

688 Bytes
Binary file not shown.

bin/thumbv7m-none-eabi.a

680 Bytes
Binary file not shown.

bin/thumbv8m.base-none-eabi.a

32 Bytes
Binary file not shown.

bin/thumbv8m.main-none-eabi.a

712 Bytes
Binary file not shown.

bin/thumbv8m.main-none-eabihf.a

712 Bytes
Binary file not shown.

build.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ fn main() {
66
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
77
let name = env::var("CARGO_PKG_NAME").unwrap();
88

9-
if target.starts_with("thumb") && env::var_os("CARGO_FEATURE_INLINE_ASM").is_none() {
9+
if target.starts_with("thumb") {
1010
fs::copy(
1111
format!("bin/{}.a", target),
1212
out_dir.join(format!("lib{}.a", name)),

src/peripheral/itm.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,19 @@ impl Stim {
5353
}
5454

5555
/// Returns `true` if the stimulus port is ready to accept more data
56+
#[cfg(not(armv8m))]
5657
#[inline]
5758
pub fn is_fifo_ready(&self) -> bool {
58-
unsafe { ptr::read_volatile(self.register.get()) == 1 }
59+
unsafe { ptr::read_volatile(self.register.get()) & 0b1 == 1 }
60+
}
61+
62+
/// Returns `true` if the stimulus port is ready to accept more data
63+
#[cfg(armv8m)]
64+
#[inline]
65+
pub fn is_fifo_ready(&self) -> bool {
66+
// ARMv8-M adds a disabled bit; we indicate that we are ready to
67+
// proceed with a stimulus write if the port is either ready (bit 0) or
68+
// disabled (bit 1).
69+
unsafe { ptr::read_volatile(self.register.get()) & 0b11 != 0 }
5970
}
6071
}

src/peripheral/mod.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,17 @@ pub struct Peripherals {
143143
// NOTE `no_mangle` is used here to prevent linking different minor versions of this crate as that
144144
// would let you `take` the core peripherals more than once (one per minor version)
145145
#[no_mangle]
146-
static mut CORE_PERIPHERALS: bool = false;
146+
static CORE_PERIPHERALS: () = ();
147+
148+
/// Set to `true` when `take` or `steal` was called to make `Peripherals` a singleton.
149+
static mut TAKEN: bool = false;
147150

148151
impl Peripherals {
149152
/// Returns all the core peripherals *once*
150153
#[inline]
151154
pub fn take() -> Option<Self> {
152155
interrupt::free(|_| {
153-
if unsafe { CORE_PERIPHERALS } {
156+
if unsafe { TAKEN } {
154157
None
155158
} else {
156159
Some(unsafe { Peripherals::steal() })
@@ -161,7 +164,7 @@ impl Peripherals {
161164
/// Unchecked version of `Peripherals::take`
162165
#[inline]
163166
pub unsafe fn steal() -> Self {
164-
CORE_PERIPHERALS = true;
167+
TAKEN = true;
165168

166169
Peripherals {
167170
CBP: CBP {

src/peripheral/scb.rs

+47-56
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
//! System Control Block
22
33
use core::ptr;
4-
#[cfg(not(any(armv6m, armv8m_base)))]
5-
use crate::interrupt;
64

75
use volatile_register::RW;
86

@@ -330,11 +328,16 @@ impl SCB {
330328
// Invalidate I-Cache
331329
cbp.iciallu();
332330

333-
// Enable I-Cache
334-
unsafe { self.ccr.modify(|r| r | SCB_CCR_IC_MASK) };
331+
// Enable I-cache
332+
extern "C" {
333+
// see asm-v7m.s
334+
fn __enable_icache();
335+
}
335336

336-
crate::asm::dsb();
337-
crate::asm::isb();
337+
// NOTE(unsafe): The asm routine manages exclusive access to the SCB
338+
// registers and applies the proper barriers; it is technically safe on
339+
// its own, and is only `unsafe` here because it's `extern "C"`.
340+
unsafe { __enable_icache(); }
338341
}
339342

340343
/// Disables I-Cache if currently enabled
@@ -392,11 +395,16 @@ impl SCB {
392395
// Invalidate anything currently in the DCache
393396
self.invalidate_dcache(cpuid);
394397

395-
// Now turn on the DCache
396-
unsafe { self.ccr.modify(|r| r | SCB_CCR_DC_MASK) };
398+
// Now turn on the D-cache
399+
extern "C" {
400+
// see asm-v7m.s
401+
fn __enable_dcache();
402+
}
397403

398-
crate::asm::dsb();
399-
crate::asm::isb();
404+
// NOTE(unsafe): The asm routine manages exclusive access to the SCB
405+
// registers and applies the proper barriers; it is technically safe on
406+
// its own, and is only `unsafe` here because it's `extern "C"`.
407+
unsafe { __enable_dcache(); }
400408
}
401409

402410
/// Disables D-cache if currently enabled
@@ -706,7 +714,7 @@ impl SCB {
706714
}
707715
}
708716

709-
/// Set the PENDSTCLR bit in the ICSR register which will clear a pending SysTick interrupt
717+
/// Set the PENDSTSET bit in the ICSR register which will pend a SysTick interrupt
710718
#[inline]
711719
pub fn set_pendst() {
712720
unsafe {
@@ -842,6 +850,20 @@ impl SCB {
842850
}
843851
}
844852

853+
/// Return the bit position of the exception enable bit in the SHCSR register
854+
#[inline]
855+
#[cfg(not(any(armv6m, armv8m_base)))]
856+
fn shcsr_enable_shift(exception: Exception) -> Option<u32> {
857+
match exception {
858+
Exception::MemoryManagement => Some(16),
859+
Exception::BusFault => Some(17),
860+
Exception::UsageFault => Some(18),
861+
#[cfg(armv8m_main)]
862+
Exception::SecureFault => Some(19),
863+
_ => None,
864+
}
865+
}
866+
845867
/// Enable the exception
846868
///
847869
/// If the exception is enabled, when the exception is triggered, the exception handler will be executed instead of the
@@ -856,24 +878,11 @@ impl SCB {
856878
#[inline]
857879
#[cfg(not(any(armv6m, armv8m_base)))]
858880
pub fn enable(&mut self, exception: Exception) {
859-
if self.is_enabled(exception) {
860-
return;
861-
}
862-
863-
// Make sure that the read-modify-write sequence happens during a critical section to avoid
864-
// modifying pending and active interrupts.
865-
interrupt::free(|_| {
866-
let shift = match exception {
867-
Exception::MemoryManagement => 16,
868-
Exception::BusFault => 17,
869-
Exception::UsageFault => 18,
870-
#[cfg(armv8m_main)]
871-
Exception::SecureFault => 19,
872-
_ => return,
873-
};
874-
881+
if let Some(shift) = SCB::shcsr_enable_shift(exception) {
882+
// The mutable reference to SCB makes sure that only this code is currently modifying
883+
// the register.
875884
unsafe { self.shcsr.modify(|value| value | (1 << shift)) }
876-
})
885+
}
877886
}
878887

879888
/// Disable the exception
@@ -890,24 +899,11 @@ impl SCB {
890899
#[inline]
891900
#[cfg(not(any(armv6m, armv8m_base)))]
892901
pub fn disable(&mut self, exception: Exception) {
893-
if !self.is_enabled(exception) {
894-
return;
895-
}
896-
897-
// Make sure that the read-modify-write sequence happens during a critical section to avoid
898-
// modifying pending and active interrupts.
899-
interrupt::free(|_| {
900-
let shift = match exception {
901-
Exception::MemoryManagement => 16,
902-
Exception::BusFault => 17,
903-
Exception::UsageFault => 18,
904-
#[cfg(armv8m_main)]
905-
Exception::SecureFault => 19,
906-
_ => return,
907-
};
908-
902+
if let Some(shift) = SCB::shcsr_enable_shift(exception) {
903+
// The mutable reference to SCB makes sure that only this code is currently modifying
904+
// the register.
909905
unsafe { self.shcsr.modify(|value| value & !(1 << shift)) }
910-
})
906+
}
911907
}
912908

913909
/// Check if an exception is enabled
@@ -921,16 +917,11 @@ impl SCB {
921917
/// Calling this function with any other exception will read `false`.
922918
#[inline]
923919
#[cfg(not(any(armv6m, armv8m_base)))]
924-
pub fn is_enabled(&mut self, exception: Exception) -> bool {
925-
let shift = match exception {
926-
Exception::MemoryManagement => 16,
927-
Exception::BusFault => 17,
928-
Exception::UsageFault => 18,
929-
#[cfg(armv8m_main)]
930-
Exception::SecureFault => 19,
931-
_ => return false,
932-
};
933-
934-
(self.shcsr.read() & (1 << shift)) > 0
920+
pub fn is_enabled(&self, exception: Exception) -> bool {
921+
if let Some(shift) = SCB::shcsr_enable_shift(exception) {
922+
(self.shcsr.read() & (1 << shift)) > 0
923+
} else {
924+
false
925+
}
935926
}
936927
}

0 commit comments

Comments
 (0)