ADC_DT_SPEC_GET doesn't work for DT nodes other than /zephyr,user

I'm using SDK v2.4.2 and trying to measure the voltage on the AIN0 pin of the nRF9160 SoC. The relevant code from my device tree source is as follows:

/ {
    batt {
        io-channels = <&adc 0>;
    };
};

&adc {
    status = "okay";
    #address-cells = <1>;
    #size-cells = <0>;
    channel@0 {
        reg = <0>;
        zephyr,gain = "ADC_GAIN_1_6";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10)>;
        zephyr,input-positive = <NRF_SAADC_AIN0>;
        zephyr,resolution = <12>;
        zephyr,oversampling = <1>;
    };  
};

In the C source code, I created an adc_dt_spec structure as follows:

static struct adc_dt_spec _batt_spec = ADC_DT_SPEC_GET(DT_PATH(batt));

For some reason, this results in a huge compilation error with hundreds of messages. However, if I simply change batt to zephyr,user in the device tree and accordingly to zephyr_user in the C code, the code compiles. I also noticed that if I want to stick with the name batt, then I must make the node compatible with the voltage-divider binding.

/ {
    batt {
        compatible = "voltage-divider";
        io-channels = <&adc 0>;
        output-ohms = <10000000>;
        full-ohms = <14700000>;
    };
};

With this, the code compiles without errors. However, I'd like to define some nodes with only the io-channels property as they aren't connected to any voltage dividers on my hardware. Is there a way to do so without being forced to place the node at the path /zephyr,user?

  • Hello Kenneth,

    As per Battery Measurement Readme, either the board devicetree should have a /vbatt node with "voltage-divider" compatible or the ADC config needs to be provided via zephyr,user node.

    Compatible is required property for voltage divider node.

    BR, Naeem

  • Hi Naeem,

    Thanks for your response. However, the Readme you mentioned is specific to the battery measurement sample. If you look into its C source code, it specifically looks for either /vbatt or /zephyr,user which is why the devicetree nodes must be named as such. In my source code, I use /batt to initialize the struct adc_dt_spec like this:

    static struct adc_dt_spec _batt_spec = ADC_DT_SPEC_GET(DT_PATH(batt));

    For this to work, the devicetree node should indeed be /batt and not /vbatt or /zephyr,user. Now, the weird thing is that this works if I define /batt with the "voltage-divider" compatible but not without it. According to Zephyr's documentation on ADC_DT_SPEC_GET and ADC_DT_SPEC_GET_BY_IDX, it should not be necessary to use the "voltage-divider" compatible. Simply defining the node with the io-channels property should suffice.

  • Hi Kenneth,

    I get what you are saying, and I can see that the ADC_DT_SPEC_GET_BY_IDX does not require "voltage-divider" compatibility.

    However, when I try to  define a node in the overlay, it immediately informs me that "compatible" is required property for a node.

    (more info here: DTS Bindings and Devicetree Bindings)

    And accordingly, the compatible will also enforce other properties, for example "output-ohms" is required property for "voltage-divider" compatible node.

  • Hi Naeem,

    Ah, so every node mandatorily needs a compatible. This I did not know. Now that solves the problem. I just defined another DT binding as follows,

    description: |
        Analog input channel.
    
    compatible: analog-input
    
    include: base.yaml
    
    properties:
        io-channels:
            type: phandle-array
            required: true

    and wrote my device tree node compatible with this binding,

    / {
        batt {
            compatible = "analog-input";
            io-channels = <&adc 0>;
        };
    };

    and now everything works just as I expect it to.

    Thanks a lot for your help!

Related