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

NRFX SPIM RX Buffer Remains Empty

Hi.  I don't believe this question would be strictly be considered a duplicate. I have seen posts discussing the same issue I'm having, but resolutions don't appear to solve my problem and are fairly stale overall.

I was hoping someone could check out my configuration below.  I'm using an nrf52840-dk with ncs 1.8.0, but trying to utilize nrfx drivers.

I'm simply reading and writing to an encoder counter IC (ls7366r).  Unfortunately, my RX buffers are not being populated with information upon reading; however, in looking at the traffic with my logic analyzer, everything appears to be working as expected, which leads me to believe this is a configuration issue on my end.  I should note, using the Zephyr APIs, this works fine (for frequencies under 2Mhz), so it is not a hardware issue:  I just wanted to apply nrfx drivers, as zephyr apis aren't allowing me to use any frequencies over 2MHz (still trying to figure that one out).

The logic analyzer traffic looks good and I believe all signal timings meet the requirements defined the IC's data sheet (https://lsicsi.com/datasheets/LS7366R.pdf).  As the encoder turns, the count increments and is viewable within the analyzer, which is illustrated in the screen shot provided (read command byte 0x60 followed by two bytes of count data); however, this information doesn't seem to write to my counter rx buffer.  This also applies to my reading back my register configs.

I am aware of that the first X bytes of an rx buffer would not contain my count information as that byte(s) would be attributed to the TX traffic.  In looking at log prints and debugging, the RX buffer elements all remain zero.

Thank you

#include <zephyr.h>
#include <drivers/gpio.h>
#include <nrfx_gpiote.h>
#include <nrfx_ppi.h>
#include <nrfx_spim.h>
#include <drivers/nrfx_errors.h>
#include <logging/log.h>

// #define HIGH_DRIVE

#define COUNTER_1X_QUAD 	0x01
#define COUNTER_2X_QUAD    	0x02    
#define COUNTER_4X_QUAD    	0x03

#define COUNTER_MODE_24    	0x01
#define COUNTER_MODE_16    	0x02
#define COUNTER_MODE_8      0x03 

#define WRITE_MDR0 		  	0x88
#define READ_MDR0          	0x48

#define READ_MDR1 		  	0x50
#define WRITE_MDR1		  	0x90

#define READ_CNTR 			0x60
#define WRITE_DTR 			0x98

#define CLR_STR 			0x30
#define CLR_CNTR 			0x20
#define LOAD_CNTR 			0xE0

#define SCK_PIN 	(47)
#define MISO_PIN	(46) 
#define MOSI_PIN	(45)
#define CS_PIN		(44)

static volatile bool spi_ready = true;

uint32_t position;

static const nrfx_spim_t spi_instance = NRFX_SPIM_INSTANCE(3);

static nrfx_spim_config_t spi_config = {
	.sck_pin 		= SCK_PIN,
	.mosi_pin 		= MISO_PIN,
	.mosi_pin 		= MOSI_PIN,
	.ss_pin 		= CS_PIN,
	.ss_active_high = false,
	.frequency 		= NRF_SPIM_FREQ_1M,
	// .frequency		= SPIM_FREQUENCY_FREQUENCY_K125,
	.mode			= NRF_SPIM_MODE_0,
	.bit_order		= NRF_SPIM_BIT_ORDER_MSB_FIRST,
	.orc			= 0xFF,
	.irq_priority   = NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY
};

LOG_MODULE_REGISTER(nrfx_encoder, LOG_LEVEL_INF);

void setMDRX(uint8_t mdr_write, uint8_t mdr_command, const char* reg_name)
{
	int err;
	uint8_t tx_buffer[2] = {mdr_write, mdr_command};
	uint8_t rx_buffer[] = {0x00}; //no feedback expected

	if (spi_ready == true)
	{
		spi_ready = false;
		nrfx_spim_xfer_desc_t transfer = {
			.p_tx_buffer = tx_buffer,
			.tx_length = sizeof(tx_buffer),
			.p_rx_buffer = rx_buffer,
			.rx_length = sizeof(rx_buffer)
		};
		err = nrfx_spim_xfer(&spi_instance, &transfer, 0);
		if (err != NRFX_SUCCESS) 
		{
			LOG_ERR("Write %s Error: %08x", reg_name, err);
			return;
		}
		while(spi_ready == false)
		{
			__WFE();
		}
	} else
	{
		LOG_ERR("SPI not Ready");
	}
}

