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

Parents
  • Hi,

    There is an unofficial sample here which demonstrate using either BLE or ESB, swithing between the two but not running it concurrently: https://github.com/droidecahedron/esb_multi (esb_prx_blefallback).

  • Hi Einar,

    thank you very much for this sample, which looks very understandable on first sight. I already have noticed differences in configuration, that are influencing the behavior of my code significantly.

    Above sample uses two config parameters that I have not noticed in any other blue-esb sample before:

    CONFIG_BT_UNINIT_MPSL_ON_DISABLE=y

    CONFIG_MPSL_DYNAMIC_INTERRUPTS=y

    Adding these two to my prj.conf for the MPSL-case solves the underlying problem, that the software crashes on the first write call to ESB-radio. If I do not enable BLE in my code, but have BLE configured, I now can safely run ESB communication and the other way around. So: one step ahead already! 

    I still need to look deeper into switching back and forth between protocols though. 

    Unfortunately I still do not completely understand, why I need to use MPSL in this at all, but it looks to me like the bluetooth implementation uses MPSL „implicitly“ - so some MPSL is active as soon as BLE is enabled… and I „actively“ need to have the system disable MPSL, if I have BLE configured, but need to use the radio in any other way.

    I would really appreciate, if you could explain the need for MPSL in this use case in a few words, because I probably will need to understand the configuration a little more in depth for further trouble shooting.

    Thanks a lot for your explanation in advance!

    I will let you know, if I can solve my switching of protocol topic completely with the help of this sample or if I need further assistance on this.

    Regards,

    Jens

  • Hi Einar,

    thanks for your comments. I am actually glad, that you run into similar problems using SDK 2.4... because that tells me, that the behavior is reproducible and depending on SDK version.

    Unfortunately so far I have not been able to resolve the issue, but I made the disconnect execute in the correct sequence by adding delays and setting up in chained work queue tasks for the switching process, containing one step per work function. I added some additional logging via CONFIG and from my code, e.g. for the radio register contents etc., too, but do not see any hint for the root cause of the problem, that I would interpret as such.

    I still do not understand, why the peripheral can advertise, the central can start to communicate for connection (without success) and then advertising stops. Why do I see no logging entry whatsoever on my peripheral - because the peripheral obviously has gotten some attempted communication from the central, because it stops advertising. Is there anything I can debug better than via logging? Which logging CONFIG could help to produce an output when a connection is attempted?

    There are three reasons for me not updating to a newer version (yet):

    1) My main sensor project and the custom hardware I am working on has been designed (and working for older use cases), when SDK 2.4 was fairly current => I thought: never change a running system, if there is no reason... as long as the development is still fairly experimental...

    2) The MacBook I am developing this software on is running MacOS 13 still, because of some legacy applications (not related to this project) I am using that are not released for newer MacOS versions... and the current nrfConnect SDK-versions are requiring newer MacOS versions...

    3) My experience of updating to a newer SDK-version (like the switch from 1.7 to 2.x). It took me quite some time to understand, what needed to be done in my device tree definition for my custom boards and the CONFIG parameters... so I thought, I would directly try to migrate to some version 3.x ... but then, the samples are done on the basis of 2.6 and I would not know, if they work on 3.x either...

    Do you foresee any problems with the sample on SDK v3.x version? If you could do a quick try out and confirmation, that updating to v3.x solves my problem, I would very much appreciate it, probably go the stony way of updating to a version 3.x... and look into a solution to my "reason 2)" above...

    Nevertheless I would really like to more deeply understand what is not working in the current setup - just to understand the topic as deeply as possible to be able to better help myself in the future. I think, the difference between 2.4 and 2.6 with respect to this behavior should be explainable... and maybe shed some more light into the internal processes in the bluetooth driver for me?

    Thanks for your support. I am looking forward to your reply!

    Regards,

    Jens

  • Hi Einar,

    I found out, that sdk v2.6.4 seems to be the last version released for my MacOS 13. Therefore I upgraded to v2.6.4. After finding out, how to make it work after this upgrade (I had to configure to disable the partition manager), unfortunately at first the behavior of my software did not change at all.

    But then I remembered the following in 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!");

    In sdk v2.6.4 this tweak seems to improve the situation: I changed these 2 entries to SWI3 within the sdk-file esb_peripherals.h.

    I had tried that before in sdk v2.4... but saw no change - and changed back, because of this.

    So far, however, this seems to be unstable for ESB-transmission in my setup, though - after some messages are transmitted, the transmission stops and restarts again after swapping to BLE and back. I will have to take a look into this, of course. BLE seems to run stable now...

    But, I really do not like to fiddle with sdk files like this. Is there any other way of changing this behavior without changing sdk files?

    Thank you very much in advance for all further advice!

    Regards,

    Jens

  • Hi Einar,

    I believed I solved my instability problem. It seems to have been due to extremely heavy logging tasks for BLE and elsewhere in my code (left overs from debugging this problem) leading to race conditions and blocking. After deactivating most of the logging, so far my software seems to be stable over the limited time I have been testing now.

    So, the only thing left is the necessary change to the SDK file "esb_peripherals.h". Is there any better approach than to fiddle with the SDK files?... or, if this is the only way to solve it in v2.6.4, a fix in SDK versions after v2.6.4?

    Thanks for an answer and perspective to this final question related to this thread. I do not feel too confident with this SDK-hack for the long term.

    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

Reply Children
No Data
Related