Перейти к содержанию
    

Не работает Watchdog в AtXmega

Прошу помощи у Клуба!

 

Кто пользовался watchdog таймером в Xmega контроллерах?

У меня watchdog нагло отказывается работать!

Вот кусок программы:

 

void watchdog_init(void)
{unsigned char s,n;
// Сгенерировано через Code Wisard AVR и проверено по атмеловскому даташиту
#pragma optsize- 
s = SREG;					                                         // Save interrupts enabled/disabled state
#asm("cli")				                                                 // Disable interrupts
n   = WDT_PER_512CLK_gc | WDT_ENABLE_bm | WDT_CEN_bm;  // Watchdog Timer: On. Period: 500 ms
CCP = CCP_IOREG_gc;
WDT.CTRL = n;

n   = (WDT.WINCTRL & (~WDT_WEN_bm)) | WDT_WCEN_bm;      // Watchdog window mode: Off
CCP = CCP_IOREG_gc; 
WDT.WINCTRL = n;

SREG = s;    				                                                 // Restore interrupts enabled/disabled state
}

#define SetGreenLed	PORTC.OUTCLR = 0x40
#define ClrGreenLed	PORTC.OUTSET = 0x40
#define SetRedLed	PORTC.OUTCLR = 0x80
#define ClrRedLed	PORTC.OUTSET = 0x80

void main(void)
{
watchdog_init();
InitPins();				        //Инициализация ножек, куча строк типа "PORTA.DIR = 0b00110110;" и ничего больше
SetGreenLed;				//
InitSystemClock();			//переключиться на внешний генератор 33 МГц
delay_ms(400);				//
ClrGreenLed;				//
delay_ms(5000);			// 
while(1)					//
  {delay_ms(250);			//
   SetRedLed;				//
   delay_ms(250);			//
   ClrRedLed;				//
  }						//
//...						//Дальше шла программа, которую WDT должен был защищать и оберегать

 

После рестарта мигает зеленый светодиод, а затем навсегда начинает мигать красный. То есть контроллер не сбрасывается.

Пробовал включить WDT через Fuse биты (устанавливал WDP и WDLOCK) - не помогает, все равно Watchdog не работает.

Пробовал на двух контроллерах AtXmega128A1 AtXmega32A4. не работает ни там ни там.

Как заставить его работать? Может я что-то упускаю? Кто то вообще использовал WDT в Xmega_х?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что такое у вас "n"?

Попробуйте прямо записать константу в WDT.CTRL, без промежуточной перевалки. Вдруг в 4 такта, резервируемых CCP, вы не уложились?

CCP = CCP_IOREG_gc;
WDT.CTRL = WDT_PER_512CLK_gc | WDT_ENABLE_bm | WDT_CEN_bm;  // Watchdog Timer: On. Period: 500 ms

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Укладывается, я смотрел сгенерированный asm, там n назначен на r16 и присвоение идет двумя последовательными командами. К сожалению, до понедельника попробовать уже не смогу. Все осталось на работе. А Вы использовали WDT в Xmega_х? Мне не верится, что он там не работает вообще, но мало ли?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А Вы использовали WDT в Xmega_х? Мне не верится, что он там не работает вообще, но мало ли?

Нет, я только Reset использовала по похожей схеме, вот так:

  __disable_interrupt();
  CCP = CCP_IOREG_gc;
  RST.CTRL = RST_SWRST_bm;
  for(;;);

И он нормально работает. Только после такого сброса нулевой байт UART'ом непонятно откуда принимается (при аппаратном ресете его нет).

 

К сожалению, до понедельника попробовать уже не смогу. Все осталось на работе. А Вы использовали WDT в Xmega_х? Мне не верится, что он там не работает вообще, но мало ли?

Проверила на своем. Вот так работает, сброс есть:

  __disable_interrupt();
  CCP = CCP_IOREG_gc;
  WDT.CTRL = WDT_PER_500CLK_gc | WDT_ENABLE_bm | WDT_CEN_bm;  // Watchdog Timer: On. Period: 500 ms
  for(;;);

Только у меня маска называется WDT_PER_500CLK_gc, а не WDT_PER_512CLK_gc. Определена в хидере так:

WDT_PER_500CLK_gc = (0x06<<2), ///< 500 cycles (0.5s @ 3.3V)

 

Контроллер ATxmega128A1 (rev.H), компилятор EWAVR 6.21.2

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хорошо хоть у кого-то работает, значит проблема решается :)

