Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

NRF5 nrf_drv_spi_transfer discrepency vs zephyr spi_transceive

Hi,

I am interfacing to this st accel+gyro, which i can successfully turn on with an nrf52 on and read back the device id using the nrf5 sdk, by using nrf_drv_spi_transfer.

I'm having trouble getting a response now im using nrf connect 2.4.1 and zephyrs spi_transceive which is generating the same clock, CS, and MOSI output signals as nrf_drv_spi_transfer previously. One difference i can see is the MOSI was high when no data was transmitted used on the nrf5 and would be low on the nrf connect. Using the connect sdk I've tried changing the drive strength to all variants by altering nordic,drive-mode in the &pinctrl for my .overlay file but still have no luck.
When i scope the miso on either it defaults to a value of 0x0C on both implementations, but with no scope on the line for the nrf5 i get correct returned values. 
I should clarify, in the images below i'm sending 0x0F which is the who_am_i ID and its a read command so the first bit is high resulting in 0x8F which i get, and then 8 more clock cycles are given expecting a response on the MISO.
For reference here is the MOSI+ CLK, CS +CLK and MISO + CLK respectively for the nrf5 implementation:



and here is the MOSI+ CLK, CS +CLK and MISO + CLK for the nrf connect 2.4.1 implementation:
I was wondering if there are any listed differences between the default settings for gpio configurations in the legacy driver and the new spim (i believe the zephyr spi driver is just a wrapper on top of spim)?.
Any help or comments would be greatly appreciated. 
Kind regards,
Liam
  • Ahh okay, previously i was implementing my spi_transceive read so the tx and rx spi_buf .len properties were equal, i only needed a length of one for the tx spi_buf for the register address and then the rx buffer needed to have a length of 1 + read_length, now my device is reading back correclty, hope this helps anyone else struggling to transfer, see code:

    int spi_read_register(uint8_t reg, uint8_t *data, size_t len)
    {
        uint8_t tx_buffer[1];  // One byte for the register address + len bytes of dummy data for reading
        uint8_t rx_buffer[len + 1];
    
        tx_buffer[0] = reg | 0x80;
        //tx_buffer[1] = 0xFF;
        memset(&tx_buffer[1], 0x00, len);  // Fill the rest with dummy data
        const struct spi_buf tx_buf = {
            .buf = tx_buffer,
            .len = 1
        };
    
        const struct spi_buf rx_buf = {
            .buf = rx_buffer,
            .len = len+1
        };
    
        const struct spi_buf_set tx_set = {
            .buffers = &tx_buf,
            .count = 1
        };
    
        const struct spi_buf_set rx_set = {
            .buffers = &rx_buf,
            .count = 1
        };
        gpio_pin_set(gpio_dev, 22, 0);
        int ret = spi_transceive(spi_dev, &spi_cfg, &tx_set, &rx_set);
        gpio_pin_set(gpio_dev, 22, 1);
        if (ret != 0) {
            return ret;
        }
        // Copy the data, skipping the first byte since it's the echoed register address
        memcpy(data, &rx_buffer, len+1);
        return 0;
    } 

  • Quite so; you might want to fix this bug though (benign but compiler-dependent):

        memset(&tx_buffer[1], 0x00, len);  // Fill the rest with dummy data
    
        memset(&rx_buffer[1], 0x00, len);  // Fill the rest with dummy data
    

Related