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

SDK 15 software crash during SPI session.

Hi

After migration from SDK 14.0.0 to 15.0.0 our FW crashes during SPI session

We use EasyDMA , so we use SPIM driver directly without wrapper  nrf_drv_spi

The crash occurs in spim_xfer  function, immediately after spim_int_enable function calling.

We found some weird workaround. The problem disappears if we add delay in spim_xfer  function, immediately after  nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);

It looks like voodoo, so I would like to know what's going on and what's a write way to manage the problem appropriately.

Regards

  • Michao and I found the problem - it was in our code.

    We used to take FreeRTOS semaphore before OS Scheduler running and somehow it caused a fault.


    We used to trigger the SPIM and wait in a loop for FreeRTOS semaphore until the completion callback gives it.
    The problem was calling this code before FreeRTOS scheduler was run.


    I still don't know why the hard fault (taking semaphore per-se doesn't do that), but replacing the semaphore with nrf_delay_us(..) in case scheduler not running solved the issue.

    {
    //
    // ...        
    //
        context->busy = true;
        
        // init the context as non-blocking SPI
        if (NRF_SUCCESS != nrfx_spim_init(context->spi,
                                            &context->spi_config,
                                            xfer_complete_handler,
                                            context))
    
        {
            return 0;
        }
    
        xfer_desc.p_tx_buffer = write_buf;
        xfer_desc.tx_length =len;
        xfer_desc.p_rx_buffer = read_buf;
        xfer_desc.rx_length = len;
        
        // start SPI xfer
        if (NRF_SUCCESS != nrfx_spim_xfer (context->spi,
                                           &xfer_desc,
                                           0))
        {
            return 0;
        }
                
        while (context->busy)
        {
            //
            // !! this code block was wrong !!
            //
            
            // wait for xfer-complete
            if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING)
                xSemaphoreTake(context->tx_ready, SPI_MAX_BLOCKING_WAIT_TIME);
            else
                nrf_delay_us(10);
        }        
    
        spi_uninit(context);
    }        
    
    //
    // ...        
    //
    
    static void spi_uninit(spi_context_t* context)
    {
        nrfx_spim_uninit(context->spi);
        
        // fix SPIM3 current usage - according to errata 195
        // http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.rev1.errata%2Fanomaly_832_17.html
        if (context->spi == &g_spi_3_instance)
        {
            *(volatile uint32_t *)0x4002F004 = 1;
        }
    }        

  • I'd like to re-open this thread.  In our system we are using SPIM3 under SDK15.0 on nRF52840 and it's been working fine with no issues.  But, we start SD140, the first attempt to call nrfx_spim_xfer() will cause a hard fault.  If the SD140 isn't initialized, then everything works perfectly.  SPIM3 has been fully initialized before the SD140 is started.

    Looking at the resource usage document for SD140 6.0.0, it shows SPIM3 as completely open, so this behavior is unexpected.

    Perhaps an issue with interrupts or DMA?

    From sdk_config.h:

    #define NRFX_SPIM3_ENABLED 1
    #define NRFX_SPIM_EXTENDED_ENABLED 0

    CFLAGS += -DNRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED

  • We also have seen this again, in a different context, but haven't had time to create a simple test program. The anomaly 198 workaround must be enabled to produce the failure.

    Just now I found this in release_notes.txt for SDK 15.3.0, under known issues, there's this warning:

    - The workaround for Anomaly 198 for nRF52840 SPIM3 peripheral that has been implemented in nrfx_spim cannot be used with a SoftDevice.
    Flag NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED must be set to zero.
    The workaround based on a dedicated RAM block for SPIM3 must be used instead.

  • Creating a dedicated transfer buffer for SPIM3 transfers and locating it in RAM3.section1, and having our app RAM start at RAM5.section0 seems to resolve the issue.  I've removed the 198 workaround from CFLAGS.  SD140 and SPIM3 both seem to work now as expected.

    source file:

    uint8_t rx_buf[RX_BUF_SIZE] __attribute__((section(".spim3_safe")));
    uint8_t tx_buf[TX_BUF_SIZE] __attribute__((section(".spim3_safe")));

    .LD file:

    MEMORY
    {
    FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0xda000
    RAM_SPIM3 (rwx) : ORIGIN = 0x20007000, LENGTH = 0x03000
    RAM (rwx) : ORIGIN = 0x2000A000, LENGTH = 0x35F00
    RAM_NOINIT (rwx) : ORIGIN = 0x2003FF00, LENGTH = 0x00100
    }

    SECTIONS
    {
    . = ALIGN(4);
    .spim3_safe (NOLOAD) :
    {
    } > RAM_SPIM3
    .mem_section_dummy_ram :
    {
    }
    .log_dynamic_data :
    {
    PROVIDE(__start_log_dynamic_data = .);
    KEEP(*(SORT(.log_dynamic_data*)))
    PROVIDE(__stop_log_dynamic_data = .);
    } > RAM
    .fs_data :
    {
    PROVIDE(__start_fs_data = .);
    KEEP(*(.fs_data))
    PROVIDE(__stop_fs_data = .);
    } > RAM
    .noinit (NOLOAD) :
    {
    } > RAM_NOINIT

    } INSERT AFTER .data;

Related