Is there a way of running BLE on the network core only on nRF5340?

Hi,

I am trying to optimize a time critical device for lowest possible latency data transmission over BLE on nRF5340 working as peripheral.
Currently my algorithms are implemented completely on the app core side of the device, while I use the original hci_rpmsg on the net core.

When I analyze my HW-signals on both ends of the BLE-transmission with an oscilloscope I mostly find a jitter in the range of the connection interval - as I expected.
Occasionally I do find outliers, though... and I see that bt_gatt_notify on the app core seems to sporadically "get stuck" for a while and "recover" after a delay...

...adding significant latency.

Since I do not understand the reason for this behavior, but need latencies as short as possible and especially as reproducible as possible for transmission and also execution on the app core, I looked into inter-core communication and alternative networking options on the nrf5340 and found, that there could also be a reduction of the connection interval with llpm-service and ESB as alternative lowest latency options.

If I could implement a very small inter core communication (in my application the size of the data to be exchanged would be very small) and a "single core" BLE implementation on the network core, I would hope to be able to achieve:

1) least overhead and uncertainty of "notify-duration" for radio communication on the app core side, which is time critical

2) a complete logical split between the radio relevant part and my time critical algorithms with least interferences to be expected

3) I could implement different options on the network side, to be used with different centrals (like llpm, if possible, BLE standard etc...)

Therefore I would like to ask for advice before I go on a mission impossible...

a) Is it possible to have a BLE-implementation 100% on the network-core side of the nrf5340? (I do not see any technical reason against this, because the net core should be fast enough - if nrf52840 can run BLE stack and controller on one core) - What would be reasons against this way of splitting?

b) Why does llpm not work for nrf5340 according to the documentation - is that related to the split core architecture?

c) Would llpm and ESB work on a single core (net core only) implementation on nrf5340?

Im am looking forward to your advice!

Regards,

Jens

