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

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Как перейти к началу функции по внешнему прерыванию?, подробнее внутри
SSerge
сообщение Aug 16 2008, 21:20
Сообщение #31


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Вообще-то для таких "фокусов" придуманы функции setjmp() и longjmp().
Не знаю как они реализованы в CodeVision, но если сделано по-простому, без особого мудрствования, то скорее всего можно вызывать longjmp() прямо в обработчике прерывания.
Переход в точку после setjmp() произойдёт, но регистр статуса может не сохраняться и не восстанавливаться после перехода (как именно это сделано в имеющейся реализации надо просто проверить). Поэтому прерывания после перехода останутся запрещёнными. Ну, да это не беда - если нужны просто резрешить.
Но лучше ещё раз подумать, нельзя ли обойтись без этого.


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 16 2008, 21:43
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(SSerge @ Aug 17 2008, 01:20) *
Вообще-то для таких "фокусов" придуманы функции setjmp() и longjmp().

Не для таких фокусов они придуманы, и уж точно не для прерываний.
Go to the top of the page
 
+Quote Post
SSerge
сообщение Aug 17 2008, 11:03
Сообщение #33


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Цитата(aaarrr @ Aug 17 2008, 04:43) *
Не для таких фокусов они придуманы, и уж точно не для прерываний.

smile.gif
Вы их просто готовить не умеете.
Вот как эти функции реализованы в IAR:
Прикрепленный файл  setjmp_longjmp.txt ( 3.07 килобайт ) Кол-во скачиваний: 177


Перочинный ножичек в руках искусного хирурга далеко лучше иного преострого ланцета. (с) Козьма Прутков. Афоризмы


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 17 2008, 11:10
Сообщение #34


Гуру
******

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



Цитата(SSerge @ Aug 17 2008, 13:03) *
Вот как эти функции реализованы в IAR:

Причем тут реализация к использованию для вышеупомянутых целей? Давайте я Вам со соловами "вот как реализовано" распечатаю еще чего нибудь....
Цитата
Перочинный ножичек в руках искусного хирурга далеко лучше иного преострого ланцета. (с) Козьма Прутков. Афоризмы

Рассуждай токмо о том, о чём понятия твои тебе сие дозволяют. Так: не зная законов языка ирокезского, можешь ли ты делать такое суждение по сему предмету, которое не было бы неосновательно и глупо? (с) Козьма Прутков. Афоризмы
smile.gif


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 17 2008, 11:14
Сообщение #35


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(SSerge @ Aug 17 2008, 15:03) *
smile.gif
Вы их просто готовить не умеете.

Замечательно. А вы умеете готовить программы, которые будут нормально работать при вываливании из любой точки после прерывания в другую?
Go to the top of the page
 
+Quote Post
SSerge
сообщение Aug 17 2008, 17:42
Сообщение #36


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Цитата(zltigo @ Aug 17 2008, 18:10) *
Рассуждай токмо о том, о чём понятия твои тебе сие дозволяют. Так: не зная законов языка ирокезского, можешь ли ты делать такое суждение по сему предмету, которое не было бы неосновательно и глупо? (с) Козьма Прутков. Афоризмы
smile.gif

Понятия дозволяют. Я законы языка ирокез С ещё на PDP-11 изучал. И с работой setjmp/longjmp тогда же разбирался.

Цитата(aaarrr @ Aug 17 2008, 18:14) *
Замечательно. А вы умеете готовить программы, которые будут нормально работать при вываливании из любой точки после прерывания в другую?

Чтобы из любой - это гораздо сложнее. Но Вас же не удивляет что любая (некооперативная) RTOS может передать управление другому процессу после того как текущий был прерван прерыванием?
Разбираемый сейчас случай попроще будет. Требуется поведение программы типа "всё бросить и вернуться на заранее подготовленные позиции", как раз для такого эти функции и предназначены.
В популярных учебниках тему setjmp/longjmp предпочитают не затрагивать, вот народ про них почти ничего и не знает.
Попробую рассказать что знаю, с некоторыми упрощениями.
Функция setjmp() всего лишь запоминает в специальном буфере содержимое нескольких регистров, указатель стека и счётчик команд (адрес возврата, лежащий в стеке). Эта информация потом, при исполнении longjmp(), позволяет восстановить состояние программы таким, словно только что произошел возврат из setjmp(). Отличается только возвращаемое значение, setjmp() возвращает 0, а longjmp() возвращает свой второй аргумент. Это позволяет понять откуда попало управление в этот раз.
Разумеется, восстанавливается далеко не всё, скажем если программа успела изменить глобальные переменные то эти изменения не будут откачены назад, ну так это-то уже в руках программиста, и он может это предусмотреть, если бывает нужно "прибрать за собой".

