SPI Communication Issue: Zephyr Driver Works, nrfx Driver Returns 0xFF

I'm having an issue with SPI communication. The problem is quite simple: if I use the Zephyr driver, everything works fine, but if I use the nrfx driver, it doesn't.
The function I call to read a register, Spi_Write_And_Read, using the Zephyr driver is:

&spi2 {
	compatible = "nordic,nrf-spim";
	status = "okay";
	pinctrl-0 = <&spi2_default>;
	pinctrl-1 = <&spi2_sleep>;
	pinctrl-names = "default", "sleep";
	cs-gpios = <&gpio0 24 GPIO_ACTIVE_LOW>;
	
	ad7779: ad7779@0 {
		compatible = "adi,ad7779";
		// compatible = "spi-device";
        reg = <0>;
        spi-max-frequency = <8000000>;
    };
};


static struct spi_dt_spec ad779SpiSpec = SPI_DT_SPEC_GET( DT_NODELABEL( ad7779 ), SPI_WORD_SET( 8 ) | SPI_TRANSFER_MSB | SPI_MODE_CPOL | SPI_MODE_CPHA, 0 );

spi_is_ready_dt( &ad779SpiSpec );

static int Spi_Write_And_Read( uint8_t *data, uint16_t len )
{
	const struct spi_buf spiTxBuff = { .buf = data, .len = len };
    const struct spi_buf spiRxBuff = { .buf = data, .len = len };
    const struct spi_buf_set tx = { .buffers = &spiTxBuff, .count = 1 };
    const struct spi_buf_set rx = { .buffers = &spiRxBuff, .count = 1 };

    return spi_transceive_dt( &ad779SpiSpec, &tx, &rx );
}

where *data is a pointer to a 2-byte buffer, with the first byte set to the value of the register I want to read, OR'ed with 0x80. This function works well and returns the buffer with the register value in the second byte.
However, if I modify the function to use:

&spi2 {
	compatible = "nordic,nrf-spim";
	status = "okay";
	pinctrl-0 = <&spi2_default>;
	pinctrl-1 = <&spi2_sleep>;
	pinctrl-names = "default", "sleep";
	cs-gpios = <&gpio0 24 GPIO_ACTIVE_LOW>;
	
	ad7779: ad7779@0 {
		compatible = "adi,ad7779";
		// compatible = "spi-device";
        reg = <0>;
        spi-max-frequency = <8000000>;
    };
};


static const nrfx_spim_t ad779SpiInstance = NRFX_SPIM_INSTANCE( 2 );
static nrfx_spim_config_t spiConfig = NRFX_SPIM_DEFAULT_CONFIG( AD7779_SCK_PIN, AD7779_MOSI_PIN, AD7779_MISO_PIN, AD7779_CS_PIN );

nrfx_spim_init( &ad779SpiInstance, &spiConfig, NULL, NULL );

static int Spi_Write_And_Read( uint8_t *data, uint16_t len )
{
    nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX( data, len, data, len );    
    nrfx_err_t err_code = nrfx_spim_xfer( &ad779SpiInstance, &xfer_desc, 0 );
    return ( err_code == NRFX_SUCCESS ) ? 0 : -1;
}

I only read 0xFF.
I checked with an oscilloscope and the SCK, MOSI, and MISO signals are identical in both cases. I'm starting to think it's a configuration issue, but I believe I've tried everything.
Do you have any suggestions?

