nRF52840: read SPI fast using nrfx_spim

Hello! Slight smile

We have a project where we are using the nRF52840 with the ADS7052 (an ADC) on the SPI bus. We are using Zephyr 4.1.0, but I guess its same same with nRF Connect SDK.

We need to read the ADC samples very fast, therefore I am using nrfx_spim directly.

The ADS7052 ADC sample readout works (simplified) as follows:

- falling edge of CS Pin, then read 3 bytes.

for another sample, we have to drive cs pin high and then go low again etc.

I tried to test that on the nRF52840DK. Read 10 samples, wait 2 seconds, repeat:

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <nrfx_spim.h>
#include <nrf_sys_event.h>
static nrfx_spim_t spim = NRFX_SPIM_INSTANCE(3);

static uint8_t rx_buf[3];                        // buffer to store the received data
static uint8_t tx_dummy[3] = {0xFF, 0xFF, 0xFF}; // 


int main(void)
{

	int ret;
	nrfx_err_t err_code;

	nrfx_spim_config_t spim_config = {
		.sck_pin = NRF_GPIO_PIN_MAP(1, 9),   // SCLK
		.miso_pin = NRF_GPIO_PIN_MAP(0, 12), // Master In Slave Out pin
		.ss_pin = NRF_GPIO_PIN_MAP(1, 0),
		.irq_priority = NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY,
		.orc = 0xFF,             // Over-run character
		.frequency = 16000000,   
		.mode = NRF_SPIM_MODE_3, 
		.bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST,
		.ss_active_high = false 
	};

	err_code = nrfx_spim_init(&spim, &spim_config, NULL, NULL);
	if (err_code != NRFX_SUCCESS) {
		LOG_ERR("spi init failed: %d", err_code);
	}

	int count = 5;
	nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(tx_dummy, 3, rx_buf, 3);
	while (1) {
		for (size_t i = 0; i < count; i++) {
			err_code = nrfx_spim_xfer(&spim, &xfer_desc, NRFX_SPIM_FLAG_REPEATED_XFER);
			if (err_code != NRFX_SUCCESS) {
				LOG_ERR("error reading SPI");
			}
		}
		LOG_INF("sleep..");
		k_sleep(K_SECONDS(2));
	}

}

on the oscilloscope, in green the cs pin, and in violet the SCLK.

It takes quiet a few us (4us) for the SCLK to start after the falling edge of CS. Also it takes very long (5.7us) for the cs pin to go high, when SCLK stops.

it takes about 6.6us for CS to go low again.

Reading the 10 samples is very slow, as we need to be faster. Are there any improvements I can make?

Thanks in Advance,

Visu

edit: I am aware that the current code does not read something properly, but currently I just want to look at the timing on the oscilloscope :)

Related