Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблема компиляции обработчика прерывания. (STM+GCC)
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Real_Bastard
Контроллер STM32L151 компилятор GCC (Sourcery G++).
Есть обработчик прерывания по таймеру.
CODE
// Обработчик прерывания TIM6_DAC
void TIM6_IRQHandler(void){
if (k==0){
k=1;
GPIO_SetBit(GPIOA,1);
} else {
GPIO_ResetBit(GPIOA,1);
k=0;
}
TIM6->SR &= ~TIM_SR_UIF; //Сбрасываем флаг UIF
}
Все отлично работает.
А вот если сброс флага вынести в отдельную функцию-начинаются проблемы.
CODE
// Обработчик прерывания TIM6_DAC
void clear_flag(void){
TIM6->SR &= ~TIM_SR_UIF; //Сбрасываем флаг UIF
}
void TIM6_IRQHandler(void){
if (k==0){
k=1;
GPIO_SetBit(GPIOA,1);
} else {
GPIO_ResetBit(GPIOA,1);
k=0;
}
clear_flag();
}

Флаг сбрасывается через раз. Естественно, зависит от оптимизации (при отключенной все хорошо).
тут у народа были похожие проблемы...
Прошу совета....
KRS
Попробуйте поставить очистку флага в начало обработчика прерывания.
_Артём_
Барьер ставить не пробовали?
Код
void RTC_Handler()
{
    /* Clear interrupt source */
    RTC_IntClear(RTC_IFC_COMP0);
    /* Flushing instructions to make sure that the interrupt is not re-triggered*/
    /* This may be required when the peripheral clock is slower than the core */
    __DSB();

}


PS. Ссылка не рабочая.
Real_Bastard
Цитата(_Артём_ @ Nov 28 2012, 15:16) *
PS. Ссылка не рабочая.

http://electronix.ru/forum/lofiversion/index.php/t84789.html . "...Код ниже. Т.е. если очищать флаг запроса на прерывание перед самым выходом из него, то попадаем в прерывание второй раз. Не могу понять причин такого поведения...."

Цитата(KRS @ Nov 28 2012, 15:15) *
Попробуйте поставить очистку флага в начало обработчика прерывания.

Объехать на кривой козе я могу....мне бы понять логику компилятора.

KRS
Цитата(Real_Bastard @ Nov 28 2012, 16:04) *
Т.е. если очищать флаг запроса на прерывание перед самым выходом из него, то попадаем в прерывание второй раз. Не могу понять причин такого поведения...."

ЕМНИП как раз по таймерам для Cortex и была рекомендация как можно раньше сбрасывать флаг до выхода из прерывания.
Достаточно просто разместить код в начале обработчика

Цитата(Real_Bastard @ Nov 28 2012, 16:15) *
Объехать на кривой козе я могу....мне бы понять логику компилятора.

Компилятор тут не причем!
Линия прерывания не успевает сброситься! Проц работает быстрее чем периферия
Real_Bastard
Цитата(_Артём_ @ Nov 28 2012, 15:16) *
Барьер ставить не пробовали?

Помогает, и добавление любой значимой строчки после вызова функции помогает.



Цитата(KRS @ Nov 28 2012, 16:17) *
Компилятор тут не причем!

Ок. Тогда где POP(R4)?
CODE
08001990 <clear_flag>:
/*void PPP_IRQHandler(void)
{
}*/
// Обработчик прерывания TIM6_DAC
void clear_flag(void){
TIM6->SR &= ~TIM_SR_UIF; //Сбрасываем флаг UIF
8001990: 4a03 ldr r2, [pc, #12] ; (80019a0 <clear_flag+0x10>)
8001992: 8a13 ldrh r3, [r2, #16]
8001994: f023 0301 bic.w r3, r3, #1
8001998: 041b lsls r3, r3, #16
800199a: 0c1b lsrs r3, r3, #16
800199c: 8213 strh r3, [r2, #16]
}
800199e: 4770 bx lr
80019a0: 40001000 .word 0x40001000

080019a4 <TIM6_IRQHandler>:

void TIM6_IRQHandler(void){
80019a4: b510 push {r4, lr}
if (k==0){
80019a6: 4c09 ldr r4, [pc, #36] ; (80019cc <TIM6_IRQHandler+0x28>)
80019a8: 6823 ldr r3, [r4, #0]
80019aa: b92b cbnz r3, 80019b8 <TIM6_IRQHandler+0x14>
k=1;
80019ac: 2101 movs r1, #1
GPIO_SetBits(GPIOA,1);
80019ae: 4808 ldr r0, [pc, #32] ; (80019d0 <TIM6_IRQHandler+0x2c>)
TIM6->SR &= ~TIM_SR_UIF; //Сбрасываем флаг UIF
}

void TIM6_IRQHandler(void){
if (k==0){
k=1;
80019b0: 6021 str r1, [r4, #0]
GPIO_SetBits(GPIOA,1);
80019b2: f000 f95a bl 8001c6a <GPIO_SetBits>
80019b6: e005 b.n 80019c4 <TIM6_IRQHandler+0x20>
} else {
GPIO_ResetBits(GPIOA,1);
80019b8: 4805 ldr r0, [pc, #20] ; (80019d0 <TIM6_IRQHandler+0x2c>)
80019ba: 2101 movs r1, #1
80019bc: f000 f957 bl 8001c6e <GPIO_ResetBits>
k=0;
80019c0: 2300 movs r3, #0
80019c2: 6023 str r3, [r4, #0]
}
clear_flag();
}
80019c4: e8bd 4010 ldmia.w sp!, {r4, lr}
GPIO_SetBits(GPIOA,1);
} else {
GPIO_ResetBits(GPIOA,1);
k=0;
}
clear_flag();
80019c8: e7e2 b.n 8001990 <clear_flag>
80019ca: bf00 nop
80019cc: 20000124 .word 0x20000124
80019d0: 40010800 .word 0x40010800

080019d4 <EXTI_DeInit>:
RabidRabbit
Цитата(Real_Bastard @ Nov 28 2012, 16:37) *
Ок. Тогда где POP(R4)?

По-моему это:
80019c4: e8bd 4010 ldmia.w sp!, {r4, lr}
Real_Bastard
Цитата(RabidRabbit @ Nov 28 2012, 17:02) *
По-моему это:
80019c4: e8bd 4010 ldmia.w sp!, {r4, lr}

Спасибо!!!!
sla000
Цитата(Real_Bastard @ Nov 28 2012, 18:07) *
CODE
// Обработчик прерывания TIM6_DAC
void clear_flag(void){
TIM6->SR &= ~TIM_SR_UIF; //Сбрасываем флаг UIF
}


Если перед void clear_flag(void){ поставить static, то скорее всего компилятор заинлайнит функцию (зависит от выбранной оптимизации), и второй вариант даст такой же код как и первый.
Real_Bastard
ВСЕМ БОЛЬШОЕ СПАСИБО!!! Вроде теперь разобрался.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.