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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Как сделать перезагрузку программно?, сходу не смог понять
ivainc1789
сообщение Jul 8 2007, 20:00
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807



В многофайловой Си необходимо в одном из файлов по результатам выполнения функции выполнить перезагрузку контроллера AVR. Т.е. перейти по адресу 0h. Что-то сходу не могу разобраться как грамотно это сделать?
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Jul 8 2007, 21:03
Сообщение #2


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Чтобы сделать перезагрузку полностью с внутренней периферией есть как минимум два пути:
1. дёрнуть в ноль свободным выводом ногу RESET;
2. запустить вотчдог на минимальное время и не сбрасывать его (зациклиться).
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jul 8 2007, 22:49
Сообщение #3


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(IgorKossak @ Jul 9 2007, 01:03) *
Чтобы сделать перезагрузку полностью с внутренней периферией есть как минимум два пути:
1. дёрнуть в ноль свободным выводом ногу RESET;

так делать нельзя...
По крайней мере Atmel на этот счет говорит четко, НИЗЯ!
Цитата
2. запустить вотчдог на минимальное время и не сбрасывать его (зациклиться).

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

Есть правда еще один способ:
- запрещаем прерывания
- выключаем все запущенные модули
- сбрасываем флаги всех прерываний
- делаем jmp 0
Но это конечно длинный путь и легко чего-нить не предусмотреть...
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Jul 9 2007, 04:43
Сообщение #4


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



объявить указатель на функцию с адресом 0

вызвать ее
Go to the top of the page
 
+Quote Post
ivainc1789
сообщение Jul 9 2007, 05:08
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807



Цитата(singlskv @ Jul 9 2007, 02:49) *
- делаем jmp 0

Можно пример? Ассемблерная вставка? Или у компилятора есть спец. средства для этого? Я нашел только: __indirect_jump_to 0x00
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jul 9 2007, 05:39
Сообщение #6


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(jorikdima @ Jul 9 2007, 08:43) *
объявить указатель на функцию с адресом 0
вызвать ее

Насколько я знаю, это будет работать не во всех компиляторах.
(не для всех процессоров/моделей памяти/опций линкера по распределению памяти)



Цитата(ivainc1789 @ Jul 9 2007, 09:08) *
Ассемблерная вставка?
Например
Цитата
Или у компилятора есть спец. средства для этого? Я нашел только: __indirect_jump_to 0x00
Indirect jump - это через регистр Z, вполне подойдет если он есть в IAR.

Вот пример, правда для WinAVR:
Код
//-------------------------------------------------------------------
// Перезагрузка (рестарт с адреса 0)
//-------------------------------------------------------------------

void Reset()
{
  __asm__ __volatile__ ("cli");  // запретить прерывания
               // останавливаем всю переферию
  SysTimerStop();
  AdcStop();
  SpiStop();
  PwmStop();
  PortsReset();
  I2cStop();
               // переходим на адрес 0
  __asm__ __volatile__("ldi r30,0\n\t"\
                       "ldi r31,0\n\t"\
                       "ijmp");
}

в каждом xxxStop(); выключается соответствующий модуль и сбрасываются флаги прерываний
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Jul 9 2007, 05:44
Сообщение #7


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



Цитата(ivainc1789 @ Jul 9 2007, 09:08) *
Можно пример? Ассемблерная вставка? Или у компилятора есть спец. средства для этого? Я нашел только: __indirect_jump_to 0x00

http://electronix.ru/forum/index.php?showt...147&hl=goto
Go to the top of the page
 
+Quote Post
spf
сообщение Jul 9 2007, 05:46
Сообщение #8


Странник
****

Группа: Свой
Сообщений: 766
Регистрация: 29-08-05
Из: Екатеринбург
Пользователь №: 8 051



Цитата(ivainc1789 @ Jul 9 2007, 11:08) *
Можно пример? Ассемблерная вставка? Или у компилятора есть спец. средства для этого? Я нашел только: __indirect_jump_to 0x00

В общем виде для Си:
Код
void (*soft_reset)(void) = 0x00;
(*soft_reset)();


--------------------
"Как много есть на свете вещей, которые мне не нужны!" Сократ
Go to the top of the page
 
