This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

how to initialize spi_cfg and switch the slave when multiple slaves on a same spi bus?

Hi Nordic,

In case of multiple slaves on the same spi bus, what is the best way to initialize 'spi_config' for spi_transceive() when Write device drivers using devicetree APIs by Option 1: create devices using instance numbers ?

Does SPI_CONFIG_DT_INST(instoperation_delay_)  can be used for multiple slaves on the same spi bus? and how to select or active the specific slave when call spi_transceive()?

two slave on same spi bus:

&spi2 {

	compatible = "nordic,nrf-spim";
	status = "okay";

	sck-pin = <4>;
	mosi-pin = <5>;
	miso-pin = <6>;

	cs-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>, <&gpio0 8 GPIO_ACTIVE_LOW>;

	ads129xr0: ads129xr@0 {
		compatible = "ti,ads129xr";
		label = "ADS129xR";
		reg = <0>;
		status = "okay";
		spi-max-frequency = <4000000>;

		pwdn-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
		reset-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
		drdy-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
		start-gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
	};
	
	ads129xr1: ads129xr@1 {
		compatible = "ti,ads129xr";
		label = "ADS129xR";
		reg = <1>;
		status = "okay";
		spi-max-frequency = <4000000>;

		pwdn-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
		reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
		drdy-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
		start-gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>;
	};
};

Device instantiation macro as below:

#define ADS129XR_INST(inst)										\
    static struct ads129xr_data ads129xr_data_##inst = {        \
        /* initialize RAM values as needed, e.g.: */            \
        .freq = DT_INST_PROP(inst, spi_max_frequency),          \
    };                                                          \
	const struct ads129xr_config ads129xr_cfg_##inst = {		\
	    /* initialize ROM values as needed. */                  \
		.start_gpio_spec = GPIO_DT_SPEC_INST_GET(inst, start_gpios),	\
		.ready_gpio_spec = GPIO_DT_SPEC_INST_GET(inst, drdy_gpios),	\
		.reset_gpio_spec = GPIO_DT_SPEC_INST_GET(inst, reset_gpios),	\
		.pwdwn_gpio_spec = GPIO_DT_SPEC_INST_GET(inst, pwdn_gpios),		\
		.ledpw_gpio_spec = GPIO_DT_SPEC_INST_GET(inst, ledpw_gpios),	\
		.spi_cfg = SPI_CONFIG_DT_INST(inst,			\
					   ADS129XR_SPI_OPERATION,	\
					   0),				\
    };                                                          \
    DEVICE_DT_INST_DEFINE(inst,				\
		ads129xr_init,						\
		NULL,								\
		&ads129xr_data_##inst,				\
		&ads129xr_cfg_##inst,				\
		POST_KERNEL,						\
		CONFIG_SENSOR_INIT_PRIORITY,		\
		&ads129xr_driver_api);


/* Call the device creation macro for each instance: */
DT_INST_FOREACH_STATUS_OKAY(ADS129XR_INST);

  • Does SPI_CONFIG_DT_INST(instoperation_delay_)  can be used for multiple slaves on the same spi bus? and how to select or active the specific slave when call spi_transceive()?

    I looked into the documentation, and it does not seem like using the Devicetree instance number is the way to go if you want to get a specific node (slave). Check out the comments given in Option 1: create devices using instance numbers and API Reference-->Devicetree-->Devicetree API

    "However, they only work when devicetree nodes for your driver’s compatible are all equivalent, and you do not need to be able to distinguish between them."

    "instance numbers in no way reflect any numbering scheme that might exist in SoC documentation, node labels or unit addresses, or properties of the /aliases node (use DT_NODELABEL() or DT_ALIAS() for those)

    there is no general guarantee that the same node will have the same instance number between builds, even if you are building the same application again in the same build directory"

    I would recommend you to go for Option 2: create devices using node labels instead, then you will be able to get a specific node (slave).

    Best regards,

    Simon

  • Hi Simon,

    I use DEVICE_DT_GET(node_idcan get the specific spi device and get the correct specific data which is the device chip id 0xd1 and 0xd2 as in picture below by call spi_transceive() in sensor_channel_get() function.

    There still have a problem, the sensor driver initiation function get the same chip id but sensor_channel_get function can get different chip id:

    main():

     

    #include <zephyr.h>
    #include <sys/printk.h>
    #include <drivers/sensor.h>
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS   1000
    #define ads129xr0 DT_NODELABEL(ads129xr0)
    #define ads129xr1 DT_NODELABEL(ads129xr1)
    
    void main(void)
    {
    	struct sensor_value value;
    	// const struct device *dev = DEVICE_DT_GET_ANY(ti_ads129xr);
    	const struct device *ads129xr0 = DEVICE_DT_GET(ads129xr0);
    	const struct device *ads129xr1 = DEVICE_DT_GET(ads129xr1);
    
    	if (!device_is_ready(ads129xr0)) {
    		printk("Device %s is not ready\n", ads129xr0->name);
    		return;
    	}
    	if (!device_is_ready(ads129xr1)) {
    		printk("Device %s is not ready\n", ads129xr1->name);
    		return;
    	}
    
    	sensor_channel_get(ads129xr0, SENSOR_CHAN_ALL, &value);
    	sensor_channel_get(ads129xr1, SENSOR_CHAN_ALL, &value);
    
    	// printk("ads129xr volt %d.%d\r\n", value.val1, value.val2);
    
    	printk("Hello World! %s\n", CONFIG_BOARD);
    	
    	while (1) {
    		// printk("Hello World! %s\n", CONFIG_BOARD);
    		k_msleep(SLEEP_TIME_MS);
    	}
    }
    

    I think the problem raised because at the beginning, both device CS are in active status during the first device call spi_tranceive(), so uncertain result received, the result maybe from the first device but also probably from the other one depends who's signal arrive MCU first.

Related