kopia lustrzana https://github.com/bristol-seds/pico-tracker
Started new watchdog and init process.
rodzic
3e87c0b877
commit
4f33da8740
|
@ -33,6 +33,7 @@ void si_trx_on(uint8_t modulation_type, uint32_t frequency, uint16_t deviation);
|
|||
void si_trx_off(void);
|
||||
void si_trx_switch_channel(int16_t channel);
|
||||
|
||||
void si_trx_shutdown(void);
|
||||
void si_trx_init(void);
|
||||
|
||||
void spi_loopback_test(void);
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Functions related to the watchdog.
|
||||
* Copyright (C) 2015 Richard Meadows <richardeoin>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef WATCHDOG_H
|
||||
#define WATCHDOG_H
|
||||
|
||||
#include "samd20.h"
|
||||
|
||||
/**
|
||||
* These are random constants to prevent run-away code from
|
||||
* accidentially hitting them.
|
||||
*/
|
||||
typedef enum {
|
||||
IDLE_NONE,
|
||||
IDLE_WAIT_FOR_GPS = 0x90137526,
|
||||
IDLE_WHILE_TELEMETRY_ACTIVE = 0x15476064,
|
||||
IDLE_WAIT_FOR_NEXT_TELEMETRY = 0x36749870,
|
||||
} idle_wait_t;
|
||||
|
||||
/**
|
||||
* Define how many iterations these loops are permitted before a reset
|
||||
* is triggered.
|
||||
*/
|
||||
#define MAXIDLE_WAIT_FOR_GPS 0xFFFFFFFE
|
||||
#define MAXIDLE_WHILE_TELEMETRY_ACTIVE 0xFFFFFFFE
|
||||
#define MAXIDLE_WAIT_FOR_NEXT_TELEMETRY 0xFFFFFFFE
|
||||
|
||||
struct idle_counter {
|
||||
uint32_t wait_for_gps;
|
||||
uint32_t while_telemetry_active;
|
||||
uint32_t wait_for_next_telemetry;
|
||||
};
|
||||
|
||||
void watchdog_do_idle(idle_wait_t idle_t);
|
||||
void watchdog_init(void);
|
||||
|
||||
#endif /* WATCHDOG_H */
|
|
@ -38,7 +38,7 @@
|
|||
#include "gps.h"
|
||||
#include "mfsk.h"
|
||||
#include "ubx_messages.h"
|
||||
#include "system/wdt.h"
|
||||
#include "watchdog.h"
|
||||
#include "xosc.h"
|
||||
#include "telemetry.h"
|
||||
#include "timer.h"
|
||||
|
@ -52,7 +52,7 @@
|
|||
#include "spi_bitbang.h"
|
||||
#include "system/interrupt.h"
|
||||
|
||||
#define CALLSIGN "UBSEDS8"
|
||||
#define CALLSIGN "UBSEDSx"
|
||||
|
||||
void xosc_measure_callback(uint32_t result);
|
||||
void timepulse_callback(uint32_t sequence);
|
||||
|
@ -60,51 +60,29 @@ void timepulse_callback(uint32_t sequence);
|
|||
int32_t _xosc_error = 0;
|
||||
|
||||
/**
|
||||
* Initialises the status LED
|
||||
* Initialises the status LED. SHOULD TURN ON THE LED
|
||||
*/
|
||||
static inline void led_init(void)
|
||||
static inline void led_reset(void)
|
||||
{
|
||||
/**
|
||||
* This pin is shared with the XOSC line on the current hardware bodge
|
||||
*/
|
||||
port_pin_set_config(LED0_PIN,
|
||||
PORT_PIN_DIR_INPUT, /* Direction */
|
||||
PORT_PIN_DIR_OUTPUT, /* Direction */
|
||||
PORT_PIN_PULL_NONE, /* Pull */
|
||||
false); /* Powersave */
|
||||
// port_pin_set_output_level(LED0_PIN, 1); /* LED is active low */
|
||||
port_pin_set_output_level(LED0_PIN, 0); /* LED is active low */
|
||||
}
|
||||
/**
|
||||
* Turns the status LED on
|
||||
*/
|
||||
static inline void led_on(void)
|
||||
{
|
||||
//port_pin_set_output_level(LED0_PIN, 0); /* LED is active low */
|
||||
port_pin_set_output_level(LED0_PIN, 0); /* LED is active low */
|
||||
}
|
||||
/**
|
||||
* Turns the status LED off
|
||||
*/
|
||||
static inline void led_off(void)
|
||||
{
|
||||
//port_pin_set_output_level(LED0_PIN, 1); /* LED is active low */
|
||||
}
|
||||
|
||||
void wdt_init() {
|
||||
/* 64 seconds timeout. So 2^(15+6) cycles of the wdt clock */
|
||||
system_gclk_gen_set_config(WDT_GCLK,
|
||||
GCLK_SOURCE_OSCULP32K, /* Source */
|
||||
false, /* High When Disabled */
|
||||
128, /* Division Factor */
|
||||
false, /* Run in standby */
|
||||
true); /* Output Pin Enable */
|
||||
system_gclk_gen_enable(WDT_GCLK);
|
||||
|
||||
/* Set the watchdog timer. On 256Hz gclk 4 */
|
||||
wdt_set_config(true, /* Lock WDT */
|
||||
true, /* Enable WDT */
|
||||
GCLK_GENERATOR_4, /* Clock Source */
|
||||
WDT_PERIOD_16384CLK, /* Timeout Period */
|
||||
WDT_PERIOD_NONE, /* Window Period */
|
||||
WDT_PERIOD_NONE); /* Early Warning Period */
|
||||
port_pin_set_output_level(LED0_PIN, 1); /* LED is active low */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -277,22 +255,22 @@ void aprs_test(void)
|
|||
if (!gps_is_locked()) return; /* Don't bother with no GPS */
|
||||
|
||||
while(1) {
|
||||
struct ubx_nav_posllh pos = gps_get_nav_posllh();
|
||||
float lat = (float)pos.payload.lat / 10000000.0; // This division is from the gps reciver, not for geofence
|
||||
float lon = (float)pos.payload.lon / 10000000.0;
|
||||
uint32_t altitude = pos.payload.height / 1000;
|
||||
struct ubx_nav_posllh pos = gps_get_nav_posllh();
|
||||
float lat = (float)pos.payload.lat / 10000000.0; // This division is from the gps reciver, not for geofence
|
||||
float lon = (float)pos.payload.lon / 10000000.0;
|
||||
uint32_t altitude = pos.payload.height / 1000;
|
||||
|
||||
/* Set location */
|
||||
aprs_set_location(lat, lon, altitude);
|
||||
/* Set location */
|
||||
aprs_set_location(lat, lon, altitude);
|
||||
|
||||
/* Set frequency */
|
||||
telemetry_aprs_set_frequency(144800000);
|
||||
/* Set frequency */
|
||||
telemetry_aprs_set_frequency(144800000);
|
||||
|
||||
/* Transmit packet and wait */
|
||||
telemetry_start(TELEMETRY_APRS, 0xFFFF);
|
||||
while (telemetry_active()) {
|
||||
system_sleep();
|
||||
}
|
||||
/* Transmit packet and wait */
|
||||
telemetry_start(TELEMETRY_APRS, 0xFFFF);
|
||||
while (telemetry_active()) {
|
||||
system_sleep();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,6 +280,21 @@ void aprs_test(void)
|
|||
*/
|
||||
void init(void)
|
||||
{
|
||||
/**
|
||||
* Reset to get the system in a safe state
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
led_reset();
|
||||
si_trx_shutdown();
|
||||
|
||||
/* If the reset was caused by the internal watchdog... */
|
||||
if (PM->RCAUSE.reg & PM_RCAUSE_WDT) {
|
||||
/* External hardware is in an undefined state. Wait here for the
|
||||
external watchdog to trigger an external reset */
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal initialisation
|
||||
* ---------------------------------------------------------------------------
|
||||
|
@ -320,8 +313,8 @@ void init(void)
|
|||
system_events_init();
|
||||
system_extint_init();
|
||||
|
||||
/* Get the current CPU Clock */
|
||||
SystemCoreClock = system_cpu_clock_get_hz();
|
||||
/* Remember the HW watchdog has been running since reset */
|
||||
//watchdog_init();
|
||||
|
||||
/* Configure Sleep Mode */
|
||||
//system_set_sleepmode(SYSTEM_SLEEPMODE_STANDBY);
|
||||
|
@ -335,15 +328,11 @@ void init(void)
|
|||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Set the wdt here. We should get to the first reset in one min */
|
||||
//wdt_init();
|
||||
//wdt_reset_count();
|
||||
|
||||
/* Enables the xosc on gclk1 */
|
||||
/* Enable the xosc on gclk1 */
|
||||
xosc_init();
|
||||
|
||||
led_init();
|
||||
gps_init();
|
||||
/* GPS init */
|
||||
// gps_init();
|
||||
|
||||
/* Enable timer interrupt and event channel */
|
||||
timepulse_extint_init();
|
||||
|
@ -395,32 +384,12 @@ int main(void)
|
|||
|
||||
init();
|
||||
|
||||
led_on();
|
||||
|
||||
|
||||
|
||||
while (1) {
|
||||
/* Sleep wait for next telemetry */
|
||||
while (telemetry_trigger_flag == 0) {
|
||||
system_sleep();
|
||||
}
|
||||
telemetry_trigger_flag = 0;
|
||||
|
||||
/* End pips */
|
||||
telemetry_stop();
|
||||
while (telemetry_active()) {
|
||||
system_sleep();
|
||||
}
|
||||
|
||||
/* Watchdog */
|
||||
//wdt_reset_count();
|
||||
|
||||
/* Send the next packet */
|
||||
/* Send a packet */
|
||||
output_telemetry_string((telemetry_alternate++ & 1) ?
|
||||
TELEMETRY_CONTESTIA :
|
||||
TELEMETRY_RTTY);
|
||||
|
||||
|
||||
/* Maybe aprs? */
|
||||
#if APRS_ENABLE
|
||||
if (aprs_trigger_flag) {
|
||||
|
@ -434,5 +403,17 @@ int main(void)
|
|||
|
||||
/* Measure XOSC against gps timepulse */
|
||||
measure_xosc(XOSC_MEASURE_TIMEPULSE, xosc_measure_callback);
|
||||
|
||||
/* Sleep wait for next telemetry */
|
||||
while (telemetry_trigger_flag == 0) {
|
||||
system_sleep();
|
||||
}
|
||||
telemetry_trigger_flag = 0;
|
||||
|
||||
/* End pips */
|
||||
telemetry_stop();
|
||||
while (telemetry_active()) {
|
||||
system_sleep();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -466,9 +466,9 @@ void si_trx_switch_channel(int16_t channel)
|
|||
}
|
||||
|
||||
/**
|
||||
* Initialises the radio interface to the radio
|
||||
* Resets the radio
|
||||
*/
|
||||
void si_trx_init(void)
|
||||
void si_trx_shutdown(void)
|
||||
{
|
||||
/* Configure the SDN pin */
|
||||
port_pin_set_config(SI406X_SDN_PIN,
|
||||
|
@ -478,6 +478,13 @@ void si_trx_init(void)
|
|||
|
||||
/* Put the transciever in shutdown */
|
||||
_si_trx_sdn_enable();
|
||||
}
|
||||
/**
|
||||
* Initialises the radio interface to the radio
|
||||
*/
|
||||
void si_trx_init(void)
|
||||
{
|
||||
si_trx_shutdown();
|
||||
|
||||
/* Configure the SPI select pin */
|
||||
port_pin_set_config(SI406X_SEL_PIN,
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Functions related to the watchdog.
|
||||
* Copyright (C) 2015 Richard Meadows <richardeoin>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "samd20.h"
|
||||
#include "watchdog.h"
|
||||
#include "hw_config.h"
|
||||
#include "system/gclk.h"
|
||||
#include "system/wdt.h"
|
||||
|
||||
struct idle_counter idle_count, idle_count_max;
|
||||
|
||||
idle_wait_t last_idle_t = IDLE_NONE;
|
||||
|
||||
|
||||
/**
|
||||
* Increments the specified idle counter
|
||||
*/
|
||||
void increment_idle_counter(idle_wait_t idle_t)
|
||||
{
|
||||
switch (idle_t) {
|
||||
case IDLE_WAIT_FOR_GPS:
|
||||
idle_count.wait_for_gps++;
|
||||
break;
|
||||
case IDLE_WHILE_TELEMETRY_ACTIVE:
|
||||
idle_count.while_telemetry_active++;
|
||||
break;
|
||||
case IDLE_WAIT_FOR_NEXT_TELEMETRY:
|
||||
idle_count.wait_for_next_telemetry++;
|
||||
break;
|
||||
default:
|
||||
/* Oh no no no. Let's die here */
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Halts if any idle counter is above it's max
|
||||
*/
|
||||
void check_idle_counters(void)
|
||||
{
|
||||
if ((idle_count.wait_for_gps > MAXIDLE_WAIT_FOR_GPS) ||
|
||||
(idle_count.while_telemetry_active > MAXIDLE_WHILE_TELEMETRY_ACTIVE) ||
|
||||
(idle_count.wait_for_next_telemetry > MAXIDLE_WAIT_FOR_NEXT_TELEMETRY)) {
|
||||
/* Oh dear. Let's die here */
|
||||
while (1);
|
||||
}
|
||||
}
|
||||
#define MAX(a,b) ((a>b)?a:b)
|
||||
#define SET_COUNT_MAX(A) idle_count_max.A = MAX(idle_count_max.A, idle_count.A)
|
||||
/**
|
||||
* Clears the idle counters
|
||||
*/
|
||||
void clear_idle_counters(void)
|
||||
{
|
||||
SET_COUNT_MAX(wait_for_gps);
|
||||
SET_COUNT_MAX(while_telemetry_active);
|
||||
SET_COUNT_MAX(wait_for_next_telemetry);
|
||||
|
||||
/* Zero out counter */
|
||||
memset(&idle_count, 0, sizeof(struct idle_counter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called in idle loops. Kicks the watchdog
|
||||
*
|
||||
* idle_t - The type of idle loop
|
||||
*/
|
||||
void watchdog_do_idle(idle_wait_t idle_t)
|
||||
{
|
||||
/* Check valid */
|
||||
if ((idle_t != IDLE_WAIT_FOR_GPS) &&
|
||||
(idle_t != IDLE_WHILE_TELEMETRY_ACTIVE) &&
|
||||
(idle_t != IDLE_WAIT_FOR_NEXT_TELEMETRY)) {
|
||||
/* Oh dear */
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* Maybe clear */
|
||||
if (idle_t != last_idle_t) {
|
||||
clear_idle_counters();
|
||||
last_idle_t = idle_t;
|
||||
}
|
||||
|
||||
/* Increment the idle counter */
|
||||
increment_idle_counter(idle_t);
|
||||
|
||||
/* Check idle counter is still okay */
|
||||
check_idle_counters();
|
||||
|
||||
/* And finally kick the watchdog */
|
||||
wdt_reset_count();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The internal watchdog is used to bring the processor to a halt and
|
||||
* coredump to external memory.
|
||||
* 0.2s < tout < 0.32s
|
||||
*
|
||||
* The external watchdog then hard resets the MCU and GPS to bring the
|
||||
* system back up in a clean state.
|
||||
* 0.8s < tout < 2.1s
|
||||
*/
|
||||
|
||||
void watchdog_init(void)
|
||||
{
|
||||
/* 0.25 seconds timeout. So 2^(15-2) cycles of the 32.768kHz wdt clock */
|
||||
system_gclk_gen_set_config(WDT_GCLK,
|
||||
GCLK_SOURCE_OSCULP32K, /* Source */
|
||||
false, /* High When Disabled */
|
||||
128, /* Division Factor 2^7 */
|
||||
false, /* Run in standby */
|
||||
true); /* Output Pin Enable */
|
||||
system_gclk_gen_enable(WDT_GCLK);
|
||||
|
||||
/* Set the watchdog timer. On 256Hz gclk */
|
||||
wdt_set_config(true, /* Lock WDT */
|
||||
true, /* Enable WDT */
|
||||
WDT_GCLK, /* Clock Source */
|
||||
WDT_PERIOD_64CLK, /* Timeout Period div 2^6 */
|
||||
WDT_PERIOD_NONE, /* Window Period */
|
||||
WDT_PERIOD_NONE); /* Early Warning Period */
|
||||
|
||||
wdt_reset_count();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called for the watchdog early warning interrupt
|
||||
*/
|
||||
void WDT_Handler(void) {
|
||||
|
||||
/* Coredump */
|
||||
|
||||
/* Wait for the watchdog to kill us */
|
||||
while (1);
|
||||
}
|
Ładowanie…
Reference in New Issue