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

 
 
> Переход из прерывания
Георгий
сообщение Feb 20 2006, 12:55
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 269
Регистрация: 17-11-05
Из: Киров-Москва
Пользователь №: 10 957



Как сделать переход к определенному месту программы из программы прерывания. Мне нужно из прерывания по таймеру, при достижении определенного значения счетчика Counter переходить в определенное место программы. На ассемблере решалось просто, искусственно восстанавливаю стек и делаю переход к метке. А В ИАР как это сделать?


--------------------
Обычно последним смеется тот, кто хуже соображает!
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 22)
GxOST
сообщение Feb 20 2006, 13:08
Сообщение #2


Участник
*

Группа: Свой
Сообщений: 58
Регистрация: 6-12-05
Из: Санкт-Петербург
Пользователь №: 11 878



это делается просто: в прерывании модифицируется флажок типа volatile, а в основном цикле программы он проверяется


--------------------
cul8r!
* #ru_embedded - эмбеддерский чат
Go to the top of the page
 
+Quote Post
dxp
сообщение Feb 20 2006, 13:14
Сообщение #3


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Георгий @ Feb 20 2006, 18:55) *
Как сделать переход к определенному месту программы из программы прерывания. Мне нужно из прерывания по таймеру, при достижении определенного значения счетчика Counter переходить в определенное место программы. На ассемблере решалось просто, искусственно восстанавливаю стек и делаю переход к метке. А В ИАР как это сделать?

Точно так же - напишите низкоуровневую функцию манипуляции контекстами на асме, а вызывайте ее из С. Вообще-то, это что-то RTOS'ом попахивает. smile.gif


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Георгий
сообщение Feb 20 2006, 13:21
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 269
Регистрация: 17-11-05
Из: Киров-Москва
Пользователь №: 10 957



Цитата
это делается просто: в прерывании модифицируется флажок типа volatile, а в основном цикле программы он проверяется

Это не подходит.
Цитата
Точно так же - напишите низкоуровневую функцию манипуляции контекстами на асме, а вызывайте ее из С

То есть без асма не обойтись? Весь проблем, как из асма перейти к метке внутри функции main.? Как сделать метку видимой для других?
Уточню свою задачу. Функция чтения в цикле опрашивает порт. Если через какое то время порт не ответил, функция должна передать управление в начало программы, но не в самое начало, а туда , где начальные условия уже выставлены и необходимо попытаться реанимировать устройство, подключенное к порту, отправив ему сброс.
Пока применяю WDT, но он делает полный сброс, к устройствам, подключенным к порту, проходят броски.

Сообщение отредактировал Георгий - Feb 20 2006, 13:30


--------------------
Обычно последним смеется тот, кто хуже соображает!
Go to the top of the page
 
+Quote Post
Rst7
сообщение Feb 20 2006, 13:55
Сообщение #5


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Могут помочь стандартные функции setjmp и longjmp.

#include "setjmp.h"
jmp_buf redo_point;

__interrupt void foo1(void)
{
...
longjmp(&redo_point,1); //Тут будет переход на оператор за setjmp

}



main
{

....
setjmp(&redo_point); //Устанавливаем точку длинного перехода


}


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
defunct
сообщение Feb 20 2006, 14:44
Сообщение #6


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Георгий @ Feb 20 2006, 15:21) *
где начальные условия уже выставлены и необходимо попытаться реанимировать устройство, подключенное к порту, отправив ему сброс.

офомить в виде функции это место и просто вызвать при необходимости

Если нужно забить гвоздь, то не надо изобретать велосипед, надо просто взять молоток и забить гвоздь.
Go to the top of the page
 
+Quote Post
Георгий
сообщение Feb 21 2006, 11:27
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 269
Регистрация: 17-11-05
Из: Киров-Москва
Пользователь №: 10 957



Дело в том, что после сброса устройства, программа должна начать все практически сначала. Если бы можно ограничиться функцией, так бы и сделал. Нужен именно переход в начало программы, но не в самое.


--------------------
Обычно последним смеется тот, кто хуже соображает!
Go to the top of the page
 
+Quote Post
dxp
сообщение Feb 21 2006, 12:05
Сообщение #8


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Георгий @ Feb 21 2006, 17:27) *
Дело в том, что после сброса устройства, программа должна начать все практически сначала. Если бы можно ограничиться функцией, так бы и сделал. Нужен именно переход в начало программы, но не в самое.

Непонятно, откуда такое суровое требование - обнулять работу программы при отсутствии сигнала в каком-то порте. Да еще и не совсем обнулять, а частично. Неужели нельзя как-то штатно эту ситуацию обрабатывать? Ну нет сигнала - это, да, событие, которое трубует обработки (как и многие другие события в системе). Зачем работу программы-то рушить? Целостность работы нарушать...


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Aleks17
сообщение Feb 21 2006, 12:16
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 238
Регистрация: 17-01-05
Из: Новосибирск
Пользователь №: 2 003



Не понимаю чем не устраивает вариант с volatile флагом. Самым удобный и разумный на мой взгляд.

