Skip to content

Commit 7739138

Browse files
bors[bot]Brandon Matthewsthenewwazookorken89
committed
Merge #106 #127
106: Stir register and debugger check r=adamgreig a=thenewwazoo Adds support for requesting an interrupt via the STIR register and checking whether a debugger is attached. 127: Cortex M0(+) DWT fixes r=adamgreig a=korken89 The current DWT setup has a lot of registers that are not available in Cortex-M0(+), fixes are added here. Co-authored-by: Brandon Matthews <[email protected]> Co-authored-by: Brandon Matthews <[email protected]> Co-authored-by: Emil Fresk <[email protected]>
3 parents ac5f677 + 2ff4735 + 712aa29 commit 7739138

File tree

4 files changed

+85
-6
lines changed

4 files changed

+85
-6
lines changed

src/peripheral/dcb.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use volatile_register::{RW, WO};
44

5+
use core::ptr;
56
use peripheral::DCB;
67

78
const DCB_DEMCR_TRCENA: u32 = 1 << 24;
@@ -20,18 +21,37 @@ pub struct RegisterBlock {
2021
}
2122

2223
impl DCB {
23-
/// Enables TRACE. This is for example required by the
24+
/// Enables TRACE. This is for example required by the
2425
/// `peripheral::DWT` cycle counter to work properly.
2526
/// As by STM documentation, this flag is not reset on
2627
/// soft-reset, only on power reset.
2728
pub fn enable_trace(&mut self) {
2829
// set bit 24 / TRCENA
29-
unsafe { self.demcr.modify(|w| w | DCB_DEMCR_TRCENA); }
30+
unsafe {
31+
self.demcr.modify(|w| w | DCB_DEMCR_TRCENA);
32+
}
3033
}
31-
34+
3235
/// Disables TRACE. See `DCB::enable_trace()` for more details
3336
pub fn disable_trace(&mut self) {
3437
// unset bit 24 / TRCENA
35-
unsafe { self.demcr.modify(|w| w & !DCB_DEMCR_TRCENA); }
38+
unsafe {
39+
self.demcr.modify(|w| w & !DCB_DEMCR_TRCENA);
40+
}
41+
}
42+
43+
/// Is there a debugger attached? (see note)
44+
///
45+
/// Note: This function is [reported not to
46+
/// work](http://web.archive.org/web/20180821191012/https://community.nxp.com/thread/424925#comment-782843)
47+
/// on Cortex-M0 devices. Per the ARM v6-M Architecture Reference Manual, "Access to the DHCSR
48+
/// from software running on the processor is IMPLEMENTATION DEFINED". Indeed, from the
49+
/// [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."
50+
pub fn is_debugger_attached() -> bool {
51+
unsafe {
52+
// do an 8-bit read of the 32-bit DHCSR register, and get the LSB
53+
let value = ptr::read_volatile(Self::ptr() as *const u8);
54+
value & 0x1 == 1
55+
}
3656
}
3757
}

src/peripheral/dwt.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Data Watchpoint and Trace unit
22
3-
use volatile_register::{RO, RW, WO};
3+
#[cfg(not(armv6m))]
4+
use volatile_register::WO;
5+
use volatile_register::{RO, RW};
46

57
use peripheral::DWT;
68

@@ -10,25 +12,41 @@ pub struct RegisterBlock {
1012
/// Control
1113
pub ctrl: RW<u32>,
1214
/// Cycle Count
15+
#[cfg(not(armv6m))]
1316
pub cyccnt: RW<u32>,
1417
/// CPI Count
18+
#[cfg(not(armv6m))]
1519
pub cpicnt: RW<u32>,
1620
/// Exception Overhead Count
21+
#[cfg(not(armv6m))]
1722
pub exccnt: RW<u32>,
1823
/// Sleep Count
24+
#[cfg(not(armv6m))]
1925
pub sleepcnt: RW<u32>,
2026
/// LSU Count
27+
#[cfg(not(armv6m))]
2128
pub lsucnt: RW<u32>,
2229
/// Folded-instruction Count
30+
#[cfg(not(armv6m))]
2331
pub foldcnt: RW<u32>,
32+
/// Cortex-M0(+) does not have these parts
33+
#[cfg(armv6m)]
34+
reserved: [u32; 6],
2435
/// Program Counter Sample
2536
pub pcsr: RO<u32>,
2637
/// Comparators
38+
#[cfg(armv6m)]
39+
pub c: [Comparator; 2],
40+
#[cfg(not(armv6m))]
41+
/// Comparators
2742
pub c: [Comparator; 16],
43+
#[cfg(not(armv6m))]
2844
reserved: [u32; 932],
2945
/// Lock Access
46+
#[cfg(not(armv6m))]
3047
pub lar: WO<u32>,
3148
/// Lock Status
49+
#[cfg(not(armv6m))]
3250
pub lsr: RO<u32>,
3351
}
3452

