2018-08-21 08:32 AM
I am trying to port the octoWS2811 for STM32F103c8T6.
This guy hubmartin has already done the heavy lifting and created a library using STM32 HAL. But the problem is that i am unable to get it to work. I am using Eclipse IDE.
This is his website where he explains whole concept :
http://www.martinhubacek.cz/arm/improved-stm32-ws2812b-library
This is the github page :
https://github.com/hubmartin/ws2812b_stm32F3
This diagram explains how the timers and DMA's are setup
I checked the relevant datasheets to see if the DMA requests by Timers are available and found that the timer used is supported.
I tried debugging to see if the DMA's were being triggered by putting a breakpoint in the halftransfer-callback and found that it wasn't triggered. Then i tried putting a Breakpoint in Timer-elapsed-callback and found that it wasn't triggered either.
Here is an important part of the code. In which the DMA and timers are configured
TIM_HandleTypeDef Tim2Handle;
TIM_OC_InitTypeDef tim2OC1;
TIM_OC_InitTypeDef tim2OC2;
uint32_t tim_period;
static void TIM2_init(void)
{
// TIM2 Periph clock enable
__HAL_RCC_TIM2_CLK_ENABLE();
// This computation of pulse length should work ok,
// at some slower core speeds it needs some tuning.
tim_period = SystemCoreClock / 800000; // 0,125us period (10 times lower the 1,25us period to have fixed math below)
uint32_t cc1 = (10 * tim_period) / 36;
uint32_t cc2 = (10 * tim_period) / 15;
Tim2Handle.Instance = TIM2;
Tim2Handle.Init.Period = tim_period;
Tim2Handle.Init.RepetitionCounter = 0;
Tim2Handle.Init.Prescaler = 0;
Tim2Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
Tim2Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
//HAL_TIM_PWM_Init(&Tim2Handle);
if(HAL_TIM_PWM_Init(&Tim2Handle) != HAL_OK)
{
Error_Handler();
}
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
tim2OC1.OCMode = TIM_OCMODE_PWM1;
tim2OC1.OCPolarity = TIM_OCPOLARITY_HIGH;
tim2OC1.Pulse = cc1;
tim2OC1.OCNPolarity = TIM_OCNPOLARITY_HIGH;
tim2OC1.OCFastMode = TIM_OCFAST_DISABLE;
//HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &tim2OC1, TIM_CHANNEL_1);
if(HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &tim2OC1, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
tim2OC2.OCMode = TIM_OCMODE_PWM1;
tim2OC2.OCPolarity = TIM_OCPOLARITY_HIGH;
tim2OC2.Pulse = cc2;
tim2OC2.OCNPolarity = TIM_OCNPOLARITY_HIGH;
tim2OC2.OCFastMode = TIM_OCFAST_DISABLE;
tim2OC2.OCIdleState = TIM_OCIDLESTATE_RESET;
tim2OC2.OCNIdleState = TIM_OCNIDLESTATE_RESET;
//HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &tim2OC2, TIM_CHANNEL_2);
if(HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &tim2OC2, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_Base_Start(&Tim2Handle);
HAL_TIM_PWM_Start(&Tim2Handle, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&Tim2Handle, TIM_CHANNEL_2);}
DMA_HandleTypeDef dmaUpdate;
DMA_HandleTypeDef dmaCC1;
DMA_HandleTypeDef dmaCC2;
static void DMA_init(void)
{
// TIM2 Update event
__HAL_RCC_DMA1_CLK_ENABLE();
dmaUpdate.Init.Direction = DMA_MEMORY_TO_PERIPH;
dmaUpdate.Init.PeriphInc = DMA_PINC_DISABLE;
dmaUpdate.Init.MemInc = DMA_MINC_DISABLE;
dmaUpdate.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
dmaUpdate.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
dmaUpdate.Init.Mode = DMA_CIRCULAR;
dmaUpdate.Init.Priority = DMA_PRIORITY_VERY_HIGH;
dmaUpdate.Instance = DMA1_Channel2;
//dmaUpdate.XferCpltCallback = TransferComplete;
//dmaUpdate.XferErrorCallback = TransferError;
HAL_DMA_DeInit(&dmaUpdate);
//HAL_DMA_Init(&dmaUpdate);
if(HAL_DMA_Init(&dmaUpdate) != HAL_OK)
{
Error_Handler();
}
//HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
//HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
HAL_DMA_Start(&dmaUpdate, (uint32_t)WS2812_IO_High, (uint32_t)&WS2812B_PORT->BSRR, BUFFER_SIZE);
// TIM2 CC1 event
dmaCC1.Init.Direction = DMA_MEMORY_TO_PERIPH;
dmaCC1.Init.PeriphInc = DMA_PINC_DISABLE;
dmaCC1.Init.MemInc = DMA_MINC_ENABLE;
dmaCC1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
dmaCC1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
dmaCC1.Init.Mode = DMA_CIRCULAR;
dmaCC1.Init.Priority = DMA_PRIORITY_VERY_HIGH;
dmaCC1.Instance = DMA1_Channel5;
//dmaUpdate.XferCpltCallback = TransferComplete;
//dmaUpdate.XferErrorCallback = TransferError;
//dmaUpdate.XferHalfCpltCallback = TransferHalf;
//HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
//HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
HAL_DMA_DeInit(&dmaCC1);
//HAL_DMA_Init(&dmaCC1);
if(HAL_DMA_Init(&dmaCC1) != HAL_OK)
{
Error_Handler();
}
HAL_DMA_Start(&dmaCC1, (uint32_t)ws2812bDmaBitBuffer, (uint32_t)&WS2812B_PORT->BRR, BUFFER_SIZE);
// TIM2 CC2 event
dmaCC2.Init.Direction = DMA_MEMORY_TO_PERIPH;
dmaCC2.Init.PeriphInc = DMA_PINC_DISABLE;
dmaCC2.Init.MemInc = DMA_MINC_DISABLE;
dmaCC2.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
dmaCC2.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
dmaCC2.Init.Mode = DMA_CIRCULAR;
dmaCC2.Init.Priority = DMA_PRIORITY_VERY_HIGH;
dmaCC2.Instance = DMA1_Channel7;
dmaCC2.XferCpltCallback = DMA_TransferCompleteHandler;
dmaCC2.XferHalfCpltCallback = DMA_TransferHalfHandler;
//dmaUpdate.XferErrorCallback = TransferError;
HAL_DMA_DeInit(&dmaCC2);
if(HAL_DMA_Init(&dmaCC2) != HAL_OK)
{
Error_Handler();
}
// __HAL_LINKDMA(htim, hdma[TIM_DMA_ID_CC2], dmaCC2);
// HAL_DMA_Init(htim->hdma[TIM_DMA_ID_CC2]);
HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
//HAL_DMA_Start(&dmaCC2, (uint32_t)WS2812_IO_Low, (uint32_t)&WS2812B_PORT->BSRR, BUFFER_SIZE);
if(HAL_DMA_Start(&dmaCC2, (uint32_t)WS2812_IO_Low, (uint32_t)&WS2812B_PORT->BSRR, BUFFER_SIZE) != HAL_OK)
{
Error_Handler();
}
}
void DMA1_Channel2_IRQHandler(void)
{
// Check the interrupt and clear flag
HAL_DMA_IRQHandler(&dmaUpdate);
}
void DMA1_Channel5_IRQHandler(void)
{
// Check the interrupt and clear flag
HAL_DMA_IRQHandler(&dmaCC1);
}
void DMA1_Channel7_IRQHandler(void)
{
// Check the interrupt and clear flag
HAL_DMA_IRQHandler(&dmaCC2);
}
I thing that the timers are not linked properly to DMA
2018-08-21 12:23 PM
Read out and check the content of relevant TIM and DMA registers.
JW
2018-08-22 01:07 AM
ok.
i will