|
Как сделать перезагрузку программно?, сходу не смог понять |
|
|
|
Jul 8 2007, 22:49
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(IgorKossak @ Jul 9 2007, 01:03)  Чтобы сделать перезагрузку полностью с внутренней периферией есть как минимум два пути: 1. дёрнуть в ноль свободным выводом ногу RESET; так делать нельзя... По крайней мере Atmel на этот счет говорит четко, НИЗЯ! Цитата 2. запустить вотчдог на минимальное время и не сбрасывать его (зациклиться). Это единственный способ работу которого гарантирует Atmel. Единственно с минимальным временем нужно осторожнее, чтобы случайно не оказаться в вечном ресете. Есть правда еще один способ: - запрещаем прерывания - выключаем все запущенные модули - сбрасываем флаги всех прерываний - делаем jmp 0 Но это конечно длинный путь и легко чего-нить не предусмотреть...
|
|
|
|
|
Jul 9 2007, 05:39
|
дятел
    
Группа: Свой
Сообщений: 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(); выключается соответствующий модуль и сбрасываются флаги прерываний
|
|
|
|
|
Jul 9 2007, 05:46
|

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

|
Цитата(ivainc1789 @ Jul 9 2007, 11:08)  Можно пример? Ассемблерная вставка? Или у компилятора есть спец. средства для этого? Я нашел только: __indirect_jump_to 0x00 В общем виде для Си: Код void (*soft_reset)(void) = 0x00; (*soft_reset)();
--------------------
"Как много есть на свете вещей, которые мне не нужны!" Сократ
|
|
|
|
|
Jul 9 2007, 08:31
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Jul 9 2007, 09:01
|
дятел
    
Группа: Свой
Сообщений: 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: ..........................
|
|
|
|
|
Jul 9 2007, 09:16
|
дятел
    
Группа: Свой
Сообщений: 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 ничего по воле компилятора уже поменятся не может...
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|