Jump to reset vector when program exceeds specified watchdog timeout

This commit is contained in:
2024-09-05 17:55:05 +02:00
parent 7eaacf4abf
commit 0bd4866816
5 changed files with 31 additions and 18 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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");
} }

View File

@@ -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);

View File

@@ -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);
} }