Skip to content

Commit

Permalink
Fix #411, rework exception handling in CFE
Browse files Browse the repository at this point in the history
Move exception handling to a PSP function.  In this approach
the CFE only logs data after the event as a background job.

Replaces the CFE_ES_ProcessCoreException with a simple notification
that causes the ES background job to run, which in turn polls the
PSP for logged exceptions and writes entries to the ES ER log.

Both the PSP execption scan and the ER log file dump are converted
to background jobs.
  • Loading branch information
jphickey committed May 6, 2020
1 parent 8365a0c commit 4eb937b
Show file tree
Hide file tree
Showing 19 changed files with 675 additions and 621 deletions.
48 changes: 1 addition & 47 deletions cmake/sample_defs/cpu1_platform_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@
** in the error log. Any context information beyond this size will
** be truncated.
*/
#define CFE_PLATFORM_ES_ER_LOG_MAX_CONTEXT_SIZE 128
#define CFE_PLATFORM_ES_ER_LOG_MAX_CONTEXT_SIZE 256


/**
Expand Down Expand Up @@ -1205,52 +1205,6 @@
*/
#define CFE_PLATFORM_ES_DEFAULT_STACK_SIZE 8192

/**
** \cfeescfg Define cFE Core Exception Function
**
** \par Description:
** This parameter defines the function-to-call when a CPU or floating point exception
** occurs. The parameter is defaulted to call the ES API function #CFE_ES_ProcessCoreException
** which handles the logging and reset from a system or cFE core exception.
**
** Note: Exception interrupts are trapped at the Platform Support Package (PSP)
** layer. In order to initiate the cFE platform defined response to an exception, this
** platform defined callback function must be prototyped and called from the PSP
** exception hook API function #CFE_PSP_ExceptionHook. For example:
**
** -- cfe_psp.h --
**
** .... Prototype for exception ISR function implemented in CFE ....
**
** typedef void (*System_ExceptionFunc_t)(uint32 HostTaskId,
** const char *ReasonString,
** const uint32 *ContextPointer,
** uint32 ContextSize);
**
** -- cfe_pspexception.c --
**
** .... Setup function pointer to CFE exception ISR callback ....
**
** static const System_ExceptionFunc_t CFE_ExceptionCallback = CFE_PLATFORM_ES_EXCEPTION_FUNCTION;
**
** void CFE_PSP_ExceptionHook (int task_id, int vector, uint8 *pEsf )
** {
** .... platform-specific logic ....
**
** .... Use function pointer to call cFE routine to finish processing the exception ....
**
** CFE_ExceptionCallback((uint32)task_id,
** CFE_PSP_ExceptionReasonString,
** (uint32 *)&CFE_PSP_ExceptionContext,
** sizeof(CFE_PSP_ExceptionContext_t));
**
** }
**
** \par Limits
** Must be a valid function name.
*/
#define CFE_PLATFORM_ES_EXCEPTION_FUNCTION CFE_ES_ProcessCoreException

/**
** \cfeescfg Define EVS Task Priority
**
Expand Down
13 changes: 9 additions & 4 deletions cmake/target/inc/target_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,15 @@ typedef void (*System_1HzISRFunc_t)(void);


/**
* Prototype for exception ISR function implemented in CFE ES
* Prototype for notification function implemented in CFE ES
* The PSP should call this when exceptions occur.
*
* NOTE: the PSP must call this routine only from a context where
* it is possible to use OSAL primitives. This means it must _not_
* be called from an ISR/signal context on systems where these are
* restricted.
*/
typedef void (*System_ExceptionFunc_t)(uint32 HostTaskId, const char *ReasonString, const uint32 *ContextPointer, uint32 ContextSize);
typedef void (*System_NotifyFunc_t)(void);

/**
* Abstract pointer to a module API
Expand Down Expand Up @@ -87,9 +92,9 @@ typedef const struct
System_MainFunc_t SystemMain;

/**
* Exception handler function. Called from PSP during exception handling.
* Notification function. Called from PSP after async event handling.
*/
System_ExceptionFunc_t SystemExceptionISR;
System_NotifyFunc_t SystemNotify;

/*
* Sizes of memory segments required by the CFE based on the current config
Expand Down
5 changes: 3 additions & 2 deletions cmake/target/src/target_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "cfe_platform_cfg.h"
#include "cfe_es.h"
#include "cfe_time.h"
#include "private/cfe_es_resetdata_typedef.h"
#include "cfecfs_version_info.h"
#include "cfecfs_build_info.h"

Expand All @@ -61,7 +62,7 @@ Target_CfeConfigData GLOBAL_CFE_CONFIGDATA =
*/
.System1HzISR = CFE_TIME_Local1HzISR,
.SystemMain = CFE_ES_Main,
.SystemExceptionISR = CFE_ES_ProcessCoreException,
.SystemNotify = CFE_ES_ProcessAsyncEvent,

