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

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> GCC: Аварийный выход из прерывания (функции), чем заменить оператор goto?
Lagman
сообщение May 19 2013, 18:26
Сообщение #16


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Цитата(MaxiMuz @ May 19 2013, 20:27) *
Точно! программа должна выполнить определенные действия и завершиться.

Если брать микроконтроллеры то там редко когда программа завершается, передавать управление некому, запуск только через включение питания (ресет).
Go to the top of the page
 
+Quote Post
Xenia
сообщение May 19 2013, 19:04
Сообщение #17


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(Lagman @ May 19 2013, 22:26) *
Если брать микроконтроллеры то там редко когда программа завершается, передавать управление некому, запуск только через включение питания (ресет).


Lagman подал хорошую идею. Разовью.
Ветвление надо произвести только один раз - в самом начале main(), еще до вхождения в бесконечный цикл.
Что вроде того:
Код
char semafor = false;
main()
{
   if( semafor)
   {
      // определенные экстренные действия
   }
   for(;;)
   {
       // бесконечный цикл
   }
}

В прерывании же при обнаружении экстренного случая взводится светофор (semafor = true) и программа запускается с нулевого адреса (setjmp 0).

P.S. Кажись с пронеслась я со своей идеей, т.к. при инициализации semafor тоже почистится. Впрочем, в качестве семафора можно взять какой-нибудь аппаратный регистр.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение May 19 2013, 20:02
Сообщение #18


Гуру
******

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



Цитата(MaxiMuz @ May 19 2013, 19:27) *
Точно! программа должна выполнить определенные действия и завершиться.

Если нужно завершить программу, то почему бы не сделать возврат из прерывания не в точку вызова, а туда где лежит фнкция завершающая программу?
Код
volatile unsigned char fatal_error;
void my_exit()
{
    cli();
    while (fatal_error) {
        PORTC^=1;
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
    }
    
}
ISR(SPM_RDY_vect)
{
    SPMCR&=~(1<<SPMIE);
    unsigned char error_detected=0;
    // какие-то дайствия
    //
    if (error_detected) {
        unsigned short sp = SP;
        unsigned short return_address=(unsigned short)my_exit;
        unsigned char *ptr=(unsigned char *)sp;
        fatal_error=1;
        ptr++;
        *ptr++=return_address>>8;
        *ptr++=return_address&255;
        asm("ret");
    }
}
Go to the top of the page
 
+Quote Post
Tiro
сообщение May 19 2013, 21:32
Сообщение #19


Знающий
****

Группа: Свой
Сообщений: 781
Регистрация: 3-10-04
Из: Санкт-Петербург
Пользователь №: 768



Цитата(MaxiMuz @ May 19 2013, 19:27) *
Помоему то что нужно!
Но всеже както странно , первый раз вижу оператор '&&' в таком применении. Это какаято особенность GCC стандарта ?

Да, это GNU расширение стандарта "С". В Вашем случае я бы использовал для восстановления микроконтроллера функцию с атрибутами static inline, а потом пересбросил бы микроконтроллер.
Go to the top of the page
 
+Quote Post
Xenia
сообщение May 19 2013, 23:31
Сообщение #20


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(_Артём_ @ May 20 2013, 00:02) *
Если нужно завершить программу, то почему бы не сделать возврат из прерывания не в точку вызова, а туда где лежит функция завершающая программу?


Тогда отчего бы не написать завершающую функцию прямо в прерывании? sm.gif
Go to the top of the page
 
+Quote Post
_Артём_
сообщение May 20 2013, 00:00
Сообщение #21


Гуру
******

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



Цитата(Xenia @ May 20 2013, 02:31) *
Тогда отчего бы не написать завершающую функцию прямо в прерывании? sm.gif

Можно и написать, но наверняка тогда прерыванию потребуется больше регистров для завершения(количество регистров зависит отсложности действий при завершении), которое выполнится один раз. То есть прерывание всегда будет сохранять-востанавливать много регистров.
А если сделать по-моему варианту, то может быть прерыванию регистров меньше понадобится(но вариант с jmp лучше чем ret). Но работа программы завершится и возобновлена может быть только после сброса.
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 20 2013, 04:53
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Xenia @ May 19 2013, 23:04) *
В прерывании же при обнаружении экстренного случая взводится светофор (semafor = true) и программа запускается с нулевого адреса