У меня определяется так же:

#define WDT_PER_512CLK_gc (0x06<<2) // 512 cycles (0.5s at 3.3V)

 

а можете показать асемблеровский кусок посмотреть?

 

В понедельник еще возьму плату трехлетней давности, чтоб точно контроллер из другой партии был и проверю на ней.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а можете показать асемблеровский кусок посмотреть?

Не могу :), почему-то компилятор выложил код одним длинным куском, в котором нужного места я не нахожу.

 

Выделила в отдельную функцию, чтобы посмотреть код:

void WatchDogStart()
{
WatchDogStart:
   CCP = CCP_IOREG_gc;  // 0xD8 - protected IO register
00000000   ED08            LDI     R16, 216
00000002   BF04            OUT     0x34, R16
   WDT.CTRL = WDT_PER_500CLK_gc | WDT_ENABLE_bm | WDT_CEN_bm;  // Watchdog Timer: On. Period: 500 ms
00000004   E10B            LDI     R16, 27
00000006   93000080        STS     128, R16
}
0000000A   9508            RET

Еще совет. Попробуйте после установки WDT подождать. Вот так:

 

  CCP = CCP_IOREG_gc;                       // 0xD8 - Снятие защиты от записи на 4 цикла
  WDT.CTRL = WDT_PER_500CLK_gc | WDT_ENABLE_bm | WDT_CEN_bm;  // Включение WDT в нормальном режиме, период выдержки 500 мс
  while( WDT.STATUS & WDT_SYNCBUSY_bm);     // Ожидание синхронизации

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

WDT никогда не использовал ни в мегах ни в хмегах.

Поэтому врядли чего подскажу.

Но мне просто интересно зачем вам нужен WDT.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вот сгенерированный код:

;void watchdog_init(void)
; 0000 0056 {unsigned char s,n;
_watchdog_init:
; 0000 0057 // Сгенерировано через Code Wisard AVR и проверено по атмеловскому даташиту
; 0000 0058 #pragma optsize-
; 0000 0059  s = SREG;					                                         // Save interrupts enabled/disabled state
ST   -Y,R17
ST   -Y,R16
;	s -> R17
;	n -> R16
IN   R17,63
; 0000 005A  #asm("cli")				                                                 // Disable interrupts
cli
; 0000 005B  n   = WDT_PER_512CLK_gc | WDT_ENABLE_bm | WDT_CEN_bm;  // Watchdog Timer: On. Period: 500 ms
LDI  R16,LOW(27)
; 0000 005C  CCP = CCP_IOREG_gc;
LDI  R30,LOW(216)
OUT  0x34,R30
; 0000 005D  WDT.CTRL = n;
STS  128,R16
; 0000 005E 
; 0000 005F  n   = (WDT.WINCTRL & (~WDT_WEN_bm)) | WDT_WCEN_bm;      // Watchdog window mode: Off
LDS  R30,129
ANDI R30,0xFD
ORI  R30,1
MOV  R16,R30
; 0000 0060  CCP = CCP_IOREG_gc;
LDI  R30,LOW(216)
OUT  0x34,R30
; 0000 0061  WDT.WINCTRL = n;
STS  129,R16
; 0000 0062 
; 0000 0063  SREG = s;    				                                                 // Restore interrupts enabled/disabled state
OUT  0x3F,R17
; 0000 0064 }
LD   R16,Y+
LD   R17,Y+
RET
;

 

Вроде все нормально. Да и я включал WDT через Fuse биты - все равно не работал!!!

Если у Вас работает, то есть подозрения на битые контроллеры. Тем более, что у меня уже есть горький опыт именно с Xmega32A4. (внутреннее АЦП в беззнаковом режиме выдавало на некоторых участках битый код. Пришлось запустить в знаковый режим, потерял 1 бит точности, но все стало работать. ) В общем в понедельник буду испытывать на других платах. и спасибо за помощь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если у Вас работает, то есть подозрения на битые контроллеры.

 

Перечитайте мой предыдущий пост, он был отредактирован.

 

По моему ваша проблема в том, что, не дождавшись истечения полусекуды, вы разрешаете WD снова. Потому у вас и нет сброса.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но мне просто интересно зачем вам нужен WDT.

Конкретно сейчас есть 3 причины:

