Skip to main content
Visitor II
March 14, 2023
Question

resolving a conflict between using Timer3 interrupt and HAL_Delay()

  • March 14, 2023
  • 2 replies
  • 2396 views

Hi all,

Hardware - STM32L4R9 Disco with STEVAL-MK172V1 eCompass

I'm stuck trying to resolve some kind of conflict I'm having with Hal_Delay. I've lowered the priority of the timer interrupt so that SysTick is a higher priority. I've tried using both the TIM3_IRQHandler() found in the stm32xxxx_it.c file in core, and writing in HAL_TIM_PeriodElapsedCallback at the bottom of my main. with either of those methods, if there is no code to be handled, the loops and interrupts function so that I get the output loop over UART I'm using as a method of output for now, just without the data I'm ultimately calculating. I've made use of __disable and __enable_irq() in the interrupt handlers in an attempt to prevent conflict, but any time I try to execute any portion of what I'd like to be updating, the controller gets stuck in an infinite loop either as a result of of trying to run HAL_Delay, HAL_TIM_Base_Start_IT or printf (which is set up to print to the UART connection I have set up over the USB cable.

When I run debug and step through everything, sometimes it gets to main while loop before getting frozen, sometimes its when I run HAL_TIM_Base_Start_IT is where it gets stuck in a loop. when I pause the debugger after hitting this loop, it's almost always in either HAL_Delay or HAL_GetTick, with the variables showing delay = 5, tickstart = ~1545 and wait = 6.

I suspect I'm missing something fundamental about timing interrupts that my brain is skipping over that has to do with the fact that the process I want run at each interrupt is more complex than flipping a bit or an LED. I've tried to break down my function to only execute the most basic need (polling a set of 12 registers over i2c on another device) but It doesn't rectify the issue. what am I missing about using a timer interrupt that would create this conflict?

    This topic has been closed for replies.

    2 replies

    Super User
    March 14, 2023

    Prepare a *minimal* but complete compilable example exhibiting the problem, and post.

    The best way to do this is to start from scratch and add only what's necessary.

    JW

    HIngv.1Author
    Visitor II
    March 14, 2023

    I think it's likely I'm trying to do too much with the interrupt. I was hoping to run at least updating the accel/mag buffer variables when the interrupt triggers, but it seems the most I should be doing is flipping a bit or changing a bool sort of thing. I was hoping to get away with more than that

    IRQ handler:

    void TIM3_IRQHandler(void)
    {
     /* USER CODE BEGIN TIM3_IRQn 0 */
    	__disable_irq();
     /* USER CODE END TIM3_IRQn 0 */
     HAL_TIM_IRQHandler(&htim3);
     /* USER CODE BEGIN TIM3_IRQn 1 */
     getMagData();
     getAccData();
     __enable_irq();
     /* USER CODE END TIM3_IRQn 1 */
    }

    and then get Mag/ACC data is probably where its too long?

    void getMagData(void){
    	uint8_t data;
    	uint8_t reg;
     
    	reg = OUTX_L_REG_M;
    	HAL_I2C_Master_Transmit(&hi2c1, MAG_ADDR, &reg, 1, HAL_MAX_DELAY);
    	HAL_I2C_Master_Receive(&hi2c1, MAG_ADDR, &data, 1, HAL_MAX_DELAY);
    	mBuffer[0] = data;
    	reg = OUTX_H_REG_M;
    	HAL_I2C_Master_Transmit(&hi2c1, MAG_ADDR, &reg, 1, HAL_MAX_DELAY);
    	HAL_I2C_Master_Receive(&hi2c1, MAG_ADDR, &data, 1, HAL_MAX_DELAY);
    	mBuffer[1] = data;
    	reg = OUTY_L_REG_M;
    	HAL_I2C_Master_Transmit(&hi2c1, MAG_ADDR, &reg, 1, HAL_MAX_DELAY);
    	HAL_I2C_Master_Receive(&hi2c1, MAG_ADDR, &data, 1, HAL_MAX_DELAY);
    	mBuffer[2] = data;
    	reg = OUTY_H_REG_M;
    	HAL_I2C_Master_Transmit(&hi2c1, MAG_ADDR, &reg, 1, HAL_MAX_DELAY);
    	HAL_I2C_Master_Receive(&hi2c1, MAG_ADDR, &data, 1, HAL_MAX_DELAY);
    	mBuffer[3] = data;
    	reg = OUTZ_L_REG_M;
    	HAL_I2C_Master_Transmit(&hi2c1, MAG_ADDR, &reg, 1, HAL_MAX_DELAY);
    	HAL_I2C_Master_Receive(&hi2c1, MAG_ADDR, &data, 1, HAL_MAX_DELAY);
    	mBuffer[4] = data;
    	reg = OUTZ_H_REG_M;
    	HAL_I2C_Master_Transmit(&hi2c1, MAG_ADDR, &reg, 1, HAL_MAX_DELAY);
    	HAL_I2C_Master_Receive(&hi2c1, MAG_ADDR, &data, 1, HAL_MAX_DELAY);
    	mBuffer[5] = data;
    }//end getMagData
     
    void getAccData(void){
    	uint8_t data;
    	uint8_t reg;
     
    	reg = OUTX_L_A;
    	HAL_I2C_Master_Transmit(&hi2c1, ACC_ADDR, &reg, 1, HAL_MAX_DELAY);
    	HAL_I2C_Master_Receive(&hi2c1, ACC_ADDR, &data, 1, HAL_MAX_DELAY);
    	aBuffer[0] = data;
    	HAL_Delay(5);
    	reg = OUTX_H_A;
    	HAL_I2C_Master_Transmit(&hi2c1, ACC_ADDR, &reg, 1, HAL_MAX_DELAY);
    	HAL_I2C_Master_Receive(&hi2c1, ACC_ADDR, &data, 1, HAL_MAX_DELAY);
    	aBuffer[1] = data;
    	HAL_Delay(5);
    	reg = OUTY_L_A;
    	HAL_I2C_Master_Transmit(&hi2c1, ACC_ADDR, &reg, 1, HAL_MAX_DELAY);
    	HAL_I2C_Master_Receive(&hi2c1, ACC_ADDR, &data, 1, HAL_MAX_DELAY);
    	aBuffer[2] = data;
    	HAL_Delay(5);
    	reg = OUTY_H_A;
    	HAL_I2C_Master_Transmit(&hi2c1, ACC_ADDR, &reg, 1, HAL_MAX_DELAY);
    	HAL_I2C_Master_Receive(&hi2c1, ACC_ADDR, &data, 1, HAL_MAX_DELAY);
    	aBuffer[3] = data;
    	HAL_Delay(5);
    	reg = OUTZ_L_A;
    	HAL_I2C_Master_Transmit(&hi2c1, ACC_ADDR, &reg, 1, HAL_MAX_DELAY);
    	HAL_I2C_Master_Receive(&hi2c1, ACC_ADDR, &data, 1, HAL_MAX_DELAY);
    	aBuffer[4] = data;
    	HAL_Delay(5);
    	reg = OUTZ_H_A;
    	HAL_I2C_Master_Transmit(&hi2c1, ACC_ADDR, &reg, 1, HAL_MAX_DELAY);
    	HAL_I2C_Master_Receive(&hi2c1, ACC_ADDR, &data, 1, HAL_MAX_DELAY);
    	aBuffer[5] = data;
    }//end getAccData

    Graduate II
    March 14, 2023

    You can't disable interrupts and expect delays and timeouts, dependent on a higher priority interrupt, to function properly/desirably..

    Interrupts and callbacks should do the least amount of work possible. If you've got a long amounts of linear work, and blocking, perhaps thing of using an RTOS with tasks/threads, so other things can run concurrently.

    Super User
    March 14, 2023

    > I think it's likely I'm trying to do too much with the interrupt.

    Yes.

    The usual pattern is to set a flag in the interrupt and leave; and then in main loop check that flag and if set, perform the lengthy action.

    JW

    HIngv.1Author
    Visitor II
    March 14, 2023

    Thank you. I figured it was on my end and wanted to confirm.