ivainc1789 0 8 июля, 2007 Опубликовано 8 июля, 2007 · Жалоба В многофайловой Си необходимо в одном из файлов по результатам выполнения функции выполнить перезагрузку контроллера AVR. Т.е. перейти по адресу 0h. Что-то сходу не могу разобраться как грамотно это сделать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 8 июля, 2007 Опубликовано 8 июля, 2007 · Жалоба Чтобы сделать перезагрузку полностью с внутренней периферией есть как минимум два пути: 1. дёрнуть в ноль свободным выводом ногу RESET; 2. запустить вотчдог на минимальное время и не сбрасывать его (зациклиться). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 8 июля, 2007 Опубликовано 8 июля, 2007 · Жалоба Чтобы сделать перезагрузку полностью с внутренней периферией есть как минимум два пути: 1. дёрнуть в ноль свободным выводом ногу RESET; так делать нельзя... По крайней мере Atmel на этот счет говорит четко, НИЗЯ! 2. запустить вотчдог на минимальное время и не сбрасывать его (зациклиться). Это единственный способ работу которого гарантирует Atmel. Единственно с минимальным временем нужно осторожнее, чтобы случайно не оказаться в вечном ресете. Есть правда еще один способ: - запрещаем прерывания - выключаем все запущенные модули - сбрасываем флаги всех прерываний - делаем jmp 0 Но это конечно длинный путь и легко чего-нить не предусмотреть... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jorikdima 0 9 июля, 2007 Опубликовано 9 июля, 2007 · Жалоба объявить указатель на функцию с адресом 0 вызвать ее Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ivainc1789 0 9 июля, 2007 Опубликовано 9 июля, 2007 · Жалоба - делаем jmp 0 Можно пример? Ассемблерная вставка? Или у компилятора есть спец. средства для этого? Я нашел только: __indirect_jump_to 0x00 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 9 июля, 2007 Опубликовано 9 июля, 2007 · Жалоба объявить указатель на функцию с адресом 0 вызвать ее Насколько я знаю, это будет работать не во всех компиляторах. (не для всех процессоров/моделей памяти/опций линкера по распределению памяти) Ассемблерная вставка?Например Или у компилятора есть спец. средства для этого? Я нашел только: __indirect_jump_to 0x00Indirect 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(); выключается соответствующий модуль и сбрасываются флаги прерываний Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jorikdima 0 9 июля, 2007 Опубликовано 9 июля, 2007 · Жалоба Можно пример? Ассемблерная вставка? Или у компилятора есть спец. средства для этого? Я нашел только: __indirect_jump_to 0x00 http://electronix.ru/forum/index.php?showt...147&hl=goto Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
spf 0 9 июля, 2007 Опубликовано 9 июля, 2007 · Жалоба Можно пример? Ассемблерная вставка? Или у компилятора есть спец. средства для этого? Я нашел только: __indirect_jump_to 0x00 В общем виде для Си: void (*soft_reset)(void) = 0x00; (*soft_reset)(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KRS 1 9 июля, 2007 Опубликовано 9 июля, 2007 · Жалоба Единственно с минимальным временем нужно осторожнее, чтобы случайно не оказаться в вечном ресете. Что значит в вечном ресете? После перезагрузки вотчдог отключится! (если конечно фьюзы не стоят соотв.) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 9 июля, 2007 Опубликовано 9 июля, 2007 · Жалоба так делать нельзя... По крайней мере Atmel на этот счет говорит четко, НИЗЯ! Ну разумеется не так буквально, как я написал. Естественно нужно соблюсти требования по длительности сигнала RESET. Один из таких способов - перестать сбрасывать внешний вотчдог. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arttab 0 9 июля, 2007 Опубликовано 9 июля, 2007 · Жалоба нормаль по собаке сделал. дог по условию сбрасываю, а когда надо мк перезапустить, то нарушаю условие сброса. и все (немножко подождать) и мк рестартанет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 141 9 июля, 2007 Опубликовано 9 июля, 2007 · Жалоба В общем виде для Си: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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 9 июля, 2007 Опубликовано 9 июля, 2007 · Жалоба Что значит в вечном ресете? После перезагрузки вотчдог отключится! (если конечно фьюзы не стоят соотв.) Вы правы но лишь частично... Во первых, как Вы правильно заметили (если конечно фьюзы не стоят соотв.) Во вторых даже при отключенных соответствующих фузах в более новых 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: .......................... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 9 июля, 2007 Опубликовано 9 июля, 2007 · Жалоба Использую оба решения, но при использовании программного сброса легко упустить инициализацию портов. Например, оставить на выход сигналы программного I2C. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 9 июля, 2007 Опубликовано 9 июля, 2007 · Жалоба Тот же ход для 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 ничего по воле компилятора уже поменятся не может... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться