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

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

|
Возникла ситуация когда при обработке прерывания нужно изменить привычный ход программы, когда содержимое сохранненых регистров и указатель стека уже не важны. Оператор goto тут не работает: Код ISR (xxx_vect) { ... ... goto m1; } void main (void) { ... ... while (1) { ... ... } m1: ... ... } Что можно здесь сделать ?
|
|
|
|
|
 |
Ответов
|
May 16 2013, 18:20
|

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

|
Цитата(Lagman @ May 16 2013, 18:45)  Просто из прерывания вызываете другую функцию, зачем вам в main возвращаться, если вам не важны стэк и регистры. не могу перегружать память сохраняемыми регистрами в теме была описана ситуевина: http://electronix.ru/forum/index.php?showtopic=112377Цитата(zombi @ May 16 2013, 19:09)  Не знаю как на СИ. А на асме записываю в стек нужный мне адрес и ret на Асме я бы просто rjmp написал Цитата(Палыч @ May 16 2013, 19:40)  Функции setjmp / longjmp подойдут ? похоже нет Цитата(Палыч @ May 16 2013, 19:40)  Функции setjmp / longjmp подойдут ? похоже нет Цитата(Xenia @ May 16 2013, 20:51)  Проще всего в программе установить семафоры с ветвлением по if или switch, а из прерывания эти семафоры переключать. я так и поступил , но всеже хочется разобраться с "прыжками"
|
|
|
|
|
May 16 2013, 18:28
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(MaxiMuz @ May 16 2013, 21:20)  не могу перегружать память сохраняемыми регистрами в теме была описана ситуевина: http://electronix.ru/forum/index.php?showtopic=112377А регистры сохраняются? Вы смотрели? Цитата(MaxiMuz @ May 16 2013, 21:20)  на Асме я бы просто rjmp написал Так и напишите Код ISR(...) { asm("rjmp 0x1234"); // нужный адрес выберете сами } По выбранному адресу расположите вашу функцию (Си или асм) Цитата(MaxiMuz @ May 16 2013, 21:20)  я так и поступил , но всеже хочется разобраться с "прыжками" Изврат это какой-то, чего с ними разбираться.
|
|
|
|
|
May 19 2013, 16:27
|

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

|
Цитата(Tiro @ May 18 2013, 00:26)  Метки как значения давно есть в ГСС. 4.3 Labels as Values Помоему то что нужно! Но всеже както странно , первый раз вижу оператор '&&' в таком применении. Это какаято особенность GCC стандарта ? Цитата(Xenia @ May 19 2013, 03:12)  А прыгать нельзя!  Мало ли в каком состоянии стеки находятся в том месте, откуда сигануло в прерывание? Вы, положим по метке перейдете, а стек кто чистить будет? Xenia такой сценарий  Если уж выполненно определенное условие , то стек и состояние др.регистров неважно Цитата(ARV @ May 19 2013, 09:49)  с моей точки зрения ситуация, когда "регистры и состояние стека уже не важны" должна приводить к аппаратному сбросу контроллера, и никак иначе, тем более из прерывания. Точно! программа должна выполнить определенные действия и завершиться.
Сообщение отредактировал MaxiMuz - May 19 2013, 16:27
|
|
|
|
|
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 без ненужного сохранения регистров. Надо же...
|
|
|
|
|
May 20 2013, 19:05
|

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

|
Цитата(_Артём_ @ May 20 2013, 22:56)  В случае использования локальных переменных компилятор может использовать одни и те же адреса в ОЗУ для разных переменных, а для глобальных так не получится. Это только в том случае, если они освобождаются вместе с окончанием той функции/блока, в котором были заведены. Но main() свои локальные переменные (те, что заводятся в ее начале) не освободит никогда - на то у нее и бесконечный цикл внутри сидит. В данном случае разговор зашел о том, что инциализация/сброс стека приведет к пропаже локальных переменных внутри main(). Так я и выразилась в том духе, что заводить внутри main() локальные переменные смысла не имеет. Т.е. речь шла не об экономии памяти, как вы это неверно поняли, а об устойчивости переменных к сбросу стека. P.S. Не стоит обольщаться тем, что войдя джампом из прерывания во внутрь какой-то функции (в том числе и main), вы обнаружите там локальные переменные на тех же местах. Адреса локальных переменных отмеряются относительно текущего указателя стека, который при запрыгивании со стороны никак не может быть правильным (т.к. функция прерывания тоже пользуется стеком). Поэтому как ни крути, но валидными в этом случае могут быть только глобальные переменные, но не локальные. Причем независимо от того, сбрасывали вы стек или нет.
|
|
|
|
|
May 20 2013, 22:31
|
Знающий
   