+Quote Post
KRS
сообщение Jul 9 2007, 07:21
Сообщение #9


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(singlskv @ Jul 9 2007, 02:49) *
Единственно с минимальным временем нужно осторожнее, чтобы
случайно не оказаться в вечном ресете.

Что значит в вечном ресете?
После перезагрузки вотчдог отключится! (если конечно фьюзы не стоят соотв.)
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Jul 9 2007, 08:03
Сообщение #10


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(singlskv @ Jul 9 2007, 01:49) *
так делать нельзя...
По крайней мере Atmel на этот счет говорит четко, НИЗЯ!

Ну разумеется не так буквально, как я написал.
Естественно нужно соблюсти требования по длительности сигнала RESET.
Один из таких способов - перестать сбрасывать внешний вотчдог.
Go to the top of the page
 
+Quote Post
arttab
сообщение Jul 9 2007, 08:27
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 432
Регистрация: 7-12-04
Из: Новосибирск
Пользователь №: 1 371



нормаль по собаке сделал.
дог по условию сбрасываю, а когда надо мк перезапустить, то нарушаю условие сброса. и все (немножко подождать) и мк рестартанет.


--------------------
OrCAD, Altium,IAR, AVR....
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 9 2007, 08:31
Сообщение #12


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(spf @ Jul 9 2007, 08:46) *
В общем виде для Си:
Код
void (*soft_reset)(void) = 0x00;
(*soft_reset)();
или soft_reset(); поскольку в С единственное легальное действие с указателем на функцию - это вызов функции. Конкретно для IAR есть еще одно решение:
Код
extern void Reset();  // если С++ - extern "C" void Reset()
void Test
{

   Reset();
}
Project->Options->Linker->Extra Options -DReset=0x0000
Тот же ход для WinAVR:
Код
extern void Reset();  // если С++ - extern "C" void Reset()
Project->Options->Linker->Add
-Wl,--defsym,Reset=0x0000
или в Makefile
LDFLAGS += -Wl,--defsym,Reset=0x0000


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jul 9 2007, 09:01
Сообщение #13


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(KRS @ Jul 9 2007, 11:21) *
Что значит в вечном ресете?
После перезагрузки вотчдог отключится! (если конечно фьюзы не стоят соотв.)

Вы правы но лишь частично...
Во первых, как Вы правильно заметили (если конечно фьюзы не стоят соотв.)
Во вторых даже при отключенных соответствующих фузах в более новых
AVR Watchdog работает чуть-чуть иначе.
Вот кусочек даташита на Atmega48/88/168:
Note: If the Watchdog is accidentally enabled, for example by a runaway pointer or brown-out
condition, the device will be reset and the Watchdog Timer will stay enabled. If the code is not
set up to handle the Watchdog, this might lead to an eternal loop of time-out resets. To avoid this
situation, the application software should always clear the Watchdog System Reset Flag
(WDRF) and the WDE control bit in the initialisation routine, even if the Watchdog is not in use.


А вот тоже самое переведенное с английского на английский в руководстве
avr-libc для WinAVR:
Note that for newer devices (ATmega88 and newer, effectively any AVR that has the option
to also generate interrupts), the watchdog timer remains active even after a system
reset (except a power-on condition), using the fastest prescaler value (approximately
15 ms). It is therefore required to turn off the watchdog early during program startup,
the datasheet recommends a sequence like the following:
..........................
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jul 9 2007, 09:01
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



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


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jul 9 2007, 09:16
Сообщение #15


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Сергей Борщ @ Jul 9 2007, 12:31) *
Тот же ход для WinAVR:
Код
extern void Reset();  // если С++ - extern "C" void Reset()
Project->Options->Linker->Add
-Wl,--defsym,Reset=0x0000
или в Makefile
LDFLAGS += -Wl,--defsym,Reset=0x0000

Сергей, а это проверенное решение для WinAVR ?
Оно одинаково работает на контроллерах с call/rcall и тех у которых только rcall ?

Дело в том что именно с WinAVR у меня была проблема на mega8 с вызовом
функции адрес которой назначен 0x0000.
В итоге и написал через asm вставки (см. выше).
В inderect jump ничего по воле компилятора уже поменятся не может...
Go to the top of the page
 
+Quote Post

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

 


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


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