Struggling for several days to get SPI working w/ Zephyr

Hi, I can get ahold of the SPI device and call the spi_transceive function wihtout returning error codes.  Logic analyzer shows nothing happening, such as SCK clocking.  I am using the NRF52833-DK board.

In pj.conf:

CONFIG_SPI=y

In .dts:

can_spi: &spi1 {
    compatible = "nordic,nrf-spim";
    cs-gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
    pinctrl-0 = <&spi1_default>;
    pinctrl-1 = <&spi1_sleep>;
    pinctrl-names = "default", "sleep";
};

&pinctrl {
    spi1_default: spi1_default {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 1, 1)>,
                <NRF_PSEL(SPIM_MISO, 1, 2)>,
                <NRF_PSEL(SPIM_MOSI, 1, 3)>;
        };
    };

    spi1_sleep: spi1_sleep {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 1, 1)>,
                <NRF_PSEL(SPIM_MISO, 1, 2)>,
                <NRF_PSEL(SPIM_MOSI, 1, 3)>;
            low-power-enable;
        };
    };
};
In C module for SPI transactions:

#include <stdint.h>
#include <string.h>

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>                                                                                                                                                    
#include <zephyr/drivers/spi.h>
#include <zephyr/logging/log.h>

#include "spi_interface.h"

LOG_MODULE_REGISTER(spi_interface, LOG_LEVEL_INF);

static struct device * spi_dev;
static struct spi_buf tx_spi_buffer[1];
static struct spi_buf rx_spi_buffer[1];

static struct spi_config spi_cfg = {
    .frequency = 500000,
    .operation = SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) | SPI_LINES_SINGLE,
};

static const struct spi_buf_set api_tx_buff = { tx_spi_buffer, 1 };
static const struct spi_buf_set api_rx_buff = { rx_spi_buffer, 1 };

void spi_init(void)
{
    spi_dev = device_get_binding(DEVICE_DT_NAME(DT_NODELABEL(spi1)));

    if (spi_dev == NULL) {
        /* No such node, or the node does not have status "okay". */
        LOG_ERR("\nError: no device found.\n");
    }
    else if (!device_is_ready(spi_dev)) {
        LOG_ERR("\nError: Device \"%s\" is not ready; "
               "check the driver initialization logs for errors.\n",
               spi_dev->name);
    }
    else
    {
        LOG_INF("Found device \"%s\", getting sensor data\n", spi_dev->name);
    }
}

