Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmake: dts: import devicetree symbols into CMake #37624

Merged
merged 1 commit into from
Aug 26, 2021

Conversation

tejlmand
Copy link
Collaborator

@tejlmand tejlmand commented Aug 11, 2021

This commit introduces devicetree API in CMake so that devicetree
properties and register block can be used in the CMake build system.

The script scripts/dts/dts_cmake.py processes the edt.pickle and
generates a corresponding devicetree property map in a devicetree_target
that is then used in CMake.

The following devicetree API has been made available in Zephyr CMake:

- dt_nodelabel(<var> LABEL <label>)
- dt_node_exists(<var> NODE <node>)
- dt_node_has_status(<var> NODE <node> STATUS <status>)
- dt_prop(<var> NODE <node> PROPERTY <prop>)
- dt_prop(<var> NODE <node> INDEX <idx> PROPERTY <prop>)
- dt_num_regs(<var> NODE <node>)
- dt_reg_addr(<var> NODE <node> [INDEX <idx>])
- dt_reg_size(<var> NODE <node> [INDEX <idx>])
- dt_has_chosen(<var> PROPERTY <prop>)
- dt_chosen(<var> PROPERTY <prop>)

Signed-off-by: Marti Bolivar [email protected]
Signed-off-by: Torsten Rasmussen [email protected]


This is needed by: #36140

@tejlmand tejlmand requested a review from nashif as a code owner August 11, 2021 19:32
@github-actions github-actions bot added area: Build System area: Devicetree Tooling PR modifies or adds a Device Tree tooling labels Aug 11, 2021
@tejlmand tejlmand force-pushed the dts_cmake branch 2 times, most recently from 8916a8d to 2ab3b86 Compare August 11, 2021 21:54
@@ -2261,3 +2263,369 @@ function(target_byproducts)
COMMENT "Logical command for additional byproducts on target: ${TB_TARGET}"
)
endfunction()

########################################################
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we split this out into its own file.

Copy link
Collaborator Author

@tejlmand tejlmand Aug 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could, but are we sure that we want to do that ?

Today, whenever one sees a CMake function or macro in use inside Zephyr build system that is not vanilla CMake, then there is one place to look, and that is cmake/extensions.cmake.

That makes it easy to lookup extension functions.

Only exception are areas where functions are used internally, such as: cmake/flash/CMakeLists.txt but those functions are not use outside that file, afaik.

We could of course establish a new scheme, like:

  • cmake/extensions/dt-extensions.cmake
  • cmake/extensions/library-extensions.cmake
    • for library related extensions, like zephyr_library(), zephyr_library_sources, zephyr_sources, ...
  • cmake/extensions/generic-extensions.cmake
    • for generic CMake functions with a twist, like target_sources_ifdef(), add_subdirectory_ifdef().
  • cmake/extensions/misc-extensions.cmake
    • There always needs to be a misc.
  • cmake/extensions/<...>-extensions.cmake

but doing such split (which would be outside the scope of this PR) will sometimes make it harder to know where a given function belongs (most functions will be easy, but not all).

Having only devicetree functions in a separate file just makes it inconsistent where functions are placed, imho.

If it is because you believe this feature could be reusable outside Zephyr scope, like with linker generator, then I see the point and a use-case.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the thought was that this could be usable outside of zephyr.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the thought was that this could be usable outside of zephyr.

makes sense, but those functions are useless without the generated <build>/zephyr/dts.cmake file which is created here https://github.com/zephyrproject-rtos/zephyr/blob/aecb7fc1b488ac3d017447d324b1e78e793f7620/scripts/dts/dts_cmake.py based on the edt.pickle file, https://github.com/zephyrproject-rtos/zephyr/blob/aecb7fc1b488ac3d017447d324b1e78e793f7620/scripts/dts/dts_cmake.py#L34

The edt.pickle file is created in the gen_defines.py script here:

pickle.dump(edt, f, protocol=4)

so just placing those dt_* functions in its own CMake file doesn't really make them reusable.

If we really want to make it easier to reuse the devicetree --> CMake infrastructure outside Zephyr, then perhaps we should see if this could be streamlined with reusability in mind for all the parts involved:

That sounds very reasonable to me, but I think it would be outside the scope of this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @tejlmand . If someone wants to use it outside of Zephyr they can pick up the patch at that point and make it do what they need. I'm not sure it's really necessary for this PR.

@galak
Copy link
Collaborator

galak commented Aug 13, 2021

How do we feel about use of the to select files to build?

For example something like:

drivers/gpio/Kconfig.psoc6 that defines GPIO_PSOC6

and drivers/gpio/CMakeLists.txt could go from:

zephyr_library_sources_ifdef(CONFIG_GPIO_PSOC6 gpio_psoc6.c)

