1100.1010.1011.1010
Apr 6 2011, 21:44
Написана простенькая програмка работы с портами ввода/вывода(WinAvr).(последовательно и в определенном порядке включает релюшки). Предусмотрено внешнее прерывание (аварийно отключает релюшки). После наступления прерывания (аварии) необходимо заново проделывать всю программу сначала.Как это сделать?Не дергать же портом ножку ресет?))
Смотря какой процессор и какая у вас конфигурация.
Если xmega, там есть программный ресет.
Если используется вочдог, можно вызвать ресет бесконечным циклом.
Если не то и не другое, запретить прерывания, настроить стек (если он в начале программы не настраивается), сбросить все настройки периферии (особенно разрешения прерываний), которые могут помешать вашей программе (если авария, может, и периферия расстроена?), и уйти на вектор ресета (0 или бутлоадер)
1100.1010.1011.1010
Apr 7 2011, 05:18
ATtiny25.С вочдогом интересная идея,нужно будет попробовать. Примерный код обработчика прерывания
ISR(INT0_vect)
{
SetBit(PORTB,RBT);
_delay_ms(100);
ClearBit(PORTB,RBT);
ClearBit(PORTB,K1);
//здесь сделать ресет
}
Подскажите как уйти на 0x0000 средствами WinAvr?
Цитата(1100.1010.1011.1010 @ Apr 7 2011, 09:18)

Подскажите как уйти на 0x0000 средствами WinAvr?
Так же, как и на любом другом трансляторе
Код
void (* Reset)(void)= (void *)0;
........
Reset();
1100.1010.1011.1010
Apr 7 2011, 10:13
чудеса,работает!спасбо!Не могли бы вы пояснить код?как он работает?
Цитата(1100.1010.1011.1010 @ Apr 7 2011, 14:13)

Не могли бы вы пояснить код?
Ну, собственно, тут-то всего две строчки: 1) определяем указатель на функцию со значением ноль 2) вызываем функцию по указателю, т.е. переходим на выполнение функции, код которой якобы расположен с адреса ноль.
Хочу обратить внимание, что с помощью WDT - "честный" сброс МК, а код, приведенный мною - всего лишь "перезапуск" программы. Т.е. устройства, которые в этот момент работали - будут продолжать работать (например, USART - выдавать/принимать данные), что не всегда допустимо!
1100.1010.1011.1010
Apr 7 2011, 11:08
C WDT понятно.Не совсем понял (и не нашел в нете) синтаксис функции.
void (*function)(void) * это знак нулевой функции?
и что означает (void *)0;
и где бы почитать про такие фенкции?
Цитата(1100.1010.1011.1010 @ Apr 7 2011, 15:08)

Не совсем понял (и не нашел в нете) синтаксис функции.
Это - указатель на функцию - т.е. ячейка памяти, которая содержит адрес начала функции. Этому указателю присваиваем нулевое значение (вернее - указатель на нулевой адрес). При обращении к функции по указателю МК перейдет на команду с адресом равным значению указателя функции - в данном случае: указан адрес 0 как адрес начала функции.
Код
#include <avr/wdt.h>
#include <avr/interrupt.h>
__attribute__((noreturn)) void restart(void)
{
cli();
wdt_reset();
wdt_enable(WDTO_15MS);
for(;;); // Die, die my darling!
}
1100.1010.1011.1010
Apr 8 2011, 15:54
Тоже прошу немного пояснить ...
SysRq, скажите, а зачем нужен wdt_reset() после cli?
Если расчет берется на то, что прежний установленный интервал был велик, то тогда wdt_reset() имел бы смысл только после wdt_enable(WDTO_15MS), и то сомнительно. А так я не вижу от него никакого толка.
Цитата(1100.1010.1011.1010 @ Apr 8 2011, 19:54)

Тоже прошу немного пояснить ...
Ну, Вы, блин, даёте... Запретить прерывания; настроить WDT; уйти в бесконечный цикл; поскольку WDT сбрасывать никто не собирается, то через некоторое время WDT перезапустит МК...
1100.1010.1011.1010
Apr 8 2011, 16:29
Палыч,то что вы пояснили как раз понятно.Не все ясно с __attribute__((noreturn)) void restart(void)
Цитата(Xenia @ Apr 8 2011, 19:59)

скажите, а зачем нужен wdt_reset() после cli?
В данном случае - не нужен. Просто кусочек программы взят из DS из примера "нормального" запуска WDT
Цитата(1100.1010.1011.1010 @ Apr 8 2011, 20:29)

Палыч,то что вы пояснили как раз понятно.Не все ясно с __attribute__((noreturn)) void restart(void)
Из функции нет возврата управления
Цитата(Xenia @ Apr 8 2011, 19:59)

SysRq, скажите, а зачем нужен wdt_reset() после cli?
Вы правы, пожалуй. Не нужен он. Уберём-с

--
Цитата(1100.1010.1011.1010 @ Apr 8 2011, 20:29)

Не все ясно с __attribute__((noreturn)) void restart(void)
Функция с таким атрибутом имеет пролог поменьше, стека расходует меньше, т.к. не сохраняет call-saved регситры -> выполняется быстрее, и проще учитывать необходимый размер стека.
Цитата(SysRq @ Apr 8 2011, 21:29)

Функция с таким атрибутом имеет пролог поменьше, стека расходует меньше, т.к. не сохраняет call-saved регситры -> выполняется быстрее, и проще учитывать необходимый размер стека.
А вы в самом деле уверены, что cli(), wdt_reset(), wdt_enable(WDTO_15MS) - функции? На мой взгляд, в вашей программе нет никаких call и регистры в ней тоже не используются

.
Цитата(Xenia @ Apr 8 2011, 21:38)

А вы в самом деле уверены, что cli(), wdt_reset(), wdt_enable(WDTO_15MS) - функции? На мой взгляд, в вашей программе нет никаких call и регистры в ней тоже не используются

.
Из соседней единицы компиляции может быть не видно
demiurg_spb
Apr 10 2011, 15:58
Цитата(Палыч @ Apr 7 2011, 11:35)

Код
void (* Reset)(void)= (void *)0;
........
Reset();
Можно проще
Код
(*(void(*)(void))(0x0000))();
но разумней использовать перезагрузку по WDT, т.к. после реального ресета все регистры принимают значения по умолчанию, что весьма и весьма полезно.
1100.1010.1011.1010
Apr 13 2011, 17:40
Спасибо,за ответы!Разобрался,устройство запустил!
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.