Patches to implement DMA for STM32F4 SPI.
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 :-)
On Mon, 4 Feb 2019 13:31:12 +0000
"Dave Marples" <email@example.com> wrote:
Folks,Thanks for this post. The best suggestion I however would have is to
look it up in the mailing list archive and link from the Github pull
The rule of thumb we follow is that technical matters are discussed in
PRs. If discussion goes beyond mid-level technical matters, e.g. to
organizational matters, or to technical changes which may affect many
Zephyr users, an authors of proposed changes is encouraged to submit an
RFC to the mailing list to get wider coverage.
Of course, everyone if welcome to post to the mailing list to draw
attention to a particular matter.
Hope those were useful hints, and hope other folks will comment on
technical matters (but again, better if all of that is in/reachable
from the PR).
Linaro.org | Open source software for ARM SoCs
Follow Linaro: http://www.facebook.com/pages/Linaro
http://twitter.com/#!/linaroorg - http://www.linaro.org/linaro-blog