Вообще оператор goto (про него идёт речь?) в любой книжке про программистов рекомендуется забыть как страшный сон (там же и приводятся аргументы почему).
Go to the top of the page
 
+Quote Post
Георгий
сообщение Feb 21 2006, 12:24
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 269
Регистрация: 17-11-05
Из: Киров-Москва
Пользователь №: 10 957



Вся работа программы зависит от ответа устройства, опрос его может быть из разных мест, если после каждого вызова каждой функции проверять флаг, а потом делать многоуровневый откат к началу программы, это тоже не выход. Устройство может быть выдернуто в любой момент, и обнаружение ведется по прерыванию, это нормально. Но уходить надо в определенную точку из прерывания. Я не совсем еще понимаю логику работы ИАРа, но, наверно, как то можно подменить адрес возврата из прерывания на адрес этой точки. Может longjmp это и делает?


--------------------
Обычно последним смеется тот, кто хуже соображает!
Go to the top of the page
 
+Quote Post
Aleks17
сообщение Feb 21 2006, 12:36
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 238
Регистрация: 17-01-05
Из: Новосибирск
Пользователь №: 2 003



Иными словами, Вам необходимо перейти к началу какого-то алгоритма при достижении определенного условия. А нельзя это сделать так:

main()

{

Init();

do {MyStart()} while (1);

}



void MyStart()

{

if (Error)

return;

}
Go to the top of the page
 
+Quote Post
Георгий
сообщение Feb 21 2006, 13:12
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 269
Регистрация: 17-11-05
Из: Киров-Москва
Пользователь №: 10 957



Не совсем так, так было бы просто. if Error может возникнуть в любом месте, в том числе и вов вложенных несколько раз функциях.


--------------------
Обычно последним смеется тот, кто хуже соображает!
Go to the top of the page
 
+Quote Post
Rst7
сообщение Feb 21 2006, 13:15
Сообщение #13


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата(Георгий @ Feb 21 2006, 14:24) *
Вся работа программы зависит от ответа устройства, опрос его может быть из разных мест, если после каждого вызова каждой функции проверять флаг, а потом делать многоуровневый откат к началу программы, это тоже не выход. Устройство может быть выдернуто в любой момент, и обнаружение ведется по прерыванию, это нормально. Но уходить надо в определенную точку из прерывания. Я не совсем еще понимаю логику работы ИАРа, но, наверно, как то можно подменить адрес возврата из прерывания на адрес этой точки. Может longjmp это и делает?


setjmp запоминает в jmpbuf все необходимые регистры (в том числе Y, SP, PC) в точке вызова этой функции.

longjmp все это загружает обратно и возвращается по записанному в jmpbuf PC. Т.е. то, что надо.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
dxp
сообщение Feb 21 2006, 13:19
Сообщение #14


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Георгий @ Feb 21 2006, 18:24) *
Вся работа программы зависит от ответа устройства, опрос его может быть из разных мест, если после каждого вызова каждой функции проверять флаг, а потом делать многоуровневый откат к началу программы, это тоже не выход. Устройство может быть выдернуто в любой момент, и обнаружение ведется по прерыванию, это нормально. Но уходить надо в определенную точку из прерывания.

Ну и зачем делать откат в начало? Пусть себе программа работает, если выдернули устройство, то программа переходит в один режим, если вставили, то в другой. Зачем что-то обнулять? Заведите переменную, обозначающую режим и проверяйте ее. Вот прикинье - вставили/вынули USB дивайс, винда перегрузилась - хорошо это? smile.gif

Цитата(Георгий @ Feb 21 2006, 18:24) *
Я не совсем еще понимаю логику работы ИАРа, но, наверно, как то можно подменить адрес возврата из прерывания на адрес этой точки. Может longjmp это и делает?

Логики IAR'а тут никакой нет - он действует в рамках Стандарта языков С/С++. longjmp действительно может реализовать такое, но все-таки, имхо, это не путь. Имхо, чего-то не того в дизайне проги. Вы бы чуть подробнее изложили преметную область, может чего и посоветовать удалось бы.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
defunct
сообщение Feb 21 2006, 13:29
Сообщение #15


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Георгий @ Feb 21 2006, 15:12) *
Не совсем так, так было бы просто. if Error может возникнуть в любом месте, в том числе и вов вложенных несколько раз функциях.

?
ну и что? транслируйте эту ошибку "на верх" там и обрабатывайте.
Go to the top of the page
 
+Quote Post
Георгий
сообщение Feb 21 2006, 13:43
Сообщение #16


Местный
***

Группа: Свой
Сообщений: 269
Регистрация: 17-11-05
Из: Киров-Москва
Пользователь №: 10 957



Что то инет у меня глючит, начинаю отвечать , отрубается.
Транслировать наверх получется сложнее, чем сделать один переход из одной функции прерывания. Функций чтения много, и они могут быть и на втором и на третьем уровне. Это сколько проверо по дороге надо делать.

Цитата
Ну и зачем делать откат в начало? Пусть себе программа работает, если выдернули устройство, то программа переходит в один режим, если вставили, то в другой. Зачем что-то обнулять? Заведите переменную, обозначающую режим и проверяйте ее. Вот прикинье - вставили/вынули USB дивайс, винда перегрузилась - хорошо это?

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


