|
Как сделать перезагрузку программно?, сходу не смог понять |
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 21)
|
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 ничего по воле компилятора уже поменятся не может...
|
|
|
|
|
Jul 9 2007, 10:12
|

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

|
Цитата(singlskv @ Jul 9 2007, 12:16)  Сергей, а это проверенное решение для WinAVR ? Оно одинаково работает на контроллерах с call/rcall и тех у которых только rcall ? Оно проверено на вызове загрузчика, который живет по адресу 0x1800 и другой функции по другому адресу. Конкретно на адрес 0x0000 не переходил, но не вижу особой разницы - с точки зрения компилятора это вызов обычной функции, о расположении которой он ничего не знает и не должен знать. С точки зрения линкера адреса функций - обычные symbols, ему тоже все равно чему этот адрес равен конкретно. А опцией -Wl мы просто ему говорим "этот символ (метку) мы определили за тебя" Цитата(singlskv @ Jul 9 2007, 12:16)  В inderect jump ничего по воле компилятора уже поменятся не может... Да, но оно требует загрузки R30:R31 и IJMP вместо обычного ®JMP.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jul 9 2007, 10:44
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата Можно по подобней, аппарвтный сброс еще никто не запрещал, ИМХО. Вот официальное мнение Atmel по этому вопросу: Software Reset Question How can I reset my AVR through software?
Answer If you want to perform a software reset of your AVR you should use the internal Watchdog. Simply enable it and let it time out. When the Watchdog triggers it resets the program counter back to 0, clears all the registers and performs all the other tasks. This operation gives the same result as pulling the RESET line low.
You should not try to: - Use another pin of the AVR to pull the external RESET line. The pins of the AVR are tristated halfway through the minimum reset time, this releases the RESET line and hence nothing happens. - Jump to program location 0. Jumping to program location 0 does not clear all the registers and hence you do not have a "clean" reset.Цитата(Сергей Борщ @ Jul 9 2007, 14:12)  Оно проверено на вызове загрузчика, который живет по адресу 0x1800 и другой функции по другому адресу. Конкретно на адрес 0x0000 не переходил, но не вижу особой разницы - с точки зрения компилятора это вызов обычной функции, о расположении которой он ничего не знает и не должен знать. С точки зрения линкера адреса функций - обычные symbols, ему тоже все равно чему этот адрес равен конкретно. А опцией -Wl мы просто ему говорим "этот символ (метку) мы определили за тебя Вот в этом и вопрос знает или не знает ? линкер должен знать  Попробую найти/воспроизвести код с "неправильным" вызовом функции по адресу 0x0000, а потом попробую Ваш вариант. Цитата "Да, но оно требует загрузки R30:R31 и IJMP вместо обычного ®JMP. Ну вроде как в IAR для этого можно воспользоваться "__z" ?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|