1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-18 03:52:11 +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:
Corvus Corax 2014-02-07 22:34:27 +01:00
parent 9a6072d58c
commit 7ec21a8f36
3 changed files with 73 additions and 30 deletions

View File

@ -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) {

View File

@ -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;
info.is_running = true;
info.stack_remaining = cbinfo->stackNotFree;
info.running_time_count = cbinfo->runCount;
xSemaphoreGiveRecursive(mutex);
callback(cbinfo->callbackID, &info, context);
}
}
}
}
return -1;
}
/**

View File

@ -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