0
\$\begingroup\$

I am experimenting with timers and interrupts using STM32CubeIDE and STM32F411E development board. I am comfortable with working on microcontrollers. I noticed some anomalies in the behavior of the code. The idea of the code is, after I introduce an external pulse on EXTI0, I'll start 2 counters, TIM1 and TIM9. TIM1 will run 10 times with period of 0.06 sec, each update interrupt will toggle PC7 to generate a square wave on the output. TIM9 will run once with period of 6 sec, at the update of TIM9, will re-activate EXTI0 interrupt. here is part of main.c

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();
 /* USER CODE BEGIN SysInit */
 /* USER CODE END SysInit */
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_TIM1_Init();
 MX_TIM9_Init();
 /* USER CODE BEGIN 2 */
 HAL_GPIO_WritePin(LD4_GPIO_Port, LD4_Pin, GPIO_PIN_RESET);
 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
 halfPeriodCount = 0;
 highFrequencyTogglerFlag = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 if(highFrequencyTogglerFlag == 1)
 {
 highFrequencyTogglerFlag = 0;
 highFrequencyToggel();
 }
 /* USER CODE END WHILE */
 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}
void highFrequencyToggel(void)
{
 uint32_t odr;
 /* get current Output Data Register value */
 odr = GPIOC->ODR;
 /* Set selected pins that were at low level, and reset ones that were high */
 GPIOC->BSRR = ((odr & GPIO_PIN_7) << GPIO_NUMBER) | (~odr & GPIO_PIN_7);
 halfPeriodCount = halfPeriodCount + 1;
 if(halfPeriodCount >= MAX_HALF_PERIOD_COUNT)
 {
 htim1.Instance->CR1 &= ~(TIM_CR1_CEN);
 }
}
void pulseDelay(void)
{
 LD4_GPIO_Port->BSRR = (uint32_t)LD4_Pin << 16U;
 htim9.Instance->CR1 &= ~(TIM_CR1_CEN);
}
void startTimers(void)
{
 halfPeriodCount = 0;
 LD4_GPIO_Port->BSRR = LD4_Pin;
// GPIOC->BSRR = GPIO_PIN_7;
 GPIOC->BSRR = (uint32_t)GPIO_PIN_7 << 16U;
 htim1.Instance->DIER |= TIM_IT_UPDATE;
 uint32_t itflag = htim1.Instance->SR;
 if ((itflag & (TIM_FLAG_UPDATE)) == (TIM_FLAG_UPDATE))
 {
 htim1.Instance->SR = ~TIM_FLAG_UPDATE;
 }
 htim1.Instance->CR1|= TIM_CR1_CEN;
 htim9.Instance->DIER |= TIM_IT_UPDATE;
 itflag = htim9.Instance->SR;
 if ((itflag & (TIM_FLAG_UPDATE)) == (TIM_FLAG_UPDATE))
 {
 htim9.Instance->SR = ~TIM_FLAG_UPDATE;
 }
 htim9.Instance->CR1 |= TIM_CR1_CEN;
}

here is stm32f4xx_it.c that does not work

void EXTI0_IRQHandler(void)
{
 /* USER CODE BEGIN EXTI0_IRQn 0 */
 HAL_NVIC_DisableIRQ(EXTI0_IRQn);
 __HAL_GPIO_EXTI_CLEAR_IT(Start_Pin);
 startTimers();
#ifdef RUN_HAL
 /* USER CODE END EXTI0_IRQn 0 */
 HAL_GPIO_EXTI_IRQHandler(Start_Pin);
 /* USER CODE BEGIN EXTI0_IRQn 1 */
#endif
 /* USER CODE END EXTI0_IRQn 1 */
}
/**
 * @brief This function handles TIM1 break interrupt and TIM9 global interrupt.
 */
void TIM1_BRK_TIM9_IRQHandler(void)
{
 /* USER CODE BEGIN TIM1_BRK_TIM9_IRQn 0 */
#ifdef RUN_HAL
 /* USER CODE END TIM1_BRK_TIM9_IRQn 0 */
 HAL_TIM_IRQHandler(&htim1);
 HAL_TIM_IRQHandler(&htim9);
 /* USER CODE BEGIN TIM1_BRK_TIM9_IRQn 1 */
#endif
 uint32_t itflag = htim9.Instance->SR;
 if ((itflag & (TIM_FLAG_UPDATE)) == (TIM_FLAG_UPDATE))
 {
 htim9.Instance->SR = ~TIM_FLAG_UPDATE;
 pulseDelay();
 }
 HAL_NVIC_EnableIRQ(EXTI0_IRQn);
 /* USER CODE END TIM1_BRK_TIM9_IRQn 1 */
}
/**
 * @brief This function handles TIM1 update interrupt and TIM10 global interrupt.
 */
void TIM1_UP_TIM10_IRQHandler(void)
{
 /* USER CODE BEGIN TIM1_UP_TIM10_IRQn 0 */
#ifdef RUN_HAL
 /* USER CODE END TIM1_UP_TIM10_IRQn 0 */
 HAL_TIM_IRQHandler(&htim1);
 /* USER CODE BEGIN TIM1_UP_TIM10_IRQn 1 */
#endif
 uint32_t itflag = htim1.Instance->SR;
 if ((itflag & (TIM_FLAG_UPDATE)) == (TIM_FLAG_UPDATE))
 {
 htim1.Instance->SR = ~TIM_FLAG_UPDATE;
 highFrequencyTogglerFlag = 1;
 }
 /* USER CODE END TIM1_UP_TIM10_IRQn 1 */
}

if I remove int8_t highFrequencyTogglerFlag = 1; and replace it with highFrequencyToggel();, the code works. What is driving this anomaly? And how can I fix it?

The preprocessor directive #ifdef RUN_HAL is to not use the default generic HAL functions.

asked Jun 1 at 4:08
\$\endgroup\$
2
  • \$\begingroup\$ While the end of the question contains "if I remove int8_t startTimerFlag = 0;", looking at the posted code I can't see a startTimerFlag variable. Has the correct code been posted? \$\endgroup\$ Commented Jun 1 at 6:59
  • \$\begingroup\$ @ChesterGillon, Sorry for that I just edited the post. I meant highFrequencyTogglerFlag \$\endgroup\$ Commented Jun 1 at 18:17

1 Answer 1

1
\$\begingroup\$

Suggest definition is changed to qualify the variable as volatile. I.e.:

volatile int8_t highFrequencyTogglerFlag = 1;

That is because highFrequencyTogglerFlag is shared between the main function and an interrupt handler.

Without the volatile qualifier the compiler optimiser may think there are no side-effects in the main function which change highFrequencyTogglerFlag, and not sample the updated value after has been modified by the interrupt handler. See this and this for some background information.

answered Jun 1 at 18:50
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.