stm32 dma request synchronization settings - Page 1
Forum section: electronics / general

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: January 14, 2024, 01:32:38 pm
content: Hi,I have an external SPI 8 channel ADC which is connected to the STM32,one of timers would generate a 32KHz 50% pwm signal which is connected to the ADC convert pin, the ADC has a busy pin which is connected to the EXTI0 of the MCU.The plan is to use the EXTI0 to trigger 8 16bit SPI reads from the ADC, so after gathering 640 samples I would get an interrupt, to process the incoming data, since Interrupting the CPU 32000 times per second would not allow any other meaning full job to be done,So I have done like thisPin A0 configured as EXTI0SPI DMA settingsSPI NVIC settingsmy code is like thisCode:uint8_t SPISend = 1;void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi){if (hspi->Instance == SPI2) {SPISend = 1;}}int main(void){uint8_t tx={0,0,1,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};uint8_t rx={0};//init IO with CubMXwhile (1){if(SPISend == 1){HAL_SPI_TransmitReceive_DMA(&hspi2,tx,rx,5120);}}}This code works only when I enable the EXTI interrupt, which would ruin the hole prepose of eliminating the use of interrupts,Is there any work around this so I would reduce the CPU overhead and interrupts, so the CPU could do other time critical tasks.

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: January 15, 2024, 09:46:01 am
content: Is it possible?

author: pcprogrammer
author_rank: Super Contributor
timestamp: January 15, 2024, 12:24:26 pm
content: Which STM32 device are you using?For instance the STM32F10Xyy series don't seem to have the ability to start DMA from an EXTI event. With one of these it might be an option to use a TIM_TRIG event, which can be external to start the DMA.An other option is to enable the external interrupt and in the handler trigger the DMA via a SW trigger. The DMA controller can then read the data from the SPI interface.To find out if it is possible I would advice to get the datasheet and reference manual for the STM32 device you are using.

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: January 15, 2024, 02:39:42 pm
content: QuoteI'm using stm32G030k6t part

author: pcprogrammer
author_rank: Super Contributor
timestamp: January 15, 2024, 03:07:46 pm
content: I downloaded the reference manual and it looks quite complex with the DMA request multiplexer to route a trigger to a DMA channel. I do not have experience with a device from this range nor do I have one lying around.But for what I peeked at in the manual it looks like it should be possible to start the DMA from the EXTI line, but to be sure it needs more studying.Another thing is, does the ADC you are using need a command send via SPI to be able to read the conversion data, or can one just start reading and it will always return the full data in the same order.This because of the STM32F103 DMA can only read or write to the SPI interface and it would be difficult to get it to work, if at first a byte needs to be send to allow reading of the data.Don't know if this is the same on the STM32G030.

author: hans
author_rank: Super Contributor
timestamp: January 15, 2024, 06:09:39 pm
content: There are many things to consider to utilize DMA over multiple SPI frames or transactions.Like pcprogrammer said, changing the ADC channel may be a command necessary to be sent. We don't know which ADC you're using, so can't comment on that. I also don't know what kind of behaviour the ADC expects with respect to CS. Can it stay active, or does it need to be toggled between reads? Are you going to use some timer signal for that? Or does/can the SPI peripheral need to generate this?Also why would configuring EXTI make it fire interrupts? You can set up the peripheral to generate interrupts/events, but then still mask it in the NVIC registers. The event would still be handled by DMA(MUX) as configured. I don't know if STMCubeMX allows for such granularity of configuration options. Thats the reason why I still like to write my own RTL code for custom cases like this.I'm not completely convinced this chip can do all the necessary things as stated. I was able to get a similar application working on a STM32U5 chip, however, that has a linked list DMA controller which options up a ton of more possibilities to automate these things in hardware.

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: January 16, 2024, 09:08:32 am
content: hans and pcprogrammer thanks for the feedback, the ADC is a simple to read part, it's AD7606, so there is no need to send commands for reading, But you made me think if the ADC was more sophisticated and needed some commands, is it possible for those ADC's too?

author: Jeroen3
author_rank: Super Contributor
timestamp: January 16, 2024, 09:55:45 am
content: Exti events are taken of the it_exti_per signal, this goes to the DMAMUX and the NVIC.QuoteSo yes. But you could write a fast irq for this, it will interrupt only at 1/8th of the samplerate.To trigger DMA on external event you often need to hook it up to a timer trigger or capture pin.Or you link two timers, eg your timA generates your sampleclock, and your timB triggers the dma every 1/8th clock. Timers can be master/slaved in stm32. You could even count the busy pin using "External Clock Mode 1".However, at 64 MHz you lose only ~15 instructions per ISR, thus (15 * 32k) / 64M is only 0.75 %. So maybe you're worried about nothing?

author: pcprogrammer
author_rank: Super Contributor
timestamp: January 16, 2024, 10:43:37 am
content: I looked at the AD7606 datasheet and noticed that the serial interface has two data out lines to speed up reading. This would require two SPI interface to be used for which one of them should be setup as slave and have the clock output of the other one as clock input. This would have to be an external connection for as far as I know.It can also output all data on a single line using only one SPI interface.Both setups can be done based on DMA. Don't think any timer is needed to pulse the DMA, because the SPI interface can do this by itself. The only problem is how to start the reception sequence. The DMA needs the SPI receive buffer full as trigger for handling the transfer to memory. So the external signal has to start the SPI interface. Easiest would be to do this in an EXTI interrupt. At the end the process also has to be stopped, which can be done in a DMA interrupt.Personally I would forget about HAL in making this work and directly work on the registers from your own code. It can be quite simple. In the M3 interrupts do their own state saving in hardware, and my guess is that M0 does this to. So no need for telling the compiler a function is an interrupt handler.Take a look at the STM32 projects in mygithubspace. You would have to adapt for your MCU version, but a lot will be the same.Quote from: ali_asadzadeh on January 16, 2024, 09:08:32 amThis is far more difficult to do, and would require separate DMA channels for sending and receiving. Synchronizing the processes will be tricky, but guess it could be done.

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 16, 2024, 01:55:50 pm
content: It seems SPI DMA only accepts EXTI or Timer14 OC input, hmm...I've tested this, sending I2C data to a oled, toggling EXTI0 from another gpio.If EXTI flag is not cleared, DMA will stall. That's why you need the IRQ, as it does:Code:__HAL_GPIO_EXTI_CLEAR_RISING_IT(GPIO_Pin);Disabling the EXTI IRQ and clearing the flag in main loop did work as well.The only way I found was to use Timer3 in slave reset mode, connecting the input to EXTI pin.SPI will issue a transfer in the rising edge, few clocks later the timer will reset and generate a dma request.Use this DMA to automatically clear EXTI->RPR1, clearing the EXTI0 flag and making it ready for the next edge.Attached test project, debugged well. Remembeer to regenerate the code.

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: January 18, 2024, 07:46:45 pm
content: thanks DavidAlfa for sharing