-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmain.c
166 lines (138 loc) · 4.7 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include "ch.h"
#include "hal.h"
#include "chprintf.h"
#include "ptime.h"
#include "config.h"
#include "debug.h"
#include "modules.h"
#include "padc.h"
#include "pi2c.h"
#include "pac1720.h"
#include "bme280.h"
#include "sd.h"
static virtual_timer_t vt; // Virtual timer for LED blinking
uint32_t counter = 0; // Main thread counter
bool error = 0; // Error LED flag
systime_t wdg_buffer = S2ST(60); // Software thread monitor buffer, this is the time margin for
// a thread to react after its actual window expired, after
// expiration watchdog will not reset anymore which will reset
// the complete MCU
// Hardware Watchdog configuration
static const WDGConfig wdgcfg = {
.pr = STM32_IWDG_PR_256,
.rlr = STM32_IWDG_RL(10000)
};
/**
* LED blinking routine
* RED LED blinks: One or more modules crashed (software watchdog) INFO: Due to hardware bug, the LED cannot be used (pin = OSC_OUT => must be left floating)
* GREEN LED blinks: I'm alive! (STM32 crashed if not blinking)
* YELLOW LED: Camera takes a photo (See image.c)
*/
static void led_cb(void *led_sw) {
// Switch LEDs
palWritePad(PORT(LED_3GREEN), PIN(LED_3GREEN), (bool)led_sw); // Show I'M ALIVE
if(error) {
palWritePad(PORT(LED_1RED), PIN(LED_1RED), (bool)led_sw); // Show error
} else {
palSetPad(PORT(LED_1RED), PIN(LED_1RED)); // Shut off error
}
led_sw = (void*)!led_sw; // Set next state
chSysLockFromISR();
chVTSetI(&vt, MS2ST(500), led_cb, led_sw);
chSysUnlockFromISR();
}
/**
* Main routine is starting up system, runs the software watchdog (module monitoring), controls LEDs
*/
int main(void) {
halInit(); // Startup HAL
chSysInit(); // Startup RTOS
DEBUG_INIT(); // Debug Init (Serial debug port, LEDs)
TRACE_INFO("MAIN > Startup");
// Initialize Watchdog
TRACE_INFO("MAIN > Initialize Watchdog");
wdgStart(&WDGD1, &wdgcfg);
wdgReset(&WDGD1);
pi2cInit(); // Startup I2C
initEssentialModules(); // Startup required modules (input/output modules)
initModules(); // Startup optional modules (eg. POSITION, LOG, ...)
pac1720_init(); // Startup current measurement
initSD(); // Startup SD
chThdSleepMilliseconds(100);
// Initialize LED timer
chVTObjectInit(&vt);
chVTSet(&vt, MS2ST(500), led_cb, 0);
chThdSleepMilliseconds(1000);
while(true) {
// Print time every 10 sec
if(counter % 10 == 0)
PRINT_TIME("MAIN");
// Thread monitor
bool aerror = false; // Temporary error flag
bool healthy;
systime_t lu;
for(uint8_t i=0; i<sizeof(config)/sizeof(module_conf_t); i++) {
if(config[i].active) { // Is active?
// Determine health
healthy = true;
switch(config[i].trigger.type)
{
case TRIG_ONCE:
healthy = true;
break;
case TRIG_EVENT:
switch(config[i].trigger.event)
{
case NO_EVENT:
healthy = true;
break;
case EVENT_NEW_POINT:
healthy = config[i].last_update + S2ST(TRACK_CYCLE_TIME) + wdg_buffer > chVTGetSystemTimeX();
break;
}
break;
case TRIG_TIMEOUT:
healthy = config[i].last_update + S2ST(config[i].trigger.timeout) + wdg_buffer > chVTGetSystemTimeX();
break;
case TRIG_CONTINOUSLY:
healthy = config[i].last_update + wdg_buffer > chVTGetSystemTimeX();
break;
}
healthy = healthy || config[i].init_delay + wdg_buffer > chVTGetSystemTimeX();
// Debugging every 10 sec
if(counter % 10 == 0) {
lu = chVTGetSystemTimeX() - config[i].last_update;
if(healthy) {
TRACE_INFO("WDG > Module %s OK (last activity %d.%03d sec ago)", config[i].name, ST2MS(lu)/1000, ST2MS(lu)%1000);
} else {
TRACE_ERROR("WDG > Module %s failed (last activity %d.%03d sec ago)", config[i].name, ST2MS(lu)/1000, ST2MS(lu)%1000);
}
}
if(!healthy)
aerror = true; // Set error flag
}
}
// Watchdog TRACKING
healthy = watchdog_tracking + S2ST(TRACK_CYCLE_TIME) + wdg_buffer > chVTGetSystemTimeX();
lu = chVTGetSystemTimeX() - watchdog_tracking;
if(counter % 10 == 0) {
if(healthy) {
TRACE_INFO("WDG > Module TRAC OK (last activity %d.%03d sec ago)", ST2MS(lu)/1000, ST2MS(lu)%1000);
} else {
TRACE_ERROR("WDG > Module TRAC failed (last activity %d.%03d sec ago)", ST2MS(lu)/1000, ST2MS(lu)%1000);
}
}
if(!healthy)
aerror = true; // Set error flag
// Update hardware (LED, WDG)
error = aerror; // Update error LED flag
if(!error)
{
wdgReset(&WDGD1); // Reset hardware watchdog at no error
} else {
TRACE_ERROR("WDG > No reset");
}
chThdSleepMilliseconds(1000);
counter++;
}
}