When using the nRF Connect SDK with the SoftDevice Controller, what interrupt priorities can the application safely use?

The nRF52840 features an ARM Cortex-M4 processor with an interrupt controller with 3 priority bits. This means there are eight possible interrupt priorities, numbered 0 through 7, with 0 being the highest priority.

The old nRF SDK documentation was very clear about which of these priority levels the application could use while working with the SoftDevice (see here). Specifically, the SoftDevice uses priorities 0, 1, and 4, so the application is free to use the others. When in an interrupt with priority 2 or 3, the application cannot call the SoftDevice functions; when in an interrupt with priority 5, 6, or 7, it can.

Clear and simple.

I'm looking for similar guidance for the newer nRF Connect SDK, but I'm having trouble finding it.  The SoftDevice Controller documentation has an Integration with applications page, but that page doesn't mention interrupts at all.  It does say:

The SoftDevice Controller relies on the functionality provided by Nordic Semiconductor’s Multiprotocol Service Layer, which has its own set of requirements that the application must follow.

In the documentation for the Multiprotocol Service Layer, in the Integration notes section, there is guidance on interrupt priorities.  It says RTC0, TIMER0, and RADIO interrupts must be configured for priority level 0. It then says there are two other interrupts, POWER_CLOCK and low_prio_irq, that "do not have real-time requirements", but it doesn't say what priority level they should be configured for.

When I took a look at how the priority levels were actually configured when running an example, I found the following:

Interrupt Priority
RADIO 0
TIMER0 0
RTC0 0
POWER_CLOCK 3
SWI5 (low_prio_irq) 6

I experimentally determined the interrupt configuration by running a project using the SoftDevice Controller and then calling the methods NVIC_GetEnableIRQ() and NVIC_GetPriority() for every IRQ, to see which interrupts were enabled and at what priority levels.  The results are shown in the table above.

  • The RADIO, TIMER0, and RTC0 interrupts are enabled and given their priority of 0 in the mpsl_lib_init_sys() function of subsys/mpsl/init/mpsl_init.c.

  • Also in subsys/mpsl/init/mpsl_init.c, the low_prio_irq (which is apparently SWI5 on the nRF52840) is given a priority of 6. This happens in the mpsl_low_prio_init() function. The priority is actually set to 4, but IRQ_CONNECT() adds two to the priority level.

    One priority level is reserved if CONFIG_CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS is set, which it is when using an ARM Cortex-M4 processor becase CONFIG_CPU_CORTEX_M4 selects CONFIG_ARMV7_M_ARMV8_M_MAINLINE which selects CONFIG_CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS.

    Another priority level is reserved if CONFIG_ZERO_LATENCY_IRQS is set, which it is whenever the MPSL is in use because CONFIG_MPSL selects CONFIG_ZERO_LATENCY_IRQS.

    This calculation happens in Zephyr, specifically the z_arm_irq_priority_set() function of arch/arm/core/aarch32/irq_manage.c. The given priority level is increased by _IRQ_PRIO_OFFSET, which is 2 in this case. It is defined in include/zephyr/arch/arm/aarch32/exc.h.

  • Finally, the POWER_CLOCK interrupt is enabled and given a priority of 3 because of its device tree configuration.  Specifically, in Zephyr file dts/arm/nordic/nrf52840.dtsi, the clock interrupt is given priority NRF_DEFAULT_IRQ_PRIORITY, which is defined as 1 in dts/arm/nordic/nrf_common.dtsi.  That value of 1 is passed to IRQ_CONNECT(), which adds two to it (for the reasons described above) to get 3.

This is all a lot more complicated than it was with the old nRF SDK.  I hope I haven't missed anything.

  • Which interrupt priority levels can my application safely use when the SoftDevice Controller is enabled? Is anything except for 0 safe? Or should my application avoid levels 0, 3, and 6?

  • What should my application avoid doing at each priority level? Since the MPSL low_prio_irq is level 6, does that mean my application cannot do anything Bluetooth related in interrupt handlers at that priority level or higher (meaning it can only do so in an interrupt at priority 7, or outside of an interrupt)?

Thanks!

Parents Reply Children
  • Hello  !

    Whilst within the Zephyr kernel world, its understood that the thread priorities etc. are used, it would be still good to know what happens outside it. This is especially true if we want to map any customer application specific IRQs, or modify it for some custom purposes. 

    This is for example, relevant in this question -  Boot up without SoftDevice possible? (nRF Connect) . Another example is if we want to use the SoftDevice Controller without the Zephyr Host which is touched upon on this example post- nRF5340 Development Without Zephyr  .

    Do you know if there is any documentation that helps clarify the default IRQ settings on nRF Connect platform? For instance-

    • What is the minimum IRQ settings required for the SoftDevice Controller in nRF Connect to operate correctly? (e.g. owning IRQ priorities [0, 1, 4] like in nRF5 SoftDevice, or has this changed?)
    • Are there any additional IRQ settings used to ensure the Zephyr Host operates correctly, or this is entirely handled by the standard Zephyr kernel IRQs (e.g. SysTick or similar, SVCall_IRQn, PendSV_IRQn)?

    Thank you!

Related