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 Jens,

    I am glad to see you made some progress. The SoftDevice Controller, which is the link layer of the bluetooth stack, depends on MPSL, so MPSL is requiered in this case (if you were making a pure ESB application, there would not be a need for MPSL).

  • Hi Einar,

    yes, I made some progress, but I still cannot tackle the problem entirely. There seems to be ESB- and or BLE "left overs", when I switch between the two protocols.

    Behavior:

    1) Starting up as BLE peripheral works - I can connect and receive notifications and disconnect etc.. Deactivating BLE and starting up ESB works fine, too, but after stopping ESB and switching to BLE I can see the peripheral advertising, but I cannot connect to it. Whenever I try to connect e.g. with LightBlue, the peripheral becomes "invisible" - so advertising seems to stop. I can switch back to ESB though, and ESB works just fine...

    2) Starting up as ESB transmitter, it works fine, but after stopping ESB and activation of BLE I can again see the advertising, but I cannot connect - same behavior as in 1)

    3) Starting up as BLE peripheral, then using the BLE deactivation procedure I implemented seems to stop BLE connections are disabled and no advertising is detectable). Restarting BLE without switching to ESB in between, works perfectly fine. The device works as expected in BLE-mode.

    4) Switching to ESB after starting up as BLE peripheral and connecting to a central and from this state back to BLE, I see an unexpected behavior: The disconnect callback from the disconnect I am doing when shutting down BLE in case the peripheral is connected to a central does not seem to be called before I switch to ESB, but rather after I restart BLE - so I suspect, that not everything is really "clean" after BLE disable - there seems to be a "memory effect". Whatever I do, I can always switch back to a working ESB-transmission.

    The sequences I use are very similar to the one in the example you provided. The only difference is, that I do not simply use bt_disable before I switch, but rather test for an active connection, then disconnect, if there is one. Then I try to stop advertising before I go for bt_disable (but only using bt_disable as in the sample, does not make the application work). My ESB initialization/enable and disable are virtually the same as in the example code.

    There is a statement in the example, that it is important to use the system's work queue for the switch, because it would be cooperative (priority -1).

    // RF Swap workQ
    // So it runs from a cooperative thread. Work thread is cooperative, so calling fxn as work item works. Invoked in button callback in io.c
    

    I did exactly this, but realize, that using this method, I am running the switching task with priority -1 and e.g. the disconnect callback I receive from the BLE stack also runs on priority -1. So it looks like, the BLE-system might be using the same queue here. If the switching task is running in this cooperative way, I guess, some of the ESB and or BLE tasks that are supposed to run via the work queue are blocked until all of the switching steps are completed... could this be the reason for the disconnect or some other tasks related to BLE or ESB do not fully work, if BLE or ESB respectively is stopped, while some tasks are still pending on the system's work queue?

    Another statement in the example' readme, that I do not fully understand is:

    "Channel selection: 2Mbps PHY wants a 1MHz channel separating each device. So start from channel 2, and have a channel in between. (1M PHY no lower than ch1, 2M ch2 or higher, ensure enough margin on higher end of channel spectrum close to 2483.5 MHz ISM band edge.) independent channels are not necessary for this application, but I included it anyway."

    Does the selection of channels have any effect on the switching or can I safely assume, that if ESB works for itself (as it does), that I can safely expect to switch using the 2Mbps PHY?

    By the way, I am developing under nrf Connect SDK 2.4 - so not the very latest version, while the sample seems to have been developed for 2.6. Is there any different switching behavior to be expected out of that version difference?

    Any additional advice is very welcome!

    Regards,

    Jens 

Reply
  • Hi Einar,

    yes, I made some progress, but I still cannot tackle the problem entirely. There seems to be ESB- and or BLE "left overs", when I switch between the two protocols.

    Behavior:

    1) Starting up as BLE peripheral works - I can connect and receive notifications and disconnect etc.. Deactivating BLE and starting up ESB works fine, too, but after stopping ESB and switching to BLE I can see the peripheral advertising, but I cannot connect to it. Whenever I try to connect e.g. with LightBlue, the peripheral becomes "invisible" - so advertising seems to stop. I can switch back to ESB though, and ESB works just fine...

    2) Starting up as ESB transmitter, it works fine, but after stopping ESB and activation of BLE I can again see the advertising, but I cannot connect - same behavior as in 1)

    3) Starting up as BLE peripheral, then using the BLE deactivation procedure I implemented seems to stop BLE connections are disabled and no advertising is detectable). Restarting BLE without switching to ESB in between, works perfectly fine. The device works as expected in BLE-mode.

    4) Switching to ESB after starting up as BLE peripheral and connecting to a central and from this state back to BLE, I see an unexpected behavior: The disconnect callback from the disconnect I am doing when shutting down BLE in case the peripheral is connected to a central does not seem to be called before I switch to ESB, but rather after I restart BLE - so I suspect, that not everything is really "clean" after BLE disable - there seems to be a "memory effect". Whatever I do, I can always switch back to a working ESB-transmission.

    The sequences I use are very similar to the one in the example you provided. The only difference is, that I do not simply use bt_disable before I switch, but rather test for an active connection, then disconnect, if there is one. Then I try to stop advertising before I go for bt_disable (but only using bt_disable as in the sample, does not make the application work). My ESB initialization/enable and disable are virtually the same as in the example code.

    There is a statement in the example, that it is important to use the system's work queue for the switch, because it would be cooperative (priority -1).

    // RF Swap workQ
    // So it runs from a cooperative thread. Work thread is cooperative, so calling fxn as work item works. Invoked in button callback in io.c
    

    I did exactly this, but realize, that using this method, I am running the switching task with priority -1 and e.g. the disconnect callback I receive from the BLE stack also runs on priority -1. So it looks like, the BLE-system might be using the same queue here. If the switching task is running in this cooperative way, I guess, some of the ESB and or BLE tasks that are supposed to run via the work queue are blocked until all of the switching steps are completed... could this be the reason for the disconnect or some other tasks related to BLE or ESB do not fully work, if BLE or ESB respectively is stopped, while some tasks are still pending on the system's work queue?

    Another statement in the example' readme, that I do not fully understand is:

    "Channel selection: 2Mbps PHY wants a 1MHz channel separating each device. So start from channel 2, and have a channel in between. (1M PHY no lower than ch1, 2M ch2 or higher, ensure enough margin on higher end of channel spectrum close to 2483.5 MHz ISM band edge.) independent channels are not necessary for this application, but I included it anyway."

    Does the selection of channels have any effect on the switching or can I safely assume, that if ESB works for itself (as it does), that I can safely expect to switch using the 2Mbps PHY?

    By the way, I am developing under nrf Connect SDK 2.4 - so not the very latest version, while the sample seems to have been developed for 2.6. Is there any different switching behavior to be expected out of that version difference?

    Any additional advice is very welcome!

    Regards,

    Jens 

Children
No Data
Related