WatchDog на Atmega328P

Обсуждаем контроллеры компании Atmel.
Ответить
boris911
Первый раз сказал Мяу!
Сообщения: 29
Зарегистрирован: Вт май 24, 2016 11:00:18

WatchDog на Atmega328P

Сообщение boris911 »

Почему-то не хочет заводиться собака на этом камне. Если сбросить бит WDE в ноль - светодиод мигает. Если установить в 1 - не мигает. И что странно, никакого эффекта не даёт изменение битов WDP3..0, ставлю от 1 до 8 секунд - ничего. Фьюз WDTON не программируется.
Где косяк? Помогите, пожалуйста!
Спойлер#include "_def.h"
#include "_var.h"
#include "head_files.h"

//--------------------------------------------------------------------MAIN FUNCTION---
int main()
{
//--------------------------------------------------------------***---INITIALISATION---***
InitLedPorts();
InitGTimers();
//инициализируем таймер
TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(0<<COM0B1)|(0<<COM0B0)|(1<<WGM01)|(0<<WGM00);
TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(1<<CS02)|(0<<CS01)|(0<<CS00);
OCR0A=62;
TIMSK0 = (0<<OCIE0B)|(1<<OCIE0A)|(0<<TOIE0);

SEI
//инициализируем собаку на 2 секунды
WDTCSR=(0<<WDIF)|(0<<WDIE)|(0<<WDCE)|(1<<WDE)|(0<<WDP3)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);

//------------------------------------------------------------------------------------
while(1) {
//-------------------------------
StartGTimer(timer_delay500);
if (GetGTimer(timer_delay500)==500) // период 500 мс
{
StopGTimer(timer_delay500);
StartGTimer(timer_delay500);
TestLedWhite(); //мигаем светодиодом
WDR //сбрасываем собаку
}

}//while
return 0;
}//main
//------------------------------------------------------------------------------END of MAIN---
Реклама
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Re: WatchDog на Atmega328P

Сообщение uk8amk »

Из всем известного документа с грифом "Совершенно секретно":
C Code Example(1)

Код: Выделить всё

void WDT_Prescaler_Change(void)
{
__disable_interrupt();
__watchdog_reset();
/* Start timed sequence */
WDTCSR |= (1<<WDCE) | (1<<WDE);
/* Set new prescaler(time-out) value = 64K cycles (~0.5 s) */
WDTCSR = (1<<WDE) | (1<<WDP2) | (1<<WDP0);
__enable_interrupt();
}
Реклама
boris911
Первый раз сказал Мяу!
Сообщения: 29
Зарегистрирован: Вт май 24, 2016 11:00:18

Re: WatchDog на Atmega328P

Сообщение boris911 »

uk8amk
Уже пробовал. Только чуть другую процедуру(WDT_off). Не помогает.
Насколько я понял, после первого срабатывания WD после перехода на нулевой адрес программы сбрасывается прескалер WD на минимальное значение (16 мс). Поэтому после ресета его надо сразу выключить, а потом опять включить на нужное время.
Но я не вижу срабатывания WD даже первый раз, если устанавливаю таймер на длительное время (4 или 8 секунд) и отключаю сброс (//WDR)..
Спойлер#include "_def.h"
//Глобальные переменные
#include "_var.h"
///*******************
#include "head_files.h"

//--------------------------------------------------------------------MAIN FUNCTION---
int main()
{
//--------------------------------------------------------------***---INITIALISATION---***
//-----выключение WD
CLI
WDR
/* Clear WDRF in MCUSR */
MCUSR &= ~(1<<WDRF);
/* Write logical one to WDCE and WDE */
/* Keep old prescaler setting to prevent unintentional time-out */
WDTCSR |= (1<<WDCE) | (1<<WDE);
/* Turn off WDT */
WDTCSR = 0x00;
SEI
//-----

InitLedPorts();
InitGTimers();

TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(0<<COM0B1)|(0<<COM0B0)|(1<<WGM01)|(1<<WGM00);
TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(1<<CS02)|(0<<CS01)|(0<<CS00);
OCR0A=62;
TIMSK0 = (0<<OCIE0B)|(1<<OCIE0A)|(0<<TOIE0);

SEI

//Включаем WD на 4 секунды
WDTCSR=(0<<WDIF)|(0<<WDIE)|(0<<WDCE)|(1<<WDE)|(0<<WDP3)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);

//------------------------------------------------------------------------------------
while(1) {
//-------------------------------


StartGTimer(timer_delay500);
if (GetGTimer(timer_delay500)==500)
{
StopGTimer(timer_delay500);
StartGTimer(timer_delay500);
TestLedWhite();
WDR //сброс WD
}

}//while
return 0;
}//main
//------------------------------------------------------------------------------END of MAIN---
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: WatchDog на Atmega328P