Если достаточно "мягкого" рестарта, то семафор заменяет пара функций setjmp / longjmp.
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение May 20 2013, 12:40
Сообщение #23


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(_Артём_ @ May 19 2013, 23:02) *
Если нужно завершить программу, то почему бы не сделать возврат из прерывания не в точку вызова, а туда где лежит фнкция завершающая программу?

Вообщето я так и хочу сделать, только не в функцию , а в участок main
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 20 2013, 13:21
Сообщение #24


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (MaxiMuz @ May 20 2013, 15:40) *
а в участок main
А вы уверены, что этот участок адекватно отреагирует на мусор в стеке?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
_Артём_
сообщение May 20 2013, 13:31
Сообщение #25


Гуру
******

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



Цитата(MaxiMuz @ May 20 2013, 15:40) *
только не в функцию , а в участок main

Мне почему-то кажется что код идущий после метки будет выкинут оптимизатором. Или нет?
Вы с какими настройками компилируете?
Go to the top of the page
 
+Quote Post
Xenia
сообщение May 20 2013, 13:44
Сообщение #26


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(Сергей Борщ @ May 20 2013, 17:21) *
А вы уверены, что этот участок адекватно отреагирует на мусор в стеке?


Если это лебединая песнь, то легко можно установить стек(и) на начало перед прыжком.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 20 2013, 17:03
Сообщение #27


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Xenia @ May 20 2013, 16:44) *
легко можно установить стек(и) на начало перед прыжком.
установить-то можно. Вот только main() может выделить на стеке место под переменные лебединой песни и даже, возможно, разместить там заранее какие-то значения. И при установке указателя стека на начало получим обращение к несуществующей памяти, а при переходе с кучей хлама на стеке будем обрабатывать мусор. Поэтому все и пишут, что решение ущербное по условию..


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ARV
сообщение May 20 2013, 17:12
Сообщение #28


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

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



если очень хочется, то можно вот так:
Код
void  __attribute__((noreturn)) my_exit(void){
    PORTB = 0xFF;
    while(1);
}

ISR(TIMER1_OVF_vect){
    if(PINB & 1){
        PORTB = 0;
    } else {
        // проблема - обрабатываем лебединую песню!!!
        void *ptr = my_exit;
        goto *ptr;
    }
}
при желании my_exit() можно вызывать и в main, не нарушая общей структуры программы. хотя с моей точки зрения это кривой костыль, правильное по моему мнению решение я озвучивал ранее.


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
Xenia
сообщение May 20 2013, 18:41
Сообщение #29


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(Сергей Борщ @ May 20 2013, 21:03) *
установить-то можно. Вот только main() может выделить на стеке место под переменные лебединой песни и даже, возможно, разместить там заранее какие-то значения. И при установке указателя стека на начало получим обращение к несуществующей памяти, а при переходе с кучей хлама на стеке будем обрабатывать мусор. Поэтому все и пишут, что решение ущербное по условию..


Нормальные люди в main() локальных переменных не заводят! sm.gif Что проку от их локальности, если main() никогда не завершается? Переменные, используемые в main(), лучше объявлять глобальными - результат тот же самый, зато стек не расходуется впустую. А если не хотите, чтобы эти переменные из других модулей были видны, то объявите их static.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение May 20 2013, 19:03
Сообщение #30


Гуру
******

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



Цитата(Xenia @ May 20 2013, 21:41) *
Нормальные люди в main() локальных переменных не заводят! sm.gif

Смишно.

Цитата(Xenia @ May 20 2013, 21:41) *
Переменные, используемые в main(), лучше объявлять глобальными - результат тот же самый, зато стек не расходуется впустую.

Нет результат не тот же самый - расходуется память под глобальные переменные, причём не меньше. В случае использования локальных переменных компилятор может использовать одни и те же адреса в ОЗУ для разных переменных, а для глобальных так не получится.

Цитата(Xenia @ May 20 2013, 21:41) *
А если не хотите, чтобы эти переменные из других модулей были видны, то объявите их static.

Зачем? Лучше их сделать локальными, тогда точно не будут видны.

Цитата(ARV @ May 20 2013, 20:12) *
ISR(TIMER1_OVF_vect){
if(PINB & 1){
PORTB = 0;
} else {
// проблема - обрабатываем лебединую песню!!!
void *ptr = my_exit;
goto *ptr;
}
}[/code]

goto заменилось на JMP my_exit без ненужного сохранения регистров. Надо же...
Go to the top of the page
 
+Quote Post

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

 


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


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