--------------------
Обычно последним смеется тот, кто хуже соображает!
Go to the top of the page
 
+Quote Post
defunct
сообщение Feb 21 2006, 13:47
Сообщение #17


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Георгий @ Feb 21 2006, 15:43) *
Функций чтения много, и они могут быть и на втором и на третьем уровне. Это сколько проверо по дороге надо делать.

Вот и плохо что много. Должна быть одна функция чтения, в которой обрабатываются ошибки связи с устройством. т.е. разделите программу на уровни не по вложенности, а по характеру действий хотя бы на канальный, транспортный(в вашем случае сразу сеансовый) и прикладной. см. модель http://www.citforum.ru/nets/switche/osi.shtml.

Сообщение отредактировал defunct - Feb 21 2006, 13:55
Go to the top of the page
 
+Quote Post
Георгий
сообщение Feb 21 2006, 13:52
Сообщение #18


Местный
***

Группа: Свой
Сообщений: 269
Регистрация: 17-11-05
Из: Киров-Москва
Пользователь №: 10 957



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


--------------------
Обычно последним смеется тот, кто хуже соображает!
Go to the top of the page
 
+Quote Post
defunct
сообщение Feb 21 2006, 14:05
Сообщение #19


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Георгий @ Feb 21 2006, 15:52) *
Поправляюсь - функция чтения естественно одна. Но вызываеться она может с разных уровней.

мало ли откуда она вызывается? главное чтобы функция чтения производила разбор протокола работы с устройством, и обрабатывала ошибки связи, а на верхний уровень передавала только правильно распознанные данные.

Цитата
Но отсутствие устройства все рано определяется возникновением прерывания, и логично из него уйти в начало. Этим сейчас WDT занимается, но он делает полный сброс.

В прерывании установить флаг ошибки устройства, который заблокирует например функцию чтения. Разблокировать этот флаг может например, функция "реанимации" устройства, которая будет вызываться пока флаг ошибки устройства установлен.
Go to the top of the page
 
+Quote Post
Георгий
сообщение Feb 21 2006, 14:11
Сообщение #20


Местный
***

Группа: Свой
Сообщений: 269
Регистрация: 17-11-05
Из: Киров-Москва
Пользователь №: 10 957



Нет, уж я лучше оставлю все как есть. Иначе из-за одного перехода придется переписывать всю программу, менять все функции на булевые, чтобы корректно откатываться наверх. У меня эта прога была сначала написана на ассемблере, и там переход из прерывания в начало программы решал все проблемы. А перевел на Си и столкнулся с этой бякой.


--------------------
Обычно последним смеется тот, кто хуже соображает!
Go to the top of the page
 
+Quote Post
defunct
сообщение Feb 21 2006, 14:19
Сообщение #21


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Георгий @ Feb 21 2006, 16:11) *
Нет, уж я лучше оставлю все как есть.

вероятно, это правильное решение. WDT всяко надежнее манипуляций со стеком и неправильного использования прерываний.

Цитата
Иначе из-за одного перехода придется переписывать всю программу, менять все функции на булевые, чтобы корректно откатываться наверх. У меня эта прога была сначала написана на ассемблере, и там переход из прерывания в начало программы решал все проблемы. А перевел на Си и столкнулся с этой бякой.

Менять пришлось бы только функцию чтения...
Go to the top of the page
 
+Quote Post
_artem_
сообщение Feb 21 2006, 14:26
Сообщение #22


учащийся
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 29-10-05
Из: города контрастов
Пользователь №: 10 249



Внутри одной функции переход с одной позиции в другую может только через явные операторы goto, break continue или посредством других конструкций языка программирования если таковые есть или же перезагрузкой самого контроллера. Мне ваша логика непонятна - хотите ли вы совершать какие то действия после того как команда отправлена или не желаете ждать ответа от команды и проверять результат на правильность или на что то другое?

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

То есть вы програмным путем делаете контролируемую загрузку с контролем инициализации переменных, что позволяет вам определить был ли это reset или переход по ошибке. Конечно можно было просто перейти на вектор прерывания reset но будет неоднозначность значения переменной результата - на случай если состояние оперативной памяти на время загрузки неопределенно.

Но поверьте мне - овчинка не стоит выделки ...


--------------------
Зачем лаять на караван , когда на него можно плюнуть?

Go to the top of the page
 
+Quote Post
Георгий
сообщение Feb 22 2006, 05:08
Сообщение #23


Местный
***

Группа: Свой
Сообщений: 269
Регистрация: 17-11-05
Из: Киров-Москва
Пользователь №: 10 957



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

"Правильная" проверка флагов и откат по ошибке наверх увеличили программу почти на 200 байт. И глубина стека возросла.

Вариант с longjmp тоже оказался не походящим - jmp_buf отъедает 21 байт от ОЗУ (из 128). На стек уже не остается.

Сообщение отредактировал Георгий - Feb 22 2006, 09:06


--------------------
Обычно последним смеется тот, кто хуже соображает!
Go to the top of the page
 
+Quote Post

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

 


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


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