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

DMA for SPI master

I'm reading AD-converter data usin nRF51822 SPI-Master. BLE-stack is active so I can't use interrupts with SPI. I get data every 2 ms. Sometimes Events are delayed so long that I get erroneous data from AD.

Is there some way to implement DMA for the SPI-Master, maybe using SPI-slave some way?

Juha Okkonen

  • Hi Juha,

    just to clarify: the SPI transfer itself is not corrupted, right? As the SPI Master, if you get interrupted in between byte transfers your next byte transfer is simply delayed. The hardware will always complete a byte transfer, even when the CPU is interrupted.

    My understanding of the problem is that the data you want to read becomes invalid if you delay reading it for too long.

    Unfortunately, there is no DMA support for the SPI Master. Only for the SPI Slave. But it might be possible to use the SPI Slave functionality in this case.

    I suppose your AD is a SPI Slave device, and cannot act as a Master. What you would need to do is set up the SPI Slave peripheral. As both SPI devices are now slaves, you need to generate a clock signal on a different pin and connect it to the SPI Clock line. The clock can be generated using PPI and a TIMER. Load up the TX buffer with the required data (register addresses etc., depending on your AD). Configure the GPIOTE to generate an event on the AD interrupt (on both set and release edge), and connect it to your clock timer START and STOP tasks. You might also have to connect the interrupt event to the AD Slave select line. When the AD asserts the interrupt line, your GPIOTE interrupt event will fire, initiating the transfer. With large enough TX/RX buffers, you should be able to line up multiple transfers.

    I realize this explanation is a bit messy, but hopefully you can make sense of it.

    Audun

  • You understood problem correctly. Luckily I dont' need to send anything when receiving values. All configuration is done beforehand. Complication is, that interrupt from AD is kept active only until reading starts. So I don't get signal telling how long to transfer bytes. Only a starting edge. Every transfer is 9 bytes. So do you think it would be possible to generate both clock and length with a timer for the SPI-slave??

    Another complication is that I'm currently using BLE-module and not all the I/O-pins are available. It it were possible to configure SPI-slave and Timer -pins to same physical pins, it would be helpful. Is that at all possible. Theoretically I would expect it to be possible when one is output ant other input, but does HW support it?

  • You understood problem correctly. Luckily I dont' need to send anything when receiving values. All configuration is done beforehand. Complication is, that interrupt from AD is kept active only until reading starts. So I don't get signal telling how long to transfer bytes. Only a starting edge. Every transfer is 9 bytes. So do you think it would be possible to generate both clock and length with a timer for the SPI-slave??

    Another complication is that I'm currently using BLE-module and not all the I/O-pins are available. It it were possible to configure SPI-slave and Timer -pins to same physical pins, it would be helpful. Is that at all possible. Theoretically I would expect it to be possible when one is output ant other input, but does HW support it?

  • You can keep track of the length by using a second timer as a counter, stopping the clock when the counter reaches the 9 byte clock value. Possibly the END event in the SPI slave can be of use, but I suspect this event connects to the CSN line.

    "Only one peripheral can be assigned to drive a particular GPIO pin at a time, failing to do so may result in unpredictable behavior." You could give it a try, but it's not designed to work like that.. :(

    Alternatively it's possible to synchronize radio activity with your AD reads. Have you seen the radio notification functionality? You can use this to synch radio activity with a 2 ms application timer. Depending on the connection parameters and your application behaviour, you might be able to keep a steady 500 Hz AD reading. http://devzone.nordicsemi.com/documentation/nrf51/5.0.0/html/group__t__s110___n_r_f___s_o_c___f_u_n_c_t_i_o_n_s.html#ga15378609daca09588e620b64555fc2e8

  • Hi Audun,

    Could you please elaborate on how to synchronize radio activity with the AD reading to achieve 500Hz reading?

    I'm in the same situation as Juha that the AD interupts every 2/4/8 milliseconds. And unfortunately, the AD conversion data has to be read out before the next interrupt comes.

    Thanks, Bruce

Related