How to set GPIOs high before sensor driver initializes?

EDIT: Sorry to be posting a lot about my LIS2DH12 problems lately, as I'm advancing somewhat while I have open support threads. Newest thread is here:  Runing LIS2DH12 on custom hardware In preparation of this thread I have hardwired the GPIOs mentioned below to VDD so they should not affect operation.

Hi,

I'm using LIS2DH I2C driver, but my hardware design is based on SPI connection (sensor supports both). Therefore I have GPIO pins controlling some of the functions like I2C address LSB and CS signal to configure I2C operation (sensor operates in I2C mode if CS is HIGH)

First of all, the VDD of LIS2DH12 is directly connected to a GPIO pin, but this is probably solved by driver parameter "supply-gpios". I assume the GPIOs defined here are set to HIGH before during driver init to turn sensor on?

So I put three GPIOs in the supply-gpios parameter;
VDD, controlling power to the sensor
CS, controlling comm. mode 
SDO, controlling I2C address LSB

All are configured to active high, expecting them to go HIGH to turn on the device, set I2C mode and set address LSB to 1 resulting in an address of 0x19.

Do know that I also try to set these GPIOs in main thread in case the driver init does not do what I want, but it seems that sensor driver inits way before I set the GPIOs anyways.

The output of RTT terminal indicates that sensor init did not go to plan:
<err> lis2dh: Failed to read chip id.
*** Booting nRF Connect SDK 3758bcbfa5cd ***
Device LIS2DH is not ready

So I guess my main problem is that I don't get the LIS2DH12 to work but I suspect it has to do with my special requirements of having to set GPIOs to a known state before the sensor driver inits or during init. Code is based on LIS2DH12 sample with addition of some GPIO.

Any thoughts on my problems are appreciated.

/*
 * Copyright (c) 2019 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/util.h>
#include <inttypes.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(generallogs,LOG_LEVEL_DBG);

#define LED0_NODE DT_NODELABEL(led_b)
#define ADDR_NODE DT_NODELABEL(lis2dh12_addr)
#define CS_NODE DT_NODELABEL(lis2dh12_cs)
#define VDD_NODE DT_NODELABEL(lis2dh12_vdd)

static void fetch_and_display(const struct device *sensor)
{
	static unsigned int count;
	struct sensor_value accel[3];
	struct sensor_value temperature;
	const char *overrun = "";
	int rc = sensor_sample_fetch(sensor);

	++count;
	if (rc == -EBADMSG) {
		/* Sample overrun.  Ignore in polled mode. */
		if (IS_ENABLED(CONFIG_LIS2DH_TRIGGER)) {
			overrun = "[OVERRUN] ";
		}
		rc = 0;
	}
	if (rc == 0) {
		rc = sensor_channel_get(sensor,
					SENSOR_CHAN_ACCEL_XYZ,
					accel);
	}
	if (rc < 0) {
		printf("ERROR: Update failed: %d\n", rc);
	} else {
		printf("#%u @ %u ms: %sx %f , y %f , z %f",
		       count, k_uptime_get_32(), overrun,
		       sensor_value_to_double(&accel[0]),
		       sensor_value_to_double(&accel[1]),
		       sensor_value_to_double(&accel[2]));
	}

	if (IS_ENABLED(CONFIG_LIS2DH_MEASURE_TEMPERATURE)) {
		if (rc == 0) {
			rc = sensor_channel_get(sensor, SENSOR_CHAN_DIE_TEMP, &temperature);
			if (rc < 0) {
				printf("\nERROR: Unable to read temperature:%d\n", rc);
			} else {
				printf(", t %f\n", sensor_value_to_double(&temperature));
			}
		}

	} else {
		printf("\n");
	}
}

#ifdef CONFIG_LIS2DH_TRIGGER
static void trigger_handler(const struct device *dev,
			    const struct sensor_trigger *trig)
{
	fetch_and_display(dev);
}
#endif

