Brought up gps on new hw, various bugfix, pre-calculate telemetry timer counts and more

master
Richard Meadows 2015-07-03 23:40:47 +01:00
rodzic b65216498d
commit 08e3d30c25
16 zmienionych plików z 247 dodań i 170 usunięć

Wyświetl plik

@ -8,12 +8,12 @@
||gclk7|aprs clock, fed from gclk1, div 6 / 11
|
|*TC*||
||tc0|telemetry tick timer. 32-bit
||tc0|telemetry tick timer. 32-bit. glck1
||tc1|^^^^^
||tc2|counts cycles of tcxo. 32-bit
||tc2|counts cycles of tcxo. 32-bit. gclk1
||tc3|^^^^^
||tc4|osc8m event source
||tc5|telemetry pwm 16-bit, ALSO aprs carrier 16-bit
||tc4|unused (osc8m event source)
||tc5|telemetry pwm 16-bit glck0, ALSO aprs carrier 16-bit gclk7
|
|*EXTINT*|
||extint[5]|gps timepulse
@ -32,11 +32,11 @@
| Name | Function | Priority H(0-3)L | Notes
| --- | --- | --- | ---
|TC0_IRQn|telemetry tick timer|0|latency critical for symbol timing. rate <= 1200Hz
|[GPS_SERCOM]_IRQn|gps usart rx|1|latency not so critical. rate <= 960Hz
|EIC_IRQn|timepulse|2|latency not so critical. rate = 1
|TC2_IRQn|xosc measurement done|2|latency not critical
|ADC_IRQn|adc measurement done|2|latency not critical
|TC0_IRQn|telemetry tick timer|1|latency critical for symbol timing. rate <= 1200Hz
|[GPS_SERCOM]_IRQn|gps usart rx|2|latency not so critical. rate <= 960Hz
|EIC_IRQn|timepulse|3|latency not so critical. rate = 1
|TC2_IRQn|xosc measurement done|3|latency not critical
|ADC_IRQn|adc measurement done|3|latency not critical

Wyświetl plik

@ -66,6 +66,7 @@
#define GPS_SERCOM_MIGO_PIN PIN_PA07
#define GPS_SERCOM_MIGO_PINMUX PINMUX_PA07D_SERCOM0_PAD3
#define GPS_SERCOM_MUX USART_RX_3_TX_2_XCK_3
#define GPS_BAUD_RATE 9600
#define GPS_PLATFORM_MODEL UBX_PLATFORM_MODEL_AIRBORNE_1G
#define GPS_TIMEPULSE_PIN PIN_PA05
#define GPS_TIMEPULSE_PINMUX PINMUX_PA05A_EIC_EXTINT5
@ -75,7 +76,7 @@
/**
* USART Loopback Testing
*/
#define USART_MUX_LOOPBACK USART_RX_0_TX_0_XCK_1
#define USART_MUX_LOOPBACK USART_RX_2_TX_2_XCK_3
/**
* Flash Memory
@ -185,14 +186,16 @@
/**
* Interrupt Priority
*/
#define TC0_INT_PRIO 0 /* Telemetry Tick Timer */
#define WDT_INT_PRIO 0 /* Early warning interrupt */
#define GPS_SERCOM_INT_PRIO 1 /* GPS USART Rx */
#define TC0_INT_PRIO 1 /* Telemetry Tick Timer */
#define EIC_INT_PRIO 2 /* Timepulse, telemetry */
#define GPS_SERCOM_INT_PRIO 2 /* GPS USART Rx */
#define TC2_INT_PRIO 2 /* XOSC Measure Timer */
#define EIC_INT_PRIO 3 /* Timepulse, telemetry */
#define ADC_INT_PRIO 2 /* ADC */
#define TC2_INT_PRIO 3 /* XOSC Measure Timer */
#define ADC_INT_PRIO 3 /* ADC */
#endif /* HW_CONFIG_H */

Wyświetl plik

