Interrupt on both edges of the gps timepulse to ensure we hit the hardware watchdog often enough. Also control the external WDI line as an awake/asleep trigger for debugging.

This introduces a uncertainty of ±0.5s on the internal time, but we can ignore that for the moment
master
Richard Meadows 2015-07-18 16:53:25 +01:00
rodzic f7221454f0
commit b543316b42
7 zmienionych plików z 39 dodań i 23 usunięć

Wyświetl plik

@ -30,7 +30,7 @@
*/ */
#define PIPS_RATE 1 #define PIPS_RATE 1
#define PIPS_LENGTH_MS 250 #define PIPS_LENGTH_MS 200
#define PIPS_FREQUENCY (1000 / PIPS_LENGTH_MS) #define PIPS_FREQUENCY (1000 / PIPS_LENGTH_MS)
#endif /* PIPS_H */ #endif /* PIPS_H */

Wyświetl plik

@ -52,6 +52,7 @@ struct idle_counter {
uint32_t wait_for_next_telemetry; uint32_t wait_for_next_telemetry;
}; };
void awake_do_watchdog(void);
void kick_the_watchdog(void); void kick_the_watchdog(void);
void idle(idle_wait_t idle_t); void idle(idle_wait_t idle_t);
void watchdog_init(void); void watchdog_init(void);

Wyświetl plik

