NRF5340: zephyr child image image build issue.

Hello.

Hardware setup    NRF5340DK
Base Application ipc_service
IDE CLion


I'm facing a rather embarrassing issue. I've been using CLion to develop embedded software since I first got into MCUs. Needless to say, my productivity takes a nosedive whenever I'm forced to use another IDE. I'm now working on a project centered around the 5340. I created, build and flashed the ipc multi-core sample using Visual Code, than "imported" the project into CLion. Everything works, the image builds accordingly, it runs as expected, but with a tiny hiccup. Because CLion uses the top-level CMakeLists.txt to index the project, it doesn't "see" the child image. Because of the zephyr's arcane build system, CLion fails to detect the child CMake, ergo every file in the child image is seen as not being part of the project.

I know what I'm asking is technically not your concern - your official hardware & software combination works, but would you guys be so kind as to help me link the child image via the main CMake file only? Without using zephyr's rather arcane build system? Right now, I'm guessing the child image gets linked via the yml / hci folder - I think that's basically a zephyr module.

Or, another possible solution would be a link/ tutorial about how to build a net core app and a main core app completely separately and then merge them together. I must confess, I've crawled this support forum up and down, read the docs - I can't, for the life of me, figure out how to actually do that.

Thank you kindly for your time (and for all the detailed forum posts, made by your coleagues, that got me this far).

  • Hi Paul,

    I've looked around and unfortunately I couldn't find anything on how to do this outside the Zephyr build system.

    I'll leave this thread open, hopefully someone else on this forum have some tips on how to do this,

    regards

    Jared 

  • Hello Paul,

    While I won't have a working solution to your CLion, Zephyr "dual app" import situation, I may be able to offer an idea in a useful direction.  I'm not familiar with Jetbrains or their CLion IDE, but I have been working with a dual core ARM processor and Zephyr v3.4.0 as the scheduler/RTOS on each of the two cores in my team's chosen microcontroller.

    The first dual-core Zephyr application I succeeded in building, flashing and running is the IPM or inter-processor mailbox sample app from Zephyr v3.2.0.  That version of Zephyr has the sample app structured with a parent project for the first core and a child project for the second one.  In a couple of this sample app's `cmake` files I think these are also named "local project" and "remote project".

    The remote project seems to be in a way subservient to the parent project.  One of the final build steps involves concatenating the image for each core.  Because the project cmake files specify building "dot bin" final executables, the merging of the two cores' images here required a special tool `srec_cat` which is not part of Zephyr's standard toolchain.  That was mentioned in the sample app README or nearby, but still represents a more complex build process than typical.  I imagine this could also create a gap in needed build utils which CLion might need to call during multi-core (multi-project) builds.

    More recently my team migrated our project to Zephyr v3.4.0, which changed and simplified a dual-core sample project.  The new multi-project hierarchy has each project as its own stand-alone project.  One is not the child of the other nor the parent.  We ended up writing a short shell script to build each project in turn, and adjusted final output format to Intel hex file format.  This permits us to merge the two cores' images with `mergehex`, which seems a little more commonplace than `srec_cat`.

    The shell script accepts a couple of options:  one to build the projects, and one to flash them to the target hardware.

    I know that you're not looking to write and use shell scripts, but this has been a clear and straightforward solution for our team.

    To that point I am building on a Linux host using the standard Zephyr toolchain described at Zephyr's Getting Started Guide.  I think that's the arcane piece you refer to in your post.

    So I wonder whether CLion supports building two or more apps with two or more final executable files as final output?  If you can build the two projects you would possibly just have that step of merging each core's image file into a single combined image.  Then CLion should be able to call your programming utility and carry out the flash operation as normal.

    I realize that you may be obtaining your Zephyr release as part of Nordic's `ncs` SDK.  That might make it hard to move to Zephyr v3.4.0.  But even if you stay with a Zephyr release earlier than 3.4.0, if you can find a way to build parent and child projects as stand alone projects and confirm that the binaries before merging are the same as building in the original way, then you may be able to manually move files outside of CLion and create stand alone projects which could then be imported one per time into a "multi project" CLion project.

    Paul I'm sorry I do not have time to install and learn CLion.  But perhaps something here can help you to a useful next question or next step toward a solution for your work.

    - Ted

  • First off, thanks for the detailed answer and the idea. Actually, regarding the shell scripts, I'm not above putting in work - one hour spent writing a utility now saves dozens in the long run.

    I was thinking along the same lines: whip up a quick c# console app  that will *somehow* handle the build process - to complement the built-in capabilities of cmake.
    I think I'll go with an (empty) top-level cmake that adds two subdirectories. Each is a stand-alone application that will get burnt on the flash in the required order: app, network core, reset. Seems the most reasonable, by far. nrfjprog to the rescue.

    I must confess, I got seriously spooked by west + zephyr + python and I didn't exactly get what happens under the hood, once you hit that build button.

    And with a single character changed in one of the myriad of files .conf, dts, dtsi, fragments, kconfigs etc, everything gets rebuilt. And it taskes forever. So, and for any trivial task, for a zephyr beginner) there go another 12 hours.

    Right now I'm using an empty app image core and I have a standalone firmware I'm working on for the network core.

    Cmake handles the building, a c# script handles the burning of the images. The next logical step would be including a simple hello world app for the main core and editing the project *.conf file to boot the net image. If I'm not mistaken, the relevant config is

    CONFIG_BOARD_ENABLE_CPUNET=y

    What I don't understand is where does mergehex factor into all this. Is it simply to have one convenient image a flasher "knows" where to put? Does it serve any other purpose?

  • Hi Paul,

    I think you already know so, but a concatenating utility such as mergehex is not required to program applications to be run by each core in a multi-core target processor.  Mergehex "fits in" the build sequence very near the end, just before programming.  The flasher actually doesn't know more or less from `mergehex` or `srec_cat`.  With a merged image the flashing utility simply has one thing to flash rather then two or more.

    One important benefit however of a combined image is that the flashing of all cores' code is time contiguous.  The target MCU is held in a reset state until the combined image is flashed and verified.  As a result the processor does not boot up after the first core is flashed.

    This is to say that when flashing images separately to a multi-core target there will likely be a couple to few seconds where the first core begins running its latest image and the next core begins to run the older image.  We've seen this happen when we flash images separately -- no mergehex used -- and we need to be cautious in this situation that our hardware and firmware are electrically safe for those few seconds, running the differently versioned apps.

    I don't know anything about C#, which I thought was a programming language rather than a scripting or shell oriented language.  But it sounds like you are on your way. 

    A couple years ago I was asked to get our project then building both at command line with Zephyr toolchain and Segger Studio, which has a python based "import project" applet.  That importer worked most of the way, but if I ever added source files or created new project directories and moved sources, headers, cmake files and related, I had to re-import the project into Segger IDE all over again.  I found the python script which I believe was part of a special version of Segger with support for Nordic ncs SDK projects.  But from what I understand of cmake and of IDEs, they're both aiming to support and control the same "high level down to detailed levels" project configuration.

    For this reason I don't know that there's a clean, intelligent way yet among any of the IDEs to import a Zephyr based application.  The dual-core Zephyr based apps add a wrinkle to this, so yours is a "challenge question" for sure.

    I'll keep this Devzone post bookmarked because I am interested to learn your solution.  Even if I don't have need of CLion.

    Good weekend to you, and keep safe Paul,

    - Ted

  • 1. This is the first dual-core MCU I've actually used. Up until this point I've never had the opportunity (or the need) to work with multi-image builds. All the multi-core mcus I've used were flashed with a vendor binary. It would have been possible that the merge-hex tool also "formatted" the image. By that I mean, insert special markers or whatnot - like NXPs tools for the MIMX RT's do when you run binaries off SD/MMC cards (god, that's awesome). So, thank you for clearing that up for me.

    2. That's something I didn't think of. And, truth be told, the scenario is not acceptable. Electrical damage aside (highly unlikely, I would think), what if you're performing an upgrade and the filesystem running on an external flash gets blown to bits because it so happened the mcu was writing to the boot sector of the flash? Or, gods forbid, something regarding encryption/ persistent settings etc.

    3. Well, you are correct, .Net is basically java. Only more beautiful and better structured. But the new console templates (.net 6 and above, i think) have basically the same structure as a regular script.

    Anyway, I won't take up any more of your time. Thanks again for all the insights and help! And I will post my final solution here (god, that came out wrong).

    Have a great weekend, sir!

Related