564 views
in System Integration by

Hello,

I'm using Actron LizardBoard with STM32F469NIH MCU. I'm developing a rise and fall edges counter for a signal (connected to PB8 input, called DF_ENCODE1) using Timer10 Channel1 in Input Capture direct mode.

I'm having issues with the application freezing completely when I enable the timer and have a rising or falling edge of the signal.

Before integrating it with EW, I developed the application with STM32CubeIDE and tested its functionality. The application works. I then integrated the GPIO and timer10 initialization by copying the code generated by the Cube. I should point out that I've already integrated the I/O settings and the use of the SPI peripheral into the EW project, and they work.
I have the feeling that for some reason the timer10 callback isn't being executed (HAL_TIM_IC_CaptureCallback), even though it's included in the code in the file I use for device integration.

This is the inline code used for device integration:

This is the DeviceClass Init constructor:

Below is the code used to initialize timer10 in ST51PRO_tim.c file  (I also reported the code that is executed by the HAL_TIM_Base_MspInit function which is called inside the HAL_TIM_Base_Init and which is normally "customized" based on the hardwar):I explicitall:

void ST51PRO_tim_TIM10_Init(void)
{
  TIM_IC_InitTypeDef sConfigIC = {0};

  htim10.Instance = TIM10;
  htim10.Init.Prescaler = 90-1;
  htim10.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim10.Init.Period = 65535;
  htim10.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim10.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim10) != HAL_OK)
  {
    Error_Handler();
  }
  //Explicit code from HAL_TIM_Base_MspInit
  __HAL_RCC_TIM10_CLK_ENABLE();
  HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 10, 0);
  HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
  //End of explicit code

  if (HAL_TIM_IC_Init(&htim10) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_BOTHEDGE;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&htim10, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
}

This is the code to enable timer10:

void ST51PRO_tim_Start_Encoder1Counter(void)
{
  HAL_TIM_IC_Start_IT(&htim10, TIM_CHANNEL_1);      //Abilito interrupt timer10 (segnale DF_ENCODER1)  
}

This is the callback function on ST51PRO_DevInt.c file:

//Callback capture timer10 
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
  DF_DIRECTION_TOGGLE;                            //Debug signal
  //Timer10 (encoder1)
  if (htim->Instance == htim10.Instance)           //Vedo segnale per capire se fronte salita o discesa
  {
     
     if (HAL_GPIO_ReadPin(DF_ENCODER1_GPIO_Port, DF_ENCODER1_Pin) == 1)
        In.df_encoder1_rise++;
     else
       In.df_encoder1_fall++;
  }
}

I added a pin toggle (DF_DIRECTION) debug signal to see if callback is called, but nothing happens.

To see that application freezes, I added a rectangle color animation effect that changes rectangle color from white to black and when there is a rise/fall edge on DF_ENCODER1 signal the animation stops.

I understand it's not easy to provide support for device integration, but the code with ST works, so I don't understand why it seems like the program crashes when the interrupt rises. I've also tried changing the interrupt's priority and excluding as many other code as possible (SPI initialization, etc...), but I still get the same result (program freeze).
If I don't start the timer (i.e., I don't run the ST51PRO_tim_STartEncoder1Counter() function), the code doesn't crash, but obviously it doesn't count any edges!

I can provide you all the code needed to better understand the issue.

Thank you for help!

1 Answer

0 votes
by
Hello,

first some questions:
1. What exactly do you mean by "but the code with ST works"?
Does it work in standalone STM32CubeIDE without Embedded Wizard?
Same timer code and GPIO configuration?

2. What do you mean by "crashed"?
Is there a hardfault?
Where does the CPU stop in the debugger?
Can you check the call stack when it freezes?

Best regards,

Manfred.
by

Hello Manfred,

1 I mean that the code written with ST32CubeIDE to test the rise/fall counter works (in the code, global variables are increased each rising/falling edge in the callback and their values are outputted in two DAC outputs, so I see DAC output voltages rising every edge). The init code (GPIO and TIMERS) is the same, I copied it from ST32CubeIDE to my BSP files (ST51PRO_gpio.c/h, ST51PRO_tim.c/h and ST51PRO_DevInt.c/h). I also try to make some changes in the init funcion of Timer10 (copied out the code written in the HAL_TIM_Base_MspInit that sets Interrupt priority.

The main code in ST32 is:

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* Configure the peripherals common clocks */
  PeriphCommonClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_LTDC_Init();
  MX_FMC_Init();
  MX_CAN1_Init();
  MX_CRC_Init();
  MX_I2C1_Init();
  MX_QUADSPI_Init();
  MX_TIM4_Init();
  MX_RTC_Init();
  MX_DMA2D_Init();
  MX_SPI2_Init();
  MX_SPI6_Init();
  MX_USART2_UART_Init();
  MX_ADC2_Init();
  MX_USART6_UART_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  MX_TIM8_Init();
  MX_TIM9_Init();
  MX_TIM10_Init();
  MX_TIM12_Init();
  MX_TIM14_Init();
  MX_IWDG_Init();
  /* USER CODE BEGIN 2 */
  //HAL_Delay(100);
  HAL_TIM_IC_Start_IT(&htim10, TIM_CHANNEL_1);			//Abilito interrupt timer10 (segnale DF_ENCODER1)
  HAL_TIM_IC_Start_IT(&htim14, TIM_CHANNEL_1);			//Abilito interrupt timer14 (segnale DF_ENCODER2)
  In.df_encoder1_rise = 0;
  In.df_encoder1_fall = 0;
  In.df_encoder2_rise = 0;
  In.df_encoder2_fall = 0;
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  if (In.df_encoder1_rise >= 250)
	  	  In.df_encoder1_rise = 0;
	  if (In.df_encoder2_rise >= 250)
	  	  In.df_encoder2_rise = 0;
	  ST51_PRO_DAC_OutA((uint8_t) In.df_encoder1_rise);
	  ST51_PRO_DAC_OutB((uint8_t) In.df_encoder2_rise);
	  HAL_IWDG_Refresh(&hiwdg);			//Refres IWDG (timeout 512ms)
  }
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

  /* USER CODE END 3 */
}


