SPI communication from slave to master

Hello,

I'm currently working on communication between two devices using SPI. I'm developing using nRF Connect SDK v1.9.1 on Laird's BL654 dev board. 

So far I'm testing communication between two separate dev boards with one acting as a slave device and another acting as the master. 

Master overlay:

&spi1{
    compatible = "nordic,nrf-spim";
    status = "okay";
    sck-pin = <23>;
    mosi-pin = <25>;
    miso-pin = <24>;
    cs-gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
};

Slave overlay:

&spi1 {
    compatible = "nordic,nrf-spis";
    status = "okay";
    sck-pin = <30>;
    mosi-pin = <28>;
    miso-pin = <29>;
    csn-pin = <31>;
    def-char = <0xAA>;
};

I'm able to communicate in one direction from the master to the slave using the spi_tranceive() function, but when I try to send a message back from the slave to the master I don't think anything is being received.

Master code:

/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <sys/printk.h>
#include <drivers/spi.h>
#include <string.h>

#define MSG_SIZE_TX		3

uint32_t tx_message_cnt = 0;

static uint8_t spim_rx_buffer[MSG_SIZE_TX];

#define MY_SPIM DT_NODELABEL(spi1)

const struct device * spim_dev;

struct spi_cs_control spim_cs_one = { 
	.gpio_pin = DT_GPIO_PIN(MY_SPIM, cs_gpios),
	.gpio_dt_flags = GPIO_ACTIVE_LOW,
	.delay = 0,
};

static const struct spi_config spim_cfg = {
	.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB |
		SPI_MODE_CPOL | SPI_MODE_CPHA,
	.frequency = 4000000,
	.slave = 0,
	.cs = &spim_cs_one,
};

static void spim_init(void)
{
	spim_cs_one.gpio_dev = device_get_binding(DT_GPIO_LABEL(MY_SPIM, cs_gpios));
	
	if(spim_cs_one.gpio_dev != NULL)
	{
		spim_dev = device_get_binding(DT_LABEL(MY_SPIM));
		if(spim_dev != NULL)
		{
			printk("\nSPIM Device: %s \n", DT_PROP(MY_SPIM, label));
			printk("SPIM CSN PIN %d, MISO PIN %d, MOSI PIN %d, CLK PIN %d\n",
				DT_GPIO_PIN(MY_SPIM, cs_gpios),
				DT_PROP(MY_SPIM, miso_pin),
				DT_PROP(MY_SPIM, mosi_pin),
				DT_PROP(MY_SPIM, sck_pin));
		}
		else
		{
			printk("\nSPIM Device: %s\n", DT_PROP(MY_SPIM, label));
		}
	}
	else
	{
		printk("Could not get GPIO LABEL %s device\n", DT_GPIO_LABEL(MY_SPIM, cs_gpios));
	}
}

struct spi_buf spim_rx_buf = {
	.buf = spim_rx_buffer,
	.len = sizeof(spim_rx_buffer),
};

struct spi_buf_set spim_rx = {
	.buffers = &spim_rx_buf,
	.count = 1,
};

void spi_test_receive(void)
{
	int cnt;
	uint8_t incr = 0;
	do{
		cnt = spi_transceive(spim_dev, &spim_cfg, NULL, &spim_rx);

		if(cnt > 0)
		{
			printk("SPIM RX: ");
			while(incr < MSG_SIZE_TX)
			{
				printk("0x%x ", spim_rx_buffer[incr]);
				incr++;
			}
			printk("\n\n");
		}
	}while(cnt < 1);
}

void main(void)
{
	printk("\n\n\nSPI Loop Back Example\n");
	printk("SPI Master");
	spim_init();
	while(1)
	{
		spi_test_receive();
	}
	/*do{
		spi_test_send();
		k_msleep(1000);
	}while(1);*/
}

Slave code:

/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <sys/printk.h>
#include <drivers/spi.h>
#include <string.h>

#define SPI_BUFFER_SIZE	3	

#define SPIS_DEVICE	DT_NODELABEL(spi1)

const struct device * spis_dev;

static uint8_t spis_tx_buffer[SPI_BUFFER_SIZE] = {0xff, 0xAA, 0x81};

static const struct spi_config spis_cfg = {
	.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB |
		SPI_OP_MODE_SLAVE | SPI_MODE_CPOL | SPI_MODE_CPHA,
	.frequency = 4000000,
	.slave = 1,
};

static void spis_init(void){
	spis_dev = device_get_binding(DT_LABEL(SPIS_DEVICE));

	if(spis_dev != NULL)
	{
		printk("\nSPIS Init: %s\n", DT_LABEL(SPIS_DEVICE));
	}
	else
	{
		printk("Could not init %s\n", DT_PROP(SPIS_DEVICE, label));
	}
}

struct spi_buf spis_tx_buf = {
	.buf = spis_tx_buffer,
	.len = sizeof(spis_tx_buffer),
};

struct spi_buf_set spis_tx = {
	.buffers = &spis_tx_buf,
	.count = 1,
};

void spis_send(void)
{
	int err;
	uint8_t incr;
	
	incr = 0;

	printk("SPIS TX TEST\n\n");

	err = spi_transceive(spis_dev, &spis_cfg, &spis_tx, NULL);

	if(err == 0)
	{
		printk("\n");
	}
	else
	{
		printk("SPIS error: %d \n", err);
	}
}

void main(void)
{
	spis_init();
	/*while(1)
	{
		spis_read();
	}*/
	do{
		spis_send();
		k_msleep(1000);
	}while(1);
}

I'm calling the slave transmit function every 1 second, and I'm calling the master receive function continuously in a while loop. I'm not sure if the problem is due to the master controlling the clock and chip select.

If I need to clarify anything or add any details about my code, please let me know. I'm a beginner to nRF Connect SDK.

Related