My application involves the Nrf52 using softdevice and a slave only SPI ADC running at approximately 26khz. The ADC has a pin interrupt to indicate data ready. There seems to be no way that i can guarantee the softdevice won't hang up the ISR for more than ~40us so I am looking for other solutions.
The one that comes to mind is to use PPI to trigger TASK_START on the SPIM. Combined with what little I can glean from the EasyDMA lists description, it would seem that this could result in my samples getting stored successively in memory. The trouble is that I see no way to read the contents of the buffer and then reset the dma list without the possibility of yielding to the soft device somewhere in the middle of this process.
Is globally disabling interrupts the only solution here? Is there another way to read the ADC?
That's an interesting question. Let's start at the end, globally disabling interrupts will just break things, eventually you'll upset the softdevice which will notice the timings have been messed with and will fault.
I agree the documentation on the EasyDMA list is .. lacking. I read it the same way I think you do however, each time it's triggered, it will read MAXCOUNT bytes, so if you set that to and trigger it from the PPI, should work.
As long as you can consume your data faster than it's coming in, I think you can deal with the interrupts. Give yourself two chunks of buffer, set the SPI to write one of them, when you get the interrupt telling you its finished, switch it to the other one and process the first one. If you can write a marker byte as you go which gets overwritten with the real data, you don't even need to try and read back the pointer registers to work out where SPI finished writing (which I think would be hard and subject to race conditions). So you process, writing your marker byte as you go, when you see you're out of data in that buffer, flip the buffer pointer in the SPI and process the other one. Note that the buffer pointers are double-buffered, so you can write it even if the SPI is currently reading data, it will finish that transaction and write to the new location on the next one.
If I was doing this, this is probably how I'd try to approach it. At 26kHz I don't even think your buffers would have to be very long, you'd probably get max 2-3 readings in each one before you'd flip it over.
Oh of course this only works if the ADC doesn't require anything written to it, it just converts, raises its interrupt and the next SPI transaction clocks the data out of it, but that's how it sounds to me like it works.
I see. I was unclear on what double buffering of the buffer pointers was doing. I had thought this was a feature of the NRF driver, but now that I think about it, you are right and this can be used to make it work.
Maybe a wishlist feature for easydma list is to have a wraparound length at some size of the list so you can easily implement ring buffers for data reception.
Thanks so much.
My reply was all theory, I think it works, would be really pleased if you update the thread after you try it out, the EasyDMA is new to the nrf52 and it would be good to find out how it works in the field.
I was able to get this to work on Rev B silicon and SDK 11. Pretty much was able to use the nrf_drv_spi although i did have to do a little locking in the irq handler for weird race conditions with the buffer update.