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

 
 
> GCC: Аварийный выход из прерывания (функции), чем заменить оператор goto?
MaxiMuz
сообщение May 16 2013, 14:50
Сообщение #1


Местный
***

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



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

Что можно здесь сделать ?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Lagman
сообщение May 16 2013, 15:45
Сообщение #2


Знающий
****

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



Просто из прерывания вызываете другую функцию, зачем вам в main возвращаться, если вам не важны стэк и регистры.
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение May 16 2013, 18:20
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 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, а из прерывания эти семафоры переключать.
я так и поступил , но всеже хочется разобраться с "прыжками"
Go to the top of the page
 
+Quote Post
_Артём_
сообщение May 16 2013, 18:28
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 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) *
я так и поступил , но всеже хочется разобраться с "прыжками"

Изврат это какой-то, чего с ними разбираться.
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение May 17 2013, 11:10
Сообщение #5


Местный
***

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



Цитата(_Артём_ @ May 16 2013, 21:28) *
А регистры сохраняются? Вы смотрели?
почти все старшие регистры, независимо используются они или нет
Go to the top of the page
 
+Quote Post
Tiro
сообщение May 17 2013, 21:26
Сообщение #6


Знающий
****

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



Цитата(MaxiMuz @ May 17 2013, 14:10) *
почти все старшие регистры, независимо используются они или нет

Метки как значения давно есть в ГСС. 4.3 Labels as Values
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение May 19 2013, 16:27
Сообщение #7


Местный
***

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



Цитата(Tiro @ May 18 2013, 00:26) *
Метки как значения давно есть в ГСС. 4.3 Labels as Values

Помоему то что нужно!
Но всеже както странно , первый раз вижу оператор '&&' в таком применении. Это какаято особенность GCC стандарта ?

Цитата(Xenia @ May 19 2013, 03:12) *
А прыгать нельзя! sm.gif Мало ли в каком состоянии стеки находятся в том месте, откуда сигануло в прерывание? Вы, положим по метке перейдете, а стек кто чистить будет?

Xenia такой сценарий sm.gif Если уж выполненно определенное условие , то стек и состояние др.регистров неважно

Цитата(ARV @ May 19 2013, 09:49) *
с моей точки зрения ситуация, когда "регистры и состояние стека уже не важны" должна приводить к аппаратному сбросу контроллера, и никак иначе, тем более из прерывания.
Точно! программа должна выполнить определенные действия и завершиться.

Сообщение отредактировал MaxiMuz - May 19 2013, 16:27
Go to the top of the page
 
+Quote Post
_Артём_
сообщение May 19 2013, 20:02
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 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
MaxiMuz
сообщение May 20 2013, 12:40
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 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
Сообщение #10


Гуру
******

Группа: Модераторы
Сообщений: 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
Xenia
сообщение May 20 2013, 13:44
Сообщение #11


Гуру
******

Группа: Модератор 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
Сообщение #12


Гуру
******

Группа: Модераторы
Сообщений: 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
Xenia
сообщение May 20 2013, 18:41
Сообщение #13


Гуру
******

Группа: Модератор 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
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 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
Xenia
сообщение May 20 2013, 19:05
Сообщение #15


Гуру
******

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



Цитата(_Артём_ @ May 20 2013, 22:56) *
В случае использования локальных переменных компилятор может использовать одни и те же адреса в ОЗУ для разных переменных, а для глобальных так не получится.


Это только в том случае, если они освобождаются вместе с окончанием той функции/блока, в котором были заведены. Но main() свои локальные переменные (те, что заводятся в ее начале) не освободит никогда - на то у нее и бесконечный цикл внутри сидит.

В данном случае разговор зашел о том, что инциализация/сброс стека приведет к пропаже локальных переменных внутри main(). Так я и выразилась в том духе, что заводить внутри main() локальные переменные смысла не имеет. Т.е. речь шла не об экономии памяти, как вы это неверно поняли, а об устойчивости переменных к сбросу стека.

P.S. Не стоит обольщаться тем, что войдя джампом из прерывания во внутрь какой-то функции (в том числе и main), вы обнаружите там локальные переменные на тех же местах. Адреса локальных переменных отмеряются относительно текущего указателя стека, который при запрыгивании со стороны никак не может быть правильным (т.к. функция прерывания тоже пользуется стеком). Поэтому как ни крути, но валидными в этом случае могут быть только глобальные переменные, но не локальные. Причем независимо от того, сбрасывали вы стек или нет.
Go to the top of the page
 
+Quote Post
Tiro
сообщение May 20 2013, 22:31
Сообщение #16


Знающий
****

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



Цитата(Xenia @ May 20 2013, 22:05) *
Адреса локальных переменных отмеряются относительно текущего указателя стека, который при запрыгивании со стороны никак не может быть правильным (т.к. функция прерывания тоже пользуется стеком). Поэтому как ни крути, но валидными в этом случае могут быть только глобальные переменные, но не локальные. Причем независимо от того, сбрасывали вы стек или нет.

Тут поддержу Ксению, но какое это имеет отношение к вопросу топикстартера? Он же сказал, что состояние программы и стека ему не известно и не важно. Возможно, стек переполнился и залез на глобальные переменные. Надежнее не использовать вообще никакие заранее определенные переменные. Используйте константы или заведите новые переменные, порушив глобальные, переставьте указатель стека на начало и вперед! Только вперед и только хардкор biggrin.gif
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- 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


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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 16:55
Рейтинг@Mail.ru


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