mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-17 02:52:12 +01:00
OP-942 duplicated exact API of task_monitor to also monitor callbacks
This allows cleaner and fine grained handling of STACKOVERFLOW alarms
This commit is contained in:
parent
9a6072d58c
commit
7ec21a8f36
@ -96,7 +96,7 @@ static uint32_t idleCounter;
|
||||
static uint32_t idleCounterClear;
|
||||
static xTaskHandle systemTaskHandle;
|
||||
static xQueueHandle objectPersistenceQueue;
|
||||
static bool stackOverflow;
|
||||
static enum { STACKOVERFLOW_NONE = 0, STACKOVERFLOW_HARMLESS = 1, STACKOVERFLOW_CRITICAL = 3 } stackOverflow;
|
||||
static bool mallocFailed;
|
||||
static HwSettingsData bootHwSettings;
|
||||
static struct PIOS_FLASHFS_Stats fsStats;
|
||||
@ -105,6 +105,7 @@ static void objectUpdatedCb(UAVObjEvent *ev);
|
||||
static void hwSettingsUpdatedCb(UAVObjEvent *ev);
|
||||
#ifdef DIAG_TASKS
|
||||
static void taskMonitorForEachCallback(uint16_t task_id, const struct pios_task_info *task_info, void *context);
|
||||
static void callbackSchedulerForEachCallback(int16_t callback_id, const struct pios_callback_info *callback_info, void *context);
|
||||
#endif
|
||||
static void updateStats();
|
||||
static void updateSystemAlarms();
|
||||
@ -124,7 +125,7 @@ extern uintptr_t pios_user_fs_id;
|
||||
int32_t SystemModStart(void)
|
||||
{
|
||||
// Initialize vars
|
||||
stackOverflow = false;
|
||||
stackOverflow = STACKOVERFLOW_NONE;
|
||||
mallocFailed = false;
|
||||
// Create system task
|
||||
xTaskCreate(systemTask, (signed char *)"System", STACK_SIZE_BYTES / 4, NULL, TASK_PRIORITY, &systemTaskHandle);
|
||||
@ -226,7 +227,7 @@ static void systemTask(__attribute__((unused)) void *parameters)
|
||||
PIOS_TASK_MONITOR_ForEachTask(taskMonitorForEachCallback, &taskInfoData);
|
||||
TaskInfoSet(&taskInfoData);
|
||||
// Update the callback status object
|
||||
PIOS_CALLBACKSCHEDULER_CallbackInfo(&callbackInfoData);
|
||||
PIOS_CALLBACKSCHEDULER_ForEachCallback(callbackSchedulerForEachCallback, &callbackInfoData);
|
||||
CallbackInfoSet(&callbackInfoData);
|
||||
#endif
|
||||
|
||||
@ -445,7 +446,26 @@ static void taskMonitorForEachCallback(uint16_t task_id, const struct pios_task_
|
||||
((uint16_t *)&taskData->StackRemaining)[task_id] = task_info->stack_remaining;
|
||||
((uint8_t *)&taskData->RunningTime)[task_id] = task_info->running_time_percentage;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void callbackSchedulerForEachCallback(int16_t callback_id, const struct pios_callback_info *callback_info, void *context)
|
||||
{
|
||||
CallbackInfoData *callbackData = (CallbackInfoData *)context;
|
||||
|
||||
if (callback_id < 0) {
|
||||
return;
|
||||
}
|
||||
// delayed callback scheduler reports callback stack overflows as remaininng: -1
|
||||
if (callback_info->stack_remaining < 0 && stackOverflow == STACKOVERFLOW_NONE) {
|
||||
stackOverflow = STACKOVERFLOW_HARMLESS;
|
||||
}
|
||||
// By convention, there is a direct mapping between (not negative) callback scheduler callback_id's and members
|
||||
// of the CallbackInfoXXXXElem enums
|
||||
PIOS_DEBUG_Assert(callback_id < CALLBACKINFO_RUNNING_NUMELEM);
|
||||
((uint8_t *)&callbackData->Running)[callback_id] = callback_info->is_running;
|
||||
((uint32_t *)&callbackData->RunningTime)[callback_id] = callback_info->running_time_count;
|
||||
((int16_t *)&callbackData->StackRemaining)[callback_id] = callback_info->stack_remaining;
|
||||
}
|
||||
#endif /* ifdef DIAG_TASKS */
|
||||
|
||||
/**
|
||||
* Called periodically to update the I2C statistics
|
||||
@ -607,10 +627,15 @@ static void updateSystemAlarms()
|
||||
}
|
||||
|
||||
// Check for stack overflow
|
||||
if (stackOverflow) {
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_STACKOVERFLOW, SYSTEMALARMS_ALARM_CRITICAL);
|
||||
} else {
|
||||
switch (stackOverflow) {
|
||||
case STACKOVERFLOW_NONE:
|
||||
AlarmsClear(SYSTEMALARMS_ALARM_STACKOVERFLOW);
|
||||
break;
|
||||
case STACKOVERFLOW_HARMLESS:
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_STACKOVERFLOW, SYSTEMALARMS_ALARM_WARNING);
|
||||
break;
|
||||
default:
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_STACKOVERFLOW, SYSTEMALARMS_ALARM_CRITICAL);
|
||||
}
|
||||
|
||||
// Check for event errors
|
||||
@ -655,7 +680,7 @@ void vApplicationIdleHook(void)
|
||||
void vApplicationStackOverflowHook(__attribute__((unused)) xTaskHandle *pxTask,
|
||||
__attribute__((unused)) signed portCHAR *pcTaskName)
|
||||
{
|
||||
stackOverflow = true;
|
||||
stackOverflow = STACKOVERFLOW_CRITICAL;
|
||||
#if DEBUG_STACK_OVERFLOW
|
||||
static volatile bool wait_here = true;
|
||||
while (wait_here) {
|
||||
|
@ -27,11 +27,9 @@
|
||||
#include <pios.h>
|
||||
#ifdef PIOS_INCLUDE_CALLBACKSCHEDULER
|
||||
|
||||
#include <pios_struct_helper.h>
|
||||
#include <utlist.h>
|
||||
#include <uavobjectmanager.h>
|
||||
#include <taskinfo.h>
|
||||
#include <callbackinfo.h>
|
||||
|
||||
// Private constants
|
||||
#define STACK_SAFETYCOUNT 16
|
||||
@ -358,18 +356,18 @@ DelayedCallbackInfo *PIOS_CALLBACKSCHEDULER_Create(
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve callback specific runtime information
|
||||
* \param[out] *callbackInfoData pointer to CallbackInfoData structure
|
||||
* \return Success (-1), failure (0)
|
||||
* Iterator. Iterates over all callbacks and all scheduler tasks and retrieves information
|
||||
*
|
||||
* @param[in] callback Callback function to receive the data - will be called in same task context as the callerThe id of the task the task_info refers to.
|
||||
* @param context Context information optionally provided to the callback.
|
||||
*/
|
||||
int32_t PIOS_CALLBACKSCHEDULER_CallbackInfo(void *callbackInfoData)
|
||||
void PIOS_CALLBACKSCHEDULER_ForEachCallback(CallbackSchedulerCallbackInfoCallback callback, void *context)
|
||||
{
|
||||
if (!callbackInfoData) {
|
||||
return 0;
|
||||
if (!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
CallbackInfoData *info = (CallbackInfoData *)callbackInfoData;
|
||||
|
||||
struct pios_callback_info info;
|
||||
|
||||
struct DelayedCallbackTaskStruct *task = NULL;
|
||||
LL_FOREACH(schedulerTasks, task) {
|
||||
@ -378,17 +376,15 @@ int32_t PIOS_CALLBACKSCHEDULER_CallbackInfo(void *callbackInfoData)
|
||||
for (prio = 0; prio < (CALLBACK_PRIORITY_LOW + 1); prio++) {
|
||||
struct DelayedCallbackInfoStruct *cbinfo;
|
||||
LL_FOREACH(task->callbackQueue[prio], cbinfo) {
|
||||
if (cbinfo->callbackID >= 0 && cbinfo->callbackID < CALLBACKINFO_RUNNING_NUMELEM) {
|
||||
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
|
||||
((uint8_t *)&info->Running)[cbinfo->callbackID] = true;
|
||||
((uint32_t *)&info->RunningTime)[cbinfo->callbackID] = cbinfo->runCount;
|
||||
((int16_t *)&info->StackRemaining)[cbinfo->callbackID] = (int16_t)cbinfo->stackNotFree;
|
||||
xSemaphoreGiveRecursive(mutex);
|
||||
}
|
||||
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
|
||||
info.is_running = true;
|
||||
info.stack_remaining = cbinfo->stackNotFree;
|
||||
info.running_time_count = cbinfo->runCount;
|
||||
xSemaphoreGiveRecursive(mutex);
|
||||
callback(cbinfo->callbackID, &info, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,11 +187,33 @@ int32_t PIOS_CALLBACKSCHEDULER_Dispatch(DelayedCallbackInfo *cbinfo);
|
||||
int32_t PIOS_CALLBACKSCHEDULER_DispatchFromISR(DelayedCallbackInfo *cbinfo, long *pxHigherPriorityTaskWoken);
|
||||
|
||||
/**
|
||||
* Retrieve callback specific runtime information
|
||||
* \param[out] *callbackInfoData pointer to CallbackInfoData structure
|
||||
* \return Success (-1), failure (0)
|
||||
* Information about a running callback that has been registered
|
||||
* via a call to PIOS_CALLBACKSCHEDULER_Create().
|
||||
*/
|
||||
int32_t PIOS_CALLBACKSCHEDULER_CallbackInfo(void *callbackInfoData);
|
||||
struct pios_callback_info {
|
||||
/** Remaining task stack in bytes -1 for detected stack overflow. */
|
||||
int32_t stack_remaining;
|
||||
/** Flag indicating whether or not the task is running. */
|
||||
bool is_running;
|
||||
/** Count of executions of the callback since system start */
|
||||
uint32_t running_time_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterator callback, called for each monitored callback by PIOS_CALLBACKSCHEDULER_ForEachCallback().
|
||||
*
|
||||
* @param task_id The id of the task the task_info refers to.
|
||||
* @param task_info Information about the task identified by task_id.
|
||||
* @param context Context information optionally provided by the caller to PIOS_TASK_MONITOR_TasksIterate()
|
||||
*/
|
||||
typedef void (*CallbackSchedulerCallbackInfoCallback)(int16_t task_id, const struct pios_callback_info *callback_info, void *context);
|
||||
|
||||
/**
|
||||
* Iterator. Iterates over all callbacks and all scheduler tasks and retrieves information
|
||||
*
|
||||
* @param[in] callback Callback function to receive the data - will be called in same task context as the callerThe id of the task the task_info refers to.
|
||||
* @param context Context information optionally provided to the callback.
|
||||
*/
|
||||
void PIOS_CALLBACKSCHEDULER_ForEachCallback(CallbackSchedulerCallbackInfoCallback callback, void *context);
|
||||
|
||||
#endif // PIOS_CALLBACKSCHEDULER_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user