-
Notifications
You must be signed in to change notification settings - Fork 3k
Fix the ICSR mask value used to enter WFE #8224
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
@RobMeades @NeilMacMullen This has the potential to reduce power consumption when the SoftDevice is disabled |
I have problem with The test regularly pass CI, but fails if you run it locally The sleep test case perform sleep for 100 us, 200 us, ... ,1000 us in loop (us ticker wakes the boards) and verifies if sleep time matches the assumption.
In the failure case (500 us) us ticker interrupt has not been triggered yet and it looks like the board did not even enter sleep mode. This is because in the Interrupt Control and State Register I tried your fix and the the results are the same... In case of failure wake-up time is also ~14 us. Patch can be found here: PR #8257 |
@mprse - I will try to look at this today! Unfortunately I am out-of-office the rest of the week, so apologies if I have a delayed response as I have other items that need closure. |
if (SCB->ICSR & (SCB_ICSR_RESERVED_BITS_MASK)) { | ||
// Ok, there is an interrut pending, no need to go to sleep | ||
// Test if we should enter WFE | ||
if (SCB->ICSR & (SCB_ICSR_WFE_MASK)) { |
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.
Is the ICSR check needed? If an interrupt is pending shouldn't __WFE()
just clear the event register and return immediately?
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 not confident enough to say that we don't need the ICSR check but I think it's prudent. At the minimum it prevents entry to sleep while in an exception handler (either accidentally or intentionally) by including VECTACTIVE in the mask.
Possibly dumb question (not really familiar with the nRF devices) - why aren't you just using WFI here? |
As far as I can see, this is being complicated by the fact you're fighting WFE to use it for something it's not designed for. Roughly speaking WFE is for user-code spinlocks when interrupts are enabled, and WFI is for inside-the-OS power saving code when interrupts are disabled. I would expect a simple single "WFI" to work fine here, with no messing with SEV or the ICSR. Also wouldn't need to set See FAQ http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15473.html and my previous waffle at https://os.mbed.com/forum/mbed/topic/29547/?page=1#comment-55419 Also, from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHICBGB.html and other sources, there should be a DSB before WFI (or WFE). I see most targets are using WFI, but I do see a few using "SEV; WFE; WFE;" like this. Atmel_SAM_R4 apparently uses WFI for sleep and WFE for deep sleep! |
Okay, I get it - this is a special case because In that case, I think the sequence Seems safe as long as you know you're single-CPU, so won't be waking any other cores with the SEV and you know no other cores are trying to wake you, and as long as the SoftDevice code only contacts you via the masked IRQs that you're catching via the SEVONPEND. |
@kjbracey-arm - Correct - one of the subtle differences between I agree that we should add the |
Getting off on a tangent, but another possible approach would be:
That would avoid "waking" the application side and its RTOS every time there's a softdevice IRQ. That's assuming a lot of stuff I don't know about your system, eg that softdevice does all its work from IRQs, and that it's worthwhile not waking the application side for softdevice. |
@jrobeson Do you think you could comment on this proposed fix? |
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.
Change looks good to me.
Love the deep technical back and forth.
Would like one more OK from @ARMmbed/mbed-os-core since this change is so deep. |
@TacoGrandeTX Let us know if there's any pressure to get this in sooner than the next feature release. |
@cmonr I'm the last person you want to get an OK from for this sort of thing. The incorrect ICSR value got uncovered while looking into a bug I filed, and then the bug was fixed, but the ICSR value issue was not addressed. After that, I simply filed a bug to make sure it would be. |
@jrobeson Thanks for the honesty. Then I'll just wait for someone else from @mbed-os-core before moving this PR along. |
@SenRamakri - Please have a look |
@cmonr There is no pressing need to get this released. I just completed local tests of adding the DSB instruction as suggested by @kjbracey-arm and have pushed that commit. |
Aside from my wittering about other larger approaches, I do agree with @c1728p9 that in this version the "if ICSR" check just shouldn't be there. The "pending" check isn't needed - it's inherently racy, and the WFE does it for you. The "active" check I don't really understand - why do you feel you need to be defensive against people calling It's a weird thing to do, but not especially dangerous for this particular platform, is it? It's a valid request - "please block until a higher-priority interrupt would wake me". Other platforms just do "SEV; WFE; WFE;", and I don't see why you shouldn't. (And only one DSB is needed, not one per WFE). |
@kjbracey-arm That's a good point so there is no point in being defensive here. I made the most conservative change that fixed the problem but didn't think we could exclude the check. As you and @c1728p9 think the ICSR check is not needed, I'll remove it and the second DSB. |
Description
The current value of SCB_ICSR_RESERVED_BITS_MASK is not restrictive enough and will prevent the core from entering WFE if any interrupt is pending, even if it is not enabled. This can happen rather easily as one might lazily disable a low priority interrupt and not notice that the pending bit was set. This will forever prevent the core from sleeping. In fact this goes even deeper as architecturally an interrupt can go pending even if it is disabled in the NVIC.
We should just be checking against the VECTPENDING and VECTACTIVE bit fields in the Interrupt Control and State Register (ICSR). When VECTPENDING is non-zero it indicates which interrupt is pending and enabled. We don't want to enter WFE in an exception handler, so we also include VECTACTIVE in the bit mask.
This stems from #5647.
Pull request type