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

SPI MISO buffer doesn't fill

Hello,

I am using an nRF52840PDK (master) to use an SPI peripheral, where my code is based on examples\peripheral\spi. My IDE is Segger Embedded Studio and I am using SDK 15.0.0. I am using an oscilloscope to visualize the SPI bus activity.

I start of by configuring the SPI peripheral hardware on the nRF52840. Afterwards I write my configurations into the external peripheral registers over SPI. All of this works as expected.

Following is my problem:

I am trying to read from one of the registers. To do this I write my command byte and want to read 2 bytes (1 status & 1 data). I can see both MOSI and MISO lines reflect the correct data with the oscilloscope. The data does however not seem to be getting loaded into the receive buffer.

Using the debugger I can see being stuck in an endless loop (peripheral.c, register_read(), thus the spi_event_handler is not called to set spi_transfer_done = true. My first suspicion was my event_handler pointer. This works during writing so should also work during reading. Using a watch on the rx_buffer shows me that it is not being filled.

Below this is are scope images and my relevant code. At the very bottom is the concrete question.

Both of the devices are in SPI mode 0.

Yellow = MOSI - blue = MISO - grey line = SCLK 2 periods (external trigger edited in manually)      ----      The first MISO byte is a status byte and discarded, second byte is data

Image writing register 17:

 MOSI [command,  data] - MISO [status]

Image reading register 17:

 MOSI[command] - MISO[status, data]

main.c:

peripheral.h:

peripheral.c:

Regarding the SPI mode: the nRF52840 is in mode0 (SCK active high, sample on leading edge of clock) while the documentation of my peripheral reads:

"[...] These signals are represented in the form (CPOL, CPHA). An
interface that expects both positive edge SCKS and the MOSI data to be available before the first
positive clock edge, can operate in modes (0,0) and (1,1) without alteration. […]"

My question is: Why am I getting stuck in this endless loop and how can I fix it?

Thank you in advance (this is quite long),

Kevin

Edit: Corrected image discription

P.s.: I think there is a bug where I can't upload, remove, then reupload a different image with the same name. It will then show the first image again in the editor.

Parents
    1. Is the MISO line connected?
    2. Does the read function work if you place everything in main.c of the SPIM example?

    "P.s.: I think there is a bug where I can't upload, remove, then reupload a different image with the same name. It will then show the first image again in the editor." 
    - yeah we know, I think it will use the new file once you submit the post though. 

    Also, spi_config.ss_pin = SPI_SS_PIN != NRF_DRV_SPI_PIN_NOT_USED ? SPI_SS_PIN : NRF_DRV_SPI_PIN_NOT_USED; //this if statement does nothing, you might as well just use spi_config.ss_pin = SPI_SS_PIN; 

  • I have tried finding what causes spi_event_handler not to get called in my project. I have set breakpoints at

    - nrf_drv_spi.c line 94

    - nrfx_spi.c line 234, 416 and 423

    None of these breakpoints are getting triggered in my own project when reading registers. They do however trigger when writing registers.

  • I have done single stepping through the driver when calling it from the button event handler before of which I have described the behaviour in a previous comment (4 September 14:43). I have now also tried single stepping through the driver when calling from main which causes it the a "softdevice: assertion failed" error. I assume this is due to timing requirements not being met as a result of single stepping. When I use breakpoints to evaluate specific points in the driver, specifically nrfx_spim.c line 536-540, the code immediately jumps to the spi event handler function. This behaviour seems correct to me.

    So the difference is that after line 540 in nrfx_spim.c I either jump to the infinite while-loop or the spi event handler, using the button event handler or call from main respectively.

    My optimization level for the solution has been set to "none" all the time.

  • Why do you use the SPI driver and not the SPIM driver?

    The easy fix is to place the code in main.c as I believe it executes as intended when built in that compile unit. 

  • If it turns out I cannot get the code to work in seperate files I will try placing everything in main.c. This would in my opinion be a bad practice, so I will first try to get it to work in peripheral.c. I'm convinced it should be possible.
    I actually thought I had changed everything to now use the SPIM driver. I assume you are asking about the SPI driver because I had nrf_drv_spi.h included. I admittedly forgot to include nrfx_spim.h, which I have done now. I have also found that I was still using a few SPI driver types. I have now made the following changes:
    main.c

    peripheral.h


    peripheral.c

     (I can edit to include the complete code again)

    There is actually a type "nrfx_spim_evt_handler_t", but when I use this instead of void I get warnings for incompatible pointer types even though it does work. I have also tried making the event handler static or non-static and eliminating the function pointer.

    Regardless of everything I have tried, I can only make it work when I'm calling the read function from main(), but not when I press a button. Every time I use the button I can see the correct result in m_rx_buf, but the code stays in an infinite loop.

    For good measure I have placed the event handler in main.c without any pointers, removing the calls to the buffer. This shows the exact same behaviour where it works fine when calling the transfer from main(), but not when calling via a button press.

    Unfortunately it is essential for my project to be able to take user input (button) to start a transfer.

  • I have found the solution and managed to confirm with another thread.

    It comes down to the interrupt priority not being set correctly. To quote MartinBL:

    I have set SPI_DEFAULT_CONFIG_IRQ_PRIORITY to 6. I think the button is configured in GPIOTE_CONFIG_IRQ_PRIORITY which is set to 7.

    Due to this I have a few questions:

    Should I only set SPI_DEFAULT_CONFIG_IRQ_PRIORITY or also set NRFX_SPIM_DEFAULT_CONFIG_IRQ to a higher priority value, or something different altogether?

    Is it correct that GPIOTE_CONFIG_IRQ_PRIORITY is the relevant IRQ for the BSP handler?

    I also want to do a suggestion:

    Include the name of the source and/or header file in the driver/library documentation in the infocenter. This way it's easier to match/find code files to documentation, or the other way around.

  • I suggest you use GPIOTE driver or app_button library instead of the Board Support Library.

    "Should I only set SPI_DEFAULT_CONFIG_IRQ_PRIORITY or also set NRFX_SPIM_DEFAULT_CONFIG_IRQ to a higher priority value, or something different altogether?"
    - I would set both to the same value.

    "Is it correct that GPIOTE_CONFIG_IRQ_PRIORITY is the relevant IRQ for the BSP handler?

    - Yes, I believe so. The BSP uses the app_button library and it uses the GPIOTE peripheral. 

    "Include the name of the source and/or header file in the driver/library documentation in the infocenter. This way it's easier to match/find code files to documentation, or the other way around."
    - I agree on this point, right now the library names do not reflect the naming convention used in the SDK.

Reply
  • I suggest you use GPIOTE driver or app_button library instead of the Board Support Library.

    "Should I only set SPI_DEFAULT_CONFIG_IRQ_PRIORITY or also set NRFX_SPIM_DEFAULT_CONFIG_IRQ to a higher priority value, or something different altogether?"
    - I would set both to the same value.

    "Is it correct that GPIOTE_CONFIG_IRQ_PRIORITY is the relevant IRQ for the BSP handler?

    - Yes, I believe so. The BSP uses the app_button library and it uses the GPIOTE peripheral. 

    "Include the name of the source and/or header file in the driver/library documentation in the infocenter. This way it's easier to match/find code files to documentation, or the other way around."
    - I agree on this point, right now the library names do not reflect the naming convention used in the SDK.

Children
No Data