Перейти к содержанию
    

Переход из прерывания

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Это не подходит.

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

То есть без асма не обойтись? Весь проблем, как из асма перейти к метке внутри функции main.? Как сделать метку видимой для других?

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

Пока применяю WDT, но он делает полный сброс, к устройствам, подключенным к порту, проходят броски.

Изменено пользователем Георгий

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

#include "setjmp.h"

jmp_buf redo_point;

 

__interrupt void foo1(void)

{

...

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

 

}

 

 

 

main

{

 

....

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

 

 

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

Если нужно забить гвоздь, то не надо изобретать велосипед, надо просто взять молоток и забить гвоздь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Вообще оператор goto (про него идёт речь?) в любой книжке про программистов рекомендуется забыть как страшный сон (там же и приводятся аргументы почему).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

main()

 

{

 

Init();

 

do {MyStart()} while (1);

 

}

 

 

 

void MyStart()

 

{

 

if (Error)

 

return;

 

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

?

ну и что? транслируйте эту ошибку "на верх" там и обрабатывайте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...