Поскольку longjmp() переставляет указатель стека на прежнее место, то существует естественное ограничение на её применение: состояние той части стека, которая существовала на момент возврата из setjmp() не должно изменяться до выполнения longjmp(). Другими словами, не должно быть выхода из функции или блока, содержащего setjmp().

А с учетом архитектуры AVR и имеющейся реализации этих функций не вижу никаких препятствий для примения longjmp() прямо из обработчика прерывания.
Реализацию в CodeVision надо проверить, но скорее всего и там будет работать. Примерно так (для IAR):

Код
jmp_buf jbuf;

int foo()
{
   if( setjmp( jbuf ) )
   {
      // исполняется только после перехода по longjmp()
      //если переход делать прямо из обработчика, то прерывания останутся запрещёнными
      __enable_interrupt();
      afterINT();
   }
   else
   {
      // исполняется после возврата из setjmp()
   }

   for(;;)
   {
      loop();
      //........
   }
}

#pragma vector=INT0_vect
__interrupt void INT0_isr(void)
{
   longjmp( jbuf, 1);
}


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 17 2008, 22:00
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(SSerge @ Aug 17 2008, 21:42) *
Чтобы из любой - это гораздо сложнее. Но Вас же не удивляет что любая (некооперативная) RTOS может передать управление другому процессу после того как текущий был прерван прерыванием?

OS, в отличие от вашего "изобретения", вернет в какой-то момент времени управление назад.

Цитата(SSerge @ Aug 17 2008, 21:42) *
...с учетом архитектуры AVR и имеющейся реализации этих функций не вижу никаких препятствий для примения longjmp() прямо из обработчика прерывания.

Применить-то действительно никто не запрещает, только кому нужна программа, которая при выходе из прерывания в буквальном смысле все бросит и ломанется в определенную точку?

Код
   for(;;)
   {
      loop();
      //........
   }


Предположим, что из loop'а мы можем так вывалится (хотя и это сомнительно, если там производятся хоть сколько нибудь осмысленные действия), а из остальной программы, скромно обозначенной "//........"?

Ну нельзя использовать longjmp из прерывания. Одно дело, когда случилась ошибка, и нужно вернуть управление, а другое, когда эта "ошибка" генерируется снаружи.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 17 2008, 22:15
Сообщение #38


Гуру
******

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



Цитата(SSerge @ Aug 17 2008, 19:42) *
Требуется поведение программы типа "всё бросить и вернуться на заранее подготовленные позиции", как раз для такого эти функции и предназначены.

Ну насчет все грубо бросить в непонятном состоянии И ЗАБЫТЬ НА ВСЕГДА, это еще большой вопрос о допустимости такого.
Цитата
Попробую рассказать что знаю, с некоторыми упрощениями.

Спасибо, не надо - плавали. Особенно с упрощениями, ибо дявольщина таится в деталях. А деталей реализации там много и некоторые даже подбираются ключами в пределах одного компилятора.
Цитата
Разумеется, восстанавливается далеко не всё...

..И при прерывании/восстановлении в
Цитата
..уже в руках программиста...

столько всего окажется, что разбираться в отсутствии побочных эффектах придется долго.
Цитата
А с учетом архитектуры AVR и имеющейся реализации этих функций не вижу никаких препятствий для примения longjmp() прямо из обработчика прерывания.

Ага, самая примтивная архитектура и железо - скомпенсировали отсутствие RETI и типа все...
А на ARM слабо?
Цитата
Реализацию в CodeVision надо проверить...

Ага, проверить, и при получении свежего компилятора проверить...
Цитата
, но скорее всего и там будет работать. Примерно так (для IAR):

Ну и чего добились этими финтами? Эквивалент внесения afterINT() в обработчик прерывания + непонятные эффекты (особенно в случае прерывания afterINT()) + опасно переносимый или гарантированно не переносимый код.
Нет это не "руками хирурга" сделано sad.gif
И даже перечисленные лично Вами подводные камни, камня на камне не оставляют от Вашего-же утверждения
Цитата
Вообще-то для таких "фокусов" придуманы функции setjmp() и longjmp().

с которого все и началось...


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
GDI
сообщение Aug 18 2008, 10:04
Сообщение #39


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



