AnsweredAssumed Answered

STM32F407G_DISC1 --> TIM DMA Example

Question asked by Jibbajibba on Sep 18, 2016
Latest reply on Sep 18, 2016 by Clive One
Hi

Im trying to run the TIM DMA example, that is for example provided for the STM32F446ZE-Nucleo board from the STM32Cube_FW_F4_V1.13.0.

I would say i have made the changes for the STM32F407VG as it should, but somehow as soon as i enter the TIM_Config, and step trough, the debugger jumps crazy from line to line and i end up in the default handler or the error handler.

did i initialize something wrong??

as soon as i comment the tim_config, the project (currently just a blinky) runs normally.


---------------------------------------------------------------------------------
#define TIMx                             TIM4

/* Definition for TIMx clock resources */
#define TIMx_CLK_ENABLE                  __HAL_RCC_TIM4_CLK_ENABLE
#define DMAx_CLK_ENABLE                  __HAL_RCC_DMA1_CLK_ENABLE

/* Definition for TIMx Pins */
#define TIMx_CHANNEL3_GPIO_CLK_ENABLE    __HAL_RCC_GPIOB_CLK_ENABLE

#define TIMx_GPIO_CHANNEL3_PORT          GPIOB
#define GPIO_PIN_CHANNEL3                GPIO_PIN_8

#define GPIO_AF_TIMx                     GPIO_AF2_TIM4

/* Definition for TIMx's DMA */
#define TIMx_CC3_DMA_INST                DMA1_Stream7

/* Definition for ADCx's NVIC */
#define TIMx_DMA_IRQn                    DMA1_Stream7_IRQn
#define TIMx_DMA_IRQHandler              DMA1_Stream7_IRQHandler
---------------------------------------------------------------------------------

int main(void)
{
  /* MCU Configuration--------------------------------------------------------*/
  // NOTE: This is dependent on the hardware used and the projects peripherals
  //       that are being used
  // Initialize HWLib (currently hal, future: input param)
  HWLib::Initialize_HWLib(HWLib::e_hwlib_hal);
  // Initialize systems core clock configuration (currently hal)
  HWLib::SystemClock_Config(HWLib::e_hwlib_hal);
  // Initialize HWLib peripherals used in project (currently hal)
  //HWLib::Initialize_HWLibPeripherals(HWLib::e_hwlib_hal);

  Tim_Config(); // FIXME TEMP

  /* Project Configurtion ----------------------------------------------------*/
  // Initialize middleware objects: Register HWLib Function Callbacks
  // TODO
  MWLib::Initialize();
  // Initialize application object
  Application::Initialize();

  /* FreeRTOS ----------------------------------------------------------------*/
  /* Timer 1 definition */
  //osTimerDef(TimerHandle_01, Timer_CB_01); TODO
  //TimerHandle_01 = osTimerCreate(osTimer(TimerHandle_01), osTimerPeriodic, NULL);
  /* Thread 1 definition */
  osThreadDef(Thread1Name, Thread1, osPriorityNormal, 0, 128);
  ThreadHandle_01 = osThreadCreate(osThread(Thread1Name), NULL);
  /* Start scheduler */
  osKernelStart();
 
  /* DO NOT GET HERE ---------------------------------------------------------*/
  /* We should never get here as control is now taken by the RTOS scheduler */
  for(;;);
}


void HWLib::Initialize_HWLib(e_hwlib lib)
{
  if(lib == e_hwlib_hal)
  {
    /* Reset of all peripherals, Initializes the Flash interface and the
     * Systick. */
    HAL_Init();
  }
}


/* Configure the system clock */
void HWLib::SystemClock_Config(e_hwlib lib)
{
  if(lib == e_hwlib_hal)
  {
    CoreClock_Config();
  }
}


void CoreClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }

  HAL_RCC_EnableCSS();

  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 15, 0);
}


// fixme
TIM_HandleTypeDef  TimHandle;
TIM_OC_InitTypeDef sConfig;
uint32_t aCCValue_Buffer[3] = {0, 0, 0};
uint32_t uwTimerPeriod  = 0;

