cancel
Showing results for 
Search instead for 
Did you mean: 

Troubles with priorities

miguel2
Associate II
Posted on March 09, 2016 at 17:25

Hi there, can anyone help me with this??

Im working with STM32f407.

The programm consists in switch on/off lights and change its intensity using dimmer.

A 50Hz wave is connected to a zero cross detector, and its output connected to a GPIO IN, used as EXTI Line interrupt. So each 10ms is executing the task into that EXTI_Handler.

This is how I configure the interrupt:

void Configure_ZCInterrupt() {

GPIO_InitTypeDef GPIO_InitStruct;

/* Enable clock for GPIO */

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;

GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;

GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;

GPIO_Init(GPIOD, &GPIO_InitStruct);

EXTI_InitTypeDef EXTI_InitStruct;

// Enable clock for SYSCFG

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource8);

EXTI_InitStruct.EXTI_Line = EXTI_Line8;

EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;

EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;

EXTI_InitStruct.EXTI_LineCmd = ENABLE;

EXTI_Init(&EXTI_InitStruct);

NVIC_InitTypeDef NVIC_InitStruct;

// Add IRQ vector to NVIC

NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;

NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;

NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;

NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE;

NVIC_Init(&NVIC_InitStruct);

}

And this is the handler:

void EXTI9_5_IRQHandler() {

if (EXTI_GetITStatus(EXTI_Line8) != RESET) {

uint8_t num = 0;

if (screen.LIGHTS[0].status == ACTIVE) {

num = 1;

Delay_ms(1 + screen.LIGHTS[0].dimmer * 1);

Set_Light(&screen, &num);

Delay_ms(1);

Reset_Light(&screen, &num);

}

EXTI_ClearITPendingBit(EXTI_Line8);

}

In other hand, I have a timer running and if a screen is not touched for 40seconds, an update interrupt of that timer will be dispatched.

This is the timer config:

void Init_EnergySaveTimmer(void) {

TIM_TimeBaseInitTypeDef timerInitStructure;

// TIM1 Configuration

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

timerInitStructure.TIM_Prescaler = 0xffff; //timer_tick_frequency = 168000000 / 65536 = 2563.51 Hz --> 0.39 ms

timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;

timerInitStructure.TIM_Period = 0xFFFF; // Se desbordará cada 60000 x 0.39 = 23.4 s

TIM_TimeBaseInit(TIM1, &timerInitStructure);

TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);

TIM_Cmd(TIM1, ENABLE);

NVIC_InitTypeDef NVIC_InitStructure;

// Enable the TIM1 Interrupt

NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

and it is its update handler:

void TIM1_UP_TIM10_IRQHandler() {

if (TIM_GetITStatus(TIM1, TIM_IT_Update) == SET) {

if (idleState == 0) {

LCD_Clear(Black, 1);

Chk_Busy();

print_BTERecic();

Wait_ms(1200);

TM_RTC_Interrupts(TM_RTC_Int_60s);

LCD_Clear(Black, 1);

Chk_Busy();

Display_OFF();

Wait_ms(10);

BackLight_DeInit();

Wait_ms(100);

idleState = 1;

}

TIM_ClearITPendingBit(TIM1, TIM_IT_Update);

}

}

The difference between delay_ms() and wait_ms() is as follows:

Delay config and handler:

void TimerDelay_Init(void) {

TIM_TimeBaseInitTypeDef Timer_InitStructure;

NVIC_InitTypeDef NVIC_InitStruct;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);

Timer_InitStructure.TIM_Prescaler = 83; // 1 us

Timer_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;

Timer_InitStructure.TIM_Period = 999;

Timer_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;

Timer_InitStructure.TIM_RepetitionCounter = 0;

/* Initialize TIM5 */

TIM_TimeBaseInit(TIMERDELAY, &Timer_InitStructure);

/* Enable interrupt each 1ms */

//TIM_ITConfig(TIMERDELAY, TIM_IT_Update, ENABLE);

/* Set NVIC parameters */

NVIC_InitStruct.NVIC_IRQChannel = TIM5_IRQn;

NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;

NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;

/* Add Timer to NVIC */

NVIC_Init(&NVIC_InitStruct);

/*Start Timer */

TIM_Cmd(TIM5, ENABLE);

}

void Delay_ms(uint32_t ms) {

volatile uint32_t timer = TIM_GetCounter(TIM5);

uint32_t milis = ms * 1000;

do {

/* Count timer ticks */

while ((TIM5->CNT - timer) == 0)

;

/* Increase timer */

timer = TIM5->CNT;

/* Decrease microseconds */

} while (--milis);

}

void TIM5_IRQHandler(void) {

TIM_ClearITPendingBit(TIM5, TIM_IT_Update);

uint8_t i;

Time1++;

if (Time2 != 0x00) {

Time2--;

}

/* Call user function */

MILI_Handler();

}