Сообщение Z_h_e »

• Bit 4 – WDCE: Watchdog Change Enable
This bit is used in timed sequences for changing WDE and prescaler bits. To clear the WDE bit, and/or change
the prescaler bits, WDCE must be set.
Once written to one, hardware will clear WDCE after four clock cycles.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Эиком - электронные компоненты и радиодетали
boris911
Первый раз сказал Мяу!
Сообщения: 29
Зарегистрирован: Вт май 24, 2016 11:00:18

Re: WatchDog на Atmega328P

Сообщение boris911 »

Z_h_e
Что у меня не так с этим битом?
Реклама
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: WatchDog на Atmega328P

Сообщение Z_h_e »

Это описание бита WDCE. Вроде там перевести то не сложно. Смысл: включение данного бита разрешает изменение битов WDE и WDPx. Данный бит продержится во включенном состоянии 4 такта и затем сбросится. Поэтому для изменения настроек собаки надо не только включать WDCE, но и запрещать прерывания, а программирую на ЯВУ смотреть за степенью оптимаизации иначе можно в 4 такта и не уложится.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
boris911
Первый раз сказал Мяу!
Сообщения: 29
Зарегистрирован: Вт май 24, 2016 11:00:18

Re: WatchDog на Atmega328P

Сообщение boris911 »

Z_h_e
Да перевести то несложно, а вот сообразить, что даже первая установка битов прескалера должна выполняться в указанном порядке, а не просто записью битов в регистр WDTCSR... ))) Благодарю!
А можно указать компилятору явно, чтобы он не оптимизировал определенные строки? Вроде авр студия не трогает их, но хотелось бы наверняка.
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: WatchDog на Atmega328P

Сообщение Z_h_e »

В ДШ же есть примеры кодов и на ассме и на С.
Как изменять уровень оптимизации для участков кода я не знаю. А для всей функции в ее прототипе используются атрибут.

Код: Выделить всё

__attribute__((optimize(0)))	//оптимизация 0
Это для компилятора GCC. У студии он. Но если выключить оптимизацию, как раз |= скомилируется в болшое количество команд.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
boris911
Первый раз сказал Мяу!
Сообщения: 29
Зарегистрирован: Вт май 24, 2016 11:00:18

Re: WatchDog на Atmega328P

Сообщение boris911 »

Угу, всё так и есть. Пример из даташита для асма - 3 такта:
Спойлерlds r16, WDTCSR
ori r16, (1<<WDCE) | (1<<WDE)
sts WDTCSR, r16
; -- Got four cycles to set the new values from here -
; Set new prescaler(time-out) value = 64K cycles (~0.5 s)
ldi r16, (1<<WDE) | (1<<WDP2) | (1<<WDP0)
sts WDTCSR, r16
А вот что дает дизассемблер сишного оптимизированного кода - тоже 3 такта (LDI+STS):
Спойлер25: WDTCSR |= (1<<WDCE) | (1<<WDE);
+00000478: 91800060 LDS R24,0x0060 Load direct from data space
+0000047A: 6188 ORI R24,0x18 Logical OR with immediate
+0000047B: 93800060 STS 0x0060,R24 Store direct to data space
27: WDTCSR = (1<<WDE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);
+0000047D: E08F LDI R24,0x0F Load immediate
+0000047E: 93800060 STS 0x0060,R24 Store direct to data space
А вот дизасм неоптимизированного сишника - явно побольше:
Спойлер25: WDTCSR |= (1<<WDCE) | (1<<WDE);
+00000488: E680 LDI R24,0x60 Load immediate
+00000489: E090 LDI R25,0x00 Load immediate
+0000048A: E620 LDI R18,0x60 Load immediate
+0000048B: E030 LDI R19,0x00 Load immediate
+0000048C: 01F9 MOVW R30,R18 Copy register pair
+0000048D: 8120 LDD R18,Z+0 Load indirect with displacement
+0000048E: 6128 ORI R18,0x18 Logical OR with immediate
+0000048F: 01FC MOVW R30,R24 Copy register pair
+00000490: 8320 STD Z+0,R18 Store indirect with displacement
27: WDTCSR = (1<<WDE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);
+00000491: E680 LDI R24,0x60 Load immediate
+00000492: E090 LDI R25,0x00 Load immediate
+00000493: E02F LDI R18,0x0F Load immediate
+00000494: 01FC MOVW R30,R24 Copy register pair
+00000495: 8320 STD Z+0,R18 Store indirect with displacement
Единственное, что не очень хорошо видно - как студия дизассемблирует функцию. Если указать эти команды непосредственно в main, то выглядит в дизасме получше. Хотя работает и так и эдак.
Ответить

Вернуться в «AVR»