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!
  • What issue have you not been able to replicate?

    If you are referring to the sample master-slave code example, I had posted that it was, in fact, operating properly, and that I was returning to dealing with the initial issues that I had posted about.

    Are you referring to the code and overlay that I followed up with, above?  That code has issues and definitely reacts the way I've described.  I actually just found a major reason for it, but have not had time to post the reason and the fix.

  • Hello,

    espian said:
    If you are referring to the sample master-slave code example, I had posted that it was, in fact, operating properly, and that I was returning to dealing with the initial issues that I had posted about.

    Yes, I was referring to the sample code (master/slave) and use with the DK.

    I did not test with your code, or with other boards.

    espian said:
    I actually just found a major reason for it,

    Good that you that you found the issue. 

    BR

  • Since there are a number of people subscribed to this ticket, I will document this issue and what fixed it.  Then wrap up with some other comments.

    The first two things that caused me issues were that the SPI samples I was finding were using the GPIOS definitions for the CS line.  In SPIS, that is not allowed.  Tracing back the -EINVAL error (and properly enabling the logged message) was the trick to figuring out this first step.  (You can see the result of this and the 'fix' above).

    Once past this hurdle, I had mentioned multiple times that there seemed to be something that I was fundamentally missing on understanding what within SPIS actually terminated an SPI message.  There is so much abstraction and so much that is 'automagically' done within the NRFSDK and Zephyr code bases, it is very difficult to know sometimes when you need to sit back and let the code-base do something for you and when you're required to handle something for yourself.  To be clear, I'm not an embedded newbie.  I have used SPI in designs starting in the early 1990's, so am pretty well versed in the hardware and typical software to support it.  Again, my issues here were largely around the things that were abstracted away and controlled by the software libraries and how they worked.

    I finally found in the Zephyr discord channel a mention that when using SPIS the driver expects to use the hardware CS line embedded in the SPI transceiver hardware and a follow-up mention of "don't forget to set your pinctrl's".

    In the overlay, I added 

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

    };
    };
    And almost immediately my code started working.  Simply the CS line was not 'connected' to the code and as such the end of message was never being triggered because it relies on the hardware CSN line to detect that state.  I'm still not sure where in the codebase this is setup/controlled.  I'm quite sure I would struggle to find it partially due to the lack of comments in the code.
    The frustrating thing(s) to me about all of this (semi-rant follows):
    1) I had expressed where I thought my short-coming was in my understanding (not know what or how an SPI message was terminated) and yet support never seemed to completely read through my messages and information to answer those specific questions.
    2) I feel like I went to great lengths to document as much as I could, what I perceived the issues to be and yet, the postings were never read in detail and responded to in a manner that took that information fully into account.
    3) There were multiple times that I posted follow-ups and yet the support responses continued to not respond to the most recent postings, but rather something further up the message thread (again not reading everything provided).
    4) So much of this codebase is horribly documented.  For instance, the spi_nrfx_spis.c file has zero comments (besides the copyright header) throughout 320 lines of code.  The comments sprinkled throughout other code files are equally bland--often just describing what an if statement is testing for (well, I can plainly see that) but rarely going into the 'why' .
    5) The sample code often has almost no comments within it, as well.  It seems like by taking the time to document some of this better, people would be much more likely to diagnose their own issues without bothering Nordic support. (Zero comments in the master-slave sample code or overlay)
    6) For both Nordic and Zephyr, if what you are wanting to do is largely in the mainstream, there are often samples that can be leveraged to allow you to develop fairly quickly, often without fully understanding everything that is going on under the hood.  If anything that you're working on is outside of the most common use-cases, it can be super difficult to almost reverse engineer what's going on to utilize the libraries properly, partially do to lack of proper documentation/examples/comments and partially due to the level of abstraction going on.  
    7) The Zephyr docs can be downright horrible.  Click on a library documentation and it's largely a list of function prototypes--this is not support documentation, I can read the code myself.
    8). I know many people that are much more accomplished and competent software/firmware developers than myself.  EVERYONE of them that have used the Nordic/Zephyr code bases had talked about how absolutely painful it is to learn these platforms.  Often times representing months of efforts to go up the learning curve to be somewhat proficient.  This simply shouldn't be so painful.
    Good luck!
Related