не кажется что за спором вы забыли одну важную вещь, то что функция loop() конечная, т.е. она либо отработает 360 раз свой внутренний цикл, либо, по воле автора и в результате прерывания должна прервать свой цикл, что и достигается проверкой флага и оператором return. А вот что там должно произойти дальше, автор топика нам не раскрывает, т.е нужно ли после прерывания цикла в loop() выполнить следующие за ней функции(достаточно return) или нужно запустить цикл main сначала(return + continue) или перезапустить цикл в loop()(обнулить счетчик цикла).


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
Guest_@Ark_*
сообщение Aug 18 2008, 13:37
Сообщение #40





Guests






Цитата(SSerge @ Aug 17 2008, 21:42) *
... Разбираемый сейчас случай попроще будет. Требуется поведение программы типа "всё бросить и вернуться на заранее подготовленные позиции" ...

Интересно, как Вы собираетесь обрабатывать ситуацию с вложенными прерываниями, которая в общем случае теоретически возможна? Ведь тогда, номинально, нужно возвращаться не вашу программу, а в обработчик другого прерывания. Если заменить адрес возврата или сделать прямой переход, то обработка другого прерывания останется незавершенной, с неизвестными последствиями. Причем, так как ситуация довольно редкая, "скорее всего все будет работать". Но с редкими и непредсказуемыми "глюками" где-то совсем в другом месте , причину которых потом практически невозможно найти...
Go to the top of the page
 
+Quote Post
AndrewN
сообщение Aug 18 2008, 15:25
Сообщение #41


Местный
***

Группа: Участник
Сообщений: 336
Регистрация: 7-03-07
Из: Петербург
Пользователь №: 25 961



Прежде всего, спасибо всем за возможность освежить знания о setjmp/longjmp.
Как всегда, когда имеешь дело с чем-то выходящим за пределы контекста С,
выясняется, что от процессора к процессору и от компилятора к компилятору,
алгоримт работы таких компонент может варьироваться.

Я просмотрел три варианта setjmp/longjmp, в TI CCS для ARM и С6000, и в очень
старом компиляторе MS QuickC 2.5 для 16 бит x86. QC мспользует setjmp/longjmp
в своем примере для обработки прерывания по ошибке FPU, тогда как нарямую,
без дополнительного кода, использовать setjmp/longjmp внутри прерывания ARM
или С6000 нельзя.

Конечно, если дополнить код ISR (или setjmp/longjmp), то нет никаких препятствий
для использования setjmp/longjmp внутри прерывания. В любом случае, setjmp/longjmp
были в первую очередь созданы для обхода правил передачи управления установленных
языком С. Где не хватает возможностей высокого уровня надо использовать низкоуровневые
средства.

Цитата(@Ark @ Aug 18 2008, 16:37) *
Интересно, как Вы собираетесь обрабатывать ситуацию с вложенными прерываниями, которая в общем случае теоретически возможна? Ведь тогда, номинально, нужно возвращаться не вашу программу, а в обработчик другого прерывания. Если заменить адрес возврата или сделать прямой переход, то обработка другого прерывания останется незавершенной, с неизвестными последствиями. Причем, так как ситуация довольно редкая, "скорее всего все будет работать". Но с редкими и непредсказуемыми "глюками" где-то совсем в другом месте , причину которых потом практически невозможно найти...


Все эти опасения (как и те, которые следуют из некоторой неопределенности постановки задачи
у автора треда), конечно нужно принять во внимание. И, соответствующим образом, обработать.
Например, усложнение алгоритма, вызванное возможной вложенностью, обходится при помощи
счетчика вложенности прерываний (надеюсь, что никого этим не удивил), и так далее.

Для меня удивительным оказалось то, что сама постановка задачи (может быть, с точки зрения
эстетики и не самая красивая, но уж точно непротиворечивая) вызвала такую бурную дискуссию.

--
AN
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 18 2008, 15:31
Сообщение #42


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(AndrewN @ Aug 18 2008, 19:25) *
Для меня удивительным оказалось то, что сама постановка задачи (может быть, с точки зрения
эстетики и не самая красивая, но уж точно непротиворечивая) вызвала такую бурную дискуссию.

Просто тема была создана в пятницу вечером. Почему бы не оторваться на выходных? smile.gif
Go to the top of the page
 
+Quote Post
Guest_@Ark_*
сообщение Aug 18 2008, 17:28
Сообщение #43





Guests






Цитата(AndrewN @ Aug 18 2008, 19:25) *
... Все эти опасения (как и те, которые следуют из некоторой неопределенности постановки задачи
у автора треда), конечно нужно принять во внимание. И, соответствующим образом, обработать.
Например, усложнение алгоритма, вызванное возможной вложенностью, обходится при помощи
счетчика вложенности прерываний...

