2 ******************************************************************************
3 * @addtogroup OpenPilotModules OpenPilot Modules
4 * @brief The OpenPilot Modules do the majority of the control in OpenPilot. 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 OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
20 * @brief System module
22 * @see The GNU Public License (GPL) Version 3
24 *****************************************************************************/
26 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 3 of the License, or
29 * (at your option) any later version.
31 * This program is distributed in the hope that it will be useful, but
32 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
33 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36 * You should have received a copy of the GNU General Public License along
37 * with this program; if not, write to the Free Software Foundation, Inc.,
38 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41 #include <openpilot.h>
43 #include "inc/systemmod.h"
45 #include <notification.h>
46 #ifdef PIOS_INCLUDE_WS2811
47 #include <lednotification.h>
51 #include <objectpersistence.h>
52 #include <flightstatus.h>
53 #include <systemstats.h>
54 #include <systemsettings.h>
57 #include <watchdogstatus.h>
58 #include <callbackinfo.h>
59 #include <hwsettings.h>
60 #include <pios_flashfs.h>
61 #include <pios_notify.h>
63 #ifdef PIOS_INCLUDE_INSTRUMENTATION
64 #include <instrumentation.h>
65 #include <pios_instrumentation.h>
68 #if defined(PIOS_INCLUDE_RFM22B)
69 #include <oplinkstatus.h>
73 #include <sanitycheck.h>
76 // #define DEBUG_THIS_FILE
78 #if defined(PIOS_INCLUDE_DEBUG_CONSOLE) && defined(DEBUG_THIS_FILE)
79 #define DEBUG_MSG(format, ...) PIOS_COM_SendFormattedString(PIOS_COM_DEBUG, format,##__VA_ARGS__)
81 #define DEBUG_MSG(format, ...)
85 #define SYSTEM_UPDATE_PERIOD_MS 250
87 #if defined(PIOS_SYSTEM_STACK_SIZE)
88 #define STACK_SIZE_BYTES PIOS_SYSTEM_STACK_SIZE
90 #define STACK_SIZE_BYTES 1024
93 #define TASK_PRIORITY (tskIDLE_PRIORITY + 1)
98 static xTaskHandle systemTaskHandle
;
99 static xQueueHandle objectPersistenceQueue
;
100 static enum { STACKOVERFLOW_NONE
= 0, STACKOVERFLOW_WARNING
= 1, STACKOVERFLOW_CRITICAL
= 3 } stackOverflow
;
101 static bool mallocFailed
;
102 static HwSettingsData bootHwSettings
;
103 static FrameType_t bootFrameType
;
105 volatile int initTaskDone
= 0;
108 static void objectUpdatedCb(UAVObjEvent
*ev
);
109 static void checkSettingsUpdatedCb(UAVObjEvent
*ev
);
111 static void taskMonitorForEachCallback(uint16_t task_id
, const struct pios_task_info
*task_info
, void *context
);
112 static void callbackSchedulerForEachCallback(int16_t callback_id
, const struct pios_callback_info
*callback_info
, void *context
);
114 static void updateStats();
115 static void updateSystemAlarms();
116 static void systemTask(void *parameters
);
117 #ifdef DIAG_I2C_WDG_STATS
118 static void updateI2Cstats();
119 static void updateWDGstats();
122 extern uintptr_t pios_uavo_settings_fs_id
;
123 extern uintptr_t pios_user_fs_id
;
126 * Create the module task.
127 * \returns 0 on success or -1 if initialization failed
129 int32_t SystemModStart(void)
132 stackOverflow
= STACKOVERFLOW_NONE
;
133 mallocFailed
= false;
134 // Create system task
135 xTaskCreate(systemTask
, "System", STACK_SIZE_BYTES
/ 4, NULL
, TASK_PRIORITY
, &systemTaskHandle
);
137 PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_SYSTEM
, systemTaskHandle
);
143 * Initialize the module, called on startup.
144 * \returns 0 on success or -1 if initialization failed
146 int32_t SystemModInitialize(void)
148 // Must registers objects here for system thread because ObjectManager started in OpenPilotInit
149 SystemSettingsInitialize();
150 SystemStatsInitialize();
151 FlightStatusInitialize();
152 ObjectPersistenceInitialize();
154 TaskInfoInitialize();
155 CallbackInfoInitialize();
157 #ifdef DIAG_I2C_WDG_STATS
158 I2CStatsInitialize();
159 WatchdogStatusInitialize();
162 #ifdef PIOS_INCLUDE_INSTRUMENTATION
163 InstrumentationInit();
166 objectPersistenceQueue
= xQueueCreate(1, sizeof(UAVObjEvent
));
167 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 while (!initTaskDone
) {
186 /* create all modules thread */
187 MODULE_TASKCREATE_ALL
;
189 /* start the delayed callback scheduler */
190 PIOS_CALLBACKSCHEDULER_Start();
193 /* We failed to malloc during task creation,
194 * system behaviour is undefined. Reset and let
195 * the BootFault code recover for us.
199 #if defined(PIOS_INCLUDE_IAP)
200 /* Record a successful boot */
201 PIOS_IAP_WriteBootCount(0);
203 // Listen for SettingPersistance object updates, connect a callback function
204 ObjectPersistenceConnectQueue(objectPersistenceQueue
);
206 // Load a copy of HwSetting active at boot time
207 HwSettingsGet(&bootHwSettings
);
208 bootFrameType
= GetCurrentFrameType();
209 // Whenever the configuration changes, make sure it is safe to fly
210 HwSettingsConnectCallback(checkSettingsUpdatedCb
);
211 SystemSettingsConnectCallback(checkSettingsUpdatedCb
);
214 TaskInfoData taskInfoData
;
215 CallbackInfoData callbackInfoData
;
219 NotificationUpdateStatus();
220 // Update the system statistics
222 // Update the system alarms
223 updateSystemAlarms();
224 #ifdef DIAG_I2C_WDG_STATS
229 #ifdef PIOS_INCLUDE_INSTRUMENTATION
230 InstrumentationPublishAllCounters();
234 // Update the task status object
235 PIOS_TASK_MONITOR_ForEachTask(taskMonitorForEachCallback
, &taskInfoData
);
236 TaskInfoSet(&taskInfoData
);
237 // Update the callback status object
239 PIOS_CALLBACKSCHEDULER_ForEachCallback(callbackSchedulerForEachCallback
, &callbackInfoData
);
240 CallbackInfoSet(&callbackInfoData
);
247 int delayTime
= SYSTEM_UPDATE_PERIOD_MS
;
249 #if defined(PIOS_INCLUDE_RFM22B)
251 // Update the OPLinkStatus UAVO
252 OPLinkStatusData oplinkStatus
;
253 OPLinkStatusGet(&oplinkStatus
);
255 if (pios_rfm22b_id
) {
256 // Get the other device stats.
257 PIOS_RFM2B_GetPairStats(pios_rfm22b_id
, oplinkStatus
.PairIDs
, oplinkStatus
.PairSignalStrengths
, OPLINKSTATUS_PAIRIDS_NUMELEM
);
259 // Get the stats from the radio device
260 struct rfm22b_stats radio_stats
;
261 PIOS_RFM22B_GetStats(pios_rfm22b_id
, &radio_stats
);
263 // Update the OPLInk status
264 static bool first_time
= true;
265 static uint16_t prev_tx_count
= 0;
266 static uint16_t prev_rx_count
= 0;
267 oplinkStatus
.HeapRemaining
= xPortGetFreeHeapSize();
268 oplinkStatus
.DeviceID
= PIOS_RFM22B_DeviceID(pios_rfm22b_id
);
269 oplinkStatus
.RxGood
= radio_stats
.rx_good
;
270 oplinkStatus
.RxCorrected
= radio_stats
.rx_corrected
;
271 oplinkStatus
.RxErrors
= radio_stats
.rx_error
;
272 oplinkStatus
.RxMissed
= radio_stats
.rx_missed
;
273 oplinkStatus
.RxFailure
= radio_stats
.rx_failure
;
274 oplinkStatus
.TxDropped
= radio_stats
.tx_dropped
;
275 oplinkStatus
.TxFailure
= radio_stats
.tx_failure
;
276 oplinkStatus
.Resets
= radio_stats
.resets
;
277 oplinkStatus
.Timeouts
= radio_stats
.timeouts
;
278 oplinkStatus
.RSSI
= radio_stats
.rssi
;
279 oplinkStatus
.LinkQuality
= radio_stats
.link_quality
;
283 uint16_t tx_count
= radio_stats
.tx_byte_count
;
284 uint16_t rx_count
= radio_stats
.rx_byte_count
;
285 uint16_t tx_bytes
= (tx_count
< prev_tx_count
) ? (0xffff - prev_tx_count
+ tx_count
) : (tx_count
- prev_tx_count
);
286 uint16_t rx_bytes
= (rx_count
< prev_rx_count
) ? (0xffff - prev_rx_count
+ rx_count
) : (rx_count
- prev_rx_count
);
287 oplinkStatus
.TXRate
= (uint16_t)((float)(tx_bytes
* 1000) / SYSTEM_UPDATE_PERIOD_MS
);
288 oplinkStatus
.RXRate
= (uint16_t)((float)(rx_bytes
* 1000) / SYSTEM_UPDATE_PERIOD_MS
);
289 prev_tx_count
= tx_count
;
290 prev_rx_count
= rx_count
;
292 oplinkStatus
.TXSeq
= radio_stats
.tx_seq
;
293 oplinkStatus
.RXSeq
= radio_stats
.rx_seq
;
295 oplinkStatus
.LinkState
= radio_stats
.link_state
;
297 oplinkStatus
.LinkState
= OPLINKSTATUS_LINKSTATE_DISABLED
;
299 OPLinkStatusSet(&oplinkStatus
);
301 #endif /* if defined(PIOS_INCLUDE_RFM22B) */
303 if (xQueueReceive(objectPersistenceQueue
, &ev
, delayTime
) == pdTRUE
) {
304 // If object persistence is updated call the callback
305 objectUpdatedCb(&ev
);
311 * Function called in response to object updates
313 static void objectUpdatedCb(UAVObjEvent
*ev
)
315 ObjectPersistenceData objper
;
318 // If the object updated was the ObjectPersistence execute requested action
319 if (ev
->obj
== ObjectPersistenceHandle()) {
321 ObjectPersistenceGet(&objper
);
324 FlightStatusData flightStatus
;
325 FlightStatusGet(&flightStatus
);
327 // When this is called because of this method don't do anything
328 if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_ERROR
|| objper
.Operation
== OBJECTPERSISTENCE_OPERATION_COMPLETED
) {
332 // Execute action if disarmed
333 if (flightStatus
.Armed
!= FLIGHTSTATUS_ARMED_DISARMED
) {
335 } else if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_LOAD
) {
336 if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_SINGLEOBJECT
) {
337 // Get selected object
338 obj
= UAVObjGetByID(objper
.ObjectID
);
342 // Load selected instance
343 retval
= UAVObjLoad(obj
, objper
.InstanceID
);
344 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLSETTINGS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
345 retval
= UAVObjLoadSettings();
346 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLMETAOBJECTS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
347 retval
= UAVObjLoadMetaobjects();
349 } else if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_SAVE
) {
350 if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_SINGLEOBJECT
) {
351 // Get selected object
352 obj
= UAVObjGetByID(objper
.ObjectID
);
356 // Save selected instance
357 retval
= UAVObjSave(obj
, objper
.InstanceID
);
359 // Not sure why this is needed
362 // Verify saving worked
364 retval
= UAVObjLoad(obj
, objper
.InstanceID
);
366 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLSETTINGS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
367 retval
= UAVObjSaveSettings();
368 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLMETAOBJECTS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
369 retval
= UAVObjSaveMetaobjects();
371 } else if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_DELETE
) {
372 if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_SINGLEOBJECT
) {
373 // Get selected object
374 obj
= UAVObjGetByID(objper
.ObjectID
);
378 // Delete selected instance
379 retval
= UAVObjDelete(obj
, objper
.InstanceID
);
380 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLSETTINGS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
381 retval
= UAVObjDeleteSettings();
382 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLMETAOBJECTS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
383 retval
= UAVObjDeleteMetaobjects();
385 } else if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_FULLERASE
) {
386 #if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
387 retval
= PIOS_FLASHFS_Format(0);
394 objper
.Operation
= OBJECTPERSISTENCE_OPERATION_COMPLETED
;
395 ObjectPersistenceSet(&objper
);
398 objper
.Operation
= OBJECTPERSISTENCE_OPERATION_ERROR
;
399 ObjectPersistenceSet(&objper
);
408 * Called whenever hardware settings changed
410 static void checkSettingsUpdatedCb(__attribute__((unused
)) UAVObjEvent
*ev
)
412 HwSettingsData currentHwSettings
;
414 HwSettingsGet(¤tHwSettings
);
415 FrameType_t currentFrameType
= GetCurrentFrameType();
416 // check whether the Hw Configuration has changed from the one used at boot time
417 if ((memcmp(&bootHwSettings
, ¤tHwSettings
, sizeof(HwSettingsData
)) != 0) ||
418 (currentFrameType
!= bootFrameType
)) {
419 ExtendedAlarmsSet(SYSTEMALARMS_ALARM_BOOTFAULT
, SYSTEMALARMS_ALARM_CRITICAL
, SYSTEMALARMS_EXTENDEDALARMSTATUS_REBOOTREQUIRED
, 0);
424 static void taskMonitorForEachCallback(uint16_t task_id
, const struct pios_task_info
*task_info
, void *context
)
426 TaskInfoData
*taskData
= (TaskInfoData
*)context
;
428 // By convention, there is a direct mapping between task monitor task_id's and members
429 // of the TaskInfoXXXXElem enums
430 PIOS_DEBUG_Assert(task_id
< TASKINFO_RUNNING_NUMELEM
);
431 TaskInfoRunningToArray(taskData
->Running
)[task_id
] = task_info
->is_running
? TASKINFO_RUNNING_TRUE
: TASKINFO_RUNNING_FALSE
;
432 ((uint16_t *)&taskData
->StackRemaining
)[task_id
] = task_info
->stack_remaining
;
433 ((uint8_t *)&taskData
->RunningTime
)[task_id
] = task_info
->running_time_percentage
;
436 static void callbackSchedulerForEachCallback(int16_t callback_id
, const struct pios_callback_info
*callback_info
, void *context
)
438 CallbackInfoData
*callbackData
= (CallbackInfoData
*)context
;
440 if (callback_id
< 0) {
443 // delayed callback scheduler reports callback stack overflows as remaininng: -1
444 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32)
445 if (callback_info
->stack_remaining
< 0 && stackOverflow
== STACKOVERFLOW_NONE
) {
446 stackOverflow
= STACKOVERFLOW_WARNING
;
449 // By convention, there is a direct mapping between (not negative) callback scheduler callback_id's and members
450 // of the CallbackInfoXXXXElem enums
451 PIOS_DEBUG_Assert(callback_id
< CALLBACKINFO_RUNNING_NUMELEM
);
452 ((uint8_t *)&callbackData
->Running
)[callback_id
] = callback_info
->is_running
;
453 ((uint32_t *)&callbackData
->RunningTime
)[callback_id
] = callback_info
->running_time_count
;
454 ((int16_t *)&callbackData
->StackRemaining
)[callback_id
] = callback_info
->stack_remaining
;
456 #endif /* ifdef DIAG_TASKS */
459 * Called periodically to update the I2C statistics
461 #ifdef DIAG_I2C_WDG_STATS
462 static void updateI2Cstats()
464 #if defined(PIOS_INCLUDE_I2C)
465 I2CStatsData i2cStats
;
466 I2CStatsGet(&i2cStats
);
468 struct pios_i2c_fault_history history
;
469 PIOS_I2C_GetDiagnostics(&history
, &i2cStats
.event_errors
);
471 for (uint8_t i
= 0; (i
< I2C_LOG_DEPTH
) && (i
< I2CSTATS_EVENT_LOG_NUMELEM
); i
++) {
472 i2cStats
.evirq_log
[i
] = history
.evirq
[i
];
473 i2cStats
.erirq_log
[i
] = history
.erirq
[i
];
474 i2cStats
.event_log
[i
] = history
.event
[i
];
475 i2cStats
.state_log
[i
] = history
.state
[i
];
477 i2cStats
.last_error_type
= history
.type
;
478 I2CStatsSet(&i2cStats
);
482 static void updateWDGstats()
484 WatchdogStatusData watchdogStatus
;
486 watchdogStatus
.BootupFlags
= PIOS_WDG_GetBootupFlags();
487 watchdogStatus
.ActiveFlags
= PIOS_WDG_GetActiveFlags();
488 WatchdogStatusSet(&watchdogStatus
);
490 #endif /* ifdef DIAG_I2C_WDG_STATS */
493 * Called periodically to update the system stats
495 static uint16_t GetFreeIrqStackSize(void)
499 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK)
500 extern uint32_t _irq_stack_top
;
501 extern uint32_t _irq_stack_end
;
502 uint32_t pattern
= 0x0000A5A5;
503 uint32_t *ptr
= &_irq_stack_end
;
505 #if 1 /* the ugly way accurate but takes more time, useful for debugging */
506 uint32_t stack_size
= (((uint32_t)&_irq_stack_top
- (uint32_t)&_irq_stack_end
) & ~3) / 4;
508 for (i
= 0; i
< stack_size
; i
++) {
509 if (ptr
[i
] != pattern
) {
514 #else /* faster way but not accurate */
515 if (*(volatile uint32_t *)((uint32_t)ptr
+ IRQSTACK_LIMIT_CRITICAL
) != pattern
) {
516 i
= IRQSTACK_LIMIT_CRITICAL
- 1;
517 } else if (*(volatile uint32_t *)((uint32_t)ptr
+ IRQSTACK_LIMIT_WARNING
) != pattern
) {
518 i
= IRQSTACK_LIMIT_WARNING
- 1;
520 i
= IRQSTACK_LIMIT_WARNING
;
523 #endif /* if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK) */
528 * Called periodically to update the system stats
530 static void updateStats()
532 SystemStatsData stats
;
534 // Get stats and update
535 SystemStatsGet(&stats
);
536 stats
.FlightTime
= xTaskGetTickCount() * portTICK_RATE_MS
;
537 #if defined(ARCH_POSIX) || defined(ARCH_WIN32)
538 // POSIX port of FreeRTOS doesn't have xPortGetFreeHeapSize()
539 stats
.SystemModStackRemaining
= 128;
540 stats
.HeapRemaining
= 10240;
542 stats
.HeapRemaining
= xPortGetFreeHeapSize();
543 stats
.SystemModStackRemaining
= uxTaskGetStackHighWaterMark(NULL
) * 4;
546 // Get Irq stack status
547 stats
.IRQStackRemaining
= GetFreeIrqStackSize();
549 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
550 static struct PIOS_FLASHFS_Stats fsStats
;
552 if (pios_uavo_settings_fs_id
) {
553 PIOS_FLASHFS_GetStats(pios_uavo_settings_fs_id
, &fsStats
);
554 stats
.SysSlotsFree
= fsStats
.num_free_slots
;
555 stats
.SysSlotsActive
= fsStats
.num_active_slots
;
557 if (pios_user_fs_id
) {
558 PIOS_FLASHFS_GetStats(pios_user_fs_id
, &fsStats
);
559 stats
.UsrSlotsFree
= fsStats
.num_free_slots
;
560 stats
.UsrSlotsActive
= fsStats
.num_active_slots
;
563 stats
.CPULoad
= 100 - PIOS_TASK_MONITOR_GetIdlePercentage();
565 #if defined(PIOS_INCLUDE_ADC) && defined(PIOS_ADC_USE_TEMP_SENSOR)
566 float temp_voltage
= PIOS_ADC_PinGetVolt(PIOS_ADC_TEMPERATURE_PIN
);
567 stats
.CPUTemp
= PIOS_CONVERT_VOLT_TO_CPU_TEMP(temp_voltage
);;
569 SystemStatsSet(&stats
);
573 * Update system alarms
575 static void updateSystemAlarms()
577 SystemStatsData stats
;
578 UAVObjStats objStats
;
581 SystemStatsGet(&stats
);
583 // Check heap, IRQ stack and malloc failures
584 if (mallocFailed
|| (stats
.HeapRemaining
< HEAP_LIMIT_CRITICAL
)
585 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK)
586 || (stats
.IRQStackRemaining
< IRQSTACK_LIMIT_CRITICAL
)
589 AlarmsSet(SYSTEMALARMS_ALARM_OUTOFMEMORY
, SYSTEMALARMS_ALARM_CRITICAL
);
590 } else if ((stats
.HeapRemaining
< HEAP_LIMIT_WARNING
)
591 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK)
592 || (stats
.IRQStackRemaining
< IRQSTACK_LIMIT_WARNING
)
595 AlarmsSet(SYSTEMALARMS_ALARM_OUTOFMEMORY
, SYSTEMALARMS_ALARM_WARNING
);
597 AlarmsClear(SYSTEMALARMS_ALARM_OUTOFMEMORY
);
601 if (stats
.CPULoad
> CPULOAD_LIMIT_CRITICAL
) {
602 AlarmsSet(SYSTEMALARMS_ALARM_CPUOVERLOAD
, SYSTEMALARMS_ALARM_CRITICAL
);
603 } else if (stats
.CPULoad
> CPULOAD_LIMIT_WARNING
) {
604 AlarmsSet(SYSTEMALARMS_ALARM_CPUOVERLOAD
, SYSTEMALARMS_ALARM_WARNING
);
606 AlarmsClear(SYSTEMALARMS_ALARM_CPUOVERLOAD
);
609 // Check for stack overflow
610 switch (stackOverflow
) {
611 case STACKOVERFLOW_NONE
:
612 AlarmsClear(SYSTEMALARMS_ALARM_STACKOVERFLOW
);
614 case STACKOVERFLOW_WARNING
:
615 AlarmsSet(SYSTEMALARMS_ALARM_STACKOVERFLOW
, SYSTEMALARMS_ALARM_WARNING
);
618 AlarmsSet(SYSTEMALARMS_ALARM_STACKOVERFLOW
, SYSTEMALARMS_ALARM_CRITICAL
);
621 // Check for event errors
622 UAVObjGetStats(&objStats
);
623 EventGetStats(&evStats
);
626 if (objStats
.eventCallbackErrors
> 0 || objStats
.eventQueueErrors
> 0 || evStats
.eventErrors
> 0) {
627 AlarmsSet(SYSTEMALARMS_ALARM_EVENTSYSTEM
, SYSTEMALARMS_ALARM_WARNING
);
629 AlarmsClear(SYSTEMALARMS_ALARM_EVENTSYSTEM
);
632 if (objStats
.lastCallbackErrorID
|| objStats
.lastQueueErrorID
|| evStats
.lastErrorID
) {
633 SystemStatsData sysStats
;
634 SystemStatsGet(&sysStats
);
635 sysStats
.EventSystemWarningID
= evStats
.lastErrorID
;
636 sysStats
.ObjectManagerCallbackID
= objStats
.lastCallbackErrorID
;
637 sysStats
.ObjectManagerQueueID
= objStats
.lastQueueErrorID
;
638 SystemStatsSet(&sysStats
);
643 * Called by the RTOS when the CPU is idle,
645 void vApplicationIdleHook(void)
647 NotificationOnboardLedsRun();
648 #ifdef PIOS_INCLUDE_WS2811
649 LedNotificationExtLedsRun();
653 * Called by the RTOS when a stack overflow is detected.
655 #define DEBUG_STACK_OVERFLOW 0
656 void vApplicationStackOverflowHook(__attribute__((unused
)) xTaskHandle
*pxTask
,
657 __attribute__((unused
)) signed portCHAR
*pcTaskName
)
659 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32)
660 stackOverflow
= STACKOVERFLOW_CRITICAL
;
661 #if DEBUG_STACK_OVERFLOW
662 static volatile bool wait_here
= true;
672 * Called by the RTOS when a malloc call fails.
674 #define DEBUG_MALLOC_FAILURES 0
675 void vApplicationMallocFailedHook(void)
678 #if DEBUG_MALLOC_FAILURES
679 static volatile bool wait_here
= true;