From d4f62edfad2a29af6d8d9c4714ae52511e4bc058 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Wed, 29 Apr 2020 11:07:24 -0400 Subject: [PATCH 1/2] Fix #411, rework exception handling in CFE 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. --- cmake/sample_defs/cpu1_platform_cfg.h | 2 +- cmake/target/inc/target_config.h | 13 +- cmake/target/src/target_config.c | 5 +- fsw/cfe-core/src/es/cfe_es_api.c | 136 +----- fsw/cfe-core/src/es/cfe_es_apps.h | 10 + fsw/cfe-core/src/es/cfe_es_backgroundtask.c | 12 + fsw/cfe-core/src/es/cfe_es_erlog.c | 408 +++++++++++++++--- fsw/cfe-core/src/es/cfe_es_log.h | 41 +- fsw/cfe-core/src/es/cfe_es_start.c | 42 +- fsw/cfe-core/src/es/cfe_es_task.c | 94 +--- fsw/cfe-core/src/es/cfe_es_task.h | 26 ++ fsw/cfe-core/src/es/cfe_es_verify.h | 10 - fsw/cfe-core/src/inc/cfe_es.h | 17 +- fsw/cfe-core/src/inc/cfe_es_events.h | 28 +- fsw/cfe-core/src/inc/cfe_evs_msg.h | 1 + .../src/inc/private/cfe_es_erlog_typedef.h | 47 +- .../inc/private/cfe_es_resetdata_typedef.h | 2 +- fsw/cfe-core/unit-test/es_UT.c | 354 ++++++--------- 18 files changed, 674 insertions(+), 574 deletions(-) diff --git a/cmake/sample_defs/cpu1_platform_cfg.h b/cmake/sample_defs/cpu1_platform_cfg.h index 3e85be30c..1a7f3f5bd 100644 --- a/cmake/sample_defs/cpu1_platform_cfg.h +++ b/cmake/sample_defs/cpu1_platform_cfg.h @@ -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 /** diff --git a/cmake/target/inc/target_config.h b/cmake/target/inc/target_config.h index d88d512a5..71c6082cc 100644 --- a/cmake/target/inc/target_config.h +++ b/cmake/target/inc/target_config.h @@ -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 @@ -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 diff --git a/cmake/target/src/target_config.c b/cmake/target/src/target_config.c index 1bde3d10b..f15233450 100644 --- a/cmake/target/src/target_config.c +++ b/cmake/target/src/target_config.c @@ -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" @@ -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. @@ -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, diff --git a/fsw/cfe-core/src/es/cfe_es_api.c b/fsw/cfe-core/src/es/cfe_es_api.c index b863f1f69..7c39418ec 100644 --- a/fsw/cfe-core/src/es/cfe_es_api.c +++ b/fsw/cfe-core/src/es/cfe_es_api.c @@ -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" @@ -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 */ @@ -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 */ @@ -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 @@ -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(); +} diff --git a/fsw/cfe-core/src/es/cfe_es_apps.h b/fsw/cfe-core/src/es/cfe_es_apps.h index b9a2254c4..19ec02890 100644 --- a/fsw/cfe-core/src/es/cfe_es_apps.h +++ b/fsw/cfe-core/src/es/cfe_es_apps.h @@ -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 */ diff --git a/fsw/cfe-core/src/es/cfe_es_backgroundtask.c b/fsw/cfe-core/src/es/cfe_es_backgroundtask.c index 5582fa8da..5b874679e 100644 --- a/fsw/cfe-core/src/es/cfe_es_backgroundtask.c +++ b/fsw/cfe-core/src/es/cfe_es_backgroundtask.c @@ -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 } }; diff --git a/fsw/cfe-core/src/es/cfe_es_erlog.c b/fsw/cfe-core/src/es/cfe_es_erlog.c index 51ca03105..d4bf207d5 100644 --- a/fsw/cfe-core/src/es/cfe_es_erlog.c +++ b/fsw/cfe-core/src/es/cfe_es_erlog.c @@ -43,36 +43,49 @@ #include "cfe_es_apps.h" #include "cfe_es_global.h" #include "cfe_es_log.h" +#include "cfe_es_task.h" #include "cfe_psp.h" #include #include #include +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Confirm the size of the error log context buffer is at least what the user asked for. - * - * This is to catch errors such as if the CFE_PLATFORM_ES_ER_LOG_MAX_CONTEXT_SIZE was set to a value - * that is _not_ a multiple of sizeof(uint32) -- in this case the final size of the context - * buffer would end up being less than what the macro was set to. - */ -CompileTimeAssert(sizeof(CFE_ES_ResetDataPtr->ERLog[0].Context) == CFE_PLATFORM_ES_ER_LOG_MAX_CONTEXT_SIZE, CfeEsErLogContextSizeError); - - -/* -** Function: CFE_ES_WriteToERLog +** Function: CFE_ES_WriteToERLogWithContext ** ** Purpose: Create an entry in the ES Exception and Reset Log. +** This log API accepts extra context information (AppID and ContextID) +** and is used when the app/task invoking this API is not the same app +** as where the event occurred. ** */ -int32 CFE_ES_WriteToERLog( uint32 EntryType, uint32 ResetType, uint32 ResetSubtype, - const char *Description, const uint32 *Context, uint32 ContextSize ) +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +int32 CFE_ES_WriteToERLogWithContext( CFE_ES_LogEntryType_Enum_t EntryType, uint32 ResetType, uint32 ResetSubtype, + const char *Description, uint32 AppId, uint32 PspContextId) { uint32 LogIdx; + CFE_ES_ERLog_MetaData_t *EntryPtr; + CFE_TIME_SysTime_t PendingTime; /* - ** Code - */ + * Snapshot the time before locking (different subsystem) + */ + PendingTime = CFE_TIME_GetTime(); + + /* + * Ensure that description string is not NULL. + */ + if ( Description == NULL) + { + Description = "No Description String Given."; + } + + /* + * This routine needs to lock in case it is called + * from concurrent threads + */ + CFE_ES_LockSharedData(__func__,__LINE__); /* ** Try to clean up an invalid ER log index variable. @@ -96,89 +109,342 @@ int32 CFE_ES_WriteToERLog( uint32 EntryType, uint32 ResetType, uint32 ResetSu /* ** Clear out the log entry we are about to use. */ - memset( &(CFE_ES_ResetDataPtr->ERLog[LogIdx]), 0, - sizeof (CFE_ES_ERLog_t)); + EntryPtr = &CFE_ES_ResetDataPtr->ERLog[LogIdx]; + memset(EntryPtr, 0, sizeof (*EntryPtr)); /* ** Fill out the log fields */ - CFE_ES_ResetDataPtr->ERLog[LogIdx].LogEntryType = EntryType; - CFE_ES_ResetDataPtr->ERLog[LogIdx].ResetType = ResetType; - CFE_ES_ResetDataPtr->ERLog[LogIdx].ResetSubtype = ResetSubtype; - CFE_ES_ResetDataPtr->ERLog[LogIdx].BootSource = CFE_ES_ResetDataPtr->ResetVars.BootSource; - CFE_ES_ResetDataPtr->ERLog[LogIdx].ProcessorResetCount = + EntryPtr->BaseInfo.LogEntryType = EntryType; + EntryPtr->BaseInfo.ResetType = ResetType; + EntryPtr->BaseInfo.ResetSubtype = ResetSubtype; + EntryPtr->BaseInfo.BootSource = CFE_ES_ResetDataPtr->ResetVars.BootSource; + EntryPtr->BaseInfo.ProcessorResetCount = CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount; - CFE_ES_ResetDataPtr->ERLog[LogIdx].MaxProcessorResetCount = + EntryPtr->BaseInfo.MaxProcessorResetCount = CFE_ES_ResetDataPtr->ResetVars.MaxProcessorResetCount; /* ** Copy the ES Reset variables to the log (before they are modified by the log entry). */ - memcpy(&(CFE_ES_ResetDataPtr->ERLog[LogIdx].DebugVars), - (void *)&(CFE_ES_Global.DebugVars), - sizeof(CFE_ES_DebugVariables_t )); + memcpy(&EntryPtr->BaseInfo.DebugVars, &CFE_ES_Global.DebugVars, + sizeof(EntryPtr->BaseInfo.DebugVars)); /* - ** Time Stamp the log entry with the system time + ** Time Stamp the log entry with the system time */ - CFE_ES_ResetDataPtr->ERLog[LogIdx].TimeCode = CFE_TIME_GetTime(); + EntryPtr->BaseInfo.TimeCode = PendingTime; /* ** Copy the Description string to the log. */ - if ( Description == NULL) - { - strncpy(CFE_ES_ResetDataPtr->ERLog[LogIdx].Description, "No Description String Given.", 80); - } - else - { - strncpy(CFE_ES_ResetDataPtr->ERLog[LogIdx].Description, Description, 80); - } + strncpy(EntryPtr->BaseInfo.Description, Description, sizeof(EntryPtr->BaseInfo.Description)); /* - ** In the case of an exception, copy the processor context data to the log. - */ - if (Context != NULL && ContextSize > 0) - { - /* - ** Copy the processor context data (i.e. register dump). Make sure that - ** the passed-in context_size is not greater than the declared size in - ** the ER Log log entry. - */ - if ( ContextSize <= CFE_PLATFORM_ES_ER_LOG_MAX_CONTEXT_SIZE ) - { - memcpy ( (CFE_ES_ResetDataPtr->ERLog[LogIdx].Context), - (void *)Context, - ContextSize); - } - else - { - memcpy ( (CFE_ES_ResetDataPtr->ERLog[LogIdx].Context), - (void *)Context, - CFE_PLATFORM_ES_ER_LOG_MAX_CONTEXT_SIZE); - } - /* - ** Indicate that context is valid. - ** Using the original context size (not the truncated size) so it will be - ** evident if the context information was truncated. - */ - CFE_ES_ResetDataPtr->ERLog[LogIdx].ContextSize = ContextSize; - } - else - { - /* - ** Context is not valid - */ - CFE_ES_ResetDataPtr->ERLog[LogIdx].ContextSize = 0; - } /* end if */ + * Store the context info (if any) + */ + EntryPtr->AppID = AppId; + EntryPtr->PspContextId = PspContextId; /* ** Increment the number of ER log entries made */ CFE_ES_ResetDataPtr->ERLogEntries++; + /* + * Shared data update is complete + */ + CFE_ES_UnlockSharedData(__func__,__LINE__); + return(CFE_SUCCESS); + +} /* End of CFE_ES_WriteToERLogWithContext() */ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* +** Function: CFE_ES_WriteToERLog +** +** Purpose: Create an entry in the ES Exception and Reset Log. +** This log API is simplified for cases which do not have a separate context +** +*/ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +int32 CFE_ES_WriteToERLog( CFE_ES_LogEntryType_Enum_t EntryType, uint32 ResetType, uint32 ResetSubtype, + const char *Description) +{ + /* passing 0xFFFFFFFF as the appid avoids confusion with actual appid 0 */ + return CFE_ES_WriteToERLogWithContext(EntryType, ResetType, ResetSubtype, + Description, 0xFFFFFFFF, CFE_ES_ERLOG_NO_CONTEXT); } /* End of CFE_ES_WriteToERLog() */ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* Function: CFE_ES_RunERLogDump() */ +/* */ +/* Purpose: */ +/* Write exception & reset log to a file. */ +/* */ +/* Implemented as an ES background job, but the entire file write is done */ +/* in a single invocation, as the file is expected to be relatively small. */ +/* */ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +bool CFE_ES_RunERLogDump(uint32 ElapsedTime, void *Arg) +{ + CFE_ES_BackgroundLogDumpGlobal_t *State = (CFE_ES_BackgroundLogDumpGlobal_t *)Arg; + int32 WriteStat; + int32 PspStatus; + CFE_FS_Header_t FileHdr; + CFE_ES_ERLog_FileEntry_t FileEntry; + CFE_ES_ERLog_MetaData_t *EntryPtr; + uint32 FileSize; + uint32 i; + int32 fd; + + + if (!State->IsPending) + { + return false; + } + + FileSize = 0; + fd = OS_creat(State->DataFileName, OS_WRITE_ONLY); + if(fd < 0) + { + CFE_EVS_SendEvent(CFE_ES_ERLOG2_ERR_EID,CFE_EVS_EventType_ERROR, + "Error creating file %s, RC = 0x%08X", + State->DataFileName, (unsigned int)fd); + } + else + { + CFE_FS_InitHeader(&FileHdr, CFE_ES_ER_LOG_DESC, CFE_FS_SubType_ES_ERLOG); + + /* write the cFE header to the file */ + WriteStat = CFE_FS_WriteHeader(fd, &FileHdr); + if(WriteStat != sizeof(CFE_FS_Header_t)) + { + CFE_ES_FileWriteByteCntErr(State->DataFileName,sizeof(CFE_FS_Header_t),WriteStat); + } + else + { + FileSize += WriteStat; + + /* write a single ER log entry on each pass */ + for(i=0;iERLog[i]; + + /* The basic info comes directly from the ES log */ + FileEntry.BaseInfo = EntryPtr->BaseInfo; + + /* + * The context info, if available, comes from the PSP. + * This returns the actual size of the context info, or <0 on error. + */ + PspStatus = CFE_PSP_Exception_CopyContext(EntryPtr->PspContextId, &FileEntry.Context, sizeof(FileEntry.Context)); + if (PspStatus > 0) + { + FileEntry.ContextSize = PspStatus; + } + else + { + /* + * errors here are OK - just means there is no context available. + * Record a size of 0 in the log file. + */ + FileEntry.ContextSize = 0; + } + + /* + * any unused context space should be cleared. + * + * This is for binary compatibility with historical log files, where a fixed amount + * of space is given per-entry, regardless of the actual size. + */ + if (FileEntry.ContextSize < sizeof(FileEntry.Context)) + { + memset(&FileEntry.Context[FileEntry.ContextSize], 0, + sizeof(FileEntry.Context) - FileEntry.ContextSize); + } + + /* + * Now write to file + */ + WriteStat = OS_write(fd,&FileEntry,sizeof(FileEntry)); + + if(WriteStat != sizeof(FileEntry)) + { + CFE_ES_FileWriteByteCntErr(State->DataFileName,sizeof(FileEntry),WriteStat); + break; + }/* end if */ + + FileSize += WriteStat; + + } /* end for */ + + } /* end if */ + + OS_close(fd); + + CFE_EVS_SendEvent(CFE_ES_ERLOG2_EID, CFE_EVS_EventType_DEBUG, + "%s written:Size=%lu",State->DataFileName,(unsigned long)FileSize); + + } /* end if */ + + /* + * Always clear the "pending" flag whether successful or not. + * If unsuccessful, an operator needs to investigate the error and re-issue command. + */ + State->IsPending = false; + + return false; +}/* end CFE_ES_RunERLogDump */ + + +/* +**--------------------------------------------------------------------------------------- +** Name: CFE_ES_RunExceptionScan +** +** Purpose: This function pools the PSP to check if any exceptions have been logged +** since the last background cycle. If an exception is present, retreive +** the details, add it to the ER log, and trigger the action (e.g. app restart). +**--------------------------------------------------------------------------------------- +*/ +bool CFE_ES_RunExceptionScan(uint32 ElapsedTime, void *Arg) +{ + int32 Status; + uint32 PspContextId; + char ReasonString[CFE_ES_ERLOG_DESCRIPTION_MAX_LENGTH]; + CFE_ES_TaskInfo_t EsTaskInfo; + uint32 ExceptionTaskID; + uint32 ResetType; + CFE_ES_LogEntryType_Enum_t LogType; + + if (CFE_PSP_Exception_GetCount() == 0) + { + /* no exceptions pending, nothing to do */ + return false; + } + + /* + * Note a reset type of 0 is not defined by the PSP - + * the real values are all nonzero + */ + ResetType = 0; + memset(&EsTaskInfo, 0, sizeof(EsTaskInfo)); + Status = CFE_PSP_Exception_GetSummary(&PspContextId, &ExceptionTaskID, ReasonString, sizeof(ReasonString)); + if (Status != CFE_PSP_SUCCESS) + { + /* reason string is not available - populate with something for the log */ + snprintf(ReasonString, sizeof(ReasonString), "Unknown - CFE_PSP_ExceptionGetSummary() error %ld", (long)Status); + PspContextId = 0; + ExceptionTaskID = 0; + } /* end if */ + + /* + * Note that writes to the ES ER log actually do not get propagated to the debug console. + * so by writing to SysLog here it becomes visible in both places. + */ + CFE_ES_WriteToSysLog("ExceptionID 0x%lx in TaskID %lu: %s\n", + (unsigned long)PspContextId, (unsigned long)ExceptionTaskID, ReasonString); + + /* + * If task ID is 0, this means it was a system level exception and + * not associated with a specific task. + * + * Otherwise, if it was related to a task, determine the associated AppID + * so the exception action can be checked. + */ + if (ExceptionTaskID != 0) + { + 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 && + CFE_ES_Global.AppTable[EsTaskInfo.AppId].StartParams.ExceptionAction == CFE_ES_ExceptionAction_RESTART_APP) + { + /* + * Log the Application reset + */ + ResetType = CFE_ES_APP_RESTART; + } + } + + do + { + /* + * If no disposition is identified yet, then trigger a PSP reset. + * Need to determine if a processor or poweron reset is needed. + */ + if (ResetType == 0) + { + if ( CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount >= + CFE_ES_ResetDataPtr->ResetVars.MaxProcessorResetCount ) + { + CFE_ES_WriteToSysLog("Maximum Processor Reset count reached (%u)", + (unsigned int)CFE_ES_ResetDataPtr->ResetVars.MaxProcessorResetCount); + + ResetType = CFE_PSP_RST_TYPE_POWERON; + } + else + { + CFE_ES_WriteToSysLog("Processor Reset count not reached (%u/%u)", + (unsigned int)CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount, + (unsigned int)CFE_ES_ResetDataPtr->ResetVars.MaxProcessorResetCount); + + + /* + ** Update the reset variables + */ + CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount++; + CFE_ES_ResetDataPtr->ResetVars.ES_CausedReset = true; + + ResetType = CFE_PSP_RST_TYPE_PROCESSOR; + } + } + + if (ResetType == CFE_ES_APP_RESTART) + { + LogType = CFE_ES_LogEntryType_APPLICATION; + } + else + { + LogType = CFE_ES_LogEntryType_CORE; + } + + + CFE_ES_WriteToERLogWithContext(LogType, ResetType, + CFE_PSP_RST_SUBTYPE_EXCEPTION, ReasonString, + EsTaskInfo.AppId, + PspContextId); + + if (ResetType == CFE_ES_APP_RESTART) + { + /* + * Restart the App. This call is just a request + * to ES, but the request could fail. If that happens, + * proceed to a processor reset. + */ + Status = CFE_ES_RestartApp(EsTaskInfo.AppId); + if (Status != CFE_SUCCESS) + { + ResetType = 0; + snprintf(ReasonString, sizeof(ReasonString), "App Restart Failed"); + } + } + else + { + /* normally this will not return */ + CFE_PSP_Restart(ResetType); + } + } + while(ResetType == 0); + + + return true; /* returning true because there was an exception to deal with */ +} + + + /* end of file */ diff --git a/fsw/cfe-core/src/es/cfe_es_log.h b/fsw/cfe-core/src/es/cfe_es_log.h index c595be3e7..f02bc902a 100644 --- a/fsw/cfe-core/src/es/cfe_es_log.h +++ b/fsw/cfe-core/src/es/cfe_es_log.h @@ -108,6 +108,14 @@ } +/** + * \brief Indicates no context information Error Logs + * + * For use with the CFE_ES_WriteToERLog() function when no context + * information is available. + */ +#define CFE_ES_ERLOG_NO_CONTEXT (0) + /* ** Type Definitions */ @@ -328,8 +336,35 @@ void CFE_ES_PerfLogDump(void); /* ** Exception and Reset Log API */ -int32 CFE_ES_WriteToERLog( uint32 EntryType, uint32 ResetType, uint32 ResetSubtype, - const char *Description, const uint32 *Context, uint32 ContextSize ); -int32 CFE_ES_ERLogDump(const char *Filename); + +/** + * \brief Create an entry in the ES Exception and Reset Log. + * + * The exception and reset log is used to track significant system-level events and anomalies + * for later analysis. + * + * \param EntryType Whether the event is relevant to the CORE or an APPLICATION (#CFE_ES_LogEntryType_Enum_t) + * \param ResetType The type of the last reset + * \param ResetSubType The subtype of the last reset + * \param Description A summary of the event + * + * \return CFE_SUCCESS if successful, or an appropriate error code from cfe_error.h + */ +int32 CFE_ES_WriteToERLog( CFE_ES_LogEntryType_Enum_t EntryType, uint32 ResetType, uint32 ResetSubtype, + const char *Description); + + +/** + * \copydoc CFE_ES_WriteToERLog() + * + * This log API accepts extra context information (AppID and ContextID) + * and is used when the app/task invoking this API is not the same app + * as where the event occurred. + * + * \param AppId The Application ID associated with the task that caused the exception + * \param PspContextId Identifier of extended context info stored in the PSP (if available) + */ +int32 CFE_ES_WriteToERLogWithContext( CFE_ES_LogEntryType_Enum_t EntryType, uint32 ResetType, uint32 ResetSubtype, + const char *Description, uint32 AppId, uint32 PspContextId); #endif /* _cfe_es_log_ */ diff --git a/fsw/cfe-core/src/es/cfe_es_start.c b/fsw/cfe-core/src/es/cfe_es_start.c index e1ccc24a9..5d73fc64c 100644 --- a/fsw/cfe-core/src/es/cfe_es_start.c +++ b/fsw/cfe-core/src/es/cfe_es_start.c @@ -91,20 +91,6 @@ void CFE_ES_Main(uint32 StartType, uint32 StartSubtype, uint32 ModeId, const cha */ CFE_ES_Global.SystemState = CFE_ES_SystemState_EARLY_INIT; - /* - ** Initialize the Reset variables. This call is required - ** Before most of the ES functions can be used including the - ** ES System log. - */ - CFE_ES_SetupResetVariables(StartType, StartSubtype, ModeId); - - /* - ** Initialize the Logic Perf variables - ** Because this is in the ES Reset area, it must be called after - ** CFE_ES_SetupResetVariables. - */ - CFE_ES_SetupPerfVariables(StartType); - /* ** Create the ES Shared Data Mutex ** This must be done before ANY calls to CFE_ES_WriteToSysLog(), since this uses the mutex @@ -131,6 +117,20 @@ void CFE_ES_Main(uint32 StartType, uint32 StartSubtype, uint32 ModeId, const cha return; } /* end if */ + /* + ** Initialize the Reset variables. This call is required + ** Before most of the ES functions can be used including the + ** ES System log. + */ + CFE_ES_SetupResetVariables(StartType, StartSubtype, ModeId); + + /* + ** Initialize the Logic Perf variables + ** Because this is in the ES Reset area, it must be called after + ** CFE_ES_SetupResetVariables. + */ + CFE_ES_SetupPerfVariables(StartType); + /* ** Also Create the ES Performance Data Mutex ** This is to separately protect against concurrent writes to the global performance log data @@ -366,19 +366,19 @@ void CFE_ES_SetupResetVariables(uint32 StartType, uint32 StartSubtype, uint32 Bo { CFE_ES_SysLogWrite_Unsync("POWER ON RESET due to Power Cycle (Power Cycle).\n"); CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_POWERON, StartSubtype, - "POWER ON RESET due to Power Cycle (Power Cycle)", NULL,0 ); + "POWER ON RESET due to Power Cycle (Power Cycle)"); } else if ( StartSubtype == CFE_PSP_RST_SUBTYPE_HW_SPECIAL_COMMAND ) { CFE_ES_SysLogWrite_Unsync("POWER ON RESET due to HW Special Cmd (Hw Spec Cmd).\n"); CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_POWERON, StartSubtype, - "POWER ON RESET due to HW Special Cmd (Hw Spec Cmd)", NULL,0 ); + "POWER ON RESET due to HW Special Cmd (Hw Spec Cmd)"); } else { CFE_ES_SysLogWrite_Unsync("POWER ON RESET due to other cause (See Subtype).\n"); CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_POWERON, StartSubtype, - "POWER ON RESET due to other cause (See Subtype)", NULL,0 ); + "POWER ON RESET due to other cause (See Subtype)"); } /* @@ -418,7 +418,7 @@ void CFE_ES_SetupResetVariables(uint32 StartType, uint32 StartSubtype, uint32 Bo ** the entry just in case something fails. */ CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_POWERON, StartSubtype, - "POWER ON RESET due to max proc resets (HW Spec Cmd).", NULL,0 ); + "POWER ON RESET due to max proc resets (HW Spec Cmd)."); } else { @@ -430,7 +430,7 @@ void CFE_ES_SetupResetVariables(uint32 StartType, uint32 StartSubtype, uint32 Bo ** the entry just in case something fails. */ CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_POWERON, StartSubtype, - "POWER ON RESET due to max proc resets (Watchdog).", NULL,0 ); + "POWER ON RESET due to max proc resets (Watchdog)."); } /* ** Call the BSP reset routine @@ -454,7 +454,7 @@ void CFE_ES_SetupResetVariables(uint32 StartType, uint32 StartSubtype, uint32 Bo ** Log the watchdog reset */ CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_PROCESSOR, StartSubtype, - "PROCESSOR RESET due to Hardware Special Command (Hw Spec Cmd).", NULL,0 ); + "PROCESSOR RESET due to Hardware Special Command (Hw Spec Cmd)."); } else @@ -466,7 +466,7 @@ void CFE_ES_SetupResetVariables(uint32 StartType, uint32 StartSubtype, uint32 Bo ** Log the watchdog reset */ CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_PROCESSOR, StartSubtype, - "PROCESSOR RESET due to Watchdog (Watchdog).", NULL,0 ); + "PROCESSOR RESET due to Watchdog (Watchdog)."); } diff --git a/fsw/cfe-core/src/es/cfe_es_task.c b/fsw/cfe-core/src/es/cfe_es_task.c index 2f750536e..303ccfb2c 100644 --- a/fsw/cfe-core/src/es/cfe_es_task.c +++ b/fsw/cfe-core/src/es/cfe_es_task.c @@ -1589,94 +1589,30 @@ int32 CFE_ES_ClearERLogCmd(const CFE_ES_ClearERLog_t *data) int32 CFE_ES_WriteERLogCmd(const CFE_ES_WriteERLog_t *data) { const CFE_ES_FileNameCmd_Payload_t *CmdPtr = &data->Payload; - int32 Stat; - char LogFilename[OS_MAX_PATH_LEN]; - CFE_SB_MessageStringGet(LogFilename, (char *)CmdPtr->FileName, - CFE_PLATFORM_ES_DEFAULT_ER_LOG_FILE, OS_MAX_PATH_LEN, sizeof(CmdPtr->FileName)); - - Stat = CFE_ES_ERLogDump(LogFilename); - - if(Stat == CFE_SUCCESS) + if (CFE_ES_TaskData.BackgroundERLogDumpState.IsPending) { - CFE_ES_TaskData.CommandCounter++; + CFE_EVS_SendEvent(CFE_ES_ERLOG_PENDING_ERR_EID,CFE_EVS_EventType_ERROR, + "Error log write to file %s already in progress", + CFE_ES_TaskData.BackgroundERLogDumpState.DataFileName); + + /* background dump already running, consider this an error */ + CFE_ES_TaskData.CommandErrorCounter++; } else { - CFE_ES_TaskData.CommandErrorCounter++; - }/* end if */ - - return CFE_SUCCESS; -}/* end CFE_ES_WriteERLogCmd */ - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* */ -/* CFE_ES_ERLogDump() -- Write exception & reset log to a file. */ -/* */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -int32 CFE_ES_ERLogDump(const char *Filename) -{ - - int32 fd; - int32 WriteStat,BspStat; - uint32 FileSize,i,ResetAreaSize; - CFE_FS_Header_t FileHdr; - cpuaddr ResetDataAddr; - - fd = OS_creat(Filename, OS_WRITE_ONLY); - if(fd < 0) - { - CFE_EVS_SendEvent(CFE_ES_ERLOG2_ERR_EID,CFE_EVS_EventType_ERROR, - "Error creating file %s, RC = 0x%08X", - Filename,(unsigned int)fd); - return CFE_ES_FILE_IO_ERR; - }/* end if */ - - CFE_FS_InitHeader(&FileHdr, CFE_ES_ER_LOG_DESC, CFE_FS_SubType_ES_ERLOG); - - /* write the cFE header to the file */ - WriteStat = CFE_FS_WriteHeader(fd, &FileHdr); - if(WriteStat != sizeof(CFE_FS_Header_t)) - { - CFE_ES_FileWriteByteCntErr(Filename,sizeof(CFE_FS_Header_t),WriteStat); - OS_close(fd); - return CFE_ES_FILE_IO_ERR; - }/* end if */ - FileSize = WriteStat; + CFE_SB_MessageStringGet(CFE_ES_TaskData.BackgroundERLogDumpState.DataFileName, (char *)CmdPtr->FileName, + CFE_PLATFORM_ES_DEFAULT_ER_LOG_FILE, + sizeof(CFE_ES_TaskData.BackgroundERLogDumpState.DataFileName), sizeof(CmdPtr->FileName)); - /* Get the pointer to the Reset Log from the BSP */ - BspStat = CFE_PSP_GetResetArea (&ResetDataAddr, &ResetAreaSize); - if(BspStat != CFE_PSP_SUCCESS) - { - CFE_EVS_SendEvent(CFE_ES_RST_ACCESS_EID, CFE_EVS_EventType_ERROR, - "Error accessing ER Log,%s not written. RC = 0x%08X",Filename,(unsigned int)BspStat); - OS_close(fd); - return CFE_ES_RST_ACCESS_ERR; - }/* end if */ - - /* write a single ER log entry on each pass */ - for(i=0;i UINT32_MAX - #error CFE_PLATFORM_ES_RESET_AREA_SIZE cannot be greater than UINT32_MAX (4 Gigabytes)! -#endif - /* ** The size of a command to the OS that lies under the cFE */ diff --git a/fsw/cfe-core/src/inc/cfe_es.h b/fsw/cfe-core/src/inc/cfe_es.h index 4f81babbd..b52d0cbe9 100644 --- a/fsw/cfe-core/src/inc/cfe_es.h +++ b/fsw/cfe-core/src/inc/cfe_es.h @@ -979,22 +979,21 @@ uint32 CFE_ES_CalculateCRC(const void *DataPtr, uint32 DataLength, uint32 InputC /*****************************************************************************/ /** ** \ingroup CFEAPIESMisc -** \brief Process an exception detected by the underlying OS/PSP +** \brief Notification that an asynchronous event was detected by the underlying OS/PSP ** ** \par Description -** This hook routine is called from the PSP when an exception occurs +** This hook routine is called from the PSP when an exception or +** other asynchronous system event occurs ** ** \par Assumptions, External Events, and Notes: -** None. +** The PSP must guarantee that this function is only invoked from a +** context which may use OSAL primitives. In general this means that +** it shouldn't be _directly_ invoked from an ISR/signal context. ** -** \param[in] HostTaskId The OS (not OSAL) task ID -** \param[in] ReasonString Identifier from PSP -** \param[in] ContextPointer Context data from PSP -** \param[in] ContextSize Size of context data from PSP ** ******************************************************************************/ -void CFE_ES_ProcessCoreException(uint32 HostTaskId, const char *ReasonString, - const uint32 *ContextPointer, uint32 ContextSize); +void CFE_ES_ProcessAsyncEvent(void); + /**@}*/ /** @defgroup CFEAPIESCritData cFE Critical Data Store APIs diff --git a/fsw/cfe-core/src/inc/cfe_es_events.h b/fsw/cfe-core/src/inc/cfe_es_events.h index 78464a871..03da2eb37 100644 --- a/fsw/cfe-core/src/inc/cfe_es_events.h +++ b/fsw/cfe-core/src/inc/cfe_es_events.h @@ -1214,21 +1214,6 @@ **/ #define CFE_ES_FILEWRITE_ERR_EID 74 -/** \brief 'Error accessing ER Log,\%s not written.Stat=0x\%08x' -** \event 'Error accessing ER Log,\%s not written.Stat=0x\%08x' -** -** \par Type: ERROR -** -** \par Cause: -** -** This event message is generated in response to an Exception Reset Log Dump command and there is -** an error obtaining the contents of the ER Log. -** -** The \c 's' field identifies the filename of the file to which the data failed to write, -** the \c Stat field specifies, in hex, the error status returned from #CFE_PSP_GetResetArea. -**/ -#define CFE_ES_RST_ACCESS_EID 75 - /** \brief 'Error while deleting '\%s' from CDS, See SysLog.(Err=0x\%08X)' ** \event 'Error while deleting '\%s' from CDS, See SysLog.(Err=0x\%08X)' ** @@ -1518,6 +1503,19 @@ #define CFE_ES_BUILD_INF_EID 92 +/** \brief 'Error log write to file \%s already in progress' +** \event 'Error log write to file \%s already in progress' +** +** \par Type: ERROR +** +** \par Cause: +** +** This event message is generated when an Executive Services \link #CFE_ES_WRITE_ER_LOG_CC Dump Exception Reset Log +** Command \endlink is received before a previously-issued command has finished executing +** +**/ +#define CFE_ES_ERLOG_PENDING_ERR_EID 93 + #endif /* _cfe_es_events_ */ diff --git a/fsw/cfe-core/src/inc/cfe_evs_msg.h b/fsw/cfe-core/src/inc/cfe_evs_msg.h index 477b6caa8..a6fe29872 100644 --- a/fsw/cfe-core/src/inc/cfe_evs_msg.h +++ b/fsw/cfe-core/src/inc/cfe_evs_msg.h @@ -37,6 +37,7 @@ /********************************** Include Files ************************************/ #include "common_types.h" /* Basic data types */ +#include "cfe_evs_extern_typedefs.h" /* for EVS-specific types such as CFE_EVS_LogMode_Enum_t */ #include "cfe_time.h" /* Time library function definitions */ #include "cfe_sb.h" #include "cfe_es.h" diff --git a/fsw/cfe-core/src/inc/private/cfe_es_erlog_typedef.h b/fsw/cfe-core/src/inc/private/cfe_es_erlog_typedef.h index d10f9c8ec..b93fba5d4 100644 --- a/fsw/cfe-core/src/inc/private/cfe_es_erlog_typedef.h +++ b/fsw/cfe-core/src/inc/private/cfe_es_erlog_typedef.h @@ -34,6 +34,8 @@ #include #include /* Needed for CFE_TIME_SysTime_t */ +#define CFE_ES_ERLOG_DESCRIPTION_MAX_LENGTH 80 + /* ** Debug variables type */ @@ -47,7 +49,9 @@ typedef struct } CFE_ES_DebugVariables_t; /* -** Exception and Reset Log Structure +** Exception and Reset Log Base Structure +** +** This is the common data structure that is stored in RAM and log files */ typedef struct { @@ -59,11 +63,42 @@ typedef struct uint32 MaxProcessorResetCount; /* The maximum number before a Power On */ CFE_ES_DebugVariables_t DebugVars; /* ES Debug variables */ CFE_TIME_SysTime_t TimeCode; /* Time code */ - char Description[80]; /* The ascii data for the event */ - uint32 ContextSize; /* Indicates the context data is valid */ - uint32 AppID; /* The application ID */ - uint32 Context[CFE_PLATFORM_ES_ER_LOG_MAX_CONTEXT_SIZE / sizeof(uint32)]; /* cpu context */ -} CFE_ES_ERLog_t; + char Description[CFE_ES_ERLOG_DESCRIPTION_MAX_LENGTH]; /* The ascii data for the event */ +} CFE_ES_ERLog_BaseInfo_t; + + +/* +** Exception and Reset Log File Structure +** +** This is the "export" data structure that gets written to a log file +** It is intended to be binary-compatible with the historical definition of this +** structure, to work with existing tools that may read log files. +** +** Note that "AppID" really belongs in the base info, but it is kept here +** for backward compatibility. +*/ +typedef struct +{ + CFE_ES_ERLog_BaseInfo_t BaseInfo; /* basic info about the event */ + uint32 ContextSize; /* Indicates the context data is valid */ + uint32 AppID; /* The application ID */ + uint8 Context[CFE_PLATFORM_ES_ER_LOG_MAX_CONTEXT_SIZE]; /* cpu context */ +} CFE_ES_ERLog_FileEntry_t; + + +/* +** Exception and Reset Log Metadata Structure +** This is stored in ES RAM, not _directly_ written to ER log files. +*/ +typedef struct +{ + CFE_ES_ERLog_BaseInfo_t BaseInfo; /**< Core Log Data */ + uint32 AppID; /* The application ID */ + uint32 PspContextId; /**< Reference to context information stored in PSP */ +} CFE_ES_ERLog_MetaData_t; + + + diff --git a/fsw/cfe-core/src/inc/private/cfe_es_resetdata_typedef.h b/fsw/cfe-core/src/inc/private/cfe_es_resetdata_typedef.h index 872dcf3bb..aec73b459 100644 --- a/fsw/cfe-core/src/inc/private/cfe_es_resetdata_typedef.h +++ b/fsw/cfe-core/src/inc/private/cfe_es_resetdata_typedef.h @@ -63,7 +63,7 @@ typedef struct /* ** Exception and Reset log declaration */ - CFE_ES_ERLog_t ERLog[CFE_PLATFORM_ES_ER_LOG_ENTRIES]; + CFE_ES_ERLog_MetaData_t ERLog[CFE_PLATFORM_ES_ER_LOG_ENTRIES]; uint32 ERLogIndex; uint32 ERLogEntries; uint32 LastAppId; diff --git a/fsw/cfe-core/unit-test/es_UT.c b/fsw/cfe-core/unit-test/es_UT.c index e0a7a7ab3..125415600 100644 --- a/fsw/cfe-core/unit-test/es_UT.c +++ b/fsw/cfe-core/unit-test/es_UT.c @@ -2186,8 +2186,6 @@ void TestApps(void) void TestERLog(void) { int Return; - uint32 Context = 4; - char Context2[1000]; #ifdef UT_VERBOSE UT_Text("Begin Test Exception and Reset Log\n"); @@ -2199,65 +2197,18 @@ void TestERLog(void) */ ES_ResetUnitTest(); CFE_ES_ResetDataPtr->ERLogIndex = CFE_PLATFORM_ES_ER_LOG_ENTRIES + 1; - CFE_ES_ResetDataPtr->ERLog[0].ContextSize = 0; Return = CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_POWERON, 1, - NULL, - &Context, - sizeof(int)); + NULL); UT_Report(__FILE__, __LINE__, Return == CFE_SUCCESS && - !strcmp(CFE_ES_ResetDataPtr->ERLog[0].Description, + !strcmp(CFE_ES_ResetDataPtr->ERLog[0].BaseInfo.Description, "No Description String Given.") && - CFE_ES_ResetDataPtr->ERLogIndex == 1 && - CFE_ES_ResetDataPtr->ERLog[0].ContextSize == sizeof(int), + CFE_ES_ResetDataPtr->ERLogIndex == 1, "CFE_ES_WriteToERLog", "Log entries exceeded; no description; valid context size"); - /* Test initial rolling over log entry, - * null description, - * and non-null context with zero size - */ - ES_ResetUnitTest(); - CFE_ES_ResetDataPtr->ERLogIndex = 0; - CFE_ES_ResetDataPtr->ERLog[0].ContextSize = 0; - Return = CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, - CFE_PSP_RST_TYPE_POWERON, - 1, - NULL, - &Context, - 0); - UT_Report(__FILE__, __LINE__, - Return == CFE_SUCCESS && - CFE_ES_ResetDataPtr->ERLogIndex == 1 && - CFE_ES_ResetDataPtr->ERLog[0].ContextSize == 0, - "CFE_ES_WriteToERLog", - "Log entries exceeded; no description; invalid context size"); - - /* Test rolling over log entry at end, - * non-null description, - * and non-null context with large size - */ - ES_ResetUnitTest(); - CFE_ES_ResetDataPtr->ERLogIndex = CFE_PLATFORM_ES_ER_LOG_ENTRIES - 1; - CFE_ES_ResetDataPtr->ERLog[CFE_PLATFORM_ES_ER_LOG_ENTRIES - 1].ContextSize = 0; - Return = CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, - CFE_PSP_RST_TYPE_POWERON, - 1, - "LogDescription", - (uint32 *) &Context2, - 9999999); - UT_Report(__FILE__, __LINE__, - Return == CFE_SUCCESS && - !strcmp(CFE_ES_ResetDataPtr->ERLog[ - CFE_PLATFORM_ES_ER_LOG_ENTRIES - 1].Description, - "LogDescription") && - CFE_ES_ResetDataPtr->ERLogIndex == 0 && - CFE_ES_ResetDataPtr->ERLog[ - CFE_PLATFORM_ES_ER_LOG_ENTRIES - 1].ContextSize == 9999999, - "CFE_ES_WriteToERLog", - "Log entries at maximum; description; oversized context"); /* Test non-rolling over log entry, * null description, @@ -2265,17 +2216,13 @@ void TestERLog(void) */ ES_ResetUnitTest(); CFE_ES_ResetDataPtr->ERLogIndex = 0; - CFE_ES_ResetDataPtr->ERLog[0].ContextSize = 0; Return = CFE_ES_WriteToERLog(CFE_ES_LogEntryType_CORE, CFE_PSP_RST_TYPE_POWERON, 1, - NULL, - NULL, - 1); + NULL); UT_Report(__FILE__, __LINE__, Return == CFE_SUCCESS && - CFE_ES_ResetDataPtr->ERLogIndex == 1 && - CFE_ES_ResetDataPtr->ERLog[0].ContextSize == 0, + CFE_ES_ResetDataPtr->ERLogIndex == 1, "CFE_ES_WriteToERLog", "No log entry rollover; no description; no context"); } @@ -2460,6 +2407,7 @@ void TestTask(void) uint32 Id; uint32 TestObjId; uint32 ResetType; + uint32 UT_ContextBuffer; union { CFE_SB_Msg_t Msg; @@ -3264,64 +3212,157 @@ void TestTask(void) "Clear E&R log"); /* Test successful writing of the E&R log */ + /* In the current implementation, it does not directly write the file, + * this just sets a flag for the background task */ ES_ResetUnitTest(); memset(&CmdBuf, 0, sizeof(CmdBuf)); strncpy(CmdBuf.WriteERlogCmd.Payload.FileName, "filename", sizeof(CmdBuf.WriteERlogCmd.Payload.FileName)); + CFE_ES_TaskData.BackgroundERLogDumpState.IsPending = false; + UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, sizeof(CFE_ES_WriteERLog_t), + UT_TPID_CFE_ES_CMD_WRITE_ER_LOG_CC); + UT_Report(__FILE__, __LINE__, + CFE_ES_TaskData.BackgroundERLogDumpState.IsPending, + "CFE_ES_WriteERLogCmd", + "Write E&R log command; pending"); + UT_Report(__FILE__, __LINE__, + !UT_EventIsInHistory(CFE_ES_ERLOG_PENDING_ERR_EID), + "CFE_ES_WriteERLogCmd", + "Write E&R log command; no events"); + + /* sending the same command a second time should fail with an event + * indicating a file write is already pending. */ UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, sizeof(CFE_ES_WriteERLog_t), UT_TPID_CFE_ES_CMD_WRITE_ER_LOG_CC); UT_Report(__FILE__, __LINE__, - UT_EventIsInHistory(CFE_ES_ERLOG2_EID), + UT_EventIsInHistory(CFE_ES_ERLOG_PENDING_ERR_EID), + "CFE_ES_WriteERLogCmd", + "Write E&R log command; already pending event"); + + /* calling the background job when no write pending should immediately return false, no event */ + ES_ResetUnitTest(); + memset(&CFE_ES_TaskData.BackgroundERLogDumpState, 0, sizeof(CFE_ES_TaskData.BackgroundERLogDumpState)); + UT_Report(__FILE__, __LINE__, + !CFE_ES_RunERLogDump(0, &CFE_ES_TaskData.BackgroundERLogDumpState), + "CFE_ES_RunERLogDump", + "Write E&R log; not pending"); + UT_Report(__FILE__, __LINE__, + !UT_EventIsInHistory(CFE_ES_ERLOG2_EID), + "CFE_ES_WriteERLogCmd", + "Write E&R log command; no file written event"); + + /* nominal condition - still returns false, but generates event */ + ES_ResetUnitTest(); + UT_ContextBuffer = 42; + UT_SetDataBuffer(UT_KEY(CFE_PSP_Exception_CopyContext),&UT_ContextBuffer, sizeof(UT_ContextBuffer), false); + CFE_ES_TaskData.BackgroundERLogDumpState.IsPending = true; + CFE_ES_RunERLogDump(0, &CFE_ES_TaskData.BackgroundERLogDumpState); + UT_Report(__FILE__, __LINE__, + !CFE_ES_TaskData.BackgroundERLogDumpState.IsPending, + "CFE_ES_RunERLogDump", + "Write E&R log; nominal, clear flag"); + UT_Report(__FILE__, __LINE__, + UT_EventIsInHistory(CFE_ES_ERLOG2_EID), "CFE_ES_WriteERLogCmd", - "Write E&R log; success"); + "Write E&R log command; file written event"); /* Test writing the E&R log with an OS create failure */ ES_ResetUnitTest(); - memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_ES_TaskData.BackgroundERLogDumpState.IsPending = true; UT_SetForceFail(UT_KEY(OS_creat), OS_ERROR); - strncpy((char *) CmdBuf.WriteERlogCmd.Payload.FileName, "", - sizeof(CmdBuf.WriteERlogCmd.Payload.FileName)); - UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, sizeof(CFE_ES_WriteERLog_t), - UT_TPID_CFE_ES_CMD_WRITE_ER_LOG_CC); + CFE_ES_RunERLogDump(0, &CFE_ES_TaskData.BackgroundERLogDumpState); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_ERLOG2_ERR_EID), - "CFE_ES_WriteERLogCmd", + "CFE_ES_RunERLogDump", "Write E&R log; OS create"); /* Test writing the E&R log with an OS write failure */ ES_ResetUnitTest(); - memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_ES_TaskData.BackgroundERLogDumpState.IsPending = true; UT_SetForceFail(UT_KEY(OS_write), OS_ERROR); - strncpy((char *) CmdBuf.WriteERlogCmd.Payload.FileName, "n", - sizeof(CmdBuf.WriteERlogCmd.Payload.FileName)); - UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, sizeof(CFE_ES_WriteERLog_t), - UT_TPID_CFE_ES_CMD_WRITE_ER_LOG_CC); + CFE_ES_RunERLogDump(0, &CFE_ES_TaskData.BackgroundERLogDumpState); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_FILEWRITE_ERR_EID), - "CFE_ES_WriteERLogCmd", + "CFE_ES_RunERLogDump", "Write E&R log; OS write"); /* Test writing the E&R log with a write header failure */ ES_ResetUnitTest(); - memset(&CmdBuf, 0, sizeof(CmdBuf)); + CFE_ES_TaskData.BackgroundERLogDumpState.IsPending = true; UT_SetDeferredRetcode(UT_KEY(CFE_FS_WriteHeader), 1, OS_ERROR); - UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, sizeof(CFE_ES_WriteERLog_t), - UT_TPID_CFE_ES_CMD_WRITE_ER_LOG_CC); + CFE_ES_RunERLogDump(0, &CFE_ES_TaskData.BackgroundERLogDumpState); UT_Report(__FILE__, __LINE__, UT_EventIsInHistory(CFE_ES_FILEWRITE_ERR_EID), "CFE_ES_WriteERLogCmd", "Write E&R log; write header"); - /* Test writing the E&R log with a reset area failure */ + /* Test scan for exceptions in the PSP, should invoke a Processor Reset */ ES_ResetUnitTest(); - memset(&CmdBuf, 0, sizeof(CmdBuf)); - UT_SetStatusBSPResetArea(OS_ERROR, 0, CFE_TIME_ToneSignalSelect_PRIMARY); - UT_CallTaskPipe(CFE_ES_TaskPipe, &CmdBuf.Msg, sizeof(CFE_ES_WriteERLog_t), - UT_TPID_CFE_ES_CMD_WRITE_ER_LOG_CC); + UT_SetForceFail(UT_KEY(CFE_PSP_Exception_GetCount), 1); + CFE_ES_RunExceptionScan(0, NULL); UT_Report(__FILE__, __LINE__, - UT_EventIsInHistory(CFE_ES_RST_ACCESS_EID), - "CFE_ES_WriteERLogCmd", - "Write E&R log; reset area"); + UT_GetStubCount(UT_KEY(CFE_PSP_Restart)) == 1, + "CFE_ES_RunExceptionScan", + "Scan for exceptions; processor restart"); + + ES_ResetUnitTest(); + CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount = 0; + CFE_ES_ResetDataPtr->ResetVars.MaxProcessorResetCount = 1; + UT_SetForceFail(UT_KEY(CFE_PSP_Exception_GetCount), 1); + CFE_ES_RunExceptionScan(0, NULL); + /* first time should do a processor restart (limit reached) */ + UT_Report(__FILE__, __LINE__, + UT_GetStubCount(UT_KEY(CFE_PSP_Restart)) == 1, + "CFE_ES_RunExceptionScan", + "Scan for exceptions; processor restart"); + /* next time should do a poweron restart (limit reached) */ + CFE_ES_RunExceptionScan(0, NULL); + UT_Report(__FILE__, __LINE__, + UT_GetStubCount(UT_KEY(CFE_PSP_Restart)) == 2, + "CFE_ES_RunExceptionScan", + "Scan for exceptions; poweron restart"); + + /* nominal for app restart - associate exception with a task ID */ + OS_TaskCreate(&UT_ContextBuffer, "UT", NULL, NULL, 0, 0, 0); + UT_SetDataBuffer(UT_KEY(CFE_PSP_Exception_GetSummary), &UT_ContextBuffer, sizeof(UT_ContextBuffer), false); + CFE_ES_Global.TaskTable[1].RecordUsed = true; + CFE_ES_Global.TaskTable[1].AppId = 0; + CFE_ES_Global.TaskTable[1].TaskId = UT_ContextBuffer; + CFE_ES_Global.AppTable[0].AppState = CFE_ES_AppState_RUNNING; + CFE_ES_Global.AppTable[0].ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_RUN; + CFE_ES_Global.AppTable[0].ControlReq.AppTimerMsec = 0; + CFE_ES_Global.AppTable[0].Type = CFE_ES_AppType_EXTERNAL; + CFE_ES_Global.AppTable[0].StartParams.ExceptionAction = CFE_ES_ExceptionAction_RESTART_APP; + CFE_ES_RunExceptionScan(0, NULL); + /* should have changed AppControlRequest from RUN to SYS_RESTART, + * and the call to CFE_PSP_Restart should NOT increment */ + UT_Report(__FILE__, __LINE__, + CFE_ES_Global.AppTable[0].ControlReq.AppControlRequest == CFE_ES_RunStatus_SYS_RESTART, + "CFE_ES_RunExceptionScan", + "Scan for exceptions; app restart request pending"); + + UT_Report(__FILE__, __LINE__, + UT_GetStubCount(UT_KEY(CFE_PSP_Restart)) == 2, + "CFE_ES_RunExceptionScan", + "Scan for exceptions; no psp restart"); + + /* repeat, but for a CORE app, which cannot be restarted */ + UT_SetDataBuffer(UT_KEY(CFE_PSP_Exception_GetSummary), &UT_ContextBuffer, sizeof(UT_ContextBuffer), false); + CFE_ES_Global.AppTable[0].ControlReq.AppControlRequest = CFE_ES_RunStatus_APP_RUN; + CFE_ES_Global.AppTable[0].Type = CFE_ES_AppType_CORE; + CFE_ES_RunExceptionScan(0, NULL); + UT_Report(__FILE__, __LINE__, + UT_GetStubCount(UT_KEY(CFE_PSP_Restart)) == 3, + "CFE_ES_RunExceptionScan", + "Scan for exceptions; core app, psp restart"); + + /* check failure of getting summary data */ + UT_SetForceFail(UT_KEY(CFE_PSP_Exception_GetSummary), CFE_PSP_NO_EXCEPTION_DATA); + CFE_ES_RunExceptionScan(0, NULL); + UT_Report(__FILE__, __LINE__, + UT_GetStubCount(UT_KEY(CFE_PSP_Restart)) == 4, + "CFE_ES_RunExceptionScan", + "Scan for exceptions; fail to get context"); /* Test clearing the log with a bad size in the verify command * length call @@ -4338,13 +4379,12 @@ void TestPerf(void) void TestAPI(void) { - uint32 Id, Id2; - uint32 TestObjId, TestObjId2; + uint32 Id; + uint32 TestObjId; char AppName[32]; char CounterName[11]; char CDSName[CFE_MISSION_ES_CDS_MAX_NAME_LENGTH + 2]; int i; - uint32 ExceptionContext = 0; int32 Return; uint8 Data[12]; uint32 ResetType; @@ -5328,86 +5368,6 @@ void TestAPI(void) (CounterCount == 5), "CFE_ES_SetGenCount", "Check value for counter set"); - /* Test handling of logging and reset after a core exception using - * a non-running app - */ - ES_ResetUnitTest(); - OS_TaskCreate(&TestObjId, "UT", NULL, NULL, 0, 0, 0); - Id = ES_UT_OSALID_TO_ARRAYIDX(TestObjId); - OS_TaskCreate(&TestObjId2, "UT", NULL, NULL, 0, 0, 0); - Id2 = ES_UT_OSALID_TO_ARRAYIDX(TestObjId2); - strncpy((char *)CFE_ES_Global.AppTable[Id].StartParams.Name, "appName", - sizeof(CFE_ES_Global.AppTable[Id].StartParams.Name)); - CFE_ES_Global.TaskTable[Id].RecordUsed = true; - CFE_ES_Global.AppTable[Id].Type = CFE_ES_AppType_EXTERNAL; - CFE_ES_Global.AppTable[Id].AppState = CFE_ES_AppState_EARLY_INIT; - CFE_ES_Global.TaskTable[Id2].RecordUsed = true; - CFE_ES_Global.TaskTable[Id2].AppId = Id; - OS_TaskCreate(&CFE_ES_Global.TaskTable[Id2].TaskId, NULL, NULL, NULL, - 0, 0, 0); - CFE_ES_Global.AppTable[Id].StartParams.ExceptionAction = - CFE_ES_ExceptionAction_RESTART_APP; - CFE_ES_ProcessCoreException(TestObjId & 0xFFFF, - "Reason String", - &ExceptionContext, - sizeof(ExceptionContext)); - UT_Report(__FILE__, __LINE__, - UT_PrintfIsInHistory(UT_OSP_MESSAGES[UT_OSP_CANNOT_RESTART_APP]) && - UT_GetStubCount(UT_KEY(OS_printf)) == 1, - "CFE_ES_ProcessCoreException", - "Cannot restart a non-running application"); - - /* Test handling of logging and reset after a core exception; processor - * reset with no app restart - */ - ES_ResetUnitTest(); - UT_SetDataBuffer(UT_KEY(CFE_PSP_Restart), &ResetType, sizeof(ResetType), false); - OS_TaskCreate(&TestObjId, "UT", NULL, NULL, 0, 0, 0); - Id = ES_UT_OSALID_TO_ARRAYIDX(TestObjId); - OS_TaskCreate(&TestObjId2, "UT", NULL, NULL, 0, 0, 0); - Id2 = ES_UT_OSALID_TO_ARRAYIDX(TestObjId2); -// memset(CFE_ES_Global.TaskTable, 0, sizeof(CFE_ES_Global.TaskTable)); -// memset(CFE_ES_Global.AppTable, 0, sizeof(CFE_ES_Global.AppTable)); - strncpy((char *)CFE_ES_Global.AppTable[Id].StartParams.Name, "appName", - sizeof(CFE_ES_Global.AppTable[Id].StartParams.Name)); - CFE_ES_Global.TaskTable[Id2].RecordUsed = true; - CFE_ES_Global.TaskTable[Id2].AppId = Id; - OS_TaskCreate(&CFE_ES_Global.TaskTable[Id2].TaskId, NULL, NULL, NULL, - 0, 0, 0); - CFE_ES_Global.AppTable[Id].AppState = CFE_ES_AppState_RUNNING; - CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount = 0; - CFE_ES_ResetDataPtr->ResetVars.MaxProcessorResetCount = 5; - CFE_ES_Global.AppTable[3].StartParams.ExceptionAction = - CFE_ES_ExceptionAction_RESTART_APP + 1; - CFE_ES_ProcessCoreException(TestObjId2 & 0xFFFF, - "Reason String", - &ExceptionContext, - sizeof(ExceptionContext)); - UT_Report(__FILE__, __LINE__, - ResetType == CFE_PSP_RST_TYPE_PROCESSOR && - UT_GetStubCount(UT_KEY(CFE_PSP_Restart)) == 1, - "CFE_ES_ProcessCoreException", - "Processor reset with no application restart"); - - /* Test handling of logging and reset after a core exception; power on - * reset with no app restart - */ - ES_ResetUnitTest(); - UT_SetDataBuffer(UT_KEY(CFE_PSP_Restart), &ResetType, sizeof(ResetType), false); - CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount = 100; - CFE_ES_ResetDataPtr->ResetVars.MaxProcessorResetCount = 5; - CFE_ES_Global.AppTable[3].StartParams.ExceptionAction = - CFE_ES_ExceptionAction_RESTART_APP + 1; - CFE_ES_ProcessCoreException(OS_MAX_TASKS - 1, - "Reason String", - &ExceptionContext, - sizeof(ExceptionContext)); - UT_Report(__FILE__, __LINE__, - ResetType == CFE_PSP_RST_TYPE_POWERON && - UT_GetStubCount(UT_KEY(CFE_PSP_Restart)) == 1, - "CFE_ES_ProcessCoreException", - "Power on reset with no application restart"); - /* Test waiting for apps to initialize before continuing; transition from * initializing to running */ @@ -5601,68 +5561,6 @@ void TestAPI(void) "CFE_ES_GetGenCounterIDByName", "Null name"); - /* Test handling of logging and reset after failure to get the task info - * from the OS - */ - ES_ResetUnitTest(); - UT_SetDeferredRetcode(UT_KEY(OS_TaskGetInfo), 1, OS_INVALID_POINTER); - CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount = 0; - CFE_ES_ResetDataPtr->ResetVars.MaxProcessorResetCount = 5; - CFE_ES_ProcessCoreException(0xFFFFFFFF, - "Reason String", - &ExceptionContext, - sizeof(ExceptionContext)); - UT_Report(__FILE__, __LINE__, - CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount == 1 && - CFE_ES_ResetDataPtr->ResetVars.ES_CausedReset == true, - "CFE_ES_ProcessCoreException", - "Failure to get task info from OS"); - - /* Test handling of logging and reset where the host ID doesn't match - * the OS task ID - */ - ES_ResetUnitTest(); - OS_TaskCreate(&TestObjId, "UT", NULL, NULL, 0, 0, 0); - Id = ES_UT_OSALID_TO_ARRAYIDX(TestObjId); - CFE_ES_Global.TaskTable[Id].RecordUsed = true; - CFE_ES_Global.TaskTable[Id].AppId = Id; - CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount = 0; - CFE_ES_ResetDataPtr->ResetVars.MaxProcessorResetCount = 5; - CFE_ES_Global.AppTable[Id].StartParams.ExceptionAction = - CFE_ES_ExceptionAction_RESTART_APP; - CFE_ES_ProcessCoreException(0, - "Reason String", - &ExceptionContext, - sizeof(ExceptionContext)); - UT_Report(__FILE__, __LINE__, - UT_GetStubCount(UT_KEY(OS_printf)) == 0, - "CFE_ES_ProcessCoreException", - "Host ID doesn't match OS task ID"); - - /* Test handling of logging and reset where CFE_ES_GetTaskInfo fails */ - ES_ResetUnitTest(); - OS_TaskCreate(&TestObjId, "UT", NULL, NULL, 0, 0, 0); - Id = ES_UT_OSALID_TO_ARRAYIDX(TestObjId); - OS_TaskCreate(&TestObjId2, "UT", NULL, NULL, 0, 0, 0); - Id2 = ES_UT_OSALID_TO_ARRAYIDX(TestObjId2); - CFE_ES_Global.TaskTable[Id].RecordUsed = true; - CFE_ES_Global.TaskTable[Id].AppId = Id; - CFE_ES_ResetDataPtr->ResetVars.ProcessorResetCount = 0; - CFE_ES_ResetDataPtr->ResetVars.MaxProcessorResetCount = 5; - CFE_ES_Global.TaskTable[Id].RecordUsed = true; - CFE_ES_Global.TaskTable[Id].AppId = Id2; - CFE_ES_Global.AppTable[Id2].AppState = CFE_ES_AppState_UNDEFINED; - CFE_ES_Global.AppTable[Id2].StartParams.ExceptionAction = - CFE_ES_ExceptionAction_RESTART_APP; - CFE_ES_ProcessCoreException(Id, - "Reason String", - &ExceptionContext, - sizeof(ExceptionContext)); - UT_Report(__FILE__, __LINE__, - UT_GetStubCount(UT_KEY(OS_printf)) == 1, - "CFE_ES_ProcessCoreException", - "CFE_ES_GetTaskInfo failure"); - /* Test unsuccessful CDS registering */ ES_ResetUnitTest(); OS_TaskCreate(&TestObjId, "UT", NULL, NULL, 0, 0, 0); From 87b87c8c1146fdc612d08dff745b9917b8ce1771 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Wed, 6 May 2020 07:50:08 -0400 Subject: [PATCH 2/2] Update #411, documentation updates Correct items flagged as warnings in documenation build, and remove now-unused definition in sample platform config --- cmake/sample_defs/cpu1_platform_cfg.h | 46 --------------------------- docs/src/main.dox | 2 +- 2 files changed, 1 insertion(+), 47 deletions(-) diff --git a/cmake/sample_defs/cpu1_platform_cfg.h b/cmake/sample_defs/cpu1_platform_cfg.h index 1a7f3f5bd..167eedd53 100644 --- a/cmake/sample_defs/cpu1_platform_cfg.h +++ b/cmake/sample_defs/cpu1_platform_cfg.h @@ -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 ** diff --git a/docs/src/main.dox b/docs/src/main.dox index d3d583d84..d2cdf1efc 100644 --- a/docs/src/main.dox +++ b/docs/src/main.dox @@ -472,7 +472,7 @@
  • #CFE_ES_CalculateCRC - \copybrief CFE_ES_CalculateCRC
  • #CFE_ES_WriteToSysLog - \copybrief CFE_ES_WriteToSysLog -
  • #CFE_ES_ProcessCoreException - \copybrief CFE_ES_ProcessCoreException +
  • #CFE_ES_ProcessAsyncEvent - \copybrief CFE_ES_ProcessAsyncEvent