cancel
Showing results for 
Search instead for 
Did you mean: 

while(!DMA_GetFlagStatus(...)); never pass ....

hibou
Associate II
Posted on May 30, 2014 at 11:31

Hi,
I have a big problem,I try to use a WS2812 (LED card), with a stm32f4
But it doesn t work at all ....
I try in debug and the program is blocked here:while(!DMA_GetFlagStatus(DMA1_Stream5, DMA_FLAG_TCIF5));
please help ...

#include ''main.h''
#include ''usbd_hid_core.h''
#include ''usbd_usr.h''
#include ''usbd_desc.h''
#define TESTRESULT_ADDRESS 0x080FFFFC
#define ALLTEST_PASS 0x00000000
#define ALLTEST_FAIL 0x55555555
#define TIM3_CCR1_Address 0x40000434 // physical memory address of Timer 3
CCR1 register
#define d2r (3.14159265/180)

#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment = 4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN USB_OTG_CORE_HANDLE USB_OTG_dev __ALIGN_END;
uint16_t PrescalerValue = 0;
__IO uint32_t TimingDelay;
__IO uint8_t DemoEnterCondition = 0x00;
__IO uint8_t UserButtonPressed = 0x00;
LIS302DL_InitTypeDef LIS302DL_InitStruct;
LIS302DL_FilterConfigTypeDef LIS302DL_FilterStruct;
__IO int8_t X_Offset, Y_Offset, Z_Offset = 0x00;
uint8_t Buffer[6];
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure1;
uint16_t LED_BYTE_Buffer[100];
uint8_t eightbit[766][3] =
{
{255, 0, 0},
 ........ // big tab ^^
{255, 0, 0},
};

void
Timer3_init(
void
)
{
uint16_t PrescalerValue;
RCC_APB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_TIM3);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* Compute the prescaler value */
PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 29; 
// 800kHz
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
/* configure DMA */
/* DMA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
DMA_DeInit(DMA1_Stream5);
/* Configure DMA Stream */
DMA_InitStructure1.DMA_Channel = DMA_Channel_5;
DMA_InitStructure1.DMA_PeripheralBaseAddr = 0x40000434;
DMA_InitStructure1.DMA_Memory0BaseAddr = (uint32_t)LED_BYTE_Buffer;
DMA_InitStructure1.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure1.DMA_BufferSize = 42;
DMA_InitStructure1.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure1.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure1.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure1.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure1.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure1.DMA_Priority = DMA_Priority_High;
DMA_InitStructure1.DMA_FIFOMode = DMA_FIFOMode_Disable;
//DMA_InitStructure1.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure1.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure1.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream5, &DMA_InitStructure1);
/* TIM3 CC1 DMA Request enable */
TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE);
}
void
WS2812_send(uint8_t (*color)[3], uint16_t len)
{
uint8_t j;
uint8_t led;
uint16_t memaddr;
uint16_t buffersize;
buffersize = (len*24)+42; 
// number of bytes needed is #LEDs * 24 bytes +
42 trailing bytes
memaddr = 0; 
// reset buffer memory index
led = 0; 
// reset led index
// fill transmit buffer with correct compare values to achieve
// correct pulse widths according to color values
while
(len)
{
for
(j = 0; j < 8; j++) 
// GREEN data
{
if
( (color[led][1]<<j) & 0x80 ) 
// data sent MSB first, j = 0 is MSB j
= 7 
is
LSB
{
LED_BYTE_Buffer[memaddr] = 17; 
// compare value for logical 1
}
else
{
LED_BYTE_Buffer[memaddr] = 9; 
// compare value for logical 0
}
memaddr++;
}
for
(j = 0; j < 8; j++) 
// RED data
{
if
( (color[led][0]<<j) & 0x80 ) 
// data sent MSB first, j = 0 is MSB j
= 7 
is
LSB
{
LED_BYTE_Buffer[memaddr] = 17; 
// compare value for logical 1
}
else
{
LED_BYTE_Buffer[memaddr] = 9; 
// compare value for logical 0
}
memaddr++;
}
for
(j = 0; j < 8; j++) 
// BLUE data
{
if
( (color[led][2]<<j) & 0x80 ) 
// data sent MSB first, j = 0 is MSB j
= 7 
is
LSB
{
LED_BYTE_Buffer[memaddr] = 17; 
// compare value for logical 1
}
else
{
LED_BYTE_Buffer[memaddr] = 9; 
// compare value for logical 0
}
memaddr++;
}
led++;
len--;
}
// add needed delay at end of byte cycle, pulsewidth = 0
while
(memaddr < buffersize)
{
LED_BYTE_Buffer[memaddr] = 0;
memaddr++;
}
DMA_SetCurrDataCounter(DMA1_Stream5, buffersize);
DMA_Cmd(DMA1_Stream5, ENABLE);
TIM_Cmd(TIM3, ENABLE);
while
(!DMA_GetFlagStatus(DMA1_Stream5, DMA_FLAG_TCIF5)); 
TIM_Cmd(TIM3, DISABLE); 
DMA_Cmd(DMA1_Stream5, DISABLE); 
DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_TCIF5);
}
int
main(
void
)
{
int16_t i;
Timer3_init();
while
(1){
/* first cycle through the colors on 2 LEDs chained together
* last LED in the chain will receive first sent triplet
* --> last LED in the chain will 'lead'
*/
for
(i = 0; i < 766; i += 2)
{
WS2812_send(&eightbit[i], 2);
Delay(50000L);
}
/* cycle through the colors on only one LED
* this time only the first LED that data is
* fed into will update
*/
for
(i = 0; i < 766; i += 1)
{
WS2812_send(&eightbit[i], 1);
Delay(50000L);
}
}
}
void
Delay(__IO uint32_t nTime)
{
TimingDelay = nTime;
while
(TimingDelay != 0);
}
/**
* @brief Decrements the TimingDelay variable.
* @param None
* @retval None
*/
void
TimingDelay_Decrement(
void
)
{
if
(TimingDelay != 0x00)
{
TimingDelay--;
}
}
/**
* @brief This function handles the test program fail.
* @param None
* @retval None
*/
void
Fail_Handler(
void
)
{
/* Erase last sector */
FLASH_EraseSector(FLASH_Sector_11, VoltageRange_3);
/* Write FAIL code at last word in the flash memory */
FLASH_ProgramWord(TESTRESULT_ADDRESS, ALLTEST_FAIL);
while
(1)
{
/* Toggle Red LED */
STM_EVAL_LEDToggle(LED5);
Delay(5);
}
}
/**
* @brief MEMS accelerometre management of the timeout situation.
* @param None.
* @retval None.
*/
uint32_t LIS302DL_TIMEOUT_UserCallback(
void
)
{
/* MEMS Accelerometer Timeout error occured during Test program
execution */
if
(DemoEnterCondition == 0x00)
{
/* Timeout error occured for SPI TXE/RXNE flags waiting loops.*/
Fail_Handler();
}
/* MEMS Accelerometer Timeout error occured during Demo execution */
else
{
while
(1)
{
}
}
return
0;
}
#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\r\n'', file,
line) */
/* Infinite loop */
while
(1)
{
}
}
#endif