int main(void)
{
	int ret;
	static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
	static const struct gpio_dt_spec addr = GPIO_DT_SPEC_GET(ADDR_NODE, gpios);
	static const struct gpio_dt_spec cs = GPIO_DT_SPEC_GET(CS_NODE, gpios);
	static const struct gpio_dt_spec vdd = GPIO_DT_SPEC_GET(VDD_NODE, gpios);
	

	/*
	printk("Hello World! %s\n", CONFIG_BOARD);
	LOG_INF("nixie log info");
	LOG_DBG("nixie log debug");
	LOG_WRN("nixie log warning");
	LOG_ERR("nixie log error");
	*/

	if (!gpio_is_ready_dt(&led)) {
		return 0;
	}

	ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
	if (ret < 0) {
		return 0;
	}

	printf("Before GPIOs are set\n");

	gpio_pin_set_dt(&cs, 1); //Puts LIS2DH12 CS high, means I2C mode.
	gpio_pin_set_dt(&addr, 1); //Sets address pin high, means address = 0x19 (probably)
	gpio_pin_set_dt(&vdd, 1); //Sets vdd pin high, turns on LIS2DH12
 	printf("After GPIOs are set\n");

	k_sleep(K_MSEC(2000));
	printf("After sleep\n");

	gpio_pin_set_dt(&led, 1); //Turn on blue LED

	const struct device *const sensor = DEVICE_DT_GET_ANY(st_lis2dh);

	if (sensor == NULL) {
		printf("No device found\n");
		return 0;
	}
	if (!device_is_ready(sensor)) {
		printf("Device %s is not ready\n", sensor->name);
		return 0;
	}

#if CONFIG_LIS2DH_TRIGGER
	{
		struct sensor_trigger trig;
		int rc;

		trig.type = SENSOR_TRIG_DATA_READY;
		trig.chan = SENSOR_CHAN_ACCEL_XYZ;

		if (IS_ENABLED(CONFIG_LIS2DH_ODR_RUNTIME)) {
			struct sensor_value odr = {
				.val1 = 1,
			};

			rc = sensor_attr_set(sensor, trig.chan,
					     SENSOR_ATTR_SAMPLING_FREQUENCY,
					     &odr);
			if (rc != 0) {
				printf("Failed to set odr: %d\n", rc);
				return 0;
			}
			printf("Sampling at %u Hz\n", odr.val1);
		}

		rc = sensor_trigger_set(sensor, &trig, trigger_handler);
		if (rc != 0) {
			printf("Failed to set trigger: %d\n", rc);
			return 0;
		}

		printf("Waiting for triggers\n");
		while (true) {
			k_sleep(K_MSEC(2000));
		}
	}
#else /* CONFIG_LIS2DH_TRIGGER */
	printf("Polling at 0.5 Hz\n");
	while (true) {
		fetch_and_display(sensor);
		k_sleep(K_MSEC(2000));
	}
#endif /* CONFIG_LIS2DH_TRIGGER */
}

// Copyright (c) 2024 Nordic Semiconductor ASA
// SPDX-License-Identifier: Apache-2.0

/dts-v1/;
#include <nordic/nrf52810_qfaa.dtsi>
#include "holyiot_21014_nrf52810-pinctrl.dtsi"

/ {
	model = "holyiot 21014 NRF52810";
	compatible = "holyiot,holyiot-21014-nrf52810";

	chosen {
		zephyr,sram = &sram0;
		zephyr,flash = &flash0;
		zephyr,code-partition = &slot0_partition;
	};


	buttons {
		compatible = "gpio-keys";
		sw0: button_0 {
			label = "button_0";
			gpios = <&gpio0 31 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
		};
	};

	leds {
		compatible = "gpio-leds";
		led_r: led_r {
			label = "Red LED";
			gpios = <&gpio0 29 (GPIO_ACTIVE_LOW | (1 << 8))>;
		};

		led_g: led_g {
			label = "Green LED";
			gpios = <&gpio0 30 (GPIO_ACTIVE_LOW | (1 << 8))>;
		};

		led_b: led_b {
			label = "Blue LED";
			gpios = <&gpio0 28 (GPIO_ACTIVE_LOW | (1 << 8))>;
		};
	};

	gpiocustom {
        compatible = "gpio-keys";
        lis2dh12_cs: lis2dh12_cs {
            gpios = <&gpio0 4 0>;
            label = "lis2dh12_cs";
        };
        lis2dh12_addr: lis2dh12_addr {
            gpios = <&gpio0 3 0>;
            label = "lis2dh12_addr";
        };
		lis2dh12_vdd: lis2dh12_vdd {
            gpios = <&gpio0 8 (1 << 9)>;
            label = "lis2dh12_vdd";
        };
    };
};

