SPIS on NRF52840

I've been struggling bringing up a working SPIS test application and would appreciate any help I can get.  I'm much more of a HW person, so this hyper abstracted Zephyr stuff is not easy for me.

First Question:

In my overlay (see below) for the reg: attribute, I get the warning:  

Node spi-dev-a should have "compatible" property
Node should only occur on the undefined bus.

/soc/spi@40004000/spi-dev-a@0/

I've seen in https://devzone.nordicsemi.com/f/nordic-q-a/93484/struggling-to-use-spi-with-zephyr  

the following response:  "The overlay warnings I can see here also, but they don't seem to affect the example. I will try to find some time later to look into this."  referring to a similar warning, so I'm not sure if this actually an issue or not.

my_spis: &spi1 {
    compatible = "nordic,nrf-spis";
    status = "okay";
    pinctrl-0 = <&spi1_default>;
    pinctrl-1 = <&spi1_sleep>;
    pinctrl-names = "default", "sleep";
    cs-gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
    def-char = <0x00>;

    reg_my_spis: spi-dev-a@0 {
        reg = <0>;
    };

};


&spi1_default {
    group1 {
        psels = <NRF_PSEL(SPIS_SCK, 0, 31)>,
                <NRF_PSEL(SPIS_MOSI, 0, 30)>,
                <NRF_PSEL(SPIS_MISO, 1, 8)>;

    };
};

Are there any issues that are easily seen with this?

if (!device_is_ready(spi_cs.gpio.port)) and  if (!device_is_ready(spi_dev))  both report back that the SPI instance and the CS are ready.  So, I'm inclined to think that this is a non-issue.  Thoughts?
Second Question:
I am calling:  err = spi_transceive_cb(spi_dev, &spi_cfg, NULL, &rx, spi_slave_callback, NULL); which is constantly returning -22 (EINVAL).
Besides the overlay, here are the other relevant bits:
CONFIG_SPI=y
CONFIG_GPIO=y
CONFIG_SPI_SLAVE=y
CONFIG_SPI_ASYNC=y
CONFIG_DEBUG=y
CONFIG_PRINTK=y
#CONFIG_NRFX_SPIS1=y
CONFIG_USERSPACE=n
CONFIG_UART_CONSOLE=y
CONFIG_LOG=y
#CONFIG_LOG_BACKEND_RTT=n
CONFIG_LOG_BACKEND_UART=y
CONFIG_LOG_PRINTK=y
CONFIG_LOG_DEFAULT_LEVEL=4 


CONFIG_HEAP_MEM_POOL_SIZE=50512
#CONFIG_IDLE_STACK_SIZE=4096
#CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
CONFIG_MAIN_STACK_SIZE=4096


CONFIG_USE_SEGGER_RTT=n
#CONFIG_RTT_CONSOLE=n
CONFIG_SERIAL=y
struct spi_config spi_cfg = {
	.operation = SPI_WORD_SET(8) | SPI_OP_MODE_SLAVE | SPI_TRANSFER_MSB |
				 SPI_LINES_SINGLE,
	.frequency = 4000000,
	.slave = 0,
};
After the CS line is tested as ready:
	spi_cfg.cs = &spi_cs;
Here is setting the spi_cs_control struct:
static struct spi_cs_control spi_cs = {
	//	.gpio.pin = cs_gpio_pin,
	//	.gpio.dt_flags = cs_gpio_flags,
	.gpio = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(reg_my_spis)),
	.delay = 0,
};
Here is setting up the rx buffer:
		const struct spi_buf rx_buf = {
			.buf = buffer,
			.len = BUFFER_SIZE,
		};
		const struct spi_buf_set rx = {
			.buffers = &rx_buf,
			.count = 1,
		};
