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

 
 
> Поммогите с setjmp, Не смог разобраться самостоятельно
SasaVitebsk
сообщение Jan 24 2007, 02:37
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 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);                                // И перейти на сон
  }
}
....


Пожалуйста не обращайте внимание на мелочи. Просто правлю по живому.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 9)
zltigo
сообщение Jan 24 2007, 04:13
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



1. на IAR не надо пенять не должен он содержать примеры по чистому "C" - рискну smile.gif отослать к литературе.
2. Выпрыгивать хрен знает куда из обработчика прерывания это сильно "задумано" sad.gif.
Естественно абсолютно неработоспособно.
Цитата
Пожалуйста не обращайте внимание на мелочи

К вопросу о мелочах:
В давние времена когда компьютеры были большими а железо которым они управляли было очень большое и тупое, один коллега за несколько часов до торжественной сдачи объекта начиненного
герконовыми реле коммутирующими "вcухую" по 7,5A решил слегка подправить программу....
Фраза произнесенная им после залипания нескольких сотен герконов стала крылатой -
"Странно, один бит и ничего не работает".


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 24 2007, 09:41
Сообщение #3


Гуру
******

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



Цитата(SasaVitebsk @ Jan 24 2007, 06:37) *
...
Возможно, есть смысл из прирывания прыгать не куда то а на NULL? То бишь, при начальной инициализации, проверять все что надо проверять, и потом делать выводы, спать или работать... По крайней мере тогда о стеке можно забыть...
Пока сочинял текст, еще одно решение пришло на ум:
1. Пишем подпрограмму:
Код
void MySleep(void){
SPEEP(); /* asm("sleep") */
}

2. При анализе в прерывании, если надо заснуть топим в стек адрес MySleep:
Код
    UCHAR ha = HIBYTE((UINT16)MySleep);
    UCHAR la = LOBYTE((UINT16)MySleep);
    PUSH(ha);
    PUSH(la);
И приспокойно выходим из прерывания, ни чего при этом не ломая


--------------------
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 24 2007, 10:41
Сообщение #4


Гуру
******

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



Цитата(SasaVitebsk @ Jan 24 2007, 01:37) *
я пробую так
А что мешает засыпать прямо в прерывании?


--------------------
На любой вопрос даю любой ответ
"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
prottoss
сообщение Jan 24 2007, 11:12
Сообщение #5


Гуру
******

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



Цитата(Сергей Борщ @ Jan 24 2007, 14:41) *
Цитата(SasaVitebsk @ Jan 24 2007, 01:37) *

я пробую так
А что мешает засыпать прямо в прерывании?
Интересно, а если заснуть в прерывании, разве разве может МК проснуться???


--------------------
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 24 2007, 11:53
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 24 2007, 12:03
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 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?


--------------------
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 24 2007, 12:17
Сообщение #8


Гуру
******

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



Цитата(prottoss @ Jan 24 2007, 11:03) *
А не проще ли сделать, как я выше предложил с записью в стек программ адреса sleep?
В стек возвратов. Да, наверное проще, но есть недостаток - оптимизатор может объединить некоторые куски обработчика в подпрограммы и запись в стек возвратов может оказаться внутри одной (а может и не одной) из таких подпрограмм. Тогда мы подменим не адрес возврата из обработчика, а адрес возврата из такой подпрограммы. И ситуация может меняться от добавления/удаления одной команды. Придется вручную контролировать куда попадает запись после каждой компиляции, что утомительно.


--------------------
На любой вопрос даю любой ответ
"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
prottoss
сообщение Jan 24 2007, 13:26
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 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... Конечно, не самый лучший выбор, во всяком случае куда лучше чем прыжок неизвесно куда


--------------------
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Jan 24 2007, 15:12
Сообщение #10


Гуру
******

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



2 prottoss подставить адрес возврата, - я такое делал на асме для x51 в структуре типа case. Экономилось много памяти. ret - 1 байт, jmp - 2-3. На Си мягко говоря не очень будет смотреться. На мой взгляд.

Прога работает. В общем то. Но хочется лучше, как всегда. Тут в соседней ветке у человека Tiny13 мрут как мухи smile.gif (по его словам 10 циклов перезаписи) так он отвечает что ему на ночь от 5 до 10 штук требуется. smile.gif Я так понимаю это отладка уже. Я не так силён. В том плане, что за ночь могу разных версий штуки три рабочих выдать. Ну и 10 переписываний мне за глаза. smile.gif Это я zltigo обращаюсь. Я понимаю что значит один бит. Без ошибок конечно не обходится, но при возникновении работоспособность восстанавливаю быстро. Ну там веду штук 10 последних версий (для отката) проверяю по частям, прежде чем заливать проверяю раз несколько. smile.gif

Переход в 0 пробовал, правда после просыпания. Хотя какая разница соб-сно. Смысл в том что у меня часы. Так во время сна они тикают. Ну и структура со временем реальным __no_init. Уж не знаю как, но если перезапуск делаю, то адрес этой структуры текёт. Минуты становятся секундами и т.д. Не стал разбираться, по тому как это мне тоже не очень нравится. Хотелось бы максимально в рамках языка.

Ладно попробую в прерывании. Разрешение не фокус сделать на сон грядущий, а прерывания от Int0 (пропадание питания) я и так запрещаю, так как судя по даташиту, если я правильно понял, только по уровню работает.

Подал внешнее питание ч/з диод шотки, батарейка CR2032 на прямую, а землю батарейки корочу транзистором КП505 об землю по сигналу с порта. Кондёра 500мкФ хватает чтобы включить. Пробую так.

Но общий вывод неутишительный. Практически Mega8 не предназначена для использования в качестве часов реального времени, что и подтверждают ответы других несчастных. M88 намного лучше, и вроде проблем нет, но теперь у меня уже мондраж. Я хочу солидный запас иметь. И спать спокойно. Дополнительная обвеска микрухи, для того чтобы она работала без DS1307 получается дороже самой DS1307. Повоюю ещё день, и если нет то откажусь. В новых платах предусмотрю DS1307.

Спасибо всем откликнувшимся.
Go to the top of the page
 
+Quote Post

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

 


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


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