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
Merged

Stir register and debugger check #106

merged 10 commits into from
Mar 12, 2019

Conversation

thenewwazoo
Copy link

Adds support for requesting an interrupt via the STIR register and checking whether a debugger is attached.

@thenewwazoo thenewwazoo requested a review from a team as a code owner August 14, 2018 17:57
@thenewwazoo
Copy link
Author

(This is a re-submittal of #91, which I couldn't figure out how to re-open, sorry)

Copy link
Contributor

@korken89 korken89 left a 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 ?

@korken89
Copy link
Contributor

bors try

bors bot added a commit that referenced this pull request Aug 15, 2018
@bors
Copy link
Contributor

bors bot commented Aug 15, 2018

try

Build failed

@korken89
Copy link
Contributor

There were some errors in the build, for nightly it seems to be in bare-metal can you open an issue for this?

@thenewwazoo
Copy link
Author

I'm sitting on this right now because, for reasons I can't figure out, the is_debugger_attached() method doesn't appear to work as intended and I want to figure out why. In short,

(gdb) i r r0
r0             0xe000edf0	-536810000
(gdb) stepi
core::ptr::read_volatile::h4b0ffdf9b2e18c09 (src=0xe000edf0) at /checkout/src/libcore/ptr.rs:472
472	/checkout/src/libcore/ptr.rs: No such file or directory.
(gdb) disas
Dump of assembler code for function core::ptr::read_volatile::h4b0ffdf9b2e18c09:
=> 0x08003d0a <+0>:	ldr	r0, [r0, #0]
   0x08003d0c <+2>:	bx	lr
End of assembler dump.
(gdb) stepi
halted: PC: 0x08003d0c
473	in /checkout/src/libcore/ptr.rs
(gdb) i r r0
r0             0x0	0

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`.
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

@japaric
Copy link
Member

japaric commented Aug 18, 2018

@thenewwazoo did you get the is_debugger_attached method to work? i.e. is this ready for review? Actually, I'm going to let @korken89 finish the review. :-)

@korken89
Copy link
Contributor

I will give the PR a spin tonight :) If I find any issue I will report back!

@thenewwazoo
Copy link
Author

I was not able to get the is_debugger_attached method to work, but @adamgreig reported the same approach has historically worked for him on other devices than I've got on-hand. It's one of those things that should work... In any case, I don't believe I'm missing any preconditions.

@korken89
Copy link
Contributor

I have it a quick test, and it's not working for me. I will dig deeper tomorrow and see what's missing.

@adamgreig
Copy link
Member

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 DCB, just like DWT::get_cycle_count() and friends.

@japaric
Copy link
Member

japaric commented Aug 21, 2018

However I suggest replacing it with:

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)

@japaric
Copy link
Member

japaric commented Aug 21, 2018

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.

@adamgreig
Copy link
Member

Checking the ARM, for DHCSR,

Access to the DHCSR from software running on the processor is IMPLEMENTATION
DEFINED

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.

That'd be fine iff reading DHCSR does not clear any of its bits.

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.

@thenewwazoo
Copy link
Author

Great find, @adamgreig!

It looks like I can gate this on armv6m, and build a more robust test for cortex-m0 targets in a separate crate. I also agree that making the is_debugger_attached method into a function would be better.

@adamgreig
Copy link
Member

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.

build a more robust test for cortex-m0 targets

Can this be done? I can't see any good way to check for this on Cortex-M0.

@korken89
Copy link
Contributor

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 S_RESET_ST, as I see it this is only for debugger use as anyone implementing something depending on happening after reset would be done through pre_init.
Are there any more comments or change requests?

@rust-embedded/cortex-m

@adamgreig
Copy link
Member

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".

@korken89
Copy link
Contributor

korken89 commented Sep 3, 2018

@thenewwazoo Can you add these comments and I will merge this?

@korken89
Copy link
Contributor

korken89 commented Sep 3, 2018

Thanks for the quick addition @thenewwazoo !
There seems to be a problem with one of the tests, could you give it a quick look?

@thenewwazoo
Copy link
Author

thenewwazoo commented Sep 7, 2018

I looked into the test, and I've got a proximate cause.

112    assert_eq!(address(&nvic.stir), 0xE000EF00);

is the line that fails. address(&nvic.stir) evaluates to 0xe000e930, but according to the TRM, 0xE000EF00 is the correct value.

@thenewwazoo
Copy link
Author

thenewwazoo commented Sep 7, 2018

The test was executing for armv6m targets too (where the register doesn't exist), so I added a cfg attribute to skip it. The current failure is when building for x86 targets, where it is similarly nonsensical.

I figure I can:

  • also deny the test for x86 targets
  • refactor the tests to only permit armv7m, armv7em, ...?
  • adjust the reserved5 size values in nvic.rs so all platforms line up and the test "succeeds"
  • leave it as-is

@korken89
Copy link
Contributor

korken89 commented Sep 7, 2018

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 cargo test and only keep the cargo check for the x86 target.

/// 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
Copy link
Member

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.

Copy link
Author

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. :(

Copy link
Author

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. :)

Copy link
Member

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)).

@adamgreig adamgreig mentioned this pull request Jan 28, 2019
@Disasm Disasm added the S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. label Feb 22, 2019
@thenewwazoo
Copy link
Author

@Disasm @adamgreig this should be GTG (perhaps pending @japaric confirming his requested changes have been satisfied)

adamgreig
adamgreig previously approved these changes Mar 12, 2019
Copy link
Member

@adamgreig adamgreig left a 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+

@adamgreig adamgreig dismissed japaric’s stale review March 12, 2019 20:47

Requested changes have been addressed

@adamgreig adamgreig added S-waiting-on-bors Currently approved, waiting to merge. and removed S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. labels Mar 12, 2019
bors bot added a commit that referenced this pull request Mar 12, 2019
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]>
@bors
Copy link
Contributor

bors bot commented Mar 12, 2019

Build failed (retrying...)

bors bot added a commit that referenced this pull request Mar 12, 2019
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]>
@bors
Copy link
Contributor

bors bot commented Mar 12, 2019

Build failed (retrying...)

bors bot added a commit that referenced this pull request Mar 12, 2019
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]>
@bors
Copy link
Contributor

bors bot commented Mar 12, 2019

Canceled

@thenewwazoo
Copy link
Author

Tests should succeed now, having fixed the reserved offsets

@adamgreig
Copy link
Member

thanks!

bors r+

bors bot added a commit that referenced this pull request Mar 12, 2019
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]>
@bors
Copy link
Contributor

bors bot commented Mar 12, 2019

Build succeeded

@bors bors bot merged commit 771fc84 into rust-embedded:master Mar 12, 2019
@thenewwazoo thenewwazoo deleted the stir-register branch March 12, 2019 21:51
adamgreig pushed a commit that referenced this pull request Jan 12, 2022
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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Currently approved, waiting to merge.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants