-
Notifications
You must be signed in to change notification settings - Fork 168
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
Conversation
(This is a re-submittal of #91, which I couldn't figure out how to re-open, sorry) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM, but I will see if anyone else of the team has a comment. Strangely though, Travis has not run. Do you know why @japaric ?
bors try |
tryBuild failed |
There were some errors in the build, for nightly it seems to be in |
I'm sitting on this right now because, for reasons I can't figure out, the
I'm not sure if there's some precondition I'm missing to successfully reading DHCSR. |
/// | ||
/// 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`. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
@thenewwazoo did you get the |
I will give the PR a spin tonight :) If I find any issue I will report back! |
I was not able to get the |
I have it a quick test, and it's not working for me. I will dig deeper tomorrow and see what's missing. |
I've just tested this on a STM32F407 and it works as expected. In my case I flash an LED while debugger is attached and don't if not. I'll see if I can find a few other targets to test it on this week. However I suggest replacing it with: impl DCB {
/// Is there a debugger attached?
pub fn is_debugger_attached() -> bool {
unsafe { (*Self::ptr()).dhcsr.read() & 0x1 == 1 }
}
} to make it accessible without an instance of |
That'd be fine iff reading DHCSR does not clear any of its bits. (NB I haven't read this register documentation so I'm just asking for caution rather than saying this should not be done) |
If this is not working really perhaps if one of those optional things that vendors may or may not implement? If that's the case it should be noted in the docs. |
Checking the ARM, for DHCSR,
And while this technique is suggested by ARM (i.e., there's no other 'correct' way to do it AFAIK), it also appears that on Cortex-M0 the CPU can't read this register.
Annoyingly S_RESET_ST and S_RETIRE_ST are cleared by reading DHCSR, though I'm not sure if the CPU reading it will trigger the clear or only a debugger reading it. In any event S_RETIRE_ST is set to 1 whenever the processor completes an instruction, so just reading DHCSR would set the bit anyway. I wonder if it might be justifiable for this scenario. It's not like the exclusive access ensured by having a DCB object in any way synchronises access with the debugger anyway. |
Great find, @adamgreig! It looks like I can gate this on |
Even on armv6m I'm not sure it's actually never going to work, just it seems like most Cortex-M0 don't permit it. I can't find anything in the ARMv6-M ARM to say it's prohibited, just the same caution that it's implementation defined as on the ARMv7-M ARM.
Can this be done? I can't see any good way to check for this on Cortex-M0. |
I have now tested this on a Cortex-M4 and Cortex-M3 where it was working, however on a Cortex-M0 (as discussed above) it is not working. On @rust-embedded/cortex-m |
I'm happy with this as-is, but wouldn't mind a second note in the comments that it reads DHCSR and therefore clears S_RESET_ST and S_RETIRE_ST, just in case some poor soul from the future gets stuck hunting down something annoying. The existing note could maybe also be clarified to just say "This function's operation is implementation defined and is not functional on Cortex-M0 devices". |
@thenewwazoo Can you add these comments and I will merge this? |
Thanks for the quick addition @thenewwazoo ! |
I looked into the test, and I've got a proximate cause. 112 assert_eq!(address(&nvic.stir), 0xE000EF00); is the line that fails. |
The test was executing for armv6m targets too (where the register doesn't exist), so I added a I figure I can:
|
Thanks for checking and finding the cause @thenewwazoo ! Checking the tests and the CI scripts I am not sure why the x86 target is run at all. @rust-embedded/cortex-m am I missing something obvious? Else I will opt for removing the |
src/peripheral/dcb.rs
Outdated
/// 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." | ||
/// | ||
/// Note 2: This function reads the DHCSR register, and therefore clears S_RESET_ST and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not happy about this being a static method that modifies the contents of the register. The documentation says:
Writes to this register in any size other than word are Unpredictable. It is acceptable to read in any size, and you can use it to avoid or intentionally change a sticky bit.
Could you turn this into a byte read to avoid clearing the S_RESET_ST and S_RETIRE_ST bits? Then it'd be fine to keep this as a static method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried a couple of ways to do this, but am not sure which you'd prefer.
Byte-wise access:
pub struct RegisterBlock {
/// Debug Halting Control and Status
pub dhcsr: [RW<u8>;4],
...
breaks writing to the register, which requires that the high halfword always be 0xA05F
.
Using an untagged union:
pub union DHCSR {
/// 32-bit word access
w: WO<u32>,
/// Individual byte access
b: [RW<u8>; 4],
}
/// Register block
#[repr(C)]
pub struct RegisterBlock {
/// Debug Halting Control and Status
pub dhcsr: DHCSR,
...
looks like a good solution, but untagged unions of non-Copy types is unstable.
I could try to do some unsafe trickery by doing pointer math but that seems like a bad idea. What do you think?
As an aside, I'm sorry this tiny little change has eaten up so much energy. It seemed so simple at first. :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was reminded of this today - any suggestions? I'm happy to go with whatever's best, I just don't know what it is. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thenewwazoo sorry for dropping the ball here
breaks writing to the register, which requires that the high halfword always be 0xA05F.
this would be a breaking change; also it breaks writes as you say
Using an untagged union:
this is unstable so it's a no-go
I could try to do some unsafe trickery by doing pointer math but that seems like a bad idea.
using pointers seems like the only stable, backward-compatible solution. You can write something like (*(&dhcsr as *const [RW<u8>; 4]))[index].read())
to avoid the pointer math. Though pointer math is probably easier to read ptr::read_volatile((&dhcsr as *const u8).add(index))
.
@Disasm @adamgreig this should be GTG (perhaps pending @japaric confirming his requested changes have been satisfied) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe all outstanding objections have been addressed, thanks @thenewwazoo!
bors r+
Requested changes have been addressed
97: Rename `shcrs` to `shcsr` in `scb::RegisterBlock` r=adamgreig a=rajivr Commit `c290aa4e` introduced `shcrs` field to `scb::RegisterBlock`. In CMSIS, this field is `shcsr`. https://github.com/ARM-software/CMSIS_5/blob/5.3.0/CMSIS/Core/Include/core_cm4.h#L449 This patch changes `shcrs` to `shcsr`. Signed-off-by: Rajiv Ranganath <[email protected]> 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: Rajiv Ranganath <[email protected]> Co-authored-by: Brandon Matthews <[email protected]> Co-authored-by: Brandon Matthews <[email protected]> Co-authored-by: Emil Fresk <[email protected]>
Build failed (retrying...) |
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]>
Build failed (retrying...) |
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. Co-authored-by: Brandon Matthews <[email protected]> Co-authored-by: Brandon Matthews <[email protected]>
Canceled |
Tests should succeed now, having fixed the reserved offsets |
thanks! bors r+ |
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. Co-authored-by: Brandon Matthews <[email protected]> Co-authored-by: Brandon Matthews <[email protected]>
Build succeeded |
106: error during compilation if two copies of cortex-m-rt are being linked r=adamgreig a=japaric linking two copies into the final binary produces a confusing linker error message. This improves the situation by producing an error at compile time. This will have to be backported into the v0.5.x series or you won't get the new error message. r? @rust-embedded/cortex-m (anyone) Co-authored-by: Jorge Aparicio <[email protected]>
Adds support for requesting an interrupt via the STIR register and checking whether a debugger is attached.