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.

\$\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.

\$\endgroup\$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.