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
franck2
Associate II
Posted on December 03, 2014 at 14:34

Dear all,

The forum is truly awful for finding things!!!

My code has developped.

Still nothing on the SPI but looking to DMA_CCR1 I'm able to see bit HTIE and TCIE of half and full transfer switch to 1 by putting a breakpoint in my code and doing step on line with the peripheral system viewer DMA1 activated.

How do I use the TC and/or HT interrupts to toggle a GPIO as these signals are internal one?

franck2
Associate II
Posted on December 03, 2014 at 14:39

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6gc&d=%2Fa%2F0X0000000btC%2FN5NG.gMlUI6rySsmSOwErAxCgvF72Dz3Cj7SwBg3br0&asPdf=false
franck2
Associate II
Posted on December 03, 2014 at 14:57

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6gh&d=%2Fa%2F0X0000000btD%2F7_Ac.WxsYh1anKZ6p1AnXr7TOnKfK1WOYzIbLN_K_54&asPdf=false
Posted on December 03, 2014 at 19:41

This would seem to reasonably demonstrate SPI output paced via TIM+DMA, ported from my STM32F4-DISCO version.

// STM32F3-Discovery SPI2 TX DMA TIM Demo - sourcer32@gmail.com
#include ''stm32f3_discovery.h''
#include ''stm32f30x.h''
//******************************************************************************
void RCC_Configuration(void)
{
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Enable TIM1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* Enable SPI2 clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
/* GPIOB clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
}
//******************************************************************************
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_5); // PB13 SPI2 SCLK
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_5); // PB15 SPI2 MOSI
}
//******************************************************************************
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
int Prescaler, Period;
Prescaler = (SystemCoreClock / 8000000); // 8 MHz timebase, assumes APB2 H/1 TIMCLK1 H/1
Period = 8000000 / 8000; // 8 MHz -> 8 KHz
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = Period - 1;
TIM_TimeBaseStructure.TIM_Prescaler = Prescaler - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
// Need to add code to drive TIM1_CH1N as faux chip select
// going LOW at UPDATE, with Pulse tuned to go high after DMA initiated burst
// completes
/* Output Compare PMW1 Mode configuration */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OCInitStructure.TIM_Pulse = Period / 2; // 50%
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
/* Enable pins, TIM1 more sensitive */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
/* Enable the DMA trigger */
TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);
/* TIM1 enable counter */
TIM_Cmd(TIM1, ENABLE);
}
//******************************************************************************
void SPI_Configuration(void)
{
SPI_InitTypeDef SPI_InitStructure;
/* SPI configuration */
SPI_I2S_DeInit(SPI2);
/* Initializes the SPI communication */
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; // APB1 36 MHz, SPI2 55 KHz
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_Init(SPI2, &SPI_InitStructure);
/* Enable the SPI peripheral */
SPI_Cmd(SPI2, ENABLE);
}
//******************************************************************************
uint8_t TxBuffer[] = ''The quick brown fox jumps over the lazy dog'';
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
// DMA1 Channel5 TIM1_UP
/* DMA configuration */
DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&TxBuffer[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = sizeof(TxBuffer) - 1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
/* Enable the DMA channel */
DMA_Cmd(DMA1_Channel5, ENABLE);
}
//******************************************************************************
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the DMA1 Channel5 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//******************************************************************************
void DMA1_Channel5_IRQHandler(void) // X Hz
{
/* Test on DMA1 Channel5 Transfer Complete interrupt */
if(DMA_GetITStatus(DMA1_IT_TC5))
{
/* Clear DMA1 Channel5 Transfer Complete interrupt pending bits */
DMA_ClearITPendingBit(DMA1_IT_TC5);
STM_EVAL_LEDToggle(LED3); // X/2 Hz
}
}
//******************************************************************************
int main(void)
{
/* Initialize LED available on STM32F3-Discovery board */
STM_EVAL_LEDInit(LED3);
/* Turn on LD3 */
STM_EVAL_LEDOn(LED3);
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
DMA_Configuration();
SPI_Configuration();
TIM_Configuration();
while(1); /* Infinite loop */
}
/**************************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d

'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif

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 04, 2014 at 14:10

Many, Many Thanks Clive.

It works perfectly also on my evaluation board (STM32F3xx).

Few questions:

*Which pin is assign for TIM1? so I can see it on a GPIO pins of my STM32F.

As far I understand it is going low at UPDATE with Pulse tuned to go high after DMA initiated burst completes. Right?

Posted on December 04, 2014 at 14:32

Well that's functionality I didn't take to completion. You'd have to select a suitable pin/channel from the timer. I might tinker with it if I find some moments.

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 04, 2014 at 16:20

Hi Clive,

You've done the job!

It's my turn to keep going on and work on it!

Thanks a lot, again.

Best regards.

franck2
Associate II
Posted on December 12, 2014 at 15:47

Hi,

I have a pb. Everything working perfectly as shown by attachment file.

However looking to Reference Manual of STM32F302, the frame size of the SPI is 16-bits. My source is 32-bit. As indicated by still the manual the data will be truncated. Source 32-bit & Destination 16-bit. So @0x0 /B4B3B2B1 => @0x0/B1B0.

How should I overcome?

Thanks

________________

Attachments :

Screen_2014-12-12_03-40-37_0.jpeg : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0tO&d=%2Fa%2F0X0000000biX%2FpXvM2nxXWgCrATbT1PtiGSFYKYMx_HjlRy2K7khBdtk&asPdf=false
Posted on December 12, 2014 at 16:52

I'm not sure how two back-to-back 16-bit bus transactions, without intervening CS, would be materially different than one 32-bit transaction.

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 12, 2014 at 18:01

Clive,

I send a 32-bits word ABCD1234 and obtain only 1234 on the SPI as shown by the attachement as expected and said by the Reference Manual. Do I misunderstand something?

SPI configured with a 16-bit Datasize and DMA as follow:

  DMA_DeInit(DMA1_Channel5);

 

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR;

 

  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&TxBuffer[0];

 

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

 

  DMA_InitStructure.DMA_BufferSize = 1;

 

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

 

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

 

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

 

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;

 

  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

 

  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;

 

  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

 

  DMA_Init(DMA1_Channel5, &DMA_InitStructure);

Best regards