Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как это делается средствами Си или IAR C
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
SasaVitebsk
При программировании однокристалок иногда приходится обрабатывать глобальные ошибки. Или, к примеру, реагировать на существенное изменение конфигурации.

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

На Си я делаю это так:
asm("jmp 0"); // Начать сначала

У меня это единственный оператор ASM на всё прогу. Может существует специальный вызов для IAR, что-то вроде __restart(); ?

И ещё один вопрос. Компилятор вопреки моему мнению скомпилировал его не в jmp. Это зачем?
haker_fox
Цитата(SasaVitebsk @ Dec 21 2006, 07:24) *
При программировании однокристалок иногда приходится обрабатывать глобальные ошибки. Или, к примеру, реагировать на существенное изменение конфигурации.

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

На Си я делаю это так:
asm("jmp 0"); // Начать сначала

У меня это единственный оператор ASM на всё прогу. Может существует специальный вызов для IAR, что-то вроде __restart(); ?

И ещё один вопрос. Компилятор вопреки моему мнению скомпилировал его не в jmp. Это зачем?

В бутлоадере исплользовал такое объявление функции:
Код
void (*start_application)( void ) = 0x0000;     //pointer to application
                                                //at flash start

Далее, в произвольном месте программы, мы можем ее вызвать и соответственно перейти по адресу 0.
З.Ы. Работает. Использую компилятор GCC.
dxp
Цитата(SasaVitebsk @ Dec 21 2006, 05:24) *
При программировании однокристалок иногда приходится обрабатывать глобальные ошибки. Или, к примеру, реагировать на существенное изменение конфигурации.

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

На Си я делаю это так:
asm("jmp 0"); // Начать сначала

У меня это единственный оператор ASM на всё прогу. Может существует специальный вызов для IAR, что-то вроде __restart(); ?

И ещё один вопрос. Компилятор вопреки моему мнению скомпилировал его не в jmp. Это зачем?

Переносимого в рамках языка способа нет. Все очень зависит от целевого проца и кросс-компилятора. В некоторых процах есть специальные команды для глобального сброса. Сброс, также, может поддерживаться компилятором путем различного рода расширений языка. В конце концов, сбросы тоже разные бывают - "холодные", "теплые". Для "холодного" можно просто завести внешнюю ногу Reset на один из пинов МК и принудильно самого себя сбрасывать. "Теплый" сброс может быть огранизован по-разному, начиная от явного прописывания адреса перехода на вектор сброса и заканчивая сбросом средствами процессора - сторожевым таймером или специальными командами или установкой (сбросом) специальных битов в регистрах спец. функций.
zltigo
Цитата(haker_fox @ Dec 21 2006, 04:49) *
В бутлоадере исплользовал такое объявление функции:
void (*start_application)( void ) = 0x0000; //pointer to application
Далее, в произвольном месте программы, мы можем ее вызвать и соответственно перейти по адресу 0.

RAM зачем расходовать попусту? Сразу и пишите.
(void (*)(void))(0x0000)();
haker_fox
Цитата(zltigo @ Dec 21 2006, 15:45) *
Цитата(haker_fox @ Dec 21 2006, 04:49) *

В бутлоадере исплользовал такое объявление функции:
void (*start_application)( void ) = 0x0000; //pointer to application
Далее, в произвольном месте программы, мы можем ее вызвать и соответственно перейти по адресу 0.

RAM зачем расходовать попусту? Сразу и пишите.
(void (*)(void))(0x0000)();

Спасибо! Я не задумывался об этом. Теперь буду знать. А компилятор не оптимизирует, приведенное мной выражение?
aaarrr
Цитата(haker_fox @ Dec 22 2006, 05:19) *
А компилятор не оптимизирует, приведенное мной выражение?

Нет. Компилятор создаст в RAM указатель на функцию, а уж что с ним дальше произойдет - не его дело. Может быть, Вы ему не 0, а другое какое-нибудь значение перед вызовом присвоить захотите.
zltigo
Цитата(haker_fox @ Dec 22 2006, 04:19) *
А компилятор не оптимизирует, приведенное мной выражение?

Написан обычный вызов функции, только адрес указан явно 0x0000(); вместо name();. Никаким образом "заоптимизировать" его компилятор не может, ибо как минимум ничего не знает о теле вызываемой функции smile.gif
jorikdima
ну в данном то случае и goto() подойдет, верно?


описался, имел ввиду goto - ключевое слово С, а не goto()
zltigo
Цитата(jorikdima @ Dec 22 2006, 11:20) *
ну в данном то случае и goto() подойдет, верно?

????? О чем это ????? Не понимаю совсем.

#define goto( addr ) ((void (*)(void))(addr))()