void Tim_Config(void)
{
  /* Compute the value of ARR regiter to generate signal frequency at 17.57 Khz */
  uwTimerPeriod = (uint32_t)(((SystemCoreClock/2) / 800000) - 1); // TODO
  /* Compute CCR1 value to generate a duty cycle at 75% */
  aCCValue_Buffer[0] = (uint32_t)(((uint32_t) 75 * (uwTimerPeriod - 1)) / 100);
  /* Compute CCR2 value to generate a duty cycle at 50% */
  aCCValue_Buffer[1] = (uint32_t)(((uint32_t) 50 * (uwTimerPeriod - 1)) / 100);
  /* Compute CCR3 value to generate a duty cycle at 25% */
  aCCValue_Buffer[2] = (uint32_t)(((uint32_t) 25 * (uwTimerPeriod - 1)) / 100);

  /*##-1- Configure the TIM peripheral #######################################*/
  /* ---------------------------------------------------------------------------
  * TIM3 input clock is set to APB1 clock (PCLK1),
   * if (APB1 prescaler = 1) x1 else x2
   * prescaler is 4.
   * TIM1CLK = (HCLK/4) x2 = (HCLK/2)

  TIM3CLK = SystemCoreClock, Prescaler = 0, TIM3 counter clock = SystemCoreClock/2
  SystemCoreClock is set to 180 MHz for STM32F4xx devices.

  The objective is to configure TIM3 channel 3 to generate a PWM
  signal with a frequency equal to 17.57 KHz:
     - TIM3_Period = ((SystemCoreClock/2) / 17570) - 1
  and a variable duty cycle that is changed by the DMA after a specific number of
  Update DMA request.

  The number of this repetitive requests is defined by the TIM3 Repetition counter,
  each 4 Update Requests, the TIM3 Channel 3 Duty Cycle changes to the next new
  value defined by the aCCValue_Buffer.

    Note:
     SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f4xx.c file.
     Each time the core clock (HCLK) changes, user had to update SystemCoreClock
     variable value. Otherwise, any configuration based on this variable will be incorrect.
     This variable is updated in three ways:
      1) by calling CMSIS function SystemCoreClockUpdate()
      2) by calling HAL API function HAL_RCC_GetSysClockFreq()
      3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
  -----------------------------------------------------------------------------*/
  /* Initialize TIM3 peripheral as follows:
      + Period = TimerPeriod (To have an output frequency equal to 17.570 KHz)
      + Repetition Counter = 3
      + Prescaler = 0
      + ClockDivision = 0
      + Counter direction = Up
  */
  TimHandle.Instance               = TIMx;
  TimHandle.Init.Period            = uwTimerPeriod;
  TimHandle.Init.RepetitionCounter = 3;
  TimHandle.Init.Prescaler         = 0;
  TimHandle.Init.ClockDivision     = 0;
  TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
  if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }

  for(int b;;)
  {
    b++;
  }

  /*##-2- Configure the PWM channel 3 ########################################*/
  sConfig.OCMode       = TIM_OCMODE_PWM1;
  sConfig.OCPolarity   = TIM_OCPOLARITY_HIGH;
  sConfig.Pulse        = aCCValue_Buffer[0];
  sConfig.OCNPolarity  = TIM_OCNPOLARITY_HIGH;
  sConfig.OCFastMode   = TIM_OCFAST_DISABLE;
  sConfig.OCIdleState  = TIM_OCIDLESTATE_RESET;
  sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_3) != HAL_OK)
  {
    /* Configuration Error */
    Error_Handler();
  }

  /*##-3- Start PWM signal generation in DMA mode ############################*/
  if (HAL_TIM_PWM_Start_DMA(&TimHandle, TIM_CHANNEL_3, aCCValue_Buffer, 3) != HAL_OK)
  {
    /* Starting Error */
    Error_Handler();
  }
}


HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim)
{
  /* Check the TIM handle allocation */
  if(htim == NULL)
  {
    return HAL_ERROR;
  }

  /* Check the parameters */
  assert_param(IS_TIM_INSTANCE(htim->Instance));
  assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
  assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));

  if(htim->State == HAL_TIM_STATE_RESET)
  {
    /* Allocate lock resource and initialize it */
    htim->Lock = HAL_UNLOCKED;
    /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
    HAL_TIM_PWM_MspInit(htim);
  }

  /* Set the TIM state */
  htim->State= HAL_TIM_STATE_BUSY;  
 
  /* Init the base time for the PWM */  
  TIM_Base_SetConfig(htim->Instance, &htim->Init);
   
  /* Initialize the TIM state*/
  htim->State= HAL_TIM_STATE_READY;
 
  return HAL_OK;

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
  // Tim DMA transfer ---------------------------------------------------------
  // TODO integrate tim config etc.
  GPIO_InitTypeDef   GPIO_InitStruct;
  static DMA_HandleTypeDef  hdma_tim;

  /*##-1- Enable peripherals and GPIO Clocks #################################*/
  /* TIMx clock enable */
  TIMx_CLK_ENABLE();

  /* Enable GPIO Channel3/3N Clocks */
  TIMx_CHANNEL3_GPIO_CLK_ENABLE(); //FIXME already made during uart dma gpio

  /* Enable DMA clock */
  DMAx_CLK_ENABLE(); //FIXME already made during uart dma

  /* Configure TIM3_Channel3 in output, push-pull & alternate function mode */
  GPIO_InitStruct.Pin = GPIO_PIN_CHANNEL3;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF_TIMx;
  HAL_GPIO_Init(TIMx_GPIO_CHANNEL3_PORT, &GPIO_InitStruct);


  /* Set the parameters to be configured */
  hdma_tim.Init.Channel = DMA_CHANNEL_2; // todo was 5
  hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH;
  hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
  hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD ;
  hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD ;
  hdma_tim.Init.Mode = DMA_CIRCULAR;
  hdma_tim.Init.Priority = DMA_PRIORITY_HIGH;
  hdma_tim.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
  hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE;
  hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;

  /* Set hdma_tim instance */
  hdma_tim.Instance = TIMx_CC3_DMA_INST;

  /* Link hdma_tim to hdma[TIM_DMA_ID_CC3] (channel3) */
  __HAL_LINKDMA(htim, hdma[TIM_DMA_ID_CC3], hdma_tim);

  /* Initialize TIMx DMA handle */
  HAL_DMA_Init(htim->hdma[TIM_DMA_ID_CC3]);

  /*##-2- Configure the NVIC for DMA #######################################*/
  /* NVIC configuration for DMA transfer complete interrupt */
  HAL_NVIC_SetPriority(TIMx_DMA_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(TIMx_DMA_IRQn);
}




Outcomes