Jump to reset vector when program exceeds specified watchdog timeout
This commit is contained in:
@@ -12,8 +12,9 @@
|
|||||||
#define TW_MR_SLA_NACK 0x48
|
#define TW_MR_SLA_NACK 0x48
|
||||||
#define TW_MR_DATA_ACK 0x50
|
#define TW_MR_DATA_ACK 0x50
|
||||||
|
|
||||||
// XXX: Handle interrupts in I2C_vect ISR? This may not
|
// XXX: Error handling and recovery without watchdog timer.
|
||||||
// actually be much better than the blocking approach
|
// XXX: Implement I2C_vect ISR? This may not actually be
|
||||||
|
// much better than the blocking approach.
|
||||||
|
|
||||||
static void I2C_AHT20_Reset(void);
|
static void I2C_AHT20_Reset(void);
|
||||||
static bool I2C_AHT20_IsCalibrated(void);
|
static bool I2C_AHT20_IsCalibrated(void);
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "bus/mosfet.h"
|
#include "bus/mosfet.h"
|
||||||
|
|
||||||
|
// XXX: This might be too much specificity for something where
|
||||||
|
// a generic digital output implementation would be adequate.
|
||||||
|
|
||||||
int MOS_Init(void)
|
int MOS_Init(void)
|
||||||
{
|
{
|
||||||
// PB0: MOSFET #1 Peltier
|
// PB0: MOSFET #1 Peltier
|
||||||
|
|||||||
@@ -43,16 +43,16 @@ void WDT_Enable(void)
|
|||||||
WDTCR = BIT(WDE) | BIT(WDP2) | BIT(WDP1) | BIT(WDP0);
|
WDTCR = BIT(WDE) | BIT(WDP2) | BIT(WDP1) | BIT(WDP0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WDT_SetTimeout(unsigned char time)
|
void WDT_SetTimeoutFlag(unsigned char flag)
|
||||||
{
|
{
|
||||||
time = CLAMP(time, 7, 0);
|
flag = CLAMP(flag, 7, 0);
|
||||||
|
|
||||||
Info("Setting watchdog prescalar to %d...", time);
|
Info("Setting watchdog prescalar to %02X...", flag);
|
||||||
|
|
||||||
// Clear timer prescalar flags
|
// Clear timer prescalar flags
|
||||||
WDTCR &= 0xF8; // 11111000
|
WDTCR &= 0xF8; // 11111000
|
||||||
|
|
||||||
WDTCR |= time;
|
WDTCR |= flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WDT_HasTriggered(void)
|
bool WDT_HasTriggered(void)
|
||||||
@@ -88,8 +88,8 @@ bool WDT_HasTriggered(void)
|
|||||||
void WDT_Disable(void)
|
void WDT_Disable(void)
|
||||||
{
|
{
|
||||||
// WDE can only be cleared if the WDTOE bit has
|
// WDE can only be cleared if the WDTOE bit has
|
||||||
// logic level one. To disable an enabled Watchdog
|
// logic level one. To disable an enabled watchdog
|
||||||
// Timer, the following procedure must be followed:
|
// timer, the following procedure must be followed:
|
||||||
|
|
||||||
// 1. In the same operation, write a logic one to
|
// 1. In the same operation, write a logic one to
|
||||||
// WDTOE and WDE. A logic one must be written to WDE
|
// WDTOE and WDE. A logic one must be written to WDE
|
||||||
@@ -97,7 +97,7 @@ void WDT_Disable(void)
|
|||||||
// operation starts.
|
// operation starts.
|
||||||
|
|
||||||
// 2. Within the next four clock cycles, write a
|
// 2. Within the next four clock cycles, write a
|
||||||
// logic 0 to WDE. This disables the Watchdog
|
// logic 0 to WDE. This disables the watchdog.
|
||||||
|
|
||||||
// No interrupts while we set WDTCR;
|
// No interrupts while we set WDTCR;
|
||||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
@@ -108,5 +108,13 @@ void WDT_Disable(void)
|
|||||||
|
|
||||||
void WDT_Reset(void)
|
void WDT_Reset(void)
|
||||||
{
|
{
|
||||||
// TODO: Reset watchdog timer
|
// The WDR – Watchdog Reset – instruction resets the
|
||||||
|
// watchdog timer. The Watchdog Timer is also reset
|
||||||
|
// when it is disabled and when a chip reset occurs.
|
||||||
|
|
||||||
|
// If the reset period expires without another
|
||||||
|
// watchdog reset, the chip resets and executes from
|
||||||
|
// the Reset Vector.
|
||||||
|
|
||||||
|
__asm__("WDR");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
void WDT_Enable(void);
|
void WDT_Enable(void);
|
||||||
void WDT_SetTimeout(unsigned char time);
|
void WDT_SetTimeoutFlag(unsigned char flag);
|
||||||
bool WDT_HasTriggered(void);
|
bool WDT_HasTriggered(void);
|
||||||
void WDT_Disable(void);
|
void WDT_Disable(void);
|
||||||
void WDT_Reset(void);
|
void WDT_Reset(void);
|
||||||
|
|||||||
15
src/main.c
15
src/main.c
@@ -7,13 +7,14 @@
|
|||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
// TODO: Convert raw data from ADS1115 to usable values.
|
// TODO: Convert raw data from ADS1115 to usable values.
|
||||||
// TODO: Implement optional sensor value check with CRC8.
|
// TODO: Implement optional CRC8 sensor measurement check.
|
||||||
// TODO: Set timeouts for polling based things like I2C.
|
|
||||||
// TODO: Write an improved serial parser (low priority).
|
|
||||||
// TODO: Either implement software PWM for the FAN03 timer
|
// TODO: Either implement software PWM for the FAN03 timer
|
||||||
// (which will be quite complicated) or pick a chip with
|
// (which will be quite complicated) or pick a chip with
|
||||||
// more than two 16-bit PWM outputs like the ATmega328PB.
|
// more than two 16-bit PWM outputs like the ATmega328PB.
|
||||||
// https://www.mikrocontroller.net/articles/Soft-PWM
|
// https://www.mikrocontroller.net/articles/Soft-PWM
|
||||||
|
// TODO: Check if FAN02 is receiving the right frequency.
|
||||||
|
// TODO: Write an improved command parser (low priority).
|
||||||
|
// TODO: Proper error handling and recovery (after testing).
|
||||||
|
|
||||||
int Init(void)
|
int Init(void)
|
||||||
{
|
{
|
||||||
@@ -48,8 +49,8 @@ int Init(void)
|
|||||||
if (WDT_HasTriggered())
|
if (WDT_HasTriggered())
|
||||||
Info("Unexpected system reset.");
|
Info("Unexpected system reset.");
|
||||||
|
|
||||||
// WDT_Enable();
|
WDT_Enable();
|
||||||
// WDT_SetTimeout(7);
|
WDT_SetTimeoutFlag(0x7); // 2 seconds
|
||||||
|
|
||||||
// There is a possiblity to use interrupt signals
|
// There is a possiblity to use interrupt signals
|
||||||
// for I2C communication but only as one large
|
// for I2C communication but only as one large
|
||||||
@@ -98,8 +99,6 @@ void Update(void)
|
|||||||
float temp[3], rhum[3];
|
float temp[3], rhum[3];
|
||||||
short raw[4];
|
short raw[4];
|
||||||
|
|
||||||
WDT_Reset(); // Reset watchdog
|
|
||||||
|
|
||||||
Info("Reading sensor values...");
|
Info("Reading sensor values...");
|
||||||
|
|
||||||
I2C_SetChannel(AHT01);
|
I2C_SetChannel(AHT01);
|
||||||
@@ -128,7 +127,9 @@ int main(void)
|
|||||||
Init();
|
Init();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
WDT_Reset();
|
||||||
Update();
|
Update();
|
||||||
|
WDT_Reset();
|
||||||
Sleep(1000);
|
Sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user