cancel
Showing results for 
Search instead for 
Did you mean: 

Is there anaybody that have a TIM triggered DMA working Code?

franck2
Associate II
Posted on December 01, 2014 at 22:49

I'm stuck on TIM triggered DMA to SPI.

My DMA Code configuration is as follow:

void DMA_Configuration(void)

 {

     DMA_InitTypeDef               DMA_InitStructure;

    

     /* Enable DMA1 clock */

   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    

     /* Blank DMA Configuration */

     DMA_DeInit(DMA1_Channel1);      

    

     /* Using the default values at Startup */

     DMA_StructInit(&DMA_InitStructure);            

   /*Changes from the default values */    

     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(SPI2->DR);            // Address of peripheral the DMA must map to => SPI2 Data Register

   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) TTxBuffer;                // Variable to which received data will be stored

     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                           // Direction of transfer Memory to Peripheral =Destinatary

   DMA_InitStructure.DMA_BufferSize = 32;                                       // BufferSize

   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;             // We don't want to change the SPI2 Data register

   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                      // We increment Memory

   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;      // We define Peripheral Data Size as Byte

   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;              // We define Memory Data Size as Byte

   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                              // Circular Mode define

   DMA_InitStructure.DMA_Priority = DMA_Priority_High;                          // High Priority

   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                 // Memory to Memory Disable

    

      /* Initialize the DMA */

     DMA_Init(DMA1_Channel1, &DMA_InitStructure);           

    

     /* Enable the DMA transfer half and complete interrupt */

     DMA_ITConfig(DMA1_Channel1, DMA_IT_HT, ENABLE);                               // Half Transfer Interrupt Enable

   DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);                                 // Full transfer Interrupt Enable

    

     /* Enable the DMA TIM Triggered */

     TIM_DMACmd(TIM2, TIM_DMA_Trigger, ENABLE);

     TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);

    

     /* Enable DMA1 Channel1 */

     DMA_Cmd(DMA1_Channel1, ENABLE);

 }

Looking at DMA_CCR1 gives me 0x2AB7 which is ok.

Looking at the SPI2_DR I found no value ; i.e. 0

Franck
24 REPLIES 24
Posted on December 02, 2014 at 00:54

I have TIM+DMA working on a number of STM32 platforms.

I think you have an STM32F3, but it's really important that you create free standing questions, and post complete code examples that compiles.

Check to see if the DMA is throwing any error conditions/states.

Check the TIM with an external pin.

Check if memory-to-memory mode is required for DMAx != APBx

Check if SPI->DR needs to be 16 or 32-bit wide

The value read from SPI->DR will NOT reflect data written to SPI->DR, it's not memory, it doesn't work like that.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
franck2
Associate II
Posted on December 02, 2014 at 11:08

Hi Clive,

I have TIM+DMA working on a number of STM32 platforms.

Great! That's mean it does work and my code has some mistake in.

I think you have an STM32F3:

I used a STM32F302 on a Nucleo evaluation board

Complete Code attached

Check to see if the DMA is throwing any error conditions/states.

No error from what I'm able to see.

Check the TIM with an external pin.

That's ok. TIM2_CH3 on PA9 given a 8MHz signal.

Check if memory-to-memory mode is required for DMAx != APBx

memory- to-memory only on DMA2 but STM32F302 as none and possesses only DMA1

Check if SPI->DR needs to be 16 or 32-bit wide

RM0365 says that SPI is 4-bit to 16-bit data size selection. I2S is 16-bit or 32-bit data frame.

The value read from SPI->DR will NOT reflect data written to SPI->DR, it's not memory, it doesn't work like that.

Isn't the SPI2_DR the SPI data register? I expected to find in that 16-bit register the data received.

Thanks again for your help. I appreciate

________________

Attachments :

main.c : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I168&d=%2Fa%2F0X0000000bib%2FMiHFneeDc0SMZdfjw8fHf2PUuufxKu9Nq74mv_oVAPY&asPdf=false
Posted on December 02, 2014 at 13:21

Confused, you're triggering at 8 MHz, what's your SPI clocking at? 64 MHz?

Correct, reading SPI->DR will show data received, not data transmitted.

DMA2 doing memory-to-memory is an F2/F4 issue, I haven't looked at your F3 part.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
franck2
Associate II
Posted on December 02, 2014 at 14:13

SPI clocking upt o 30MHz. So effectively I change my clocking TIM2 to 20x less (1.5MHz)!!

 /* Compute the value to be set in ARR regiter to generate signal frequency at f(SPI)/20=30MHz/20 */

 

    /* SPI up to 30MHz */

 

  TimerPeriod = (SystemCoreClock / 1500000);

I changed also TIM1 to 8x less as used for LDAC of external DAC.

  /* Compute the value to be set in ARR register to generate signal frequency at F(TIM2)/8=1,5MHz/8 */

 

  TimerPeriod = (SystemCoreClock / 187500);

TIM1 and TIM2 ok on pin PA9 and PC0.

But still nothing on the SPI pin at pin PB15 (MOSI).

How can I be sure that the DMA as being triggered by the TIM2? Flag?

Would it be possible to trig the DMA with the Timer, and send 4x32bits on the SPI without any interrupt in between each 32 bit?

franck2
Associate II
franck2
Associate II
Posted on December 02, 2014 at 14:55

Can it be that I have speed pb?

If I send only one 32 bit word I received the figure attached

________________

Attachments :

Screen_2014-12-02_02-54-53.jpeg : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I15A&d=%2Fa%2F0X0000000biY%2F.MWEeTj2cDQbaRt0rznAFnNIv_J9oXdch2xXgkvx6rM&asPdf=false
Posted on December 02, 2014 at 15:04

Well if you want the bits back-to-back why use the timer at all? The SPI can use DMA on the TXE flag.

For the TIM+DMA to be viable the trigger rate needs to be below the shift/word rate of the SPI, otherwise you'll keep stomping on the SPI->DR register before it shifts out.

To confirm the DMA pace, you'd use the TC and/or HT interrupts to toggle a GPIO and then scope the frequency of that. ie 100 transfers should occur at 100 periods of the timer.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
franck2
Associate II
Posted on December 02, 2014 at 16:01

Well if you want the bits back-to-back why use the timer at all? The SPI can use DMA on the TXE flag.

I know, but I would like to stream 4x32-bit data to an external DAC, with no sweat for the processor; so direct mode.

For the TIM+DMA to be viable the trigger rate needs to be below the shift/word rate of the SPI, otherwise you'll keep stomping on the SPI->DR register before it shifts out.

Ok.

To confirm the DMA pace, you'd use the TC and/or HT interrupts to toggle a GPIO and then scope the frequency of that. ie 100 transfers should occur at 100 periods of the timer.

Ok. I'll go hunting....

franck2
Associate II
Posted on December 02, 2014 at 16:06

Clive,

Where can I find an application note like AN4031 but for the STM32F302? Not able to find same kind of ST document for that µP.