Here is the prototype for the CB:
void spi_slave_callback(const struct device *dev, int result, void *data)
There is a print statement upon enter the CB, so it's obviously not getting that far.
Does anything look obviously amiss here?  Does anyone have any suggestions on figuring out what is triggering the -EINVAL?  
Thank you for any guidance!
  • More information.....

    I changed my code to operate similar to the master/slave SPI example that is referenced in various Nordic SPI threads: NCS spi master/slave example

    In particular, adding in the kpoll method to watch for spi transaction completion.  Here are a couple of code snippets:

    	k_poll_signal_reset(&spi_slave_done_sig);
    	__asm__ volatile("nop");
    	err = spi_transceive_cb(spi_dev, &spi_cfg, NULL, &rx, spi_slave_callback, &spi_slave_done_sig);
    	__asm__ volatile("nop");
    	printf("Out of spi_transceive_cb\n RET: %d\n", err);
    	return (err);
    
    .................
    
    			printf("waiting... ");
    			do
    			{
    				err = spi_slave_check_for_message();
    			    printf(".");
    			} while (err < 0);
    			printf("\n");
    			
    .......................
    
    static int spi_slave_check_for_message(void)
    {
    	int signaled, result;
    	k_poll_signal_check(&spi_slave_done_sig, &signaled, &result);
    	if (signaled != 0)
    	{
    		return 0;
    	}
    	else
    		return -1;
    }

    The code/device sits and waits for the cs line to drop.  Once that happens the kpoll reset occurs and spi_transceive_cb is called as shown.  Then the code goes into the do while loop to look for completion of the SPI reception.  The completion never occurs and the device keeps printing '.' 's to the console.  It doesn't matter if I underflow the transmission, have it match the buffer definition exactly (8 bytes) or overflow, the spi reception never 'completes'.  

    It seems as though I'm missing something very fundamental here.  Thank you in advance for any insights.

  • Hi, 

    I am not sure why it is happening like this, while the code looks pretty much same like the SPI Master/Slave Sample.

    Have you tested the sample? Can you start with that and then modify / incorporate the changes you want.

  • Ok, here are some interesting results.

    I started a new project and pulled in the files from the master/slave GitHub repository (including the proj.conf file).  Modify nothing, build, and flash.  I get a toggling LED, as expected from the code.  However, I can not see any of the printk messages.

    As soon as I modify the proj.conf file so that I can see the printk output, I start having issues.  Here is the output:

    [00:00:00.249,93[00:00:00.250,244] <dbg> mpu: region_init: [2] 0x20012000 0x150b000a
    SPI master/slave example started
    --- 37 messages dropped ---
    SPI SLAVE TX: 0x00, 0x00
    SPI TX: 0x00, 0x00
    [00:00:00.250,427] <dbg> spi_nrfx_spim: spi_context_buffers_setup: tx_bufs 0x20012fc8 - rx_bufs 0x20012fb8 - 1
    [00:00:00.250,457] <dbg> spi_nrfx_spim: spi_context_buffers_setup: current_tx 0x20012fd0 (1), current_rx 0x20012fc0 (1), tx buf/len 0x200007e4/2, rx buf/len 0x200007e0/2
    [00:00:00.250,488] <dbg> spi_nrfx_spim: spi_context_update_tx: tx buf/len (nil)/0
    [00:00:00.250,518] <dbg> spi_nrfx_spim: spi_context_update_rx: rx buf/len (nil)/0
    [00:00:00.250,549] <dbg> spi_nrfx_spim: finish_transaction: Transaction finished with status 0
    SPI RX: 0x00, 0x00
    [00:00:00.250,640] <dbg> os: z_tick_sleep: thread 0x20000600 for 32768 ticks
    [00:00:00.250,671] <dbg> mpu: z_arm_configure_dynamic_mpu_regions: configure thread 0x20000000's domain
    [00:00:00.250,701] <dbg> mpu: z_arm_configure_dynamic_mpu_regions: configure domain: 0x20001448
    [00:00:00.250,701] <dbg> mpu: z_arm_configure_dynamic_mpu_regions: configure domain: 0x20001448
    [00:00:00.250,732] <dbg> mpu: z_arm_configure_dynamic_mpu_regions: configure user thread 0x20000000's context
    [00:00:00.250,762] <dbg> mpu: mpu_configure_region: Configure MPU region at index 0x2
    [00:00:00.250,793] <dbg> mpu: region_allocate_and_init: Program MPU region at index 0x2
    [00:00:00.250,793] <dbg> mpu: region_init: [2] 0x20002000 0x150b000a
    [00:00:00.249,938] <dbg> mpu: mpu_configure_region: Configure MPU region at index 0x2
    [00:00:00.250,976] <err> os: ***** MPU FAULT *****
    [00:00:00.251,007] <err> os:   Data Access Violation
    [00:00:00.251,007] <err> os:   MMFAR Address: 0x20002010
    [00:00:00.251,037] <err> os: r0/a1:  0x200020e0  r1/a2:  0x0000001c  r2/a3:  0x00000000
    [00:00:00.251,068] <err> os: r3/a4:  0x20002094 r12/ip:  0x0000000e r14/lr:  0x0000258f
    [00:00:00.251,068] <err> os:  xpsr:  0x01000000
    [00:00:00.251,098] <err> os: Faulting instruction address (r15/pc): 0x00000bda
    [00:00:00.251,159] <err> os: >>> ZEPHYR FATAL ERROR 2: Stack overflow on CPU 0
    [00:00:00.251,190] <err> os: Current thread: 0x20000000 (logging)
    [00:00:01.086,059] <err> os: Halting system

    Here is the modified proj.conf file:

    CONFIG_GPIO=y
    
    CONFIG_SPI=y
    CONFIG_SPI_ASYNC=y
    
    CONFIG_SPI_SLAVE=y
    
    CONFIG_DEBUG=y
    CONFIG_PRINTK=y
    #CONFIG_NRFX_SPIS1=y
    CONFIG_USERSPACE=y
    CONFIG_UART_CONSOLE=n
    CONFIG_LOG=y
    CONFIG_LOG_BACKEND_RTT=y
    CONFIG_LOG_BACKEND_UART=n
    CONFIG_LOG_PRINTK=y
    CONFIG_LOG_DEFAULT_LEVEL=4 
    CONFIG_USE_SEGGER_RTT=y
    CONFIG_RTT_CONSOLE=y
    CONFIG_SERIAL=y
    
    CONFIG_HEAP_MEM_POOL_SIZE=50512
    CONFIG_IDLE_STACK_SIZE=4096
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
    CONFIG_MAIN_STACK_SIZE=4096

    I had also tried a version to route the console to the UART, but was still not seeing output (am connected to UART0, UART0 is enabled and connected to the console per the dts file, UART1 is disabled per the overlay).

  • espian said:
    As soon as I modify the proj.conf file so that I can see the printk output, I start having issues.

    I am not sure why such is happening. 

    can you send your minimal project, just enough to show what you are facing. Please strip it down to minimal version just to show the functionality and error.

  • My last set of comments were with the GitHub master slave code with the only change being 1) changing several of the printk's to printf's and 2) the above changes to the proj.conf file.  

Related