This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Clarification on intended driver to communicating with generic SPI device on nRF52 DK running Zephyr

I apologize if this has been asked in a different way but I have come across several older threads that seem outdated and was hoping for the new "best practices" for the current release of the nRF Connect SDK (v1.2.0) at the time of this writing.

I am trying to communicate with a "generic" SPI device. Unfortunately this is not a device already included in the Zephyr base.

Reading through the Zephyr documentation it seems that I must:

1. Write a device tree overlay compatible with "nordic,nrf-spim" that specifies the MISO, MOSI, and SCK pins

2. Add a child node compatible with "spi-device" that has a reg property equal to the pin I am using as CS pin (although there is some confusion here because there is also a property in the spi-controller device tree binding that specifies a "cs-gpios" and it seems that there is redundancy between this property and the "reg" property of the child node for the slave device)

3. Include a library that is aware of these device tree configurations

Currently my devicetree overlay file looks like this:

&spi0 {
	compatible = "nordic,nrf-spim";
	status = "okay";
	sck-pin = <25>;
	mosi-pin = <23>;
	miso-pin = <24>;
    rhd2132@22 {
        compatible = "spi-device";
        reg = <22>
        spi-max-frequency = <24000000>
        label = "RHD2132"
    };
};

Digging through the documentation it appears that there used to be a nordic driver for SPI devices in the nRF5 SDKs, but I guess that is no longer true in the nRF Connect SDK. It also looks like that driver did not rely on the devicetree system so all the pin configurations happen as #DEFINE's in the application code.

Instead it now appears that there is a driver located at <SDK_DIR>/zephyr/drivers/spi/spi_nrfx_spim.c.

Is this the appropriate driver to use. If so could you point me in the direction of the documentation for this driver and/or and example of it being used including the devicetree overlay file necessary? I assume I need to use this one if I want to take advantage of the DMA features of the nrf devices.

