|
Поммогите с setjmp, Не смог разобраться самостоятельно |
|
|
|
Jan 24 2007, 02:37
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Не ругайте сильно и не отсылайте пожалуйста к литературе. Перечитал всё что мог, но не смог разобраться полностью. Наверное тупею с годами. К тому же не очень очевидно, ну и хочу заметить себе в оправдание, что IAR жутко скупится на примеры. Те же примеры которые я нашёл, оставили некоторые вопросы. Сначала опишу задачу. Может её кто по другому решал и я зря огород горожу. Стоит M8. Обслуживает некоторые датчики и часы реального времени. На вход Int0 поступает сигнал от внешнего (не батарейного) питания. Мне надо чтобы она заснула как можно быстрее. Опрос не проходит, так как в теле очень много временных интервалов формируется и везде вставлять выход на точку засыпания не получается. Короче формирую прерывание по провалу питания. Хочу из обработчика прерывания перейти на сон. Естественно с сохранением стеков. Остальное не волнует. После сна инициализация по новый. Вопросы такие 1) возможно ли это (написано что из более высокоуровневой только). 2) Как это сделать я пробую так Код .... // Голова. Вот сюда я хочу перейти по провалу питания setjmp(Adr_sleep);
if((INT0_PIN & (1<<INT0))==0) { // При нормальном питании - не выполнять // Вырубание переферии для уменьшения потребления ...... ......
#pragma vector=INT0_vect // Пропадание питания __interrupt static void Power(void) { //========================================= if((INT0_PIN & (1<<INT0))==0){ PWR_BAT_ON; // Если питание пропало, то включить батарейку #if __ATmega88__ EIMSK=0; // прерывание от INT0 запретить #else GICR=0x0; // прерывание от INT0 запретить #endif longjmp(Adr_sleep,1); // И перейти на сон } } .... Пожалуйста не обращайте внимание на мелочи. Просто правлю по живому.
|
|
|
|
|
 |
Ответов
|
Jan 24 2007, 11:53
|

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

|
Цитата(prottoss @ Jan 24 2007, 10:12)  Цитата(Сергей Борщ @ Jan 24 2007, 14:41)  Цитата(SasaVitebsk @ Jan 24 2007, 01:37)  я пробую так
А что мешает засыпать прямо в прерывании? Интересно, а если заснуть в прерывании, разве может МК проснуться??? Хм. В остальных встречавшихся мне процессорах мог. Причем в зависимости от того запрещены или разрешены прерывания глобально он после выхода из спячки либо выполнял обработчик прерывания либо просто продолжал выполнение с команды после sleep. В доке на мегу8 об этом ничего не нашел кроме фразы Цитата If an enabled interrupt occurs while the MCU is in a sleep mode, the MCU wakes up. The MCU is then halted for four cycles in addition to the start-up time, it executes the interrupt routine, and resumes execution from the instruction following SLEEP И если понятие "enabled interrupt" выводить как противоположность от Цитата If the Global Interrupt Enable bit is cleared, none of the interrupts are enabled то выходит что при глобально запрещенных прерываниях не проснется никогда, что само по себе странно и неестественно. Надо будет проверить это на живом проце. Однако даже это не мешает перед засыпанием запретить прерывание, в обработчике которого находимся и глобально разрешить прерывания. После выхода из спячки и исполнения разбудившего обработчика делаем обратное - запрещаем глобально и разрешаем текущее прерывание. Не забыть только что стека потребуется для обоих обработчиков - текущего и будильника.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 24 2007, 12:03
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(Сергей Борщ @ Jan 24 2007, 15:53)  Цитата(prottoss @ Jan 24 2007, 10:12)  Цитата(Сергей Борщ @ Jan 24 2007, 14:41)  Цитата(SasaVitebsk @ Jan 24 2007, 01:37)  я пробую так
А что мешает засыпать прямо в прерывании? Интересно, а если заснуть в прерывании, разве может МК проснуться??? Хм. В остальных встречавшихся мне процессорах мог. Год назад я проводил подобные опыты с ATtiny2313 - и помнится программа умирала после sleep в прерывании... по моему Цитата(Сергей Борщ @ Jan 24 2007, 15:53)  Однако даже это не мешает перед засыпанием запретить прерывание, в обработчике которого находимся и глобально разрешить прерывания. После выхода из спячки и исполнения разбудившего обработчика делаем обратное - запрещаем глобально и разрешаем текущее прерывание. Не забыть только что стека потребуется для обоих обработчиков - текущего и будильника. А не проще ли сделать, как я выше предложил с записью в стек программ адреса sleep?
--------------------
|
|
|
|
|
Jan 24 2007, 13:26
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(Сергей Борщ @ Jan 24 2007, 16:17)  Цитата(prottoss @ Jan 24 2007, 11:03)  А не проще ли сделать, как я выше предложил с записью в стек программ адреса sleep?
В стек возвратов. Да, наверное проще, но есть недостаток - оптимизатор может объединить некоторые куски обработчика в подпрограммы и запись в стек возвратов может оказаться внутри одной (а может и не одной) из таких подпрограмм. Тогда мы подменим не адрес возврата из обработчика, а адрес возврата из такой подпрограммы. И ситуация может меняться от добавления/удаления одной команды. Придется вручную контролировать куда попадает запись после каждой компиляции, что утомительно. Это будет только в том случае, если компилятор решит операторы Код UCHAR ha = HIBYTE((UINT16)MySleep); UCHAR la = LOBYTE((UINT16)MySleep); PUSH(ha); PUSH(la); загнать в подпрограмму и вызывать через call... Конечно, не самый лучший выбор, во всяком случае куда лучше чем прыжок неизвесно куда
--------------------
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|