to

zephyr_library_sources_dt_compat_enabled("cypress,psoc6-gpio" gpio_psoc6.c)

@galak
Copy link
Collaborator

galak commented Aug 13, 2021

Is this used for anything other than zephyr,dtcm and zephyr,itcm in the linker PR?

@tejlmand
Copy link
Collaborator Author

Is this used for anything other than zephyr,dtcm and zephyr,itcm in the linker PR?

also here in linker PR:
https://github.com/zephyrproject-rtos/zephyr/blob/aa4f08e1220b1c5f53ad5b8bff87ae89730286e7/cmake/extensions.cmake#L2818-L2836
which is then used here:
https://github.com/zephyrproject-rtos/zephyr/blob/aa4f08e1220b1c5f53ad5b8bff87ae89730286e7/cmake/linker_script/arm/linker.cmake#L40-L49

but besides that, there have previous been requests regarding devicetree symbols in CMake.

@tejlmand
Copy link
Collaborator Author

How do we feel about use of the to select files to build?

Personal I think that would cleanup the code not having the intermediate Kconfig setting for enabling the driver, but when looking at the Kconfig:

config GPIO_PSOC6
bool "Cypress PSoC-6 GPIO driver"
default y if $(dt_compat_enabled,$(DT_COMPAT_CYPRESS_PSOC6_GPIO))
then the symbol does have a prompt, although with default y

So today it is possible to have dt_compat_enabled for cypress,psoc6-gpio and CONFIG_GPIO_PSOC6=n which would disable the sw-driver.
I don't know the exact usecase for that, but it does allow users to provide their own driver which would not be possible if we include the driver based directly on devicetree properties.

@mbolivar-nordic
Copy link
Contributor

mbolivar-nordic commented Aug 16, 2021

I don't know the exact usecase for that, but it does allow users to provide their own driver which would not be possible if we include the driver based directly on devicetree properties.

This is important to users; see e.g. #10621 (comment) from @henrikbrixandersen

Copy link
Contributor

@mbolivar-nordic mbolivar-nordic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As some background, the devicetree.h API in C uses "node identifier" as a precise term for the magic macros we use to refer to nodes, but we only have those because we cannot refer to a node by its path.

However, in CMake, we can refer to nodes by their paths, so I don't think the term "node identifier" should be used in this context. I would rather preserve the term "node identifier" for just the magic macro you see in C. That will be less ambiguous. In CMake, we can just take a path or alias when the user wants to tell us what node they want instead.

@mbolivar-nordic
Copy link
Contributor

mbolivar-nordic commented Aug 16, 2021

How do we feel about use of the to select files to build?

Deciding whether or not to enable an entire driver should be left user-settable via Kconfig as I mentioned earlier.

However there are use cases, like here:

#if BME280_BUS_I2C

When CONFIG_BME280=y, I still only want to build bme280_i2c.c if there is an instance of the compatible on an I2C bus.

So if I could do something like this:

if (CONFIG_BME280)
  dt_compat_on_bus_status_okay(result COMPATIBLE bosch,bme280 BUS i2c)
  if (result)
    zephyr_library_sources(bme280_i2c.c)
  endif()
  dt_compat_on_bus_status_okay(result COMPATIBLE bosch,bme280 BUS i2c)
  if (result)
    zephyr_library_sources(bme280_i2c.c)
  endif()
endif()

Then I think that would be a little cleaner than the current ifdef in the driver source.

Edit: or even something like this:

zephyr_library_sources_if_compat_on_bus(bme280_i2c.c COMPATIBLE bosch,bme280 BUS i2c)
zephyr_library_sources_if_compat_on_bus(bme280_spi.c COMPATIBLE bosch,bme280 BUS spi)

@tejlmand
Copy link
Collaborator Author

However, in CMake, we can refer to nodes by their paths, so I don't think the term "node identifier" should be used in this context. I would rather preserve the term "node identifier" for just the magic macro you see in C. That will be less ambiguous. In CMake, we can just take a path or alias when the user wants to tell us what node they want instead.

Good point, changed node identifier --> node path.

@tejlmand
Copy link
Collaborator Author

Then I think that would be a little cleaner than the current ifdef in the driver source.

Edit: or even something like this:

Agree, let's look into the cleanest way to do this after the basic support for devicetree has been merged (This PR).
Initial feeling is that a 40 chars long function call is a bit long, and because you would end-up line wrapping anyway, then this might be just as clean, imho:

dt_compat_on_bus_status_okay(result COMPATIBLE bosch,bme280 BUS i2c)
zephyr_library_sources_ifdef(result bme280_i2c.c)

Remember, we already have the zephyr_library_sources_ifdef() function.

