Possible SPI master bug when using DMA

Braver gravatar image

asked 2017-02-17 16:07:43 +0100

Hello,

I've been implementing DAC control trough SPI and DMA using the NRF52 and it is working nicely. During development however I encountered what i think is a bug in the SPI master driver. It occurs when calling the nrf_drv_spi_xfer function in combination with the NRF_DRV_SPI_FLAG_HOLD_XFER flag as illustrated below:

nrf_drv_spi_xfer_desc_t xfer_disc = NRF_DRV_SPI_XFER_TX(packet, transfer_length);

uint32_t spi_flags =    NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER    |
                        NRF_DRV_SPI_FLAG_HOLD_XFER              |
                        NRF_DRV_SPI_FLAG_TX_POSTINC             |
                        NRF_DRV_SPI_FLAG_REPEATED_XFER;

APP_ERROR_CHECK(nrf_drv_spi_xfer(&spi_dac_instance, &xfer_disc, spi_flags));

This causes the SPI master driver to hang. i've isolated this to the spim_xfer() function in nrf_drv_spi.c of which I included a snippet below.

if (!(flags & NRF_DRV_SPI_FLAG_HOLD_XFER))
{
    nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);
}

if (!p_cb->handler)
{
    while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END)){}
    if (p_cb->ss_pin != NRF_DRV_SPI_PIN_NOT_USED)
    {
        nrf_gpio_pin_set(p_cb->ss_pin);
    }
}
    else
    {
        spim_int_enable(p_spim, !(flags & NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER));
    }
err_code = NRF_SUCCESS;

because the start task isn't triggered because of the HOLF_XFER flag the subsequent while loop hangs as the SPI module can't finish what it didn't start. I've fixed this by simply encasing it al in the first if statement as such:

if (!(flags & NRF_DRV_SPI_FLAG_HOLD_XFER))
{
    nrf_spim_task_trigger(p_spim, NRF_SPIM_TASK_START);    

    if (!p_cb->handler)
    {
        while (!nrf_spim_event_check(p_spim, NRF_SPIM_EVENT_END)){}
        if (p_cb->ss_pin != NRF_DRV_SPI_PIN_NOT_USED)
        {
            nrf_gpio_pin_set(p_cb->ss_pin);
        }
    }else{
            spim_int_enable(p_spim, !(flags & NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER));
    }
}
err_code = NRF_SUCCESS;

So i think this is a problem with the SPI driver but i might just be calling something in the wrong way, any input would be very helpful.

Regards,

Braver

edit retag flag offensive close delete report spam

Comments

I agree that this can happen, but I don't see when you need to use the NRF_DRV_SPI_FLAG_HOLD_XFER flag if you don't have an event handler. You will need to know in the application when the transfer is finished, so if you don't have an event handler you will have to add the while loop in main after you trigger the start task.

Ole Bauck ( 2017-02-20 13:24:28 +0100 )editconvert to answer

It was my understanding that the NRF_DRV_SPI_FLAG_HOLD_XFER flag can be used in combination with PPI. We would program the spi peripheral with the right parameters and then generate repeated start events using a timer. A counter would then count the spi start events and notify the CPU when the data has run out and needs to be refreshed, again calling the spi_xfer function. A spi event handler in this situation would just invoke unnecessary interrupts.

Braver ( 2017-02-21 15:10:23 +0100 )editconvert to answer

Ok, I did not realize that you where using the list feature (the NRF_DRV_SPI_FLAG_TX_POSTINC flag will enable this). Then I understand your problem.

I will report this internally

Ole Bauck ( 2017-02-21 16:52:30 +0100 )editconvert to answer
1

Thank you. I had the same problem with the endless loop. Sad that there are no examples for the advanced use cases in the SDK so somebody could discover issues with that. It is still present in the version 13.

codezork ( 2017-05-15 21:27:32 +0100 )editconvert to answer