This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

PPI to SPIM Task, How to?

Hello,

I am having much fun with nrf52. I'd like to implement SPI read (few bytes) per GPIOTE event over PPI, the source is the GPIO event and the destination task is a SPI read of few specified bytes. The event is currently generated without Interrupt, and this is preferred.

I'd like to use easyDMA on the SPIM end. I have done the easyDMA setup, the MAXCNT, PTR, LIST are all setup register writes are verified correctly.

The issue is I am still missing something, I can not stitch together in my mind the steps needed to setup a READ task for SPI without interrupts to trigger a START Task, also how it looks from PPI to easyDMA. Please help to explain. Would the p_spim->START register contains actually a pointer to a chunk of code? How to best take advantage of the sweet nRF52 features?

I have checked the path over PPI assignment and verified the external event are generated and general routing (from event to task) over PPI is working via a test GPIO output:

err_code = nrf_drv_ppi_channel_assign(ppi_channel1,
	  nrf_drv_gpiote_in_event_addr_get(trigPIN),
	  nrf_drv_gpiote_out_task_addr_get(testOutPin));
	  //nrf_drv_spi_start_task_get(&afeSpi));

Please enlight! Thanks in advance!

FI

  • Hi, I suggest you combine two examples in the SDK:

    \examples\peripheral\saadc\
    \examples\peripheral\spi\

    The first example show how you can setup a compare0 event from a timer to trigger an ADC conversion. In your case you need to include the SPI driver to trigger an SPI transfer instead.

    To setup the SPI transfer first call spim_xfer() with NRF_DRV_SPI_FLAG_HOLD_XFER flag. To get the actual task to trigger the SPI transfer use nrf_drv_spi_start_task_get(). Now you should only need replace nrf_drv_saadc_sample_task_get() with nrf_drv_spi_start_task_get(), and then the SPI transfer will be executed on every compare0 event. You can replace the compare0 event with any other event you want to trigger the transfer.

    Every time an SPI transfer is complete the application will be interrupted with spi_event_handler().

    There is however one problem here, the slave select pin is not toggled by itself, only the SCK, MISO and MOSI will be transferred. To include the slave select pin you might configure the compare0 event to trigger two tasks by setup two PPI channels:

    • one channel to toggle the slave select
    • the second channel to start the spi transfer

    The two tasks will then occur very close in time, this may or may not work depending on the SPI slave you are communicating with. Alternatively you will need to make this more intricate by having both a compare0 and compare1 event, to control the time between slave select go low until SPI transfer occur.

    There are many possibilities, but hope you have something to get you started.

  • Great Ken, will check that out today. Thanks!!

  • Hello Ken,

    Per your instructions. The PPI to SPI is working! I'd like to shoot out another question before I call it the night. So using SPIM the easyDMA is setup by defining MAXCNT, PTR and LIST type and ENABLE. I have a buffer size of few bytes per transfer per event, what is the best way in the sense of no CPU intervention to append these data into a larger array? I noticed that if I put the larger buffer and pointer to it via the MAXCNT and PTR registers, each event would then trigger a SPI transfer of that large size, I only need a segment of few bytes. I experimented by defining another transfer size when I call nrf_drv_spi_xfer(), but the MAXCNT supersedes. I also experiment with the flags NRF_DRV_SPI_FLAG_HOLD_XFER vs NRF_DRV_SPI_FLAG_REPEATED_XFER, but did not see a difference. Your input is appreciated! Thanks again!

    Thanks again!

  • Maybe an event from DataCount?

  • I still think you need CPU interaction here, but there are flags you can use when you are setting up the SPI transfer by nrf_drv_spi_xfer() such as NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER, NRF_DRV_SPI_FLAG_TX_POSTINC and NRF_DRV_SPI_FLAG_RX_POSTINC. So if you want to do multiple SPI transfers without CPU interrupt, then you can trigger the start task a number of times from a timer for instance. But you need to have some control on how many times you trigger the start task.

Related