nrf_gpio_pin_set causes random MCU resets during Manual-CS SPI transactions

I created a function, spi_read, that performs a SPI transaction to RAM, comprised of 400 chunks, each 96 bytes long.

The CS control is set to manual.

that function crashes every 5-30 runs, randomly, probably at the call to nrf_gpio_pin_set.

Please see its code below.

As a patch, I added a 1 microsecond wait after nrf_gpio_pin_set, which occurs after every chunk, which solves the issue,

If the PATCH segment is removed, the reset occurs randomly, every 5-30 runs.

I'm using the NRF52840, running SDK version 17.0.2.

astatus_t spi_read(const hal_spi_t * p_spi, uint16_t len, uint8_t reg_add, uint8_t * p_read_buf)
{
    astatus_t rc = AE_SUCCESS;
    spi_xfer_done = false;
    nrfx_spim_xfer_desc_t const tx_xfer_desc = NRFX_SPIM_XFER_TX(&reg_add, 1);
    nrf_gpio_pin_clear(p_spi->spi_manual_cs);
    if ( NRFX_SUCCESS != nrfx_spim_xfer(&m_spi_master[p_spi->spi_index], &tx_xfer_desc, 0) )
    {
        NRF_LOG_ERROR("atom_hal_spi_read_write nrfx_spim_xfer");
        rc = AE_FAILURE;
    }
    if (AE_SUCCESS == rc)
    {
        rc = wait_for_spi_completion(OP_TIMEOUT_MSEC);
    }
	if ( rc != AE_SUCCESS )
    {
        ATLOG_WARN("wait_for_spi_completion failed %d", rc);
        goto hal_spi_read_exit;
    }

    nrfx_spim_xfer_desc_t const rx_xfer_desc = NRFX_SPIM_XFER_RX(p_read_buf, len);
    spi_xfer_done = false;
    if ( NRFX_SUCCESS != nrfx_spim_xfer(&m_spi_master[p_spi->spi_index], &rx_xfer_desc, 0) )
    {
        NRF_LOG_ERROR("atom_hal_spi_read_write nrfx_spim_xfer");
        rc = AE_FAILURE;
    }
    if (AE_SUCCESS == rc)
    {
        rc = wait_for_spi_completion(OP_TIMEOUT_MSEC);
    }
hal_spi_read_exit:
    nrf_gpio_pin_set(p_spi->spi_manual_cs);
    
    /////////// PATCH
    atom_hal_time_delay_us(1);
    /////////// PATCH
    return rc;
}

How can I better solve this?

Parents
  • I do not see how adding a delay after pin set avoids a reset. We first need to know the reset reason before we can try to understand the context of the reset. As discussed in this thread, try to see if you can read the reset reason register after the reset happens, so that we can debug this further.

    If this turns out to be a soft-reset, this the application error handler could most likely be a reason. But at this point, we cannot debug this further without knowing the reason reason.

  • it might not be known why, but it is what happens nonetheless. Adding a 1 microsecond delay between SPI transactions, after CS being set to inactive, right before the next transaction begins and CS is set to active again, avoids the reset.

    The reset reason is 0.

    (The reset read operations shows 1 after I press the reset button, so I believe it is working properly.)

    The SPI configuration is:

            .conf =
            {
                .sck_pin = NRFX_SPIM_SCK_PIN,
                .mosi_pin = NRFX_SPIM_MOSI_PIN,
                .miso_pin = NRFX_SPIM_MISO_PIN,
                .ss_pin = NRFX_SPIM_PIN_NOT_USED,
                .ss_active_high = false,
                .irq_priority = NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY,
                .orc = 0xFF,
                .frequency = NRF_SPIM_FREQ_8M,
                .mode = NRF_SPIM_MODE_0,
                .bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST,
                NRFX_SPIM_DEFAULT_EXTENDED_CONFIG
            },

Reply
  • it might not be known why, but it is what happens nonetheless. Adding a 1 microsecond delay between SPI transactions, after CS being set to inactive, right before the next transaction begins and CS is set to active again, avoids the reset.

    The reset reason is 0.

    (The reset read operations shows 1 after I press the reset button, so I believe it is working properly.)

    The SPI configuration is:

            .conf =
            {
                .sck_pin = NRFX_SPIM_SCK_PIN,
                .mosi_pin = NRFX_SPIM_MOSI_PIN,
                .miso_pin = NRFX_SPIM_MISO_PIN,
                .ss_pin = NRFX_SPIM_PIN_NOT_USED,
                .ss_active_high = false,
                .irq_priority = NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY,
                .orc = 0xFF,
                .frequency = NRF_SPIM_FREQ_8M,
                .mode = NRF_SPIM_MODE_0,
                .bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST,
                NRFX_SPIM_DEFAULT_EXTENDED_CONFIG
            },

Children
Related