Hi all,

I made the following post on devzone but perhaps this is a better place to begin:
https://devzone.nordicsemi.com/f/nordic-q-a/106115/difficulty-creating-a-zephyr-based-nrfconnect-project-within-vscode-that-contains-a-custom-sensor-driver

Here’s my situation. I want to make a simple, stupid “hello world” like SPI driver for a sensor chip, for example the IIS3WDB SPI based vibration sensor so I can read accelerations, etc. This chip isn’t part of Zephyr’s library, so I want to use an out of tree method. I have VSCode, the nRF SDK (2.5.0 for SDK + toolchain). I tried cloning a Zephyr example application that includes device tree bindings for a fake driver called “examplesensor.”
git clone https://github.com/zephyrproject-rtos/example-application my-app, then opening the my-app/app folder and configuring the build chain.
I added an overlay to this app to enable “examplesensor0”.

/{
    examplesensor0 {
        compatible = "zephyr,examplesensor";
        input-gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    };
};

The structure of my_app contains an “app” folder then the device tree/bindings and driver folders as well.

When I try to build the app it fails here:

../src/main.c: In function 'main':
/opt/nordic/ncs/v2.5.0/zephyr/include/zephyr/device.h:85:41: error: '__device_dts_ord_DT_N_NODELABEL_examplesensor0_ORD' undeclared (first use in this function)

however the overlay references examplesensor0.

Clearly this isn’t working off the bat.

Is there a working example project that is compatible with nRF SDK that contains an example application and external driver complete with dts bindings that one can simply download, open, and build that contains both an app and a drivers/sensor/mysensor? I don’t want to modify the Zephyr source and put my driver in the tree in my own branch, that doesn’t make sense.

In addition, what architecture/directory structure is most commonly used and easiest to configure? 1(A), 1(B), or 2?

(1) Package my app with my sensor driver, in which case do I put my app at the same level as the driver, or put the driver within my app directory
Example:

(A)

my_app
---app
     ---src
     ---drivers/sensor, yaml, dts, CMakelists,etc

or
(B)

my_app
---app
     ---src
 ---drivers/sensor,yaml,dts,CMakelists,etc

2: have an app workspace that is separate from custom sensor driver (how do you link that in?) and also separate from Zephyr and nRF SDK