Wait config and handler:

void TimerWait_Init(void) {

TIM_TimeBaseInitTypeDef timerInitStructure;

// TIM3 Configuration

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

timerInitStructure.TIM_Prescaler = 8399; //timer_tick_frequency = 84000000 / (8399+1) = 10 KHz --> 100 us

timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;

timerInitStructure.TIM_Period = 0xffff;

timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;

timerInitStructure.TIM_RepetitionCounter = 0;

TIM_TimeBaseInit(TIM3, &timerInitStructure);

TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);

TIM_Cmd(TIM3, ENABLE);

}

 void Wait_ms(uint32_t ms) {

TIM_Cmd(TIM3, ENABLE);

TIM_SetCounter(TIM3, 0);

uint32_t *contador;

uint32_t milis = ms * 10;

contador = &TIM3->CNT;

while (TIM3->CNT < milis) {

}

}

Due to the priorities, EXTI_9_5_Handler, should be executing each 10ms, but its not working like that.

When TIM1 (EnergySaveTimer) updates, EXTI_9_5_Handler, is not executing while wait_ms() is executing, but i dont understand why, becouseseach 10ms, should be called, but it is not. Can anyone tell me whats wrong here??

Thanks in advance

5 REPLIES 5
Posted on March 09, 2016 at 18:23

I would not put large delays in IRQHandlers, or build code that is dependent on IRQ driven software counters, there is NO reason to do that.

Use TIM2 as a 32-bit maximal count, clock it at 1 MHz, so each tick is 1us, and then just delta the timer in a loop.

uint32_t start = TIM2->CNT;

while((TIM2->CNT - start) < microsecdelay);

This would be agnostic to wrapping, and be good >71 minutes

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
miguel2
Associate II
Posted on March 10, 2016 at 16:37

Hi Clive,

 

 

Thanks for answering.

 

 

I`ve changed my code. Now I`m using TIM2 as you said:

void init_Tim2() {

TIM_TimeBaseInitTypeDef timerInitStructure2;

// TIM2 Configuration

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

timerInitStructure2.TIM_Prescaler = 83; //timer_tick_frequency = 84000000 / 83+1 = 1 MHz --> 1 us

timerInitStructure2.TIM_CounterMode = TIM_CounterMode_Up;

timerInitStructure2.TIM_Period = 0xfffffffff;

TIM_TimeBaseInit(TIM2, &timerInitStructure2);

TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);

TIM_Cmd(TIM2, ENABLE);

}

void TIM1_UP_TIM10_IRQHandler() {

if (TIM_GetITStatus(TIM1, TIM_IT_Update) == SET) {

if (idleState == 0) {

LCD_Clear(Black, 1);

Chk_Busy();

print_BTERecic();

uint32_t start = TIM2->CNT;

while ((TIM2->CNT - start) < 1200000);

LCD_Clear(Black, 1);

Chk_Busy();

Display_OFF();

BackLight_DeInit();

idleState = 1;

}

}

 TIM_ClearITPendingBit(TIM1, TIM_IT_Update);

}

}

void EXTI9_5_IRQHandler() {

if (EXTI_GetITStatus(EXTI_Line8) != RESET) {

uint8_t num = 0;

uint32_t dimerTime = 0;

uint32_t start = 0;

if (screen.LIGHTS[0].status == ACTIVE) {

num = 1;

dimerTime = (1000 + screen.LIGHTS[0].dimmer * 1000);

start = TIM2->CNT;

while (TIM2->CNT - start < dimerTime)

;

Set_Light(&screen, &num);

start = TIM2->CNT;

while (TIM2->CNT - start < 1000)

;

Reset_Light(&screen, &num);

     }

}

The problem still continues, when TIM_UPDATE_Handler is executing with Priority:

 

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;

and interrupt on EXTI_LINE8 arrives with priority:

NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;

It should expropiate the cpu and start executing EXTI_Handler insteaad of continuing on TIM1_UPDATE_Handler.

Do you see where is the problem??

Thanks

Posted on March 10, 2016 at 17:12

Do you define the NVIC Priority Grouping setting to actually permit pre-emption?

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABHGEAJ.html

You really need to evaluate why this kind of delay is required in an IRQ Handler

uint32_t start = TIM2->CNT;

while ((TIM2->CNT - start) < 1200000);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
miguel2
Associate II
Posted on March 11, 2016 at 12:39

miguel2
Associate II
Posted on March 11, 2016 at 16:06

Hi There,

Is there a way to Stop, reset counter, and restart a timer??

When timer is already configured, I`m using:

 TIM_Cmd(TIMx,DISABLE); to stop the counter.

TIM:Setcounter(TIMx,0); to reset the counter.

TIM_Cmd(TIMx,ENABLE); to restart the counter.

But it is not working. It seems like the counter is running allways since the timer is configured.

Thanks,