void readMDRX(uint8_t read_reg_cmd, const char* reg_name)
{
	int err;
	uint8_t tx_buffer[] = { read_reg_cmd };
	uint8_t rx_buffer[2]; //get one byte back from MRD0 and/or MDR1

	if(spi_ready == true)
	{
		spi_ready = false;
		nrfx_spim_xfer_desc_t transfer = {
			.p_tx_buffer = tx_buffer,
			.tx_length = sizeof(tx_buffer),
			.p_rx_buffer = rx_buffer,
			.rx_length = sizeof(rx_buffer)
		};

		err = nrfx_spim_xfer(&spi_instance, &transfer, 0);
		if (err != NRFX_SUCCESS) 
		{
			LOG_ERR("%s Read Error: %08x", reg_name, err);
			return;
		} 

		while(spi_ready == false)
		{
			__WFE();
		}

		LOG_INF("%s Contents: %i", reg_name, rx_buffer[1]);
	} else
	{
		LOG_ERR("SPI not Ready");
	}
}

void clearRegs(uint8_t reg_clear_command)
{
	int err;
	uint8_t tx_buffer[] = {reg_clear_command};
	uint8_t rx_buffer[] = {0x00}; //no feedback expected
	
	if(spi_ready == true)
	{
		spi_ready = false;
		nrfx_spim_xfer_desc_t transfer = {
			.p_tx_buffer = tx_buffer,
			.tx_length = sizeof(tx_buffer),
			.p_rx_buffer = rx_buffer,
			.rx_length = sizeof(rx_buffer)
		};

		err = nrfx_spim_xfer(&spi_instance, &transfer, 0);
		if (err != NRFX_SUCCESS) 
		{
			LOG_ERR("Clear Error: %08x", err);
			return;
		}
		while(spi_ready == false)
		{
			__WFE();
		}
	} else
	{
		LOG_ERR("SPI not Ready");
	}
}

void readEncoder(void)
{
	int err;
	uint8_t tx_buffer[] = { READ_CNTR };
	uint8_t count_buffer[3]; // should get two bytes of data given my MDR1 settings (count_buffer[0] will be 0xFF from tx)

	if(spi_ready == true)
    {
		spi_ready = false;
		nrfx_spim_xfer_desc_t transfer = {
			.p_tx_buffer = tx_buffer,
			.tx_length = sizeof(tx_buffer),
			.p_rx_buffer = count_buffer,
			.rx_length = sizeof(count_buffer)
		};

		err = nrfx_spim_xfer(&spi_instance, &transfer, 0);
		if (err != NRFX_SUCCESS) 
		{
			LOG_ERR("Count Error: %08x", err);
			return;
		}

		while(spi_ready == false)
		{
			__WFE();
		}

		for (int i = 0; i <sizeof(count_buffer); i++)
		{
			LOG_INF("count_buffer[%i] = %zx", i, count_buffer[i]);
		}

        // position = (count_buffer[0] << 8) + count_buffer[1];
		// LOG_INF("Position: %i\n", position);
	} else
	{
		LOG_ERR("SPI not Ready to Count");
	}
}

static void spim_handler(nrfx_spim_evt_t const *p_event, void *p_context)
{
	if (p_event->type == NRFX_SPIM_EVENT_DONE) 
	{
		LOG_INF("transfer complete");
		spi_ready = true;
	}
}