Вы, возможно, не поняли о чем речь, или я плохо сформулировал. Счетчик тут не поможет. Речь идет не об одном и том же прерывании, а о прерывании работы другого обработчика прерываний. Например, обработчик прерывания в каком-нибудь драйвере ОС, может запрещать прерывания только в своей критической части кода. А дальше - они разрешены, хотя сама процедура обработки прерывания еще не завершена. И вот, в этот неподходящий момент, может возникнуть ваше прерывание, после которого вы не возвращаете управление. Работа драйвера будет нарушена.
P.S. На такие "грабли" лучше не наступать. Замучеетесь искать причину...
Go to the top of the page
 
+Quote Post
AndrewN
сообщение Aug 18 2008, 19:06
Сообщение #44


Местный
***

Группа: Участник
Сообщений: 336
Регистрация: 7-03-07
Из: Петербург
Пользователь №: 25 961



Цитата(@Ark @ Aug 18 2008, 20:28) *
Вы, возможно, не поняли о чем речь, или я плохо сформулировал. Счетчик тут не поможет. Речь идет не об одном и том же прерывании, а о прерывании работы другого обработчика прерываний. Например, обработчик прерывания в каком-нибудь драйвере ОС, может запрещать прерывания только в своей критической части кода. А дальше - они разрешены, хотя сама процедура обработки прерывания еще не завершена. И вот, в этот неподходящий момент, может возникнуть ваше прерывание, после которого вы не возвращаете управление. Работа драйвера будет нарушена.
P.S. На такие "грабли" лучше не наступать. Замучеетесь искать причину...

Конечно, такая вложенность вполне возможна. И в таком случае в ISR, которая выполняет, назовем
это так, "необычный" возврат, счетчик вложенности > 1, и ISR должна должна выполнить наиболее
подходящие действия. Возможно, что нужно переделать логику у всех возможных ISR - некий
аналог планировщика, который осуществляет только два вида выхода из прерывания - или обычный
возврат или "необычный" возврат на начало loop() .

Другой пример: в исходной задаче говорится, что переход на начало loop() из прерывания (т.е. из
ISR, обрабатывающей прерывание от соответствующего устройства) должен происходить в том случае,
если была прервана сама подпрограмма loop(), если я не ошибаюсь. Это значит, что ISR должна
анализировать такое событие, т.е. еще один флаг, на этот раз бинарный.

Вероятно, автору придется помучится, а как же без этого? С другой стороны, существует отличная
от нуля вероятность, что это мы тут мучаемся (бесплодно...), а заказчик автора имел ввиду
совершенно другой алгоритм, или вопрос был сформулирован совсем уж плохо. Кто знает?..

Если исходить из общей формулировки задачи реального времени, я склоняюсь в пользу
последнего. В самом деле, если прерывания приходят так часто, что loop() вообще никогда
не имеет возможности довести свои вычисления до конца, что эквивалентно тому, что
управляющие действия никогда не будут осуществлены. Возможна ли такая крайность?
Возможно, что и нет, что только иногда loop() не будет успевать завершиться до следующего
прерывания и, поэтому, выбран алгоритм, который вместо буферизации запросов
использует алгоритм своего рода "забывания" о предыдущем, неисполненном запросе.

Про ОС очень хорошее замечание. Сейчас мне кажется, что исходную задачу можно решить
с помощью двух процессов, один управляющий, который или запускает или снимает с исполнения
(фактически, перезапускает) второй процесс, который производит вычисления и управляет внешним
устройством. Я подробно о таком способе пока не думал.

--
AN
Go to the top of the page
 
+Quote Post
MMos
сообщение Aug 19 2008, 08:25
Сообщение #45


Частый гость
**

Группа: Участник
Сообщений: 147
Регистрация: 7-12-07
Пользователь №: 33 057



Недавно в одной ветке, я обмолвился, что пишу на ассемблере и был подвергнут порицанию типа "до чего же надо себя не любить..."

Почитал я всё вышеизложенное на 3 страницах и решил, что у вас у всех слишком много свободного времени. В ассемблере эта задача решается парой строк. Естественно, этой парой строк можно пользоваться только тогда, когда понимаешь, что далаешь. Но если пишешь на языке высокого уровня, такого понимания никогда не будет. Для справки: на высоком уровне тоже пишу, но меня периодически посещает мысль, что кто-то пытается "держать меня за последнего лоха".

Теперь по сути темы. В одном устройстве у меня была похожая задача. При её решении вместо прерывания я использовал RESET и флаг "горячий/холодный старт".
Go to the top of the page
 
+Quote Post

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

 


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


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