cancel
Showing results for 
Search instead for 
Did you mean: 

Slower FSMC memory transfer by DMA possible? (Time triggered?)

flyer31
Senior
Posted on January 31, 2012 at 17:58

Hi,

I invested already complete afternoon, but I cannot come further, perhaps somebody could give me a hint?

I need to read data from a parallel bus (16 bit wide) with a reduced frequency of typically 1-5MHz (should be adjustable by configuration). The bus is connected to FSMC.

I hoped that this might work with some timer, and some DMA. I successfully tested the STM32F4-StdPeripheral-Lib example DMA-FLASH_RAM. This works nicely, but much too fast (I need it much slower in this case). I also tested the DAC_SignalGeneration example, this works with Timer trigger - but here a special trigger functionality of the DAC module is used, which is lacking in the FSMC - I do not see any trigger channel there.

Anybody has a hint how to control the read cycle time for DMA fetch from FMSC?
4 REPLIES 4
Posted on January 31, 2012 at 21:24

I'd look at the PWM Out DMA examples, where the DMA is paced with the TIM Update, then instead of Mem-to-Periph, do a Mem-to-Mem.

I can't pluck a TIM#, DMA#, Stream# out of my head for the F2/F4 series. Look at the DMA trigger matrix.

From RM0033 Table 22, pg 174

DMA1 Stream0 Channel6 TIM5_UP

DMA1 Stream1 Channel3 TIM3_UP

DMA1 Stream2 Channel1 TIM7_UP

DMA1 Stream4 Channel1 TIM7_UP

DMA1 Stream6 Channel 2 TIM4_UP

DMA1 Stream6 Channel 6 TIM5_UP

DMA1 Stream7 Channel 3 TIM2_UP

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
flyer31
Senior
Posted on January 31, 2012 at 21:40

Thanks for your fast answer - I should have asked earlier then I would have saved 1 grey hair at least :).

I now also recognized meanwhile, that this is the trick - specifying per to mem, and then just using mem to mem base address config.

Just currently I got this running only with following restrictions:

- only in circular mode (so number of transactions cannot be specified)

- If I use DMA2 - Channel 6, so that Timer 1 specifies the ''rhythm'', then Stream 0 did not work (TIM1_TRIG - I specified TIM1_CR2 MMS to Update (10), but anyway no DMA trigger) - but Stream 1 and 5 worked (TIM1_CH1 and TIM1_UP).

So I am reasonably happy - but circular mode still a problem - I need to specify the number of read cycles. Any hint? (I am just working through all the registers in the ref manual to be sure that I see all the ''hidden'' possibilities).

Posted on January 31, 2012 at 21:56

Read cycles on the FSMC bus?

I'm not sure you can specify precise sample point for the DMA, it'll be delayed by whatever bus activity or arbitration is going on at the time. The DMA request should stay on pace as the update controls the beat. You wouldn't need to have the TIM generate an interrupt.

I haven't looked at circular vs non-circular, but the SRAM-to-LCD via FSMC uses circular, unless I'm mistaken.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
flyer31
Senior
Posted on January 31, 2012 at 22:22

Now I got it - you have to set the PFCTRL bit to 1 (Peripheral flow control on), and the CIRC bit to 0 (Circular mode off).

With the StdPeriphLib-Function DMA_Init this is not possible, you need to invoke a special function DMA_FlowControllerConfig for this - this really is a bit stupid, how should a beginner know this (and I think the lib should make life easier for beginners).

 I think it would be much more user-friendly, if they would define a further memory mode: Now they have DMA_DIR_PeripheralToMemory, DMA_DIR_MemoryToPeripheral, DMA_DIR_MemoryToMemory, and I would propose a further mode DMA_DIR_MemoryToMemory_PeripheralFlowControl, then it would be quite clear also for a beginner.

If a function is called DMA_Init, it really should do ALL initialisations, anything else is very misleading.

A similar problem they have in the Timer module stm32f4xx_tim.c: If you there just change an example code from TIM3 to TIM1, at first nothing will work any more, because for TIM1 you additionally need to set the MOE bit, which is done by the special function TIM_CtrlPWMOutputs - but how can you guess as a beginner, that it is necessary to invoke this function for Timer 1 and Timer 8?

Besides the Timer comparison table, I asked for in some earlier post, it would be very helpful, if they include such important bits already in the basic configuration, so that it is really sufficient to invoke TIM_Init, and then TIM_Enable - for any timer the same procedure. E. g. if you start with ST4Discovery, a very common startup example for nearly every beginner will be the TIM_PWM_Output. If you look at this at beginner, I think nearly every beginner will try to change from TIM3 to TIM1 and will be quite bewildered, that this example does not run with TIM1 (because or course this function TIM_CtrlPWMOutputs is not called, as it is not needed for TIM3). It would be much better, if e. g. there is some more complex definition possibility for the structure TIM_OCInitStructure. E. g. for TIM_OutputState, now you can define TIM_OutputStateEnable. To adjust for the possibilities of Timer 1 and 8, it would be necessary to add another possiblity ''TIM_OutputStateEnable_MOEdisabled'' (perhaps with a comment line - use only with TIM1 or TIM8).