Группа: Свой
Сообщений: 781
Регистрация: 3-10-04
Из: Санкт-Петербург
Пользователь №: 768

|
Цитата(Xenia @ May 20 2013, 22:05)  Адреса локальных переменных отмеряются относительно текущего указателя стека, который при запрыгивании со стороны никак не может быть правильным (т.к. функция прерывания тоже пользуется стеком). Поэтому как ни крути, но валидными в этом случае могут быть только глобальные переменные, но не локальные. Причем независимо от того, сбрасывали вы стек или нет. Тут поддержу Ксению, но какое это имеет отношение к вопросу топикстартера? Он же сказал, что состояние программы и стека ему не известно и не важно. Возможно, стек переполнился и залез на глобальные переменные. Надежнее не использовать вообще никакие заранее определенные переменные. Используйте константы или заведите новые переменные, порушив глобальные, переставьте указатель стека на начало и вперед! Только вперед и только хардкор
|
|
|
|
Сообщений в этой теме
MaxiMuz GCC: Аварийный выход из прерывания (функции) May 16 2013, 14:50      Lagman Цитата(MaxiMuz @ May 19 2013, 20:27) Точн... May 19 2013, 18:26       Xenia Цитата(Lagman @ May 19 2013, 22:26) Если ... May 19 2013, 19:04        Палыч Цитата(Xenia @ May 19 2013, 23:04) В прер... May 20 2013, 04:53       Xenia Цитата(_Артём_ @ May 20 2013, 00:02) Если... May 19 2013, 23:31        _Артём_ Цитата(Xenia @ May 20 2013, 02:31) Тогда ... May 20 2013, 00:00             ARV Цитата(_Артём_ @ May 20 2013, 23:03) goto... May 21 2013, 18:08              _Артём_ Цитата(ARV @ May 21 2013, 21:08) так ведь... May 21 2013, 19:20        _Артём_ Цитата(MaxiMuz @ May 20 2013, 15:40) толь... May 20 2013, 13:31         MaxiMuz Цитата(_Артём_ @ May 20 2013, 16:31) Мне ... May 21 2013, 20:17          _Артём_ Цитата(MaxiMuz @ May 21 2013, 23:17) возм... May 21 2013, 20:54           MaxiMuz Цитата(_Артём_ @ May 21 2013, 23:54) О ка... May 21 2013, 21:01            demiurg_spb Всё это (аварийный выход) стоит завернуть в какой-... May 22 2013, 06:52             Палыч Цитата(demiurg_spb @ May 22 2013, 10:52) ... May 22 2013, 07:01              demiurg_spb Цитата(Палыч @ May 22 2013, 11:01) В AVR ... May 22 2013, 07:05      Tiro Цитата(MaxiMuz @ May 19 2013, 19:27) Помо... May 19 2013, 21:32    _Артём_ Цитата(MaxiMuz @ May 17 2013, 14:10) почт... May 18 2013, 22:42  zombi Цитата(MaxiMuz @ May 16 2013, 21:20) на А... May 16 2013, 19:03  Палыч Цитата(MaxiMuz @ May 16 2013, 22:20) похо... May 16 2013, 19:40  Xenia Цитата(MaxiMuz @ May 16 2013, 22:20) я та... May 19 2013, 00:12 zombi Не знаю как на СИ.
А на асме записываю в стек нужн... May 16 2013, 16:09 Палыч Функции setjmp / longjmp подойдут ? May 16 2013, 16:40 Xenia Проще всего в программе установить семафоры с ветв... May 16 2013, 17:51 ARV Цитата(MaxiMuz @ May 16 2013, 18:50) Возн... May 19 2013, 06:49 ARV если очень хочется, то можно вот так:Кодvoid __at... May 20 2013, 17:12 Сергей Борщ _Артем_ ответил по всем пунктам.
Касаемо последних... May 21 2013, 07:45 Палыч Совершенно непонятно: почему ТС не хочет использов... May 21 2013, 08:00  _Артём_ Цитата(Палыч @ May 21 2013, 11:00) Соверш... May 21 2013, 12:51 rudy_b Что-то непонятно. Что значит "программа должн... May 21 2013, 19:32 _Артём_ Цитата(rudy_b @ May 21 2013, 22:32) И что... May 21 2013, 19:47  rudy_b Цитата(_Артём_ @ May 21 2013, 22:47) Пере... May 22 2013, 08:28   MaxiMuz Цитата(rudy_b @ May 22 2013, 11:28) А что... May 25 2013, 06:49 _Pasha Пора голосовать, хто за setjmp/longjmp ? May 25 2013, 10:16
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|