&flash0 {
	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		boot_partition: partition@0 {
			label = "mcuboot";
			reg = <0x0 0xc000>;
		};
		slot0_partition: partition@c000 {
			label = "image-0";
			reg = <0xc000 0xa000>;
		};
		slot1_partition: partition@16000 {
			label = "image-1";
			reg = <0x16000 0xa000>;
		};
		scratch_partition: partition@20000 {
			label = "image-scratch";
			reg = <0x20000 0xa000>;
		};
		storage_partition: partition@2a000 {
			label = "storage";
			reg = <0x2a000 0x6000>;
		};
	};
};


&gpio0 {
	status = "okay";
};

&gpiote {
	status = "okay";
};

&i2c0 {
	status = "okay";
	pinctrl-0 = <&i2c0_default>;
	pinctrl-1 = <&i2c0_sleep>;
	pinctrl-names = "default", "sleep";

	lis2dh@19 {
		compatible = "st,lis2dh";
		reg = <0x19>;
		label = "LIS2DH";
		irq-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>, <&gpio0 7 GPIO_ACTIVE_LOW>;
		//supply-gpios = <&gpio0 8 (1 << 9)>, <&gpio0 3 0>, <&gpio0 4 0>;
		supply-gpios = <&gpio0 8 0>, <&gpio0 3 0>, <&gpio0 4 0>;
	};
};

/*&spi0 {
	cs-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
	status = "okay";
	max-frequency = <DT_FREQ_M(8)>;
	pinctrl-0 = <&spi0_default>;
	pinctrl-names = "default";

	lis2dh_spi@0 {
		compatible = "st,lis2dh";
		reg = <0>;
		supply-gpios = <&gpio0 8 0>;
		spi-max-frequency = <DT_FREQ_M(8)>;
		irq-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>, <&gpio0 7 GPIO_ACTIVE_LOW>;
	};
};*/

&adc {
	status = "okay";
};

&pinctrl {

	/*spi0_default: spi0_default {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 0, 5)>,
					<NRF_PSEL(SPIM_MISO, 0, 3)>,
					<NRF_PSEL(SPIM_MOSI, 0, 2)>;
		};
	};*/

	i2c0_default {
		group1 {
			psels = <NRF_PSEL(TWIM_SDA, 0, 2)>, 
					<NRF_PSEL(TWIM_SCL, 0, 5)>;
		};
	};

	i2c0_sleep {
		group1 {
			psels = <NRF_PSEL(TWIM_SDA, 0, 2)>, 
					<NRF_PSEL(TWIM_SCL, 0, 5)>;
		};
	};
};

# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

CONFIG_SOC_SERIES_NRF52X=y
CONFIG_SOC_NRF52810_QFAA=y
CONFIG_BOARD_HOLYIOT_21014_NRF52810=y

# Enable MPU
CONFIG_ARM_MPU=y

# Enable hardware stack protection
CONFIG_HW_STACK_PROTECTION=y

# Enable RTT
CONFIG_USE_SEGGER_RTT=y

# enable GPIO
CONFIG_GPIO=y

# enable uart driver
CONFIG_SERIAL=y

# enable console
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

# additional board options
CONFIG_GPIO_AS_PINRESET=y

CONFIG_PINCTRL=y

# from lis2dh example
CONFIG_STDOUT_CONSOLE=y
CONFIG_I2C=y
CONFIG_SENSOR=y
CONFIG_CBPRINTF_FP_SUPPORT=y

I have some overlapping Kconfigs in prj.conf:

CONFIG_STDOUT_CONSOLE=y
CONFIG_I2C=y
CONFIG_SPI=y
CONFIG_SENSOR=y
CONFIG_CBPRINTF_FP_SUPPORT=y

CONFIG_LOG=y

CONFIG_LOG_PRINTK=y

CONFIG_USE_SEGGER_RTT=y

CONFIG_RTT_CONSOLE=y

Related