void main(void)
{
	LOG_INF("Configuring SPI");

	nrfx_err_t err;

	#ifdef	HIGH_DRIVE
	LOG_INF("High Drive");

	nrf_gpio_cfg(CS_PIN,
				NRF_GPIO_PIN_DIR_OUTPUT,
				NRF_GPIO_PIN_INPUT_DISCONNECT,
				NRF_GPIO_PIN_PULLUP,
				NRF_GPIO_PIN_H0H1,
				NRF_GPIO_PIN_NOSENSE);

	nrf_gpio_cfg(SCK_PIN,
				NRF_GPIO_PIN_DIR_OUTPUT,
				NRF_GPIO_PIN_INPUT_DISCONNECT,
				NRF_GPIO_PIN_PULLDOWN,
				NRF_GPIO_PIN_H0H1,
				NRF_GPIO_PIN_NOSENSE);

	nrf_gpio_cfg(MOSI_PIN,
				NRF_GPIO_PIN_DIR_OUTPUT,
				NRF_GPIO_PIN_INPUT_DISCONNECT,
				NRF_GPIO_PIN_PULLDOWN,
				NRF_GPIO_PIN_H0H1,
				NRF_GPIO_PIN_NOSENSE);

	k_sleep(K_MSEC(100));
	#endif

	IRQ_CONNECT(SPIM3_IRQn, 0, nrfx_isr, nrfx_spim_3_irq_handler, 0);
	irq_enable(SPIM3_IRQn);

	err = nrfx_spim_init(&spi_instance, &spi_config, spim_handler, NULL);
	if (err != NRFX_SUCCESS) 
	{
		LOG_ERR("nrfx_spim_init error: %08x", err);
		return;
	}

	k_sleep(K_MSEC(250));
	clearRegs(CLR_STR);
	clearRegs(CLR_CNTR);
	setMDRX(WRITE_MDR0, COUNTER_1X_QUAD, "MDR0");
	k_sleep(K_MSEC(250));
	setMDRX(WRITE_MDR1, COUNTER_MODE_16, "MDR1");
	readMDRX(READ_MDR0, "MDR0");
	k_sleep(K_MSEC(250));
	readMDRX(READ_MDR1, "MDR1");

	while(1)
	{
		k_sleep(K_MSEC(2000));
		readEncoder();
	}
}
// prj.conf
CONFIG_LOG=y

CONFIG_SPI=n
CONFIG_NRFX_SPIM=y
CONFIG_NRFX_SPIM3=y
CONFIG_MAIN_STACK_SIZE=4096


Parents
  • Hello,

    It is a bit difficult for me to test this, because I don't have your SPI device. 

    Did you check that you are using the correct SPI mode in your spi_config? It should be quite quick to check all the modes.

    The zephyr implementation is using the nrfx drivers ultimately, so there is no particular reason why it wouldn't work.

    There is nothing from the log indicating that it shouldn't work, right? There are no errors (from your main.c) being printed?

    for debugging purposes, does the behavior change if you try to use another SPIM instance? I understand that you want to use SPIM3 for the speed, but for testing, can you try to use SPIM0?

    Best regards,

    Edvin

  • Hi Edvin

    Yes, the SPI mode is correct.  As I mentioned above, in reference to the logic analyzer images, everything looks perfect, the data is being read, and the traffic patterns mirror those I get when using Zephyr APIs - its simply that the count data isn't being written to my receiver buffer.  I did cycle through the different SPIM instances (and even cycled through the different SPI modes - just in case); however, the problem persisted.  I'll continue to explore as time permits - I'm sure it's something silly I'm overlooking.  Thanks for your help.

Reply
  • Hi Edvin

    Yes, the SPI mode is correct.  As I mentioned above, in reference to the logic analyzer images, everything looks perfect, the data is being read, and the traffic patterns mirror those I get when using Zephyr APIs - its simply that the count data isn't being written to my receiver buffer.  I did cycle through the different SPIM instances (and even cycled through the different SPI modes - just in case); however, the problem persisted.  I'll continue to explore as time permits - I'm sure it's something silly I'm overlooking.  Thanks for your help.

Children
No Data
Related