Made a change to overlay in project, now nothing will build.

I had a project working using nRFConnect, with VSCode. I then made the mistake of removing a peripheral I don't need (this is a custom board using the nRF52840) Removed the UART0 and a button and builds now fail with errors like: 

devicetree error: 'gpios' is marked as required in 'properties:' in C:/ncs/v2.4.2/zephyr/dts/bindings\input\gpio-keys.yaml, but does not appear in <Node /buttons/button_2 in 'C:/ncs/v2.4.2/zephyr/misc/empty_file.c'>

I have no idea what this means - I'm a programmer, and it seems like most Nordic/zephyr development is just creating config files all over the place and having the code magically auto-generated and hidden away. This is in stark contrast with every other architecture I use where I write C/C++ code and compile it normally. I find myself having to rely on git to roll back changes that cause the build system to break for unknown reasons with cryptic errors related to macros inside macros relying upon parsing all kinds of config files. I prefer working with C/C++ and debugger to this fragile auto-generated nightmare :) 

I've tried adding the button back, but the build still crashes out with the same error. So once again I have to roll back the project. Is it possible to develop for the nRF52 series without Zephyr and auto-generated code?

Parents
  • Hello Scerion,

    I've tried adding the button back, but the build still crashes out with the same error. So once again I have to roll back the project. Is it possible to develop for the nRF52 series without Zephyr and auto-generated code?

    There are two alternatives to this:

    • Use the nRF5 SDK
      • This SDK is in maintenance mode, and we strongly recommend against using it for new project.
        It won't get updated with new features such as Bluetooth 5.4 or Mesh 1.1 support.
    • Use the nrfx drivers in Zephyr
      • The nrfx drivers interact with the hardware directly.
      • The Zephyr drivers are implemented using the nrfx driver under the hood.
        They also are initialized automatically during OS boot up.
        Therefore, to safely use the nrfx driver, you need to disable all Zephyr drivers to prevent conflicts.
      • Samples are available in <NCS root>\modules\hal\nordic\nrfx\samples.
        Also available online: https://github.com/zephyrproject-rtos/hal_nordic/tree/nrfx-2.11.0/nrfx/samples

    However, for tasks such as UART or Button, I think the DeviceTree and Zephyr driver setup should be generally simpler to use.

    I too come from a bare-metal MCU programming background, and I share your frustration while adapting to Zephyr. It is definitely a steep learning curve. However, please take my words that it is worth it. User  expresses it very well in a comment, which I quote:

    I have been developing on nRF51, nRF52 and nRF53. Used both SDK5 and now nRF Connect SDK on the nRF52840; nRF5340 only on the nRF Connect SDK. Real-world projects with actual product results that do something.
    ...
    Once you get used to the runtime environment and you do not run into resource limits, Zephyr is quite nice. It allows you to design and implement your software development in nice and organized modules which is a lot harder when writing "on the naked iron". In our last project, we run some async protocols; you simply cannot beat a good multitasking architecture here. Maybe the code is not as compact compared to a cold metal solution, maybe it uses more RAM. But the convenience of having an RTOS available in such a case is unbeatable.

    Onto the error message:

    devicetree error: 'gpios' is marked as required in 'properties:' in C:/ncs/v2.4.2/zephyr/dts/bindings\input\gpio-keys.yaml, but does not appear in <Node /buttons/button_2 in 'C:/ncs/v2.4.2/zephyr/misc/empty_file.c'>

    The keyword you will want to pick up here are: gpios, properties, bindings, and gpio-keys.yaml.

    The way the DeviceTree magic works, is that it looks at a node's compatible properties for a binding.
    The binding describes how that DeviceTree node should be understood.
    The value of the compatible properties will most of the times be exactly the name of the bindings YML file.

    Thus, in our case here, to see what your node should look like, you should search for the regex compatible.*gpio-keys in the reference nrf52840dk_nrf52840.dts file. You would find the default button node written as such:

    	buttons {
    		compatible = "gpio-keys";
    		button0: button_0 {
    			gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
    			label = "Push button switch 0";
    			zephyr,code = <INPUT_KEY_0>;
    		};
    		...
    	};

    And there you found a reference for how to fix the gpio properties for your button node.

    For more information on how DeviceTree works, please refer to the Zephyr documentation on our website or on the Zephyr RTOS website.

    I am sure error codes would look more meaningful once you go over those guides a little.

    If you meet any other difficulties, please don't hesitate to use DevZone. For the current topic, please reply here. For new topics, please simply start a new thread.

    Best regards,

    Hieu 

  • Thank you for the reply and explanation. I did find a kind of fix for the problem after posting my question - I am working with a custom overlay as I'm using my own PCB for this project - the overlay began as the standard nRF52840 overlay. Anyway, I found that if I removed the button input using the GUI overlay editor I had the error. However if I removed the UART CTS output first, then the button, then added the CTS back again the error disappeared. I think it's due to how the GUI generates the overlay file, with each line overriding previous properties if the name matches and for some reason it fixes it. 

    My project is very low power, and being able to start and stop the UART peripheral (and i2C etc) in code is preferable so it's not wasting power by running all of the time. The Zephyr method of creating all the peripherals in a GUI and having it magically write the code for you hides how this would be achieved. It also means that anyone else opening the project and looking at the GUI tool would assume that the UART is always active, even though the code might disable it. Not sure if that makes sense?

  • Scerion said:
    Thank you for the reply and explanation. I did find a kind of fix for the problem after posting my question - I am working with a custom overlay as I'm using my own PCB for this project - the overlay began as the standard nRF52840 overlay. Anyway, I found that if I removed the button input using the GUI overlay editor I had the error. However if I removed the UART CTS output first, then the button, then added the CTS back again the error disappeared. I think it's due to how the GUI generates the overlay file, with each line overriding previous properties if the name matches and for some reason it fixes it. 

    That honestly sound like something wrong. If you can give me the steps to consistently reproduce the issue, I will relay it to the VS Code Extension team. Please also run Generate Support Information and include the output.

    If you find the UI tool hiding too many things from you, you could consider tweaking with the overlay files with a text editing approach instead.

    Scerion said:
    My project is very low power, and being able to start and stop the UART peripheral (and i2C etc) in code is preferable so it's not wasting power by running all of the time. The Zephyr method of creating all the peripherals in a GUI and having it magically write the code for you hides how this would be achieved.

    The implementation is hidden, but the achievement of low-power is not necessarily hidden, right?
    You still need to have code to set the device into low-power mode.

    Scerion said:
    It also means that anyone else opening the project and looking at the GUI tool would assume that the UART is always active, even though the code might disable it. Not sure if that makes sense?

    It makes sense when you restrict any implications to only within the scope of each element in the setup.
    (I am unable to find a better word here. My apologies. Hopefully the explanation below will help it make sense)

    The DeviceTree describes that the hardware.
    If the device has a UART peripheral with certain pin connections, and if that is always true, then it makes sense for it to always be on the DeviceTree.

    Similarly, in Kconfig, "CONFIG_SERIAL being set" means that the Serial driver is built into the project and available to be used. It does not reflect whether the applications actually use the driver for anything at all.

    Finally, we have the runtime status and behavior. Whether the UART peripheral is put into Low Power mode or not falls into this.

    It's somewhat similar to the layered concepts we often meet in software architectures.

