cancel
Showing results for 
Search instead for 
Did you mean: 

Can STM32F103c8T6 transfer data from memory to GPIO

RJaco
Associate

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

0690X000006BuxgQAC.png

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

2 REPLIES 2

Read out and check the content of relevant TIM and DMA registers.

JW

RJaco
Associate

ok.

i will