Slow SPI performance with zephyr

SDK Environment: nRF Connect SDK v1.7.1

Target: Decawave DWM1001-DEV. This uses the nRF52832

A 5 byte SPI transfer is taking about 17us when using the nordic spim drivers and about 56us when using the zephyr spim drivers.

SPI CLK frequency = 8M

Would this be considered normal? The slow speed of the zephyr SPI drivers is causing problems in my application.

The zephyr drivers seem to be stable, but slow.

I set and clear a gpio testpin before and after the SPI transfer so I can measure the timing.

SPI timing with the nordic drivers

SPI timing with the zephyr drivers

"nrfx_spim.zip" uses the nordic drivers

"zephyr_spim.zip" uses the zephyr drivers

6763.nrfx_spim.zipzephyr_spim.zip

Parents
  • How do you set the SS signal?

    I had attached the source code for the two test cases in the first post.

    I am using Zephyr OS build v2.6.99-ncs1-1. This is the version that came with nRF Connect SDK v1.7.1

    The following is the source code for the zephyr test:

    /*
     * Copyright (c) 2016 Intel Corporation
     *
     * SPDX-License-Identifier: Apache-2.0
     */

    #include <zephyr.h>
    #include <device.h>
    #include <string.h>
    #include <drivers/gpio.h>
    #include <nrfx_spim.h>
    #include <device.h>
    #include <drivers/spi.h>
    #include <devicetree/spi.h>
    #include <assert.h>

    #define SLEEP_TIME  (100)       // ms
    #define SPI_BUF_SIZE (255)

    const struct gpio_dt_spec test_j7_pin3 = {.port = DEVICE_DT_GET(DT_NODELABEL(gpio0)), .pin = 12, .dt_flags = GPIO_ACTIVE_HIGH};

    const struct device* spi = DEVICE_DT_GET(DT_PARENT(DT_NODELABEL(dw1000_dev)));

    const static struct spi_config spi_config_dw1000 = SPI_CONFIG_DT(DT_NODELABEL(dw1000_dev), SPI_WORD_SET(8), 0);

    uint8_t tx_buf [SPI_BUF_SIZE];
    uint8_t rx_buf [SPI_BUF_SIZE];

    void setup_spim(void)
    {
        if (!device_is_ready(spi_config_dw1000.cs->gpio_dev))
        {
          printk("ERROR: spi gpio_dev not ready");
          for(;;);
        }

        if (!device_is_ready(spi))
        {
          printk("ERROR: failed to open spi");
          for(;;);
        }
    }

    /*
    * Setup output test pins for external monitoring.
    */
    void testPin1Set()
    {
        gpio_pin_set_dt(&test_j7_pin3, 1);
    }

    void testPin1Clear()
    {
        gpio_pin_set_dt(&test_j7_pin3, 0);
    }

    void testPinsSetup()
    {
        gpio_pin_configure_dt(&test_j7_pin3, GPIO_OUTPUT_INACTIVE);
    }

    void main(void)
    {
        testPinsSetup();
        setup_spim();

        printk("NRFX SPIM sample\n");
        printk("Read DW1000 DWT_DEVICE_ID\n");

        while (1)
        {
            k_msleep(SLEEP_TIME);

            testPin1Set();

            const int length = 5;
            memset(tx_buf, 0, length);
            memset(rx_buf, 0, length);

            struct spi_buf spi_buf_tx = {.buf = tx_buf, .len = length};
            struct spi_buf spi_buf_rx = {.buf = rx_buf, .len = length};

            struct spi_buf_set spi_buf_set_tx = {.buffers = &spi_buf_tx, .count = 1};
            struct spi_buf_set spi_buf_set_rx = {.buffers = &spi_buf_rx, .count = 1};

            spi_transceive(spi, &spi_config_dw1000, &spi_buf_set_tx, &spi_buf_set_rx);

            testPin1Clear();
            // Expecting DWT_DEVICE_ID   (0xDECA0130)        //!< DW1000 MP device ID
            printk("Result = %x\n", *((uint32_t*) &rx_buf[1]));
        }
    }
Reply
  • How do you set the SS signal?

    I had attached the source code for the two test cases in the first post.

    I am using Zephyr OS build v2.6.99-ncs1-1. This is the version that came with nRF Connect SDK v1.7.1

    The following is the source code for the zephyr test:

    /*
     * Copyright (c) 2016 Intel Corporation
     *
     * SPDX-License-Identifier: Apache-2.0
     */

    #include <zephyr.h>
    #include <device.h>
    #include <string.h>
    #include <drivers/gpio.h>
    #include <nrfx_spim.h>
    #include <device.h>
    #include <drivers/spi.h>
    #include <devicetree/spi.h>
    #include <assert.h>

    #define SLEEP_TIME  (100)       // ms
    #define SPI_BUF_SIZE (255)

    const struct gpio_dt_spec test_j7_pin3 = {.port = DEVICE_DT_GET(DT_NODELABEL(gpio0)), .pin = 12, .dt_flags = GPIO_ACTIVE_HIGH};

    const struct device* spi = DEVICE_DT_GET(DT_PARENT(DT_NODELABEL(dw1000_dev)));

    const static struct spi_config spi_config_dw1000 = SPI_CONFIG_DT(DT_NODELABEL(dw1000_dev), SPI_WORD_SET(8), 0);

    uint8_t tx_buf [SPI_BUF_SIZE];
    uint8_t rx_buf [SPI_BUF_SIZE];

    void setup_spim(void)
    {
        if (!device_is_ready(spi_config_dw1000.cs->gpio_dev))
        {
          printk("ERROR: spi gpio_dev not ready");
          for(;;);
        }

        if (!device_is_ready(spi))
        {
          printk("ERROR: failed to open spi");
          for(;;);
        }
    }

    /*
    * Setup output test pins for external monitoring.
    */
    void testPin1Set()
    {
        gpio_pin_set_dt(&test_j7_pin3, 1);
    }

    void testPin1Clear()
    {
        gpio_pin_set_dt(&test_j7_pin3, 0);
    }

    void testPinsSetup()
    {
        gpio_pin_configure_dt(&test_j7_pin3, GPIO_OUTPUT_INACTIVE);
    }

    void main(void)
    {
        testPinsSetup();
        setup_spim();

        printk("NRFX SPIM sample\n");
        printk("Read DW1000 DWT_DEVICE_ID\n");

        while (1)
        {
            k_msleep(SLEEP_TIME);

            testPin1Set();

            const int length = 5;
            memset(tx_buf, 0, length);
            memset(rx_buf, 0, length);

            struct spi_buf spi_buf_tx = {.buf = tx_buf, .len = length};
            struct spi_buf spi_buf_rx = {.buf = rx_buf, .len = length};

            struct spi_buf_set spi_buf_set_tx = {.buffers = &spi_buf_tx, .count = 1};
            struct spi_buf_set spi_buf_set_rx = {.buffers = &spi_buf_rx, .count = 1};

            spi_transceive(spi, &spi_config_dw1000, &spi_buf_set_tx, &spi_buf_set_rx);

            testPin1Clear();
            // Expecting DWT_DEVICE_ID   (0xDECA0130)        //!< DW1000 MP device ID
            printk("Result = %x\n", *((uint32_t*) &rx_buf[1]));
        }
    }
Children
No Data
Related