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

devicetree: improved support for enum values #21273

Closed
pabigot opened this issue Dec 10, 2019 · 5 comments · Fixed by #30406
Closed

devicetree: improved support for enum values #21273

pabigot opened this issue Dec 10, 2019 · 5 comments · Fixed by #30406
Assignees
Labels
area: Devicetree Enhancement Changes/Updates/Additions to existing features

Comments

@pabigot
Copy link
Collaborator

pabigot commented Dec 10, 2019

Extracted from #17309 where this was originally proposed:

Currently there is one in-tree use of the enum type in bindings, for the usb controller field maximum-speed:

maximum-speed:
  type: string
  enum:
     - "low-speed"
     - "full-speed"
     - "high-speed"
     - "super-speed"

It generates symbols like this:

#define DT_NXP_KINETIS_USBD_402E0000_MAXIMUM_SPEED  "full-speed"
#define DT_NXP_KINETIS_USBD_402E0000_MAXIMUM_SPEED_ENUM 1

This is not robust. The symbol that identifies the selection has a string value that is not readily usable to control compilation or initialize runtime data structures. The symbol that provides an integer identifier is dependent on the order values were listed in the binding, which is not visible to the application or driver source and might change over time.

The sole in-tree users of this are sam and stm32 USB controllers, which have to do string comparisons against the enum value to determine the selected value.

I would like to use the enum type for properties that are constrained to one of a small set of values, but in its current form this is not possible. Below are the original potential solution paths extracted from #17309. Implementing either or both would make it much easier to use such properties.

Tokenizable Values

NOTE: The "Generated Enums" feature below may be a better solution to the underlying problem.

Waveshare's e-paper displays use the same API with a large number of device-specific values, including initialization sequences and look-up tables. I would like the driver I'm developing to allow selection of the display like this:

    variant:
      type: string
      category: required
      generation: define
      enum:
        - "epd1p54"
        - "epd1p54b"
        - "epd1p54c"
        - "epd4p2"
        # ...

Currently what I get is:

#define DT_NORDIC_NRF_SPI_40004000_WAVESHARE_EPD_0_VARIANT "epd1p54b"

In the driver I have things like:

static u8_t epd1p54b_init[] = { /* lots of bytes here */};

Since the value of the property is expressed as a string rather than a token, I can't use it in something like:

   .init = CONCAT(DT_INST_0_WAVESHARE_EPD_VARIANT, _init),

So I want an option to generate string-valued properties as tokens.

Generated Enums

Alternative to "Tokenizable Values" changing the property define value from a string to a (sequence of) tokens, a define for a string enum value could be generated like this:

#define DT_NORDIC_NRF_SPI_40004000_WAVESHARE_EPD_0_VARIANT "epd1p54b"
#define DT_NORDIC_NRF_SPI_40004000_WAVESHARE_EPD_0_VARIANT_EPD1P54B 1

This would also allow preprocessor detection of the variant, more convenient then token catenation in most cases, but also more limiting.

For this approach we need a clear description of how string enum values are converted to a character sequence suitable as a macro name suffix, e.g. anything not isalnum becomes _.

@pabigot pabigot added Enhancement Changes/Updates/Additions to existing features area: Devicetree labels Dec 10, 2019
@ulfalizer
Copy link
Collaborator

ulfalizer commented Dec 11, 2019

As a cop-out, I wonder if it could just be documented that *_ENUM is based on the order that values are listed in enum:.

The code could then have something like this:

#define LOW_SPEED   0
#define FULL_SPEED  1
#define HIGH_SPEED  2
#define SUPER_SPEED 3

A warning could be added in the binding re. keeping it in sync with the code.

Note that enum: also works for other types btw (int, array, etc.) That makes it a bit iffy to special-case it for strings.

@ulfalizer
Copy link
Collaborator

ulfalizer commented Dec 11, 2019

Maybe just some light special-casing for strings could be added too, with an additional ..._ENUM_ID that gets generated, like this:

#define ..._ENUM_ID LOW_SPEED

Guess that could be done for all strings too, and not just for enums, though it'd get very spammy.

@pabigot
Copy link
Collaborator Author

pabigot commented Dec 11, 2019

