|
|
  |
GCC: Аварийный выход из прерывания (функции), чем заменить оператор goto? |
|
|
|
May 19 2013, 19:04
|

Гуру
     
Группа: Модератор 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 тоже почистится. Впрочем, в качестве семафора можно взять какой-нибудь аппаратный регистр.
|
|
|
|
|
May 20 2013, 17:12
|

Профессионал
    
Группа: Свой
Сообщений: 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, не нарушая общей структуры программы. хотя с моей точки зрения это кривой костыль, правильное по моему мнению решение я озвучивал ранее.
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
May 20 2013, 18:41
|

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

|
Цитата(Сергей Борщ @ May 20 2013, 21:03)  установить-то можно. Вот только main() может выделить на стеке место под переменные лебединой песни и даже, возможно, разместить там заранее какие-то значения. И при установке указателя стека на начало получим обращение к несуществующей памяти, а при переходе с кучей хлама на стеке будем обрабатывать мусор. Поэтому все и пишут, что решение ущербное по условию.. Нормальные люди в main() локальных переменных не заводят!  Что проку от их локальности, если main() никогда не завершается? Переменные, используемые в main(), лучше объявлять глобальными - результат тот же самый, зато стек не расходуется впустую. А если не хотите, чтобы эти переменные из других модулей были видны, то объявите их static.
|
|
|
|
|
May 20 2013, 19:03
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(Xenia @ May 20 2013, 21:41)  Нормальные люди в main() локальных переменных не заводят!  Смишно. Цитата(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 без ненужного сохранения регистров. Надо же...
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|