1. При подаче питания с помощью искрящего контакта контроллер зависает где -то один раз из двадцати. (это при том, BOD включен на 2,4В при питании 3,3, а нормально работать контроллер начинает с 1,8В)

2. Плата работает в условии достаточно сильных помех от расположенных рядом двигателей + также рядом стоящие радиопередатчики ей здоровья не добавляют :twak: .

3. Использование WDT дает +2 к такому важному навыку разработчика, как "здоровый сон" :)

 

Перечитайте мой предыдущий пост...

Да, я читал, как доберусь до железа - обязательно попробую и сообщу о результатах.

Еще раз спасибо за помощь!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Конкретно сейчас есть 3 причины:

1. При подаче питания с помощью искрящего контакта контроллер зависает где -то один раз из двадцати. (это при том, BOD включен на 2,4В при питании 3,3, а нормально работать контроллер начинает с 1,8В)

2. Плата работает в условии достаточно сильных помех от расположенных рядом двигателей + также рядом стоящие радиопередатчики ей здоровья не добавляют :twak: .

3. Использование WDT дает +2 к такому важному навыку разработчика, как "здоровый сон" :)

1.Попробуйте внешний супервизор.

2.Борьба с зависаниями с помощью WDT абсурд.

3.Только с этим и согласен.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

:bb-offtopic: Уважаемый zombi, на этом форуме уже есть не одна тема (и не без Вашего участия) с обсуждением стоит ли использовать WDT, с подобной "помощью" милости прошу туда!

 

1.Попробуйте внешний супервизор.

Использование внешнего супервизора это абсурд, так как есть встроенный (BOD) который ничем не хуже, только дешевле. А от внешних мы отказались уже лет 8 назад, после того, как несколько штук сгорели и стали выдавать непериодический ресет просто так! (уж поверьте, сгорели именно супервизоры, а не питание сделалось плохим.)

2.Борьба с зависаниями с помощью WDT абсурд.

Может мы говорим о разных вещах, но в документации от "атмел" написано, что ихний WDT именно для этого и предназначен!

3.Только с этим и согласен.

Уже только этого и достаточно.

 

P.S. Вы все равно не убедите меня, что WDT это зло, поэтому прошу по этому поводу в данной теме больше не писать.

Кстати, некоторые убеждены, что ремень безопасности в машине это тоже зло, но я все равно им пользуюсь :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Использование внешнего супервизора это абсурд, так как есть встроенный (BOD) который ничем не хуже, только дешевле.

Таки бывают случаи, когда внешний необходим, но данной темы это не касается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

прошу по этому поводу в данной теме больше не писать.

Ой сорри. Больше не буду.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все! Я окончательно понял, что контроллеры делаются с помощью черной магии и их работоспособность сильно зависит от количества китайцев, на земле, фазы луны и еще от чего-то! :wacko:

В общем танцевал я с бубном вокруг WDT с утра и до обеда. Что только не пробовал на трех разных платах: и задержки и инициализации разные, по несколько раз через софт и через фьюзы, в конце вообще на ассемблер перешел прямо в АВР студии, чтоб компилятор был от производителя - ничего не помогает. Не работает и все! (Программный Reset, кстати, работал) Потом осенило посмотреть что в WDT.CTRL. Вывожу я его через UART наружу и - о чудо! Там 0x1A - в полном соответствии с симулятором! То есть WDT разрешён, и период 0,5сек. как я и устанавливаю. Получается - не работает сам модуль WDT в железе. Ну я и успокоился, решил что научились китайцы делать поддельные контроллеры, а нам повезло найти нужного поставщика - ну с кем не бывает :). Повытирал все свои эксперименты и сел дальше софт писать. Ближе к 5 часам вечера начинает коллега ругаться плохими словами - говорит программатор сдох ни с того ни с сего. Одолжил я ему свой (AVRISP mkII) на 5 мин., он свою плату перешил и программатор вернул. Прошиваю я сразу свою плату и вижу,что она уходит в ресет постоянный. И тут до меня доходит, что все "wdr" в программе закрыты, а watchdog в фьюзах остался включенным и он почему-то заработал. Беру другую плату - WDT не работает. Просто перешиваю программу (фьюзы не трогаю) и снова чудо - WDT заработал и на ней. Вот теперь даже не знаю - плакать :crying: или смеяться :08: , а главное - каких сюрпризов дальше ждать. :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...