Best,
Josh Karch

    Hey @jkarch

    Have you watched these videos?

    https://www.youtube.com/watch?v=63YXMZtovLw
    https://www.youtube.com/watch?v=qalO_vmipJk

    You will need to create the DTS bindings for your particular driver. You can put project specific dts bindings in <your app base>/<your app>/dts/bindings/ You may have some luck looking for an already developed existing driver and model yours against it. (Bindings end in .yml)

    If you want to make your project also a library then it will need a <app base>/zephyr/module.yml in order to recognize any library code. Generally you put a Kconfig and CMakeLists.txt

    Here’s an example where the nrf9160 folder is an app for the nRF9160

    ❯ tree -L 3
    .
    ├── nrf9160
    │   ├── boards
    │   │   ├── circuitdojo_feather_nrf9160_ns.conf
    │   │   └── circuitdojo_feather_nrf9160_ns.overlay
    │   ├── child_image
    │   │   └── mcuboot
    │   ├── CMakeLists.txt
    │   ├── drivers
    │   │   └── zephyr
    │   ├── dts
    │   │   └── bindings
    │   ├── Kconfig
    │   ├── src
    │   │   └── main.c
    │   └── version.conf
    ├── Readme.md
    ├── west.yml
    └── zephyr
        └── module.yml

    There’s plenty of examples right under your nose. Zephyr is chock full of them. 😃

      jaredwolff

      Thanks for the quick reply Jared! One of the issues is that Zephyr’s been a moving target, and the nRF SDK has made it more difficult rather than easier. Some of the concepts I feel I’m missing is the concept of apps. nRFConnect separates the app from the SDK and toolchain. Is it safe to say that the nRF9160 app tree you are showing here contains everything needed, minus the SDK/toolchain to build the app? I don’t see west.yml in any of the nRFConnect examples.

      I did watch your videos a couple weeks ago, Thank you! I’ll watch them again and let you know my thoughts. I think the main question I have is a packaging question. From there, the intricacies of bindings, overlays, and other such things are still a bit confusing.

      I’m used to doing embedded Linux development with a system like “Petalinux” where you can create modules and packages and use Yocto to build a kernel. All of the components look similar, device trees, menuconfig, KConfig, etc, but instead of building a Linux system with multiple apps and drivers, you’re trying to do similar things to build an app using the Zephyr repo and nRFConnect toolchain. For some reason, this isn’t quite as straightforward and I think the reason is knowing how to properly package and reference. But from the tree you’ve shown here, it appears the board, drivers, and app all get collected together and are separate from the SDK or toolchain.

      Best, and Thanks Again!

      Josh

        jkarch Is it safe to say that the nRF9160 app tree you are showing here contains everything needed, minus the SDK/toolchain to build the app? I don’t see west.yml in any of the nRFConnect examples

        Yea I’d have to agree here. They abstract both the toolchain and SDK away. Advantage: it doesn’t get in your way. Disadvantage: you have no idea how it works underneath the hood.

        jkarch But from the tree you’ve shown here, it appears the board, drivers, and app all get collected together and are separate from the SDK or toolchain.

        The nice thing about Zephyr is that it’s flexible. If you don’t plan on ever submitting the driver you’re developing to the main Zephyr tree, then you can develop “out of tree” drivers which live next to your application. i.e. You can develop full boards outside without ever having to touch the inner workings of the Zephyr repository.

          jaredwolff
          It does seem that “In Tree” could be easier (and better once I learn how to develop drivers that meet Zephyr dev standards). In terms of getting up and running, it would be nice to be able to build up an embedded system the way I may have done it with an STM32 and FreeRTOS. Load up FreeRTOS, make header and source files for the driver that connects to SPI/I2C, and I’m on my way.

          With Zephyr I have to learn how to work with KConfig, CMakeLists, YAML files, DTS bindings, directory structures, then the source and header files which then adapt to a sensor or actuator API enforced by Zephyr. It really is a pretty big effort to get started, and that’s before I start dealing with normal RTOS things like threads, mutexes, etc. It’s considerably more challenging than ordinary embedded SW development for small micros. Unfortunately, I also think the abstractions from nRFConnect make the task considerably harder.

          One thing that I think would improve my chances of succeeding is getting an nRFConnect activated virtual environment within VSCode so I can directly run west commands instead of clicking buttons. Otherwise, it almost seems it’s better to just completely skip nRFConnect, even though the graphical config with the device tree is very nice. Is there a plugin you recommend for VSCode or do you just open up a separate terminal and activate a virtual environment? Do you use Zephyr from the source (eg. 3.5) or can you activate based on the nRF SDK?

          Best,
          Josh

            @jkarch you can try mine if you want: https://marketplace.visualstudio.com/items?itemName=circuitdojo.zephyr-tools

            It basically does all the heavy lifting for you, still supports nRF SDK and allows you full access to all the related Zephyr files within your project folder. (everything lives in ~/.zephyrtools including a python virtual env)

            You can check out the Getting Started documentation. Even if you’re not using a nRF9160 Feather, the process is similar for other boards.

            https://docs.circuitdojo.com/nrf9160-getting-started.html

              jaredwolff
              I’ll give that a try, Thank you! That might make things easier. I’m using the nRF52832. I’ll have to check out the feather board too. I’m basically looking for a low cost BLE Microcontroller for a project, fell into the nRF5xxxx platform with an old dev kit, and got thrust into Zephyrland 🙂

              Here’s a quick update: my first success with Zephyr: I figured you’d find this useful, and I may do my own writeup about the experience. I did everything with the command line and skipped using any plugins.

              After hours of scouring through and tinkering with Zephyr to learn how to build things, I tried two things
              (1) I tried building Zephyr through 3.5.99 and downloading the example from Zephyr project: It did not work right out of the box.
              (.venv) jkarch@Joshuas-MacBook-Pro zephyrproject % git clone https://github.com/zephyrproject-rtos/example-application my-app
              Cloning into 'my-app'...
              remote: Enumerating objects: 397, done.
              remote: Counting objects: 100% (233/233), done.
              remote: Compressing objects: 100% (122/122), done.
              remote: Total 397 (delta 140), reused 111 (delta 111), pack-reused 164
              Receiving objects: 100% (397/397), 59.92 KiB | 11.98 MiB/s, done.
              Resolving deltas: 100% (165/165), done.
              (.venv) jkarch@Joshuas-MacBook-Pro zephyrproject % cd my-app
              (.venv) jkarch@Joshuas-MacBook-Pro my-app % unset ZEPHYR_BASE
              (.venv) jkarch@Joshuas-MacBook-Pro my-app % source ~/zephyrproject/zephyr/zephyr-env.sh
              (.venv) jkarch@Joshuas-MacBook-Pro my-app % west build -b custom_plank app
              ...
              ...
              ...
              No board named 'custom_plank' found.

              The error found was that the board was missing, it could not find custom_plank and told me to select another board.
              So I tried again: (I run rm -rf build) in between each run to get rid of the caching of CMake.
              west build -b custom_plank app -DBOARD_ROOT=$PWD

              I received the following error:
              /Users/jkarch/zephyrproject/my-app/app/src/main.c:47: undefined reference to__device_dts_ord_4′`

              To me, this means that 3.5.99 isn’t properly using the libraries to work with the ncs HW. I still don’t know yet how to debug this, but I decided to skip this error and continue, using NCS’ specific build.

              I then decided to download the ncs-example-application and followed the steps in README.md and run the setup scripts initialized in:
              https://github.com/nrfconnect/ncs-example-application/tree/main
              source ~/my-workspace/zephyr/zephyr-env.sh
              This is the NCS zephyr environment.

              The app obtained by cloning the stock example-application repository built successfully:
              -- Zephyr version: 3.4.99 (/Users/jkarch/my-workspace/zephyr), build: v3.4.99-ncs1-105-gf8dc8ac55203
              [138/138] Linking C executable zephyr/zephyr.elf
              Memory region Used Size Region Size %age Used
              FLASH: 20928 B 1 MB 2.00%
              RAM: 6348 B 256 KB 2.42%
              IDT_LIST: 0 GB 2 KB 0.00%

              Great, progress. Next, I decided to try to build this app for the nrf52dk_nrf52832. I copied an nrf42dk_nrf52832 overlay file over containing the “examplesensor0” device tree entry.

              `/ {

              examplesensor0: examplesensor_0 {
              	compatible = "zephyr,examplesensor";
              	input-gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
              };

              };
              `

              (.venv) jkarch@Joshuas-MacBook-Pro my-app % rm -rf build
              (.venv) jkarch@Joshuas-MacBook-Pro my-app % west build -b nrf52dk_nrf52832 app -- -DDTC_OVERLAY_FILE=$(PWD)/boards/nrf52dk_nrf52832.overlay

              And mission success! So basically I learned a few things:
              (1) It seems that the example application is having linker errors with 3.5.99
              (2) you need to point either the current BOARD_ROOT or the custom DTC_OVERLAY_FILE to make use of the board. That file is set in the boards directory at the same level as the app.

              So I finally see a structure on how to create an app. Next step is to try this with my custom driver. Thanks Jared for the initial pointers and getting started! I’ll post an update when I get that working… But it is starting to become clear to me that the automation tools are abstracting away the commands, making it hard to compile custom projects as easily. I’m sure if I now open this up with VSCode, I might be able to make this work as well, but at least I understand the structure a bit better.

                After a bit more tinkering, here is a fully working Zephyr Workspace application using NCS that showcases multiple out of tree device drivers with a basic application structure (not set up with RTOS threads yet). The goal here is to show how to add your own driver to a workspace and integrate it into your project.
                Check out the [readme] if interested in cloning and building: (https://github.com/jkarch/zephyr-workspace-driver/blob/main/README.md). It’s set up for the nrf52dk_nrf52832 and is a combination of the Blinky, Blinky PWM, and device driver example. Please feel free to contribute to the repo as well so that folks can learn about creating and implementing out of tree drivers in Zephyr. I created a test driver for the ST Micro IIS3WDB vibration sensor. It is not a complete driver, more of a stub to configure the HW and read accelerations for now.
                repo link

                Pretty easy to get started. I would suggest diffing this with the main NCS repo to see how to add drivers.

                6 days later
                6 days later

                A few questions about your code.
                I have it very similar, but there are compilation errors that were supposedly closed two years ago if you read the zephyr commits.

                In the west.ym file:
                what is the purpose of specifying hal_stm3 if you have a different microcontroller?

                By content and folder structure did you take the application template for T2 topology?

                Do you have a zephyrproject folder? (documentation - first steps to install)

                Where is your the “my-exampledriver-workspace” folder located ? In the zephyrproject folder or elsewhere?

                  Terms and Conditions | Privacy Policy