From 5d6d35d9dc253199b6f4deff8edb962d6075df00 Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Sat, 4 Jul 2015 20:47:58 +0100 Subject: [PATCH] Increase the frequency of the internal watchdog gclk so we don't get massive lag when kicking it. Also fix up varous timing issues / speed things up --- firmware/inc/hw_config.h | 4 ++++ firmware/inc/si_trx.h | 5 ++++- firmware/src/si_trx.c | 10 +--------- firmware/src/telemetry.c | 13 ++++--------- firmware/src/timer.c | 5 +++++ firmware/src/watchdog.c | 30 ++++++++++++++++-------------- 6 files changed, 34 insertions(+), 33 deletions(-) diff --git a/firmware/inc/hw_config.h b/firmware/inc/hw_config.h index fb18e24..80e14c4 100644 --- a/firmware/inc/hw_config.h +++ b/firmware/inc/hw_config.h @@ -167,7 +167,11 @@ /** * Watchdog Timer + * + * There is a performance penalty to using the watchdog - you must + * wait up to 1/16kHz when kicking to sync with it. Disable when not in use */ +#define DEBUG_USE_INTWATCHDOG 1 #define WDT_GCLK GCLK_GENERATOR_4 /** diff --git a/firmware/inc/si_trx.h b/firmware/inc/si_trx.h index 7d8e95f..a53753d 100644 --- a/firmware/inc/si_trx.h +++ b/firmware/inc/si_trx.h @@ -34,7 +34,10 @@ void si_trx_modem_set_deviation(uint32_t deviation); void si_trx_on(uint8_t modulation_type, uint32_t frequency, uint16_t deviation, uint8_t power); void si_trx_off(void); -void si_trx_switch_channel(int16_t channel); + +void si_trx_modem_set_offset(int16_t channel); +#define si_trx_switch_channel si_trx_modem_set_offset + void si_trx_shutdown(void); void si_trx_init(void); diff --git a/firmware/src/si_trx.c b/firmware/src/si_trx.c index 5c3dd86..fd49f66 100644 --- a/firmware/src/si_trx.c +++ b/firmware/src/si_trx.c @@ -300,7 +300,7 @@ static void si_trx_modem_tx_filter_coefficients(uint8_t* coeff_array) * * This is a signed 16-bit value. */ -static void si_trx_modem_set_offset(int16_t offset) +void si_trx_modem_set_offset(int16_t offset) { /* _si_trx_set_property_16(SI_PROPERTY_GROUP_MODEM, */ /* SI_MODEM_FREQ_OFFSET, */ @@ -489,14 +489,6 @@ void si_trx_off(void) _si_trx_sdn_enable(); } -/** - * Switches the transmission to the specified channel. Signed 16-bit int - */ -void si_trx_switch_channel(int16_t channel) -{ - si_trx_modem_set_offset(channel); -} - /** * Resets the radio */ diff --git a/firmware/src/telemetry.c b/firmware/src/telemetry.c index d291c70..1a1e156 100644 --- a/firmware/src/telemetry.c +++ b/firmware/src/telemetry.c @@ -363,6 +363,8 @@ const uint8_t tick_gclk_gen_num = 1; */ void timer0_tick_init(uint32_t count) { + tc_reset(TC0); + /* Configure Timer 0 */ bool t0_capture_channel_enables[] = {false, false}; uint32_t t0_compare_channel_values[] = {count, 0x0000}; @@ -381,15 +383,8 @@ void timer0_tick_init(uint32_t count) t0_capture_channel_enables, /* Capture Channel Enables */ t0_compare_channel_values); /* Compare Channels Values */ - /* Enable Events */ - struct tc_events event; - memset(&event, 0, sizeof(struct tc_events)); - event.generate_event_on_compare_channel[0] = true; - event.event_action = TC_EVENT_ACTION_RETRIGGER; - tc_enable_events(TC0, &event); - /* Enable Interrupt */ - TC0->COUNT16.INTENSET.reg = TC_INTENSET_MC0; + TC0->COUNT32.INTENSET.reg = TC_INTENSET_MC0; irq_register_handler(TC0_IRQn, TC0_INT_PRIO); /* Highest Priority */ /* Enable Timer */ @@ -420,7 +415,7 @@ void timer0_tick_deinit() */ void TC0_Handler(void) { - if (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); telemetry_tick(); diff --git a/firmware/src/timer.c b/firmware/src/timer.c index 67d7252..c3e2f3e 100644 --- a/firmware/src/timer.c +++ b/firmware/src/timer.c @@ -30,6 +30,7 @@ #include "system/extint.h" #include "system/events.h" #include "system/interrupt.h" +#include "system/port.h" uint32_t gps_timepulse_count = 0; uint32_t timepulse_sequence = 0; @@ -48,6 +49,10 @@ void timepulse_extint_init(void) { extint_enable_events(&events); /* Configure extinit channel */ + /** + * We trigger on both edges so that we get woken up at 2x the tick + * rate. This means we can kick the watchdog often enough. + */ struct extint_chan_conf config; config.gpio_pin = GPS_TIMEPULSE_PIN; config.gpio_pin_mux = GPS_TIMEPULSE_PINMUX; diff --git a/firmware/src/watchdog.c b/firmware/src/watchdog.c index 89a5bdc..63a83eb 100644 --- a/firmware/src/watchdog.c +++ b/firmware/src/watchdog.c @@ -93,12 +93,6 @@ void clear_idle_counters(void) */ void kick_the_watchdog(void) { - /* tc_set_count_value(TC1, 0); */ - /* tc_clear_status(TC1, TC_STATUS_CHANNEL_0_MATCH); */ - - wdt_reset_count(); - - kick_external_watchdog(); } /** * Called in idle loops. Kicks the watchdog @@ -128,20 +122,28 @@ void idle(idle_wait_t idle_t) check_idle_counters(); /* Kick the watchdog */ - kick_the_watchdog(); +#ifdef DEBUG_USE_INTWATCHDOG + wdt_reset_count(); +#endif + + port_pin_set_output_level(WDT_WDI_PIN, 0); /* And sleep */ system_sleep(); /* Same again when we wake from sleep */ - kick_the_watchdog(); +#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 * coredump to external memory. - * 0.4s < t_early_w < 0.64s + * 0.8s < t_early_w < 0.128s * * The external watchdog then hard resets the MCU and GPS to bring the * system back up in a clean state. @@ -157,30 +159,30 @@ void watchdog_init(void) false); /* Powersave */ kick_external_watchdog(); /* Kick External */ +#if DEBUG_USE_INTWATCHDOG /* /\* 0.5s early warn. So 2^(15-1) cycles of the 32.768kHz ulposc *\/ */ system_gclk_gen_set_config(WDT_GCLK, GCLK_SOURCE_OSCULP32K, /* Source */ false, /* High When Disabled */ - 128, /* Division Factor 2^7 */ + 4, /* Division Factor 1 */ false, /* Run in standby */ true); /* Output Pin Enable */ system_gclk_gen_enable(WDT_GCLK); - /* Set the watchdog timer. On 256Hz gclk */ + /* Set the watchdog timer. On 8kHz gclk */ wdt_set_config(false, /* Lock WDT */ true, /* Enable WDT */ WDT_GCLK, /* Clock Source */ WDT_PERIOD_16384CLK, /* Timeout Period */ WDT_PERIOD_NONE, /* Window Period */ - WDT_PERIOD_128CLK); /* Early Warning Period */ + WDT_PERIOD_8192CLK); /* Early Warning Period */ WDT->INTENSET.reg |= WDT_INTENSET_EW; WDT->INTFLAG.reg |= WDT_INTFLAG_EW; irq_register_handler(WDT_IRQn, WDT_INT_PRIO); - /* Kick Watchdogs */ - kick_external_watchdog(); wdt_reset_count(); +#endif }