Wednesday, May 23, 2018

Watchdog library | AVR microcontrollers | ATmega328P

Even if you are a dog or a cat person, you should still be using the watchdog.

For those who don't know, a watchdog is a timer inside the microcontroller generated by an RC oscillator - with 128kHz frequency on an AVR device. When it times out, the microcontroller is reset. To prevent it from resetting the MCU, the watchdog timer must be reset by the code inside the while loop. The idea is that if you have a loop and gets stuck, the watchdog timer will not be reset and so the microcontroller will be reset after the timer reaches the timeout period. Say you read a sensor and in a loop the code waits for the sensor response but the sensor is malfunctioning. If not for the watchdog, the MCU will get stuck and your drone will crash.



Watchdog extension library for AVR microcontrollers

On ATmega328 the available timeouts are 16ms, 32ms, 64ms, 0.125s, 0.25s, 0.5s, 1s, 2s, 4s, 8s. Choosing the right timeout depends on the specific application. The while loop must be able to finish executing the code and reset the watchdog timer before the timer runs out. For critical applications where if the CPU being stuck for more than 1 second is unacceptable, you can choose timeouts of a few milliseconds. Those cases can be a drone where reaction time needs to be fast, or a 3D printer reaches the end and the motor needs to be stopped in time. But in most cases the timeout can even be 8s, like when taking room temperature readings.

Other uses for the Watchdog timer

The watchdog can also be used for it's timer not just the reset function. Some devices like ATmega328, have the ability to produce an interrupt instead of resetting the MCU. So is like setting up a timer to trigger an interrupt at a preset time interval.

The advantages are that the powerful timers can be used for something else, and also it's easier to set up a watchdog timer than a conventional timer.

The disadvantages are timer resolution - you are limited only for a few preset intervals and since the timer oscillator is an RC type, the timeout depends on voltage and temperature.

Nevertheless it still might be useful in many scenarios. Putting the MCU in sleep mode, the CPU can be wake up by the watchdog interrupt. On low power devices a LED can be flashed every 2 seconds to indicate that the device is on, or some sensors can be red and logged every few seconds.


How to use the Watchdog timer

If you are using the avr-gcc compiler, the library is already present. All you have to do is include it like this


#include <avr/wdt.h>

To enable the watchdog and set the timeout


wdt_enable(WDTO_2S); 

This function must be placed before the while loop in the main function. The available parameters are available on avr-gcc site here. In the above example, WDTO_2S means a timeout of 2 seconds.

In the while loop use this function to reset the watchdog timer


wdt_reset();

To stop the watchdog, use


wdt_disable();

To make use of the watchdog interrupt, i have made an library extension to the one provided by avr-gcc and can be downloaded bellow.

Doesn't matter if you include or not the wdt.h header file, since it will be included by the wdt_extension.h file.


#include "wdt_extension.h"

Now new macros are available. All of them takes a timeout value as a argument. Again, the list of available timeouts macros can be found on avr-gcc site https://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html


wdt_interrupt_mode(timeout)

This enables the watchdog interrupt and disables the reset function. Inside the wdt_extension.h file there is an ISR function at the bottom that can be moved in the main.c file if needed. The ISR function must be defined even if is left empty otherwise the interrupt will not work.

Do not reset the watchdog timer if you want the watchdog ISR to trigger.

Same as for wdt_enable function, this must be placed inside the main function before the while loop.

This mode is useful for detecting and stopping the applications that take to much time to complete. Suppose you have multiple sensors and one is broken. Depending on the code, it could stay in a loop waiting for a response forever. If it is not critical, you don't want a system reset but instead a bypass of the unresponsive application. In the ISR you could use some flags to do this.

This also clears the reset source for the watchdog, so if you need to know what caused the reset, read the appropriate register before this macro.


wdt_interrupt_reset_mode(timeout)

With this macro, both the interrupt and the reset function are enabled. If the watchdog timer is not reset before the timeout, the watchdog interrupt will be triggered. After the ISR execution, the interrupt will be disabled. After another timeout the system will be reset. The interrupt can be re-enabled but not inside the ISR.

Same as for wdt_enable function, this must be placed inside the main function before the while loop.

With this mode, the system can be notified before a system reset, for let's say... data saving. Care must be taken that the timeout is long enough for the system to shutdown properly.



Download

v1.0

wdt_extension.h

No comments:

Post a Comment