Started new watchdog and init process.

master
Richard Meadows 2015-06-24 22:44:07 +01:00
rodzic 3e87c0b877
commit 4f33da8740
5 zmienionych plików z 281 dodań i 75 usunięć

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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