Reply
  • Scerion said:
    Thank you for the reply and explanation. I did find a kind of fix for the problem after posting my question - I am working with a custom overlay as I'm using my own PCB for this project - the overlay began as the standard nRF52840 overlay. Anyway, I found that if I removed the button input using the GUI overlay editor I had the error. However if I removed the UART CTS output first, then the button, then added the CTS back again the error disappeared. I think it's due to how the GUI generates the overlay file, with each line overriding previous properties if the name matches and for some reason it fixes it. 

    That honestly sound like something wrong. If you can give me the steps to consistently reproduce the issue, I will relay it to the VS Code Extension team. Please also run Generate Support Information and include the output.

    If you find the UI tool hiding too many things from you, you could consider tweaking with the overlay files with a text editing approach instead.

    Scerion said:
    My project is very low power, and being able to start and stop the UART peripheral (and i2C etc) in code is preferable so it's not wasting power by running all of the time. The Zephyr method of creating all the peripherals in a GUI and having it magically write the code for you hides how this would be achieved.

    The implementation is hidden, but the achievement of low-power is not necessarily hidden, right?
    You still need to have code to set the device into low-power mode.

    Scerion said:
    It also means that anyone else opening the project and looking at the GUI tool would assume that the UART is always active, even though the code might disable it. Not sure if that makes sense?

    It makes sense when you restrict any implications to only within the scope of each element in the setup.
    (I am unable to find a better word here. My apologies. Hopefully the explanation below will help it make sense)

    The DeviceTree describes that the hardware.
    If the device has a UART peripheral with certain pin connections, and if that is always true, then it makes sense for it to always be on the DeviceTree.

    Similarly, in Kconfig, "CONFIG_SERIAL being set" means that the Serial driver is built into the project and available to be used. It does not reflect whether the applications actually use the driver for anything at all.

    Finally, we have the runtime status and behavior. Whether the UART peripheral is put into Low Power mode or not falls into this.

    It's somewhat similar to the layered concepts we often meet in software architectures.

Children
  • Not sure if I explained my point very well. Basically in the nRF Connect VSCode extension, it relies on the GUI tool to enable and disable peripherals, which then autogenerates the code etc. The programmer (i.e. me) does not have any information about how to enable/disable the peripherals in code, as everything is hidden behind Zephyr drivers and config files, templates and overlays etc. So where-as in other architectures I can just modify memory-mapped registers to change peripheral settings, to freely enable/disable and modify settings at any time, with the nRF approach, you set things up with the GUI, and then it's a hidden immutable code block somewhere away from my source. 

    An example would be if the UART should be disabled to save power unless a button is pressed at boot, to enable debugging output on a board. With the GUI tools, it's either on or off permanently - whether it's used or not. Hope that makes sense.

Related