@ -50,15 +50,12 @@ int telemetry_start_rsid(rsid_code_t rsid);
void telemetry_aprs_set_frequency(int32_t frequency);
float telemetry_si_temperature(void);
float timer0_tick_init(float frequency);
uint32_t timer0_tick_frequency(float frequency);
void timer0_tick_init(uint32_t count);
void timer0_tick_deinit();
void telemetry_init();
void telemetry_gpio1_pwm_init(void);
void telemetry_gpio1_pwm_duty(float duty_cycle);
void telemetry_gpio1_pwm_deinit(void);
void telemetry_gpio1_init(void);
void telemetry_gpio1_set(uint8_t value);
#endif /* TELEMETRY_H */

Wyświetl plik

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

Wyświetl plik

@ -197,11 +197,6 @@ uint8_t aprs_start(void)
telemetry
);
// RTTY/434.6U8N2",
/* Let's actually try that out.. We can add comment etc. later */
/* Transmit the frame using ax25 */
ax25_start(addresses, addresses_len,
information, information_len);

Wyświetl plik

@ -40,7 +40,8 @@ struct tracker_time time = {0};
struct tracker_datapoint* dp;
/* Low Power Mode */
#define LOW_POWER(d) (d->solar < 0.2)
#define LOW_POWER(d) (0)
//(d->solar < 0.2)
void rtty_telemetry(struct tracker_datapoint* dp);
void contestia_telemetry(struct tracker_datapoint* dp);
@ -86,26 +87,26 @@ void do_cron(void)
memcpy(&t, &time, sizeof(struct tracker_time));
/* ---- Data every 30 seconds ---- */
if ((time.second % 30) == 0) {
if ((t.second % 30) == 0) {
dp = collect_data();
memcpy(&dp->time, &t, sizeof(struct tracker_time));
} else if ((time.second % 30) == 20) {
memcpy(&dp->time, &time, sizeof(struct tracker_time));
} else if ((t.second % 30) == 20) {
collect_data_async();
}
/* ---- Telemetry output ---- */
/* RTTY */
if (time.second == 0 && !LOW_POWER(dp)) {
if (t.second == 0 && !LOW_POWER(dp)) {
rtty_telemetry(dp);
/* Contestia */
} else if (time.second == 30 && !LOW_POWER(dp)) {
} else if (t.second == 30 && !LOW_POWER(dp)) {
contestia_telemetry(dp);
/* Low Power */
} else if (time.second == 0 && LOW_POWER(dp)) {
if ((time.minute % 2) == 0) {
} else if (t.second == 0 && LOW_POWER(dp)) {
if ((t.minute % 2) == 0) {
rtty_telemetry(dp);
} else {
contestia_telemetry(dp);
@ -113,18 +114,18 @@ void do_cron(void)
/* APRS */
#ifdef APRS_ENABLE
} else if ((time.minute % 2) == 0 && time.second == 55) {
} else if ((t.minute % 2) == 0 && t.second == 55) {
aprs_telemetry(dp);
#endif
/* Pips */
} else if ((time.second % 1) == 0) {
} else if ((t.second % 1) == 0) {
pips_telemetry();
}
/* ---- Record for backlog ---- */
if ((time.minute == 0) && (time.second == 25)) {
if ((t.minute % 1 == 0) && (t.second == 25)) {
record_backlog(dp);
}
}
@ -136,11 +137,11 @@ void cron_tick(void) {
/* Update time internally */
time.epoch++; time.second++;
if (time.second > 60) {
if (time.second >= 60) {
time.second = 0; time.minute++;
if (time.minute > 60) {
if (time.minute >= 60) {
time.minute = 0; time.hour++;
if (time.hour > 23) {
if (time.hour >= 24) {
time.hour = 0;
}
}
@ -151,7 +152,7 @@ void cron_tick(void) {
if (((time.hour == 0) && (time.minute == 0) && (time.second == 5)) ||
((time.second == 5) && !(time.valid & UBX_TIMEUTC_VALID_UTC))) {
/* Be careful not a call this while the collect_data function is running */
/* Be careful not to call this while the collect_data function is running */
read_gps_time();
}
}

Wyświetl plik

@ -49,6 +49,9 @@ void collect_data_async(void)
{
/* Measure XOSC against gps timepulse */
measure_xosc(XOSC_MEASURE_TIMEPULSE, xosc_measure_callback);
/* Analogue Measurements */
start_adc_conversion_sequence();
}
/**
* Collect Data synchronously and return datapoint

Wyświetl plik

@ -35,6 +35,7 @@
#include "util/dbuffer.h"
#include "ubx_messages.h"
#include "gps.h"
#include "watchdog.h"
/**
* UBX Constants
@ -264,13 +265,13 @@ void _ubx_poll(ubx_message_t* message) {
/**
* Disable NMEA messages on the uBlox
*/
void gps_disable_nmea(void)
void gps_set_io_config(uint32_t baud_rate)
{
ubx_cfg_prt.payload.portID = 1;
ubx_cfg_prt.payload.res0 = 0;
ubx_cfg_prt.payload.txReady = 0;
ubx_cfg_prt.payload.mode = 0x08D0; /* 8 bit, No Parity */
ubx_cfg_prt.payload.baudRate = 9600;
ubx_cfg_prt.payload.baudRate = baud_rate;
ubx_cfg_prt.payload.inProtoMask = 0x7; /* UBX */
ubx_cfg_prt.payload.outProtoMask = 0x1; /* UBX */
ubx_cfg_prt.payload.flags = 0;
@ -450,9 +451,9 @@ void gps_set_powersave_auto(void)
}
/**
* Init
* Init + enable for the usart at the given baud rate
*/
void gps_init(void)
void gps_usart_init_enable(uint32_t baud_rate)
{
/* USART */
usart_init(GPS_SERCOM,
@ -468,7 +469,7 @@ void gps_init(void)
false, /** Enable LIN Slave Support */
false, /** Enable start of frame dection */
false, /** Enable collision dection */
9600, /** USART Baud rate */
baud_rate, /** USART Baud rate */
true, /** Enable receiver */
true, /** Enable transmitter */
false, /** Sample on the rising edge of XLCK */
@ -483,19 +484,34 @@ void gps_init(void)
PINMUX_UNUSED); /** PAD3 pinmux */
usart_enable(GPS_SERCOM);
}
/**
* Init
*/
void gps_init(void)
{
/* Enable usart */
gps_usart_init_enable(GPS_BAUD_RATE);
kick_the_watchdog();
/* We use ubx protocol */
gps_disable_nmea();
gps_set_io_config(GPS_BAUD_RATE);
/* Incoming ubx messages are handled in an irq */
usart_register_rx_callback(GPS_SERCOM, gps_rx_callback, GPS_SERCOM_INT_PRIO);
kick_the_watchdog();
/* Set the platform model */
gps_set_platform_model();
/* Set which GNSS constellation we'd like to use */
gps_set_gnss();
kick_the_watchdog();
/* Exit powersave mode to start */
gps_set_powersave(false);
@ -524,7 +540,7 @@ void usart_loopback_test(void)
false, /** Enable LIN Slave Support */
false, /** Enable start of frame dection */
false, /** Enable collision dection */
9600, /** USART Baud rate */
GPS_BAUD_RATE, /** USART Baud rate */
true, /** Enable receiver */
true, /** Enable transmitter */
false, /** Sample on the rising edge of XLCK */
@ -532,8 +548,8 @@ void usart_loopback_test(void)
0, /** External clock frequency in synchronous mode. */
false, /** Run in standby */
GCLK_GENERATOR_0, /** GCLK generator source */
PINMUX_DEFAULT, /** PAD0 pinmux */
PINMUX_DEFAULT, /** PAD1 pinmux */
GPS_SERCOM_MOGI_PINMUX, /** PAD0 pinmux */
GPS_SERCOM_MIGO_PINMUX, /** PAD1 pinmux */
PINMUX_UNUSED, /** PAD2 pinmux */
PINMUX_UNUSED); /** PAD3 pinmux */
@ -542,5 +558,5 @@ void usart_loopback_test(void)
usart_write_wait(GPS_SERCOM, 0x34);
usart_read_wait(GPS_SERCOM, &data);
semihost_printf("Rx'ed: 0x%02x\n", data);
usart_disable(GPS_SERCOM);
}

Wyświetl plik

@ -73,14 +73,6 @@ void init(timepulse_callback_t callback)
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
* ---------------------------------------------------------------------------
@ -100,7 +92,7 @@ void init(timepulse_callback_t callback)
system_extint_init();
/* Watchdog */
//watchdog_init();
watchdog_init();
/* Configure Sleep Mode */
//system_set_sleepmode(SYSTEM_SLEEPMODE_STANDBY);
@ -120,8 +112,11 @@ void init(timepulse_callback_t callback)
/* Enable the xosc on gclk1 */
xosc_init();
/* Telemetry init depends on gclk */
telemetry_init();
/* GPS init */
// gps_init();
gps_init();
/* Enable timer interrupt and event channel */
timepulse_extint_init();

Wyświetl plik

@ -40,6 +40,7 @@
#include "rf_tests.h"
#include "data.h"
#include "backlog.h"
#include "pips.h"
#define CALLSIGN "UBSEDSx"
#define APRS_COMMENT "RTTY/434.6U8N2"
@ -50,7 +51,7 @@
* The telemetry string starts with the specified number of dollar signs
*/
uint16_t format_telemetry_string(char* string, struct tracker_datapoint* dp,
uint8_t dollars)
uint8_t dollars, uint8_t reduce_char_set)
{
double lat_fmt = 0.0;
double lon_fmt = 0.0;
@ -73,6 +74,11 @@ uint16_t format_telemetry_string(char* string, struct tracker_datapoint* dp,
lat_fmt, lon_fmt, altitude, dp->satillite_count,
dp->battery, dp->temperature, dp->xosc_error);
if (reduce_char_set) {
/* Reduce character set */
contestiaize(telemetry_string + dollars);
}
/* sprintf - checksum. don't include dollars */
len += sprintf(telemetry_string + len,
"*%04X\r",
@ -93,6 +99,11 @@ uint16_t format_telemetry_string(char* string, struct tracker_datapoint* dp,
dp->time.hour, dp->time.minute, dp->time.second,
lat_fmt, lon_fmt, altitude);
if (reduce_char_set) {
/* Reduce character set */
contestiaize(telemetry_string + dollars);
}
/* sprintf - checksum. don't include dollars */
len += sprintf(telemetry_string + len,
"*%04X\r",
@ -109,7 +120,7 @@ uint16_t format_telemetry_string(char* string, struct tracker_datapoint* dp,
void rtty_telemetry(struct tracker_datapoint* dp) {
uint16_t len;
len = format_telemetry_string(telemetry_string, dp, RTTY_DOLLARS);
len = format_telemetry_string(telemetry_string, dp, RTTY_DOLLARS, 0);
/* Main telemetry */
telemetry_start(TELEMETRY_RTTY, len);
@ -126,10 +137,7 @@ void rtty_telemetry(struct tracker_datapoint* dp) {
void contestia_telemetry(struct tracker_datapoint* dp) {
uint16_t len;
len = format_telemetry_string(telemetry_string, dp, CONTESTIA_DOLLARS);
/* Reduce character set */
contestiaize(telemetry_string + CONTESTIA_DOLLARS);
len = format_telemetry_string(telemetry_string, dp, CONTESTIA_DOLLARS, 1);
/* RSID */
telemetry_start_rsid(RSID_CONTESTIA_32_1000);

Wyświetl plik

@ -29,6 +29,7 @@
#include "telemetry.h"
#include "aprs.h"
#include "ax25.h"
#include "watchdog.h"
#define APRS_TEST_LAT 51.47
#define APRS_TEST_LON -2.58
@ -39,10 +40,14 @@ void telemetry_tone(void)
{
while (1) {
si_trx_on(SI_MODEM_MOD_TYPE_CW, TELEMETRY_FREQUENCY, 0, 36);
for (int i = 0; i < 200*1000; i++);
for (int i = 0; i < 200*1000; i++) {
idle(IDLE_TELEMETRY_ACTIVE);
}
si_trx_off();
si_trx_on(SI_MODEM_MOD_TYPE_CW, TELEMETRY_FREQUENCY, 0, 0x7f);
for (int i = 0; i < 200*1000; i++);
for (int i = 0; i < 200*1000; i++) {
idle(IDLE_TELEMETRY_ACTIVE);
}
si_trx_off();
}
}
@ -50,10 +55,14 @@ void aprs_tone(void)
{
while (1) {
si_trx_on(SI_MODEM_MOD_TYPE_CW, APRS_TEST_FREQUENCY, 0, 36);
for (int i = 0; i < 200*1000; i++);
for (int i = 0; i < 200*1000; i++) {
idle(IDLE_TELEMETRY_ACTIVE);
}
si_trx_off();
si_trx_on(SI_MODEM_MOD_TYPE_CW, APRS_TEST_FREQUENCY, 0, 0x7f);
for (int i = 0; i < 200*1000; i++);
for (int i = 0; i < 200*1000; i++) {
idle(IDLE_TELEMETRY_ACTIVE);
}
si_trx_off();
}
}
@ -75,7 +84,9 @@ void aprs_high_fm_tone(void)
si_trx_on(SI_MODEM_MOD_TYPE_2GFSK, APRS_TEST_FREQUENCY,
AX25_DEVIATION, APRS_POWER);
while (1);
while (1) {
idle(IDLE_TELEMETRY_ACTIVE);
}
}
/**
@ -92,7 +103,9 @@ void aprs_test(void)
/* Transmit packet and wait */
telemetry_start(TELEMETRY_APRS, 0xFFFF);
while (telemetry_active());
while (telemetry_active()) {
idle(IDLE_TELEMETRY_ACTIVE);
}
}
}

Wyświetl plik

@ -626,7 +626,7 @@ static usart_rx_callback_t _usart_rx_callbacks[SERCOM_INST_NUM] = {
void _usart_interrupt_handler(Sercom* const sercom_instance, uint8_t instance_index)
{
/* Hardware instance */
SercomUsart* const hw = (SercomUsart*)SERCOM1; //sercom_instance;
SercomUsart* const hw = (SercomUsart*)sercom_instance;
/* Temporary variables */
uint16_t interrupt_status;

Wyświetl plik

@ -421,13 +421,15 @@ void si_trx_reset(uint8_t modulation_type, uint32_t frequency,
{
_si_trx_sdn_enable(); /* active high shutdown = reset */
for (int i = 0; i < 15*1000; i++); /* Approx. 15ms */
for (int i = 0; i < 15*1000; i++); /* Approx. 15 */
_si_trx_sdn_disable(); /* booting */
for (int i = 0; i < 15*1000; i++); /* Approx. 15ms */
uint16_t part_number = si_trx_get_part_info();
while (part_number != 17512);
/* Power Up */
si_trx_power_up(SI_POWER_UP_TCXO, VCXO_FREQUENCY);
@ -573,6 +575,7 @@ void spi_loopback_test(void)
/* SI4xxx_SERCOM_MISO_PINMUX, /\** Pinmux *\/ */
/* SI4xxx_SERCOM_SCK_PINMUX, /\** Pinmux *\/ */
/* PINMUX_UNUSED); /\** Pinmux *\/ */
/* spi_enable(SI_TRX_SERCOM); */
/* Init loopback */
spi_bitbang_init(SI4xxx_SERCOM_MOSI_PIN,

Wyświetl plik

@ -126,6 +126,8 @@ int telemetry_active(void) {
return (telemetry_string_length > 0);
}
uint32_t contestia_timer_count, rtty_timer_count;
uint32_t pips_timer_count, ax25_timer_count, rsid_timer_count;
/**
* Starts telemetry output
*
@ -142,16 +144,16 @@ int telemetry_start(enum telemetry_t type, int32_t length) {
/* Setup timer tick */
switch(telemetry_type) {
case TELEMETRY_CONTESTIA:
timer0_tick_init(CONTESTIA_SYMBOL_RATE);
timer0_tick_init(contestia_timer_count);
break;
case TELEMETRY_RTTY:
timer0_tick_init(RTTY_BITRATE);
timer0_tick_init(rtty_timer_count);
break;
case TELEMETRY_PIPS:
timer0_tick_init(PIPS_FREQUENCY);
timer0_tick_init(pips_timer_count);
break;
case TELEMETRY_APRS:
timer0_tick_init(AX25_TICK_RATE);
timer0_tick_init(ax25_timer_count);
break;
case TELEMETRY_RSID: /* Not used - see function below */
break;
@ -178,7 +180,7 @@ int telemetry_start_rsid(rsid_code_t rsid) {
rsid_start(rsid);
/* Setup timer tick */
timer0_tick_init(RSID_SYMBOL_RATE);
timer0_tick_init(rsid_timer_count);
return 0; /* Success */
} else {
@ -335,10 +337,11 @@ void telemetry_tick(void) {
radio_on = 1;
} else { /* Turn off */
si_trx_off(); radio_on = 0;
si_trx_off(); radio_on = 0;
telemetry_stop();
}
break;
}
}
@ -358,12 +361,8 @@ const uint8_t tick_gclk_gen_num = 1;
*
* Returns the frequency we actually initialised.
*/
float timer0_tick_init(float frequency)
void timer0_tick_init(uint32_t count)
{
/* Calculate the wrap value for the given frequency */
float gclk_frequency = (float)system_gclk_gen_get_hz(tick_gclk_gen_num);
uint32_t count = (uint32_t)(gclk_frequency / frequency);
/* Configure Timer 0 */
bool t0_capture_channel_enables[] = {false, false};
uint32_t t0_compare_channel_values[] = {count, 0x0000};
@ -390,32 +389,21 @@ float timer0_tick_init(float frequency)
tc_enable_events(TC0, &event);
/* Enable Interrupt */
TC0->COUNT32.INTENSET.reg = (1 << 4);
TC0->COUNT16.INTENSET.reg = TC_INTENSET_MC0;
irq_register_handler(TC0_IRQn, TC0_INT_PRIO); /* Highest Priority */
/* Enable Timer */
tc_enable(TC0);
tc_start_counter(TC0);
/* Return the frequency we actually initialised */
return gclk_frequency / (float)count;
}
/**
* Changes the timer0 frequency.
*
* Returns the timer count that this corresponds to.
* Gets the count value required on timer0 for a specific frequency
*/
uint32_t timer0_tick_frequency(float frequency)
uint32_t timer0_get_count_value(float frequency)
{
float gclk_frequency = (float)system_gclk_gen_get_hz(tick_gclk_gen_num);
uint32_t count = (uint32_t)(gclk_frequency / frequency);
tc_set_compare_value(TC0,
TC_COMPARE_CAPTURE_CHANNEL_0,
count);
/* We need to reset the count here so it's not beyond the capture limit */
tc_set_count_value(TC0, 0);
return count;
}
/**
@ -437,9 +425,28 @@ void TC0_Handler(void)
telemetry_tick();
}
}
/**
* Init. Mostly used for calculating timer counts. Must be called after gclk1
*/
void telemetry_init(void)
{
contestia_timer_count = timer0_get_count_value(CONTESTIA_SYMBOL_RATE);
rtty_timer_count = timer0_get_count_value(RTTY_BITRATE);
pips_timer_count = timer0_get_count_value(PIPS_FREQUENCY);
ax25_timer_count = timer0_get_count_value(AX25_TICK_RATE);
rsid_timer_count = timer0_get_count_value(RSID_SYMBOL_RATE);
}
/**
* =========== PWM
*/
#define GPIO1_PWM_STEPS 200 // ~ 2kHz on a 4 MHz clock
/**

Wyświetl plik

@ -29,7 +29,11 @@
#include "hw_config.h"
#include "system/gclk.h"
#include "system/wdt.h"
#include "system/interrupt.h"
#include "system/port.h"
#include "tc/tc_driver.h"
#include "si_trx.h"
#include "init.h"
struct idle_counter idle_count, idle_count_max;
@ -84,6 +88,18 @@ void clear_idle_counters(void)
memset(&idle_count, 0, sizeof(struct idle_counter));
}
/**
* Kick
*/
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
*
@ -112,8 +128,7 @@ void idle(idle_wait_t idle_t)
check_idle_counters();
/* Kick the watchdog */
wdt_reset_count();
kick_external_watchdog();
kick_the_watchdog();
/* And sleep */
system_sleep();
@ -123,7 +138,7 @@ void idle(idle_wait_t idle_t)
/**
* The internal watchdog is used to bring the processor to a halt and
* coredump to external memory.
* 0.2s < tout < 0.32s
* 0.4s < t_early_w < 0.64s
*
* The external watchdog then hard resets the MCU and GPS to bring the
* system back up in a clean state.
@ -139,36 +154,56 @@ void watchdog_init(void)
false); /* Powersave */
kick_external_watchdog(); /* Kick External */
/* 0.25 seconds timeout. So 2^(15-2) cycles of the 32.768kHz wdt clock */
/* /\* 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 */
false, /* Run in standby */
true); /* Output Pin Enable */
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_set_config(false, /* Lock WDT */
true, /* Enable WDT */
WDT_GCLK, /* Clock Source */
WDT_PERIOD_16384CLK, /* Timeout Period */
WDT_PERIOD_NONE, /* Window Period */
WDT_PERIOD_256CLK); /* Early Warning Period */
WDT->INTENSET.reg |= WDT_INTENSET_EW;
WDT->INTFLAG.reg |= WDT_INTFLAG_EW;
irq_register_handler(WDT_IRQn, 0);
/* Kick Watchdogs */
wdt_reset_count();
kick_external_watchdog();
wdt_reset_count();
}
/**
* Called for the watchdog early warning interrupt
*/
void WDT_Handler(void) {
void WDT_Handler(void)
{
Wdt *const hw = WDT;
/* Bring the system into a safe state */
si_trx_shutdown();
/* LED on */
led_on();
/* Coredump */
/* Wait for the watchdog to kill us */
while (1);
/* Wait for the external watchdog to kill us */
while (1) {
led_on();
for (int i = 0; i < 25*1000; i++);
led_off();
for (int i = 0; i < 25*1000; i++);
/**
* Whilst this is generally bad practice in this system we have an
* external watchdog for the actual reset.
*/
wdt_reset_count();
}
}

Wyświetl plik

@ -97,59 +97,59 @@ void osc8m_set_calibration(struct osc8m_calibration_t calib) {
/**
* Configure timer 4 to generate events at 1Hz of OSC8M
*/
void osc8m_event_source(void) {
/* void osc8m_event_source(void) { */
/* Timer 4 runs on GCLK0 (4MHz) */
bool t4_capture_channel_enables[] = {false, false};
uint32_t t4_compare_channel_values[] = {15625, 0x0000};
/* Divide by 256*15625 = 1Hz events */
tc_init(TC4,
GCLK_GENERATOR_0,
TC_COUNTER_SIZE_16BIT,
TC_CLOCK_PRESCALER_DIV256,
TC_WAVE_GENERATION_NORMAL_FREQ,
TC_RELOAD_ACTION_GCLK,
TC_COUNT_DIRECTION_UP,
TC_WAVEFORM_INVERT_OUTPUT_NONE,
false, /* Oneshot */
false, /* Run in standby */
0x0000, /* Initial value */
0xFFFF, /* Top value */
t4_capture_channel_enables, /* Capture Channel Enables */
t4_compare_channel_values); /* Compare Channels Values */
/* /\* Timer 4 runs on GCLK0 (4MHz) *\/ */
/* bool t4_capture_channel_enables[] = {false, false}; */
/* uint32_t t4_compare_channel_values[] = {15625, 0x0000}; */
/* /\* Divide by 256*15625 = 1Hz events *\/ */
/* tc_init(TC4, */
/* GCLK_GENERATOR_0, */
/* TC_COUNTER_SIZE_16BIT, */
/* TC_CLOCK_PRESCALER_DIV256, */
/* TC_WAVE_GENERATION_NORMAL_FREQ, */
/* TC_RELOAD_ACTION_GCLK, */
/* TC_COUNT_DIRECTION_UP, */
/* TC_WAVEFORM_INVERT_OUTPUT_NONE, */
/* false, /\* Oneshot *\/ */
/* false, /\* Run in standby *\/ */
/* 0x0000, /\* Initial value *\/ */
/* 0xFFFF, /\* Top value *\/ */
/* t4_capture_channel_enables, /\* Capture Channel Enables *\/ */
/* t4_compare_channel_values); /\* Compare Channels Values *\/ */
/* Timer 4 generates an event on compare channel 0 */
struct tc_events events;
events.generate_event_on_compare_channel[0] = true;
events.generate_event_on_compare_channel[1] = false;
events.generate_event_on_overflow = false;
events.invert_event_input = false;
events.on_event_perform_action = true;
events.event_action = TC_EVENT_ACTION_RETRIGGER;
tc_enable_events(TC4, &events);
/* /\* Timer 4 generates an event on compare channel 0 *\/ */
/* struct tc_events events; */
/* events.generate_event_on_compare_channel[0] = true; */
/* events.generate_event_on_compare_channel[1] = false; */
/* events.generate_event_on_overflow = false; */
/* events.invert_event_input = false; */
/* events.on_event_perform_action = true; */
/* events.event_action = TC_EVENT_ACTION_RETRIGGER; */
/* tc_enable_events(TC4, &events); */
events_attach_user(0, 4); // Timer 4 is event user on channel 1
/* events_attach_user(0, 4); // Timer 4 is event user on channel 1 */
/* This event is picked up on event channel 0 */
events_allocate(0,
EVENTS_EDGE_DETECT_NONE,
EVENTS_PATH_ASYNCHRONOUS,
0x29, /* TC4 MC0 */
0);
/* /\* This event is picked up on event channel 0 *\/ */
/* events_allocate(0, */
/* EVENTS_EDGE_DETECT_NONE, */
/* EVENTS_PATH_ASYNCHRONOUS, */
/* 0x29, /\* TC4 MC0 *\/ */
/* 0); */
/* This event is picked up on event channel 1 */
events_allocate(1,
EVENTS_EDGE_DETECT_NONE,
EVENTS_PATH_ASYNCHRONOUS,
0x29, /* TC4 MC0 */
0);
/* /\* This event is picked up on event channel 1 *\/ */
/* events_allocate(1, */
/* EVENTS_EDGE_DETECT_NONE, */
/* EVENTS_PATH_ASYNCHRONOUS, */
/* 0x29, /\* TC4 MC0 *\/ */
/* 0); */
tc_enable(TC4); /* Retrigger event means counter doesn't start yet */
tc_start_counter(TC4); /* We start it manually now */
}
void osc8m_event_source_disable(void) {
tc_disable(TC4);
}
/* tc_enable(TC4); /\* Retrigger event means counter doesn't start yet *\/ */
/* tc_start_counter(TC4); /\* We start it manually now *\/ */
/* } */
/* void osc8m_event_source_disable(void) { */
/* tc_disable(TC4); */
/* } */
/**
* Configure the timepulse extint to generate events
@ -212,7 +212,7 @@ void measure_xosc(enum xosc_measurement_t measurement_t,
/* Configure an event source */
switch (measurement_t) {
case XOSC_MEASURE_OSC8M:
osc8m_event_source(); // osc8m issues events
// osc8m_event_source(); // osc8m issues events
break;
case XOSC_MEASURE_TIMEPULSE:
timepulse_extint_event_source(); // timepulse issues events
@ -227,7 +227,7 @@ void measure_xosc_disable(enum xosc_measurement_t measurement_t) {
switch (measurement_t) {
case XOSC_MEASURE_OSC8M:
osc8m_event_source_disable();
// osc8m_event_source_disable();
break;
case XOSC_MEASURE_TIMEPULSE:
timepulse_extint_event_source_disable();