Trying to disable UART20 on nrf54l15 and reuse pins p1.5/4 for ADC but they are not working

Running Zephyr + NRF54l15 (board = nrf54l15dk/nrf54l15/cpuapp)

When attempting to use gpio1.5 and gpio1.4 for ADC inputs, we first disable the UART20 (which uses those pines) then use them in the ADC section of our overlay.

After setting them up in code and running firmware, we only read 1.8V from the ADC inputs (when we should be reading 0).

However, if we first configure the p1.5/4 as gpio inputs / no pull and THEN configure them as ADC inputs we measure the correct voltage.

Why does this happen?


Here is an overlay snippet

&uart20 {
    status = "disabled"; // used p1.4 and p1.5
};

&adc {
    #address-cells = <1>;
    #size-cells = <0>;

    channel@0 {
        reg = <0>;
        zephyr,gain = "ADC_GAIN_1_2";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,input-positive = <NRF_SAADC_AIN0>; /* P1.04 */
        zephyr,resolution = <12>;
    };

    channel@1 {
        reg = <1>;
        zephyr,gain = "ADC_GAIN_1_2";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,input-positive = <NRF_SAADC_AIN1>; /* P1.05 */
        zephyr,resolution = <12>;
    };
};

and here is our adc setup with the gpio fix beforehand

int hi_adc_setup(void)
{
    /* FWE-1242: Somthing in zephyr or nrf is setting up the P1.4/5 with a pullup
                 which interfers with the ADC functionality. Clear the gpio config completed to fix.
    */
    nrf_gpio_cfg(NRF_GPIO_PIN_MAP(1, 4), NRF_GPIO_PIN_DIR_INPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL,
                 NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_NOSENSE);

    nrf_gpio_cfg(NRF_GPIO_PIN_MAP(1, 5), NRF_GPIO_PIN_DIR_INPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL,
                 NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_NOSENSE);

    const struct device *adc_dev = DEVICE_DT_GET(ADC_NODE);
    int                  err     = 0;

    if (!device_is_ready(adc_dev))
    {
        LOG_ERR("ADC device %s not ready", adc_dev->name);
        return -1;
    }

    uint32_t channel_mask = 0;

    /* Loop through all channels and configure them */
    int configured_count  = 0;
    for (size_t i = 0; i < CHANNEL_COUNT; i++)
    {
        /* Only configure certain channels */
        if (channel_cfgs[i].channel_id != CHANNEL0_ID && channel_cfgs[i].channel_id != CHANNEL1_ID)
        {
            LOG_WRN("%s skip adc0 channel %d", __func__, channel_cfgs[i].channel_id);
            continue; /* Skip everything except channel 0 and 1 */
        }

        err = adc_channel_setup(adc_dev, &channel_cfgs[i]);
        if (err < 0)
        {
            LOG_ERR("Failed to configure ADC channel %u (%d)", channel_cfgs[i].channel_id, err);
            return err;
        }

        channel_mask |= BIT(channel_cfgs[i].channel_id);

        /* Populate voltage reference if not already set */
        if ((vrefs_mv[i] == 0) && (channel_cfgs[i].reference == ADC_REF_INTERNAL))
        {
            vrefs_mv[i] = adc_ref_internal(adc_dev);
        }
        configured_count++;
    }

    LOG_INF("Configured %u ADC channels on %s", configured_count, adc_dev->name);
    return 0;
}

why do we need to add this hack to ensure the ADC inputs work correctly? what else could be using p1.4/5 if we disabled the UART20? Something to do with TAMPC protection?

Parents Reply Children
No Data
Related