cmake/extensions.cmake Outdated Show resolved Hide resolved
Copy link
Collaborator

@galak galak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See inline comments:

General comments:

  • cleanup docs to clarify return values for true/false cases as well as on "errors" (ie path doesn't exist, prop doesn't exist, etc)
  • replace NODE with PATH

Copy link
Contributor

@mbolivar-nordic mbolivar-nordic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I generally agree with Kumar's cleanup suggestions, with a couple of other ideas and additional comments inline. Thanks.

cmake/dts.cmake Outdated Show resolved Hide resolved
cmake/extensions.cmake Outdated Show resolved Hide resolved
cmake/extensions.cmake Outdated Show resolved Hide resolved
cmake/extensions.cmake Show resolved Hide resolved
endfunction()

# Usage:
# dt_node_exists(<var> NODE <node>)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think dt_node_exists is a good name for the function. It should take PATH <path> for now, but we can extend it later to also accept ALIAS <alias>, NODELABEL <label>, etc. without changing the name. I think that would be nicer than having separate dt_alias_exists ,dt_nodelabel_exists, etc.

cmake/extensions.cmake Outdated Show resolved Hide resolved
scripts/dts/dts_cmake.py Outdated Show resolved Hide resolved
cmake/dts.cmake Outdated Show resolved Hide resolved
cmake/dts.cmake Outdated Show resolved Hide resolved
@mbolivar-nordic
Copy link
Contributor

mbolivar-nordic commented Aug 25, 2021

@tejlmand I pushed a fixup branch here:

https://github.com/mbolivar-nordic/zephyr/tree/dts_cmake

Please fetch, review, and squash if it looks OK with you. See commit logs for justifications.

If we're on the same page about all of those, I'm +1 to get this in.

@mbolivar-nordic
Copy link
Contributor

If we're on the same page about all of those, I'm +1 to get this in.

And if I've made any terrible mistakes, please let me know 😄

@tejlmand
Copy link
Collaborator Author

If we're on the same page about all of those, I'm +1 to get this in.

And if I've made any terrible mistakes, please let me know 😄

Not a mistake, but placed a comment here: mbolivar-nordic@d3b44e2#r55395442
which allows us to handle the edge case without a lot of extra code.

@tejlmand tejlmand force-pushed the dts_cmake branch 2 times, most recently from 736dc0b to 7dbfc00 Compare August 25, 2021 08:00
@tejlmand
Copy link
Collaborator Author

tejlmand commented Aug 25, 2021

Please fetch, review, and squash if it looks OK with you. See commit logs for justifications.

Thanks a lot, I have taken in your changes here: https://github.com/zephyrproject-rtos/zephyr/compare/f0cae1d28edafda85345fe24de6e37dc64c0063c..736dc0b1edc516de74568881ca44c7f484e0a79c

and then made a small update according to my comments here:
https://github.com/zephyrproject-rtos/zephyr/compare/7dbfc0094d73a90822d69041454792573cce6e0a..55ac7d859a1380cbc66b2379aa1a895863cc8937

@tejlmand tejlmand force-pushed the dts_cmake branch 2 times, most recently from 55ac7d8 to f42386d Compare August 25, 2021 15:12
Copy link
Contributor

@mbolivar-nordic mbolivar-nordic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good now, thanks.

@mbolivar-nordic
Copy link
Contributor

I think we should dismiss @galak's review as "addressed" to get this in for feature freeze.

This commit introduces devicetree API in CMake so that devicetree
properties and register block can be used in the CMake build system.

The script scripts/dts/gen_dts_cmake.py processes the edt.pickle and
generates a corresponding devicetree property map in a devicetree_target
that is then used in CMake.

The following devicetree API has been made available in Zephyr CMake:
- dt_nodelabel(<var> NODELABEL <label>)
- dt_node_exists(<var> PATH <path>)
- dt_node_has_status(<var> PATH <path> STATUS <status>)
- dt_prop(<var> PATH <path> PROPERTY <prop>)
- dt_prop(<var> PATH <path> INDEX <idx> PROPERTY <prop>)
- dt_num_regs(<var> PATH <path>)
- dt_reg_addr(<var> PATH <path> [INDEX <idx>])
- dt_reg_size(<var> PATH <path> [INDEX <idx>])
- dt_has_chosen(<var> PROPERTY <prop>)
- dt_chosen(<var> PROPERTY <prop>)

Signed-off-by: Martí Bolívar <[email protected]>
Signed-off-by: Torsten Rasmussen <[email protected]>
@nashif nashif merged commit fcf7209 into zephyrproject-rtos:main Aug 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Build System area: Devicetree Tooling PR modifies or adds a Device Tree tooling
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants