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

SDK 15.0 SPIM Example Issue on nRF52840

Hey all,

I am trying to run the "nrfx_spim" example on my nRF52840 USB Dongle (Makerdiary nRF52840 USB dongle), however it is not working. It looks like the code is never reaching the interrupt handler "spim_event_handler()". The example code is using SPI3 to run this example, and I confirmed that NRFX_SPIM3 is enabled in the sdk_config.h.

This is a dongle, so I don't have a way of seeing any of the NRF_LOG entries unfortunately.

nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
spi_config.frequency      = NRF_SPIM_FREQ_1M;
spi_config.ss_pin         = NRFX_SPIM_SS_PIN;
spi_config.miso_pin       = NRFX_SPIM_MISO_PIN;
spi_config.mosi_pin       = NRFX_SPIM_MOSI_PIN;
spi_config.sck_pin        = NRFX_SPIM_SCK_PIN;
spi_config.dcx_pin        = NRFX_SPIM_DCX_PIN;
spi_config.use_hw_ss      = true;
spi_config.ss_active_high = true;
spi_config.mode           = NRF_SPIM_MODE_1; 

APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, spim_event_handler, NULL));

Here is the interrupt handler:

void spim_event_handler(nrfx_spim_evt_t const * p_event,
                       void *                  p_context)
{
	bsp_board_led_invert(BSP_BOARD_LED_1);

    spi_xfer_done = true;
    NRF_LOG_INFO("Transfer completed.");
    if (m_rx_buf[0] != 0)
    {
        NRF_LOG_INFO(" Received:");
        NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
    }
}

Here is the main loop that is supposed to send out a packet every 200 ms:

while (1)
{
    // Reset rx buffer and transfer done flag
    memset(m_rx_buf, 0, m_length);
    spi_xfer_done = false;

	APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, 0));


    while (!spi_xfer_done)
    {
        __WFE();
    }

    NRF_LOG_FLUSH();

    bsp_board_led_invert(BSP_BOARD_LED_1);
    nrf_delay_ms(200);
}

I checked the SPI lines on my oscilloscope, and I see that the SS pin goes high (I have it set to active high polarity), the SPI clock runs, and I can see data being pushed out on the MOSI pin. However, after the transaction ends, the SS pin does not go back low, and the interrupt handler does not trigger. I reckon the issue is with the end of the transaction, but can't figure out what's wrong. I hope someone can help, thanks!

  • Hi

    Have you adapted the example to run on the Dongle? Please check out the Dongle Programming tutorial and the Adapt a simple example (without SoftDevice) section to see how to adapt your project to fit the Dongle.

    Best regards,

    Simon

  • This seems to be a common mistake when using SPI, covered quite a few times here on the devzone so maybe worth looking through some of those posts. In brief the received data is actually the 2nd byte, not the 1st byte. Change this:

        if (m_rx_buf[0] != 0)

    to this:

        if (m_rx_buf[1] != 0)

    mrxbuf must of course be at least 2 bytes long, and the requested received data length must be at least 2 bytes; 1 byte will not work as the SPI slave doesn't know what data to send until it has received and decoded the first transmitted byte.

  • Thanks for the reply Simon. I have some updates:

    When I don't pass a function for the SPI event handler, such that I initialize SPIM like this:

    APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, NULL, NULL));

    Without interrupts, I am able to get SPIM to work. Looks like the issue lies somewhere within how the interrupts are handled. I have looked through the SDK documents, but can't figure out what I might be doing wrong. Any idea why event handler interrupts are not being handled? I am pretty sure that when I have the event handler passed into the SPIM init function, the function itself never gets called, and the SPI transaction stalls after the data bits are sent out without SS getting de-asserted. Thanks! 

  • Thanks for replying. I agree with what you are saying, and I am aware of this nuance. However unfortunately, the problem somehow lies within how the interrupts are handled in my case, and the event handler not being called. This information might help others though.

  • Ah, I think you have DCX set (if NRFX_SPIM_DCX_PIN is defined as a pin and NRFX_SPIM_EXTENDED_ENABLED) but are using the non-DCX transfer function which never sets the expected length. If so maybe try this:

     APP_ERROR_CHECK(nrfx_spim_xfer_dcx(&spi, &xfer_desc, 0, 15)); // 15 is the example

Related