2023-12-27 09:58 AM
Hi everyone,
I am using STM32F410 CPU.
I need to send 4096 bytes of data via SPI using DMA transfer.
The transfer should be triggered by each TIM1 event.
I have read these two posts:
https://community.st.com/t5/stm32cubemx-mcus/trigger-spi-dma-transfer-from-timer-directly/td-p/300292
https://community.st.com/t5/stm32-mcus-products/dma-only-sending-one-byte-and-not-whole-buffer/td-p/434611
Where similar issues were discussed.
But faced with some problem.
I have selected two DMA streams.
One is memory to SPI_CR register. The request source is TIM1.
Other is memory to SPI data register. The request source is SPI.
I have preprogrammed DMA NTDR register with data size i want
to send over SPI.
When TIM1 event occurs first DMA stream transfers data to SPI
config register. It enables SPI.
SPI starts to generate requests and data is loaded over second
stream.
I see that it is working but only one time.
The problem is that when second request from TIM1 happen
SPI is already enabled. So update of SPI SR register not needed.
But the main problem is that NDTR is already empty.
And no second transfer happen.
I don't know how to update NDTR again?
Or disable SPI after it completed DMA transfer?
I can't enable circular mode because SPI start transmitting
all the time without TIM1 synchronization.
I would like to do it without CPU and any interrupts.
Is that possible?
Thanks
2023-12-27 10:44 AM - edited 2023-12-27 10:44 AM
Set NDTR to 4096 out the outset. Each trigger will transfer one byte, and after 4096 bytes it will not trigger any more.
> Or disable SPI after it completed DMA transfer?
Once DMA finishes (NDTR=0), it won't send any more bytes. That should be all you need.
If you want to disable SPI, you'll need to capture the TC flag and do it then, after ensuring the SPI isn't busy.
2023-12-27 11:19 AM
Thanks for reply.
>>Set NDTR to 4096 out the outset. Each trigger will transfer one byte, and after 4096 bytes it will not trigger any more.
Yes. I tried this way. Each timer request triggers one DMA transfer.
The problem with this approach is that there is a 100ns delay (6 cycles) between timer trigger and start of SP I transfer.
I want to form timing diagram as compact as possible.
Actually i am not sending any data via SPI :)
I want to use SPI clock as a reference to control external device.
I don't know how to get 30MHz clock out of the STM32f410rbt6.
2023-12-27 11:36 AM - edited 2023-12-27 11:37 AM
The "original" solution by @berendi from the first link asumes, that you "perform housekeeping" after finishing the transfers, using DMA interrupt, with taking into account the delay between DMA writes last frame to SPI_DR until SPI finishes its Tx. As I've wrote there, tracking SPI_Rx is the best solution for this. However, interrupts i.e. software is always involved in this.
My solution outlined in the same thread is to use two timers interconnected through their master-slave connection, one generating triggers for DMA transferring data to SPI_DR, other serving as the counter for 4096 transfers. One way how this can be achieved is that the external trigger triggers one single pulse in a timer (other than TIM1), duration of which is the 4096 periods of TIM1, and is the master, of which TIM1 is slave in gated mode. TIM1's period is then equal to the time needed to transmit one SPI frame, and triggers the DMA which transfers the frame from memory to SPI_DR. This DMA then does not need to be set for 4096 frames, can be more, and can be set as circular.
Would you need less than 256 transfers, this could've been pulled out entirely by TIM1, in one-pulse mode and using RCR.
JW