Skip to content

Stir register and debugger check #106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 12, 2019
28 changes: 24 additions & 4 deletions src/peripheral/dcb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use volatile_register::{RW, WO};

use core::ptr;
use peripheral::DCB;

const DCB_DEMCR_TRCENA: u32 = 1 << 24;
Expand All @@ -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
}
}
}
30 changes: 28 additions & 2 deletions src/peripheral/nvic.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you include in the documentation why would one prefer this over set_pending and also mention that this API is not available on ARMv6-M.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll be honest... I don't know why to choose one vs the other. The reference manuals don't make the different clear. :) I'll add a note about not being available on armv6m

///
/// 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)
Expand Down
2 changes: 2 additions & 0 deletions src/peripheral/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,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]
Expand Down