void spi_trx(uint8_t* tx_buf, uint8_t write_size, uint8_t* rx_buf, uint8_t read_size)
{
    tx_spi_buffer[0].buf = tx_buf;
    tx_spi_buffer[0].len = write_size;
 
    rx_spi_buffer[0].buf = rx_buf;
    rx_spi_buffer[0].len = read_size;

    int ret = spi_transceive(spi_dev,
                   &spi_cfg,
                   &api_tx_buff,
                   &api_rx_buff);

    if (ret < 0)
    {
        LOG_ERR("err code %d", ret);
    }
}
Parents
  • Hello, 

    • Do you get anything in the log output?
      • Can you please provide it here?
    • What version of nRF Connect SDK are you working on?
      • Have you based you application on a specific sample? 

    Kind regards,
    Øyvind

  • Hi Øyvind,

    -Are you referring to the .ninja_log?  Will provide when certain.

    -SDK version is 2.2.0

    --Yes, started with 'hello world' for nRF52833.  Have 802.15.4, GPIO output, GPIO inputs w/ interrupts, and        GPIOTE working

    Thank you!

    -Ben

  • Oh, I missunderstood.  Yes, it is outputting a '0', which is success.  I am printing over UART to NRF console.  I'll have a look and get back.  Thanks!

  • Hi Øyvind,

    The sample project has been helpful!  I think I may have found an issue though.  I choose nrf52833dk_nrf52833 as my board as that is my dev board.  When making my overlay, all the references, such as &spi2, are referencing nrf52dk_nrf52832.dts.  Thi pins specified do not match the dev board I have so could this be a bug with nRF Connect?  I figured I'd ask.

    Aside from that, I cannot get the example to compile  I am getting this now:

    zephyr\include\zephyr\device.h:83:41: error: '__device_dts_ord_DT_N_NODELABEL_mcp2517fd_BUS_P_cs_gpios_IDX_DT_N_NODELABEL_mcp2517fd_REG_IDX_0_VAL_ADDRESS_PH_ORD' undeclared here (not in a function)
       83 | #define DEVICE_NAME_GET(dev_id) _CONCAT(__device_, dev_id)
          |                                         ^~~~~~~~~
    C:\Users\Bmalch01\ncs\v2.2.0\zephyr\include\zephyr\device.h:209:37: note: in expansion of macro 'DEVICE_NAME_GET'
      209 | #define DEVICE_DT_NAME_GET(node_id) DEVICE_NAME_GET(Z_DEVICE_DT_DEV_ID(node_id))
          |                                     ^~~~~~~~~~~~~~~
    C:\Users\Bmalch01\ncs\v2.2.0\zephyr\include\zephyr\device.h:226:34: note: in expansion of macro 'DEVICE_DT_NAME_GET'
      226 | #define DEVICE_DT_GET(node_id) (&DEVICE_DT_NAME_GET(node_id))

    It cannot get a reference to the CS pin.  I had to add some tweaks to get the overlay to not have errors.  I'll highlight those:

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

        spi0_sleep: spi0_sleep {
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 0, 31)>,
                        <NRF_PSEL(SPIM_MOSI, 0, 30)>,
                        <NRF_PSEL(SPIM_MISO, 0, 29)>;
                low-power-enable;
            };
        };
    };

    can_spi: &spi0 {
        compatible = "nordic,nrf-spi";
        status = "okay";
        pinctrl-0 = <&spi1_default>;
        pinctrl-1 = <&spi1_sleep>;
        cs-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
        mcp2517fd: spi-dev-a@0 {
            //added this
    compatible = "spi-device";
            reg = <0>;
    //added this
            spi-max-frequency = < 500000 >;
        };
    };
  • Forgot to add this as it shows where the error is being generated:

    struct spi_cs_control spim_cs = {
        .gpio = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(mcp2517fd)),
        .delay = 0,
    };
  • It looks like I missed some steps in West.  I think this can be closed and I have to go back and familiarize myself with the initial env. setup.  Thanks for the SPI example though!  It was useful.

  • After realizing I made some dumb mistakes, I have it linking.  Figured I'd post in case someone else wants some snippets.  Thanks again!

    can_spi: &arduino_spi {
    {
        mcp2517fd: spi-dev-a@0{
            compatible = "spi-device";
            spi-max-frequency = < 500000 >;
            reg = < 0 >;
        };
    };
    #define CAN_SPI DT_NODELABEL(can_spi)
    #define CAN_SPI_CS DT_NODELABEL(mcp2517fd)

    LOG_MODULE_REGISTER(spi_interface, LOG_LEVEL_ERR);

    static const struct device * spi_dev;

    static struct spi_buf tx_spi_buffer[1];
    static struct spi_buf rx_spi_buffer[1];

    struct spi_cs_control spim_cs = {
        .gpio = DEVICE_DT_GET_ANY(CAN_SPI_CS),
        .delay = 0,
    };

    static struct spi_config spi_cfg = {
        .frequency = 500000,
        .operation = SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_MODE_CPOL | SPI_MODE_CPHA,
        .cs = &spim_cs
    };
Reply
  • After realizing I made some dumb mistakes, I have it linking.  Figured I'd post in case someone else wants some snippets.  Thanks again!

    can_spi: &arduino_spi {
    {
        mcp2517fd: spi-dev-a@0{
            compatible = "spi-device";
            spi-max-frequency = < 500000 >;
            reg = < 0 >;
        };
    };
    #define CAN_SPI DT_NODELABEL(can_spi)
    #define CAN_SPI_CS DT_NODELABEL(mcp2517fd)

    LOG_MODULE_REGISTER(spi_interface, LOG_LEVEL_ERR);

    static const struct device * spi_dev;

    static struct spi_buf tx_spi_buffer[1];
    static struct spi_buf rx_spi_buffer[1];

    struct spi_cs_control spim_cs = {
        .gpio = DEVICE_DT_GET_ANY(CAN_SPI_CS),
        .delay = 0,
    };

    static struct spi_config spi_cfg = {
        .frequency = 500000,
        .operation = SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_MODE_CPOL | SPI_MODE_CPHA,
        .cs = &spim_cs
    };
Children
Related