How to software-switch between ESB and BLE on a nrf5340 net-core?

Hi,

I am working on a sensor device that requires very accurate timing on the sensing and sensor signal algorithm side. This device needs a low latency and low jitter radio transmission in one use case (A) sending very low volume of data (send to receive < 1ms) and another use case (B) with a lot higher data volume but less strict requirements on latency and jitter. The device should be able to switch back and forth between these two use cases via a push button on the device.

I chose nrf5340 for this device, because with its two cores I can keep my sensor-algo on the app core and (almost) independently have all radio operation on the net core.

My implementation keeps all app core (sensor) code the same for both use cases, sending messages to the net core via IPC. All difference between (A) and (B) is implemented in the software running on the net-core. Aside from some small part of the code processing the IPC-messages use case specific, the main difference is, that use case (A) uses ESB (Enhanced Shock Burst) for radio transmission and use case (B) uses BLE.

Currently I have successfully implemented use case (A) and use case (B) - but I only can build and successfully run the code for use case (A) by using one set of config parameters and (B) by using a different set of config parameters and select the code to be compiled by #if statements depending on config parameters.

As soon as I try to enable BLE and ESB at the same time, I need to activate MPSL and dynamic interrupt config parameters - as in the unofficial sample code for using both protocols concurrently. This, however, leads to interrupt problems with operating IPC or build problems, that I am not able to solve - and especially, that I do not understand the need for.

My question: Is there a way to build and run for BLE- and ESB-use alternatively instead of concurrently, while being able to switch between these protocols without restarting or reflashing the device... and, if possible, without the need for MPSL or dynamic interrupts?

To really keep the lowest possible jitter and latency, my pure ESB-implementation, which currently runs with latency far below 1 ms, should be able to run while BLE completely is inactive for use case (A). When the button is pressed, the device should completely switch off ESB and start BLE-operation and vice versa.

I have seen some questions similar to mine, but was not able to find a simple and solid solution without the use of MPSL and dynamic interrupts etc...keeping the great latency performance of IPC + ESB in my critical use case (A).

Thank you very much for any advice you can give me.

Regards,

Jens

  • Hi Jens,

    Thank you for letting me know that you see this working in a stable way now. As you write, the interrupt number is currently hard coded so you will have to modify the SDK code for now. But I have made an internal ticket so that this can be updated to be configurable in another way in the future.

    Br,

    Einar

  • Thank you, Einar!

    So solution for my case in short is now: 

    - use no older than SDK v2.6.4

    - take the CONFIG parameters e.g. from 

    - change the interrupt number in the esb_peripherals.h of the sdk as can be read in the warning message in this other sample (which will not be necessary as "SDK hack" after your internal ticket has been resolved):

    https://github.com/too1/ncs-esb-ble-mpsl-demo/blob/master/app_netcore/src/main.c:

    LOG_WRN("Change ESB_EVT_IRQ and ESB_EVT_IRQHandler in esb_peripherals.h to use SWI3 instead of SWI0!");

    - take care to actively give other threads "enough room to execute" by scheduling the swap steps in tasks for the system work queue of zephyr (executing with prio -1).

    - do not use excessive logging ;-) if you do not want to run into stability problems...

    So much for now - and thanks again! Solved from my perspective.

    Jens

  • Hello Jens,

    i have mainly extracted the worker and the two Kconfigs from the esb_prx_blefallback example and the switching between BLE and ESB works like a charm without any errors until now. 

    @ Einar, thanks for sharing this example.

    I'm starting with ESB PTX and switch via button to BLE and back. in my case there were no "leftovers" from any stack. 

    Really happy with this solution, that I can continue my research. 

    Thanks for all of your help, information and explanations.

    Best regards,

    Robert

  • I am looking at the code for SDK v3.3.0-preview, and it's still SWI0. Why is that?

    #if defined(CONFIG_SOC_SERIES_NRF54H)
    
    	/** The ESB EVT IRQ is using EGU on nRF54 devices. */
    	#define ESB_EVT_IRQ_NUMBER EGU020_IRQn
    	#define ESB_EVT_USING_EGU 1
    
    	/** The ESB Radio interrupt number. */
    	#define ESB_RADIO_IRQ_NUMBER RADIO_0_IRQn
    
    	/** DPPIC instance number used by ESB. */
    	#define ESB_DPPIC_INSTANCE_NO 020
    
    	/** ESB EGU instance configuration. */
    	#define ESB_EGU NRF_EGU020
    
    	/** Use end of packet send/received over the air for nRF54 devices. */
    	#define ESB_RADIO_EVENT_END NRF_RADIO_EVENT_PHYEND
    	#define ESB_RADIO_SHORT_END_DISABLE NRF_RADIO_SHORT_PHYEND_DISABLE_MASK
    
    	#define ESB_RADIO_INT_END_MASK NRF_RADIO_INT_PHYEND_MASK
    
    #elif defined(CONFIG_SOC_SERIES_NRF54L)
    
    	/** The ESB EVT IRQ is using EGU on nRF54 devices. */
    	#define ESB_EVT_IRQ_NUMBER EGU10_IRQn
    	#define ESB_EVT_USING_EGU 1
    
    	/** The ESB Radio interrupt number. */
    	#define ESB_RADIO_IRQ_NUMBER RADIO_0_IRQn
    
    	/** DPPIC instance number used by ESB. */
    	#define ESB_DPPIC_INSTANCE_NO 10
    
    	/** ESB EGU instance configuration. */
    	#define ESB_EGU NRF_EGU10
    
    	/** Use end of packet send/received over the air for nRF54 devices. */
    	#define ESB_RADIO_EVENT_END NRF_RADIO_EVENT_PHYEND
    	#define ESB_RADIO_SHORT_END_DISABLE NRF_RADIO_SHORT_PHYEND_DISABLE_MASK
    
    	#define ESB_RADIO_INT_END_MASK NRF_RADIO_INT_PHYEND_MASK
    #else
    
    	/** The ESB event IRQ number when running on the nRF52 and nRF53 device. */
    	#define ESB_EVT_IRQ_NUMBER SWI0_IRQn
    
    	/** The ESB Radio interrupt number. */
    	#define ESB_RADIO_IRQ_NUMBER RADIO_IRQn
    
    	/** ESB EGU instance configuration. */
    	#define ESB_EGU NRF_EGU0
    
    	/** nRF52 and nRF53 device has just one kind of end event. */
    	#define ESB_RADIO_EVENT_END NRF_RADIO_EVENT_END
    	#define ESB_RADIO_SHORT_END_DISABLE NRF_RADIO_SHORT_END_DISABLE_MASK
    
    	#define ESB_RADIO_INT_END_MASK NRF_RADIO_INT_END_MASK
    
    #endif

  • Hi,

    You are right, this is still not configurable in the SDK. We have a ticket to fix it at some point, but I cannot say when. For now you need to modify this in the ESB implementation as described earlier in this thread.

Related