//..SOME OTHER FUNCIONS SET BY CubeMX (void SystemClock_Config(void) and void PeriphCommonClock_Config(void))

/* USER CODE BEGIN 4 */
//Callback capture timer10 (df_encoder1) e 14 (Df_encoder2)
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
  HAL_GPIO_TogglePin(DF_DIRECTION_GPIO_Port, DF_DIRECTION_Pin);     //Segnale debug
  //TImer10 (encoder1)
  if (htim->Instance == htim10.Instance)				//Vedo segnale per capire se fronte salita o discesa
  {
	  if (HAL_GPIO_ReadPin(DF_ENCODER1_GPIO_Port, DF_ENCODER1_Pin) == 1)
		  In.df_encoder1_rise++;
	  else
		  In.df_encoder1_fall++;
  }
  //Timer14 (encoder2)
  else if (htim->Instance == htim14.Instance)			//Vedo segnale per capire se fronte salita o discesa
  {
	  if (HAL_GPIO_ReadPin(DF_ENCODER2_GPIO_Port, DF_ENCODER2_Pin) == 1)
		  In.df_encoder2_rise++;
	  else
		  In.df_encoder2_fall++;
  }
}

 

The code of HAL_TIM_Base_MspInit related to timer10 in CubeIDE is:

else if(htim_base->Instance==TIM10)
  {
    /* USER CODE BEGIN TIM10_MspInit 0 */

    /* USER CODE END TIM10_MspInit 0 */

    /* Peripheral clock enable */
    __HAL_RCC_TIM10_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**TIM10 GPIO Configuration
    PB8     ------> TIM10_CH1
    */
    GPIO_InitStruct.Pin = GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF3_TIM10;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* TIM10 interrupt Init */
    HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
    /* USER CODE BEGIN TIM10_MspInit 1 */

    /* USER CODE END TIM10_MspInit 1 */
  }

I also tried to change priority (HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 10, 0);

2 With "crashed" I mean that the whole application freezes: when a rising/falling edge of the DF_ENCODER1 signal is generated, touch screen doesn't works and the animation of the rectangle stops. The screen remains as it was when the DF_ENCODER1 signal changed state. It "seems" that the system enters in some never ending function and waits for something.

I'm quite new in EW, so I don't know if there is a way to debug the application on the target and not only in prototype.How can I check the call stack in the target?

Thank for support!

Nicola

 

by

Hello Nicola,

difficult to give you helpful advices without debugging your code...

Anyhow, let me give you some hints:

  • Please follow our Getting Started documentation that fits to your STM32 Platform (see STM32 Build Environments). Within each document you find a section that describes the debugging options via serial interface and a console output and it describes the workflow with the different toolchains, inclusive STM32CubeIDE. So it is possible to debug.
  • Please have a look to the example DeviceIntegration that you will find within most Build Environments within the folder /Examples/DeviceIntegration. It shows the integration of devices into a UI application and addresses typical questions: How to start a certain action on the target? How to get data from a device? So it demonstrates the access to the underlying hardware, e.g. accessing a LED and getting events from a hardbutton.
  • As you have a running example with CubeMX, you can take step by step the initialization code and integrate that into your project.

I hope this helps.

Best regards,

Manfred

by

Hello Manfred,

finally, I have found the issue! As you suggested, I take step by step the inizialization code and the IRQ handle. I have found that I missed to insert code on the file stm32f4xx_it.c/h to handle the interrupt. This file is part of the LizardBoard package and that's why I thought it didn't need to be modified.

I added the code:

void TIM1_UP_TIM10_IRQHandler(void)
{
  HAL_TIM_IRQHandler(&htim10);
}

and the interrupt now works!

I'm quite new also in STM32 microcontroller, so I didn't know that I had to set also this in code integration (CubeMx did it for me in IDE!).

Thank you for support.

Nicola

Ask Embedded Wizard - Archive

Welcome to the Ask Embedded Wizard archive. This community forum served us well for many years, but we've evolved our support approach!

Your resources:

The Embedded Wizard Online Documentation provides comprehensive documentation, tutorials, examples and ready-to-use software packages.

For dedicated assistance, explore our Embedded Wizard Product Support.

You can still browse the valuable discussions from our community history here.

Embedded Wizard Website | Privacy Policy | Imprint

...