/*
* Default values for Startup file.
Expand All @@ -73,7 +74,7 @@ Target_CfeConfigData GLOBAL_CFE_CONFIGDATA =
* Sizes of other memory segments
*/
.CdsSize = CFE_PLATFORM_ES_CDS_SIZE,
.ResetAreaSize = CFE_PLATFORM_ES_RESET_AREA_SIZE,
.ResetAreaSize = sizeof(CFE_ES_ResetData_t),
.UserReservedSize = CFE_PLATFORM_ES_USER_RESERVED_SIZE,

.RamDiskSectorSize = CFE_PLATFORM_ES_RAM_DISK_SECTOR_SIZE,
Expand Down
2 changes: 1 addition & 1 deletion docs/src/main.dox
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@
<UL>
<LI> #CFE_ES_CalculateCRC - \copybrief CFE_ES_CalculateCRC
<LI> #CFE_ES_WriteToSysLog - \copybrief CFE_ES_WriteToSysLog
<LI> #CFE_ES_ProcessCoreException - \copybrief CFE_ES_ProcessCoreException
<LI> #CFE_ES_ProcessAsyncEvent - \copybrief CFE_ES_ProcessAsyncEvent
</UL>
</UL>

Expand Down
136 changes: 12 additions & 124 deletions fsw/cfe-core/src/es/cfe_es_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "cfe_es_events.h"
#include "cfe_es_cds.h"
#include "cfe_es_cds_mempool.h"
#include "cfe_es_task.h"
#include "cfe_psp.h"
#include "cfe_es_log.h"

Expand Down Expand Up @@ -96,7 +97,7 @@ int32 CFE_ES_ResetCFE(uint32 ResetType)
*/
CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_POWERON,
CFE_PSP_RST_SUBTYPE_RESET_COMMAND,
"POWER ON RESET due to max proc resets (Commanded).", NULL,0 );
"POWER ON RESET due to max proc resets (Commanded).");
/*
** Call the BSP reset routine
*/
Expand All @@ -116,7 +117,7 @@ int32 CFE_ES_ResetCFE(uint32 ResetType)
*/
CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_PROCESSOR,
CFE_PSP_RST_SUBTYPE_RESET_COMMAND,
"PROCESSOR RESET called from CFE_ES_ResetCFE (Commanded).", NULL,0 );
"PROCESSOR RESET called from CFE_ES_ResetCFE (Commanded).");
/*
** Call the BSP reset routine
*/
Expand All @@ -140,7 +141,7 @@ int32 CFE_ES_ResetCFE(uint32 ResetType)
*/
CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_POWERON,
CFE_PSP_RST_SUBTYPE_RESET_COMMAND,
"POWERON RESET called from CFE_ES_ResetCFE (Commanded).", NULL,0 );
"POWERON RESET called from CFE_ES_ResetCFE (Commanded).");

/*
** Call the BSP reset routine
Expand Down Expand Up @@ -1716,126 +1717,13 @@ void CFE_ES_UnlockSharedData(const char *FunctionName, int32 LineNumber)
}/* end CFE_ES_UnlockSharedData */