Parents
  • Hi Jens,

    The netcore should handle all the realtime requirements of the BLE connection, so even though the host still run on the application, there should be no realtime requirement by the host that should prevent the application to have the highest priority for the nRF5340, so if you observe that the application interrupt do not behave as you expect (e.g. have jitter), I suspect you may need to adjust the priority of the thread you want to run in the application. How much jitter do you observe or how much jitter can you allow?

    If you want to have even better control you may need to look at using the low level nrfx drivers:
    https://docs.nordicsemi.com/bundle/nrfx-apis-latest/page/nrfx_drv_supp_matrix.html 
    https://docs.nordicsemi.com/bundle/nrfx-apis-latest/page/nrfx_examples_desc.html 

    Kenneth

  • Hi Kenneth,

    thanks for your reply. I was not expecting to see any large jitter (>> the connection interval) for my device, but I actually do observe it. The reason for choosing nrf5340 was to decouple the transmission via standard BLE (or other radio protocols) from my time critical application, which essentially requires to be in the range of 1ms in a loop reading sensors and every now and then sending a notification. In >>99% of the cases everything on the application side works as expected and the notification takes between 50 and 120 µs on the app core. Unfortunately every now and then the notify takes far longer even though I have only the main thread running from my application side and a cyclic hardware interrupt firing regularly but not firing in the first 200µs after calling the notify... so this interrupt should not be the original cause of my jitter problem.

    I implemented a simple IPC communication from app core to net core instead of the notify and that runs "rock steady" with no jitter to speak of and no outliers always taking less than 50µs on the app core. Of course I needed to replace the net-core by an IDC-service code... which gave me the opportunity to better understand the communication and also to use some gpios on the net core side for oscilloscope "debugging".. and, I obviously disabled BLE...

    => so, if I would be able to either:

    a) debug and measure the communication between app core and net core in the BLE case (which would mean changing the hci_rpmsg code to e.g. control some gpio pins for oscilloscope measurements) I might be able to better understand the source of the problem.

    or preferably:

    b) use my simple IPC communication to decouple app core and net core and then have something different from the "standard" hci_rpmsg on the net core, I would be able to keep my inter core communication absolutely the same no matter which type of radio protocol I implement on the net core (standard BLE, llpm or ESB - if possible on the nrf5340 net core only) as alternatives for different communication partners.

    I would like to try your suggestion on adjusting priorities, if that could solve my problem in case a). Since my work loop code runs in the main thread, I assume it will have priority 0, because I do not actually assign a priority to it. That leads to two questions

    => how do I change priority? I guess I would need to create a thread to run my application's critical loop and assign some priority to it, or can I change the priority of the main thread?

    => since whatever is interrupting the notify function is not a thread or interrupt I explicitly created from my application side, I assume it is somehow related to a zephyr driver ... maybe BLE?
    --> So: how do I find out, what is causing the effect
    --> So: which priority level should I assign to my work loop?

    To give you some background to my latency and jitter requirements:

    The possible applications of my device depend on the total transmission latency of the chain. It would be top notch to reach something stable below 3 ms, most applications would still tolerate 10 ms , which could be reached with a 7.5ms connection interval, if communication errors would occur next to never and a few use cases will also work with up to 20 ms.
    If it would be possible to have a choice of protocol depending on the capability of the radio-communication partner, it would be ideal for my device.

    In short:

    1) I would like to reach latencies and jitter both in the range of 1 ms (ESB or llpm) to be able to stay below 3 ms always.

    2) I absolutely need to reliably have maximum latencies of 1 connection interval + 3 ms (BLE)

    With a BLE central capable of 7.5 ms connection interval and no other communication going on in parallel, I currently see the following (this central can reliably communicate with a BLE peripheral in less than 10ms):
    very often the transmission takes <(1 connection interval + 3ms), but not always... sometimes the transmission needs up to (2 connection intervals + a little bit) using my application on a nrf5340dk or on my own custom device.

    Unfortunately I do not exactly understand your reference to the nrfx drivers. The links do not really lead to pages with a detailed description but a list of all drivers supported. Could you please tell me, which drivers would be relevant to solve my problem of core communication and/or BLE on the nrf5340?

    Thanks for your advice.

    Regards,

    Jens

  • Hello,

    You are free to solve this with whatever approach you are most comfortable with, I know everyone have their own preferences. Here is in any case my input.

    We have a few tutorials in general for the nRF Connect SDK:
    https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/  
    https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/ 
    https://academy.nordicsemi.com/courses/bluetooth-low-energy-fundamentals/ 

    In your case I would in specific check out the "Thread Viewer" further down on this page:
    https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-2-debugging/topic/debugging-in-vs-code/ 

    Then you can see the priority of all the threads running in the appcore, and configure the thread you want to run to be either higher or between the existing threads running.

    Unfortunately the priorities with negative value are cooperative threads, which once started can't be preempted, not even by higher priority threads. That said, those cooperative threads should be short by design, I would not expect them to block more than potentially a few hundred of us in worst case.

    It's an option to have the algorithms run in a thread with high priority, and then each time you want to send data you transfer that to a work queue to handle the bt_gatt_notify().

    The only thing I can think of that may block in the tens of ms is if you are doing flash operations, such as storing data to flash, which may indirectly trigger erasing flash pages, moving around data in flash etc, this will take a long time, but this should only occur for instance shortly after bonding, or if you are supporting multiple bonds, it may also occur if you have enabled BT_KEYS_OVERWRITE_OLDEST shortly after connection is established.

    All that said, an alternative is to look into this example:
    https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/samples/bluetooth/rpc_host/README.html 

    The problem with the RPC example is that it's experimental, and as it says in the Note: "Currently, only a subset of Zephyr’s Bluetooth APIs is available over Bluetooth nRF RPC. For more details about the limitations, see the API documentation of the Bluetooth nRF RPC library."

    Unfortunately it's been "Currently" for quite some time, so I don't expect it will change anytime soon.

    An alternative approach you may consider is to switch to the nRF54L15, which provide a risc-v CPU that can run whatever you want, completely uninterrupted: 
    https://docs.nordicsemi.com/bundle/ps_nrf54L15/page/vpr.html 

    You can then use mbox to transfer data between the application core and the risc-v cpu core:
    https://docs.nordicsemi.com/bundle/ncs-latest/page/zephyr/hardware/peripherals/mbox.html 

    Example project:
    \zephyr\samples\drivers\mbox

    Personally I would have checked out the nRF54L, since it's our latest development platform, with a range of devices in the roadmap (reach out to someone in sales if there are specific features you are interested in that is not part of the nRF54L15, use contact us and sales related questions: https://www.nordicsemi.com/About-us/Contact-Us). LLPM is also supported by the nRF54L, which have far better latency than normal BLE due to 7x interval. Of course if you have got far in development with the nRF5340 that is not an option.

    Hope it helps,
    Kenneth

Reply Children
No Data
Related