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

consistent support in sd_* wrapper functions

The documentation for S110 v7.1.0 sd_nvic_ClearPendingIRQ implies that it works with any valid IRQ.

I find that (using S110 v7.1.0 with SDK 7.1.0):

  sd_nvic_ClearPendingIRQ(UART0_IRQn);

generates a hard fault while

  NVIC_ClearPendingIRQ(UART0_IRQn);

works fine, in an application which has already started the soft device.

Am I doing something wrong, or is it not only unnecessary but actively wrong to invoke the wrapper functions with peripherals that are not restricted by the soft device? This comment suggests it's supposed to be OK.

(I'm writing code that is supposed to be independent of what soft-device it's running with, so am not trying to guess whether a particular peripheral is restricted or not.)

  • Does sd_nvic_ClearPendingIRQ() return an error? Have you tried to put a breakpoint in app_error_handler()? You need to turn off optimizations and add DEBUG as a preprocessor symbol to see the error code. Please edit your question to include the information. It would also be helpful if you could let us know what SDK version you have, and if you could upload your complete project with the fault.

  • I've updated to clarify that I'm using the version corresponding to the documentation I cited. I'm not sure how I'm supposed to get an error code out of the fact the PC is left in HardFault_Handler.

    Just confirmation that we should not expect to use the sd wrappers on peripherals that the soft device doesn't manage would be enough to answer the question. If we are supposed to be able to do that, perhaps you could verify that it works for you.

  • Yes you can and should use the sd_ wrappers to enable/disable/clear interrupts whether they are restricted or not. Those functions check (if the softdevice is active) the peripheral you are working with to ensure it's not restricted (and error if it is). In this case clearly you are using UART0 which isn't restricted, so that's not the problem.

    Where are you calling this from? Are you calling it from an interrupt handler? The sd_* calls all just emit a svc instruction. The priority of that interrupt (from the softdevice manual) is Upper Stack which is '2'. If you are running in Application High (which is interrupt level '1') or from one of the timeslot API callbacks which runs in 'Lower Stack', (which is '0') then the svc call will hardfault as you can't call a lower priority interrupt from a higher priority one.

    And yes I find it infinitely confusing that the lower priority user interrupt level is called 'Application Low' and the higher one 'Application High', however the highest priority in the softdevice is the 'Lower Stack' and the lower priority is the 'Upper Stack'.

    If you aren't calling this from an interrupt handler or similar, then it should work. If you are calling it from one, then switching that interrupt to priority NRF_APP_PRIORITY_LOW should work.

  • the svc call will hardfault as you can't call a lower priority interrupt from a higher priority one.

    Thanks; that provided the clue. I wasn't calling from an interrupt handler, but I was calling it from an initialization sequence during which interrupts were disabled. Perfectly fine with the standard CMSIS function which just writes a register. Not fine with the svc instruction

    FWIW, I've pretty well committed to not using these wrappers for peripherals that are "open" under the SD. The overhead of the SVC interrupt compared with a single instruction is too high; worse, the SD wrappers error if the soft device is disabled and one potential application architecture involves turning off the SD completely to control the radio. I'm hoping the multiprotocol support meets the requirements of the existing application so this won't be necessary, but I can't be sure yet.

Related