SPI async comms between 2 nRF52dk boards using zephir (nRF Connect SDK v1.8.0)

I have to implement async communication between two nRF52832 chips. I am using two nRF52dk boards and nRF Connect SDK v1.8.0.

Following this case:

https://devzone.nordicsemi.com/f/nordic-q-a/69034/nrf52840-spi-slave-configuration-event_handler

Based on the spi_loopback as suggested on the case, I have managed to get a spi slave sample compiling and working in principle. Here it is the configuration and code:

SLAVE

prj.conf

#
# Copyright (c) 2020 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
#
# CONFIG_BOARD_ENABLE_CPUNET=y
CONFIG_SPI=y
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_SPI_SLAVE=y
CONFIG_SPI_ASYNC=y

# Config logger
CONFIG_LOG=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_LOG_BACKEND_RTT=y
CONFIG_LOG_BACKEND_UART=n
CONFIG_PRINTK=y
CONFIG_ASSERT=y

CONFIG_LOG=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y
CONFIG_PRINTK=y

CMakeList.txt

#
# Copyright (c) 2020 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
#

cmake_minimum_required(VERSION 3.8.2)

if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/spm.conf")
  set(spm_CONF_FILE
    prj.conf
    ${CMAKE_CURRENT_LIST_DIR}/spm.conf
  )
endif()

if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/mcuboot.conf")
  set(mcuboot_CONF_FILE
    prj.conf
    ${CMAKE_CURRENT_LIST_DIR}/mcuboot.conf
  )
endif()

if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${BOARD}.overlay")
  set(mcuboot_DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${BOARD}.overlay")
endif()

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(03-spis)

target_sources(app PRIVATE src/main.c)

nrf52dk_nrf52832.overlay

&spi1 {
	compatible = "nordic,nrf-spis";
	status = "okay";
	sck-pin = <22>;
	mosi-pin = <23>;
	miso-pin = <24>;
	csn-pin = <25>;
	def-char = <0xFF>;
};

main.c

/*
* 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>

#define DT_DRV_COMPAT nordic_nrf_spis

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

const struct device *spi_dev;

#define SPIS_STACK_SIZE 500
#define SPIS_PRIORITY 5

// TODO K_FOREVER should be used in K_THREAD_DEFINE but causes an error
#define K_FOREVER_WORKAROUND -1

extern void spi_test_transceive(void *, void *, void *);

K_THREAD_DEFINE(spis_tid, SPIS_STACK_SIZE, spi_test_transceive, NULL, NULL, NULL,
		SPIS_PRIORITY, 0, K_FOREVER_WORKAROUND);

static void spi_async_call_cb(struct k_poll_event *async_evt,
			      struct k_sem *caller_sem,
			      void *unused);

static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER(async_sig);
static struct k_poll_event async_evt =
	K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
				 K_POLL_MODE_NOTIFY_ONLY,
				 &async_sig);
static K_SEM_DEFINE(caller, 0, 1);
static int result = 1;
       
K_THREAD_DEFINE(async_thread, SPIS_STACK_SIZE,(k_thread_entry_t)spi_async_call_cb,
		&async_evt, &caller, NULL, K_PRIO_COOP(7), 0, 0);


static void spi_init(void)
{
  spi_dev = device_get_binding(DT_LABEL(DT_DRV_INST(0)));

  printk("SPI Init\n");
  printk("Device name: %s\n", DT_LABEL(DT_DRV_INST(0)));

  if (spi_dev == NULL) {
          printk("Could not get %s device\n", DT_LABEL(DT_DRV_INST(0)));
          return;
  }

  printk("SPI CSN %d, MISO %d, MOSI %d, CLK %d\n",
         DT_PROP(DT_DRV_INST(0), csn_pin),
         DT_PROP(DT_DRV_INST(0), miso_pin),
         DT_PROP(DT_DRV_INST(0), mosi_pin),
         DT_PROP(DT_DRV_INST(0), sck_pin));

  k_thread_start(spis_tid);
}

static void spi_async_call_cb(struct k_poll_event *async_evt,
			      struct k_sem *caller_sem,
			      void *unused)
{
	int ret;

	printk("SPI async callback started\n");

	while (1) {
        printk("Polling...\n");
		ret = k_poll(async_evt, 1, K_FOREVER);
		//zassert_false(ret, "one or more events are not ready");

		result = async_evt->signal->result;
		k_sem_give(caller_sem);

		/* Reinitializing for next call */
		async_evt->signal->signaled = 0U;
		async_evt->state = K_POLL_STATE_NOT_READY;
	}
}

void spi_test_transceive(void *unused1, void *unused2, void *unused3)
{
  int ret;
  static uint8_t tx_buffer[32] = { 's', 'p', 'i', 's', 'l',
                                   'a', 'v', 'e', '\n' };
  static uint8_t rx_buffer[32];

  const struct spi_buf tx_buf = { .buf = tx_buffer,
                                  .len = sizeof(tx_buffer) };
  const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1 };

  struct spi_buf rx_buf = { .buf = rx_buffer,
                            .len = sizeof(rx_buffer) };
  const struct spi_buf_set rx = { .buffers = &rx_buf, .count = 1 };

  printk("SPI Transcive Thread Started\n");

  while (1) {

    ret = spi_transceive_async(spi_dev, &spi_cfg, &tx, &rx, &async_sig);
    if (ret == -ENOTSUP) {
            printk("Not supported");
    }

    if (ret) {
            printk("Code %d", ret);
            //zassert_false(ret, "SPI transceive failed");
    }

    k_sem_take(&caller, K_FOREVER);

    if (result)  {
            printk("Call code %d", ret);
            //zassert_false(result, "SPI transceive failed");
    }
    else {		
            printk("byte received: %d\n", ret);
            printk("TX buffer [0]: %x\n", tx_buffer[0]);
            printk("RX buffer [0]: %x\n", rx_buffer[0]);
            tx_buffer[0]++;
    }
  }
}

void main(void)
{
    printk("SPIS Example\n");
    spi_init();

}

MASTER

The problem comes when I tried to implement the master project. First, I implemented the following changes

1. Commented out this line in prj.conf

#CONFIG_SPI_SLAVE=y

2. Changed spi_config to the following:

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

Unfortunately this changes will bring about the below error:

Device name: SPI_1
Could not get SPI_1 device

I tried to follow the comments on this case:

https://devzone.nordicsemi.com/f/nordic-q-a/60878/configuring-spi0---dt_nordic_nrf_spi_spi_0_irq_0_priority-undeclared

but adding any of these lines to prj.conf will cause a cmake error:

CONFIG_SPI_NRFX=y
CONFIG_SPI_0_NRF_SPIM=y

Any help getting a spi async master sample?

Thanks

Related