Reading a second register over SPI seemingly overwrites value from first register read.

I'm working in Windows using nRF Connect for VSCode and I'm trying to read registers from an ADXL345 over SPI. I have no issues reading the device ID in reg 0x00 but when I go to read the interrupt source reg 0x2D and print out its value, it seems to overwrite the value of the device ID retrieved previously. DEVID 0x00 and INT_SOURCE 0x2D register at power up have default values of 0xE5 and 0x02 respectively. I've never seen the act of writing to a variable affect a wholly different variable like this before.

read_reg() implementation:

static int read_reg(uint8_t reg, uint8_t *data, uint8_t size)
{
	int err;

	/* STEP 4.1 - Set the transmit and receive buffers */
	uint8_t tx_buffer = reg;
	struct spi_buf tx_spi_buf			= {.buf = (void *)&tx_buffer, .len = 1};
	struct spi_buf_set tx_spi_buf_set 	= {.buffers = &tx_spi_buf, .count = 1};
	struct spi_buf rx_spi_bufs 			= {.buf = data, .len = size};
	struct spi_buf_set rx_spi_buf_set	= {.buffers = &rx_spi_bufs, .count = 1};

	/* STEP 4.2 - Call the transceive function */
	err = spi_transceive_dt(&spi, &tx_spi_buf_set, &rx_spi_buf_set);
	if (err < 0) {
		LOG_ERR("spi_transceive_dt() failed, err: %d", err);
		return err;
	}

	return 0;
}

Overlay:

&spi21 {
    compatible = "nordic,nrf-spim";
    status = "ok";
    pinctrl-0 = <&spi21_default>;
    pinctrl-1 = <&spi21_sleep>;
    pinctrl-names = "default", "sleep";
    cs-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;

    accelerometer_spi: adxl345@0 {
        compatible = "adi,adxl345";
        reg = <0>;
        spi-max-frequency = <DT_FREQ_M(2)>;
        spi-cpha;
        spi-cpol;
        //cs-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
    };
};

&pinctrl {
    spi21_default: spi21_default {
        group1 {
            psels = <NRF_PSEL(SPIM_MISO, 1, 14)>, <NRF_PSEL(SPIM_MOSI, 1, 13)>;
        };
        group2 {
            psels = <NRF_PSEL(SPIM_SCK, 1, 11)>;
            bias-pull-up;
        };
    };

    spi21_sleep: spi21_sleep {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 1, 11)>,
                    <NRF_PSEL(SPIM_MOSI, 1, 13)>,
                    <NRF_PSEL(SPIM_MISO, 1, 14)>;
            low-power-enable;
        };
    };
};

Parents
  • I still don't quite understand why but it appears to have been fixed by:

    1. Transmitting the register + a dummy byte in read_reg() and,

    2. Setting MSb of reg (this is how read operations are defined for ADXL345)

    Of course also change the length of tx_buffer on line 7, like so:

    static int read_reg(uint8_t reg, uint8_t *data, uint8_t size)
    {
    	int err;
    
    	/* STEP 4.1 - Set the transmit and receive buffers */
    	uint8_t tx_buffer[] = {0x80 | reg, 0x00};
    	struct spi_buf tx_spi_buf			= {.buf = (void *)&tx_buffer, .len = sizeof(tx_buffer)};
    	struct spi_buf_set tx_spi_buf_set 	= {.buffers = &tx_spi_buf, .count = 1};
    	struct spi_buf rx_spi_bufs 			= {.buf = data, .len = size};
    	struct spi_buf_set rx_spi_buf_set	= {.buffers = &rx_spi_bufs, .count = 1};
    
    	/* STEP 4.2 - Call the transceive function */
    	err = spi_transceive_dt(&spi, &tx_spi_buf_set, &rx_spi_buf_set);
    	if (err < 0) {
    		LOG_ERR("spi_transceive_dt() failed, err: %d", err);
    		return err;
    	}
    
    	return 0;
    }

Reply
  • I still don't quite understand why but it appears to have been fixed by:

    1. Transmitting the register + a dummy byte in read_reg() and,

    2. Setting MSb of reg (this is how read operations are defined for ADXL345)

    Of course also change the length of tx_buffer on line 7, like so:

    static int read_reg(uint8_t reg, uint8_t *data, uint8_t size)
    {
    	int err;
    
    	/* STEP 4.1 - Set the transmit and receive buffers */
    	uint8_t tx_buffer[] = {0x80 | reg, 0x00};
    	struct spi_buf tx_spi_buf			= {.buf = (void *)&tx_buffer, .len = sizeof(tx_buffer)};
    	struct spi_buf_set tx_spi_buf_set 	= {.buffers = &tx_spi_buf, .count = 1};
    	struct spi_buf rx_spi_bufs 			= {.buf = data, .len = size};
    	struct spi_buf_set rx_spi_buf_set	= {.buffers = &rx_spi_bufs, .count = 1};
    
    	/* STEP 4.2 - Call the transceive function */
    	err = spi_transceive_dt(&spi, &tx_spi_buf_set, &rx_spi_buf_set);
    	if (err < 0) {
    		LOG_ERR("spi_transceive_dt() failed, err: %d", err);
    		return err;
    	}
    
    	return 0;
    }

Children
No Data
Related