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

SPI Manager seems slower than using raw SPI master code

I am trying to migrate a blocking SPI transfer code to a non-blocking SPI Manager schedule call. I have 16 transfers queued up in one transaction.

When I launch it, the complete transaction takes ~300us. If I use the old code, the 16 transfers only take ~170us. Do you have any idea what may cause this? I was trying to understand the manager code, but could not see anything that would explain the slower communication.

Attaching a screenshot of one transaction (using the manager):

 

Using raw SPI master calls:

Code snippet I am using. Note, EasyDMA is turned on:

#define TRANSACTION_QUEUE_SIZE 3
#define
SPI_INSTANCE 0

static nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
NRF_SPI_MNGR_DEF(spi_mngr, TRANSACTION_QUEUE_SIZE, SPI_INSTANCE);
static nrf_spi_mngr_transfer_t transfers[16];

static uint16_t rx_buffer[16] = {0};
...


static nrf_spi_mngr_transaction_t transaction = {
.begin_callback = NULL,
.end_callback = emg_handle_received,
.p_user_data = NULL,
.p_transfers = transfers,
.number_of_transfers = 16,
.p_required_spi_cfg = NULL};

return nrf_spi_mngr_schedule(&spi_mngr, &transaction);

Thanks!
  • Hi,

     

    I did a 16 bytes x 16 transfers using the nrf_spi_mngr and it takes ~0.635 ms at 4 MHz at my end:

    Not sure about the amount of bytes each queued transferred at your end, or what your speed is, but it is close to the theoretical transfer time of  (1/4M * (16 bytes * 8) * 16 transfers) = 512 us.

    Here's my test-code, based on example spi_master_using_nrf_spi_mngr in SDK 14.2.

    /**
     * Copyright (c) 2017 - 2017, Nordic Semiconductor ASA
     * 
     * All rights reserved.
     * 
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     * 
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     * 
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     * 
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     * 
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     * 
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     */
    
    /** @file
     * @brief SPI Example Application main file.
     *
     * This file contains the source code for a sample application using nRF SPI manager and nRF GFX.
     */
    
    #include <stdio.h>
    #include "boards.h"
    #include "app_util_platform.h"
    #include "app_timer.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_drv_clock.h"
    #include "app_error.h"
    #include "app_timer.h"
    #include "nrf_spi_mngr.h"
    #include "st7565LCD.h"
    #include "nrf_lcd.h"
    #include "nrf_gfx.h"
    #include "bsp.h"
    
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define TRANSACTION_QUEUE_SIZE 3
    #define SPI_INSTANCE 0
    
    NRF_SPI_MNGR_DEF(spi_mngr, TRANSACTION_QUEUE_SIZE, SPI_INSTANCE);
    static nrf_spi_mngr_transfer_t transfers[16];
    static uint8_t tx_buffer[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
    APP_TIMER_DEF(m_timer);
    
    const nrf_drv_spi_config_t m_master0_config =
    {
        .sck_pin        = ARDUINO_13_PIN,
        .mosi_pin       = ARDUINO_11_PIN,
        .miso_pin       = ARDUINO_12_PIN,
        .ss_pin         = ARDUINO_10_PIN,
        .irq_priority   = APP_IRQ_PRIORITY_LOWEST,
        .orc            = 0xAA,
        .frequency      = NRF_DRV_SPI_FREQ_4M,
        .mode           = NRF_DRV_SPI_MODE_0,
        .bit_order      = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST
    };
    
    uint32_t spi_send(void);
    
    static void lfclk_config(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_clock_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_clock_lfclk_request(NULL);
    }
    
    
    static void timer_handler(void * p_context)
    {
        spi_send();
        nrf_gpio_pin_toggle(LED_1);
    }
    
    
    static void timer_interrupt_init(void)
    {
        ret_code_t err_code;
    
        err_code = app_timer_create(&m_timer, APP_TIMER_MODE_REPEATED, timer_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = app_timer_start(m_timer, APP_TIMER_TICKS(20), NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    void start_cb(void * p_user_data)
    {
        nrf_gpio_pin_toggle(LED_3);
    }
    
    void end_cb(ret_code_t result, void * p_user_data)
    {
        nrf_gpio_pin_toggle(LED_2);
    }
    
    uint32_t spi_send(void)
    {
        static nrf_spi_mngr_transaction_t transaction = 
        {
            .begin_callback = start_cb,
            .end_callback = end_cb,
            .p_user_data = NULL,
            .p_transfers = transfers,
            .number_of_transfers = 16,
            .p_required_spi_cfg = NULL
        };
    
        return nrf_spi_mngr_schedule(&spi_mngr, &transaction);    
    }
    
    int main(void)
    {
        lfclk_config();
        APP_ERROR_CHECK(app_timer_init());
        timer_interrupt_init();
        APP_ERROR_CHECK(nrf_pwr_mgmt_init());
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
        nrf_spi_mngr_init(&spi_mngr, &m_master0_config);
        nrf_gpio_range_cfg_output(LED_1, LED_4);
        
        for(int i = 0; i < sizeof(transfers)/sizeof(transfers[0]); i++)
        {
            transfers[i].p_tx_data = tx_buffer;
            transfers[i].tx_length = sizeof(tx_buffer);
        }
        NRF_LOG_INFO("SPI transaction manager example\n\r");
    
        while (true)
        {
            nrf_pwr_mgmt_run();
            NRF_LOG_FLUSH();
        }
    }
    
    

    Could you check if disabling the NRF_LOG module improves the scenario at your end? Could be uart prints that slows you down.

     

    Best regards,

    Håkon

  • Hi Håkon,

    I'm only sending/receiving 2 bytes per transfer, hence the 16 x 2 byte array. (uint16_t rx_buffer[16])

    At the time NRF_LOG was turned off, but I had the esb module on. Do you think that can cause slowdowns?

    Thanks  

  • Sounds like something in the system is blocking or delaying your transactions. It could be esb. You could try disabling that for testing purposes to double-check.

Related