@ -48,6 +48,7 @@
#include "system/system.h" #include "system/system.h"
#include "system/pinmux.h" #include "system/pinmux.h"
#include "adc/adc.h" #include "adc/adc.h"
#include "watchdog.h"
#define Assert assert #define Assert assert
@ -531,6 +532,8 @@ enum adc_status_code adc_init(Adc *hw,
/** Interrupt handler for the ADC module. */ /** Interrupt handler for the ADC module. */
void ADC_Handler(void) void ADC_Handler(void)
{ {
awake_do_watchdog();
/* get interrupt flags and mask out enabled callbacks */ /* get interrupt flags and mask out enabled callbacks */
uint32_t flags = module_inst.hw->INTFLAG.reg; uint32_t flags = module_inst.hw->INTFLAG.reg;

Wyświetl plik

@ -41,7 +41,7 @@
#include "system/port.h" #include "system/port.h"
#include "tc/tc_driver.h" #include "tc/tc_driver.h"
#include "hw_config.h" #include "hw_config.h"
#include "watchdog.h"
/** /**
* CYCLIC REDUNDANCY CHECK (CRC) * CYCLIC REDUNDANCY CHECK (CRC)
@ -418,6 +418,8 @@ void timer0_tick_deinit()
*/ */
void TC0_Handler(void) void TC0_Handler(void)
{ {
awake_do_watchdog();
while (tc_get_status(TC0) & TC_STATUS_CHANNEL_0_MATCH) { while (tc_get_status(TC0) & TC_STATUS_CHANNEL_0_MATCH) {
tc_clear_status(TC0, TC_STATUS_CHANNEL_0_MATCH); tc_clear_status(TC0, TC_STATUS_CHANNEL_0_MATCH);

Wyświetl plik

@ -31,8 +31,9 @@
#include "system/events.h" #include "system/events.h"
#include "system/interrupt.h" #include "system/interrupt.h"
#include "system/port.h" #include "system/port.h"
#include "watchdog.h"
uint32_t gps_timepulse_count = 0; volatile uint32_t gps_timepulse_count = 0;
uint32_t timepulse_sequence = 0; uint32_t timepulse_sequence = 0;
timepulse_callback_t _timer_callback; timepulse_callback_t _timer_callback;
@ -56,15 +57,15 @@ void timepulse_extint_init(void) {
struct extint_chan_conf config; struct extint_chan_conf config;
config.gpio_pin = GPS_TIMEPULSE_PIN; config.gpio_pin = GPS_TIMEPULSE_PIN;
config.gpio_pin_mux = GPS_TIMEPULSE_PINMUX; config.gpio_pin_mux = GPS_TIMEPULSE_PINMUX;
config.gpio_pin_pull = EXTINT_PULL_NONE; // ??? config.gpio_pin_pull = EXTINT_PULL_DOWN;
config.wake_if_sleeping = false; // ??? config.wake_if_sleeping = true;
config.filter_input_signal = false; config.filter_input_signal = false;
config.detection_criteria = EXTINT_DETECT_RISING; config.detection_criteria = EXTINT_DETECT_BOTH;
extint_chan_set_config(GPS_TIMEPULSE_EXTINT, &config); extint_chan_set_config(GPS_TIMEPULSE_EXTINT, &config);
/* We route this event to event channel 0 */ /* We route this event to event channel 0 */
events_allocate(0, events_allocate(0,
EVENTS_EDGE_DETECT_NONE, EVENTS_EDGE_DETECT_NONE, /* Don't care for async path */
EVENTS_PATH_ASYNCHRONOUS, EVENTS_PATH_ASYNCHRONOUS,
0xC + GPS_TIMEPULSE_EXTINT, /* External Interrupt Number */ 0xC + GPS_TIMEPULSE_EXTINT, /* External Interrupt Number */
0); 0);
@ -83,14 +84,16 @@ void timepulse_set_callback(timepulse_callback_t callback) {
/** /**
* EIC Handler, triggered by the GPS at GPS_TIMEPULSE_FREQ Hz * EIC Handler, triggered by the GPS at GPS_TIMEPULSE_FREQ Hz
*/ */
void EIC_Handler(void) { void EIC_Handler(void)
{
awake_do_watchdog();
if (EIC->INTFLAG.reg & (1 << GPS_TIMEPULSE_EXTINT)) { if (EIC->INTFLAG.reg & (1 << GPS_TIMEPULSE_EXTINT)) {
EIC->INTFLAG.reg = (1 << GPS_TIMEPULSE_EXTINT); EIC->INTFLAG.reg = (1 << GPS_TIMEPULSE_EXTINT);
gps_timepulse_count++; gps_timepulse_count++;
/* Runs at 1Hz */ /* Runs at 1Hz */
if (gps_timepulse_count >= GPS_TIMEPULSE_FREQ) { if (gps_timepulse_count >= GPS_TIMEPULSE_FREQ * 2) { /* Both */
gps_timepulse_count = 0; gps_timepulse_count = 0;
/* Make the callback if we have one */ /* Make the callback if we have one */

Wyświetl plik

@ -39,7 +39,7 @@ struct idle_counter idle_count, idle_count_max;
idle_wait_t last_idle_t = IDLE_NONE; idle_wait_t last_idle_t = IDLE_NONE;
#define kick_external_watchdog() port_pin_toggle_output_level(WDT_WDI_PIN) #define kick_external_watchdog() port_pin_toggle_output_level(WDT_WDI_PIN)
/** /**
* Increments the specified idle counter * Increments the specified idle counter
@ -88,6 +88,18 @@ void clear_idle_counters(void)
memset(&idle_count, 0, sizeof(struct idle_counter)); memset(&idle_count, 0, sizeof(struct idle_counter));
} }
/**
* To be run when we wake from sleep
*/
void awake_do_watchdog(void)
{
#ifdef DEBUG_USE_INTWATCHDOG
wdt_reset_count();
#endif
/* WDI high */
port_pin_set_output_level(WDT_WDI_PIN, 1);
}
/** /**
* Kick * Kick
*/ */
@ -130,24 +142,18 @@ void idle(idle_wait_t idle_t)
wdt_reset_count(); wdt_reset_count();
#endif #endif
/* WDI low */
port_pin_set_output_level(WDT_WDI_PIN, 0); port_pin_set_output_level(WDT_WDI_PIN, 0);
/* And sleep */ /* And sleep */
system_sleep(); system_sleep();
/* Same again when we wake from sleep */
#ifdef DEBUG_USE_INTWATCHDOG
wdt_reset_count();
#endif
port_pin_set_output_level(WDT_WDI_PIN, 1);
} }
/** /**
* The internal watchdog is used to bring the processor to a halt and * The internal watchdog is used to bring the processor to a halt and
* coredump to external memory. * coredump to external memory (todo)
* 0.8s < t_early_w < 0.128s * 0.6s < t_early_w < 0.96s
* *
* The external watchdog then hard resets the MCU and GPS to bring the * The external watchdog then hard resets the MCU and GPS to bring the
* system back up in a clean state. * system back up in a clean state.
@ -168,12 +174,12 @@ void watchdog_init(void)
system_gclk_gen_set_config(WDT_GCLK, system_gclk_gen_set_config(WDT_GCLK,
GCLK_SOURCE_OSCULP32K, /* Source */ GCLK_SOURCE_OSCULP32K, /* Source */
false, /* High When Disabled */ false, /* High When Disabled */
4, /* Division Factor 1 */ 3, /* Division Factor */
false, /* Run in standby */ false, /* Run in standby */
true); /* Output Pin Enable */ true); /* Output Pin Enable */
system_gclk_gen_enable(WDT_GCLK); system_gclk_gen_enable(WDT_GCLK);
/* Set the watchdog timer. On 8kHz gclk */ /* Set the watchdog timer. On ~11kHz gclk */
wdt_set_config(false, /* Lock WDT */ wdt_set_config(false, /* Lock WDT */
true, /* Enable WDT */ true, /* Enable WDT */
WDT_GCLK, /* Clock Source */ WDT_GCLK, /* Clock Source */

Wyświetl plik

@ -34,7 +34,7 @@
#include "tc/tc_driver.h" #include "tc/tc_driver.h"
#include "hw_config.h" #include "hw_config.h"
#include "xosc.h" #include "xosc.h"
#include "watchdog.h"
enum measure_state_t { enum measure_state_t {
MEASURE_WAIT_FOR_FIRST_EVENT, MEASURE_WAIT_FOR_FIRST_EVENT,
@ -235,7 +235,6 @@ void measure_xosc_disable(enum xosc_measurement_t measurement_t) {
} }
} }
/** /**
* Triggered on timer 2 capture * Triggered on timer 2 capture
*/ */
@ -243,6 +242,8 @@ void TC2_Handler(void) {
uint32_t capture_value; uint32_t capture_value;
uint32_t source_freq; uint32_t source_freq;
awake_do_watchdog();
if (tc_get_status(TC2) & TC_STATUS_CHANNEL_0_MATCH) { if (tc_get_status(TC2) & TC_STATUS_CHANNEL_0_MATCH) {
tc_clear_status(TC2, TC_STATUS_CHANNEL_0_MATCH); tc_clear_status(TC2, TC_STATUS_CHANNEL_0_MATCH);