Parents Reply Children
  • Hi,

     

    Could you try to split the buffers, ie. uint8_t * data_tx and data_rx, and see if this helps?

     

    Kind regards,

    Håkon

  • I have this function that I use to read the registers of my AD7779 (Analog Devices driver):

    int32_t ad7779_spi_int_reg_read(ad7779_dev *dev,
    				uint8_t reg_addr,
    				uint8_t *reg_data)
    {
    	uint8_t buf[3];
    	uint8_t buf_size = 2;
    	uint8_t crc;
    	int32_t ret;
    
    	buf[0] = 0x80 | (reg_addr & 0x7F);
    	buf[1] = 0x00;
    	buf[2] = 0x00;
    	if (dev->spi_crc_en == AD7779_ENABLE)
    		buf_size = 3;
    	ret = dev->spi_transmit(buf, buf_size);
    	// ret = dev->spi_read(buf[0], &buf[1], buf_size - 1);
    
    	*reg_data = buf[1];
    	if (dev->spi_crc_en == AD7779_ENABLE) {
    		buf[0] = 0x80 | (reg_addr & 0x7F);
    		crc = ad7779_compute_crc8(&buf[0], 2);
    		if (crc != buf[2]) {
    			// LOG_WRN("%s: CRC Error.\n", __func__);
    			ret = -1;
    		}
    	}
    
    	return ret;
    }

    The dev->spi_transmit function is my Spi_Write_And_Read. When I use this configuration:

    static struct spi_dt_spec ad779SpiSpec = SPI_DT_SPEC_GET( DT_NODELABEL( ad7779 ), SPI_WORD_SET( 8 ) | SPI_TRANSFER_MSB | SPI_MODE_CPOL | SPI_MODE_CPHA, 0 );
    
    err = spi_is_ready_dt( &ad779SpiSpec );
    
    if ( !err )
    {
        LOG_WRN( "SPI Eeg Sensor is not ready, err: %d", err );
        Error_Managing_Signal( SYSTEM_ERROR_INIT_EEG, __FILE__, __LINE__ );
        return SYSTEM_ERROR;
    }
    
    static int Spi_Write_And_Read( uint8_t *data, uint16_t len )
    {
    	const struct spi_buf txBuff = { .buf = data, .len = len };
        const struct spi_buf rxBuff = { .buf = data, .len = len };
        const struct spi_buf_set tx = { .buffers = &txBuff, .count = 1 };
        const struct spi_buf_set rx = { .buffers = &rxBuff, .count = 1 };
    
        return spi_transceive_dt( &ad779SpiSpec, &tx, &rx );
    }

    everything works.

    But if I use this alternative setup:

    static const nrfx_spim_t ad779SpiInstance = NRFX_SPIM_INSTANCE( 2 );
    static nrfx_spim_config_t spiConfig = NRFX_SPIM_DEFAULT_CONFIG( AD7779_SCK_PIN, AD7779_MOSI_PIN, AD7779_MISO_PIN, AD7779_CS_PIN );
    
    spiConfig.frequency = NRFX_MHZ_TO_HZ( 8 );
    spiConfig.mode = NRF_SPIM_MODE_3;
    spiConfig.bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST;
    
    if ( nrfx_spim_init( &ad779SpiInstance, &spiConfig, NULL, NULL ) != NRFX_SUCCESS )
    {
        Error_Managing_Signal( SYSTEM_ERROR_INIT_EEG, __FILE__, __LINE__ );
        return SYSTEM_ERROR;
    }
    
    static int Spi_Write_And_Read( uint8_t *data, uint16_t len )
    {
    	nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX( data, len, data, len );    
        nrfx_err_t err_code = nrfx_spim_xfer( &ad779SpiInstance, &xfer_desc, 0 );
        return ( err_code == NRFX_SUCCESS ) ? 0 : -1;
    }

    it no longer works, and ad7779_spi_int_reg_read returns 0xFF in reg_data.

    If I instead implement the function like this:

    static int Spi_Write_And_Read( uint8_t *data, uint16_t len )
    {
    	uint8_t dataTx[ len ];
        uint8_t dataRx[ len ];
        memcpy( dataTx, data, len );
        memset( dataRx, 0, len );
    
        LOG_WRN( "dataTx 0x%X 0x%X", dataTx[ 0 ], dataTx[ 1 ] );
        LOG_WRN( "dataRx 0x%X 0x%X", dataRx[ 0 ], dataRx[ 1 ] );
        nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX( dataTx, len, dataRx, len );    
        nrfx_err_t err_code = nrfx_spim_xfer( &ad779SpiInstance, &xfer_desc, 0 );
        LOG_WRN( "dataTx 0x%X 0x%X", dataTx[ 0 ], dataTx[ 1 ] );
        LOG_WRN( "dataRx 0x%X 0x%X", dataRx[ 0 ], dataRx[ 1 ] );
        return ( err_code == NRFX_SUCCESS ) ? 0 : -1;
    }

    I get the following output:

    00> [00:00:02.695,739] <wrn> adc: dataTx 0x91 0x0
    00> [00:00:02.695,739] <wrn> adc: dataRx 0x0 0x0
    00> [00:00:02.695,770] <wrn> adc: dataTx 0x91 0x0
    00> [00:00:02.695,800] <wrn> adc: dataRx 0xFF 0xFF

    Do you have any advice on what else I could try?

  • Hi,

     

    It is unclear to me what is the expected result.

    Q1: Could you share what value you expect to read?

     

    Q2: Could you also share a scope plot of the communication?

    As it is the MISO pin that is, as far as I understand, not reading correct, it would be interesting to see if the sensor shifts out correctly.

     

    Q3: What is the physical pin out that you use? Please share what AD7779_MISO_PIN is and what your pinctrl entries for spi2 are.

     

    Kind regards,

    Håkon

Related