Patches to implement DMA for STM32F4 SPI.


Dave Marples
 

Folks,

I'm new around here so please bear with me and nudge me in the right direction if I get things wrong.

I have just submitted Pull Request 13031 which implements DMA mode on the STM32F4 series (specifically tested on the STM32F427ZI). This note is by way of providing a bit more background on it since the PullReq itself probably isn't the place for it.

My use case is a pin going low which triggers the exchange of 24 octets of data which happen to originate from an ADC. This occurs at 100uS intervals. My CPU is running from flash at 160MHz, with 8 bit SPI running at 10MHz. The actual 'busy time' exchanging these data should be 19.2uS.

I initially tried Interrupt mode. The 100uS deadline was frequently exceeded and the intervals _between_ each octet exchange were longer than each octet exchange itself! A typical 24-octet exchange took 116uS from the pin request to the pin going inactive again at the end of the request.  This is shown at https://drive.google.com/file/d/1m20klSrnFNzHa7W3f3j03g4-1PaoB6Dk (Yellow trace is the requesting pin, green is the SPI clock. The high pulse after 100uS is the next data request coming in).

Programmed IO mode is better, reducing the time required to 93uS ( At https://drive.google.com/file/d/1IH15dD1WMq0hX5KvmDU0qm9o8ardhoaJ ) but the CPU is busy and I don't get any time to do anything with the samples after they've arrived.

I therefore added DMA mode to the driver and the result is visible at https://drive.google.com/file/d/1KiroWn1kfyrg1gnOl7xfAeVmwFkq5M8j . The actual data transfer now takes the calculated minimum of 19.2uS and the overall transaction time is reduced to 69uS.

It can be seen in that last scope picture that the setup latency is really starting to hurt in this scenario so I've gone slightly further.  I have added a new operation flag in spi.h called SPI_DEFER_TRANSFER. When a spi transfer is set up it will do everything as normal apart from actually enabling the SPI device itself....effectively the transfer hangs in a pending state. When the trigger arrives then a new API called spi_trigger is called, which actually enables the SPI device (and thus the transfer to complete). Since this doesn't use any APIs other other routines the intention is that it should be safe to call from a direct interrupt and it should work irrespective of if you're using ProgrammedIO, Interrupt or DMA mode.  When called from a conventional GPIO interrupt, the result using DMA is shown at https://drive.google.com/file/d/1gxxBnc4MZEWD5YouEQ0NHh1wBH5bVMIT ... basically, a reduction in SPI startup latency from 32uS to 3.5uS, and a reduction in overall SPI transaction time from 69uS to 35uS for this 24 octet packet (it should reduce considerably further when I move to a direct interrupt for the GPIO).

I'd appreciate it if folks can take a look at these patches and give (constructive?) feedback. For me the RT is the important bit in this RTos :-)

Regards

DAVE

Join {devel@lists.zephyrproject.org to automatically receive all group messages.