2 ******************************************************************************
3 * @addtogroup LibrePilotModules LibrePilot Modules
4 * @brief The LibrePilot Modules do the majority of the control in LibrePilot. The
5 * @ref SystemModule "System Module" starts all the other modules that then take care
6 * of all the telemetry and control algorithms and such. This is done through the @ref PIOS
7 * "PIOS Hardware abstraction layer" which then contains hardware specific implementations
8 * (currently only STM32 supported)
11 * @addtogroup SystemModule System Module
12 * @brief Initializes PIOS and other modules runs monitoring
13 * After initializing all the modules (currently selected by Makefile but in
14 * future controlled by configuration on SD card) runs basic monitoring and
19 * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
20 * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2015.
21 * @brief System module
23 * @see The GNU Public License (GPL) Version 3
25 *****************************************************************************/
27 * This program is free software; you can redistribute it and/or modify
28 * it under the terms of the GNU General Public License as published by
29 * the Free Software Foundation; either version 3 of the License, or
30 * (at your option) any later version.
32 * This program is distributed in the hope that it will be useful, but
33 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
34 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37 * You should have received a copy of the GNU General Public License along
38 * with this program; if not, write to the Free Software Foundation, Inc.,
39 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 #include <openpilot.h>
44 #include "inc/systemmod.h"
46 #include <notification.h>
47 #ifdef PIOS_INCLUDE_WS2811
48 #include <lednotification.h>
52 #include <objectpersistence.h>
53 #include <flightstatus.h>
54 #include <systemstats.h>
55 #include <systemsettings.h>
58 #include <watchdogstatus.h>
59 #include <callbackinfo.h>
60 #include <hwsettings.h>
61 #include <pios_flashfs.h>
62 #include <pios_notify.h>
63 #include <pios_task_monitor.h>
64 #include <pios_board_init.h>
67 #ifdef PIOS_INCLUDE_INSTRUMENTATION
68 #include <instrumentation.h>
69 #include <pios_instrumentation.h>
72 #if defined(PIOS_INCLUDE_RFM22B)
73 #include <oplinkstatus.h>
77 #include <sanitycheck.h>
80 // #define DEBUG_THIS_FILE
82 #if defined(PIOS_INCLUDE_DEBUG_CONSOLE) && defined(DEBUG_THIS_FILE)
83 #define DEBUG_MSG(format, ...) PIOS_COM_SendFormattedString(PIOS_COM_DEBUG, format,##__VA_ARGS__)
85 #define DEBUG_MSG(format, ...)
89 #define SYSTEM_UPDATE_PERIOD_MS 250
91 #if defined(PIOS_SYSTEM_STACK_SIZE)
92 #define STACK_SIZE_BYTES PIOS_SYSTEM_STACK_SIZE
94 #define STACK_SIZE_BYTES 1024
97 #define TASK_PRIORITY (tskIDLE_PRIORITY + 1)
102 static xTaskHandle systemTaskHandle
;
103 static xQueueHandle objectPersistenceQueue
;
104 static enum { STACKOVERFLOW_NONE
= 0, STACKOVERFLOW_WARNING
= 1, STACKOVERFLOW_CRITICAL
= 3 } stackOverflow
;
105 static bool mallocFailed
;
106 static HwSettingsData bootHwSettings
;
107 static FrameType_t bootFrameType
;
109 volatile int initTaskDone
= 0;
112 static void objectUpdatedCb(UAVObjEvent
*ev
);
113 static void checkSettingsUpdatedCb(UAVObjEvent
*ev
);
115 static void taskMonitorForEachCallback(uint16_t task_id
, const struct pios_task_info
*task_info
, void *context
);
116 static void callbackSchedulerForEachCallback(int16_t callback_id
, const struct pios_callback_info
*callback_info
, void *context
);
118 static void updateStats();
119 static void updateSystemAlarms();
120 static void systemTask(void *parameters
);
121 #ifdef DIAG_I2C_WDG_STATS
122 static void updateI2Cstats();
123 static void updateWDGstats();
126 extern uintptr_t pios_uavo_settings_fs_id
;
127 extern uintptr_t pios_user_fs_id
;
130 * Create the module task.
131 * \returns 0 on success or -1 if initialization failed
133 int32_t SystemModStart(void)
136 stackOverflow
= STACKOVERFLOW_NONE
;
137 mallocFailed
= false;
138 // Create system task
139 xTaskCreate(systemTask
, "System", STACK_SIZE_BYTES
/ 4, NULL
, TASK_PRIORITY
, &systemTaskHandle
);
145 * Initialize the module, called on startup.
146 * \returns 0 on success or -1 if initialization failed
148 int32_t SystemModInitialize(void)
150 // Must registers objects here for system thread because ObjectManager started in OpenPilotInit
151 SystemSettingsInitialize();
152 SystemStatsInitialize();
153 FlightStatusInitialize();
154 ObjectPersistenceInitialize();
156 TaskInfoInitialize();
157 CallbackInfoInitialize();
159 #ifdef DIAG_I2C_WDG_STATS
160 I2CStatsInitialize();
161 WatchdogStatusInitialize();
164 #ifdef PIOS_INCLUDE_INSTRUMENTATION
165 InstrumentationInit();
168 objectPersistenceQueue
= xQueueCreate(1, sizeof(UAVObjEvent
));
169 if (objectPersistenceQueue
== NULL
) {
176 MODULE_INITCALL(SystemModInitialize
, 0);
178 * System task, periodically executes every SYSTEM_UPDATE_PERIOD_MS
180 static void systemTask(__attribute__((unused
)) void *parameters
)
182 /* calibrate the cpu usage monitor */
183 PIOS_TASK_MONITOR_CalibrateIdleCounter();
184 /* board driver init */
187 /* Initialize all modules */
188 MODULE_INITIALISE_ALL
;
190 while (!initTaskDone
) {
194 #ifndef PIOS_INCLUDE_WDG
195 // if no watchdog is enabled, don't reset watchdog in MODULE_TASKCREATE_ALL loop
196 #define PIOS_WDG_Clear()
198 /* create all modules thread */
199 MODULE_TASKCREATE_ALL
;
201 /* start the delayed callback scheduler */
202 PIOS_CALLBACKSCHEDULER_Start();
205 PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_SYSTEM
, systemTaskHandle
);
208 /* We failed to malloc during task creation,
209 * system behaviour is undefined. Reset and let
210 * the BootFault code recover for us.
214 #if defined(PIOS_INCLUDE_IAP)
215 /* Record a successful boot */
216 PIOS_IAP_WriteBootCount(0);
218 // Listen for SettingPersistance object updates, connect a callback function
219 ObjectPersistenceConnectQueue(objectPersistenceQueue
);
221 // Load a copy of HwSetting active at boot time
222 HwSettingsGet(&bootHwSettings
);
223 bootFrameType
= GetCurrentFrameType();
224 // Whenever the configuration changes, make sure it is safe to fly
225 HwSettingsConnectCallback(checkSettingsUpdatedCb
);
226 SystemSettingsConnectCallback(checkSettingsUpdatedCb
);
229 TaskInfoData taskInfoData
;
230 CallbackInfoData callbackInfoData
;
234 NotificationUpdateStatus();
235 // Update the system statistics
237 // Update the system alarms
238 updateSystemAlarms();
239 #ifdef DIAG_I2C_WDG_STATS
244 #ifdef PIOS_INCLUDE_INSTRUMENTATION
245 InstrumentationPublishAllCounters();
249 // Update the task status object
250 PIOS_TASK_MONITOR_ForEachTask(taskMonitorForEachCallback
, &taskInfoData
);
251 TaskInfoSet(&taskInfoData
);
252 // Update the callback status object
254 PIOS_CALLBACKSCHEDULER_ForEachCallback(callbackSchedulerForEachCallback
, &callbackInfoData
);
255 CallbackInfoSet(&callbackInfoData
);
262 int delayTime
= SYSTEM_UPDATE_PERIOD_MS
;
264 #if defined(PIOS_INCLUDE_RFM22B)
266 // Update the OPLinkStatus UAVO
267 OPLinkStatusData oplinkStatus
;
268 OPLinkStatusGet(&oplinkStatus
);
270 if (pios_rfm22b_id
) {
271 // Get the other device stats.
272 PIOS_RFM22B_GetPairStats(pios_rfm22b_id
, oplinkStatus
.PairIDs
, oplinkStatus
.PairSignalStrengths
, OPLINKSTATUS_PAIRIDS_NUMELEM
);
274 // Get the stats from the radio device
275 struct rfm22b_stats radio_stats
;
276 PIOS_RFM22B_GetStats(pios_rfm22b_id
, &radio_stats
);
278 // Update the OPLInk status
279 static bool first_time
= true;
280 static uint16_t prev_tx_count
= 0;
281 static uint16_t prev_rx_count
= 0;
282 static uint16_t prev_tx_seq
= 0;
283 static uint16_t prev_rx_seq
= 0;
285 oplinkStatus
.HeapRemaining
= xPortGetFreeHeapSize();
286 oplinkStatus
.DeviceID
= PIOS_RFM22B_DeviceID(pios_rfm22b_id
);
287 oplinkStatus
.RxGood
= radio_stats
.rx_good
;
288 oplinkStatus
.RxCorrected
= radio_stats
.rx_corrected
;
289 oplinkStatus
.RxErrors
= radio_stats
.rx_error
;
290 oplinkStatus
.RxMissed
= radio_stats
.rx_missed
;
291 oplinkStatus
.RxFailure
= radio_stats
.rx_failure
;
292 oplinkStatus
.TxDropped
= radio_stats
.tx_dropped
;
293 oplinkStatus
.TxFailure
= radio_stats
.tx_failure
;
294 oplinkStatus
.Resets
= radio_stats
.resets
;
295 oplinkStatus
.Timeouts
= radio_stats
.timeouts
;
296 oplinkStatus
.RSSI
= radio_stats
.rssi
;
297 oplinkStatus
.LinkQuality
= radio_stats
.link_quality
;
301 uint16_t tx_count
= radio_stats
.tx_byte_count
;
302 uint16_t rx_count
= radio_stats
.rx_byte_count
;
303 uint16_t tx_packets
= radio_stats
.tx_seq
- prev_tx_seq
;
304 uint16_t rx_packets
= radio_stats
.rx_seq
- prev_rx_seq
;
305 uint16_t tx_bytes
= (tx_count
< prev_tx_count
) ? (0xffff - prev_tx_count
+ tx_count
) : (tx_count
- prev_tx_count
);
306 uint16_t rx_bytes
= (rx_count
< prev_rx_count
) ? (0xffff - prev_rx_count
+ rx_count
) : (rx_count
- prev_rx_count
);
307 oplinkStatus
.TXRate
= (uint16_t)((float)(tx_bytes
* 1000) / SYSTEM_UPDATE_PERIOD_MS
);
308 oplinkStatus
.RXRate
= (uint16_t)((float)(rx_bytes
* 1000) / SYSTEM_UPDATE_PERIOD_MS
);
309 oplinkStatus
.TXPacketRate
= (uint16_t)((float)(tx_packets
* 1000) / SYSTEM_UPDATE_PERIOD_MS
);
310 oplinkStatus
.RXPacketRate
= (uint16_t)((float)(rx_packets
* 1000) / SYSTEM_UPDATE_PERIOD_MS
);
311 prev_tx_count
= tx_count
;
312 prev_rx_count
= rx_count
;
313 prev_tx_seq
= radio_stats
.tx_seq
;
314 prev_rx_seq
= radio_stats
.rx_seq
;
316 oplinkStatus
.TXSeq
= radio_stats
.tx_seq
;
317 oplinkStatus
.RXSeq
= radio_stats
.rx_seq
;
319 oplinkStatus
.LinkState
= radio_stats
.link_state
;
321 oplinkStatus
.LinkState
= OPLINKSTATUS_LINKSTATE_DISABLED
;
323 OPLinkStatusSet(&oplinkStatus
);
325 #endif /* if defined(PIOS_INCLUDE_RFM22B) */
327 if (xQueueReceive(objectPersistenceQueue
, &ev
, delayTime
) == pdTRUE
) {
328 // If object persistence is updated call the callback
329 objectUpdatedCb(&ev
);
335 * Function called in response to object updates
337 static void objectUpdatedCb(UAVObjEvent
*ev
)
339 ObjectPersistenceData objper
;
342 // If the object updated was the ObjectPersistence execute requested action
343 if (ev
->obj
== ObjectPersistenceHandle()) {
345 ObjectPersistenceGet(&objper
);
348 FlightStatusData flightStatus
;
349 FlightStatusGet(&flightStatus
);
351 // When this is called because of this method don't do anything
352 if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_ERROR
|| objper
.Operation
== OBJECTPERSISTENCE_OPERATION_COMPLETED
) {
356 // Execute action if disarmed
357 if (flightStatus
.Armed
!= FLIGHTSTATUS_ARMED_DISARMED
) {
359 } else if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_LOAD
) {
360 if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_SINGLEOBJECT
) {
361 // Get selected object
362 obj
= UAVObjGetByID(objper
.ObjectID
);
366 // Load selected instance
367 retval
= UAVObjLoad(obj
, objper
.InstanceID
);
368 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLSETTINGS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
369 retval
= UAVObjLoadSettings();
370 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLMETAOBJECTS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
371 retval
= UAVObjLoadMetaobjects();
373 } else if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_SAVE
) {
374 if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_SINGLEOBJECT
) {
375 // Get selected object
376 obj
= UAVObjGetByID(objper
.ObjectID
);
380 // Save selected instance
381 retval
= UAVObjSave(obj
, objper
.InstanceID
);
383 // Not sure why this is needed
386 // Verify saving worked
388 retval
= UAVObjLoad(obj
, objper
.InstanceID
);
390 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLSETTINGS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
391 retval
= UAVObjSaveSettings();
392 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLMETAOBJECTS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
393 retval
= UAVObjSaveMetaobjects();
395 } else if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_DELETE
) {
396 if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_SINGLEOBJECT
) {
397 // Get selected object
398 obj
= UAVObjGetByID(objper
.ObjectID
);
402 // Delete selected instance
403 retval
= UAVObjDelete(obj
, objper
.InstanceID
);
404 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLSETTINGS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
405 retval
= UAVObjDeleteSettings();
406 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLMETAOBJECTS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
407 retval
= UAVObjDeleteMetaobjects();
409 } else if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_FULLERASE
) {
410 #if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
411 retval
= PIOS_FLASHFS_Format(0);
418 objper
.Operation
= OBJECTPERSISTENCE_OPERATION_COMPLETED
;
419 ObjectPersistenceSet(&objper
);
422 objper
.Operation
= OBJECTPERSISTENCE_OPERATION_ERROR
;
423 ObjectPersistenceSet(&objper
);
432 * Called whenever hardware settings changed
434 static void checkSettingsUpdatedCb(__attribute__((unused
)) UAVObjEvent
*ev
)
436 HwSettingsData currentHwSettings
;
438 HwSettingsGet(¤tHwSettings
);
439 FrameType_t currentFrameType
= GetCurrentFrameType();
440 // check whether the Hw Configuration has changed from the one used at boot time
441 if ((memcmp(&bootHwSettings
, ¤tHwSettings
, sizeof(HwSettingsData
)) != 0) ||
442 (currentFrameType
!= bootFrameType
)) {
443 ExtendedAlarmsSet(SYSTEMALARMS_ALARM_BOOTFAULT
, SYSTEMALARMS_ALARM_CRITICAL
, SYSTEMALARMS_EXTENDEDALARMSTATUS_REBOOTREQUIRED
, 0);
448 static void taskMonitorForEachCallback(uint16_t task_id
, const struct pios_task_info
*task_info
, void *context
)
450 TaskInfoData
*taskData
= (TaskInfoData
*)context
;
452 // By convention, there is a direct mapping between task monitor task_id's and members
453 // of the TaskInfoXXXXElem enums
454 PIOS_DEBUG_Assert(task_id
< TASKINFO_RUNNING_NUMELEM
);
455 TaskInfoRunningToArray(taskData
->Running
)[task_id
] = task_info
->is_running
? TASKINFO_RUNNING_TRUE
: TASKINFO_RUNNING_FALSE
;
456 ((uint16_t *)&taskData
->StackRemaining
)[task_id
] = task_info
->stack_remaining
;
457 ((uint8_t *)&taskData
->RunningTime
)[task_id
] = task_info
->running_time_percentage
;
460 static void callbackSchedulerForEachCallback(int16_t callback_id
, const struct pios_callback_info
*callback_info
, void *context
)
462 CallbackInfoData
*callbackData
= (CallbackInfoData
*)context
;
464 if (callback_id
< 0) {
467 // delayed callback scheduler reports callback stack overflows as remaininng: -1
468 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32)
469 if (callback_info
->stack_remaining
< 0 && stackOverflow
== STACKOVERFLOW_NONE
) {
470 stackOverflow
= STACKOVERFLOW_WARNING
;
473 // By convention, there is a direct mapping between (not negative) callback scheduler callback_id's and members
474 // of the CallbackInfoXXXXElem enums
475 PIOS_DEBUG_Assert(callback_id
< CALLBACKINFO_RUNNING_NUMELEM
);
476 ((uint8_t *)&callbackData
->Running
)[callback_id
] = callback_info
->is_running
;
477 ((uint32_t *)&callbackData
->RunningTime
)[callback_id
] = callback_info
->running_time_count
;
478 ((int16_t *)&callbackData
->StackRemaining
)[callback_id
] = callback_info
->stack_remaining
;
480 #endif /* ifdef DIAG_TASKS */
483 * Called periodically to update the I2C statistics
485 #ifdef DIAG_I2C_WDG_STATS
486 static void updateI2Cstats()
488 #if defined(PIOS_INCLUDE_I2C)
489 I2CStatsData i2cStats
;
490 I2CStatsGet(&i2cStats
);
492 struct pios_i2c_fault_history history
;
493 PIOS_I2C_GetDiagnostics(&history
, &i2cStats
.event_errors
);
495 for (uint8_t i
= 0; (i
< I2C_LOG_DEPTH
) && (i
< I2CSTATS_EVENT_LOG_NUMELEM
); i
++) {
496 i2cStats
.evirq_log
[i
] = history
.evirq
[i
];
497 i2cStats
.erirq_log
[i
] = history
.erirq
[i
];
498 i2cStats
.event_log
[i
] = history
.event
[i
];
499 i2cStats
.state_log
[i
] = history
.state
[i
];
501 i2cStats
.last_error_type
= history
.type
;
502 I2CStatsSet(&i2cStats
);
506 static void updateWDGstats()
508 WatchdogStatusData watchdogStatus
;
510 watchdogStatus
.BootupFlags
= PIOS_WDG_GetBootupFlags();
511 watchdogStatus
.ActiveFlags
= PIOS_WDG_GetActiveFlags();
512 WatchdogStatusSet(&watchdogStatus
);
514 #endif /* ifdef DIAG_I2C_WDG_STATS */
517 * Called periodically to update the system stats
519 static uint16_t GetFreeIrqStackSize(void)
523 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK)
524 extern uint32_t _irq_stack_top
;
525 extern uint32_t _irq_stack_end
;
526 uint32_t pattern
= 0x0000A5A5;
527 uint32_t *ptr
= &_irq_stack_end
;
529 #if 1 /* the ugly way accurate but takes more time, useful for debugging */
530 uint32_t stack_size
= (((uint32_t)&_irq_stack_top
- (uint32_t)&_irq_stack_end
) & ~3) / 4;
532 for (i
= 0; i
< stack_size
; i
++) {
533 if (ptr
[i
] != pattern
) {
538 #else /* faster way but not accurate */
539 if (*(volatile uint32_t *)((uint32_t)ptr
+ IRQSTACK_LIMIT_CRITICAL
) != pattern
) {
540 i
= IRQSTACK_LIMIT_CRITICAL
- 1;
541 } else if (*(volatile uint32_t *)((uint32_t)ptr
+ IRQSTACK_LIMIT_WARNING
) != pattern
) {
542 i
= IRQSTACK_LIMIT_WARNING
- 1;
544 i
= IRQSTACK_LIMIT_WARNING
;
547 #endif /* if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK) */
552 * Called periodically to update the system stats
554 static void updateStats()
556 SystemStatsData stats
;
558 // Get stats and update
559 SystemStatsGet(&stats
);
560 stats
.FlightTime
= xTaskGetTickCount() * portTICK_RATE_MS
;
561 #if defined(ARCH_POSIX) || defined(ARCH_WIN32)
562 // POSIX port of FreeRTOS doesn't have xPortGetFreeHeapSize()
563 stats
.SystemModStackRemaining
= 128;
564 stats
.HeapRemaining
= 10240;
566 stats
.HeapRemaining
= xPortGetFreeHeapSize();
567 stats
.SystemModStackRemaining
= uxTaskGetStackHighWaterMark(NULL
) * 4;
570 // Get Irq stack status
571 stats
.IRQStackRemaining
= GetFreeIrqStackSize();
573 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
574 static struct PIOS_FLASHFS_Stats fsStats
;
576 if (pios_uavo_settings_fs_id
) {
577 PIOS_FLASHFS_GetStats(pios_uavo_settings_fs_id
, &fsStats
);
578 stats
.SysSlotsFree
= fsStats
.num_free_slots
;
579 stats
.SysSlotsActive
= fsStats
.num_active_slots
;
581 if (pios_user_fs_id
) {
582 PIOS_FLASHFS_GetStats(pios_user_fs_id
, &fsStats
);
583 stats
.UsrSlotsFree
= fsStats
.num_free_slots
;
584 stats
.UsrSlotsActive
= fsStats
.num_active_slots
;
587 stats
.CPUIdleTicks
= PIOS_TASK_MONITOR_GetIdleTicksCount();
588 stats
.CPUZeroLoadTicks
= PIOS_TASK_MONITOR_GetZeroLoadTicksCount();
589 stats
.CPULoad
= 100 - (uint8_t)((100 * stats
.CPUIdleTicks
) / stats
.CPUZeroLoadTicks
);
591 #if defined(PIOS_INCLUDE_ADC) && defined(PIOS_ADC_USE_TEMP_SENSOR)
592 float temp_voltage
= PIOS_ADC_PinGetVolt(PIOS_ADC_TEMPERATURE_PIN
);
593 stats
.CPUTemp
= PIOS_CONVERT_VOLT_TO_CPU_TEMP(temp_voltage
);;
595 SystemStatsSet(&stats
);
599 * Update system alarms
601 static void updateSystemAlarms()
603 SystemStatsData stats
;
604 UAVObjStats objStats
;
607 SystemStatsGet(&stats
);
609 // Check heap, IRQ stack and malloc failures
610 if (mallocFailed
|| (stats
.HeapRemaining
< HEAP_LIMIT_CRITICAL
)
611 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK)
612 || (stats
.IRQStackRemaining
< IRQSTACK_LIMIT_CRITICAL
)
615 AlarmsSet(SYSTEMALARMS_ALARM_OUTOFMEMORY
, SYSTEMALARMS_ALARM_CRITICAL
);
616 } else if ((stats
.HeapRemaining
< HEAP_LIMIT_WARNING
)
617 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK)
618 || (stats
.IRQStackRemaining
< IRQSTACK_LIMIT_WARNING
)
621 AlarmsSet(SYSTEMALARMS_ALARM_OUTOFMEMORY
, SYSTEMALARMS_ALARM_WARNING
);
623 AlarmsClear(SYSTEMALARMS_ALARM_OUTOFMEMORY
);
627 if (stats
.CPULoad
> CPULOAD_LIMIT_CRITICAL
) {
628 AlarmsSet(SYSTEMALARMS_ALARM_CPUOVERLOAD
, SYSTEMALARMS_ALARM_CRITICAL
);
629 } else if (stats
.CPULoad
> CPULOAD_LIMIT_WARNING
) {
630 AlarmsSet(SYSTEMALARMS_ALARM_CPUOVERLOAD
, SYSTEMALARMS_ALARM_WARNING
);
632 AlarmsClear(SYSTEMALARMS_ALARM_CPUOVERLOAD
);
635 // Check for stack overflow
636 switch (stackOverflow
) {
637 case STACKOVERFLOW_NONE
:
638 AlarmsClear(SYSTEMALARMS_ALARM_STACKOVERFLOW
);
640 case STACKOVERFLOW_WARNING
:
641 AlarmsSet(SYSTEMALARMS_ALARM_STACKOVERFLOW
, SYSTEMALARMS_ALARM_WARNING
);
644 AlarmsSet(SYSTEMALARMS_ALARM_STACKOVERFLOW
, SYSTEMALARMS_ALARM_CRITICAL
);
647 // Check for event errors
648 UAVObjGetStats(&objStats
);
649 EventGetStats(&evStats
);
652 if (objStats
.eventCallbackErrors
> 0 || objStats
.eventQueueErrors
> 0 || evStats
.eventErrors
> 0) {
653 AlarmsSet(SYSTEMALARMS_ALARM_EVENTSYSTEM
, SYSTEMALARMS_ALARM_WARNING
);
655 AlarmsClear(SYSTEMALARMS_ALARM_EVENTSYSTEM
);
658 if (objStats
.lastCallbackErrorID
|| objStats
.lastQueueErrorID
|| evStats
.lastErrorID
) {
659 SystemStatsData sysStats
;
660 SystemStatsGet(&sysStats
);
661 sysStats
.EventSystemWarningID
= evStats
.lastErrorID
;
662 sysStats
.ObjectManagerCallbackID
= objStats
.lastCallbackErrorID
;
663 sysStats
.ObjectManagerQueueID
= objStats
.lastQueueErrorID
;
664 SystemStatsSet(&sysStats
);
669 * Called by the RTOS when the CPU is idle,
671 void vApplicationIdleHook(void)
673 PIOS_TASK_MONITOR_IdleHook();
674 NotificationOnboardLedsRun();
675 #ifdef PIOS_INCLUDE_WS2811
676 LedNotificationExtLedsRun();
680 * Called by the RTOS when a stack overflow is detected.
682 #define DEBUG_STACK_OVERFLOW 0
683 void vApplicationStackOverflowHook(__attribute__((unused
)) xTaskHandle
*pxTask
,
684 __attribute__((unused
)) signed portCHAR
*pcTaskName
)
686 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32)
687 stackOverflow
= STACKOVERFLOW_CRITICAL
;
688 #if DEBUG_STACK_OVERFLOW
689 static volatile bool wait_here
= true;
699 * Called by the RTOS when a malloc call fails.
701 #define DEBUG_MALLOC_FAILURES 0
702 void vApplicationMallocFailedHook(void)
705 #if DEBUG_MALLOC_FAILURES
706 static volatile bool wait_here
= true;