This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

sd_app_evt_wait and unprivileged thread mode

Hello,

Our board is based on nRF52832 with S132 5.1.0, without RTOS. Now we have a requirement to protect sensitive memory areas with MPU, so I'm trying to run firmware in unprivileged mode (CONTROL=0x01), and I got Bus Fault in sd_app_evt_wait() handler. Should I use __WFE() instead, is it safe with SoftDevice enabled?

Dmitry

  • Thanks Edvin, it seems nobody else tried to use softdevice with restricted privileges. For now just one more question: what's a possible scenario of lockup / lost interrupts if I use WFE with interrupts enabled? As I understand, once interrupt arrives, it get handled even when next instruction is WFE. Do you have some details what's going inside sd_app_evt_wait(), maybe I could implement that safely in my code?

    Dmitry

  • The sd_app_evt_wait() uses WFE along with some other stuff, and it uses an IRQ mask to filter different types of events.

    Basically, it waits for any event. If it is only a softdevice event, such as an advertising event or a connection event, it will only do the part that the softdevice uses, and not wake up/notify the application (so you will not see/notice this from the application layer). If it is not a softdevice event, it will forward the interrupt to the application, just like a plain WFE would do.

    Best regards,

    Edvin

  • I tried an experiment with this myself last night, and I was able to duplicate your results. In my project I'm using the ChibiOS RTOS. Normally it runs all tasks in privileged mode, but like I tried to setting bit 0 in the CONTROL register to switch to unprivileged mode to see what would happen. I also saw that calling sd_app_evt_wait() would trigger a hard fault. Aside from that, the SoftDevice continued to work as expected.

    I do not think you forgot anything or are doing anything wrong. I think this is just an unexpected use case.

    I can see that when entering exception handler, bit 0 in the CONTROL register remains set. Basically I believe the semantics are: "when this bit is set, then the CPU will operate in unprivileged mode when executing in thread context." When you take an exception, you enter handler mode: at this point, the state of the privilege bit in the CONTROL register remains unchanged, but since the CPU is no longer in thread mode the access restrictions no longer apply.

    As you say, the sd_app_evt_wait() handler switches back to thread mode in order to sleep. At that point, the access restrictions take effect again, and unfortunately the code then tries to access some of the NVIC registers. (It looked to me like the access was to 0xe000e200, which is NVIC_ISPR0.) And as you noted, the generic timer, NVIC and SCB registers are not accessible when running in unprivileged thread mode, so you get a fault.

    I'm not sure what could be done to mitigate this, other than what you're already doing. I suppose sd_app_evt_wait() could temporarily clear bit 0 in the CONTROL register before escaping to thread mode and then restore it when it returns, but this might break the protection model.

    (I guess we should wait to see what the Nordic engineers say though. :) )

    -Bill

  • You are right, the sd_app_evt_wait always runs the sleep instructions in the privileged thread mode and hence it expects to return it to that state. I think this needs to be a feature request to change that behavior, as I do not see anything wrong in what you are doing. For now we are limited by this behavior.

    Could below be a possible workaround?

    Can we switch to privileged thread mode just before sleeping and change to unprivileged thread mode after wakeup? this way the SD thread mode switch behavior is consistent with the application.

  • If I understand right, this workaround should:

    - enter privileged mode (for example, using SVC 0x01)

    - from SVC handler, clear CONTROL register and change return address in stack to some intermediate Thread code

    - that code will call SVC 0x3E (sd_app_evt_wait)

    - at return, it will set CONTROL register back and pass control to calling function

    Maybe it's possible but it makes too easy to shoot own's foot :)  I decided to set MPU XN bit on RAM and leave in privileged mode - at least this way protects from accidental reading of critical memory regions.

    Could I make a feature request as you said? Are there plans to release an update for softdevice 5.x?

Related