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

nRFX SPIM write causes fatal error & reboot when sending lots of data.

I am new to the nRF5 SDK. This is my first time using nRFX SPIM so this may well be a beginner error.

I'm using SDK version 17.02 and I am using a nRF52840 module.

I based my code off the nrfx_spim example found in the peripheral examples folder.

I am building, or porting across, code for a waveshare EPD 2in9 display module. I found that all other examples found online are using nrf spim method. I wanted to use the new nrfx option.

So for my set up I have done the following:

static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */

nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
    spi_config.frequency      = NRF_SPIM_FREQ_8M;
    spi_config.ss_pin         = EPD_SS_PIN;
    //spi_config.miso_pin       = EPD_MISO_PIN;
    spi_config.mosi_pin       = EPD_MOSI_PIN;
    spi_config.sck_pin        = EPD_SCK_PIN;
    spi_config.dcx_pin        = EPD_DCX_PIN;
    spi_config.use_hw_ss      = true;
    spi_config.ss_active_high = false;
    APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, spim_event_handler, NULL));

Then to write to SPI bus within my application I have (by way of example):

    uint8_t  m_tx_buf[4];

    memset(m_tx_buf, '\0', sizeof(m_tx_buf));
    m_tx_buf[0] = 0x44;           // SET_RAM_X_ADDRESS_START_END_POSITION
    m_tx_buf[1] = (Xstart >> 3) & 0xFF;
    m_tx_buf[2] = (Xend >> 3) & 0xFF;
    spi_write(&m_tx_buf, 3);

Then for event handler I have:

static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */

void spim_event_handler(nrfx_spim_evt_t const * p_event,
                       void *                  p_context)
{
    spi_xfer_done = true;
}

And for the SPI write function, I have:

/******************************************************************************
function :    SPI write command
parameter:
******************************************************************************/
static inline void spi_write(const void * data, size_t size)
{
    nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(data, size, NULL, 0);
    APP_ERROR_CHECK(nrfx_spim_xfer_dcx(&spi, &xfer_desc, 0, 1));    // first byte is always the command byte
    while (!spi_xfer_done)
    {
        __WFE();
    }
}

This works fine if data is a couple of bytes. However if I have something like this, it crashes the device and comes up with a fatal error message and keeps rebooting.

const uint8_t EPD_2IN9_lut_full_update[31] = {0x32,   // 1st param is the WRITE_LUT_REGISTER command
    0x50, 0xAA, 0x55, 0xAA, 0x11, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

const uint8_t EPD_2IN9_lut_partial_update[31] = {0x32,   // 1st param is the WRITE_LUT_REGISTER command
    0x10, 0x18, 0x18, 0x08, 0x18, 0x18,
    0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x13, 0x14, 0x44, 0x12,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

if(Mode == EPD_2IN9_FULL)
      spi_write(&EPD_2IN9_lut_full_update, sizeof(EPD_2IN9_lut_full_update));
else if(Mode == EPD_2IN9_PART)
      spi_write(&EPD_2IN9_lut_partial_update, sizeof(EPD_2IN9_lut_partial_update));
else {
        NRF_LOG_DEBUG("error, the Mode is EPD_2IN9_FULL or EPD_2IN9_PART");
        NRF_LOG_FLUSH();
}

I don't understand why. So all comment appreciated.

For my workaround, which mostly works (as in, I can run a simple demo), I had to implement the following:

/******************************************************************************
function :    SPI write command
parameter:
******************************************************************************/
static inline void spi_write(const void * data, size_t size)
{
    nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(data, size, NULL, 0);
    APP_ERROR_CHECK(nrfx_spim_xfer_dcx(&spi, &xfer_desc, 0, 1));
    //while (!spi_xfer_done)
    //{
        //__WFE();
    //}
    nrf_delay_ms(1);

}

void spim_event_handler(nrfx_spim_evt_t const * p_event,
                       void *                  p_context)
{
    //spi_xfer_done = true;

}

Related