#ws2812-stm32-led-pwm-dma
20 REPLIES 20
Posted on May 30, 2014 at 15:28

Yes, I haven't review everything, but you aren't using the right stream. You need to review the DMA trigger table in RM0090

TIM3_CH1 is Stream 4 (Channel 5, DMA1)

TIM3_UP is Stream 2 (Channel 5, DMA1)

You don't get a TC signal because there are no transfers occurring, and you can't make random associations.

Expressing the peripheral address as (uint32_t)&TIM3->CCR1; might be preferable to a define. I don't recall if TIM3 is 32-bit or 16-bit, this will of course impact the width of CCR1
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
hibou
Associate II
Posted on May 30, 2014 at 18:01

hey, thanks for your answer, but I don't understand because like you can see here (page 9):

http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00046011.pdf

We have on DMA1, TIM3_CH2 in stream5, channel 5

In fact we have a STM32F407 but I guess it's the same ?

So is it good to use stream5, channel5 with TIM3 please ?

hibou
Associate II
Posted on June 02, 2014 at 10:15

Any ideas, please ?

stm322399
Senior
Posted on June 02, 2014 at 10:50

Either use Stream4 as Clive recommended, or change TIM3_CH1 for TIM3_CH2 if you really prefer to use Stream5.

Posted on June 02, 2014 at 10:52

You don't use CH2, so why would the related DMA stream/channel be relevant?

JW
hibou
Associate II
Posted on June 02, 2014 at 11:56

Thank you for your answer ...

I'm a beginner and I don't understand how to use this channel 2 in fact ... so please if you can indicate me ... what to do

Posted on June 02, 2014 at 12:13

> I'm a beginner and I don't understand how to use this channel 2 in fact ... so please if you can indicate me ... what to do

The timer has 4 channels, i.e. 4 ''outputs'' - think of it as if it would be an integrated circuit with 4 output pins, except it's integrated within the microcontroller - and every output goes to a different DMA stream/channel. So if you configure output on channel 1 usin

g
TIM_OC1Init()

, you then should use the DMA Stream/Channel connected to that one, i.e. DMA1/Stream4/Channel5. JW
hibou
Associate II
Posted on June 02, 2014 at 13:15

Thank you for your answer

Oh ok so I must change Stream5 by Stream4, good.

Is it good to say that I can, also, use 

TIM_OC2Init() instead of 

TIM_OC1Init() ?

I will try with stream4 btw, thanks

hibou
Associate II
Posted on June 02, 2014 at 18:43

SO i tried with Stream4, I change all stream5 by Stream4 ... and it doesn't work again .... program block on the same while ... transfer never finish ...

Please help