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

Parents
  • Michao and MartinBL,

    Was the cause of this problem ever diagnosed? Thanks.

    We've seen what sounds like the same problem with the nRF52840 DK, using SD140 v6.1.0, and nrfx v1.3.1. We are not using the full SDK, only nrfx. After we advertise a BLE peripheral, a spim_xfer() causes what appears to be a reset. If we create the peripheral but don't advertise, the problem does not occur. The problem occurs with SPIM, but not with TWIM or UART peripherals.

    I don't have a C test case right now because the code that causes this is written in CircuitPython, which is implemented as described above. But I could probably work one up if necessary.

    I set the HardFault_Handler to loop on a fault, so I could get a backtrace, but the handler doesn't appear to be entered, so I'm not sure what's causing the reset.

  • 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;
        }
    }        

Reply
  • 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;
        }
    }        

Children
Related