@@ -46,11 +64,13 @@ pub struct Comparator {
4664

4765
impl DWT {
4866
/// Enables the cycle counter
67+
#[cfg(not(armv6m))]
4968
pub fn enable_cycle_counter(&mut self) {
5069
unsafe { self.ctrl.modify(|r| r | 1) }
5170
}
5271

5372
/// Returns the current clock cycle count
73+
#[cfg(not(armv6m))]
5474
pub fn get_cycle_count() -> u32 {
5575
// NOTE(unsafe) atomic read with no side effects
5676
unsafe { (*Self::ptr()).cyccnt.read() }

src/peripheral/nvic.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Nested Vector Interrupt Controller
22
33
#[cfg(not(armv6m))]
4-
use volatile_register::RO;
4+
use volatile_register::{RO, WO};
55
use volatile_register::RW;
66

77
use interrupt::Nr;
@@ -65,9 +65,38 @@ pub struct RegisterBlock {
6565
/// so convenient byte-sized representation wouldn't work on that
6666
/// architecture.
6767
pub ipr: [RW<u32>; 8],
68+
69+
#[cfg(not(armv6m))]
70+
reserved5: [u32; 208],
71+
72+
#[cfg(armv6m)]
73+
reserved5: [u32; 696],
74+
75+
#[cfg(not(armv6m))]
76+
/// Software Trigger Interrupt
77+
pub stir: WO<u32>,
6878
}
6979

7080
impl NVIC {
81+
#[cfg(not(armv6m))]
82+
/// Request an IRQ in software
83+
///
84+
/// Writing a value to the INTID field is the same as manually pending an interrupt by setting
85+
/// the corresponding interrupt bit in an Interrupt Set Pending Register. This is similar to
86+
/// `set_pending`.
87+
///
88+
/// This method is not available on ARMv6-M chips.
89+
pub fn request<I>(&mut self, interrupt: I)
90+
where
91+
I: Nr,
92+
{
93+
let nr = interrupt.nr();
94+
95+
unsafe {
96+
self.stir.write(nr as u32);
97+
}
98+
}
99+
71100
/// Clears `interrupt`'s pending state
72101
#[deprecated(since = "0.5.8", note = "Use `NVIC::unpend`")]
73102
pub fn clear_pending<I>(&mut self, interrupt: I)

src/peripheral/test.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,17 @@ fn dwt() {
2929
let dwt = unsafe { &*::peripheral::DWT::ptr() };
3030

3131
assert_eq!(address(&dwt.ctrl), 0xE000_1000);
32+
#[cfg(not(armv6m))]
3233
assert_eq!(address(&dwt.cyccnt), 0xE000_1004);
34+
#[cfg(not(armv6m))]
3335
assert_eq!(address(&dwt.cpicnt), 0xE000_1008);
36+
#[cfg(not(armv6m))]
3437
assert_eq!(address(&dwt.exccnt), 0xE000_100C);
38+
#[cfg(not(armv6m))]
3539
assert_eq!(address(&dwt.sleepcnt), 0xE000_1010);
40+
#[cfg(not(armv6m))]
3641
assert_eq!(address(&dwt.lsucnt), 0xE000_1014);
42+
#[cfg(not(armv6m))]
3743
assert_eq!(address(&dwt.foldcnt), 0xE000_1018);
3844
assert_eq!(address(&dwt.pcsr), 0xE000_101C);
3945
assert_eq!(address(&dwt.c[0].comp), 0xE000_1020);
@@ -42,7 +48,9 @@ fn dwt() {
4248
assert_eq!(address(&dwt.c[1].comp), 0xE000_1030);
4349
assert_eq!(address(&dwt.c[1].mask), 0xE000_1034);
4450
assert_eq!(address(&dwt.c[1].function), 0xE000_1038);
51+
#[cfg(not(armv6m))]
4552
assert_eq!(address(&dwt.lar), 0xE000_1FB0);
53+
#[cfg(not(armv6m))]
4654
assert_eq!(address(&dwt.lsr), 0xE000_1FB4);
4755
}
4856

@@ -109,6 +117,8 @@ fn nvic() {
109117
assert_eq!(address(&nvic.icpr), 0xE000E280);
110118
assert_eq!(address(&nvic.iabr), 0xE000E300);
111119
assert_eq!(address(&nvic.ipr), 0xE000E400);
120+
#[cfg(not(armv6m))]
121+
assert_eq!(address(&nvic.stir), 0xE000EF00);
112122
}
113123

114124
#[test]

0 commit comments

Comments
 (0)