реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Проблема компиляции обработчика прерывания. (STM+GCC)
Real_Bastard
сообщение Nov 28 2012, 11:07
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 7-11-06
Из: Санкт-Петербург
Пользователь №: 22 041



Контроллер 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();
}

Флаг сбрасывается через раз. Естественно, зависит от оптимизации (при отключенной все хорошо).
тут у народа были похожие проблемы...
Прошу совета....

Сообщение отредактировал Real_Bastard - Nov 28 2012, 12:07
Go to the top of the page
 
+Quote Post
KRS
сообщение Nov 28 2012, 11:15
Сообщение #2


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Попробуйте поставить очистку флага в начало обработчика прерывания.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Nov 28 2012, 11:16
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Барьер ставить не пробовали?
Код
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. Ссылка не рабочая.
Go to the top of the page
 
+Quote Post
Real_Bastard
сообщение Nov 28 2012, 12:15
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 7-11-06
Из: Санкт-Петербург
Пользователь №: 22 041



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

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

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

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



Сообщение отредактировал Real_Bastard - Nov 28 2012, 12:10
Go to the top of the page
 
+Quote Post
KRS
сообщение Nov 28 2012, 12:17
Сообщение #5


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



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

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

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

Компилятор тут не причем!
Линия прерывания не успевает сброситься! Проц работает быстрее чем периферия
Go to the top of the page
 
+Quote Post
Real_Bastard
сообщение Nov 28 2012, 12:37
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 7-11-06
Из: Санкт-Петербург
Пользователь №: 22 041



Цитата(_Артём_ @ 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>:
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение Nov 28 2012, 13:02
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



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

По-моему это:
80019c4: e8bd 4010 ldmia.w sp!, {r4, lr}
Go to the top of the page
 
+Quote Post
Real_Bastard
сообщение Nov 28 2012, 16:30
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 7-11-06
Из: Санкт-Петербург
Пользователь №: 22 041



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

Спасибо!!!!
Go to the top of the page
 
+Quote Post
sla000
сообщение Nov 29 2012, 05:11
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 25-06-07
Из: Томск
Пользователь №: 28 670



Цитата(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, то скорее всего компилятор заинлайнит функцию (зависит от выбранной оптимизации), и второй вариант даст такой же код как и первый.
Go to the top of the page
 
+Quote Post
Real_Bastard
сообщение Nov 29 2012, 12:10
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 7-11-06
Из: Санкт-Петербург
Пользователь №: 22 041



ВСЕМ БОЛЬШОЕ СПАСИБО!!! Вроде теперь разобрался.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 17:58
Рейтинг@Mail.ru


Страница сгенерированна за 0.01531 секунд с 7
ELECTRONIX ©2004-2016