Simplest nRF53 dual-core ESB communication?

I want to receive a few bytes over ESB on the NET core, and then forward those values to the APP core to dim a few PWM LEDs.

I thought this would be a good basic beginner's project to apply several previously learned concepts and integrate them into cohesive working code, but I'm already staring down a warren of rabbit holes so deep and blitheringly complicated that I just want to crawl back in bed.

I can dim PWM LEDs on the APP core. Easy.

I can receive bytes over ESB on the NET core. Solved.

But now I face the daunting task of not only choosing one of several bewildering and competing inter-core communication protocols, but also deciphering how to compile and flash multiple CPU images using the staggering Sysbuild, and once again the exhausting learning curve in front of me seems many more distant moons away.

Can Nordic please define the simplest path forward, so that I'll fail miserably in just a few weeks this time, instead of the typical months it usually takes me to accomplish nothing?

Just a few bytes, in one direction, from NET to APP.

Parents
No Data
Reply
  • I spent the entirety of my weekend buried in documentation, trying to make sense out of the dizzying number of disparate options. Nordic fails to helpfully summarize this information anywhere that I could find, so for those following along from the future, here's what I've learned so far.

    The nRF53 has an IPC peripheral that allows communication between its APP and NET cores. At the register level, this uses PPI and interrupts to pass messages and events, but is unwieldy to manage directly, especially for complex scenarios.

    The next layer up is the nrfx_ipc driver, which conveniently manages the setup and configuration of the registers, and also provides functions for sending and receiving signals on the PPI channels, but is of course proprietary to Nordic hardware.

    Zephyr's ipc_service is the highest level layer and uses nrfx_ipc internally when appropriate, and also manages several communication backends: the simpler and lightweight icmsg variants, and the more featureful (albeit heavier) OpenAMP-based rpmsg.

    The absolute simplest is plain icmsg, which only offers a single endpoint (or channel) between cores, and consumes the fewest resources, however it does require some small devicetree changes as it's not the NCS default.

    Built on top of this are icbmsg and icmsg_me, which add additional functionality such as no-copy features (using a shared memory buffer) and multiple endpoints.

    Finally there's the NCS default rpmsg, which is the path of least resistance as it's already configured in devicetree, and offers all of the above features at the expense of more resources and complexity. This uses static_vrings and virtqueues memory structures, and is built on top of OpenAMP (which is an entire rabbit hole unto itself).

    The NCS IPC Service sample demonstrates both the default rpmsg and the simpler icmsg backends, as well as the devicetree modifications needed for the latter, while Zephyr also has several IPC Samples that showcase its sundry options.

    The appropriate choice from all of these is apparently left to the user.

Children
  • I was going through the ipc_service example to attempt to help you out because your candor suggested kindred spirt. It wasn't working for me, so I decided to "edgemecate" myself on sysbuild to figure out why the example wasn't working... then attempting to run through devacadamy to get a clue on sysbuild ... 
    Finally realized I was at work and this wasn't a priority for me ... but ...you know the saying "the thought that counts?" or in my case the road to hell is paved with good intentions. 

    Glad you learned something and thanks for your description. I hope you can move forward from here.
    A M

Related