/******************************************************************************
** Function: CFE_ES_ProcessCoreException() - See API and header file for details
** Function: CFE_ES_ProcessAsyncEvent()
**
** Purpose:
** Called by the PSP to notify CFE ES that an asynchronous event occurred.
*/
void CFE_ES_ProcessCoreException(uint32 HostTaskId, const char *ReasonString,
const uint32 *ContextPointer, uint32 ContextSize)
void CFE_ES_ProcessAsyncEvent(void)
{
uint32 i;
int32 Status;
OS_task_prop_t TaskProp;
CFE_ES_TaskInfo_t EsTaskInfo;
uint32 FoundExceptionTask = 0;
uint32 ExceptionTaskID = 0;

/*
** If a loadable cFE Application caused the reset and it's
** exception action is set to Restart the App rather than cause a
** processor reset, then just reset the App.
*/

/*
** We have the Host Task Id ( vxWorks, RTEMS, etc ). Search
** the OSAPI to see if a match can be found.
*/
for ( i = 0; i < OS_MAX_TASKS; i++ )
{
if (CFE_ES_Global.TaskTable[i].RecordUsed == true)
{
ExceptionTaskID = CFE_ES_Global.TaskTable[i].TaskId;
Status = OS_TaskGetInfo (ExceptionTaskID, &TaskProp);

if ( Status == OS_SUCCESS && TaskProp.OStask_id == HostTaskId )
{
FoundExceptionTask = 1;
break;
}
}
}

/*
** If the Task is found in the OS, see if the cFE App ID associated with it can be found.
*/
if ( FoundExceptionTask == 1 )
{
Status = CFE_ES_GetTaskInfo( &EsTaskInfo, ExceptionTaskID );
/*
** The App ID was found, now see if the ExceptionAction is set for a reset
*/
if ( Status == CFE_SUCCESS )
{
if ( CFE_ES_Global.AppTable[EsTaskInfo.AppId].StartParams.ExceptionAction == CFE_ES_ExceptionAction_RESTART_APP )
{

/*
** Log the Application reset
*/
CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_ES_APP_RESTART,
CFE_PSP_RST_SUBTYPE_EXCEPTION, (char *)ReasonString,
ContextPointer, ContextSize );

/*
** Finally restart the App! This call is just a request
** to ES.
*/
CFE_ES_RestartApp(EsTaskInfo.AppId );

/*
** Return to avoid the Processor Restart Logic
*/
return;

} /* end if ExceptionAction */

} /* end if */

} /* End if FoundExceptionTask */

/*
** If we made it here, which means that we need to do a processor reset
*/

/*
** Before doing a Processor reset, check to see
** if the maximum number has been exceeded
*/
if ( CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount >=
CFE_ES_ResetDataPtr->ResetVars.MaxProcessorResetCount )
{
/*
** Log the reset in the ER Log. The log will be wiped out, but it's good to have
** the entry just in case something fails.
*/
CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_POWERON,
CFE_PSP_RST_SUBTYPE_EXCEPTION, (char *)ReasonString,
ContextPointer, ContextSize );

/*
** Call the BSP reset routine to do a Poweron Reset
*/
CFE_PSP_Restart(CFE_PSP_RST_TYPE_POWERON);

}
else /* Do a processor reset */
{
/*
** Update the reset variables
*/
CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount++;
CFE_ES_ResetDataPtr->ResetVars.ES_CausedReset = true;

/*
** Log the reset in the ER Log
*/
CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_PROCESSOR,
CFE_PSP_RST_SUBTYPE_EXCEPTION, (char *)ReasonString,
ContextPointer, ContextSize );

/*
** Need to do a processor reset
*/
CFE_PSP_Restart(CFE_PSP_RST_TYPE_PROCESSOR);

} /* end if */

} /* End of CFE_ES_ProcessCoreException */
/* This just wakes up the background task to log/handle the event. */
CFE_ES_BackgroundWakeup();
}
10 changes: 10 additions & 0 deletions fsw/cfe-core/src/es/cfe_es_apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,16 @@ int32 CFE_ES_AppDumpAllInfo(void);
*/
bool CFE_ES_RunAppTableScan(uint32 ElapsedTime, void *Arg);

/*
** Scan for new exceptions stored in the PSP
*/
bool CFE_ES_RunExceptionScan(uint32 ElapsedTime, void *Arg);

/*
** Check if ER log dump request is pending
*/
bool CFE_ES_RunERLogDump(uint32 ElapsedTime, void *Arg);

/*
** Perform the requested control action for an application
*/
Expand Down
12 changes: 12 additions & 0 deletions fsw/cfe-core/src/es/cfe_es_backgroundtask.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,18 @@ const CFE_ES_BackgroundJobEntry_t CFE_ES_BACKGROUND_JOB_TABLE[] =
.JobArg = &CFE_ES_TaskData.BackgroundPerfDumpState,
.ActivePeriod = CFE_PLATFORM_ES_PERF_CHILD_MS_DELAY,
.IdlePeriod = CFE_PLATFORM_ES_PERF_CHILD_MS_DELAY * 1000
},
{ /* Check for exceptions stored in the PSP */
.RunFunc = CFE_ES_RunExceptionScan,
.JobArg = NULL,
.ActivePeriod = CFE_PLATFORM_ES_APP_SCAN_RATE,
.IdlePeriod = CFE_PLATFORM_ES_APP_SCAN_RATE
},
{ /* Check for ER log write requests */
.RunFunc = CFE_ES_RunERLogDump,
.JobArg = &CFE_ES_TaskData.BackgroundERLogDumpState,
.ActivePeriod = CFE_PLATFORM_ES_APP_SCAN_RATE,
.IdlePeriod = CFE_PLATFORM_ES_APP_SCAN_RATE
}
};

Expand Down
Loading

0 comments on commit 4eb937b

Please sign in to comment.