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

SPI DFU Bootloader

I'm trying to adapt the DFU bootloader to work with a SPI slave as the transfer mechanism, but I'm running into issues getting the SPI communication up and running. I've added a nrf_spi_dfu.c to the SDK and have configured everything so that it's getting pulled in and at least the transport init is running successfully. The problem I'm running into is that I never seem to get any SPI events either from incoming data or to signal a data output.

There's similar SPI communication occurring in the application, which is working fine, so pin configurations and the behavior of the external SPI master should all be fine. I've been able to confirm the SPI master behavior using a logic analyzer as well.

Am I missing something for setting up the SPI slave in the bootloader? What might be causing the slave to fail to communicate?

Terminal Output:

:INFO:Inside bootloader main
:DEBUG:In nrf_bootloader_init
:DEBUG:In real nrf_dfu_init
:DEBUG:running nrf_dfu_settings_init
:DEBUG:Enter nrf_dfu_continue
:ERROR:Single: Invalid bank
:DEBUG:Enter nrf_dfu_app_is_valid
:DEBUG:Return false in valid app check
:DEBUG:In nrf_dfu_transports_init
:DEBUG:num transports: 1
SPIS:INFO:Function: nrf_drv_spis_init, error code: NRF_SUCCESS.
SPI_DFU:DEBUG:nrf_spi_dfu.c: 42
SPIS:DEBUG:SPIS_BUFFER_RESOURCE_REQUESTED
SPIS:DEBUG:SPIS: Event: NRF_SPIS_EVENT_ACQUIRED.
SPIS:DEBUG:SPIS_BUFFER_RESOURCE_CONFIGURED
SPI_DFU:DEBUG:Got SPI event with type 0
SPIS:INFO:Function: nrf_drv_spis_buffers_set, error code: NRF_SUCCESS.
SPI_DFU:DEBUG:Set SPI buffers
:DEBUG:After nrf_dfu_transports_init
:DEBUG:------- nrf_dfu_flash_init-------
:DEBUG:Waiting for events

nrf_spi_dfu.c

#include "nrf_spi_dfu.h"

#include <stdint.h>
#include <stdbool.h>
#include "boards.h"
#include "nrf_dfu_transport.h"
#include "nrf_drv_spis.h"
#include "nrf_delay.h"

#define NRF_LOG_MODULE_NAME "SPI_DFU"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"

//lint -save -e545 -esym(526, dfu_spi_trans) -esym(528, dfu_spi_trans)
DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const dfu_spi_trans) =
{
    .init_func =        spi_dfu_transport_init,
    .close_func =       spi_dfu_transport_close
};
//lint -restore

#define SPI_RX_PACKET_MAX_SIZE  0x80                    /**< Maximum size of incoming payload data. */
#define SPI_TX_PACKET_MAX_SIZE  0x80                    /**< Maximum size of outgoing payload data. */
#define SPI_RX_BUFFER_SIZE      SPI_RX_PACKET_MAX_SIZE  /**< Maximum size of any SPI frame sent by the master. */
#define SPI_TX_BUFFER_SIZE      SPI_TX_PACKET_MAX_SIZE  /**< Maximum size of any SPI frame sent to the master. */

#define APP_SPIS_CS_PIN     11
#define APP_SPIS_MISO_PIN   10
#define APP_SPIS_MOSI_PIN    9
#define APP_SPIS_SCK_PIN     8
#define APP_SPI_IRQ         12

#define SPIS_INSTANCE 1 /**< SPIS instance index. */
static const nrf_drv_spis_t spis = NRF_DRV_SPIS_INSTANCE(SPIS_INSTANCE); /**< SPIS instance. */

static uint8_t m_tx_buf[SPI_TX_BUFFER_SIZE];  /**< TX buffer. (Read by SPIS hardware.) */
static uint8_t m_rx_buf[SPI_RX_BUFFER_SIZE];  /**< RX buffer. (Written by SPIS hardware.) */

