How to configure the SPIM MOSI/MISO/SCK pins

How to configure the SPIM if i have defined my MOSI/MISO/SCK pins in the device overlay file, shown below:

&pinctrl {
spi0_default: spi0_default {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 0, 26)>,
<NRF_PSEL(SPIM_MISO, 0, 30)>;
};
};

spi0_sleep: spi0_sleep {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 0, 26)>,
<NRF_PSEL(SPIM_MISO, 0, 30)>;
};
};
};

&spi0 {
status = "okay";
pinctrl-0 = <&spi0_default>;
pinctrl-1 = <&spi0_sleep>;
pinctrl-names = "default", "sleep";
cs-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
};



and in the main.c file this, how I am configuring it


#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <nrfx_spim.h>

#define SPI_NODE DT_NODELABEL(spi0)

const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(0);

nrfx_spim_config_t cfg = {
.sck_pin = NRFX_SPIM_PIN_NOT_USED,
.mosi_pin = NRFX_SPIM_PIN_NOT_USED,
.miso_pin = NRFX_SPIM_PIN_NOT_USED,
.ss_pin = NRFX_SPIM_PIN_NOT_USED,
.frequency = NRF_SPIM_FREQ_8M,
.mode = NRF_SPIM_MODE_0,
.bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST,
};

nrfx_spim_init(&spi, &cfg, NULL, NULL);


But, apparently, no movement on the SCK pins. I am controlling the CS pin via GPIO, which is toggling at the given frequency. I am unable to connect my device overlay to the SPIM configuration. What am I missing?

However, it's working fine if I am defining the macros of all these pins and providing those macros in the config of spim, shown below:


 #define SPIM_MISO_PIN 30
 #define SPIM_SCK_PIN 26
 #define SPIM_CS_PIN 29

nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG(SPIM_SCK_PIN,
NRF_SPIM_PIN_NOT_CONNECTED,
SPIM_MISO_PIN,
NRF_SPIM_PIN_NOT_CONNECTED);
spi_config.sck_pin = SPIM_SCK_PIN;
spi_config.mosi_pin = NRF_SPIM_PIN_NOT_CONNECTED; // No MOSI pin
spi_config.miso_pin = SPIM_MISO_PIN;
spi_config.ss_pin = NRF_SPIM_PIN_NOT_CONNECTED; // No SS pin, using GPIOTE to toggle CNVST pin
spi_config.mode = NRF_SPIM_MODE_1; // CPOL = 0, CPHA = 1
spi_config.frequency = NRFX_MHZ_TO_HZ(8); // 8MHz


Thanks

  • In your main.c, it looks like you're setting the all the pins to NRFX_SPIM_PIN_NOT_USED and using it like that.  What happens if you put the correct pin values?

    What you're doing seems pretty manual.  Here's an example of something I'm working on... Note that I'm using an nRF54l15, so device names and pins will be different.  The waveshare_epd device is specific to my stuff - In this example I'm using SPI to connect to a display device from Waveshare.  You'll want to replace that with a reference to the driver for your device that's on the SPI bus.  If it's a custom device (or no definition already exists for it), you'll need a YAML file that describes it.

    &pinctrl {
        spi22_default: spi22_default {
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 1, 11)>,
                        <NRF_PSEL(SPIM_MOSI, 1, 12)>,
                        <NRF_PSEL(SPIM_MISO, 1, 13)>; /* optional, write-only display */
            };
        };
        spi22_sleep: spi22_sleep {
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 1, 11)>,
                        <NRF_PSEL(SPIM_MOSI, 1, 12)>,
                        <NRF_PSEL(SPIM_MISO, 1, 13)>;
                low-power-enable;
            };
        };
    };
    &spi22 {
        compatible = "nordic,nrf-spim";
        status = "okay";
        pinctrl-0 = <&spi22_default>;
        pinctrl-1 = <&spi22_sleep>;
        pinctrl-names = "default", "sleep";
        cs-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;   /* Chip select */
        clock-frequency = <20000000>;
        waveshare_epd: epd@0 {
            compatible = "waveshare,4in-eink";
            reg = <0>;
            spi-max-frequency = <20000000>;
            dc-gpios   = <&gpio0 0 0>;
            rst-gpios  = <&gpio0 1 0>;
            busy-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
            pwr-gpios  = <&npm1300_gpio 2 GPIO_ACTIVE_HIGH>;
            buck-en-gpios = <&npm1300_gpio 1 GPIO_ACTIVE_HIGH>;
            spi-rx-bits = <0>;  /* write-only */
        };
    };
    And that sets up the device for me.  I don't init the SPI bus.  The code does:
    // Get reference to SPI device from devicetree
    #define SPIOP   SPI_WORD_SET(8) | SPI_TRANSFER_MSB
    struct spi_dt_spec spispec = SPI_DT_SPEC_GET(DT_NODELABEL(waveshare_epd), SPIOP, 0);
    ...
        if (!spi_is_ready_dt(&spispec)) {
            LOG_ERR("SPI controller not ready");
            return;
        }
    ...
        gpio_pin_set_dt(&cs_pin, 0);
        struct spi_buf tx_spi_buf = {.buf = &cmd, .len = 1};
        struct spi_buf_set tx_spi_buf_set = {.buffers = &tx_spi_buf, .count = 1};
        int err = spi_write_dt(&spispec, &tx_spi_buf_set);
        if (err < 0) {
            LOG_ERR("spi_write_dt() failed, err %d", err);
        }
        gpio_pin_set_dt(&cs_pin, 1);

  • Hello,

    You set SPIM in the device tree using zephyr's pincntrl and in the code you used  nrfx nrfx_spim_init() configuration, which are completely independent. 

    You can look at this Lesson 5 - Serial Peripheral Interface (SPI) - Nordic Developer Academy lesson from devacademy to know how to implement SPI in the application.

Related