Jump to content

    
dontsov

Очень странная перезагрузка attiny85 по Watchdog Reset Flag

Recommended Posts

Прошу помощи!

Счетчик импульсов (watchdog в режиме генерации прерываний) на attiny85 считает импульсы просыпаясь раз в 250мс и раз в сутки выходит из цикла и общается по i2c.
Возникла проблема — очень редко (!) attiny85 перезагружается после общения по i2c.

Как я это понял: я вижу на сервере увеличение на единицу счетчика перезагрузок и MCUSR в setup().
MCUSR обычно 1, а становится равен 8 (1000 - WDRF: Watchdog Reset Flag. Завершение работы таймера.).

Подозрения на некорректную настройку watchdog. Проблема проявляется крайне редко и не понятно как отловить.

Код: main.cpp

main.cpp "избранное":

int16_t wakeup_period_min;

volatile int wdt_count; 

ISR( WDT_vect ) { 
	wdt_count--;
}  

void resetWatchdog() {
	MCUSR = 0;
	WDTCR = bit( WDCE ) | bit( WDE );
	WDTCR = bit( WDIE ) | bit( WDP2 );     // 250 ms
	wdt_reset();
} 

#define ONE_MINUTE 240

void setup() {
	info.service = MCUSR; //причина перезагрузки

	noInterrupts();
	ACSR |= bit( ACD ); 
	interrupts();
	resetWatchdog(); 

	wakeup_period_min = WAKEUP_DEFAULT_PER_MIN;

    if (storage.get(info.data)) { //не первая загрузка
		info.resets = EEPROM.read(storage.size());
		info.resets++;
		EEPROM.write(storage.size(), info.resets);
	} else {
		EEPROM.write(storage.size(), 0);
	}
}


void loop() {
	power_all_disable();  
	set_sleep_mode( SLEEP_MODE_PWR_DOWN );  
	resetWatchdog(); 
	for (unsigned int i = 0; i < ONE_MINUTE && !button.pressed(); ++i)  {
		wdt_count = wakeup_period_min;
		while ( wdt_count > 0 ) {
			noInterrupts();
			if (button.pressed()) { 
				interrupts();
				break;
			} else 	{
				counting();
				interrupts();
				sleep_mode(); 
			}
		}
	}
	wdt_disable();

	....
	....Связь по i2c
	....
	
}


Выдержка из даташита

photo_2021-04-02_23-59-59.jpg.b539379f21534eeb99a4ae69eeccb125.jpg

photo_2021-04-02_23-59-50.thumb.jpg.46e3be252a0176e70979309cb3cbf332.jpg

Какие гипотезы тестируются:
1. по даташиту нужно "To avoid the Watchdog Reset, WDIE must be set after each interrupt." 
добавил в ISR(WDT_vect):   WDTCR |= bit( WDIE );

2. Убрать WDE из WDTCR = bit( WDCE ) | bit( WDE );

Почему я уверен, что устройства не зависают:
а) attiny продолжает считать импульсы корректно
б) я посмотрел статистику и 70% attiny вышли на связь через WAKEUP_DEFAULT_PER_MIN, который получают в setup(). В остальных случаях через Х * WAKEUP_DEFAULT_PER_MIN из-за проблем со связью.

Почему я думаю, что проблема в начале функции loop(), а не в цикле подсчета импульсов:
a) attiny выходит на связь через дефалтный период, а не хаотично.
б) attiny выходит на связь ПОСЛЕ цикла подсчета импульсов, значит ошибка была не в цикле, а перед ним. 

Проблема появляется с вероятностью около 0,0002%.

К сожалению, моих знаний не достаточно, чтобы предположить, что может быть причиной перезагрузки. Прошу помощи!

Edited by dontsov

Share this post


Link to post
Share on other sites

5 тестовых устройств с WDTCR |= bit( WDIE ) в ISR(WDT_vect) продолжают исправно работать, когда без него через сутки точно зависали.
Дополнительно убрал WDE из WDTCR = bit( WDCE ) | bit( WDE ), т.к. бит отвечает за перезагрузку МК.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.