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

Как это делается средствами Си или IAR C

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

 

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

 

На Си я делаю это так:

asm("jmp 0"); // Начать сначала

 

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

 

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

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


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

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

 

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

 

На Си я делаю это так:

asm("jmp 0"); // Начать сначала

 

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

 

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

В бутлоадере исплользовал такое объявление функции:

void (*start_application)( void ) = 0x0000;     //pointer to application
                                                //at flash start

Далее, в произвольном месте программы, мы можем ее вызвать и соответственно перейти по адресу 0.

З.Ы. Работает. Использую компилятор GCC.

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


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

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

 

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

 

На Си я делаю это так:

asm("jmp 0"); // Начать сначала

 

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

 

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

Переносимого в рамках языка способа нет. Все очень зависит от целевого проца и кросс-компилятора. В некоторых процах есть специальные команды для глобального сброса. Сброс, также, может поддерживаться компилятором путем различного рода расширений языка. В конце концов, сбросы тоже разные бывают - "холодные", "теплые". Для "холодного" можно просто завести внешнюю ногу Reset на один из пинов МК и принудильно самого себя сбрасывать. "Теплый" сброс может быть огранизован по-разному, начиная от явного прописывания адреса перехода на вектор сброса и заканчивая сбросом средствами процессора - сторожевым таймером или специальными командами или установкой (сбросом) специальных битов в регистрах спец. функций.

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


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

В бутлоадере исплользовал такое объявление функции:

void (*start_application)( void ) = 0x0000; //pointer to application

Далее, в произвольном месте программы, мы можем ее вызвать и соответственно перейти по адресу 0.

RAM зачем расходовать попусту? Сразу и пишите.

(void (*)(void))(0x0000)();

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


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

В бутлоадере исплользовал такое объявление функции:

void (*start_application)( void ) = 0x0000; //pointer to application

Далее, в произвольном месте программы, мы можем ее вызвать и соответственно перейти по адресу 0.

RAM зачем расходовать попусту? Сразу и пишите.

(void (*)(void))(0x0000)();

Спасибо! Я не задумывался об этом. Теперь буду знать. А компилятор не оптимизирует, приведенное мной выражение?

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


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

А компилятор не оптимизирует, приведенное мной выражение?

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

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


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

А компилятор не оптимизирует, приведенное мной выражение?

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

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


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

ну в данном то случае и goto() подойдет, верно?

 

 

описался, имел ввиду goto - ключевое слово С, а не goto()

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


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

ну в данном то случае и goto() подойдет, верно?

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

 

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

 

Или о чем?

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


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

Тормознул :biggrin::biggrin:

goto ведь на метку идет, а не по адресу.

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

goto Label;

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


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

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

goto Label;

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

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


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

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

watchdog или соединение ресета с одним из gpio можно попробовать в этом случае.

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


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

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

goto Label;

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

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

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


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

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

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

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


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

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

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

Я имел в виду переход между функцииями. setjmp() запоминает стек и PC точки перехода в буфере, переход в эту точку происходит путем вызова функции longjmp().

Изменено пользователем _Bill

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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