Или о чем?
jorikdima
Тормознул biggrin.gif biggrin.gif
goto ведь на метку идет, а не по адресу.
Вот если метку моставить туда куда идти надо (на main() например), то можно просто
goto Label;
zltigo
Цитата(jorikdima @ Dec 22 2006, 14:30) *
от если метку моставить туда куда идти надо (на main() например), то можно просто
goto Label;

Ну-ну область видимости меток ограничена smile.gif, по понятным причинам, и за пределы функции уж точно не выпрыгните.
_artem_
У прямого перехода по адресу есть свои минусы - не происходит внутреннего резета процессора , что в некоторых слючаях желательно.
watchdog или соединение ресета с одним из gpio можно попробовать в этом случае.
_Bill
Цитата(zltigo @ Dec 22 2006, 16:17) *
Цитата(jorikdima @ Dec 22 2006, 14:30) *

от если метку моставить туда куда идти надо (на main() например), то можно просто
goto Label;

Ну-ну область видимости меток ограничена smile.gif, по понятным причинам, и за пределы функции уж точно не выпрыгните.

Можно использовать функции setjmp() и longjmp().
zltigo
Цитата(_Bill @ Dec 22 2006, 16:37) *
Можно использовать функции setjmp() и longjmp().

Для описанного случая нельзя smile.gif setjmp() текущий pc и стек сохраняет а не устанавливает какой хочется.
_Bill
Цитата(zltigo @ Dec 22 2006, 18:41) *
Цитата(_Bill @ Dec 22 2006, 16:37) *

Можно использовать функции setjmp() и longjmp().

Для описанного случая нельзя smile.gif setjmp() текущий pc и стек сохраняет а не устанавливает какой хочется.

Я имел в виду переход между функцииями. setjmp() запоминает стек и PC точки перехода в буфере, переход в эту точку происходит путем вызова функции longjmp().
zltigo
Цитата(_Bill @ Dec 22 2006, 22:01) *
переход в эту точку происходит путем вызова функции longjmp().

А я о чем? Только о том, что прямо установить точку возврата невозможно.
SasaVitebsk
Цитата(haker_fox @ Dec 21 2006, 05:49) *
В бутлоадере исплользовал такое объявление функции:
Код
void (*start_application)( void ) = 0x0000;     //pointer to application
                                                //at flash start

Далее, в произвольном месте программы, мы можем ее вызвать и соответственно перейти по адресу 0.
З.Ы. Работает. Использую компилятор GCC.


Спасибо. Не додумался до такого. Прямолинейно мыслю, - переход значит переход! smile.gif

А в IAR, интересно, это выглядит так?

extern void start_application(void)@0x0000;

Спасибо также _bill. Не обратил внимания, теперь буду помнить. Думаю можно использовать по входу/выходу из sleep.

Всем остальным тоже спасибо. Буду переваривать и пробовать.
aaarrr
Цитата(SasaVitebsk @ Dec 25 2006, 01:53) *
А в IAR, интересно, это выглядит так?

extern void start_application(void)@0x0000;


Процитирую коллегу:

Цитата(zltigo @ Dec 21 2006, 10:45) *
RAM зачем расходовать попусту? Сразу и пишите.
(void (*)(void))(0x0000)();


Это наиболее правильный вариант.
zltigo
Цитата(aaarrr @ Dec 25 2006, 01:19) *
Процитирую коллегу:

Цитата(zltigo @ Dec 21 2006, 10:45) *

RAM зачем расходовать попусту? Сразу и пишите.
(void (*)(void))(0x0000)();


Это наиболее правильный вариант.


Сейчас глянул на цитируемое и понял, что в первом посте банально опечатался sad.gif и для полгого счастья скобочек не хватает. Во втором посте не ошибся, полностью универсально и переносимо так:
Код
((void (*)(void))(0x0000))();


1. Берем абстрактный 0
2.....делаем из него указатель (*)0
3. ... на функцию ((*)())0
4. ... без аргументов ((*)(void))0
5.... ничего не возвращающую (void(*)(void))0
6.... если вместо 0 какой-нибудь define выражение поставлять будут и забудут в выражении скобочки поставить,то для перестраховки ставим свои (void(*)(void))(0)
7. осталось вызвать функцию ((void(*)(void))(0))();
8. Это я все к тому, что на форуме уже был спор по подобному прводу со стенаниями "непонятно!!!","скобочки!!!", "звездочки!!!". Решил пошагово обьяснить.
IgorKossak
Цитата(zltigo @ Dec 25 2006, 11:38) *
8. Это я все к тому, что на форуме уже был спор по подобному прводу со стенаниями "непонятно!!!","скобочки!!!", "звездочки!!!". Решил пошагово обьяснить.

Стенают обычно те, кто вырос на Паскале.
У эмбеддеров такие вопросы не возникают.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.