dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
alarms.c
Go to the documentation of this file.
1 
14 /*
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful, but
21  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  * for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, see <http://www.gnu.org/licenses/>
27  *
28  * Additional note on redistribution: The copyright and license notices above
29  * must be maintained in each individual source file that is a derivative work
30  * of this source file; otherwise redistribution is prohibited.
31  */
32 
33 #include "openpilot.h"
34 #include "alarms.h"
35 #include "pios_mutex.h"
36 #include "pios_reset.h"
37 
38 // Private constants
39 
40 // Private types
41 
42 // Private variables
43 static struct pios_mutex *lock;
44 
45 // Private functions
46 static int32_t hasSeverity(SystemAlarmsAlarmOptions severity);
47 
51 int32_t AlarmsInitialize(void)
52 {
53  SystemAlarmsInitialize();
54  lock = PIOS_Mutex_Create();
55  PIOS_Assert(lock != NULL);
56 
57  uint8_t reboot_reason = SYSTEMALARMS_REBOOTCAUSE_UNDEFINED;
58 
59  switch (PIOS_RESET_GetResetReason()) {
60  case PIOS_RESET_FLAG_BROWNOUT: // Brownouts are not detected on STM32F1 or STM32F3
61  reboot_reason = SYSTEMALARMS_REBOOTCAUSE_BROWNOUT;
62  break;
64  reboot_reason = SYSTEMALARMS_REBOOTCAUSE_PINRESET;
65  break;
67  reboot_reason = SYSTEMALARMS_REBOOTCAUSE_POWERONRESET;
68  break;
70  reboot_reason = SYSTEMALARMS_REBOOTCAUSE_SOFTWARERESET;
71  break;
73  reboot_reason = SYSTEMALARMS_REBOOTCAUSE_INDEPENDENTWATCHDOG;
74  break;
76  reboot_reason = SYSTEMALARMS_REBOOTCAUSE_WINDOWWATCHDOG;
77  break;
79  reboot_reason = SYSTEMALARMS_REBOOTCAUSE_LOWPOWER;
80  break;
82  reboot_reason = SYSTEMALARMS_REBOOTCAUSE_UNDEFINED;
83  break;
84  }
85 
86  SystemAlarmsRebootCauseSet(&reboot_reason);
87 
88  return 0;
89 }
90 
97 int32_t AlarmsSet(SystemAlarmsAlarmElem alarm, SystemAlarmsAlarmOptions severity)
98 {
99  SystemAlarmsData alarms;
100 
101  // Check that this is a valid alarm
102  if (alarm >= SYSTEMALARMS_ALARM_NUMELEM)
103  {
104  return -1;
105  }
106 
107  // Lock
109 
110  // Read alarm and update its severity only if it was changed
111  SystemAlarmsGet(&alarms);
112  if ( alarms.Alarm[alarm] != severity )
113  {
114  alarms.Alarm[alarm] = severity;
115  SystemAlarmsSet(&alarms);
116  }
117 
118  // Release lock
119  PIOS_Mutex_Unlock(lock);
120  return 0;
121 
122 }
123 
129 SystemAlarmsAlarmOptions AlarmsGet(SystemAlarmsAlarmElem alarm)
130 {
131  SystemAlarmsData alarms;
132 
133  // Check that this is a valid alarm
134  if (alarm >= SYSTEMALARMS_ALARM_NUMELEM)
135  {
136  return 0;
137  }
138 
139  // Read alarm
140  SystemAlarmsGet(&alarms);
141  return alarms.Alarm[alarm];
142 }
143 
149 int32_t AlarmsDefault(SystemAlarmsAlarmElem alarm)
150 {
151  return AlarmsSet(alarm, SYSTEMALARMS_ALARM_DEFAULT);
152 }
153 
158 {
159  uint32_t n;
160  for (n = 0; n < SYSTEMALARMS_ALARM_NUMELEM; ++n)
161  {
162  AlarmsDefault(n);
163  }
164 }
165 
171 int32_t AlarmsClear(SystemAlarmsAlarmElem alarm)
172 {
173  return AlarmsSet(alarm, SYSTEMALARMS_ALARM_OK);
174 }
175 
180 {
181  uint32_t n;
182  for (n = 0; n < SYSTEMALARMS_ALARM_NUMELEM; ++n)
183  {
184  AlarmsClear(n);
185  }
186 }
187 
193 {
194  return hasSeverity(SYSTEMALARMS_ALARM_WARNING);
195 }
196 
202 {
203  return hasSeverity(SYSTEMALARMS_ALARM_ERROR);
204 };
205 
211 {
212  return hasSeverity(SYSTEMALARMS_ALARM_CRITICAL);
213 };
214 
219 static int32_t hasSeverity(SystemAlarmsAlarmOptions severity)
220 {
221  SystemAlarmsData alarms;
222  uint32_t n;
223 
224  // Lock
226 
227  // Read alarms
228  SystemAlarmsGet(&alarms);
229 
230  // Go through alarms and check if any are of the given severity or higher
231  for (n = 0; n < SYSTEMALARMS_ALARM_NUMELEM; ++n)
232  {
233  if ( alarms.Alarm[n] >= severity)
234  {
235  PIOS_Mutex_Unlock(lock);
236  return 1;
237  }
238  }
239 
240  // If this point is reached then no alarms found
241  PIOS_Mutex_Unlock(lock);
242  return 0;
243 }
244 
245 static const char alarm_names[][10] = {
246  [SYSTEMALARMS_ALARM_OUTOFMEMORY] = "MEMORY",
247  [SYSTEMALARMS_ALARM_CPUOVERLOAD] = "CPU",
248  [SYSTEMALARMS_ALARM_STACKOVERFLOW] = "STACK",
249  [SYSTEMALARMS_ALARM_SYSTEMCONFIGURATION] = "CONFIG",
250  [SYSTEMALARMS_ALARM_EVENTSYSTEM] = {0}, // XXX TODO Temporarily ignored
251  [SYSTEMALARMS_ALARM_TELEMETRY] = {0}, // ignored
252  [SYSTEMALARMS_ALARM_MANUALCONTROL] = "MANUAL",
253  [SYSTEMALARMS_ALARM_ACTUATOR] = "ACTUATOR",
254  [SYSTEMALARMS_ALARM_ATTITUDE] = "ATTITUDE",
255  [SYSTEMALARMS_ALARM_SENSORS] = "SENSORS",
256  [SYSTEMALARMS_ALARM_STABILIZATION] = "STAB",
257  [SYSTEMALARMS_ALARM_PATHFOLLOWER] = "P-FOLLOW",
258  [SYSTEMALARMS_ALARM_PATHPLANNER] = "P-PLAN",
259  [SYSTEMALARMS_ALARM_BATTERY] = "BATTERY",
260  [SYSTEMALARMS_ALARM_FLIGHTTIME] = "TIME",
261  [SYSTEMALARMS_ALARM_I2C] = "I2C",
262  [SYSTEMALARMS_ALARM_GPS] = "GPS",
263  [SYSTEMALARMS_ALARM_ALTITUDEHOLD] = "A-HOLD",
264  [SYSTEMALARMS_ALARM_BOOTFAULT] = "BOOT",
265  [SYSTEMALARMS_ALARM_GEOFENCE] = "GEOFENCE",
266  [SYSTEMALARMS_ALARM_TEMPBARO] = "TEMPBARO",
267  [SYSTEMALARMS_ALARM_GYROBIAS] = "GYROBIAS",
268  [SYSTEMALARMS_ALARM_ADC] = "ADC",
269  [SYSTEMALARMS_ALARM_GIMBAL] = "GIMBAL",
270 };
271 
272 // If someone adds a new alarm, we'd like it added to the array above.
273 DONT_BUILD_IF(NELEMENTS(alarm_names) != SYSTEMALARMS_ALARM_NUMELEM, AlarmArrayMismatch);
274 
275 static const char config_error_names[][15] = {
276  [SYSTEMALARMS_CONFIGERROR_STABILIZATION] = "CFG:STAB",
277  [SYSTEMALARMS_CONFIGERROR_MULTIROTOR] = "CFG:MULTIROTOR",
278  [SYSTEMALARMS_CONFIGERROR_AUTOTUNE] = "CFG:AUTOTUNE",
279  [SYSTEMALARMS_CONFIGERROR_ALTITUDEHOLD] = "CFG:AH1",
280  [SYSTEMALARMS_CONFIGERROR_POSITIONHOLD] = "CFG:POS-HOLD",
281  [SYSTEMALARMS_CONFIGERROR_PATHPLANNER] = "CFG:PATHPLAN",
282  [SYSTEMALARMS_CONFIGERROR_DUPLICATEPORTCFG] = "CFG:DUP PORT",
283  [SYSTEMALARMS_CONFIGERROR_NAVFILTER] = "CFG:NAVFILTER",
284  [SYSTEMALARMS_CONFIGERROR_UNSAFETOARM] = "CFG:UNSAFE",
285  [SYSTEMALARMS_CONFIGERROR_LQG] = "CFG:LQG",
286  [SYSTEMALARMS_CONFIGERROR_UNDEFINED] = "CFG:UNDEF",
287  [SYSTEMALARMS_CONFIGERROR_NONE] = {0},
288 };
289 
290 // DONT_BUILD_IF(NELEMENTS(CONFIG_ERROR_NAMES) != SYSTEMALARMS_CONFIGERROR_NUMELEM, AlarmArrayMismatch);
291 
292 static const char manual_control_names[][13] = {
293  [SYSTEMALARMS_MANUALCONTROL_SETTINGS] = "MAN:SETTINGS",
294  [SYSTEMALARMS_MANUALCONTROL_NORX] = "MAN:NO RX",
295  [SYSTEMALARMS_MANUALCONTROL_ACCESSORY] = "MAN:ACC",
296  [SYSTEMALARMS_MANUALCONTROL_ALTITUDEHOLD] = "MAN:A-HOLD",
297  [SYSTEMALARMS_MANUALCONTROL_PATHFOLLOWER] = "MAN:PATH-F",
298  [SYSTEMALARMS_MANUALCONTROL_CHANNELCONFIGURATION] = "MAN:INPUT",
299  [SYSTEMALARMS_MANUALCONTROL_UNDEFINED] = "MAN:UNDEF",
300  [SYSTEMALARMS_MANUALCONTROL_NONE] = {0},
301 };
302 
303 // DONT_BUILD_IF(NELEMENTS(MANUAL_CONTROL_NAMES) != SYSTEMALARMS_MANUALCONTROL_NUMELEM, AlarmArrayMismatch);
304 
305 static const char boot_reason_names[][16] = {
306  [SYSTEMALARMS_REBOOTCAUSE_BROWNOUT] = "BOOT:BROWNOUT",
307  [SYSTEMALARMS_REBOOTCAUSE_PINRESET] = "BOOT:PIN RESET",
308  [SYSTEMALARMS_REBOOTCAUSE_POWERONRESET] = "BOOT:PWR ON RST",
309  [SYSTEMALARMS_REBOOTCAUSE_SOFTWARERESET] = "BOOT:SW RESET",
310  [SYSTEMALARMS_REBOOTCAUSE_INDEPENDENTWATCHDOG] = "BOOT:INDY WDOG",
311  [SYSTEMALARMS_REBOOTCAUSE_WINDOWWATCHDOG] = "BOOT:WIN WDOG",
312  [SYSTEMALARMS_REBOOTCAUSE_LOWPOWER] = "BOOT:LOW POWER",
313  [SYSTEMALARMS_REBOOTCAUSE_UNDEFINED] = "BOOT:UNDEFINED",
314 };
315 
316 #define LONGEST_MESSAGE 17
317 
318 DONT_BUILD_IF((LONGEST_MESSAGE <= sizeof(*config_error_names)
319  || LONGEST_MESSAGE <= sizeof(*manual_control_names)
320  || LONGEST_MESSAGE <= sizeof(*boot_reason_names)),
321  InsufficientBufferage);
322 
323 const char *AlarmBootReason(uint8_t reason) {
324  if (reason >= NELEMENTS(boot_reason_names)) {
325  return (const char*)&boot_reason_names[SYSTEMALARMS_REBOOTCAUSE_UNDEFINED];
326  }
327  return (const char*)&boot_reason_names[reason];
328 }
329 
330 int32_t AlarmString(SystemAlarmsData *alarm, char *buf, size_t buflen, bool blink, uint8_t *state) {
331  *state = SYSTEMALARMS_ALARM_OK;
332  buf[0] = '\0';
333  int pos = 0;
334 
335  // TODO(dustin): sort the alarms by severity. Alarm messages
336  // will get truncated. We want the most urgent stuff to show
337  // up first, having warnings show up only if there's space.
338  for (int i = 0; i < SYSTEMALARMS_ALARM_NUMELEM; i++) {
339  if (((alarm->Alarm[i] == SYSTEMALARMS_ALARM_WARNING) ||
340  (alarm->Alarm[i] == SYSTEMALARMS_ALARM_ERROR) ||
341  (alarm->Alarm[i] == SYSTEMALARMS_ALARM_CRITICAL))) {
342 
343  if (!alarm_names[i][0]) {
344  // zero-length alarm names indicate the alarm is
345  // explicitly ignored
346  continue;
347  }
348 
349  // Returned state is the worst state.
350  if (alarm->Alarm[i] > *state) {
351  *state = alarm->Alarm[i];
352  }
353 
354  char current_msg[LONGEST_MESSAGE+1] = {0};
355  switch (i) {
356  case SYSTEMALARMS_ALARM_SYSTEMCONFIGURATION:
357  strncpy(current_msg,
358  (const char*)config_error_names[alarm->ConfigError],
359  sizeof(*config_error_names));
360  current_msg[sizeof(*config_error_names)] = '\0';
361  break;
362  case SYSTEMALARMS_ALARM_MANUALCONTROL:
363  strncpy(current_msg,
364  (const char*)manual_control_names[alarm->ManualControl],
365  sizeof(*manual_control_names));
366  current_msg[sizeof(*manual_control_names)] = '\0';
367  break;
368  default:
369  strncpy(current_msg, (const char*)alarm_names[i], sizeof(*alarm_names));
370  current_msg[sizeof(*alarm_names)] = '\0';
371  }
372 
373  int this_len = strlen(current_msg);
374 
375  if (pos + this_len + 2 >= buflen) {
376  break;
377  }
378 
379  if ((alarm->Alarm[i] != SYSTEMALARMS_ALARM_WARNING) && !blink) {
380  this_len += 1;
381  while (this_len > 0) {
382  buf[pos++] = ' ';
383  this_len--;
384  }
385  continue;
386  }
387 
388  memcpy(&buf[pos], current_msg, this_len);
389  pos += this_len;
390  buf[pos++] = ' ';
391 
392  }
393  }
394 
395  buf[pos] = '\0';
396  return pos;
397 }
398 
static int32_t hasSeverity(SystemAlarmsAlarmOptions severity)
Definition: alarms.c:219
#define NELEMENTS(x)
Definition: pios.h:192
int16_t PIOS_RESET_GetResetReason(void)
PIOS_RESET_GetResetReason Does nothing on POSIX systems.
Definition: pios_reset.c:47
static bool blink
static const char manual_control_names[][13]
Definition: alarms.c:292
int32_t AlarmsSet(SystemAlarmsAlarmElem alarm, SystemAlarmsAlarmOptions severity)
Definition: alarms.c:97
bool PIOS_Mutex_Unlock(struct pios_mutex *mtx)
Definition: pios_mutex.c:104
struct pios_mutex * PIOS_Mutex_Create(void)
Definition: pios_mutex.c:43
void AlarmsClearAll()
Definition: alarms.c:179
static const char config_error_names[][15]
Definition: alarms.c:275
static const char boot_reason_names[][16]
Definition: alarms.c:305
DONT_BUILD_IF(NELEMENTS(alarm_names)!=SYSTEMALARMS_ALARM_NUMELEM, AlarmArrayMismatch)
struct _msp_pid_item pos
Definition: msp_messages.h:100
#define LONGEST_MESSAGE
Definition: alarms.c:316
void AlarmsDefaultAll()
Definition: alarms.c:157
Include file of the alarm library.
int32_t AlarmsHasCritical()
Definition: alarms.c:210
uint8_t i
Definition: msp_messages.h:97
#define SYSTEMALARMS_ALARM_DEFAULT
Definition: alarms.h:31
const char * AlarmBootReason(uint8_t reason)
static struct pios_mutex * lock
Definition: alarms.c:43
Includes PiOS and core architecture components.
int32_t AlarmsClear(SystemAlarmsAlarmElem alarm)
Definition: alarms.c:171
int32_t AlarmsHasErrors()
Definition: alarms.c:201
int32_t AlarmsHasWarnings()
Definition: alarms.c:192
static const char alarm_names[][10]
Definition: alarms.c:245
int32_t AlarmString(SystemAlarmsData *alarm, char *buf, size_t buflen, bool blink, uint8_t *state)
Reset information.
int32_t AlarmsInitialize(void)
Definition: alarms.c:51
#define PIOS_Assert(test)
Definition: pios_debug.h:52
#define PIOS_MUTEX_TIMEOUT_MAX
Definition: pios_mutex.h:30
SystemAlarmsAlarmOptions AlarmsGet(SystemAlarmsAlarmElem alarm)
Definition: alarms.c:129
bool PIOS_Mutex_Lock(struct pios_mutex *mtx, uint32_t timeout_ms)
Definition: pios_mutex.c:66
int32_t AlarmsDefault(SystemAlarmsAlarmElem alarm)
Definition: alarms.c:149
enum arena_state state