As a cop-out, I wonder if it could just be documented that *_ENUM is based on the order that values are listed in enum:.

That would be a policy that would prevent me from ever using enum. It's far to trusting and fragile.

I think it's reasonable that the generated enum like DT_NORDIC_NRF_SPI_40004000_WAVESHARE_EPD_0_VARIANT_EPD1P54B be provided only when the value of the enum is a string.

@ulfalizer
Copy link
Collaborator

ulfalizer commented Dec 11, 2019

Thinking about it, just outputting an additional concat-friendly macro for all type: string properties might not be so bad, because e.g. compatible is a string-array.

I'll implement and check.

@ulfalizer
Copy link
Collaborator

Hmm... that might not solve the compile-time-test-by-name part though. Will poke around a bit.

ulfalizer added a commit to ulfalizer/zephyr that referenced this issue Dec 12, 2019
For each 'type: string' property, generate an additional *_UNQUOTED
macro that with an unquoted value. This can be useful with token pasting
and the like.

Motivated by zephyrproject-rtos#21273,
where there's this:

    variant:
        type: string
        category: required
        generation: define
        enum:
            - "epd1p54"
            - "epd1p54b"
            - "epd1p54c"
            - "epd4p2"
            # ...

Depending on the selection, an identifier like 'epd1p56b_init' should be
generated.

The macros below now get generated, where the *_UNQUOTED version could
be token-pasted to generate 'epd1p56b_init'.

    #define DT_..._VARIANT "epd1p54b"
    #define DT_..._VARIANT_UNQUOTED epd1p54b

Something like *_ID could've been used instead of *_UNQUOTED too, but
*_UNQUOTED is nice in that it's greppable and makes the magic stick out
more.

Signed-off-by: Ulf Magnusson <[email protected]>
@pabigot pabigot mentioned this issue Mar 19, 2020
12 tasks
pabigot added a commit to pabigot/zephyr that referenced this issue Dec 2, 2020
Generate tokens for enumerations that have string values that are
identifiers.  Prototype for potential resolution to zephyrproject-rtos#21273.
mbolivar-nordic pushed a commit to mbolivar-nordic/zephyr that referenced this issue Dec 8, 2020
Whenever a devicetree binding defines a string property whose
enumerated values are all tokenizable, generate C macros for each
property value that are the corresponding tokens.

Note that "token" is distinct from "identifier": both 'foo' and '123'
are valid tokens, but only 'foo' is a valid identifier. We permit some
strings which are not valid identifiers in anticipation that the
generalization may be useful, e.g. when defining macros that paste the
token onto a prefix that makes the whole thing an identifier.

Fixes: zephyrproject-rtos#21273
Signed-off-by: Peter Bigot <[email protected]>
Signed-off-by: Martí Bolívar <[email protected]>
nashif pushed a commit that referenced this issue Dec 14, 2020
Whenever a devicetree binding defines a string property whose
enumerated values are all tokenizable, generate C macros for each
property value that are the corresponding tokens.

Note that "token" is distinct from "identifier": both 'foo' and '123'
are valid tokens, but only 'foo' is a valid identifier. We permit some
strings which are not valid identifiers in anticipation that the
generalization may be useful, e.g. when defining macros that paste the
token onto a prefix that makes the whole thing an identifier.

Fixes: #21273
Signed-off-by: Peter Bigot <[email protected]>
Signed-off-by: Martí Bolívar <[email protected]>
bwasim pushed a commit to bwasim/zephyr that referenced this issue Jan 5, 2021
Whenever a devicetree binding defines a string property whose
enumerated values are all tokenizable, generate C macros for each
property value that are the corresponding tokens.

Note that "token" is distinct from "identifier": both 'foo' and '123'
are valid tokens, but only 'foo' is a valid identifier. We permit some
strings which are not valid identifiers in anticipation that the
generalization may be useful, e.g. when defining macros that paste the
token onto a prefix that makes the whole thing an identifier.

Fixes: zephyrproject-rtos#21273
Signed-off-by: Peter Bigot <[email protected]>
Signed-off-by: Martí Bolívar <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Devicetree Enhancement Changes/Updates/Additions to existing features
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants