cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F SPI DMA transfer, triggered by Timer

francesco2
Associate
Posted on March 14, 2016 at 10:54

Hi everyone,

I have some cpu-load issue on my design, so I am trying to redesign an high frequency Rx spi transfer. (24bit)

I would like to setup a timer that at a certain frequency triggers the Rx SPI transfer.

Right now I have a timer (TIM8) that triggers a DMA stream (TIM8_UP)(DMA2_Stream4).

I am using SPI1 (DMA2_Stream2)

I saw in this forum some possible solutions (set the peripheral address as SPIx->DR) but I think it doesn't work (I would probably read a stream of 0s... wouldn't I?).

So am figuring out to setup a number of timers (all synch each other with TRGO/ITR functionality), which will trigger a number of dma streams to:

 A)disable SPI_DMA_Req

 B) disable the DMA2_Stream2 (SpiRx)

 C.a) setup the size of the transfer (NDTR register)

 C.b) enable the DMA2_Stream2 (SpiRx)

 D) enable SPI_DMA_Req

So, I need to use 4 timers.

My application doesn't requires the usage of a lot of timers, so it wouldn't problem, but I am wondering if it'd be a more readable/easy solution.

Many thanks,

Francesco

#stm32f-spi-dma-timer
1 REPLY 1
knielsen
Associate II
Posted on March 14, 2016 at 12:17

You write you are doing an SPI Rx transfer. Presumably, your device is doing SPI in master mode, since in slave mode the data arrives as dictated by the master, without the need or possibility for your code to affect it. You did not write which STM32 you are using, I will assume STM32F405 or similar.

So your problem is actually to setup an SPI Tx - you will then receive corresponding Rx data on your SPI1_RX on dma 2 channel 3 stream 2.

That is how the usual method you saw works, of setting SPI1->DR as the peripheral address of the TIM8 DMA channel. Every time the timer triggers a dma request, a new data byte is written to the SPI1 data register, initiating sending that byte and receiving a corresponding byte. This can then trigger another DMA request from the SPI1 to your SPI1_RX dma channel, which can store the byte received in memory.

The trick is that the timer DMA is not reading the bytes from the SPI. The timer is writing bytes to the SPI to trigger a SPI transfer, and the results are read by a normal SPI Rx DMA channel.

It sounds like you could use this simple method. You write you need to transfer 3 bytes (24 bits). Presumably you could setup your timer to trigger at 3 times the frequency of your transfer. And then you could setup your DMA buffers and transfers to eg. 300 bytes to do 100 transfers before ending the DMA and requiring your CPU to process the results. You could probably also set it up in circular mode to have continuous transfer without CPU intervention.

I think your alternative suggestion with multiple timers each writing to different DMA control registers could probably also work, but it sounds more complex to get right. And you still need to control the Tx channel with the timers. The Rx channel needs nothing special, it will just transfer the bytes received as they become available, by DMA requests triggered by the SPI.

Hope this helps,

 - Kristian.