SapegoAL 0 21 декабря, 2006 Опубликовано 21 декабря, 2006 · Жалоба При программировании однокристалок иногда приходится обрабатывать глобальные ошибки. Или, к примеру, реагировать на существенное изменение конфигурации. В этом случае самый простой а чаще и найболее надёжный способ, - это рестарт программы. Во всяком случае я пользовался таким способом под ASM и, несмотря на "некрасивость", не хочу обходится без этого и на СИ. На Си я делаю это так: asm("jmp 0"); // Начать сначала У меня это единственный оператор ASM на всё прогу. Может существует специальный вызов для IAR, что-то вроде __restart(); ? И ещё один вопрос. Компилятор вопреки моему мнению скомпилировал его не в jmp. Это зачем? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 21 декабря, 2006 Опубликовано 21 декабря, 2006 · Жалоба При программировании однокристалок иногда приходится обрабатывать глобальные ошибки. Или, к примеру, реагировать на существенное изменение конфигурации. В этом случае самый простой а чаще и найболее надёжный способ, - это рестарт программы. Во всяком случае я пользовался таким способом под ASM и, несмотря на "некрасивость", не хочу обходится без этого и на СИ. На Си я делаю это так: asm("jmp 0"); // Начать сначала У меня это единственный оператор ASM на всё прогу. Может существует специальный вызов для IAR, что-то вроде __restart(); ? И ещё один вопрос. Компилятор вопреки моему мнению скомпилировал его не в jmp. Это зачем? В бутлоадере исплользовал такое объявление функции: void (*start_application)( void ) = 0x0000; //pointer to application //at flash start Далее, в произвольном месте программы, мы можем ее вызвать и соответственно перейти по адресу 0. З.Ы. Работает. Использую компилятор GCC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 53 21 декабря, 2006 Опубликовано 21 декабря, 2006 · Жалоба При программировании однокристалок иногда приходится обрабатывать глобальные ошибки. Или, к примеру, реагировать на существенное изменение конфигурации. В этом случае самый простой а чаще и найболее надёжный способ, - это рестарт программы. Во всяком случае я пользовался таким способом под ASM и, несмотря на "некрасивость", не хочу обходится без этого и на СИ. На Си я делаю это так: asm("jmp 0"); // Начать сначала У меня это единственный оператор ASM на всё прогу. Может существует специальный вызов для IAR, что-то вроде __restart(); ? И ещё один вопрос. Компилятор вопреки моему мнению скомпилировал его не в jmp. Это зачем? Переносимого в рамках языка способа нет. Все очень зависит от целевого проца и кросс-компилятора. В некоторых процах есть специальные команды для глобального сброса. Сброс, также, может поддерживаться компилятором путем различного рода расширений языка. В конце концов, сбросы тоже разные бывают - "холодные", "теплые". Для "холодного" можно просто завести внешнюю ногу Reset на один из пинов МК и принудильно самого себя сбрасывать. "Теплый" сброс может быть огранизован по-разному, начиная от явного прописывания адреса перехода на вектор сброса и заканчивая сбросом средствами процессора - сторожевым таймером или специальными командами или установкой (сбросом) специальных битов в регистрах спец. функций. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 1 21 декабря, 2006 Опубликовано 21 декабря, 2006 · Жалоба В бутлоадере исплользовал такое объявление функции: void (*start_application)( void ) = 0x0000; //pointer to application Далее, в произвольном месте программы, мы можем ее вызвать и соответственно перейти по адресу 0. RAM зачем расходовать попусту? Сразу и пишите. (void (*)(void))(0x0000)(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 22 декабря, 2006 Опубликовано 22 декабря, 2006 · Жалоба В бутлоадере исплользовал такое объявление функции: void (*start_application)( void ) = 0x0000; //pointer to application Далее, в произвольном месте программы, мы можем ее вызвать и соответственно перейти по адресу 0. RAM зачем расходовать попусту? Сразу и пишите. (void (*)(void))(0x0000)(); Спасибо! Я не задумывался об этом. Теперь буду знать. А компилятор не оптимизирует, приведенное мной выражение? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 22 декабря, 2006 Опубликовано 22 декабря, 2006 · Жалоба А компилятор не оптимизирует, приведенное мной выражение? Нет. Компилятор создаст в RAM указатель на функцию, а уж что с ним дальше произойдет - не его дело. Может быть, Вы ему не 0, а другое какое-нибудь значение перед вызовом присвоить захотите. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 1 22 декабря, 2006 Опубликовано 22 декабря, 2006 · Жалоба А компилятор не оптимизирует, приведенное мной выражение? Написан обычный вызов функции, только адрес указан явно 0x0000(); вместо name();. Никаким образом "заоптимизировать" его компилятор не может, ибо как минимум ничего не знает о теле вызываемой функции :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jorikdima 0 22 декабря, 2006 Опубликовано 22 декабря, 2006 · Жалоба ну в данном то случае и goto() подойдет, верно? описался, имел ввиду goto - ключевое слово С, а не goto() Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 1 22 декабря, 2006 Опубликовано 22 декабря, 2006 · Жалоба ну в данном то случае и goto() подойдет, верно? ????? О чем это ????? Не понимаю совсем. #define goto( addr ) ((void (*)(void))(addr))() Или о чем? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jorikdima 0 22 декабря, 2006 Опубликовано 22 декабря, 2006 · Жалоба Тормознул goto ведь на метку идет, а не по адресу. Вот если метку моставить туда куда идти надо (на main() например), то можно просто goto Label; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 1 22 декабря, 2006 Опубликовано 22 декабря, 2006 · Жалоба от если метку моставить туда куда идти надо (на main() например), то можно просто goto Label; Ну-ну область видимости меток ограничена :), по понятным причинам, и за пределы функции уж точно не выпрыгните. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_artem_ 0 22 декабря, 2006 Опубликовано 22 декабря, 2006 · Жалоба У прямого перехода по адресу есть свои минусы - не происходит внутреннего резета процессора , что в некоторых слючаях желательно. watchdog или соединение ресета с одним из gpio можно попробовать в этом случае. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Bill 0 22 декабря, 2006 Опубликовано 22 декабря, 2006 · Жалоба от если метку моставить туда куда идти надо (на main() например), то можно просто goto Label; Ну-ну область видимости меток ограничена :), по понятным причинам, и за пределы функции уж точно не выпрыгните. Можно использовать функции setjmp() и longjmp(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 1 22 декабря, 2006 Опубликовано 22 декабря, 2006 · Жалоба Можно использовать функции setjmp() и longjmp(). Для описанного случая нельзя :) setjmp() текущий pc и стек сохраняет а не устанавливает какой хочется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Bill 0 22 декабря, 2006 Опубликовано 22 декабря, 2006 (изменено) · Жалоба Можно использовать функции setjmp() и longjmp(). Для описанного случая нельзя :) setjmp() текущий pc и стек сохраняет а не устанавливает какой хочется. Я имел в виду переход между функцииями. setjmp() запоминает стек и PC точки перехода в буфере, переход в эту точку происходит путем вызова функции longjmp(). Изменено 22 декабря, 2006 пользователем _Bill Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться