2015-05-03 09:42 PM
Hello everyone,
Nowadays, I'm trying to figure out how the FIFO of DMA works. But get stumbled with the DMA memory to peripheral mode with FIFO enabled.
Firstly, the STM32F4 ''RM0090 Reference manual'' P.219 ''Memory-to-peripheral mode'' which describes:
When this mode is enabled (by setting the EN bit in the DMA_SxCR register), the stream immediately initiates transfers from the source to
entirely
fill the FIFO.
Each time a peripheral request occurs, the contents of the FIFO are drained and stored into the destination. When the level of the FIFO is
lower than or equal to
the predefined threshold level, the FIFO is
fully reloaded
with data from the memory.
Note the word ''entirely'' and the ''fully reloaded'', shouldn't it be the ''FIFO threshold''? If so, it also conflicts with ''lower than or equal to''. I'm confused about these two sentence.
Moreover, in the same mode, it says ''
When this mode is enabled,
the stream immediately initiates transfers''. Assuming I have a buffer u16 M[8] defined in memory, and set the FIFO threshold level to 1/2 (4 half words), the peripheral burst 4 beats of u16. The NDTR is 8.
So, when the DMA stream is enabled, the M[0]~M[3]
immediately
fill the 1/2 FIFO. And when the DMA trigger arrives, the 1/2 FIFO data sends to the Peripheral, also
at the same time (?)
the FIFO re-fills the 1/2 with M[4]~M[7].If this is how it works. Assuming, after the DMA stream is enabled, and lately I changes the data of M[0]~M[3], and the DMA trigger arrives. The data in the 1/2 FIFO is the pre-M[0]~pre-M[3] value, rather than the M[0]~M[3] I just changed?
If so, there is a delay between the value I write into M[0]~M[3] and the value the Peripheral receives, due to the FIFO structure.
If my assumption above is correct, is there some way to flush (meaning
delete
)the preloaded value in the FIFO? As a consequence, I could do the following procedure: modify M[0]~M[3], flush (delete, not to peripheral) 1/2 FIFO, re-fill 1/2 FIFO with M[0]~M[3], waiting for DMA trigger.
Please help me out!
2015-05-04 01:43 AM
Wei,
the sentence from the manual looks clear to me. In Memory-to-peripheral transfer, the DMA tries to read as much data as possible from memory, ahead of transfer to the peripheral. This is a sane behaviour to reduce memory contention when feeding the peripheral. At start DMA reads as much as it can from memory. When the peripheral is served (sometime only a single byte for every trigger), the FIFO threshold avoids to request a memory transfer for a small byte count (memory transfer is more efficient using words). Waiting for the FIFO being 1/4 or 1/2 full is good because it requires 1 or 2 words to be loaded from the memory (actually 1/2 is better because a burst of two words is more efficient than loading twice a single word). There is no way to reset the DMA FIFO except to stop DMA, reset and restart. It sound weird that you started a DMA with some data, then changed your mind and decide to change data without respect that older data has been send or not ... what are you trying to do ? -- laurent2015-05-05 10:45 PM
Hi laurent,
Sorry for the late reply. Yes, this is what the Reference Mannual meant. What makes me confused is that in some ST training materials the FIFO in Memory to Peripheral mode behaves like what I've mentioned above. Of course, I think I should assume that the Reference Mannual is correct. But here's still a question. If EN is enabled, the FIFO should be entirely filled. What will happen if the data in memory is less than the FIFO memory? Especially in circular mode? In this occasion, the FIFO should be full filled or not, I couldn't find any mention in the Reference Manual. As for what I'm trying to do. I'm trying to use DMA to send the desired value to the Peripheral register at an exact time. Here's the detail: The STM32F407 has TIM1 of PWM modes PWM1 and PWM2 in center-aligned mode. I've been working on some PWM algorithms of motor control, some PWM algorithms require switch between PWM1 and PWM2 in the update time of the counter (when the counter counts to 0 or PERIOD-1). The difference between PWM1 and PWM2 is that they have reversed OCREF phase, but, most of all, the output polarity remains unchanged. I may switch the output polarity to realize reversed output phase, but in complementary output mode, due the deadtime, I couldn't switch the output polarity. So, the only solution is switch between PWM1 and PWM2. But what makes me annoying is that, ''In PWM mode 1 or 2, the OCREF level changes only when the result of the comparison changes or when the output compare mode switches from “frozen�? mode to “PWM�? mode.'' The delay is not acceptable to the PWM algorithm. So, when I want to switch from PWM1 to PWM2, I must first switch the output compare mode to Frozen and then to PWM2. There's software way, with interrupt, which I'm not preferred. I think with DMA is more efficient. The TIM1->CCMR1 and TIM1->CCMR2 need to be firstly updated with 0, and then quickly with PWM2. Could you think up some better idea? Many thanks.2015-05-06 12:26 AM
Hi Wei,
> What makes me confused is that in some ST training materials the FIFO in Memory to Peripheral mode behaves like what I've mentioned above. Do you have links to such? As to your particular problem, I don't try to understand what do you need to achieve, but maybe this one tip may help you: the DMA can be temporarily put to ''hold'' simply by throttling it at the ''trigger source'', in this case, by clearing the respective bit in TIMx_DIER. JW2015-05-06 01:10 AM
Wei,
I am not sure to understand the whole picture. IMHO it is not a good idea to rely on PWM mode switching, whatever you are trying to do. It look to me that it is an uncertain and not deterministic way of doing thing. Moreover, I am not sure that using DMA for writing CCMRx to 0 and then ''quickly'' to another value, will ever work. DMA will trigger transfer to the peripheral upon an event. It's ok that the first event is the timer update event, but what about the second one ? I hope you can find another way to meet your needs, if ever possible. I am sorry not being able to help you without entering deeper into your timing constraints. My advice is to forget about the DMA as being a peripheral to do thing quickly, but to see it as a peripheral to do things without CPU intervention. Good luck.2015-05-06 04:34 AM
Hi waclawek,
The training material I mentioned is in the website: http://www.stmcu.com.cn/design_resources.html Unfortunately, this is a Chinese site. In the bottomhttp://www.stmicroelectronics.com.cn
, it maybe a official training site. The DMA pdf, is in http://www.stmcu.com.cn/designDownload.html?index=1126 Page 27 is where I'm confused. I haven't found the related English version yet :( This may be a misunderstanding or mistake of Chinese engineer. Thanks for your kindly help :)2015-05-06 05:09 AM
gonzalez,
Here's the char art. Hope it appears correctly in your system. The switch between PWM1 and PWM2 sounds strange, but it is useful in some PWM algorithms. I've studied all the functions of the timer, unfortunately, using DMA is the best solution I could get. Yes, we need at least two DMA channels to realize PWM1-Frozen-PWM2, the first DMA is triggered by TIM1 Update Event (TIM1_UP), and meanwhile select UPDATE as TIM1 TRGO, and to TIM3 TRGI. The second DMA is triggered by TIM3 TRGI. And the DMA needs manage CCMR1 and CCMR2 correctly .... Oh, that's a lot of software work ...../\ /\ <------ CNT
/ \ / \ --/----\----/----\-- <-- OC1 / \ / \ / \/ \ --______--__------__ <-- OC1REF --______--__------__ <-- CH1 __------__--______-- <-- CH1N (PWM1) (PWM2) ^<-Switch There's some deadtime between CH1 and CH1N;2015-05-06 05:41 AM
Wei,
the chart art displays perfectly ! I will redo my recommendation, do not rely on PWM1-Frozen-PWM2 sequence. Moreover it is very uncertain to program two different DMA channel with the same target. Trigger events are likely to be ordered, but nothing give you a warranty that DMA transfer will happen in the same order. Go away from that architecture. If I were you, I will investigate a single mode PWM architecture, using DMA to change period and duty cycle at every cycle. The DMA can preload period+compare for the next cycle, then at the timer update event those values are taken into account. It requires you to prepare the shape of your waveform in a table that you feed into the DMA, for minimum CPU intervention.2015-05-06 06:49 AM
gonzalez,
Yeah, things will become uncertain if DMA is used in this circumstance. Your advice is helpful. I will reconsider this architecture and try to figure out another way :> thanks again2015-05-06 06:50 AM
gonzalez,
Yeah, things will become uncertain if DMA is used in this circumstance. Your advice is helpful. I will reconsider this architecture and try to figure out another way :> thanks again