Again, I apologize for the confusion I think I am getting tripped up in the change from nRF5 to nRF Connect SDK and want to use the "most" supported method of communicating with SPI devices on nRF chips.

  • Hi, 

     

    Is this the appropriate driver to use. If so could you point me in the direction of the documentation for this driver and/or and example of it being used including the devicetree overlay file necessary? I assume I need to use this one if I want to take advantage of the DMA features of the nrf devices.

    When you set compatible = "nordic,nrf-spim";, you're telling dts to target the NRF_SPIM peripheral, which is DMA only.

    If you were to switch it out with "nordic,nrf-spi", you will use the older NRF_SPI module, which is not DMA capable. NRF_SPI is only supported on nRF51 and nRF52-series devices.

     

    Drivers-wise, you essentially have two options (zephyr choice is divided into two options):

    1. Use the generic Zephyr driver API

        a. Hard way: Create a full-blown zephyr based driver - this is normally not done unless you plan to do a pull-request to the zephyr-rtos project.

        b. Easier way: Setup the SPI instance in your application, then add the communication protocol on-top.

    2. Use the nordic specific nrfx driver directly

    You can use the Zephyr API to create your own driver. This includes creating Kconfig menu, device tree, and developing the sensor src and porting to use the spi.h API. This would then be a portable driver, which can theoretically run on any of the supported SPI "backends" (ie: x86, arm, xtensa, etc), but its not a straight forward process.

    You also have the option to use the nrfx_spim driver directly in your application, by adding CONFIG_NRFX_SPIM=y, then adding for instance CONFIG_NRFX_SPIM1=y.

     

    I made a quick example, based on zephyr/samples/basic/blinky/, where I added nrfx_spim, so that you can have a look at the steps for manually adding a nrfx driver to a sample.

    The sequence is very similar on other nrfx drivers (pdm, i2s, rtc, etc).

    nrfx_spim.zip

     

    I tested this on both nrf52_pca10040 board, and nrf9160_pca10090 board. You short MISO and MOSI pin to receive what you transmit.

    I also added a .overlay file for nrf52_pca10040, in case you want to look into adding the zephyr SPI driver.

    Again, I apologize for the confusion I think I am getting tripped up in the change from nRF5 to nRF Connect SDK and want to use the "most" supported method of communicating with SPI devices on nRF chips.

     This is nothing to apologize for. It is a huge change, and it is very understandable that you ask questions. Have you seen this blog post series? https://devzone.nordicsemi.com/nordic/nrf-connect-sdk-guides/b/getting-started/posts/nrf-connect-sdk-tutorial

    That should help with understanding how it all is tied together.

     

    Kind regards,

    Håkon

  • Hi Håkon,

    Thanks very much for the detailed reply and links to resources. I will spend some time digging into this.

  • Hi again,

    Small update: 

    I also have a old sample to interface zephyr spi API here: https://github.com/Rallare/fw-nrfconnect-nrf/blob/nrf9160_samples/samples/nrf9160/spi/src/main.c

    This will highly likely not compile with latest NCS, and especially towards nrf52-series (SPIM3 not present in most nRF52-series devices), but let me know if you want to try and get stuck somewhere.

     

    Kind regards,

    Håkon

  • Hi Håkon,

    I have finally had some more time to work on this. I decided I wanted to try and get the "Zephyr" option working so I was referring to the nrf9160 example you sent. At the moment I am just trying to get the "device_get_binding()" function to run properly and identify the SPI controller I am hoping to use. During complilation I get an error from the nrfx_spi library that says

    "'DT_NORDIC_NRF_SPI_SPI_1_IRQ_0_PRIORITY' undeclared (first use in this function); did you mean 'DT_NORDIC_NRF_SPIM_SPI_1_IRQ_0_PRIORITY'?"

     

    The surrounding code in the driver is this:

    	static int spi_##idx##_init(struct device *dev)			       \
    	{								       \
    		IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_SPI##idx),		       \
    			    DT_NORDIC_NRF_SPI_SPI_##idx##_IRQ_0_PRIORITY,      \
    			    nrfx_isr, nrfx_spi_##idx##_irq_handler, 0);	       \
    		return init_spi(dev);					       \
    	}	
    	
    	...
    	
    		static const struct spi_nrfx_config spi_##idx##z_config = {	       \
    		.spi = NRFX_SPI_INSTANCE(idx),				       \
    		.config = {						       \
    			.sck_pin   = DT_NORDIC_NRF_SPI_SPI_##idx##_SCK_PIN,    \
    			.mosi_pin  = DT_NORDIC_NRF_SPI_SPI_##idx##_MOSI_PIN,   \
    			.miso_pin  = DT_NORDIC_NRF_SPI_SPI_##idx##_MISO_PIN,   \
    			.ss_pin    = NRFX_SPI_PIN_NOT_USED,		       \
    			.orc       = CONFIG_SPI_##idx##_NRF_ORC,	       \
    			.frequency = NRF_SPI_FREQ_4M,			       \
    			.mode      = NRF_SPI_MODE_0,			       \
    			.bit_order = NRF_SPI_BIT_ORDER_MSB_FIRST,	       \
    			.miso_pull = SPI_NRFX_MISO_PULL(idx),		       \
    		}							       \
    	};	

    I also get some errors around where the pin assigments are made (also in code snippet above). For the record it looks like changing the SPI port I am trying to configure does properly populate the "idx" variable.

    Also here is my most up-to-date overlay file and proj.conf file

    # GPIO
    CONFIG_GPIO=y
    
    # SPI - Copied from Nordic nrf9160 samples
    CONFIG_SPI=y
    CONFIG_SPI_NRFX=y
    CONFIG_SPI_1=y
    CONFIG_SPI_1_NRF_SPIM=y

    &spi1 {
    	compatible = "nordic,nrf-spim";
    	status = "okay";
    	sck-pin = <25>;
    	mosi-pin = <23>;
    	miso-pin = <24>;
        rhd2132@22 {
            compatible = "spi-device";
            reg = <22>;
            spi-max-frequency = <24000000>;
            label = "RHD2132";
        };
    };

    Any ideas? In order to get things working in the short term I may just switch to the nrfx library that you suggested.

    Thanks again

  • Hi,

     

    nRF9160 has the NRF_SPIM peripheral only, not the legacy NRF_SPI peripheral.

    Have you manually created a driver for the rhd2132 in the zephyr tree (dts + .c / .h)? If not, that overlay section related to "rhd2132@22" will not work as you intend it to, and you should remove it from the overlay file.

     

    Kind regards,

    Håkon

Related