cancel
Showing results for 
Search instead for 
Did you mean: 

delay function with timer interrupt

Benjamin Brammer
Senior II
Posted on April 25, 2018 at 16:03

Hey Guys,

I don't know what I am doing wrong here and really would appreciate some help:

I created a function called

void DELAY_1_5us(uint16_t period)
{
delay = true;
__HAL_TIM_SET_AUTORELOAD(&htim7, period);
LCD_CS_LOW;
HAL_TIM_Base_Start_IT(&htim7);
while(delay);
}�?�?�?�?�?�?�?�?

this function uses TIM7 of the STM32F429ZI-DISC1 discovery board as a simple programmable timer for approx. x time 1,5µs delay. with the 16-Bit ARR value I get maximum 2^16 x 1,5µs delays because of the following init routine (84MHz/128 = 656,250kHz = 1,5238 µs counter tick):

void MX_TIM7_Init(void)
{
 TIM_MasterConfigTypeDef sMasterConfig;
 htim7.Instance = TIM7;
 htim7.Init.Prescaler = 128;
 htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
 htim7.Init.Period = 1;
 if (HAL_TIM_Base_Init(&htim7) != HAL_OK)
 {
 _Error_Handler(__FILE__, __LINE__);
 }
 sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
 if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK)
 {
 _Error_Handler(__FILE__, __LINE__);
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

In the ISR I just set the delay value so the while loop in the dely function is interrupted. The LCD_CS pin is just to measure the elapsed time on an oscilloscope.

void TIM7_IRQHandler(void)
{
 /* USER CODE BEGIN TIM7_IRQn 0 */
HAL_TIM_Base_Stop_IT(&htim7);
LCD_CS_HIGH;
delay = false;
 /* USER CODE END TIM7_IRQn 0 */
 HAL_TIM_IRQHandler(&htim7);
 /* USER CODE BEGIN TIM7_IRQn 1 */
 /* USER CODE END TIM7_IRQn 1 */
}�?�?�?�?�?�?�?�?�?�?�?�?

The problem now is, that the function -regardless which value for the delay period of the DELAY_1_5_us functionI choose - the timer shows only approx. 1µs delay on the oscilloscope. I checked the register entry for TIM7_ARR and it changes with each function call. I also thought this might have to do something with the UG bit to generate an UE so that the timer loads the new ARR value.

But even with htim7.instance->EGR = 0x1 nothing is happening. Also when I try to activate the preload buffer with htim7.instance->CR1 |= 0x0080; nothing is changing in the appropriate reigisters.

I would really appreciate if someone could help me. I tried the code with ATOLLIC TrueStudio and SW4STM32 all set with optimize for debug.

best regads

Benjamin

#delay-function #stm32f4 #tim7 #changing-arr-in-run
17 REPLIES 17
Posted on April 26, 2018 at 01:01

Read out and post the TIM registers just before you enable the interrupt, or maybe in the ISR (or both).

JW

Posted on April 27, 2018 at 09:31

Hey JW,

thx for your answer. I will provide the readout on monday because I have free time today.

Have a nice weekend.

best regards

Benjamin

henry.dick
Senior II
Posted on April 30, 2018 at 12:13

'

The problem now is, that the function'

make sure that there is sufficient time for the isr overhead and execution. super short time periods may not work.

to see if that's a problem, increase the timer period.

BTW, there are better ways to do this.

Posted on April 30, 2018 at 10:51

Hey JW,

see attached the screenshots from the registers:

First I issued a delay of 10 x 1,5µs so the ARR is 10. This screenshot is when the MC processes the function call:

0690X00000604XoQAI.jpg

Here is the screenshot of the first ISR entering (10x1,5µs):

0690X00000604dfQAA.jpg

When I issue a second delay right after with 100 x 1,5µs it seems as if the counter doesn't start from zero, but the last value after I stopped it in the ISR. Possible this might be the error I am facing? 

0690X00000604Y2QAI.jpg

Inside ISR (100 x 1,5µs):

0690X00000604e4QAA.jpg

Ok, I will try to write 0x00 into TIM7_CNT so I force the timer to start from zero. Hopefully this workaround will work..

best regards

Benjamin

Posted on April 30, 2018 at 10:59

Nope..did not work. The counter doesn't reset. I even get the impression it is still running, allthough I stop it inside the ISR... But maybe I set this wrong:

void DELAY_1_5us(uint16_t period)
{
 delay = true;
 __HAL_TIM_SET_AUTORELOAD(&htim7, period);
 htim7.Instance->CNT = 0;
 htim7.Instance->EGR = TIM_EGR_UG;
 TEST_LOW;
 HAL_TIM_Base_Start_IT(&htim7);
 while(delay);
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Mhh..this is really strange. The timer seems not to halt after the last ISR execution..allthough the HAL command is issued...Why is that so?

Posted on April 30, 2018 at 12:10

It's really really strange. when I do irect registr access, like TIM7->CR1 |=TIM_CR1_ARPE; nothing is happening in the registers...

Also the timer is not stopped after the last ISR execution.  Another really strange behavior is that sometimes the above register command is executed and sometimes not. I am using TRUEStudio, but I think TRUE Studio has a lot of fails and problems. I will try to switch back to SW4STM32 and see if there is the same strange behavior..

Posted on April 30, 2018 at 14:00

Hello dhenry,

I did test the delay function with 10 x 1,5µs , 100 and 1000. Nothing changes in the execution time..that is basically the problem. As I am running the processor with 168MHz and the timers with 168MHz or 84MHz I think there should be enough time for µs delay, don't you?

What would be an accurate and better solution for µs delay than this? I would be happy for a link or advise.

best regards

Benjamin

Benjamin Brammer
Senior II
Posted on April 30, 2018 at 16:34

OK the following Version seems to work perfectly and accurate:

DWT->CTRL |= 1; // enabling the DWT counter
#pragma GCC push_options
#pragma GCC optimize ('O3')
void delayUS_DWT(uint32_t us)
{
volatile uint32_t cycles = (SystemCoreClock/1000000L)*us;
volatile uint32_t start = DWT->CYCCNT;
GPIOC->ODR &= ~TEST_Pin;
do {
} while(DWT->CYCCNT - start < cycles);
GPIOC->ODR |= TEST_Pin;
}
#pragma GCC pop_options�?�?�?�?�?�?�?�?�?�?�?�?�?�?

I will use this version instead of my ISR Timer-Variants.

Thx for all the help and advies!

Benjamin

Posted on April 30, 2018 at 14:57

I rewrote the delay function and ISR handling to have a constant 1µs cycle time so that I have an ISR every 1µs and decrease the time for the delay in x µs buteven when I change theARR value the first counter cycle has allways the same amount of time in exicution, all the other delay times change the timer cycle but are not linearily scaled. This is now really strange I think.

Here the new delay function:

void DELAY_1_5us(uint16_t period)
{
 //htim7.Instance->EGR = TIM_EGR_UG;
 delay = period;
 TIM7->CNT = 0;
 TEST_LOW;
 HAL_TIM_Base_Start_IT(&htim7);
 while(delay > 0);
 TEST_HIGH;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

The ISR:

void TIM7_IRQHandler(void)
{
 /* USER CODE BEGIN TIM7_IRQn 0 */
 delay--;
 if(delay == 0)
 {
 HAL_TIM_Base_Stop_IT(&htim7);
 }
 /* USER CODE END TIM7_IRQn 0 */
 HAL_TIM_IRQHandler(&htim7);
 /* USER CODE BEGIN TIM7_IRQn 1 */
 /* USER CODE END TIM7_IRQn 1 */
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

and some stuff of my main:

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_DMA_Init();
 MX_CRC_Init();
 MX_DMA2D_Init();
 MX_FMC_Init();
 MX_LTDC_Init();
 MX_SPI4_Init();
 MX_SPI5_Init();
 MX_TIM1_Init();
 MX_TIM2_Init();
 MX_USB_OTG_HS_HCD_Init();
 MX_TIM7_Init();
 /* USER CODE BEGIN 2 */

 DELAY_1_5us(1);
 DELAY_1_5us(10);
 DELAY_1_5us(100);
 DELAY_1_5us(1000);
 //LCD_sendCommand(0,0);
 LED_RED_OFF;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 /* USER CODE END WHILE */
 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

I honestly don't get it. Why does the first execution allways generates me a timer cycle of about 3,45µs no matter what ARR value I program on set up. And the following delays don not scale linear. as if the MCU changes execution time of each function call.