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

SDK15.2 SPI transfer stops after 16bits (no more clocks)

I have recently migrated from SDK 15.0 to 15.2 and are experiencing problems with my code.

I have a nRF52840DK and have attached two accelerometers to this board. I am able to talk to the accelerometers, and initialize them. This is done by short 2-bytes writes.

After initialization I want to read out 6 bytes from the accelerometer. This was achieved by setting up a transfer where I transfer one register address to the accelerometer (1 byte) and read out 6 bytes (7 incl the first do-not-care byte). The code is as follows:

    static const uint8_t tx_data[]= {0x86};
    uint8_t rx_data[]= {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    static nrf_spi_mngr_transfer_t spitransfer;
    
    spitransfer.p_tx_data = tx_data;
    spitransfer.tx_length = sizeof(tx_data);
    spitransfer.p_rx_data = rx_data;
    spitransfer.rx_length = sizeof(rx_data);
    
    nrf_drv_gpiote_out_clear(cs_pin_number);
    
    APP_ERROR_CHECK(nrf_spi_mngr_perform(m_mngr_spi, m_spi_config, &spitransfer, 1 , NULL));
    
    nrf_drv_gpiote_out_set(cs_pin_number);

This has worked with SDK 15.0. However, when migrating to 15.2 the transfer only generates 16 clock cycles. Hence, the transfer never completes. Is there an error in SDK15.2 or am I doing something wrong?

I have also tried to increase the transmit data, padding with zeros to have same length as rx_buffer, but this does not work either. Always stops after the first 16 clock cycles. Attached is scope plot of the transfer.

Scope plot of issue

Parents
  • Hey Geir,

    From the SDK 15.2 release notes:
    "Changed the default interrupt priority level for the peripherals from 7 to 6. This is done to be aligned with the priority of the SWI coming from the SoftDevice."

    I think you need to change #define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY from 7 to 6 in nrfx_config.h as well as  NRF_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY in sdk_config.h

    Cheers,

    Håkon.

Reply
  • Hey Geir,

    From the SDK 15.2 release notes:
    "Changed the default interrupt priority level for the peripherals from 7 to 6. This is done to be aligned with the priority of the SWI coming from the SoftDevice."

    I think you need to change #define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY from 7 to 6 in nrfx_config.h as well as  NRF_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY in sdk_config.h

    Cheers,

    Håkon.

Children
  • Hi Håkon,

    NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY is not defined in nrfx_config.h as it only links in sdk_config.h.

    The NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY was (and still is) set to 6 in sdk_config.h.

    Going through the code in more detail, I realized that I was using the old SPI driver and not SPIM. I am still having difficulties understanding which settings makes the driver switch from one to the other, but if I have debugged correctly, I need to set SPI0_ENABLED (or 1 or 2) _and_ SPI0_USE_EASY_DMA. Is this corect? Alll other settings related to SPI in sdk_config.h does not seem to influence which driver to use. 

    My first try with SPIM crashed at run-time as my transmit "buffer" were defined static const and the SPIM requires the tx_buffer to be in RAM. I wonder if the SPIM version of the driver should copy the transmit buffer as it is increasingly difficult to force compilers to keep static parts in RAM...

  • Most C compilers will put static const arrays[] into flash - this is expected on ARM architecture.

  • I think your comment about interrupts may have gotten me thinking: the code I execute is run inside a app_timer event, and if I remember correctly, the SWI0 interrupt is set to interrupt priority 6. So isn't it true that the interrupt from SPI will never happen as it is on the same priority? And that may be the reason why the SPI never transmitted more than 16 bits (without DMA)? I am rewriting the code to use SPIM, but I was wondering what best practice is regarding timers and peripherals.

    I need to sample the accelerometer every N millisecond and then do something with those data. Should the sampling of accelerometer happen in the main loop, using a flag to signal that I need to sample the accelerometer?

  • I know, but even taking away static const from the array definition may result in arrays being put in flash as the compiler finds out that they are not modified...

  • Ok. 

    Removing the SPI transactions from the app_timer event handler fixed the issue. So my initial thoughts about SDK error was wrong - problem between keyboard and chair. 

Related