aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/peripheral/dcb.rs28
-rw-r--r--src/peripheral/dwt.rs22
-rw-r--r--src/peripheral/nvic.rs30
-rw-r--r--src/peripheral/test.rs10
4 files changed, 83 insertions, 7 deletions
diff --git a/src/peripheral/dcb.rs b/src/peripheral/dcb.rs
index 14dc75b..e12542c 100644
--- a/src/peripheral/dcb.rs
+++ b/src/peripheral/dcb.rs
@@ -2,6 +2,7 @@
use volatile_register::{RW, WO};
+use core::ptr;
use peripheral::DCB;
const DCB_DEMCR_TRCENA: u32 = 1 << 24;
@@ -20,18 +21,37 @@ pub struct RegisterBlock {
}
impl DCB {
- /// Enables TRACE. This is for example required by the
+ /// Enables TRACE. This is for example required by the
/// `peripheral::DWT` cycle counter to work properly.
/// As by STM documentation, this flag is not reset on
/// soft-reset, only on power reset.
pub fn enable_trace(&mut self) {
// set bit 24 / TRCENA
- unsafe { self.demcr.modify(|w| w | DCB_DEMCR_TRCENA); }
+ unsafe {
+ self.demcr.modify(|w| w | DCB_DEMCR_TRCENA);
+ }
}
-
+
/// Disables TRACE. See `DCB::enable_trace()` for more details
pub fn disable_trace(&mut self) {
// unset bit 24 / TRCENA
- unsafe { self.demcr.modify(|w| w & !DCB_DEMCR_TRCENA); }
+ unsafe {
+ self.demcr.modify(|w| w & !DCB_DEMCR_TRCENA);
+ }
+ }
+
+ /// Is there a debugger attached? (see note)
+ ///
+ /// Note: This function is [reported not to
+ /// work](http://web.archive.org/web/20180821191012/https://community.nxp.com/thread/424925#comment-782843)
+ /// on Cortex-M0 devices. Per the ARM v6-M Architecture Reference Manual, "Access to the DHCSR
+ /// from software running on the processor is IMPLEMENTATION DEFINED". Indeed, from the
+ /// [Cortex-M0+ r0p1 Technical Reference Manual](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0484c/BABJHEIG.html), "Note Software cannot access the debug registers."
+ pub fn is_debugger_attached() -> bool {
+ unsafe {
+ // do an 8-bit read of the 32-bit DHCSR register, and get the LSB
+ let value = ptr::read_volatile(Self::ptr() as *const u8);
+ value & 0x1 == 1
+ }
}
}
diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs
index 84f002e..77ec450 100644
--- a/src/peripheral/dwt.rs
+++ b/src/peripheral/dwt.rs
@@ -1,6 +1,8 @@
//! Data Watchpoint and Trace unit
-use volatile_register::{RO, RW, WO};
+#[cfg(not(armv6m))]
+use volatile_register::WO;
+use volatile_register::{RO, RW};
use peripheral::DWT;
@@ -10,25 +12,41 @@ pub struct RegisterBlock {
/// Control
pub ctrl: RW<u32>,
/// Cycle Count
+ #[cfg(not(armv6m))]
pub cyccnt: RW<u32>,
/// CPI Count
+ #[cfg(not(armv6m))]
pub cpicnt: RW<u32>,
/// Exception Overhead Count
+ #[cfg(not(armv6m))]
pub exccnt: RW<u32>,
/// Sleep Count
+ #[cfg(not(armv6m))]
pub sleepcnt: RW<u32>,
/// LSU Count
+ #[cfg(not(armv6m))]
pub lsucnt: RW<u32>,
/// Folded-instruction Count
+ #[cfg(not(armv6m))]
pub foldcnt: RW<u32>,
+ /// Cortex-M0(+) does not have these parts
+ #[cfg(armv6m)]
+ reserved: [u32; 6],
/// Program Counter Sample
pub pcsr: RO<u32>,
/// Comparators
+ #[cfg(armv6m)]
+ pub c: [Comparator; 2],
+ #[cfg(not(armv6m))]
+ /// Comparators
pub c: [Comparator; 16],
+ #[cfg(not(armv6m))]
reserved: [u32; 932],
/// Lock Access
+ #[cfg(not(armv6m))]
pub lar: WO<u32>,
/// Lock Status
+ #[cfg(not(armv6m))]
pub lsr: RO<u32>,
}
@@ -46,11 +64,13 @@ pub struct Comparator {
impl DWT {
/// Enables the cycle counter
+ #[cfg(not(armv6m))]
pub fn enable_cycle_counter(&mut self) {
unsafe { self.ctrl.modify(|r| r | 1) }
}
/// Returns the current clock cycle count
+ #[cfg(not(armv6m))]
pub fn get_cycle_count() -> u32 {
// NOTE(unsafe) atomic read with no side effects
unsafe { (*Self::ptr()).cyccnt.read() }
diff --git a/src/peripheral/nvic.rs b/src/peripheral/nvic.rs
index c59c2c8..57ce009 100644
--- a/src/peripheral/nvic.rs
+++ b/src/peripheral/nvic.rs
@@ -1,8 +1,8 @@
//! Nested Vector Interrupt Controller
-#[cfg(not(armv6m))]
-use volatile_register::RO;
use volatile_register::RW;
+#[cfg(not(armv6m))]
+use volatile_register::{RO, WO};
use interrupt::Nr;
use peripheral::NVIC;
@@ -65,9 +65,35 @@ pub struct RegisterBlock {
/// so convenient byte-sized representation wouldn't work on that
/// architecture.
pub ipr: [RW<u32>; 8],
+
+ #[cfg(not(armv6m))]
+ _reserved6: [u32; 580],
+
+ #[cfg(not(armv6m))]
+ /// Software Trigger Interrupt
+ pub stir: WO<u32>,
}
impl NVIC {
+ #[cfg(not(armv6m))]
+ /// Request an IRQ in software
+ ///
+ /// Writing a value to the INTID field is the same as manually pending an interrupt by setting
+ /// the corresponding interrupt bit in an Interrupt Set Pending Register. This is similar to
+ /// `set_pending`.
+ ///
+ /// This method is not available on ARMv6-M chips.
+ pub fn request<I>(&mut self, interrupt: I)
+ where
+ I: Nr,
+ {
+ let nr = interrupt.nr();
+
+ unsafe {
+ self.stir.write(nr as u32);
+ }
+ }
+
/// Clears `interrupt`'s pending state
#[deprecated(since = "0.5.8", note = "Use `NVIC::unpend`")]
pub fn clear_pending<I>(&mut self, interrupt: I)
diff --git a/src/peripheral/test.rs b/src/peripheral/test.rs
index 1f75818..4eb48f5 100644
--- a/src/peripheral/test.rs
+++ b/src/peripheral/test.rs
@@ -29,11 +29,17 @@ fn dwt() {
let dwt = unsafe { &*::peripheral::DWT::ptr() };
assert_eq!(address(&dwt.ctrl), 0xE000_1000);
+ #[cfg(not(armv6m))]
assert_eq!(address(&dwt.cyccnt), 0xE000_1004);
+ #[cfg(not(armv6m))]
assert_eq!(address(&dwt.cpicnt), 0xE000_1008);
+ #[cfg(not(armv6m))]
assert_eq!(address(&dwt.exccnt), 0xE000_100C);
+ #[cfg(not(armv6m))]
assert_eq!(address(&dwt.sleepcnt), 0xE000_1010);
+ #[cfg(not(armv6m))]
assert_eq!(address(&dwt.lsucnt), 0xE000_1014);
+ #[cfg(not(armv6m))]
assert_eq!(address(&dwt.foldcnt), 0xE000_1018);
assert_eq!(address(&dwt.pcsr), 0xE000_101C);
assert_eq!(address(&dwt.c[0].comp), 0xE000_1020);
@@ -42,7 +48,9 @@ fn dwt() {
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);
+ #[cfg(not(armv6m))]
assert_eq!(address(&dwt.lar), 0xE000_1FB0);
+ #[cfg(not(armv6m))]
assert_eq!(address(&dwt.lsr), 0xE000_1FB4);
}
@@ -109,6 +117,8 @@ fn nvic() {
assert_eq!(address(&nvic.icpr), 0xE000E280);
assert_eq!(address(&nvic.iabr), 0xE000E300);
assert_eq!(address(&nvic.ipr), 0xE000E400);
+ #[cfg(not(armv6m))]
+ assert_eq!(address(&nvic.stir), 0xE000EF00);
}
#[test]