cancel
Showing results for 
Search instead for 
Did you mean: 

Timer Interrupt with DMA (ADC, SPI), non-blocking while loop?

IJo.1
Associate III

Hi,

I always appreciate all members here for helping beginners like me 🙂

I am currently working on a project using Timer and ADC+SPI with DMA.

The main timer loop is running at 40kHz, and this frequency should be strictly guaranteed.

Two DMA process is also running with the timer, one is ADC and the other is SPI Comm.

I want to check if the two DMA process is done in the timer ISR and

do next procedure I need and while DMA process is being checked, I also want the timer to be continuously ticking.

The reason I want to use DMA is to make two peripherals work simultaneously so I can get two results in a shorter time.

At first, I tried just polling type of ADC and SPI comm.

SPI comm starts after ADC is done.

0693W00000JMUXKQA5.pngBy doing so, it is easy to make the timer frequency strictly the same.

but what if ADC and SPI are working by DMA?

I thought it can be done parallelly like the follows:

0693W00000JMUZVQA5.png 

"Do something" needs two data from ADC and SPI, therefore

it has to check if both works are done and move on to the Do something part.

The problem is :

I tried to make the priority of timer lower than DMA interrupts,

and use the while() loop in the timer to check the DMA status.

but it doesn't work properly, I think while() loop blocks and bothers the timer so the frequency is not guaranteed..

Could you please give me some advice to achieve this kind of thing?

or DMA doesn't help and the polling type is the answer to do so?

Thank you all!

Best,

IJo

7 REPLIES 7
TDK
Guru

The concept you've outlined should work.

Lower-priority interrupts should not affect the higher priority ones, and certainly a while loop should have no effect on the timer.

Things like disabling interrupts, or making blocking calls within them, may cause issues.

Hard to know what's going on without seeing code.

Note that 0 is the highest priority and 15 is the lowest.

If you feel a post has answered your question, please click "Accept as Solution".

0693W00000JMXwsQAH.pngSorry, the text lies - it's not a *whole timer period* but timer period minus duration of "Do something".

If time between end of timer ISR and beginning of the next is not sufficient to both DMAs to finish, use double-buffering - start the two DMA at the beginning of TIMER but alternate between two buffers into which the DMA goes, and in the "Do something" use the other buffer's content.

And even if you'd wish to check whether DMA finished, you don't need any DMA interrupt for that. Simply check the DMA status flags.

 JW

IJo.1
Associate III

hi, TDK

yes, by setting up the priority of DMA interrupt higher than of the timer interrupt, the while loop in timer ISR works with DMA process as you mentioned.

I am wondering if the timer ticking frequency can be strictly remained with the condition above.

I think the timer ISR is affected by the dma interrupt and check routine in the while loop, since the priority of the timer interrupt is lower.

and this makes the timer slower or something so the frequency is not remained as it was set?

sorry for this unclear question, the dma interrupts seem to affect timer ISR and the frequency somehow and I need to find a way to solve this problem.

I will share more data after I try.

thank you

:))

IJo.1
Associate III

removed post

hi waclawek.jan,

> And even if you'd wish to check whether DMA finished, you don't need any DMA interrupt for that. Simply check the DMA status flags.

then it does not require DMA interrupt which bothers the timer interrupt?

I will try that and also try dma at the end of timer ISR!

thank you so much and I will share how it goes. :))

IJo

Numerically lower priorities are higher priorities which makes it difficult to decipher what you are asking.
The timer tick rate is entirely independent of the CPU. The interrupt will be regular if it is the highest priority interrupt, but can vary by a few ticks of jitter due to various things.
If you feel a post has answered your question, please click "Accept as Solution".
IJo.1
Associate III

Hi all,

I have a little progress, thanks to TDK and waclawek.jan!

The concept which like the diagram I posted, works fine now.

SPI via DMA is simple but ADC was kind of a headache for me.

Few things​ I have learned:

  • as waclawek.jan said, I was trying to check the status using EOC bit. but I failed since when DMA Finished, it is cleared as soon as the transfer is done. I have to use my own flag in TxCpltCallback to check the status.
  • To use dual regular simultaneous mode DMA, saying ADC1, ADC2, I configured as follows:
    • ADC1 as a Master, ADC2 as a Slave
    • DMA Access Enable, and set DMA of ADC1 only
    • Data Width are set to Word, for Peripheral and Memory both.
    • Use HAL_ADCEx_MultiModeStart_DMA, it reads ADC_CDR(Common Data Register)

That's it.

BTW, I come up with a new query,

Why the data width of Peripheral should be Word? does it matter?

The direction of DMA is Peripheral to Memory,

and I understand the data width of Memory should be Word since CDR is 32 bit long,

but why the data width of Peripheral has to be Word?

Best,

IJo