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"
44 #include "notification.h"
47 #include <objectpersistence.h>
48 #include <flightstatus.h>
49 #include <systemstats.h>
50 #include <systemsettings.h>
53 #include <watchdogstatus.h>
54 #include <callbackinfo.h>
55 #include <hwsettings.h>
56 #include <pios_flashfs.h>
58 #ifdef PIOS_INCLUDE_INSTRUMENTATION
59 #include <instrumentation.h>
60 #include <pios_instrumentation.h>
63 #if defined(PIOS_INCLUDE_RFM22B)
64 #include <oplinkstatus.h>
68 #include <sanitycheck.h>
71 // #define DEBUG_THIS_FILE
73 #if defined(PIOS_INCLUDE_DEBUG_CONSOLE) && defined(DEBUG_THIS_FILE)
74 #define DEBUG_MSG(format, ...) PIOS_COM_SendFormattedString(PIOS_COM_DEBUG, format,##__VA_ARGS__)
76 #define DEBUG_MSG(format, ...)
80 #define SYSTEM_UPDATE_PERIOD_MS 250
82 #if defined(PIOS_SYSTEM_STACK_SIZE)
83 #define STACK_SIZE_BYTES PIOS_SYSTEM_STACK_SIZE
85 #define STACK_SIZE_BYTES 1024
88 #define TASK_PRIORITY (tskIDLE_PRIORITY + 1)
93 static xTaskHandle systemTaskHandle
;
94 static xQueueHandle objectPersistenceQueue
;
95 static enum { STACKOVERFLOW_NONE
= 0, STACKOVERFLOW_WARNING
= 1, STACKOVERFLOW_CRITICAL
= 3 } stackOverflow
;
96 static bool mallocFailed
;
97 static HwSettingsData bootHwSettings
;
98 static FrameType_t bootFrameType
;
99 static struct PIOS_FLASHFS_Stats fsStats
;
102 static void objectUpdatedCb(UAVObjEvent
*ev
);
103 static void checkSettingsUpdatedCb(UAVObjEvent
*ev
);
105 static void taskMonitorForEachCallback(uint16_t task_id
, const struct pios_task_info
*task_info
, void *context
);
106 static void callbackSchedulerForEachCallback(int16_t callback_id
, const struct pios_callback_info
*callback_info
, void *context
);
108 static void updateStats();
109 static void updateSystemAlarms();
110 static void systemTask(void *parameters
);
111 #ifdef DIAG_I2C_WDG_STATS
112 static void updateI2Cstats();
113 static void updateWDGstats();
116 extern uintptr_t pios_uavo_settings_fs_id
;
117 extern uintptr_t pios_user_fs_id
;
120 * Create the module task.
121 * \returns 0 on success or -1 if initialization failed
123 int32_t SystemModStart(void)
126 stackOverflow
= STACKOVERFLOW_NONE
;
127 mallocFailed
= false;
128 // Create system task
129 xTaskCreate(systemTask
, "System", STACK_SIZE_BYTES
/ 4, NULL
, TASK_PRIORITY
, &systemTaskHandle
);
131 PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_SYSTEM
, systemTaskHandle
);
137 * Initialize the module, called on startup.
138 * \returns 0 on success or -1 if initialization failed
140 int32_t SystemModInitialize(void)
142 // Must registers objects here for system thread because ObjectManager started in OpenPilotInit
143 SystemSettingsInitialize();
144 SystemStatsInitialize();
145 FlightStatusInitialize();
146 ObjectPersistenceInitialize();
148 TaskInfoInitialize();
149 CallbackInfoInitialize();
151 #ifdef DIAG_I2C_WDG_STATS
152 I2CStatsInitialize();
153 WatchdogStatusInitialize();
156 #ifdef PIOS_INCLUDE_INSTRUMENTATION
157 InstrumentationInit();
160 objectPersistenceQueue
= xQueueCreate(1, sizeof(UAVObjEvent
));
161 if (objectPersistenceQueue
== NULL
) {
170 MODULE_INITCALL(SystemModInitialize
, 0);
172 * System task, periodically executes every SYSTEM_UPDATE_PERIOD_MS
174 static void systemTask(__attribute__((unused
)) void *parameters
)
176 /* create all modules thread */
177 MODULE_TASKCREATE_ALL
;
179 /* start the delayed callback scheduler */
180 PIOS_CALLBACKSCHEDULER_Start();
183 /* We failed to malloc during task creation,
184 * system behaviour is undefined. Reset and let
185 * the BootFault code recover for us.
189 #if defined(PIOS_INCLUDE_IAP)
190 /* Record a successful boot */
191 PIOS_IAP_WriteBootCount(0);
193 // Listen for SettingPersistance object updates, connect a callback function
194 ObjectPersistenceConnectQueue(objectPersistenceQueue
);
196 // Load a copy of HwSetting active at boot time
197 HwSettingsGet(&bootHwSettings
);
198 bootFrameType
= GetCurrentFrameType();
199 // Whenever the configuration changes, make sure it is safe to fly
200 HwSettingsConnectCallback(checkSettingsUpdatedCb
);
201 SystemSettingsConnectCallback(checkSettingsUpdatedCb
);
204 TaskInfoData taskInfoData
;
205 CallbackInfoData callbackInfoData
;
209 NotificationUpdateStatus();
210 // Update the system statistics
212 // Update the system alarms
213 updateSystemAlarms();
214 #ifdef DIAG_I2C_WDG_STATS
219 #ifdef PIOS_INCLUDE_INSTRUMENTATION
220 InstrumentationPublishAllCounters();
224 // Update the task status object
225 PIOS_TASK_MONITOR_ForEachTask(taskMonitorForEachCallback
, &taskInfoData
);
226 TaskInfoSet(&taskInfoData
);
227 // Update the callback status object
229 PIOS_CALLBACKSCHEDULER_ForEachCallback(callbackSchedulerForEachCallback
, &callbackInfoData
);
230 CallbackInfoSet(&callbackInfoData
);
237 int delayTime
= SYSTEM_UPDATE_PERIOD_MS
;
239 #if defined(PIOS_INCLUDE_RFM22B)
241 // Update the OPLinkStatus UAVO
242 OPLinkStatusData oplinkStatus
;
243 OPLinkStatusGet(&oplinkStatus
);
245 if (pios_rfm22b_id
) {
246 // Get the other device stats.
247 PIOS_RFM2B_GetPairStats(pios_rfm22b_id
, oplinkStatus
.PairIDs
, oplinkStatus
.PairSignalStrengths
, OPLINKSTATUS_PAIRIDS_NUMELEM
);
249 // Get the stats from the radio device
250 struct rfm22b_stats radio_stats
;
251 PIOS_RFM22B_GetStats(pios_rfm22b_id
, &radio_stats
);
253 // Update the OPLInk status
254 static bool first_time
= true;
255 static uint16_t prev_tx_count
= 0;
256 static uint16_t prev_rx_count
= 0;
257 oplinkStatus
.HeapRemaining
= xPortGetFreeHeapSize();
258 oplinkStatus
.DeviceID
= PIOS_RFM22B_DeviceID(pios_rfm22b_id
);
259 oplinkStatus
.RxGood
= radio_stats
.rx_good
;
260 oplinkStatus
.RxCorrected
= radio_stats
.rx_corrected
;
261 oplinkStatus
.RxErrors
= radio_stats
.rx_error
;
262 oplinkStatus
.RxMissed
= radio_stats
.rx_missed
;
263 oplinkStatus
.RxFailure
= radio_stats
.rx_failure
;
264 oplinkStatus
.TxDropped
= radio_stats
.tx_dropped
;
265 oplinkStatus
.TxResent
= radio_stats
.tx_resent
;
266 oplinkStatus
.TxFailure
= radio_stats
.tx_failure
;
267 oplinkStatus
.Resets
= radio_stats
.resets
;
268 oplinkStatus
.Timeouts
= radio_stats
.timeouts
;
269 oplinkStatus
.RSSI
= radio_stats
.rssi
;
270 oplinkStatus
.LinkQuality
= radio_stats
.link_quality
;
274 uint16_t tx_count
= radio_stats
.tx_byte_count
;
275 uint16_t rx_count
= radio_stats
.rx_byte_count
;
276 uint16_t tx_bytes
= (tx_count
< prev_tx_count
) ? (0xffff - prev_tx_count
+ tx_count
) : (tx_count
- prev_tx_count
);
277 uint16_t rx_bytes
= (rx_count
< prev_rx_count
) ? (0xffff - prev_rx_count
+ rx_count
) : (rx_count
- prev_rx_count
);
278 oplinkStatus
.TXRate
= (uint16_t)((float)(tx_bytes
* 1000) / SYSTEM_UPDATE_PERIOD_MS
);
279 oplinkStatus
.RXRate
= (uint16_t)((float)(rx_bytes
* 1000) / SYSTEM_UPDATE_PERIOD_MS
);
280 prev_tx_count
= tx_count
;
281 prev_rx_count
= rx_count
;
283 oplinkStatus
.TXSeq
= radio_stats
.tx_seq
;
284 oplinkStatus
.RXSeq
= radio_stats
.rx_seq
;
286 oplinkStatus
.LinkState
= radio_stats
.link_state
;
288 oplinkStatus
.LinkState
= OPLINKSTATUS_LINKSTATE_DISABLED
;
290 OPLinkStatusSet(&oplinkStatus
);
292 #endif /* if defined(PIOS_INCLUDE_RFM22B) */
294 if (xQueueReceive(objectPersistenceQueue
, &ev
, delayTime
) == pdTRUE
) {
295 // If object persistence is updated call the callback
296 objectUpdatedCb(&ev
);
302 * Function called in response to object updates
304 static void objectUpdatedCb(UAVObjEvent
*ev
)
306 ObjectPersistenceData objper
;
309 // If the object updated was the ObjectPersistence execute requested action
310 if (ev
->obj
== ObjectPersistenceHandle()) {
312 ObjectPersistenceGet(&objper
);
315 FlightStatusData flightStatus
;
316 FlightStatusGet(&flightStatus
);
318 // When this is called because of this method don't do anything
319 if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_ERROR
|| objper
.Operation
== OBJECTPERSISTENCE_OPERATION_COMPLETED
) {
323 // Execute action if disarmed
324 if (flightStatus
.Armed
!= FLIGHTSTATUS_ARMED_DISARMED
) {
326 } else if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_LOAD
) {
327 if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_SINGLEOBJECT
) {
328 // Get selected object
329 obj
= UAVObjGetByID(objper
.ObjectID
);
333 // Load selected instance
334 retval
= UAVObjLoad(obj
, objper
.InstanceID
);
335 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLSETTINGS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
336 retval
= UAVObjLoadSettings();
337 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLMETAOBJECTS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
338 retval
= UAVObjLoadMetaobjects();
340 } else if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_SAVE
) {
341 if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_SINGLEOBJECT
) {
342 // Get selected object
343 obj
= UAVObjGetByID(objper
.ObjectID
);
347 // Save selected instance
348 retval
= UAVObjSave(obj
, objper
.InstanceID
);
350 // Not sure why this is needed
353 // Verify saving worked
355 retval
= UAVObjLoad(obj
, objper
.InstanceID
);
357 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLSETTINGS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
358 retval
= UAVObjSaveSettings();
359 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLMETAOBJECTS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
360 retval
= UAVObjSaveMetaobjects();
362 } else if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_DELETE
) {
363 if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_SINGLEOBJECT
) {
364 // Get selected object
365 obj
= UAVObjGetByID(objper
.ObjectID
);
369 // Delete selected instance
370 retval
= UAVObjDelete(obj
, objper
.InstanceID
);
371 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLSETTINGS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
372 retval
= UAVObjDeleteSettings();
373 } else if (objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLMETAOBJECTS
|| objper
.Selection
== OBJECTPERSISTENCE_SELECTION_ALLOBJECTS
) {
374 retval
= UAVObjDeleteMetaobjects();
376 } else if (objper
.Operation
== OBJECTPERSISTENCE_OPERATION_FULLERASE
) {
377 #if defined(PIOS_INCLUDE_FLASH_LOGFS_SETTINGS)
378 retval
= PIOS_FLASHFS_Format(0);
385 objper
.Operation
= OBJECTPERSISTENCE_OPERATION_COMPLETED
;
386 ObjectPersistenceSet(&objper
);
389 objper
.Operation
= OBJECTPERSISTENCE_OPERATION_ERROR
;
390 ObjectPersistenceSet(&objper
);
399 * Called whenever hardware settings changed
401 static void checkSettingsUpdatedCb(__attribute__((unused
)) UAVObjEvent
*ev
)
403 HwSettingsData currentHwSettings
;
405 HwSettingsGet(¤tHwSettings
);
406 FrameType_t currentFrameType
= GetCurrentFrameType();
407 // check whether the Hw Configuration has changed from the one used at boot time
408 if ((memcmp(&bootHwSettings
, ¤tHwSettings
, sizeof(HwSettingsData
)) != 0) ||
409 (currentFrameType
!= bootFrameType
)) {
410 ExtendedAlarmsSet(SYSTEMALARMS_ALARM_BOOTFAULT
, SYSTEMALARMS_ALARM_CRITICAL
, SYSTEMALARMS_EXTENDEDALARMSTATUS_REBOOTREQUIRED
, 0);
415 static void taskMonitorForEachCallback(uint16_t task_id
, const struct pios_task_info
*task_info
, void *context
)
417 TaskInfoData
*taskData
= (TaskInfoData
*)context
;
419 // By convention, there is a direct mapping between task monitor task_id's and members
420 // of the TaskInfoXXXXElem enums
421 PIOS_DEBUG_Assert(task_id
< TASKINFO_RUNNING_NUMELEM
);
422 TaskInfoRunningToArray(taskData
->Running
)[task_id
] = task_info
->is_running
? TASKINFO_RUNNING_TRUE
: TASKINFO_RUNNING_FALSE
;
423 ((uint16_t *)&taskData
->StackRemaining
)[task_id
] = task_info
->stack_remaining
;
424 ((uint8_t *)&taskData
->RunningTime
)[task_id
] = task_info
->running_time_percentage
;
427 static void callbackSchedulerForEachCallback(int16_t callback_id
, const struct pios_callback_info
*callback_info
, void *context
)
429 CallbackInfoData
*callbackData
= (CallbackInfoData
*)context
;
431 if (callback_id
< 0) {
434 // delayed callback scheduler reports callback stack overflows as remaininng: -1
435 if (callback_info
->stack_remaining
< 0 && stackOverflow
== STACKOVERFLOW_NONE
) {
436 stackOverflow
= STACKOVERFLOW_WARNING
;
438 // By convention, there is a direct mapping between (not negative) callback scheduler callback_id's and members
439 // of the CallbackInfoXXXXElem enums
440 PIOS_DEBUG_Assert(callback_id
< CALLBACKINFO_RUNNING_NUMELEM
);
441 ((uint8_t *)&callbackData
->Running
)[callback_id
] = callback_info
->is_running
;
442 ((uint32_t *)&callbackData
->RunningTime
)[callback_id
] = callback_info
->running_time_count
;
443 ((int16_t *)&callbackData
->StackRemaining
)[callback_id
] = callback_info
->stack_remaining
;
445 #endif /* ifdef DIAG_TASKS */
448 * Called periodically to update the I2C statistics
450 #ifdef DIAG_I2C_WDG_STATS
451 static void updateI2Cstats()
453 #if defined(PIOS_INCLUDE_I2C)
454 I2CStatsData i2cStats
;
455 I2CStatsGet(&i2cStats
);
457 struct pios_i2c_fault_history history
;
458 PIOS_I2C_GetDiagnostics(&history
, &i2cStats
.event_errors
);
460 for (uint8_t i
= 0; (i
< I2C_LOG_DEPTH
) && (i
< I2CSTATS_EVENT_LOG_NUMELEM
); i
++) {
461 i2cStats
.evirq_log
[i
] = history
.evirq
[i
];
462 i2cStats
.erirq_log
[i
] = history
.erirq
[i
];
463 i2cStats
.event_log
[i
] = history
.event
[i
];
464 i2cStats
.state_log
[i
] = history
.state
[i
];
466 i2cStats
.last_error_type
= history
.type
;
467 I2CStatsSet(&i2cStats
);
471 static void updateWDGstats()
473 WatchdogStatusData watchdogStatus
;
475 watchdogStatus
.BootupFlags
= PIOS_WDG_GetBootupFlags();
476 watchdogStatus
.ActiveFlags
= PIOS_WDG_GetActiveFlags();
477 WatchdogStatusSet(&watchdogStatus
);
479 #endif /* ifdef DIAG_I2C_WDG_STATS */
482 * Called periodically to update the system stats
484 static uint16_t GetFreeIrqStackSize(void)
488 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK)
489 extern uint32_t _irq_stack_top
;
490 extern uint32_t _irq_stack_end
;
491 uint32_t pattern
= 0x0000A5A5;
492 uint32_t *ptr
= &_irq_stack_end
;
494 #if 1 /* the ugly way accurate but takes more time, useful for debugging */
495 uint32_t stack_size
= (((uint32_t)&_irq_stack_top
- (uint32_t)&_irq_stack_end
) & ~3) / 4;
497 for (i
= 0; i
< stack_size
; i
++) {
498 if (ptr
[i
] != pattern
) {
503 #else /* faster way but not accurate */
504 if (*(volatile uint32_t *)((uint32_t)ptr
+ IRQSTACK_LIMIT_CRITICAL
) != pattern
) {
505 i
= IRQSTACK_LIMIT_CRITICAL
- 1;
506 } else if (*(volatile uint32_t *)((uint32_t)ptr
+ IRQSTACK_LIMIT_WARNING
) != pattern
) {
507 i
= IRQSTACK_LIMIT_WARNING
- 1;
509 i
= IRQSTACK_LIMIT_WARNING
;
512 #endif /* if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK) */
517 * Called periodically to update the system stats
519 static void updateStats()
521 SystemStatsData stats
;
523 // Get stats and update
524 SystemStatsGet(&stats
);
525 stats
.FlightTime
= xTaskGetTickCount() * portTICK_RATE_MS
;
526 #if defined(ARCH_POSIX) || defined(ARCH_WIN32)
527 // POSIX port of FreeRTOS doesn't have xPortGetFreeHeapSize()
528 stats
.SystemModStackRemaining
= 128;
529 stats
.HeapRemaining
= 10240;
531 stats
.HeapRemaining
= xPortGetFreeHeapSize();
532 stats
.SystemModStackRemaining
= uxTaskGetStackHighWaterMark(NULL
) * 4;
535 // Get Irq stack status
536 stats
.IRQStackRemaining
= GetFreeIrqStackSize();
538 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32)
539 if (pios_uavo_settings_fs_id
) {
540 PIOS_FLASHFS_GetStats(pios_uavo_settings_fs_id
, &fsStats
);
541 stats
.SysSlotsFree
= fsStats
.num_free_slots
;
542 stats
.SysSlotsActive
= fsStats
.num_active_slots
;
544 if (pios_user_fs_id
) {
545 PIOS_FLASHFS_GetStats(pios_user_fs_id
, &fsStats
);
546 stats
.UsrSlotsFree
= fsStats
.num_free_slots
;
547 stats
.UsrSlotsActive
= fsStats
.num_active_slots
;
550 stats
.CPULoad
= 100 - PIOS_TASK_MONITOR_GetIdlePercentage();
552 #if defined(PIOS_INCLUDE_ADC) && defined(PIOS_ADC_USE_TEMP_SENSOR)
553 float temp_voltage
= PIOS_ADC_PinGetVolt(PIOS_ADC_TEMPERATURE_PIN
);
554 stats
.CPUTemp
= PIOS_CONVERT_VOLT_TO_CPU_TEMP(temp_voltage
);;
556 SystemStatsSet(&stats
);
560 * Update system alarms
562 static void updateSystemAlarms()
564 SystemStatsData stats
;
565 UAVObjStats objStats
;
568 SystemStatsGet(&stats
);
570 // Check heap, IRQ stack and malloc failures
571 if (mallocFailed
|| (stats
.HeapRemaining
< HEAP_LIMIT_CRITICAL
)
572 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK)
573 || (stats
.IRQStackRemaining
< IRQSTACK_LIMIT_CRITICAL
)
576 AlarmsSet(SYSTEMALARMS_ALARM_OUTOFMEMORY
, SYSTEMALARMS_ALARM_CRITICAL
);
577 } else if ((stats
.HeapRemaining
< HEAP_LIMIT_WARNING
)
578 #if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK)
579 || (stats
.IRQStackRemaining
< IRQSTACK_LIMIT_WARNING
)
582 AlarmsSet(SYSTEMALARMS_ALARM_OUTOFMEMORY
, SYSTEMALARMS_ALARM_WARNING
);
584 AlarmsClear(SYSTEMALARMS_ALARM_OUTOFMEMORY
);
588 if (stats
.CPULoad
> CPULOAD_LIMIT_CRITICAL
) {
589 AlarmsSet(SYSTEMALARMS_ALARM_CPUOVERLOAD
, SYSTEMALARMS_ALARM_CRITICAL
);
590 } else if (stats
.CPULoad
> CPULOAD_LIMIT_WARNING
) {
591 AlarmsSet(SYSTEMALARMS_ALARM_CPUOVERLOAD
, SYSTEMALARMS_ALARM_WARNING
);
593 AlarmsClear(SYSTEMALARMS_ALARM_CPUOVERLOAD
);
596 // Check for stack overflow
597 switch (stackOverflow
) {
598 case STACKOVERFLOW_NONE
:
599 AlarmsClear(SYSTEMALARMS_ALARM_STACKOVERFLOW
);
601 case STACKOVERFLOW_WARNING
:
602 AlarmsSet(SYSTEMALARMS_ALARM_STACKOVERFLOW
, SYSTEMALARMS_ALARM_WARNING
);
605 AlarmsSet(SYSTEMALARMS_ALARM_STACKOVERFLOW
, SYSTEMALARMS_ALARM_CRITICAL
);
608 // Check for event errors
609 UAVObjGetStats(&objStats
);
610 EventGetStats(&evStats
);
613 if (objStats
.eventCallbackErrors
> 0 || objStats
.eventQueueErrors
> 0 || evStats
.eventErrors
> 0) {
614 AlarmsSet(SYSTEMALARMS_ALARM_EVENTSYSTEM
, SYSTEMALARMS_ALARM_WARNING
);
616 AlarmsClear(SYSTEMALARMS_ALARM_EVENTSYSTEM
);
619 if (objStats
.lastCallbackErrorID
|| objStats
.lastQueueErrorID
|| evStats
.lastErrorID
) {
620 SystemStatsData sysStats
;
621 SystemStatsGet(&sysStats
);
622 sysStats
.EventSystemWarningID
= evStats
.lastErrorID
;
623 sysStats
.ObjectManagerCallbackID
= objStats
.lastCallbackErrorID
;
624 sysStats
.ObjectManagerQueueID
= objStats
.lastQueueErrorID
;
625 SystemStatsSet(&sysStats
);
630 * Called by the RTOS when the CPU is idle,
632 void vApplicationIdleHook(void)
634 NotificationOnboardLedsRun();
637 * Called by the RTOS when a stack overflow is detected.
639 #define DEBUG_STACK_OVERFLOW 0
640 void vApplicationStackOverflowHook(__attribute__((unused
)) xTaskHandle
*pxTask
,
641 __attribute__((unused
)) signed portCHAR
*pcTaskName
)
643 stackOverflow
= STACKOVERFLOW_CRITICAL
;
644 #if DEBUG_STACK_OVERFLOW
645 static volatile bool wait_here
= true;
654 * Called by the RTOS when a malloc call fails.
656 #define DEBUG_MALLOC_FAILURES 0
657 void vApplicationMallocFailedHook(void)
660 #if DEBUG_MALLOC_FAILURES
661 static volatile bool wait_here
= true;