static void spi_service(void)
{
    NRF_LOG_DEBUG("nrf_spi_dfu.c: %d\r\n", __LINE__);
    ret_code_t err_code;

    // Clear SPIS transmit buffer.
    memset(m_tx_buf, 0, sizeof(m_tx_buf));

    m_tx_buf[0] = 0xA5;
    m_tx_buf[1] = 0x5A;

    err_code = nrf_drv_spis_buffers_set(&spis, m_tx_buf, 2, m_rx_buf, sizeof(m_rx_buf));
    if (err_code == NRF_ERROR_INVALID_STATE)
    {
        NRF_LOG_ERROR("Failed to lock SPIS: dropped TX packet!\r\n");
    }
    else
    {
        APP_ERROR_CHECK(err_code);
        NRF_LOG_DEBUG("Set SPI buffers\r\n");
    }
}

static void spi_event_handler(nrf_drv_spis_event_t event)
{
    NRF_LOG_DEBUG("Got SPI event with type %d\r\n", event.evt_type);
    if (event.evt_type == NRF_DRV_SPIS_XFER_DONE)
    {
        NRF_LOG_DEBUG("Got transfer complete event\r\n");
        if (event.rx_amount > 0)
        {
            NRF_LOG_DEBUG("Received %d bytes\r\n", event.rx_amount);
        }
        if (event.tx_amount > 0)
        {
            NRF_LOG_DEBUG("Sent %d bytes\r\n", event.tx_amount);
        }

        spi_service();
    }
}

uint32_t spi_dfu_transport_init(void)
{
    // Set up IRQ to host pin
    nrf_gpio_pin_set(APP_SPI_IRQ);
    nrf_gpio_cfg_output(APP_SPI_IRQ);

    // Configure SPIS
    nrf_drv_spis_config_t spis_config = NRF_DRV_SPIS_DEFAULT_CONFIG;
    spis_config.csn_pin               = APP_SPIS_CS_PIN;
    spis_config.miso_pin              = APP_SPIS_MISO_PIN;
    spis_config.mosi_pin              = APP_SPIS_MOSI_PIN;
    spis_config.sck_pin               = APP_SPIS_SCK_PIN;
    spis_config.mode                  = NRF_DRV_SPIS_MODE_1;  /* (CPOL = 0, CPHA = 1). */
    spis_config.bit_order             = NRF_DRV_SPIS_BIT_ORDER_MSB_FIRST;
    spis_config.csn_pullup            = NRF_GPIO_PIN_NOPULL;

    uint32_t err_code;
    err_code = nrf_drv_spis_init(&spis, &spis_config, spi_event_handler);
    if (err_code != NRF_SUCCESS)
    {
        NRF_LOG_DEBUG("Error initializing SPI\r\n");
    }

    /* while (1) */
    /* { */
    /*     NRF_WDT->RR[0] = WDT_RR_RR_Reload; */
        spi_service();
    /*     __WFE(); */
    /* } */

    return NRF_SUCCESS;
}


uint32_t spi_dfu_transport_close(void)
{
    NRF_LOG_DEBUG("Closing SPI transport\r\n");

    nrf_drv_spis_uninit(&spis);

    return NRF_SUCCESS;
}

Parents
  • I've changed a few things since posting this, so there may be more complexity, but it seems like the crux of this issue was not enabling deferred logging. Presumably, printing out the logs was taking long enough/at the right time, to block the SPI from seeing the incoming signals from the master to allow it to send out data. Setting NRF_LOG_DEFERRED in sdk_config.h enabled the SPI slave to start sending out data successfully.

Reply
  • I've changed a few things since posting this, so there may be more complexity, but it seems like the crux of this issue was not enabling deferred logging. Presumably, printing out the logs was taking long enough/at the right time, to block the SPI from seeing the incoming signals from the master to allow it to send out data. Setting NRF_LOG_DEFERRED in sdk_config.h enabled the SPI slave to start sending out data successfully.

Children
No Data
Related