kopia lustrzana https://github.com/bristol-seds/pico-tracker
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 momentmaster
rodzic
f7221454f0
commit
b543316b42
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue