From b2dd44dcc10b5776d31cee41964fb5965ad4d1ec Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Mon, 27 Apr 2020 09:24:30 -0400 Subject: [PATCH 1/4] Fix #156, termination on strncpy Fix possible non-termination of strings in command line option parsing. These generated warnings in GCC9. --- fsw/pc-linux/src/cfe_psp_start.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fsw/pc-linux/src/cfe_psp_start.c b/fsw/pc-linux/src/cfe_psp_start.c index b2cc804c..6a8432c6 100644 --- a/fsw/pc-linux/src/cfe_psp_start.c +++ b/fsw/pc-linux/src/cfe_psp_start.c @@ -186,7 +186,9 @@ void OS_Application_Startup(void) switch( opt ) { case 'R': - strncpy(CommandData.ResetType, optarg, CFE_PSP_RESET_NAME_LENGTH); + strncpy(CommandData.ResetType, optarg, CFE_PSP_RESET_NAME_LENGTH-1); + CommandData.ResetType[CFE_PSP_RESET_NAME_LENGTH-1] = 0; + if ((strncmp(CommandData.ResetType, "PO", CFE_PSP_RESET_NAME_LENGTH ) != 0 ) && (strncmp(CommandData.ResetType, "PR", CFE_PSP_RESET_NAME_LENGTH ) != 0 )) { @@ -214,7 +216,8 @@ void OS_Application_Startup(void) break; case 'N': - strncpy(CommandData.CpuName, optarg, CFE_PSP_CPU_NAME_LENGTH ); + strncpy(CommandData.CpuName, optarg, CFE_PSP_CPU_NAME_LENGTH-1 ); + CommandData.CpuName[CFE_PSP_CPU_NAME_LENGTH-1] = 0; printf("CFE_PSP: CPU Name: %s\n",CommandData.CpuName); CommandData.GotCpuName = 1; break; @@ -521,7 +524,8 @@ void CFE_PSP_ProcessArgumentDefaults(CFE_PSP_CommandData_t *CommandDataDefault) if ( CommandDataDefault->GotCpuName == 0 ) { - strncpy(CommandDataDefault->CpuName, CFE_PSP_CPU_NAME, CFE_PSP_CPU_NAME_LENGTH ); + strncpy(CommandDataDefault->CpuName, CFE_PSP_CPU_NAME, CFE_PSP_CPU_NAME_LENGTH-1 ); + CommandDataDefault->CpuName[CFE_PSP_CPU_NAME_LENGTH-1] = 0; printf("CFE_PSP: Default CPU Name: %s\n",CFE_PSP_CPU_NAME); CommandDataDefault->GotCpuName = 1; } From fe5e0194835bf32083da860c2b50a90aad3e098b Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Wed, 29 Apr 2020 11:30:11 -0400 Subject: [PATCH 2/4] Fix #158, Exception handling in PSP Implment exceptions for VxWorks and PC-Linux PSP Exceptions are buffered in an extra block inside the PSP reserved area. On pc-linux, the interrupt (CTRL+C) handling is also treated as an exception, which shuts down the CFE normally. This also means processor resets on the pc-linux can be tested. --- CMakeLists.txt | 2 + fsw/inc/cfe_psp.h | 17 +- fsw/inc/cfe_psp_configdata.h | 8 +- fsw/mcp750-vxworks/inc/cfe_psp_config.h | 58 ++++- fsw/mcp750-vxworks/src/cfe_psp_exception.c | 117 ++++----- fsw/mcp750-vxworks/src/cfe_psp_memory.c | 123 +++++++-- fsw/mcp750-vxworks/src/cfe_psp_memory.h | 91 ------- fsw/mcp750-vxworks/src/cfe_psp_start.c | 20 +- fsw/mcp750-vxworks/src/cfe_psp_support.c | 28 +- fsw/pc-linux/inc/cfe_psp_config.h | 101 ++++++- fsw/pc-linux/src/cfe_psp_exception.c | 289 +++++++++++++++++---- fsw/pc-linux/src/cfe_psp_memory.c | 255 ++++++++++-------- fsw/pc-linux/src/cfe_psp_start.c | 174 ++++++++----- fsw/pc-linux/src/cfe_psp_support.c | 55 +++- fsw/pc-rtems/inc/cfe_psp_config.h | 57 +++- fsw/pc-rtems/src/cfe_psp_exception.c | 100 ++----- fsw/pc-rtems/src/cfe_psp_memory.c | 195 ++++++++------ fsw/pc-rtems/src/cfe_psp_memory.h | 82 ------ fsw/pc-rtems/src/cfe_psp_start.c | 5 + fsw/pc-rtems/src/cfe_psp_support.c | 16 +- fsw/shared/cfe_psp_configdata.c | 1 - fsw/shared/cfe_psp_exceptionstorage.c | 265 +++++++++++++++++++ fsw/shared/cfe_psp_exceptionstorage.h | 107 ++++++++ fsw/shared/cfe_psp_memory.h | 107 ++++++++ fsw/ut-stubs/ut_psp_stubs.c | 42 +++ 25 files changed, 1592 insertions(+), 723 deletions(-) delete mode 100644 fsw/mcp750-vxworks/src/cfe_psp_memory.h delete mode 100644 fsw/pc-rtems/src/cfe_psp_memory.h create mode 100644 fsw/shared/cfe_psp_exceptionstorage.c create mode 100644 fsw/shared/cfe_psp_exceptionstorage.h create mode 100644 fsw/shared/cfe_psp_memory.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 838ec376..e59dcd36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ add_definitions(-D_CFE_PSP_) include_directories(fsw/shared) # Build the PSP implementation which lies in a system-specific subdirectory +include_directories(fsw/shared) include_directories(fsw/${CFE_SYSTEM_PSPNAME}/inc) add_subdirectory(fsw/${CFE_SYSTEM_PSPNAME} ${CFE_SYSTEM_PSPNAME}) @@ -16,6 +17,7 @@ add_subdirectory(fsw/${CFE_SYSTEM_PSPNAME} ${CFE_SYSTEM_PSPNAME}) add_library(psp-${CFE_SYSTEM_PSPNAME} STATIC fsw/shared/cfe_psp_configdata.c fsw/shared/cfe_psp_eeprom.c + fsw/shared/cfe_psp_exceptionstorage.c fsw/shared/cfe_psp_memrange.c fsw/shared/cfe_psp_memutils.c fsw/shared/cfe_psp_module.c diff --git a/fsw/inc/cfe_psp.h b/fsw/inc/cfe_psp.h index b33ec55c..b4f190a3 100644 --- a/fsw/inc/cfe_psp.h +++ b/fsw/inc/cfe_psp.h @@ -65,6 +65,7 @@ #define CFE_PSP_ERROR_NOT_IMPLEMENTED (-27) #define CFE_PSP_INVALID_MODULE_NAME (-28) #define CFE_PSP_INVALID_MODULE_ID (-29) +#define CFE_PSP_NO_EXCEPTION_DATA (-30) @@ -196,7 +197,7 @@ extern uint32 CFE_PSP_GetRestartType(uint32 *restartSubType ); */ -extern void CFE_PSP_FlushCaches(uint32 type, cpuaddr address, uint32 size); +extern void CFE_PSP_FlushCaches(uint32 type, void* address, uint32 size); /* ** This is a BSP specific cache flush routine */ @@ -247,16 +248,6 @@ extern uint32 CFE_PSP_Get_Dec(void); ** CFE_PSP_Get_Dec */ - -extern int32 CFE_PSP_InitProcessorReservedMemory(uint32 RestartType ); -/* -** CFE_PSP_InitProcessorReservedMemory initializes all of the memory in the -** BSP that is preserved on a processor reset. The memory includes the -** Critical Data Store, the ES Reset Area, the Volatile Disk Memory, and -** the User Reserved Memory. In general, the memory areas will be initialized -** ( cleared ) on a Power On reset, and preserved during a processor reset. -*/ - extern int32 CFE_PSP_GetCDSSize(uint32 *SizeOfCDS); /* ** CFE_PSP_GetCDSSize fetches the size of the OS Critical Data Store area. @@ -368,6 +359,10 @@ extern void CFE_PSP_SetDefaultExceptionEnvironment(void); */ +extern uint32 CFE_PSP_Exception_GetCount(void); +extern int32 CFE_PSP_Exception_GetSummary(uint32 *ContextLogId, uint32 *TaskId, char *ReasonBuf, uint32 ReasonSize); +extern int32 CFE_PSP_Exception_CopyContext(uint32 ContextLogId, void *ContextBuf, uint32 ContextSize); + /* ** I/O Port API */ diff --git a/fsw/inc/cfe_psp_configdata.h b/fsw/inc/cfe_psp_configdata.h index f00787da..61217bb6 100644 --- a/fsw/inc/cfe_psp_configdata.h +++ b/fsw/inc/cfe_psp_configdata.h @@ -58,18 +58,12 @@ typedef const struct uint32 PSP_WatchdogMin; /**< PSP Minimum watchdog in milliseconds */ uint32 PSP_WatchdogMax; /**< PSP Maximum watchdog in milliseconds */ uint32 PSP_MemTableSize; /**< Size of PSP memory table */ + uint32 PSP_ExceptionLogSize; /**< Size of PSP exception log */ CFE_PSP_MemTable_t *PSP_MemoryTable; /**< Pointer to PSP memory table (forward reference) */ uint32 OS_VolumeTableSize; /**< Size of OS volume table */ OS_VolumeInfo_t *OS_VolumeTable; /**< Pointer to OS volume table (forward reference) */ - /** - * Processor Context type. - * This is needed to determine the size of the context entry in the ER log. - * It is a placeholder as the implementation to use it is not merged in yet. - */ - uint32 OS_CpuContextSize; - /** * Number of EEPROM banks on this platform */ diff --git a/fsw/mcp750-vxworks/inc/cfe_psp_config.h b/fsw/mcp750-vxworks/inc/cfe_psp_config.h index ad0c4be8..337b497b 100644 --- a/fsw/mcp750-vxworks/inc/cfe_psp_config.h +++ b/fsw/mcp750-vxworks/inc/cfe_psp_config.h @@ -44,21 +44,47 @@ */ #define CFE_PSP_MEM_TABLE_SIZE 10 +/** + * This define sets the maximum number of exceptions + * that can be stored. + * + * It must always be a power of two. + */ +#define CFE_PSP_MAX_EXCEPTION_ENTRIES 4 + /* -** Processor Context type. -** This is needed to determine the size of the context entry in the ER log. -** Although this file is in a CPU directory, it really is OS dependant, so supporting -** multiple OSs on the same CPU architecture ( i.e. x86/linux, x86/windows, x86/osx ) -** will require IFDEFS. +** Typedef for the layout of the vxWorks boot record structure +** +** This is statically placed at the beginning of system memory (sysMemTop) +** which should be reserved in the kernel. */ -typedef struct +typedef struct { - ESFPPC esf; /* Exception stack frame */ - FP_CONTEXT fp; /* floating point registers */ - -} CFE_PSP_ExceptionContext_t; + uint32 bsp_reset_type; + uint32 spare1; + uint32 spare2; + uint32 spare3; + +} CFE_PSP_ReservedMemoryBootRecord_t; -#define CFE_PSP_CPU_CONTEXT_SIZE (sizeof(CFE_PSP_ExceptionContext_t)) + +/** + * \brief The data type used by the underlying OS to represent a thread ID. + */ +typedef TASK_ID CFE_PSP_Exception_SysTaskId_t; + +/* +** Global variables +*/ +typedef struct +{ + UINT32 timebase_upper; /* Upper 32 bits of timebase as sampled by hook */ + UINT32 timebase_lower; /* Lower 32 bits of timebase as sampled by hook */ + int vector; /* vector number */ + ESFPPC esf; /* Exception stack frame */ + FP_CONTEXT fp; /* floating point registers */ + +} CFE_PSP_Exception_ContextDataEntry_t; /* ** Watchdog minimum and maximum values ( in milliseconds ) @@ -71,6 +97,16 @@ typedef struct */ #define CFE_PSP_NUM_EEPROM_BANKS 1 +/* + * The alignment to use for each reserved memory block. + * + * This is a mask to be applied to each block base address + * + * Chosen as the cache line size of the MPC750 processor (32 bytes) + * such that the blocks will be cached more efficiently. + */ +#define CFE_PSP_MEMALIGN_MASK ((cpuaddr)0x1F) + #endif diff --git a/fsw/mcp750-vxworks/src/cfe_psp_exception.c b/fsw/mcp750-vxworks/src/cfe_psp_exception.c index ab4bb8b6..7fbee892 100644 --- a/fsw/mcp750-vxworks/src/cfe_psp_exception.c +++ b/fsw/mcp750-vxworks/src/cfe_psp_exception.c @@ -54,33 +54,11 @@ #include "cfe_psp.h" #include "cfe_psp_config.h" +#include "cfe_psp_exceptionstorage.h" #include "cfe_psp_memory.h" #include -/* -** Types and prototypes for this module -*/ - -/* use the exception ISR binding from the global config data */ -#define CFE_PSP_ES_EXCEPTION_FUNCTION (*GLOBAL_CONFIGDATA.CfeConfig->SystemExceptionISR) - -/* -** BSP Specific defines -*/ - - -/* -** External Declarations -*/ - -/* -** Global variables -*/ - -CFE_PSP_ExceptionContext_t CFE_PSP_ExceptionContext; -char CFE_PSP_ExceptionReasonString[256]; - /* ** ** LOCAL FUNCTION PROTOTYPES @@ -110,7 +88,8 @@ void CFE_PSP_ExceptionHook ( TASK_ID task_id, int vector, void* vpEsf ); void CFE_PSP_AttachExceptions(void) { excHookAdd( CFE_PSP_ExceptionHook ); - OS_printf("CFE_PSP: Attached cFE Exception Handler. Context Size = %d bytes.\n",CFE_PSP_CPU_CONTEXT_SIZE); + OS_printf("CFE_PSP: Attached cFE Exception Handler. Context Size = %u bytes.\n",sizeof(CFE_PSP_Exception_ContextDataEntry_t)); + CFE_PSP_Exception_Reset(); } @@ -135,46 +114,42 @@ void CFE_PSP_AttachExceptions(void) */ void CFE_PSP_ExceptionHook (TASK_ID task_id, int vector, void* vpEsf ) { - ESFPPC *pEsf = vpEsf; - char *TaskName; + CFE_PSP_Exception_LogData_t* Buffer; - /* - ** Get the vxWorks task name - */ - TaskName = taskName(task_id); - - if ( TaskName == NULL ) + Buffer = CFE_PSP_Exception_GetNextContextBuffer(); + if (Buffer != NULL) { - sprintf(CFE_PSP_ExceptionReasonString, "Exception: Vector=0x%06X, vxWorks Task Name=NULL, Task ID=0x%08X", - vector,task_id); + /* + * Immediately get a snapshot of the timebase when exception occurred + * + * This is because the remainder of exception processing might be done + * in a cleanup job as a low priority background task, and might be + * considerably delayed from the time the actual exception occurred. + */ + vxTimeBaseGet(&Buffer->context_info.timebase_upper, &Buffer->context_info.timebase_lower); + + Buffer->sys_task_id = task_id; + Buffer->context_info.vector = vector; + + /* + * Save Exception Stack frame + */ + memcpy(&Buffer->context_info.esf, vpEsf, sizeof(Buffer->context_info.esf)); + + /* + * Save floating point registers + */ + fppSave(&Buffer->context_info.fp); + + CFE_PSP_Exception_WriteComplete(); } - else + + if (GLOBAL_CFE_CONFIGDATA.SystemNotify != NULL) { - sprintf(CFE_PSP_ExceptionReasonString, "Exception: Vector=0x%06X, vxWorks Task Name=%s, Task ID=0x%08X", - vector, TaskName, task_id); + /* notify the CFE of the event */ + GLOBAL_CFE_CONFIGDATA.SystemNotify(); } - /* - ** Save Exception Stack frame - */ - memcpy(&(CFE_PSP_ExceptionContext.esf), pEsf, sizeof(ESFPPC)); - - /* - ** Save floating point registers - */ - fppSave(&CFE_PSP_ExceptionContext.fp); - - /* - ** Call the Generic cFE routine to finish processing the exception and - ** restart the cFE - */ - CFE_PSP_ES_EXCEPTION_FUNCTION((uint32) task_id, - (char *) CFE_PSP_ExceptionReasonString, - (uint32 *) &CFE_PSP_ExceptionContext, - sizeof(CFE_PSP_ExceptionContext_t)); - /* - ** No return to here - */ } /* end function */ @@ -210,3 +185,29 @@ void CFE_PSP_SetDefaultExceptionEnvironment(void) _PPC_FPSCR_UE ); /* fp underflow enable */ } +/* + * Name: CFE_PSP_ExceptionGetSummary_Impl + * + * Purpose: Translate a stored exception log entry into a summary string + */ +int32 CFE_PSP_ExceptionGetSummary_Impl(const CFE_PSP_Exception_LogData_t* Buffer, char *ReasonBuf, uint32 ReasonSize) +{ + const char *TaskName; + + /* + ** Get the vxWorks task name + */ + TaskName = taskName(Buffer->sys_task_id); + + if ( TaskName == NULL ) + { + TaskName = "NULL"; + } + + snprintf(ReasonBuf, ReasonSize, "Vector=0x%06X, vxWorks Task Name=%s, Task ID=0x%08X", + Buffer->context_info.vector,TaskName,Buffer->sys_task_id); + + return CFE_PSP_SUCCESS; +} + + diff --git a/fsw/mcp750-vxworks/src/cfe_psp_memory.c b/fsw/mcp750-vxworks/src/cfe_psp_memory.c index 2cbac0e3..ace5842c 100644 --- a/fsw/mcp750-vxworks/src/cfe_psp_memory.c +++ b/fsw/mcp750-vxworks/src/cfe_psp_memory.c @@ -56,6 +56,8 @@ #include "cfe_psp.h" #include "cfe_psp_memory.h" +#include + /* ** Define the cFE Core loadable module name */ @@ -78,7 +80,11 @@ extern unsigned int GetWrsKernelTextEnd (void); ** Pointer to the vxWorks USER_RESERVED_MEMORY area ** The sizes of each memory area is defined in os_processor.h for this architecture. */ -CFE_PSP_ReservedMemory_t *CFE_PSP_ReservedMemoryPtr; +CFE_PSP_ReservedMemoryMap_t CFE_PSP_ReservedMemoryMap; + + +CFE_PSP_MemoryBlock_t MCP750_ReservedMemBlock; + /* ********************************************************************************* @@ -109,7 +115,7 @@ int32 CFE_PSP_GetCDSSize(uint32 *SizeOfCDS) } else { - *SizeOfCDS = CFE_PSP_CDS_SIZE; + *SizeOfCDS = CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize; return_code = CFE_PSP_SUCCESS; } return(return_code); @@ -138,12 +144,14 @@ int32 CFE_PSP_WriteToCDS(const void *PtrToDataToWrite, uint32 CDSOffset, uint32 } else { - if ( (CDSOffset < CFE_PSP_CDS_SIZE ) && ( (CDSOffset + NumBytes) <= CFE_PSP_CDS_SIZE )) + if ( (CDSOffset < CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize ) && + ( (CDSOffset + NumBytes) <= CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize )) { - CopyPtr = &(CFE_PSP_ReservedMemoryPtr->CDSMemory[CDSOffset]); - memcpy(CopyPtr, (char *)PtrToDataToWrite,NumBytes); + CopyPtr = CFE_PSP_ReservedMemoryMap.CDSMemory.BlockPtr; + CopyPtr += CDSOffset; + memcpy(CopyPtr, (char *)PtrToDataToWrite,NumBytes); - return_code = CFE_PSP_SUCCESS; + return_code = CFE_PSP_SUCCESS; } else { @@ -180,12 +188,14 @@ int32 CFE_PSP_ReadFromCDS(void *PtrToDataToRead, uint32 CDSOffset, uint32 NumByt } else { - if ( (CDSOffset < CFE_PSP_CDS_SIZE ) && ( (CDSOffset + NumBytes) <= CFE_PSP_CDS_SIZE )) + if ( (CDSOffset < CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize ) && + ( (CDSOffset + NumBytes) <= CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize )) { - CopyPtr = &(CFE_PSP_ReservedMemoryPtr->CDSMemory[CDSOffset]); - memcpy((char *)PtrToDataToRead,CopyPtr, NumBytes); + CopyPtr = CFE_PSP_ReservedMemoryMap.CDSMemory.BlockPtr; + CopyPtr += CDSOffset; + memcpy((char *)PtrToDataToRead,CopyPtr, NumBytes); - return_code = CFE_PSP_SUCCESS; + return_code = CFE_PSP_SUCCESS; } else { @@ -228,8 +238,8 @@ int32 CFE_PSP_GetResetArea (cpuaddr *PtrToResetArea, uint32 *SizeOfResetArea) } else { - *PtrToResetArea = (cpuaddr)(CFE_PSP_ReservedMemoryPtr->ResetMemory); - *SizeOfResetArea = CFE_PSP_RESET_AREA_SIZE; + *PtrToResetArea = (cpuaddr)(CFE_PSP_ReservedMemoryMap.ResetMemory.BlockPtr); + *SizeOfResetArea = CFE_PSP_ReservedMemoryMap.ResetMemory.BlockSize; return_code = CFE_PSP_SUCCESS; } @@ -265,8 +275,8 @@ int32 CFE_PSP_GetUserReservedArea(cpuaddr *PtrToUserArea, uint32 *SizeOfUserArea } else { - *PtrToUserArea = (cpuaddr)(CFE_PSP_ReservedMemoryPtr->UserReservedMemory); - *SizeOfUserArea = CFE_PSP_USER_RESERVED_SIZE; + *PtrToUserArea = (cpuaddr)(CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockPtr); + *SizeOfUserArea = CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockSize; return_code = CFE_PSP_SUCCESS; } @@ -302,8 +312,8 @@ int32 CFE_PSP_GetVolatileDiskMem(cpuaddr *PtrToVolDisk, uint32 *SizeOfVolDisk ) } else { - *PtrToVolDisk = (cpuaddr)(CFE_PSP_ReservedMemoryPtr->VolatileDiskMemory); - *SizeOfVolDisk = CFE_PSP_VOLATILE_DISK_SIZE; + *PtrToVolDisk = (cpuaddr)(CFE_PSP_ReservedMemoryMap.VolatileDiskMemory.BlockPtr); + *SizeOfVolDisk = CFE_PSP_ReservedMemoryMap.VolatileDiskMemory.BlockSize; return_code = CFE_PSP_SUCCESS; } @@ -337,12 +347,12 @@ int32 CFE_PSP_InitProcessorReservedMemory( uint32 RestartType ) if ( RestartType != CFE_PSP_RST_TYPE_PROCESSOR ) { OS_printf("CFE_PSP: Clearing Processor Reserved Memory.\n"); - memset((void *)CFE_PSP_ReservedMemoryPtr, 0, sizeof(CFE_PSP_ReservedMemory_t)); + memset(MCP750_ReservedMemBlock.BlockPtr, 0, MCP750_ReservedMemBlock.BlockSize); /* ** Set the default reset type in case a watchdog reset occurs */ - CFE_PSP_ReservedMemoryPtr->bsp_reset_type = CFE_PSP_RST_TYPE_PROCESSOR; + CFE_PSP_ReservedMemoryMap.BootPtr->bsp_reset_type = CFE_PSP_RST_TYPE_PROCESSOR; } return_code = CFE_PSP_SUCCESS; @@ -350,6 +360,83 @@ int32 CFE_PSP_InitProcessorReservedMemory( uint32 RestartType ) } +/****************************************************************************** +** Function: CFE_PSP_SetupReservedMemoryMap +** +** Purpose: +** Set up the CFE_PSP_ReservedMemoryMap global data structure +** This only sets the pointers, it does not initialize the data. +** +** Arguments: +** (none) +** +** Return: +** (none) +*/ +void CFE_PSP_SetupReservedMemoryMap(void) +{ + cpuaddr start_addr; + cpuaddr end_addr; + + /* + ** Note: this uses a "cpuaddr" (integer address) as an intermediate + ** to avoid warnings about alignment. The output of sysMemTop() + ** should be aligned to hold any data type, being the very start + ** of the memory space. + */ + start_addr = (cpuaddr) sysMemTop(); + end_addr = start_addr; + + memset(&CFE_PSP_ReservedMemoryMap, 0, sizeof(CFE_PSP_ReservedMemoryMap)); + + CFE_PSP_ReservedMemoryMap.BootPtr = (CFE_PSP_ReservedMemoryBootRecord_t *)end_addr; + end_addr += sizeof(CFE_PSP_ReservedMemoryBootRecord_t); + end_addr = (end_addr + CFE_PSP_MEMALIGN_MASK) & ~CFE_PSP_MEMALIGN_MASK; + + CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr = (CFE_PSP_ExceptionStorage_t *)end_addr; + end_addr += sizeof(CFE_PSP_ExceptionStorage_t); + end_addr = (end_addr + CFE_PSP_MEMALIGN_MASK) & ~CFE_PSP_MEMALIGN_MASK; + + CFE_PSP_ReservedMemoryMap.ResetMemory.BlockPtr = (void*)end_addr; + CFE_PSP_ReservedMemoryMap.ResetMemory.BlockSize = GLOBAL_CONFIGDATA.CfeConfig->ResetAreaSize; + end_addr += CFE_PSP_ReservedMemoryMap.ResetMemory.BlockSize; + end_addr = (end_addr + CFE_PSP_MEMALIGN_MASK) & ~CFE_PSP_MEMALIGN_MASK; + + CFE_PSP_ReservedMemoryMap.VolatileDiskMemory.BlockPtr = (void*)end_addr; + CFE_PSP_ReservedMemoryMap.VolatileDiskMemory.BlockSize = + GLOBAL_CONFIGDATA.CfeConfig->RamDiskSectorSize * GLOBAL_CONFIGDATA.CfeConfig->RamDiskTotalSectors; + end_addr += CFE_PSP_ReservedMemoryMap.VolatileDiskMemory.BlockSize; + end_addr = (end_addr + CFE_PSP_MEMALIGN_MASK) & ~CFE_PSP_MEMALIGN_MASK; + + CFE_PSP_ReservedMemoryMap.CDSMemory.BlockPtr = (void*)end_addr; + CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize = GLOBAL_CONFIGDATA.CfeConfig->CdsSize; + end_addr += CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize; + end_addr = (end_addr + CFE_PSP_MEMALIGN_MASK) & ~CFE_PSP_MEMALIGN_MASK; + + CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockPtr = (void*)end_addr; + CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockSize = GLOBAL_CONFIGDATA.CfeConfig->UserReservedSize; + end_addr += CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockSize; + end_addr = (end_addr + CFE_PSP_MEMALIGN_MASK) & ~CFE_PSP_MEMALIGN_MASK; + + /* The total size of the entire block is the difference in address */ + MCP750_ReservedMemBlock.BlockPtr = (void*)start_addr; + MCP750_ReservedMemBlock.BlockSize = end_addr - start_addr; + + + OS_printf("CFE_PSP: MCP750 Reserved Memory Block at 0x%08lx, Total Size = 0x%lx\n", + (unsigned long)MCP750_ReservedMemBlock.BlockPtr, + (unsigned long)MCP750_ReservedMemBlock.BlockSize); +} + +/****************************************************************************** + * Function: CFE_PSP_DeleteProcessorReservedMemory + * + * No action on MCP750 - reserved block is statically allocated at sysMemTop. + * Implemented for API consistency with other PSPs. + */ +void CFE_PSP_DeleteProcessorReservedMemory(void) +{ +} /* ********************************************************************************* diff --git a/fsw/mcp750-vxworks/src/cfe_psp_memory.h b/fsw/mcp750-vxworks/src/cfe_psp_memory.h deleted file mode 100644 index 62e403f7..00000000 --- a/fsw/mcp750-vxworks/src/cfe_psp_memory.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -** GSC-18128-1, "Core Flight Executive Version 6.7" -** -** Copyright (c) 2006-2019 United States Government as represented by -** the Administrator of the National Aeronautics and Space Administration. -** All Rights Reserved. -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -/* -** File Name: cfe_psp_memory.h -** -** Author: A. Cudmore -** -** Purpose: This file contains PSP support routine internal prototypes -** and typedefs. The routines and typedefs are intended for -** the local PSP routines only. -** -** Modification History: -** -*/ - -#ifndef _cfe_psp_memory_ -#define _cfe_psp_memory_ - -/* -** Include Files -*/ - -#include "common_types.h" - -/* - * the CFE platform config is required - * to size the ReservedMemory structure, below - */ -#include - -#include - -/* -** Macro Definitions -*/ -#define CFE_PSP_CDS_SIZE (GLOBAL_CONFIGDATA.CfeConfig->CdsSize) -#define CFE_PSP_RESET_AREA_SIZE (GLOBAL_CONFIGDATA.CfeConfig->ResetAreaSize) -#define CFE_PSP_USER_RESERVED_SIZE (GLOBAL_CONFIGDATA.CfeConfig->UserReservedSize) - -#define CFE_PSP_VOLATILE_DISK_SIZE (CFE_PLATFORM_ES_RAM_DISK_SECTOR_SIZE * CFE_PLATFORM_ES_RAM_DISK_NUM_SECTORS) - - -/* -** Typedef for the layout of the vxWorks USER_RESERVED_MEM -** Note that the structure below reserves memory sizes defined -** at compile time directly from cfe_platform_cfg.h above. -** A future enhancement should reserve blocks based on the runtime -** size in GLOBAL_CONFIGDATA. -*/ -typedef struct -{ - uint32 bsp_reset_type; - uint32 spare1; - uint32 spare2; - uint32 spare3; - uint8 ResetMemory[CFE_PLATFORM_ES_RESET_AREA_SIZE]; - uint8 VolatileDiskMemory[CFE_PSP_VOLATILE_DISK_SIZE]; - uint8 CDSMemory[CFE_PLATFORM_ES_CDS_SIZE]; - uint8 UserReservedMemory[CFE_PLATFORM_ES_USER_RESERVED_SIZE]; - -} CFE_PSP_ReservedMemory_t; - -/* -** External variables -*/ - -/* -** Pointer to the vxWorks USER_RESERVED_MEMORY area -** The sizes of each memory area is defined in os_processor.h for this architecture. -*/ -extern CFE_PSP_ReservedMemory_t *CFE_PSP_ReservedMemoryPtr; - -#endif /* _cfe_psp_memory_ */ diff --git a/fsw/mcp750-vxworks/src/cfe_psp_start.c b/fsw/mcp750-vxworks/src/cfe_psp_start.c index 18927248..509cd016 100644 --- a/fsw/mcp750-vxworks/src/cfe_psp_start.c +++ b/fsw/mcp750-vxworks/src/cfe_psp_start.c @@ -97,7 +97,6 @@ void OS_Application_Startup(void) uint32 reset_type; uint32 reset_subtype; char reset_register; - cpuaddr memaddr; int32 Status; @@ -128,14 +127,8 @@ void OS_Application_Startup(void) /* ** Setup the pointer to the reserved area in vxWorks. ** This must be done before any of the reset variables are used. - ** - ** Note: this uses a "cpuaddr" (integer address) as an intermediate - ** to avoid a warning about alignment. The output of sysMemTop() - ** should be aligned to hold any data type, being the very start - ** of the memory space. */ - memaddr = (cpuaddr) sysMemTop(); - CFE_PSP_ReservedMemoryPtr = (CFE_PSP_ReservedMemory_t *) memaddr; + CFE_PSP_SetupReservedMemoryMap(); /* ** Determine Reset type by reading the hardware reset register. @@ -183,7 +176,7 @@ void OS_Application_Startup(void) ** reboot functions use this reset type, we want to use this for a software ** commanded processor or Power on reset. */ - if ( CFE_PSP_ReservedMemoryPtr->bsp_reset_type == CFE_PSP_RST_TYPE_POWERON) + if ( CFE_PSP_ReservedMemoryMap.BootPtr->bsp_reset_type == CFE_PSP_RST_TYPE_POWERON) { OS_printf("CFE_PSP: POWERON Reset: Software Hard Reset.\n"); reset_type = CFE_PSP_RST_TYPE_POWERON; @@ -202,6 +195,15 @@ void OS_Application_Startup(void) reset_type = CFE_PSP_RST_TYPE_POWERON; reset_subtype = CFE_PSP_RST_SUBTYPE_UNDEFINED_RESET; } + + /* + * If CFE fails to boot with a processor reset, + * then make sure next time it uses a power on reset. + */ + if ( reset_type == CFE_PSP_RST_TYPE_PROCESSOR ) + { + CFE_PSP_ReservedMemoryMap.BootPtr->bsp_reset_type = CFE_PSP_RST_TYPE_POWERON; + } /* ** Initialize the reserved memory diff --git a/fsw/mcp750-vxworks/src/cfe_psp_support.c b/fsw/mcp750-vxworks/src/cfe_psp_support.c index 7d11a980..99d3080f 100644 --- a/fsw/mcp750-vxworks/src/cfe_psp_support.c +++ b/fsw/mcp750-vxworks/src/cfe_psp_support.c @@ -63,6 +63,18 @@ #include "cfe_psp.h" #include "cfe_psp_memory.h" +#include + +#define CFE_PSP_CPU_ID (GLOBAL_CONFIGDATA.Default_CpuId) +#define CFE_PSP_SPACECRAFT_ID (GLOBAL_CONFIGDATA.Default_SpacecraftId) + +/* + * Track the overall "reserved memory block" at the start of RAM. + * This single large block is then subdivided into separate areas for CFE use. + */ +extern CFE_PSP_MemoryBlock_t MCP750_ReservedMemBlock; + + /****************************************************************************** ** Function: CFE_PSP_Restart() ** @@ -81,14 +93,14 @@ void CFE_PSP_Restart(uint32 reset_type) if ( reset_type == CFE_PSP_RST_TYPE_POWERON ) { - CFE_PSP_ReservedMemoryPtr->bsp_reset_type = CFE_PSP_RST_TYPE_POWERON; - CFE_PSP_FlushCaches(1, (uint32 )CFE_PSP_ReservedMemoryPtr, sizeof(CFE_PSP_ReservedMemory_t)); + CFE_PSP_ReservedMemoryMap.BootPtr->bsp_reset_type = CFE_PSP_RST_TYPE_POWERON; + CFE_PSP_FlushCaches(1, MCP750_ReservedMemBlock.BlockPtr, MCP750_ReservedMemBlock.BlockSize); reboot(BOOT_CLEAR); } else { - CFE_PSP_ReservedMemoryPtr->bsp_reset_type = CFE_PSP_RST_TYPE_PROCESSOR; - CFE_PSP_FlushCaches(1, (uint32 )CFE_PSP_ReservedMemoryPtr, sizeof(CFE_PSP_ReservedMemory_t)); + CFE_PSP_ReservedMemoryMap.BootPtr->bsp_reset_type = CFE_PSP_RST_TYPE_PROCESSOR; + CFE_PSP_FlushCaches(1, MCP750_ReservedMemBlock.BlockPtr, MCP750_ReservedMemBlock.BlockSize); reboot(BOOT_NORMAL); } @@ -128,11 +140,11 @@ void CFE_PSP_Panic(int32 ErrorCode) ** (none) */ -void CFE_PSP_FlushCaches(uint32 type, uint32 address, uint32 size) +void CFE_PSP_FlushCaches(uint32 type, void* address, uint32 size) { if ( type == 1 ) { - cacheTextUpdate((void *)address, size); + cacheTextUpdate(address, size); } } @@ -156,7 +168,7 @@ void CFE_PSP_FlushCaches(uint32 type, uint32 address, uint32 size) */ uint32 CFE_PSP_GetProcessorId (void) { - return(CFE_PLATFORM_CPU_ID); + return CFE_PSP_CPU_ID; } @@ -177,6 +189,6 @@ uint32 CFE_PSP_GetProcessorId (void) */ uint32 CFE_PSP_GetSpacecraftId (void) { - return(CFE_MISSION_SPACECRAFT_ID); + return CFE_PSP_SPACECRAFT_ID; } diff --git a/fsw/pc-linux/inc/cfe_psp_config.h b/fsw/pc-linux/inc/cfe_psp_config.h index ac4e56de..8937a2dc 100644 --- a/fsw/pc-linux/inc/cfe_psp_config.h +++ b/fsw/pc-linux/inc/cfe_psp_config.h @@ -29,6 +29,9 @@ #include "common_types.h" +#include +#include +#include /* ** This define sets the number of memory ranges that are defined in the memory range defintion @@ -36,22 +39,94 @@ */ #define CFE_PSP_MEM_TABLE_SIZE 10 +/** + * This define sets the maximum number of exceptions + * that can be stored. + * + * It must always be a power of two. + */ +#define CFE_PSP_MAX_EXCEPTION_ENTRIES 4 +#define CFE_PSP_MAX_EXCEPTION_BACKTRACE_SIZE 16 + + +/* + * A random 32-bit value that is used as the "validity flag" + * of the PC-Linux boot record structure. This is simply + * a value that is unlikely to occur unless specifically set. + */ +#define CFE_PSP_BOOTRECORD_VALID ((uint32)0x2aebe984) +#define CFE_PSP_BOOTRECORD_INVALID (~CFE_PSP_BOOTRECORD_VALID) /* -** Processor Context type. -** This is needed to determine the size of the context entry in the ER log. -** Although this file is in a CPU directory, it really is OS dependant, so supporting -** multiple OSs on the same CPU architecture ( i.e. x86/linux, x86/windows, x86/osx ) -** will require IFDEFS. + * The amount of time to wait for an orderly shutdown + * in the event of a call to CFE_PSP_Restart() + * + * If this expires, then an abnormal exit/abort() is triggered. + */ +#define CFE_PSP_RESTART_DELAY 10000 + +/* use the "USR1" signal to wake the idle thread when an exception occurs */ +#define CFE_PSP_EXCEPTION_EVENT_SIGNAL SIGUSR1 + + +/* +** Global variables +*/ + +/* +** Typedef for the header structure on the reserved memory block +** +** Note that the structure below reserves memory sizes defined +** at compile time directly from cfe_platform_cfg.h above. +** A future enhancement should reserve blocks based on the runtime +** size in GLOBAL_CONFIGDATA. */ -typedef struct +typedef struct { - uint32 regs[32]; - -} CFE_PSP_ExceptionContext_t; + uint32 ValidityFlag; + uint32 NextResetType; -#define CFE_PSP_CPU_CONTEXT_SIZE (sizeof(CFE_PSP_ExceptionContext_t)) +} CFE_PSP_ReservedMemoryBootRecord_t; +/* + * The state of the PSP "idle task" + * + * This is the main/initial thread that runs early init, + * it is NOT an OSAL task. + * + * Once initialized, this thread goes idle and waits for + * asynchronous events to occur, and resumes with an orderly + * shutdown if requested. + */ +typedef struct +{ + pthread_t ThreadID; + volatile bool ShutdownReq; +} CFE_PSP_IdleTaskState_t; + + + +/** + * \brief The data type used by the underlying OS to represent a thread ID. + */ +typedef pthread_t CFE_PSP_Exception_SysTaskId_t; + +/** + * \brief Exception context data which is relevant for offline/post-mortem diagnosis. + * + * This may be stored in a persistent exception log file for later analysis. + */ +typedef struct +{ + struct timespec event_time; + siginfo_t si; + + /* + * Note this is a variably-filled array based on the number of addresses + * reported by the library. It should be last. + */ + void *bt_addrs[CFE_PSP_MAX_EXCEPTION_BACKTRACE_SIZE]; +} CFE_PSP_Exception_ContextDataEntry_t; /* ** Watchdog minimum and maximum values ( in milliseconds ) @@ -64,5 +139,11 @@ typedef struct */ #define CFE_PSP_NUM_EEPROM_BANKS 1 +/* + * Information about the "idle task" -- + * this is used by exception handling to wake it when an event occurs + */ +extern CFE_PSP_IdleTaskState_t CFE_PSP_IdleTaskState; + #endif diff --git a/fsw/pc-linux/src/cfe_psp_exception.c b/fsw/pc-linux/src/cfe_psp_exception.c index 5326a563..bf16fb5e 100644 --- a/fsw/pc-linux/src/cfe_psp_exception.c +++ b/fsw/pc-linux/src/cfe_psp_exception.c @@ -37,6 +37,7 @@ S */ #include #include +#include /* ** cFE includes @@ -45,89 +46,214 @@ S #include "osapi.h" #include "cfe_psp.h" #include "cfe_psp_config.h" +#include "cfe_psp_exceptionstorage.h" -#include - -#define CFE_PSP_ES_EXCEPTION_FUNCTION (*GLOBAL_CONFIGDATA.CfeConfig->SystemExceptionISR) +#include +#include /* -** Types and prototypes for this module -*/ + * A set of asynchronous signals which will be masked during other signal processing + */ +sigset_t CFE_PSP_AsyncMask; -/* -** PSP Specific defines -*/ -/* -** External Declarations -*/ -/* -** Global variables -*/ -CFE_PSP_ExceptionContext_t CFE_PSP_ExceptionContext; -char CFE_PSP_ExceptionReasonString[256]; +/*************************************************************************** + ** FUNCTIONS DEFINITIONS + ***************************************************************************/ + /* +** Name: CFE_PSP_ExceptionSigHandler ** -** Local Function Prototypes +** Installed as a signal handler to log exception events. ** */ +void CFE_PSP_ExceptionSigHandler (int signo, siginfo_t *si, void *ctxt) +{ + CFE_PSP_Exception_LogData_t* Buffer; + int NumAddrs; -void CFE_PSP_ExceptionHook ( int task_id, int vector, uint8 *pEsf ); - + /* + * Note that the time between CFE_PSP_Exception_GetNextContextBuffer() + * and CFE_PSP_Exception_WriteComplete() is sensitive in that it is + * accessing a global. + * + * Cannot use a conventional lock because this is a signal handler, the + * solution would need to involve a signal-safe spinlock and/or C11 + * atomic ops. + * + * This means if another exception occurs on another task during this + * time window, it may use the same buffer. + * + * However, exceptions should be rare enough events that this is highly + * unlikely to occur, so leaving this unhandled for now. + */ + Buffer = CFE_PSP_Exception_GetNextContextBuffer(); + if (Buffer != NULL) + { + /* + * read the clock as a timestamp - note "clock_gettime" is signal safe per POSIX, + * + * _not_ going through OSAL to read this as it may do something signal-unsafe... + * (current implementation would be safe, but it is not guaranteed to always be). + */ + clock_gettime(CLOCK_MONOTONIC, &Buffer->context_info.event_time); + memcpy(&Buffer->context_info.si, si, sizeof(Buffer->context_info.si)); + NumAddrs = backtrace(Buffer->context_info.bt_addrs, CFE_PSP_MAX_EXCEPTION_BACKTRACE_SIZE); + Buffer->context_size = offsetof(CFE_PSP_Exception_ContextDataEntry_t, bt_addrs[NumAddrs]); + /* pthread_self() is signal-safe per POSIX.1-2013 */ + Buffer->sys_task_id = pthread_self(); + CFE_PSP_Exception_WriteComplete(); + } -/*************************************************************************** - ** FUNCTION DEFINITIONS - ***************************************************************************/ + /* + * notify the main (idle) thread that an interesting event occurred. + * Note on this platform this cannot _directly_ invoke CFE from a signal handler. + */ + pthread_kill(CFE_PSP_IdleTaskState.ThreadID, CFE_PSP_EXCEPTION_EVENT_SIGNAL); +} /* +** Name: CFE_PSP_ExceptionSigHandlerSuspend ** -** Name: CFE_PSP_AttachExceptions +** An extension of CFE_PSP_ExceptionSigHandler that also +** suspends the calling task and prevents returning to the +** application. ** -** Purpose: This function Initializes the task execptions and adds a hook -** into the system exception handling. +** This is required for handling events like Floating Point exceptions, +** where returning to the application would resume at the same instruction +** and re-trigger the exception, resulting in a loop. ** */ +void CFE_PSP_ExceptionSigHandlerSuspend (int signo, siginfo_t *si, void *ctxt) +{ + /* + * Perform normal exception logging + */ + CFE_PSP_ExceptionSigHandler(signo, si, ctxt); -void CFE_PSP_AttachExceptions(void) + /* + * calling "sigsuspend" with an empty mask should + * block this thread indefinitely. This is intended + * to replicate the behavior of vxworks which suspends + * the task after an exception. + * + * This stops execution of the thread in anticipation that it + * will be deleted by the CFE/OSAL. + */ + sigsuspend(&CFE_PSP_AsyncMask); + +} /* end function */ + +/* + * Helper function to call sigaction() to attach a signal handler + */ +void CFE_PSP_AttachSigHandler (int signo) { - OS_printf("CFE_PSP: CFE_PSP_AttachExceptions Called\n"); + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_mask = CFE_PSP_AsyncMask; + + if(!sigismember(&CFE_PSP_AsyncMask, signo)) + { + /* + * In the event that the handler is being installed for one of the + * synchronous events, use the CFE_PSP_ExceptionSigHandlerSuspend variant. + * + * This suspends the caller and prevents returning to the application. + */ + sa.sa_sigaction = CFE_PSP_ExceptionSigHandlerSuspend; + /* + * add it back to the mask set. + * This is supposed to be default unless SA_NODEFER flag is set, + * but also setting it here to be sure. + */ + sigaddset(&sa.sa_mask, signo); + } + else + { + /* + * Use default handler which will return to the application + * after logging the event + */ + sa.sa_sigaction = CFE_PSP_ExceptionSigHandler; + } + sa.sa_flags = SA_SIGINFO; + + sigaction(signo, &sa, NULL); } + /* -** Name: CFE_PSP_ExceptionHook +** Name: CFE_PSP_AttachExceptions ** -** Purpose: Make the proper call to CFE_PSP_ES_EXCEPTION_FUNCTION (defined in -** cfe_es_platform.cfg) +** This is called from the CFE Main task, before any other threads +** are started. Use this opportunity to install the handler for +** CTRL+C events, which will now be treated as an exception. ** +** Not only does this clean up the code by NOT requiring a specific +** handler for CTRL+C, it also provides a way to exercise and test +** the exception handling in general, which tends to be infrequently +** invoked because otherwise it only happens with off nominal behavior. +** +** This has yet another benefit that SIGINT events will make their +** way into the exception and reset log, so it is visible why the +** CFE shut down. */ -void CFE_PSP_ExceptionHook (int task_id, int vector, uint8 *pEsf ) -{ - sprintf(CFE_PSP_ExceptionReasonString, "Processor Exception %d, task ID %d", vector, task_id); +void CFE_PSP_AttachExceptions(void) +{ + void *Addr[1]; /* - ** Save Exception Stack frame - */ - memcpy(&(CFE_PSP_ExceptionContext.regs), pEsf, (32*4)); + * preemptively call "backtrace" - + * The manpage notes that backtrace is implemented in libgcc + * which may be dynamically linked with lazy binding. So + * by calling it once we ensure that it is loaded and therefore + * it is safe to use in a signal handler. + */ + backtrace(Addr, 1); - /* - ** Call the Generic cFE routine to finish processing the exception and - ** restart the cFE - */ - CFE_PSP_ES_EXCEPTION_FUNCTION((uint32)task_id, CFE_PSP_ExceptionReasonString, - (uint32 *)&CFE_PSP_ExceptionContext, sizeof(CFE_PSP_ExceptionContext_t)); + OS_printf("CFE_PSP: CFE_PSP_AttachExceptions Called\n"); /* - ** No return to here - */ + * Block most other signals during handler execution. + * Exceptions are for synchronous errors SIGFPE/SIGSEGV/SIGILL/SIGBUS + */ + sigfillset(&CFE_PSP_AsyncMask); + sigdelset(&CFE_PSP_AsyncMask, SIGILL); + sigdelset(&CFE_PSP_AsyncMask, SIGFPE); + sigdelset(&CFE_PSP_AsyncMask, SIGBUS); + sigdelset(&CFE_PSP_AsyncMask, SIGSEGV); -} /* end function */ + /* + * Install sigint_handler as the signal handler for SIGINT. + * + * In the event that the user presses CTRL+C at the console + * this will be recorded as an exception and use the general + * purpose exception processing logic to shut down CFE. + * + * Also include SIGTERM so it will invoke a graceful shutdown + */ + CFE_PSP_AttachSigHandler(SIGINT); + CFE_PSP_AttachSigHandler(SIGTERM); + /* + * Clear any pending exceptions. + * + * This is just in case this is a PROCESSOR reset and there + * was something still in the queue from the last lifetime. + * + * It should have been logged already, but if not, then + * don't action on it now. + */ + CFE_PSP_Exception_Reset(); +} /* ** @@ -142,5 +268,76 @@ void CFE_PSP_ExceptionHook (int task_id, int vector, uint8 *pEsf ) void CFE_PSP_SetDefaultExceptionEnvironment(void) { - return; + /* + * This additionally sets a handler for SIGFPE which will catch arithmetic errors + * such as divide by zero. Other possibilities are SIGILL/SIGBUS/SIGSEGV. + * + * This is primarily used as a proof-of-concept on this platform to demonstrate + * how the exception handling feature works. + * + * As the PC-Linux platform is often used for debugging, it is better to + * maintain the default signal handler for the SIGILL/SIGBUS/SIGSEGV which will + * abort the program and generate a core file. + */ + CFE_PSP_AttachSigHandler(SIGFPE); +} + +int32 CFE_PSP_ExceptionGetSummary_Impl(const CFE_PSP_Exception_LogData_t* Buffer, char *ReasonBuf, uint32 ReasonSize) +{ + const char *ComputedReason = "unknown"; + + /* check the "code" within the siginfo structure, which reveals more info about the FP exception */ + if (Buffer->context_info.si.si_signo == SIGFPE) + { + switch(Buffer->context_info.si.si_code) + { + case FPE_INTDIV: + ComputedReason = "Integer divide by zero"; + break; + case FPE_INTOVF: + ComputedReason = "Integer overflow"; + break; + case FPE_FLTDIV: + ComputedReason = "Floating-point divide by zero"; + break; + case FPE_FLTOVF: + ComputedReason = "Floating-point overflow"; + break; + case FPE_FLTUND: + ComputedReason = "Floating-point underflow"; + break; + case FPE_FLTRES: + ComputedReason = "Floating-point inexact result"; + break; + case FPE_FLTINV: + ComputedReason = "Invalid floating-point operation"; + break; + case FPE_FLTSUB: + ComputedReason = "Subscript out of range"; + break; + default: + ComputedReason = "Unknown SIGFPE"; + } + (void)snprintf(ReasonBuf, ReasonSize, "%s at ip 0x%lx", ComputedReason, + (unsigned long)Buffer->context_info.si.si_addr); + + } + else if (Buffer->context_info.si.si_signo == SIGINT) + { + /* interrupt e.g. CTRL+C */ + (void)snprintf(ReasonBuf, ReasonSize, "Caught SIGINT"); + } + else + { + /* + * other signal.... + * POSIX 2008 does provide a strsignal() function to get the name, but this + * is a newer spec than what is targeted by CFE, so just print the number. + */ + (void)snprintf(ReasonBuf, ReasonSize, "Caught Signal %d",Buffer->context_info.si.si_signo); + } + + return CFE_PSP_SUCCESS; } + + diff --git a/fsw/pc-linux/src/cfe_psp_memory.c b/fsw/pc-linux/src/cfe_psp_memory.c index 6bb5072e..a1414ac7 100644 --- a/fsw/pc-linux/src/cfe_psp_memory.c +++ b/fsw/pc-linux/src/cfe_psp_memory.c @@ -62,6 +62,7 @@ ** PSP Specific defines */ #include "cfe_psp_config.h" +#include "cfe_psp_memory.h" #define CFE_PSP_CDS_KEY_FILE ".cdskeyfile" #define CFE_PSP_RESET_KEY_FILE ".resetkeyfile" @@ -77,13 +78,21 @@ #define CFE_PSP_RESET_AREA_SIZE (GLOBAL_CONFIGDATA.CfeConfig->ResetAreaSize) #define CFE_PSP_USER_RESERVED_SIZE (GLOBAL_CONFIGDATA.CfeConfig->UserReservedSize) + +typedef struct +{ + CFE_PSP_ReservedMemoryBootRecord_t BootRecord; + CFE_PSP_ExceptionStorage_t ExceptionStorage; +} CFE_PSP_LinuxReservedAreaFixedLayout_t; + + /* ** Internal prototypes for this module */ -int32 CFE_PSP_InitCDS(uint32 RestartType ); -int32 CFE_PSP_InitResetArea(uint32 RestartType); -int32 CFE_PSP_InitVolatileDiskMem(uint32 RestartType ); -int32 CFE_PSP_InitUserReservedArea(uint32 RestartType ); +void CFE_PSP_InitCDS(void); +void CFE_PSP_InitResetArea(void); +void CFE_PSP_InitVolatileDiskMem(void); +void CFE_PSP_InitUserReservedArea(void); /* ** External Declarations @@ -94,14 +103,16 @@ extern unsigned int _fini; /* ** Global variables */ -uint8 *CFE_PSP_CDSPtr = 0; -uint8 *CFE_PSP_ResetAreaPtr = 0; -uint8 *CFE_PSP_UserReservedAreaPtr = 0; int ResetAreaShmId; int CDSShmId; int UserShmId; - +/* +** Pointer to the vxWorks USER_RESERVED_MEMORY area +** The sizes of each memory area is defined in os_processor.h for this architecture. +*/ +CFE_PSP_ReservedMemoryMap_t CFE_PSP_ReservedMemoryMap; + /* ********************************************************************************* @@ -125,9 +136,8 @@ int UserShmId; ** (none) */ -int32 CFE_PSP_InitCDS(uint32 RestartType ) +void CFE_PSP_InitCDS(void) { - int32 return_code; key_t key; /* @@ -151,22 +161,14 @@ int32 CFE_PSP_InitCDS(uint32 RestartType ) /* ** attach to the segment to get a pointer to it: */ - CFE_PSP_CDSPtr = shmat(CDSShmId, (void *)0, 0); - if (CFE_PSP_CDSPtr == (uint8 *)(-1)) + CFE_PSP_ReservedMemoryMap.CDSMemory.BlockPtr = shmat(CDSShmId, (void *)0, 0); + if (CFE_PSP_ReservedMemoryMap.CDSMemory.BlockPtr == (void*)(-1)) { OS_printf("CFE_PSP: Cannot shmat to CDS Shared memory Segment!\n"); exit(-1); } - if ( RestartType == CFE_PSP_RST_TYPE_POWERON ) - { - OS_printf("CFE_PSP: Clearing out CFE CDS Shared memory segment.\n"); - memset(CFE_PSP_CDSPtr, 0, CFE_PSP_CDS_SIZE); - } - - return_code = CFE_PSP_SUCCESS; - return(return_code); - + CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize = CFE_PSP_CDS_SIZE; } @@ -192,12 +194,12 @@ void CFE_PSP_DeleteCDS(void) if ( ReturnCode == 0 ) { - printf("CFE_PSP: Critical Data Store Shared memory segment removed\n"); + OS_printf("CFE_PSP: Critical Data Store Shared memory segment removed\n"); } else { - printf("CFE_PSP: Error Removing Critical Data Store Shared memory Segment.\n"); - printf("CFE_PSP: It can be manually checked and removed using the ipcs and ipcrm commands.\n"); + OS_printf("CFE_PSP: Error Removing Critical Data Store Shared memory Segment.\n"); + OS_printf("CFE_PSP: It can be manually checked and removed using the ipcs and ipcrm commands.\n"); } @@ -259,10 +261,11 @@ int32 CFE_PSP_WriteToCDS(const void *PtrToDataToWrite, uint32 CDSOffset, uint32 { if ( (CDSOffset < CFE_PSP_CDS_SIZE ) && ( (CDSOffset + NumBytes) <= CFE_PSP_CDS_SIZE )) { - CopyPtr = &(CFE_PSP_CDSPtr[CDSOffset]); - memcpy(CopyPtr, (char *)PtrToDataToWrite,NumBytes); + CopyPtr = CFE_PSP_ReservedMemoryMap.CDSMemory.BlockPtr; + CopyPtr += CDSOffset; + memcpy(CopyPtr, (char *)PtrToDataToWrite,NumBytes); - return_code = CFE_PSP_SUCCESS; + return_code = CFE_PSP_SUCCESS; } else { @@ -302,10 +305,11 @@ int32 CFE_PSP_ReadFromCDS(void *PtrToDataToRead, uint32 CDSOffset, uint32 NumByt { if ( (CDSOffset < CFE_PSP_CDS_SIZE ) && ( (CDSOffset + NumBytes) <= CFE_PSP_CDS_SIZE )) { - CopyPtr = &(CFE_PSP_CDSPtr[CDSOffset]); - memcpy((char *)PtrToDataToRead,CopyPtr, NumBytes); + CopyPtr = CFE_PSP_ReservedMemoryMap.CDSMemory.BlockPtr; + CopyPtr += CDSOffset; + memcpy((char *)PtrToDataToRead,CopyPtr, NumBytes); - return_code = CFE_PSP_SUCCESS; + return_code = CFE_PSP_SUCCESS; } else { @@ -337,12 +341,15 @@ int32 CFE_PSP_ReadFromCDS(void *PtrToDataToRead, uint32 CDSOffset, uint32 NumByt ** Return: ** (none) */ -int32 CFE_PSP_InitResetArea(uint32 RestartType) +void CFE_PSP_InitResetArea(void) { - int32 return_code; key_t key; - + size_t total_size; + size_t reset_offset; + size_t align_mask; + cpuaddr block_addr; + CFE_PSP_LinuxReservedAreaFixedLayout_t *FixedBlocksPtr; /* ** Make the Shared memory key */ @@ -352,10 +359,23 @@ int32 CFE_PSP_InitResetArea(uint32 RestartType) exit(-1); } + /* + * NOTE: Historically the CFE ES reset area also contains the Exception log. + * This is now allocated as a separate structure in the PSP, but it can + * reside in this shared memory segment so it will be preserved on a processor + * reset. + */ + align_mask = sysconf(_SC_PAGESIZE) - 1; /* align blocks to whole memory pages */ + total_size = sizeof(CFE_PSP_LinuxReservedAreaFixedLayout_t); + total_size = (total_size + align_mask) & ~align_mask; + reset_offset = total_size; + total_size += CFE_PSP_RESET_AREA_SIZE; + total_size = (total_size + align_mask) & ~align_mask; + /* ** connect to (and possibly create) the segment: */ - if ((ResetAreaShmId = shmget(key, CFE_PSP_RESET_AREA_SIZE, 0644 | IPC_CREAT)) == -1) + if ((ResetAreaShmId = shmget(key, total_size, 0644 | IPC_CREAT)) == -1) { OS_printf("CFE_PSP: Cannot shmget Reset Area Shared memory Segment!\n"); exit(-1); @@ -364,21 +384,21 @@ int32 CFE_PSP_InitResetArea(uint32 RestartType) /* ** attach to the segment to get a pointer to it: */ - CFE_PSP_ResetAreaPtr = shmat(ResetAreaShmId, (void *)0, 0); - if (CFE_PSP_ResetAreaPtr == (uint8 *)(-1)) + block_addr = (cpuaddr)shmat(ResetAreaShmId, (void *)0, 0); + if (block_addr == (cpuaddr)(-1)) { OS_printf("CFE_PSP: Cannot shmat to Reset Area Shared memory Segment!\n"); exit(-1); } - if ( RestartType == CFE_PSP_RST_TYPE_POWERON ) - { - OS_printf("CFE_PSP: Clearing out CFE Reset Shared memory segment.\n"); - memset(CFE_PSP_ResetAreaPtr, 0, CFE_PSP_RESET_AREA_SIZE); - } - - return_code = CFE_PSP_SUCCESS; - return(return_code); + FixedBlocksPtr = (CFE_PSP_LinuxReservedAreaFixedLayout_t *)block_addr; + block_addr += reset_offset; + + CFE_PSP_ReservedMemoryMap.BootPtr = &FixedBlocksPtr->BootRecord; + CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr = &FixedBlocksPtr->ExceptionStorage; + + CFE_PSP_ReservedMemoryMap.ResetMemory.BlockPtr = (void*)block_addr; + CFE_PSP_ReservedMemoryMap.ResetMemory.BlockSize = CFE_PSP_RESET_AREA_SIZE; } @@ -403,12 +423,12 @@ void CFE_PSP_DeleteResetArea(void) if ( ReturnCode == 0 ) { - printf("Reset Area Shared memory segment removed\n"); + OS_printf("Reset Area Shared memory segment removed\n"); } else { - printf("Error Removing Reset Area Shared memory Segment.\n"); - printf("It can be manually checked and removed using the ipcs and ipcrm commands.\n"); + OS_printf("Error Removing Reset Area Shared memory Segment.\n"); + OS_printf("It can be manually checked and removed using the ipcs and ipcrm commands.\n"); } @@ -441,8 +461,8 @@ int32 CFE_PSP_GetResetArea (cpuaddr *PtrToResetArea, uint32 *SizeOfResetArea) } else { - *PtrToResetArea = (cpuaddr)CFE_PSP_ResetAreaPtr; - *SizeOfResetArea = CFE_PSP_RESET_AREA_SIZE; + *PtrToResetArea = (cpuaddr)CFE_PSP_ReservedMemoryMap.ResetMemory.BlockPtr; + *SizeOfResetArea = CFE_PSP_ReservedMemoryMap.ResetMemory.BlockSize; return_code = CFE_PSP_SUCCESS; } @@ -468,9 +488,8 @@ int32 CFE_PSP_GetResetArea (cpuaddr *PtrToResetArea, uint32 *SizeOfResetArea) ** Return: ** (none) */ -int32 CFE_PSP_InitUserReservedArea(uint32 RestartType ) +void CFE_PSP_InitUserReservedArea(void) { - int32 return_code; key_t key; /* @@ -494,22 +513,14 @@ int32 CFE_PSP_InitUserReservedArea(uint32 RestartType ) /* ** attach to the segment to get a pointer to it: */ - CFE_PSP_UserReservedAreaPtr = shmat(UserShmId, (void *)0, 0); - if (CFE_PSP_UserReservedAreaPtr == (uint8 *)(-1)) + CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockPtr = shmat(UserShmId, (void *)0, 0); + if (CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockPtr == (void*)(-1)) { OS_printf("CFE_PSP: Cannot shmat to User Reserved Area Shared memory Segment!\n"); exit(-1); } - if ( RestartType == CFE_PSP_RST_TYPE_POWERON ) - { - OS_printf("CFE_PSP: Clearing out CFE User Reserved Shared memory segment.\n"); - memset(CFE_PSP_UserReservedAreaPtr, 0, CFE_PSP_USER_RESERVED_SIZE); - } - - return_code = CFE_PSP_SUCCESS; - return(return_code); - + CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockSize = CFE_PSP_USER_RESERVED_SIZE; } /****************************************************************************** @@ -533,12 +544,12 @@ void CFE_PSP_DeleteUserReservedArea(void) if ( ReturnCode == 0 ) { - printf("User Reserved Area Shared memory segment removed\n"); + OS_printf("User Reserved Area Shared memory segment removed\n"); } else { - printf("Error Removing User Reserved Area Shared memory Segment.\n"); - printf("It can be manually checked and removed using the ipcs and ipcrm commands.\n"); + OS_printf("Error Removing User Reserved Area Shared memory Segment.\n"); + OS_printf("It can be manually checked and removed using the ipcs and ipcrm commands.\n"); } } @@ -566,8 +577,8 @@ int32 CFE_PSP_GetUserReservedArea(cpuaddr *PtrToUserArea, uint32 *SizeOfUserArea } else { - *PtrToUserArea = (cpuaddr)(&CFE_PSP_UserReservedAreaPtr); - *SizeOfUserArea = CFE_PSP_USER_RESERVED_SIZE; + *PtrToUserArea = (cpuaddr)CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockPtr; + *SizeOfUserArea = CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockSize; return_code = CFE_PSP_SUCCESS; } @@ -594,18 +605,12 @@ int32 CFE_PSP_GetUserReservedArea(cpuaddr *PtrToUserArea, uint32 *SizeOfUserArea ** Return: ** (none) */ -int32 CFE_PSP_InitVolatileDiskMem(uint32 RestartType ) +void CFE_PSP_InitVolatileDiskMem(void) { - int32 return_code; - /* ** Here, we want to clear out the volatile ram disk contents ** on a power on reset */ - - return_code = CFE_PSP_SUCCESS; - return(return_code); - } /****************************************************************************** @@ -631,8 +636,8 @@ int32 CFE_PSP_GetVolatileDiskMem(cpuaddr *PtrToVolDisk, uint32 *SizeOfVolDisk ) } else { - *PtrToVolDisk = 0; - *SizeOfVolDisk = 0; + *PtrToVolDisk = (cpuaddr)CFE_PSP_ReservedMemoryMap.VolatileDiskMemory.BlockPtr; + *SizeOfVolDisk = CFE_PSP_ReservedMemoryMap.VolatileDiskMemory.BlockSize; return_code = CFE_PSP_SUCCESS; } @@ -658,9 +663,8 @@ int32 CFE_PSP_GetVolatileDiskMem(cpuaddr *PtrToVolDisk, uint32 *SizeOfVolDisk ) ** Return: ** (none) */ -int32 CFE_PSP_InitProcessorReservedMemory( uint32 RestartType ) +void CFE_PSP_SetupReservedMemoryMap(void) { - int32 return_code; int tempFd; /* @@ -673,41 +677,72 @@ int32 CFE_PSP_InitProcessorReservedMemory( uint32 RestartType ) close(tempFd); tempFd = open(CFE_PSP_RESERVED_KEY_FILE, O_RDONLY | O_CREAT, S_IRWXU ); close(tempFd); - - - return_code = CFE_PSP_InitCDS( RestartType ); - if (return_code != CFE_PSP_SUCCESS) - { - OS_printf("CFE_PSP_InitCDS didn't return success (%d)\n", return_code); - - return(return_code); - } - - return_code = CFE_PSP_InitResetArea( RestartType ); - if (return_code != CFE_PSP_SUCCESS) - { - OS_printf("CFE_PSP_InitResetArea didn't return success (%d)\n", return_code); - return(return_code); - } - - return_code = CFE_PSP_InitVolatileDiskMem( RestartType ); - if (return_code != CFE_PSP_SUCCESS) - { - OS_printf("CFE_PSP_InitVolatileDiskMem didn't return success (%d)\n", return_code); - - return(return_code); - } - - return_code = CFE_PSP_InitUserReservedArea( RestartType ); - if (return_code != CFE_PSP_SUCCESS) - { - OS_printf("CFE_PSP_InitVolatileDiskMem didn't return success (%d)\n", return_code); + /* + * The setup of each section is done as a separate init. + * + * Any failures within these routines call exit(), so there + * is no need to check status - failure means no return. + */ + + CFE_PSP_InitCDS(); + CFE_PSP_InitResetArea(); + CFE_PSP_InitVolatileDiskMem(); + CFE_PSP_InitUserReservedArea(); +} - return(return_code); - } +int32 CFE_PSP_InitProcessorReservedMemory( uint32 RestartType ) +{ - return(return_code); + /* + * Clear the segments only on a POWER ON reset + * + * Newly-created segments should already be zeroed out, + * but this ensures it. + */ + if ( RestartType == CFE_PSP_RST_TYPE_POWERON ) + { + OS_printf("CFE_PSP: Clearing out CFE CDS Shared memory segment.\n"); + memset(CFE_PSP_ReservedMemoryMap.CDSMemory.BlockPtr, 0, CFE_PSP_CDS_SIZE); + OS_printf("CFE_PSP: Clearing out CFE Reset Shared memory segment.\n"); + memset(CFE_PSP_ReservedMemoryMap.ResetMemory.BlockPtr, 0, CFE_PSP_RESET_AREA_SIZE); + OS_printf("CFE_PSP: Clearing out CFE User Reserved Shared memory segment.\n"); + memset(CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockPtr, 0, CFE_PSP_USER_RESERVED_SIZE); + + memset(CFE_PSP_ReservedMemoryMap.BootPtr, 0, sizeof(*CFE_PSP_ReservedMemoryMap.BootPtr)); + memset(CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr, 0, sizeof(*CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr)); + + /* + * If an unclean shutdown occurs, try to do a PROCESSOR reset next. + * This will attempt to preserve the exception and reset log content. + */ + CFE_PSP_ReservedMemoryMap.BootPtr->NextResetType = CFE_PSP_RST_TYPE_PROCESSOR; + } + else + { + /* + * If an unclean shutdown occurs after a PROCESSOR reset, then next time should + * be a POWERON reset. + */ + CFE_PSP_ReservedMemoryMap.BootPtr->NextResetType = CFE_PSP_RST_TYPE_POWERON; + } + + /* + * Reset the boot record validity flag (always). + * + * If an unclean shutdown occurs, such as a software crash or abort, this + * will remain in the shm structure and it can be detected at startup. + * + * This can be used to differentiate between an intentional and unintentional + * processor reset. + * + * If a directed shutdown occurs (via CFE_PSP_Restart) then this + * is overwritten with the valid value. + */ + CFE_PSP_ReservedMemoryMap.BootPtr->ValidityFlag = CFE_PSP_BOOTRECORD_INVALID; + + + return(CFE_PSP_SUCCESS); } /****************************************************************************** diff --git a/fsw/pc-linux/src/cfe_psp_start.c b/fsw/pc-linux/src/cfe_psp_start.c index b2cc804c..732d1cd8 100644 --- a/fsw/pc-linux/src/cfe_psp_start.c +++ b/fsw/pc-linux/src/cfe_psp_start.c @@ -54,6 +54,7 @@ #include "osapi.h" #include "cfe_psp.h" +#include "cfe_psp_memory.h" /* * The preferred way to obtain the CFE tunable values at runtime is via @@ -106,17 +107,11 @@ typedef struct /* ** Prototypes for this module */ -void CFE_PSP_SigintHandler (int signal); void CFE_PSP_TimerHandler (int signum); void CFE_PSP_DisplayUsage(char *Name ); void CFE_PSP_ProcessArgumentDefaults(CFE_PSP_CommandData_t *CommandDataDefault); void CFE_PSP_SetupLocal1Hz(void); -/* -** External Declarations -*/ -extern void CFE_PSP_DeleteProcessorReservedMemory(void); - /* ** Global variables */ @@ -126,6 +121,8 @@ uint32 CFE_PSP_SpacecraftId; uint32 CFE_PSP_CpuId; char CFE_PSP_CpuName[CFE_PSP_CPU_NAME_LENGTH]; +CFE_PSP_IdleTaskState_t CFE_PSP_IdleTaskState; + /* ** getopts parameter passing options string */ @@ -144,7 +141,7 @@ static const struct option longOpts[] = { { NULL, no_argument, NULL, 0 } }; - + /****************************************************************************** ** Function: main() ** @@ -173,7 +170,7 @@ void OS_Application_Startup(void) ** Initialize the CommandData struct */ memset(&(CommandData), 0, sizeof(CFE_PSP_CommandData_t)); - + /* ** Process the arguments with getopt_long(), then ** start the cFE @@ -249,20 +246,6 @@ void OS_Application_Startup(void) */ CFE_PSP_ProcessArgumentDefaults(&CommandData); - /* - ** Set the reset type - */ - if (strncmp("PR", CommandData.ResetType, 2 ) == 0 ) - { - reset_type = CFE_PSP_RST_TYPE_PROCESSOR; - printf("CFE_PSP: Starting the cFE with a PROCESSOR reset.\n"); - } - else - { - reset_type = CFE_PSP_RST_TYPE_POWERON; - printf("CFE_PSP: Starting the cFE with a POWER ON reset.\n"); - } - /* ** Assign the Spacecraft ID, CPU ID, and CPU Name */ @@ -275,10 +258,6 @@ void OS_Application_Startup(void) */ reset_subtype = CommandData.SubType; - /* - ** Install sigint_handler as the signal handler for SIGINT. - */ - signal(SIGINT, CFE_PSP_SigintHandler); /* ** Initialize the OS API data structures @@ -292,6 +271,17 @@ void OS_Application_Startup(void) CFE_PSP_Panic(Status); } + /* + * Map the PSP shared memory segments + */ + CFE_PSP_SetupReservedMemoryMap(); + + /* + * Prepare for exception handling in the idle task + */ + memset(&CFE_PSP_IdleTaskState, 0, sizeof(CFE_PSP_IdleTaskState)); + CFE_PSP_IdleTaskState.ThreadID = pthread_self(); + /* ** Set up the timebase, if OSAL supports it ** Done here so that the modules can also use it, if desired @@ -336,6 +326,48 @@ void OS_Application_Startup(void) sleep(1); + /* + * For informational purposes, show the state of the last exit + */ + if (CFE_PSP_ReservedMemoryMap.BootPtr->ValidityFlag == CFE_PSP_BOOTRECORD_VALID) + { + OS_printf("CFE_PSP: Normal exit from previous cFE instance\n"); + } + else if (CFE_PSP_ReservedMemoryMap.BootPtr->ValidityFlag == CFE_PSP_BOOTRECORD_INVALID) + { + OS_printf("CFE_PSP: Abnormal exit from previous cFE instance\n"); + } + + /* + * determine reset type... + * If not specified at the command line, then check the "boot record" + */ + reset_type = 0; + if (!CommandData.GotResetType) + { + if (CFE_PSP_ReservedMemoryMap.BootPtr->ValidityFlag == CFE_PSP_BOOTRECORD_VALID || + CFE_PSP_ReservedMemoryMap.BootPtr->ValidityFlag == CFE_PSP_BOOTRECORD_INVALID) + { + reset_type = CFE_PSP_ReservedMemoryMap.BootPtr->NextResetType; + } + } + else if (strncmp("PR", CommandData.ResetType, 2 ) == 0 ) + { + reset_type = CFE_PSP_RST_TYPE_PROCESSOR; + } + + if (reset_type == CFE_PSP_RST_TYPE_PROCESSOR) + { + OS_printf("CFE_PSP: Starting the cFE with a PROCESSOR reset.\n"); + } + else + { + /* catch-all for anything else */ + reset_type = CFE_PSP_RST_TYPE_POWERON; + OS_printf("CFE_PSP: Starting the cFE with a POWER ON reset.\n"); + } + + /* ** Initialize the reserved memory */ @@ -364,45 +396,62 @@ void OS_Application_Startup(void) void OS_Application_Run(void) { - /* - ** Let the main thread sleep. - ** - ** OS_IdleLoop() will wait forever and return if - ** someone calls OS_ApplicationShutdown(true) - */ - OS_IdleLoop(); + int sig; + int ret; + sigset_t sigset; - /* - * The only way OS_IdleLoop() will return is if SIGINT is captured - * Handle cleanup duties. - */ - OS_printf("\nCFE_PSP: Control-C Captured - Exiting cFE\n"); - /* Deleting these memories will unlink them, but active references should still work */ - CFE_PSP_DeleteProcessorReservedMemory(); + /* + * Now that all main tasks are created, + * this original thread will exist just to service signals + * that aren't directed to a specific task. + * + * OSAL sets a very conservative signal mask that + * blocks most signals. Start by unblocking the + * ones that should be handled. + * + * Unblock SIGQUIT so the user can force exit the CFE + * by pressing CTRL+\ (default handler). Also allow + * SIGTERM for which a handler was installed in CFE_PSP_AttachExceptions() + */ + sigemptyset(&sigset); + sigaddset(&sigset, SIGQUIT); + sigaddset(&sigset, SIGTERM); + pthread_sigmask(SIG_UNBLOCK, &sigset, NULL); - OS_printf("CFE_PSP: NOTE: After quitting the cFE with a Control-C signal, it MUST be started next time\n"); - OS_printf(" with a Poweron Reset ( --reset PO ). \n"); + /* + * Reset to the signal for background events (SIGUSR1) + */ + sigemptyset(&sigset); + sigaddset(&sigset, CFE_PSP_EXCEPTION_EVENT_SIGNAL); - OS_DeleteAllObjects(); -} + /* + ** just wait for events to occur and notify CFE + ** + ** "shutdownreq" will become true if CFE calls CFE_PSP_Restart(), + ** indicating a request to gracefully exit and restart CFE. + */ + while (!CFE_PSP_IdleTaskState.ShutdownReq) + { + /* go idle and wait for an event */ + ret = sigwait(&sigset, &sig); -/****************************************************************************** -** Function: CFE_PSP_SigintHandler() -** -** Purpose: -** SIGINT routine for linux/OSX -** -** Arguments: -** (none) -** -** Return: -** (none) -*/ + if (ret == 0 && !CFE_PSP_IdleTaskState.ShutdownReq && + sig == CFE_PSP_EXCEPTION_EVENT_SIGNAL && + GLOBAL_CFE_CONFIGDATA.SystemNotify != NULL) + { + /* notify the CFE of the event */ + GLOBAL_CFE_CONFIGDATA.SystemNotify(); + } + } -void CFE_PSP_SigintHandler (int signal) -{ - OS_ApplicationShutdown(true); + /* + * This happens if an unhandled exception occurs, or if the user presses CTRL+C + */ + OS_printf("\nCFE_PSP: Shutdown initiated - Exiting cFE\n"); + OS_TaskDelay(100); + + OS_DeleteAllObjects(); } /****************************************************************************** @@ -491,13 +540,6 @@ void CFE_PSP_DisplayUsage(char *Name ) */ void CFE_PSP_ProcessArgumentDefaults(CFE_PSP_CommandData_t *CommandDataDefault) { - if ( CommandDataDefault->GotResetType == 0 ) - { - strncpy(CommandDataDefault->ResetType, "PO", sizeof(CommandDataDefault->ResetType) ); - printf("CFE_PSP: Default Reset Type = PO\n"); - CommandDataDefault->GotResetType = 1; - } - if ( CommandDataDefault->GotSubType == 0 ) { CommandDataDefault->SubType = 1; diff --git a/fsw/pc-linux/src/cfe_psp_support.c b/fsw/pc-linux/src/cfe_psp_support.c index db9bbb01..be884a83 100644 --- a/fsw/pc-linux/src/cfe_psp_support.c +++ b/fsw/pc-linux/src/cfe_psp_support.c @@ -36,9 +36,6 @@ #include #include -/* -** cFE includes -*/ #include "common_types.h" #include "osapi.h" @@ -46,6 +43,9 @@ ** Types and prototypes for this module */ #include "cfe_psp.h" +#include "cfe_psp_config.h" +#include "cfe_psp_memory.h" + /* ** External Variables @@ -69,22 +69,53 @@ extern uint32 CFE_PSP_CpuId; void CFE_PSP_Restart(uint32 reset_type) { - if ( reset_type == CFE_PSP_RST_TYPE_POWERON ) { OS_printf("CFE_PSP: Exiting cFE with POWERON Reset status.\n"); - OS_printf("CFE_PSP: Start the cFE Core with the PO parameter to complete the Power On Reset\n"); - OS_printf("CFE_PSP: When the Power On Reset is completed, the Shared Memroy segments will be CLEARED\n"); - exit(CFE_PSP_RST_TYPE_POWERON); + + /* Also delete the SHM segments, so they will be recreated on next boot */ + /* Deleting these memories will unlink them, but active references should still work */ + CFE_PSP_DeleteProcessorReservedMemory(); } else { OS_printf("CFE_PSP: Exiting cFE with PROCESSOR Reset status.\n"); - OS_printf("CFE_PSP: Shared Memory segments have been PRESERVED.\n"); - OS_printf("CFE_PSP: Restart the cFE with the PR parameter to complete the Processor Reset.\n"); - exit(CFE_PSP_RST_TYPE_PROCESSOR); } + /* + * Record the reset type for the next boot. + */ + CFE_PSP_ReservedMemoryMap.BootPtr->NextResetType = reset_type; + CFE_PSP_ReservedMemoryMap.BootPtr->ValidityFlag = CFE_PSP_BOOTRECORD_VALID; + + /* + * Begin process of orderly shutdown. + * + * This should cause the original thread (main task) to wake up + * and start the shutdown procedure. + */ + CFE_PSP_IdleTaskState.ShutdownReq = true; + pthread_kill(CFE_PSP_IdleTaskState.ThreadID, CFE_PSP_EXCEPTION_EVENT_SIGNAL); + + /* + * Give time for the orderly shutdown to occur. + * + * Normally during shutdown this task will be deleted, and therefore + * this does not return. + * + * However, if problems occur (e.g. deadlock) eventually this timeout + * will expire and return. + */ + OS_TaskDelay(CFE_PSP_RESTART_DELAY); + + /* + * Timeout expired without this task being deleted, so abort(). + * + * This should generate a core file to reveal what went wrong + * with normal shutdown. + */ + abort(); + } /****************************************************************************** @@ -105,7 +136,7 @@ void CFE_PSP_Panic(int32 ErrorCode) { OS_printf("CFE_PSP_Panic Called with error code = 0x%08X. Exiting.\n",(unsigned int)ErrorCode); OS_printf("The cFE could not start.\n"); - exit(-1); + abort(); /* abort() is preferable to exit(-1), as it may create a core file for debug */ } @@ -122,7 +153,7 @@ void CFE_PSP_Panic(int32 ErrorCode) ** Return: ** (none) */ -void CFE_PSP_FlushCaches(uint32 type, cpuaddr address, uint32 size) +void CFE_PSP_FlushCaches(uint32 type, void* address, uint32 size) { printf("CFE_PSP_FlushCaches called -- Currently no Linux/OSX/Cygwin implementation\n"); } diff --git a/fsw/pc-rtems/inc/cfe_psp_config.h b/fsw/pc-rtems/inc/cfe_psp_config.h index 7fd7bc41..176f941e 100644 --- a/fsw/pc-rtems/inc/cfe_psp_config.h +++ b/fsw/pc-rtems/inc/cfe_psp_config.h @@ -29,7 +29,7 @@ #include "common_types.h" - +#include /* ** This define sets the number of memory ranges that are defined in the memory range defintion @@ -37,21 +37,43 @@ */ #define CFE_PSP_MEM_TABLE_SIZE 10 +/** + * This define sets the maximum number of exceptions + * that can be stored. + * + * It must always be a power of two. + */ +#define CFE_PSP_MAX_EXCEPTION_ENTRIES 1 + /* -** Processor Context type. -** This is needed to determine the size of the context entry in the ER log. -** Although this file is in a CPU directory, it really is OS dependant, so supporting -** multiple OSs on the same CPU architecture ( i.e. x86/linux, x86/windows, x86/osx ) -** will require IFDEFS. +** Typedef for the layout of the header in the reserved memory block */ -typedef struct +typedef struct { - uint32 registers[32]; /* TBD for coldfire */ - -} CFE_PSP_ExceptionContext_t; - -#define CFE_PSP_CPU_CONTEXT_SIZE (sizeof(CFE_PSP_ExceptionContext_t)) + /* not currently used in PC-RTEMS */ + uint32 reserved; + +} CFE_PSP_ReservedMemoryBootRecord_t; + + +/** + * \brief The data type used by the underlying OS to represent a thread ID. + */ +typedef rtems_id CFE_PSP_Exception_SysTaskId_t; + +/** + * \brief Exception context data which is relevant for offline/post-mortem diagnosis. + * + * This may be stored in a persistent exception log file for later analysis. + * + * On PC-RTEMS, this is reserved for future use. Exception handling is not + * currently implemented. + */ +typedef struct +{ + uint32 reserved; /* prevent empty structure */ +} CFE_PSP_Exception_ContextDataEntry_t; /* @@ -65,6 +87,17 @@ typedef struct */ #define CFE_PSP_NUM_EEPROM_BANKS 1 +/* + * The alignment to use for each reserved memory block. + * + * This is a mask to be applied to each block base address + * + * Using 128 bytes as this is the cache line size of many + * modern processors. + */ +#define CFE_PSP_MEMALIGN_MASK ((cpuaddr)0x7F) + + #endif diff --git a/fsw/pc-rtems/src/cfe_psp_exception.c b/fsw/pc-rtems/src/cfe_psp_exception.c index 7e973b76..0178555f 100644 --- a/fsw/pc-rtems/src/cfe_psp_exception.c +++ b/fsw/pc-rtems/src/cfe_psp_exception.c @@ -46,45 +46,15 @@ #include "cfe_psp.h" #include "cfe_psp_config.h" - -#include "cfe_psp_memory.h" - -/* -** Types and prototypes for this module -*/ - - -/* -** BSP Specific defines -*/ +#include "cfe_psp_memory.h" +#include "cfe_psp_exceptionstorage.h" -/* -** External Declarations -*/ - -/* -** Global variables -*/ - -CFE_PSP_ExceptionContext_t CFE_PSP_ExceptionContext; -char CFE_PSP_ExceptionReasonString[256]; - -/* -** -** IMPORTED FUNCTIONS -** -*/ - -void CFE_ES_ProcessCoreException(uint32 HostTaskId, uint8 *ReasonString, - uint32 *ContextPointer, uint32 ContextSize); - /* ** ** LOCAL FUNCTION PROTOTYPES ** */ -void CFE_PSP_ExceptionHook (int task_id, int vector, int32 *pEsf ); /*************************************************************************** ** FUNCTIONS DEFINITIONS @@ -92,68 +62,28 @@ void CFE_PSP_ExceptionHook (int task_id, int vector, int32 *pEsf ); /* ** -** Name: OS_BSPAttachExceptions -** -** Purpose: This function Initializes the task execptions and adds a hook -** into the VxWorks exception handling. The below hook is called -** for every exception that VxWorks catches. -** -** Notes: if desired - to attach a custom handler put following code in -** this function: excConnect ((VOIDFUNCPTR*)VECTOR, ExceptionHandler); +** Name: CFE_PSP_AttachExceptions +** +** Purpose: No-op on this platform, implemented for API compatibility. ** */ - void CFE_PSP_AttachExceptions(void) { - OS_printf("CFE PSP: Attached cFE Exception Handler. Context Size = %d bytes.\n",(int)CFE_PSP_CPU_CONTEXT_SIZE); + OS_printf("CFE_PSP: CFE_PSP_AttachExceptions Called\n"); + CFE_PSP_Exception_Reset(); } - /* -** Name: CFE_PSP_ExceptionHook -** -** Purpose: Make the proper call to CFE_ES_ProcessCoreException -** -** Notes: pEsf - pointer to exception stack frame. -** fppSave - When it makes this call, it captures the last floating -** point context - which may not be valid. If a floating -** point exception occurs you can be almost 100% sure -** that this will reflect the proper context. But if another -** type of exception occurred then this has the possibility -** of not being valid. Specifically if a task that is not -** enabled for floating point causes a non-floating point -** exception, then the meaning of the floating point context -** will not be valid. If the task is enabled for floating point, -** then it will be valid. -** -*/ -void CFE_PSP_ExceptionHook (int task_id, int vector, int32 *pEsf ) + * Name: CFE_PSP_ExceptionGetSummary_Impl + * + * Purpose: Translate a stored exception log entry into a summary string + */ +int32 CFE_PSP_ExceptionGetSummary_Impl(const CFE_PSP_Exception_LogData_t* Buffer, char *ReasonBuf, uint32 ReasonSize) { + /* exceptions are not yet implemented on this platform */ + return CFE_PSP_ERROR_NOT_IMPLEMENTED; +} - sprintf(CFE_PSP_ExceptionReasonString, "Not Implemented"); - - /* - ** Save Exception Stack frame - */ - memcpy(&(CFE_PSP_ExceptionContext.registers), pEsf, sizeof(CFE_PSP_ExceptionContext_t)); - - /* - ** Save floating point registers - */ - /* fppSave(&OS_ExceptionContext.fp); */ - - /* - ** Call the Generic cFE routine to finish processing the exception and - ** restart the cFE - */ - CFE_ES_ProcessCoreException((uint32)task_id, (uint8 *)CFE_PSP_ExceptionReasonString, - (uint32 *)&CFE_PSP_ExceptionContext, sizeof(CFE_PSP_ExceptionContext_t)); - - /* - ** No return to here - */ - -} /* end function */ /* diff --git a/fsw/pc-rtems/src/cfe_psp_memory.c b/fsw/pc-rtems/src/cfe_psp_memory.c index c976ba82..dc2135c3 100644 --- a/fsw/pc-rtems/src/cfe_psp_memory.c +++ b/fsw/pc-rtems/src/cfe_psp_memory.c @@ -68,6 +68,15 @@ #define CFE_PSP_RAM_DISK_SECTOR_SIZE (GLOBAL_CONFIGDATA.CfeConfig->RamDiskSectorSize) #define CFE_PSP_RAM_DISK_NUM_SECTORS (GLOBAL_CONFIGDATA.CfeConfig->RamDiskTotalSectors) + +typedef struct +{ + CFE_PSP_ReservedMemoryBootRecord_t BootRecord; + CFE_PSP_ExceptionStorage_t ExceptionStorage; +} CFE_PSP_RtemsReservedAreaFixedLayout_t; + + + /* ** External Declarations */ @@ -81,6 +90,10 @@ */ CFE_PSP_ReservedMemoryMap_t CFE_PSP_ReservedMemoryMap = { 0 }; + +CFE_PSP_MemoryBlock_t PcRtems_ReservedMemBlock; + + /* ********************************************************************************* ** CDS related functions @@ -104,13 +117,13 @@ int32 CFE_PSP_GetCDSSize(uint32 *SizeOfCDS) { int32 return_code; - if ( SizeOfCDS == NULL || CFE_PSP_ReservedMemoryMap.TotalSize == 0 ) + if ( SizeOfCDS == NULL ) { return_code = OS_ERROR; } else { - *SizeOfCDS = CFE_PSP_ReservedMemoryMap.CDSSize; + *SizeOfCDS = CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize; return_code = OS_SUCCESS; } return(return_code); @@ -133,18 +146,20 @@ int32 CFE_PSP_WriteToCDS(const void *PtrToDataToWrite, uint32 CDSOffset, uint32 uint8 *CopyPtr; int32 return_code; - if ( PtrToDataToWrite == NULL || CFE_PSP_ReservedMemoryMap.TotalSize == 0 ) + if ( PtrToDataToWrite == NULL ) { return_code = OS_ERROR; } else { - if ( (CDSOffset < CFE_PSP_ReservedMemoryMap.CDSSize ) && ( (CDSOffset + NumBytes) <= CFE_PSP_ReservedMemoryMap.CDSSize )) + if ( (CDSOffset < CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize ) && + ( (CDSOffset + NumBytes) <= CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize )) { - CopyPtr = &(CFE_PSP_ReservedMemoryMap.CDSMemory[CDSOffset]); - memcpy((char *)CopyPtr, (char *)PtrToDataToWrite,NumBytes); + CopyPtr = CFE_PSP_ReservedMemoryMap.CDSMemory.BlockPtr; + CopyPtr += CDSOffset; + memcpy((char *)CopyPtr, (char *)PtrToDataToWrite,NumBytes); - return_code = OS_SUCCESS; + return_code = OS_SUCCESS; } else { @@ -175,18 +190,20 @@ int32 CFE_PSP_ReadFromCDS(void *PtrToDataToRead, uint32 CDSOffset, uint32 NumByt uint8 *CopyPtr; int32 return_code; - if ( PtrToDataToRead == NULL || CFE_PSP_ReservedMemoryMap.TotalSize == 0 ) + if ( PtrToDataToRead == NULL ) { return_code = OS_ERROR; } else { - if ( (CDSOffset < CFE_PSP_ReservedMemoryMap.CDSSize ) && ( (CDSOffset + NumBytes) <= CFE_PSP_ReservedMemoryMap.CDSSize )) + if ( (CDSOffset < CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize ) && + ( (CDSOffset + NumBytes) <= CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize )) { - CopyPtr = &(CFE_PSP_ReservedMemoryMap.CDSMemory[CDSOffset]); - memcpy((char *)PtrToDataToRead, (char *)CopyPtr, NumBytes); + CopyPtr = CFE_PSP_ReservedMemoryMap.CDSMemory.BlockPtr; + CopyPtr += CDSOffset; + memcpy((char *)PtrToDataToRead, (char *)CopyPtr, NumBytes); - return_code = OS_SUCCESS; + return_code = OS_SUCCESS; } else { @@ -223,14 +240,14 @@ int32 CFE_PSP_GetResetArea (cpuaddr *PtrToResetArea, uint32 *SizeOfResetArea) { int32 return_code; - if ( SizeOfResetArea == NULL || PtrToResetArea == NULL || CFE_PSP_ReservedMemoryMap.TotalSize == 0 ) + if ( SizeOfResetArea == NULL || PtrToResetArea == NULL ) { return_code = OS_ERROR; } else { - *PtrToResetArea = (cpuaddr)(CFE_PSP_ReservedMemoryMap.ResetMemory); - *SizeOfResetArea = CFE_PSP_ReservedMemoryMap.ResetSize; + *PtrToResetArea = (cpuaddr)(CFE_PSP_ReservedMemoryMap.ResetMemory.BlockPtr); + *SizeOfResetArea = CFE_PSP_ReservedMemoryMap.ResetMemory.BlockSize; return_code = OS_SUCCESS; } @@ -260,14 +277,14 @@ int32 CFE_PSP_GetUserReservedArea(cpuaddr *PtrToUserArea, uint32 *SizeOfUserArea { int32 return_code; - if ( SizeOfUserArea == NULL || PtrToUserArea == NULL || CFE_PSP_ReservedMemoryMap.TotalSize == 0 ) + if ( SizeOfUserArea == NULL || PtrToUserArea == NULL ) { return_code = OS_ERROR; } else { - *PtrToUserArea = (cpuaddr)(CFE_PSP_ReservedMemoryMap.UserReservedMemory); - *SizeOfUserArea = CFE_PSP_ReservedMemoryMap.UserReservedSize; + *PtrToUserArea = (cpuaddr)(CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockPtr); + *SizeOfUserArea = CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockSize; return_code = OS_SUCCESS; } @@ -297,14 +314,14 @@ int32 CFE_PSP_GetVolatileDiskMem(cpuaddr *PtrToVolDisk, uint32 *SizeOfVolDisk ) { int32 return_code; - if ( SizeOfVolDisk == NULL || PtrToVolDisk == NULL || CFE_PSP_ReservedMemoryMap.TotalSize == 0 ) + if ( SizeOfVolDisk == NULL || PtrToVolDisk == NULL ) { return_code = OS_ERROR; } else { - *PtrToVolDisk = (cpuaddr)(CFE_PSP_ReservedMemoryMap.VolatileDiskMemory); - *SizeOfVolDisk = CFE_PSP_ReservedMemoryMap.VolatileDiskSize; + *PtrToVolDisk = (cpuaddr)(CFE_PSP_ReservedMemoryMap.VolatileDiskMemory.BlockPtr); + *SizeOfVolDisk = CFE_PSP_ReservedMemoryMap.VolatileDiskMemory.BlockSize; return_code = OS_SUCCESS; } @@ -320,7 +337,7 @@ int32 CFE_PSP_GetVolatileDiskMem(cpuaddr *PtrToVolDisk, uint32 *SizeOfVolDisk ) */ /****************************************************************************** -** Function: CFE_PSP_InitProcessorReservedMemory +** Function: CFE_PSP_SetupReservedMemoryMap ** ** Purpose: ** This function performs the top level reserved memory initialization. @@ -331,81 +348,97 @@ int32 CFE_PSP_GetVolatileDiskMem(cpuaddr *PtrToVolDisk, uint32 *SizeOfVolDisk ) ** Return: ** (none) */ -int32 CFE_PSP_InitProcessorReservedMemory( uint32 RestartType ) +void CFE_PSP_SetupReservedMemoryMap(void) { - int32 return_code; - uint32 RequiredSize; - uint32 SizeAlignMask; - uint8 *ReservedMemoryPtr; + CFE_PSP_RtemsReservedAreaFixedLayout_t *FixedPtr; + cpuaddr ReservedMemoryAddr; + size_t FixedSize; + size_t ResetSize; + size_t CDSSize; + size_t UserReservedSize; + size_t VolatileDiskSize; + size_t RequiredSize; /* ** Allocate memory for the cFE memory. Note that this is malloced on ** the COTS board, but will be a static location in the ETU. */ - SizeAlignMask = sizeof(uint32) - 1; - - CFE_PSP_ReservedMemoryMap.ResetSize = CFE_PSP_RESET_AREA_SIZE; - CFE_PSP_ReservedMemoryMap.VolatileDiskSize = (CFE_PSP_RAM_DISK_SECTOR_SIZE * CFE_PSP_RAM_DISK_NUM_SECTORS); - CFE_PSP_ReservedMemoryMap.CDSSize = CFE_PSP_CDS_SIZE; - CFE_PSP_ReservedMemoryMap.UserReservedSize = CFE_PSP_USER_RESERVED_SIZE; + FixedSize = sizeof(CFE_PSP_RtemsReservedAreaFixedLayout_t); + ResetSize = CFE_PSP_RESET_AREA_SIZE; + VolatileDiskSize = (CFE_PSP_RAM_DISK_SECTOR_SIZE * CFE_PSP_RAM_DISK_NUM_SECTORS); + CDSSize = CFE_PSP_CDS_SIZE; + UserReservedSize = CFE_PSP_USER_RESERVED_SIZE; + + FixedSize = (FixedSize + CFE_PSP_MEMALIGN_MASK) & ~CFE_PSP_MEMALIGN_MASK; + ResetSize = (ResetSize + CFE_PSP_MEMALIGN_MASK) & ~CFE_PSP_MEMALIGN_MASK; + CDSSize = (CDSSize + CFE_PSP_MEMALIGN_MASK) & ~CFE_PSP_MEMALIGN_MASK; + VolatileDiskSize = (VolatileDiskSize + CFE_PSP_MEMALIGN_MASK) & ~CFE_PSP_MEMALIGN_MASK; + UserReservedSize = (UserReservedSize + CFE_PSP_MEMALIGN_MASK) & ~CFE_PSP_MEMALIGN_MASK; /* Calculate the required size, adding padding so that each element is aligned */ - RequiredSize = (sizeof(CFE_PSP_ReservedFixedInfo_t) + SizeAlignMask) & ~SizeAlignMask; - RequiredSize += (CFE_PSP_ReservedMemoryMap.ResetSize + SizeAlignMask) & ~SizeAlignMask; - RequiredSize += (CFE_PSP_ReservedMemoryMap.CDSSize + SizeAlignMask) & ~SizeAlignMask; - RequiredSize += (CFE_PSP_ReservedMemoryMap.VolatileDiskSize + SizeAlignMask) & ~SizeAlignMask; - RequiredSize += (CFE_PSP_ReservedMemoryMap.UserReservedSize + SizeAlignMask) & ~SizeAlignMask; + RequiredSize = FixedSize; + RequiredSize += ResetSize; + RequiredSize += VolatileDiskSize; + RequiredSize += CDSSize; + RequiredSize += UserReservedSize; OS_printf("Sizeof BSP reserved memory = %u bytes\n",(unsigned int)RequiredSize); - ReservedMemoryPtr = (uint8 *)malloc(RequiredSize); + PcRtems_ReservedMemBlock.BlockPtr = malloc(RequiredSize); - if ( ReservedMemoryPtr == NULL ) + if ( PcRtems_ReservedMemBlock.BlockPtr == NULL ) { OS_printf("CFE_PSP: Error: Cannot malloc BSP reserved memory!\n"); - return_code = OS_ERROR; + abort(); } - else - { - OS_printf("CFE_PSP: Allocated %u bytes for PSP reserved memory at: 0x%08X\n", - (unsigned int)RequiredSize, (unsigned int)ReservedMemoryPtr); - - /* FIXME: On real HW clearing would be only done if RestartType != CFE_PSP_PROCESSOR_RESET, - but in this impl we are using malloc'ed memory so it always must be done */ - - OS_printf("CFE_PSP: Clearing Processor Reserved Memory.\n"); - memset(ReservedMemoryPtr, 0, RequiredSize); - - CFE_PSP_ReservedMemoryMap.FixedInfo = (CFE_PSP_ReservedFixedInfo_t *)ReservedMemoryPtr; - ReservedMemoryPtr += (sizeof(CFE_PSP_ReservedFixedInfo_t) + SizeAlignMask) & ~SizeAlignMask; - - CFE_PSP_ReservedMemoryMap.ResetMemory = ReservedMemoryPtr; - ReservedMemoryPtr += (CFE_PSP_ReservedMemoryMap.ResetSize + SizeAlignMask) & ~SizeAlignMask; - - CFE_PSP_ReservedMemoryMap.VolatileDiskMemory = ReservedMemoryPtr; - ReservedMemoryPtr += (CFE_PSP_ReservedMemoryMap.VolatileDiskSize + SizeAlignMask) & ~SizeAlignMask; - - CFE_PSP_ReservedMemoryMap.CDSMemory = ReservedMemoryPtr; - ReservedMemoryPtr += (CFE_PSP_ReservedMemoryMap.CDSSize + SizeAlignMask) & ~SizeAlignMask; - - CFE_PSP_ReservedMemoryMap.UserReservedMemory = ReservedMemoryPtr; - ReservedMemoryPtr += (CFE_PSP_ReservedMemoryMap.UserReservedSize + SizeAlignMask) & ~SizeAlignMask; - - /* - ** Set the default reset type in case a watchdog reset occurs - */ - CFE_PSP_ReservedMemoryMap.FixedInfo->bsp_reset_type = CFE_PSP_RST_TYPE_PROCESSOR; - - /* Keep the actual size for future reference. - This is also something that can be checked to see if things were initialized successfully. - (i.e. If this reads zero then none of the other pointers are useful) - */ - CFE_PSP_ReservedMemoryMap.TotalSize = RequiredSize; - - return_code = OS_SUCCESS; - } - return(return_code); + PcRtems_ReservedMemBlock.BlockSize = RequiredSize; + ReservedMemoryAddr = (cpuaddr)PcRtems_ReservedMemBlock.BlockPtr; + + OS_printf("CFE_PSP: Allocated %u bytes for PSP reserved memory at: 0x%08lX\n", + (unsigned int)RequiredSize, (unsigned long)ReservedMemoryAddr); + + FixedPtr = (CFE_PSP_RtemsReservedAreaFixedLayout_t*)ReservedMemoryAddr; + + CFE_PSP_ReservedMemoryMap.BootPtr = &FixedPtr->BootRecord; + CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr = &FixedPtr->ExceptionStorage; + ReservedMemoryAddr += FixedSize; + + CFE_PSP_ReservedMemoryMap.ResetMemory.BlockPtr = (void*)ReservedMemoryAddr; + CFE_PSP_ReservedMemoryMap.ResetMemory.BlockSize = CFE_PSP_RESET_AREA_SIZE; + ReservedMemoryAddr += ResetSize; + + CFE_PSP_ReservedMemoryMap.VolatileDiskMemory.BlockPtr = (void*)ReservedMemoryAddr; + CFE_PSP_ReservedMemoryMap.VolatileDiskMemory.BlockSize = (CFE_PSP_RAM_DISK_SECTOR_SIZE * CFE_PSP_RAM_DISK_NUM_SECTORS); + ReservedMemoryAddr += VolatileDiskSize; + + CFE_PSP_ReservedMemoryMap.CDSMemory.BlockPtr = (void*)ReservedMemoryAddr; + CFE_PSP_ReservedMemoryMap.CDSMemory.BlockSize = CFE_PSP_CDS_SIZE; + ReservedMemoryAddr += CDSSize; + + CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockPtr = (void*)ReservedMemoryAddr; + CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockSize = CFE_PSP_USER_RESERVED_SIZE; + ReservedMemoryAddr += UserReservedSize; + +} + +/****************************************************************************** +** Function: CFE_PSP_InitProcessorReservedMemory +** +** Purpose: +** This function performs the top level reserved memory initialization. +** +** Arguments: +** (none) +** +** Return: +** (none) +*/ +int32 CFE_PSP_InitProcessorReservedMemory( uint32 RestartType ) +{ + OS_printf("CFE_PSP: Clearing Processor Reserved Memory.\n"); + memset(PcRtems_ReservedMemBlock.BlockPtr, 0, PcRtems_ReservedMemBlock.BlockSize); + return CFE_PSP_SUCCESS; } diff --git a/fsw/pc-rtems/src/cfe_psp_memory.h b/fsw/pc-rtems/src/cfe_psp_memory.h deleted file mode 100644 index b1dda523..00000000 --- a/fsw/pc-rtems/src/cfe_psp_memory.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -** GSC-18128-1, "Core Flight Executive Version 6.7" -** -** Copyright (c) 2006-2019 United States Government as represented by -** the Administrator of the National Aeronautics and Space Administration. -** All Rights Reserved. -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -/* -** File Name: cfe_psp_memory.h -** -** Author: A. Cudmore -** -** Purpose: This file contains PSP support routine internal prototypes -** and typedefs. The routines and typedefs are intended for -** the local PSP routines only. -** -** Modification History: -** -*/ - -#ifndef _cfe_psp_memory_ -#define _cfe_psp_memory_ - -/* -** Include Files -*/ - -#include "common_types.h" -#include "cfe_psp.h" - - -/* -** Typedef for the layout of the vxWorks USER_RESERVED_MEM -*/ - -typedef struct -{ - uint32 bsp_reset_type; - uint32 spare1; - uint32 spare2; - uint32 spare3; -} CFE_PSP_ReservedFixedInfo_t; - - -typedef struct -{ - uint32 TotalSize; - CFE_PSP_ReservedFixedInfo_t *FixedInfo; - uint32 ResetSize; - uint8 *ResetMemory; - uint32 VolatileDiskSize; - uint8 *VolatileDiskMemory; - uint32 CDSSize; - uint8 *CDSMemory; - uint32 UserReservedSize; - uint8 *UserReservedMemory; -} CFE_PSP_ReservedMemoryMap_t; - -/* -** External variables -*/ - -/* -** Pointer to the vxWorks USER_RESERVED_MEMORY area -** The sizes of each memory area is defined in os_processor.h for this architecture. -*/ -extern CFE_PSP_ReservedMemoryMap_t CFE_PSP_ReservedMemoryMap; - -#endif /* _cfe_psp_memory_ */ diff --git a/fsw/pc-rtems/src/cfe_psp_start.c b/fsw/pc-rtems/src/cfe_psp_start.c index 6e9eb4bb..affa2a16 100644 --- a/fsw/pc-rtems/src/cfe_psp_start.c +++ b/fsw/pc-rtems/src/cfe_psp_start.c @@ -251,6 +251,11 @@ void CFE_PSP_Main(void) CFE_PSP_Panic(Status); } + /* + * Initialize the CFE reserved memory map + */ + CFE_PSP_SetupReservedMemoryMap(); + /* ** Initialize the statically linked modules (if any) */ diff --git a/fsw/pc-rtems/src/cfe_psp_support.c b/fsw/pc-rtems/src/cfe_psp_support.c index b6b068e9..8a26c7d4 100644 --- a/fsw/pc-rtems/src/cfe_psp_support.c +++ b/fsw/pc-rtems/src/cfe_psp_support.c @@ -63,6 +63,14 @@ #define CFE_PSP_CPU_NAME (GLOBAL_CONFIGDATA.Default_CpuName) #define CFE_PSP_SPACECRAFT_ID (GLOBAL_CONFIGDATA.Default_SpacecraftId) + +/* + * Track the overall "reserved memory block" at the start of RAM. + * This single large block is then subdivided into separate areas for CFE use. + */ +extern CFE_PSP_MemoryBlock_t PcRtems_ReservedMemBlock; + + /****************************************************************************** ** Function: CFE_PSP_Restart() ** @@ -81,14 +89,12 @@ void CFE_PSP_Restart(uint32 reset_type) if ( reset_type == CFE_PSP_RST_TYPE_POWERON ) { - CFE_PSP_ReservedMemoryMap.FixedInfo->bsp_reset_type = CFE_PSP_RST_TYPE_POWERON; - CFE_PSP_FlushCaches(1, (cpuaddr)CFE_PSP_ReservedMemoryMap.FixedInfo, CFE_PSP_ReservedMemoryMap.TotalSize); + CFE_PSP_FlushCaches(1, PcRtems_ReservedMemBlock.BlockPtr, PcRtems_ReservedMemBlock.BlockSize); /* reboot(BOOT_CLEAR); Need RTEMS equiv. */ } else { - CFE_PSP_ReservedMemoryMap.FixedInfo->bsp_reset_type = CFE_PSP_RST_TYPE_PROCESSOR; - CFE_PSP_FlushCaches(1, (cpuaddr)CFE_PSP_ReservedMemoryMap.FixedInfo, CFE_PSP_ReservedMemoryMap.TotalSize); + CFE_PSP_FlushCaches(1, PcRtems_ReservedMemBlock.BlockPtr, PcRtems_ReservedMemBlock.BlockSize); /* reboot(BOOT_NORMAL); Need RTEMS Equiv */ } @@ -131,7 +137,7 @@ void CFE_PSP_Panic(int32 ErrorCode) ** (none) */ -void CFE_PSP_FlushCaches(uint32 type, cpuaddr address, uint32 size) +void CFE_PSP_FlushCaches(uint32 type, void* address, uint32 size) { if ( type == 1 ) { diff --git a/fsw/shared/cfe_psp_configdata.c b/fsw/shared/cfe_psp_configdata.c index 710e2433..0bd712fb 100644 --- a/fsw/shared/cfe_psp_configdata.c +++ b/fsw/shared/cfe_psp_configdata.c @@ -47,7 +47,6 @@ Target_PspConfigData GLOBAL_PSP_CONFIGDATA = .OS_VolumeTableSize = NUM_TABLE_ENTRIES, .OS_VolumeTable = OS_VolumeTable, - .OS_CpuContextSize = CFE_PSP_CPU_CONTEXT_SIZE, .HW_NumEepromBanks = CFE_PSP_NUM_EEPROM_BANKS, diff --git a/fsw/shared/cfe_psp_exceptionstorage.c b/fsw/shared/cfe_psp_exceptionstorage.c new file mode 100644 index 00000000..a3843b57 --- /dev/null +++ b/fsw/shared/cfe_psp_exceptionstorage.c @@ -0,0 +1,265 @@ +/* +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/****************************************************************************** +** +** File: cfe_psp_exception.c +** +** MCP750 vxWorks 6.2 Version +** +** Purpose: +** cFE PSP Exception related functions. +** +** History: +** 2007/05/29 A. Cudmore | vxWorks 6.2 MCP750 version +** 2016/04/07 M.Grubb | Updated for PSP version 1.3 +** +******************************************************************************/ + +/* +** Include Files +*/ +#include +#include + +/* +** cFE includes +*/ +#include "common_types.h" +#include "osapi.h" + +#include "cfe_psp.h" +#include "cfe_psp_config.h" +#include "cfe_psp_exceptionstorage.h" +#include "cfe_psp_memory.h" + +#include + +/* +** Constants +*/ +#define CFE_PSP_MAX_EXCEPTION_ENTRY_MASK (CFE_PSP_MAX_EXCEPTION_ENTRIES-1) +#define CFE_PSP_EXCEPTION_ID_BASE ((OS_OBJECT_TYPE_USER + 0x101) << OS_OBJECT_TYPE_SHIFT) + + +/*************************************************************************** + ** INTERNAL FUNCTION DEFINITIONS + ** (Functions used only within the PSP itself) + ***************************************************************************/ + +/*--------------------------------------------------------------------------- + * CFE_PSP_Exception_Reset + * Internal function - see description in prototype + *---------------------------------------------------------------------------*/ +void CFE_PSP_Exception_Reset(void) +{ + /* just reset the counter */ + CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr->NumRead = + CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr->NumWritten; +} + +/*--------------------------------------------------------------------------- + * CFE_PSP_Exception_GetBuffer + * Internal function - see description in prototype + *---------------------------------------------------------------------------*/ +CFE_PSP_Exception_LogData_t* CFE_PSP_Exception_GetBuffer(uint32 seq) +{ + return &CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr->Entries[seq & CFE_PSP_MAX_EXCEPTION_ENTRY_MASK]; +} + +/*--------------------------------------------------------------------------- + * CFE_PSP_Exception_GetNextContextBuffer + * Internal function - see description in prototype + *---------------------------------------------------------------------------*/ +CFE_PSP_Exception_LogData_t* CFE_PSP_Exception_GetNextContextBuffer(void) +{ + CFE_PSP_Exception_LogData_t* Buffer; + uint32 NextWrite; + + NextWrite = CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr->NumWritten; + if ((NextWrite - CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr->NumRead) >= CFE_PSP_MAX_EXCEPTION_ENTRIES) + { + /* no space to store another context */ + return NULL; + } + + Buffer = CFE_PSP_Exception_GetBuffer(NextWrite); + + memset(Buffer, 0, sizeof(*Buffer)); + Buffer->context_id = CFE_PSP_EXCEPTION_ID_BASE + (NextWrite & OS_OBJECT_INDEX_MASK); + + return Buffer; +} + +/*--------------------------------------------------------------------------- + * CFE_PSP_Exception_WriteComplete + * Internal function - see description in prototype + *---------------------------------------------------------------------------*/ +void CFE_PSP_Exception_WriteComplete(void) +{ + CFE_PSP_Exception_LogData_t* Buffer; + + /* + * Incrementing the "NumWritten" field allows the application to receive this data + */ + ++CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr->NumWritten; + + /* + * preemptively zero-out the "id" field of the _next_ entry - + * this expires the buffer, which prevents it from being read. + * + * This is just in case another exception occurs while a log + * file write is in progress. It's not 100% foolproof, but + * it does reduce the chance of data corruption (because it + * is not possible to "lock out" exceptions, they can occur at + * any time code is running) + */ + Buffer = CFE_PSP_Exception_GetBuffer(CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr->NumWritten); + Buffer->context_id = 0; +} + + +/*************************************************************************** + ** EXTERNAL FUNCTION DEFINITIONS + ** (Functions used by CFE or PSP) + ***************************************************************************/ + +/*--------------------------------------------------------------------------- + * CFE_PSP_Exception_GetCount + * See description in PSP API + *---------------------------------------------------------------------------*/ +uint32 CFE_PSP_Exception_GetCount(void) +{ + return (CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr->NumWritten - CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr->NumRead); +} + +/*--------------------------------------------------------------------------- + * CFE_PSP_Exception_GetSummary + * See description in PSP API + *---------------------------------------------------------------------------*/ +int32 CFE_PSP_Exception_GetSummary(uint32 *ContextLogId, uint32 *TaskId, char *ReasonBuf, uint32 ReasonSize) +{ + const CFE_PSP_Exception_LogData_t* Buffer; + uint32 NumStored; + int32 Status; + + NumStored = CFE_PSP_Exception_GetCount(); + if (NumStored == 0) + { + /* no context available for reading */ + return CFE_PSP_NO_EXCEPTION_DATA; + } + + Buffer = CFE_PSP_Exception_GetBuffer(CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr->NumRead); + + /* + * Store the abstract entry ID for future retrieval (e.g. log to file) + */ + if (ContextLogId != NULL) + { + *ContextLogId = Buffer->context_id; + } + + /* + * If caller supplied a TaskID buffer, then call OSAL to reverse-lookup + * the abstract ID from the underlying system thread ID. + */ + if (TaskId != NULL) + { + Status = OS_TaskFindIdBySystemData(TaskId, &Buffer->sys_task_id, sizeof(Buffer->sys_task_id)); + if (Status != OS_SUCCESS) + { + *TaskId = 0; /* failed to find a corresponding OSAL ID, so set to zero. */ + } + } + + /* + * If caller supplied a reason buffer, then call the implementation to fill it. + */ + if (ReasonBuf != NULL && ReasonSize > 0) + { + Status = CFE_PSP_ExceptionGetSummary_Impl(Buffer, ReasonBuf, ReasonSize); + if (Status != CFE_PSP_SUCCESS) + { + ReasonBuf[0] = 0; /* failed to get a reason, so return empty string */ + } + } + + ++CFE_PSP_ReservedMemoryMap.ExceptionStoragePtr->NumRead; + + /* + * returning SUCCESS to indicate an entry was popped from the queue + * + * this doesn't necessarily mean that the output fields have valid data, + * but it does mean they are initialized to something. + */ + return CFE_PSP_SUCCESS; +} + +/*--------------------------------------------------------------------------- + * CFE_PSP_Exception_CopyContext + * See description in PSP API + *---------------------------------------------------------------------------*/ +int32 CFE_PSP_Exception_CopyContext(uint32 ContextLogId, void *ContextBuf, uint32 ContextSize) +{ + const CFE_PSP_Exception_LogData_t* Buffer; + uint32 SeqId; + uint32 ActualSize; + + SeqId = ContextLogId - CFE_PSP_EXCEPTION_ID_BASE; + if (SeqId > OS_OBJECT_INDEX_MASK) + { + /* supplied ID is not valid at all */ + return CFE_PSP_NO_EXCEPTION_DATA; + } + + Buffer = CFE_PSP_Exception_GetBuffer(SeqId); + if (Buffer->context_id != ContextLogId) + { + /* data has expired from the memory log */ + return CFE_PSP_NO_EXCEPTION_DATA; + } + + /* Copy the "context info" out to the buffer. + * But do not copy more than the output buffer. */ + if (ContextSize >= Buffer->context_size) + { + ActualSize = Buffer->context_size; + } + else + { + /* this will truncate, not ideal, but no alternative. + * If this happens it generally indicates a misconfiguration between CFE and PSP, + * where the CFE platform configuration has not allocated enough space for context logs. + * Generate a warning message to raise awareness. */ + OS_printf("CFE_PSP: Insufficient buffer for exception context, total=%lu bytes, saved=%lu\n", + (unsigned long)Buffer->context_size, (unsigned long)ContextSize); + ActualSize = ContextSize; + } + + + memcpy(ContextBuf, &Buffer->context_info, ActualSize); + + /* + * The return value is the actual size of copied data. + */ + return (int32)ActualSize; +} + diff --git a/fsw/shared/cfe_psp_exceptionstorage.h b/fsw/shared/cfe_psp_exceptionstorage.h new file mode 100644 index 00000000..4b837fb7 --- /dev/null +++ b/fsw/shared/cfe_psp_exceptionstorage.h @@ -0,0 +1,107 @@ +/* +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/** + * \file cfe_psp_exceptionstorage.h + * + * Provides a generic storage buffer ring for exceptions + */ + +#ifndef CFE_PSP_EXCEPTIONSTORAGE_H_ +#define CFE_PSP_EXCEPTIONSTORAGE_H_ + +#include +#include + +/* + * The "MetaData" stores ephemeral exception information + * which only has meaning within the currently-running process. + * + * This data is important for diagnosing the exception, but it + * is NOT saved to any persistent log because it will not be + * relevant once the process ends. + */ +typedef struct +{ + uint32 context_id; /**< a unique ID assigned to this exception entry */ + uint32 context_size; /**< actual size of the "context_info" data */ + CFE_PSP_Exception_SysTaskId_t sys_task_id; /**< the BSP-specific task info (not osal abstracted id) */ + CFE_PSP_Exception_ContextDataEntry_t context_info; +} CFE_PSP_Exception_LogData_t; + + +typedef struct +{ + volatile uint32 NumWritten; + volatile uint32 NumRead; + CFE_PSP_Exception_LogData_t Entries[CFE_PSP_MAX_EXCEPTION_ENTRIES]; +} CFE_PSP_ExceptionStorage_t; + + + +/* ------------------------------------------------------------- + * Functions implemented in shared layer, invoked by impl layer. + * ------------------------------------------------------------- */ + +/** + * \brief Get the next buffer for exception context storage + * + * This function is invoked by the low level exception handler (typically an ISR/signal) + * to obtain a buffer for context capture. The buffer is cleared (memset zero) before + * returning to the caller. + * + * \returns pointer to buffer, or NULL if storage is full. + */ +extern CFE_PSP_Exception_LogData_t* CFE_PSP_Exception_GetNextContextBuffer(void); + +/** + * \brief Finish storage of exception data + * + * This function is invoked by the low level exception handler (typically an ISR/signal) + * once the exception context capture is complete. This should be invoked after a successful + * call to CFE_PSP_Exception_GetNextContextBuffer() to commit the information to the log. + */ +extern void CFE_PSP_Exception_WriteComplete(void); + +/** + * \brief Reset the exception storage buffer + * + * Marks any pending exceptions as "read". This resets the state of exception processing. + */ +extern void CFE_PSP_Exception_Reset(void); + +/* ------------------------------------------------------------- + * Functions implemented in impl layer, invoked by shared layer. + * ------------------------------------------------------------- */ + +/** + * \brief Translate the exception context data into a user-friendly "reason" string + * + * This is called in an application context to determine the cause of the exception. + * + * \param[in] Buffer Context data previously stored by ISR/signal handler + * \param[out] ReasonBuf Buffer to store string + * \param[in] ReasonSize Size of string buffer + * + * \returns CFE_PSP_SUCCESS on success + */ +extern int32 CFE_PSP_ExceptionGetSummary_Impl(const CFE_PSP_Exception_LogData_t* Buffer, char *ReasonBuf, uint32 ReasonSize); + +#endif /* CFE_PSP_EXCEPTIONSTORAGE_H_ */ diff --git a/fsw/shared/cfe_psp_memory.h b/fsw/shared/cfe_psp_memory.h new file mode 100644 index 00000000..2a0ae905 --- /dev/null +++ b/fsw/shared/cfe_psp_memory.h @@ -0,0 +1,107 @@ +/* +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/* +** File Name: cfe_psp_memory.h +** +** Author: A. Cudmore +** +** Purpose: This file contains PSP support routine internal prototypes +** and typedefs. The routines and typedefs are intended for +** the local PSP routines only. +** +** Modification History: +** +*/ + +#ifndef _cfe_psp_memory_ +#define _cfe_psp_memory_ + +/* +** Include Files +*/ + +#include "common_types.h" +#include "cfe_psp_config.h" +#include "cfe_psp_exceptionstorage.h" + +typedef struct +{ + void* BlockPtr; + size_t BlockSize; + +} CFE_PSP_MemoryBlock_t; + + +typedef struct +{ + CFE_PSP_ReservedMemoryBootRecord_t *BootPtr; + CFE_PSP_ExceptionStorage_t *ExceptionStoragePtr; + + CFE_PSP_MemoryBlock_t ResetMemory; + CFE_PSP_MemoryBlock_t VolatileDiskMemory; + CFE_PSP_MemoryBlock_t CDSMemory; + CFE_PSP_MemoryBlock_t UserReservedMemory; +} CFE_PSP_ReservedMemoryMap_t; + + + +/** + * \brief Initialize the CFE_PSP_ReservedMemoryMap global object + * + * This must be called by the startup code before the map is accessed. + */ +extern void CFE_PSP_SetupReservedMemoryMap(void); + + +/* + * CFE_PSP_InitProcessorReservedMemory initializes all of the memory in the + * BSP that is preserved on a processor reset. The memory includes the + * Critical Data Store, the ES Reset Area, the Volatile Disk Memory, and + * the User Reserved Memory. + * + * This initializes based on the reset type. Typically, the information + * is preserved on a processor reset, and cleared/reinitialized on a power-on + * reset. + */ +extern int32 CFE_PSP_InitProcessorReservedMemory(uint32 RestartType ); + + +/** + * \brief Unlink the memory segments within the CFE_PSP_ReservedMemoryMap global object + * + * This function is only relevant on systems where the objects are implemented + * as kernel shared memory segments. The segments will be marked for deletion + * but the local maps remain usable until the process ends. + */ +extern void CFE_PSP_DeleteProcessorReservedMemory(void); + + +/* +** External variables +*/ + +/* +** Map to the reserved memory area(s) +** Contains a pointer to each of the separate memory blocks +*/ +extern CFE_PSP_ReservedMemoryMap_t CFE_PSP_ReservedMemoryMap; + +#endif /* _cfe_psp_memory_ */ diff --git a/fsw/ut-stubs/ut_psp_stubs.c b/fsw/ut-stubs/ut_psp_stubs.c index f32e161f..eb6e1d53 100644 --- a/fsw/ut-stubs/ut_psp_stubs.c +++ b/fsw/ut-stubs/ut_psp_stubs.c @@ -659,3 +659,45 @@ int32 CFE_PSP_MemSet(void *dst, uint8 value , uint32 size) return status; } +uint32 CFE_PSP_Exception_GetCount(void) +{ + int32 status; + + status = UT_DEFAULT_IMPL(CFE_PSP_Exception_GetCount); + + return status; +} + +int32 CFE_PSP_Exception_GetSummary(uint32 *ContextLogId, uint32 *TaskId, char *ReasonBuf, uint32 ReasonSize) +{ + int32 status; + + *ContextLogId = 0; + *TaskId = 0; + *ReasonBuf = 0; + + /* allow the testcase to easily set the taskID output, anything more involved needs a hook */ + status = UT_DEFAULT_IMPL_ARGS(CFE_PSP_Exception_GetSummary, ContextLogId, TaskId, ReasonBuf, ReasonSize); + if (status == 0 && *TaskId == 0) + { + UT_Stub_CopyToLocal(UT_KEY(CFE_PSP_Exception_GetSummary), TaskId, sizeof(*TaskId)); + } + + + return status; +} + +int32 CFE_PSP_Exception_CopyContext(uint32 ContextLogId, void *ContextBuf, uint32 ContextSize) +{ + int32 status; + + status = UT_DEFAULT_IMPL(CFE_PSP_Exception_CopyContext); + if (status == 0) + { + status = UT_Stub_CopyToLocal(UT_KEY(CFE_PSP_Exception_CopyContext), ContextBuf, ContextSize); + } + + return status; +} + + From 93990ef242036bb6df809f6a27128bb15ede5797 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Tue, 5 May 2020 16:51:30 -0400 Subject: [PATCH 3/4] Update #158, Minor fixes for cppcheck issues --- fsw/pc-linux/src/cfe_psp_start.c | 3 ++- fsw/pc-rtems/src/cfe_psp_memory.c | 7 +++++++ fsw/pc-rtems/src/cfe_psp_support.c | 12 +----------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/fsw/pc-linux/src/cfe_psp_start.c b/fsw/pc-linux/src/cfe_psp_start.c index 732d1cd8..926a987e 100644 --- a/fsw/pc-linux/src/cfe_psp_start.c +++ b/fsw/pc-linux/src/cfe_psp_start.c @@ -251,7 +251,8 @@ void OS_Application_Startup(void) */ CFE_PSP_SpacecraftId = CommandData.SpacecraftId; CFE_PSP_CpuId = CommandData.CpuId; - strncpy(CFE_PSP_CpuName, CommandData.CpuName, CFE_PSP_CPU_NAME_LENGTH); + strncpy(CFE_PSP_CpuName, CommandData.CpuName, sizeof(CFE_PSP_CpuName)-1); + CFE_PSP_CpuName[sizeof(CFE_PSP_CpuName)-1] = 0; /* ** Set the reset subtype diff --git a/fsw/pc-rtems/src/cfe_psp_memory.c b/fsw/pc-rtems/src/cfe_psp_memory.c index dc2135c3..7f9068a0 100644 --- a/fsw/pc-rtems/src/cfe_psp_memory.c +++ b/fsw/pc-rtems/src/cfe_psp_memory.c @@ -420,6 +420,13 @@ void CFE_PSP_SetupReservedMemoryMap(void) CFE_PSP_ReservedMemoryMap.UserReservedMemory.BlockSize = CFE_PSP_USER_RESERVED_SIZE; ReservedMemoryAddr += UserReservedSize; + /* + * displaying the final address shows how much was actually used, + * and additionally avoids a warning about the result of the final increment not being used. + * (prefer this over removing the increment, as it is safer if another block is added) + */ + OS_printf("CFE_PSP: PSP reserved memory ends at: 0x%08lX\n", + (unsigned long)ReservedMemoryAddr); } /****************************************************************************** diff --git a/fsw/pc-rtems/src/cfe_psp_support.c b/fsw/pc-rtems/src/cfe_psp_support.c index 8a26c7d4..83732f64 100644 --- a/fsw/pc-rtems/src/cfe_psp_support.c +++ b/fsw/pc-rtems/src/cfe_psp_support.c @@ -87,17 +87,7 @@ extern CFE_PSP_MemoryBlock_t PcRtems_ReservedMemBlock; void CFE_PSP_Restart(uint32 reset_type) { - if ( reset_type == CFE_PSP_RST_TYPE_POWERON ) - { - CFE_PSP_FlushCaches(1, PcRtems_ReservedMemBlock.BlockPtr, PcRtems_ReservedMemBlock.BlockSize); - /* reboot(BOOT_CLEAR); Need RTEMS equiv. */ - } - else - { - CFE_PSP_FlushCaches(1, PcRtems_ReservedMemBlock.BlockPtr, PcRtems_ReservedMemBlock.BlockSize); - /* reboot(BOOT_NORMAL); Need RTEMS Equiv */ - } - + CFE_PSP_FlushCaches(1, PcRtems_ReservedMemBlock.BlockPtr, PcRtems_ReservedMemBlock.BlockSize); OS_printf("CFE_PSP_Restart is not implemented on this platform ( yet ! )\n"); exit(-1); From 87542326b0546bf8def573b1061cfeb34d6bee21 Mon Sep 17 00:00:00 2001 From: "Gerardo E. Cruz-Ortiz" Date: Wed, 13 May 2020 10:35:17 -0400 Subject: [PATCH 4/4] Increase version to 1.4.11. Update Readme and tidy up markdown. --- README.md | 90 +++++++++++++++++----------- fsw/mcp750-vxworks/inc/psp_version.h | 2 +- fsw/pc-linux/inc/psp_version.h | 2 +- fsw/pc-rtems/inc/psp_version.h | 2 +- 4 files changed, 57 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 6f51fadd..b15360f0 100644 --- a/README.md +++ b/README.md @@ -4,56 +4,74 @@ Travis-CI: [![Build Status](https://travis-ci.com/nasa/PSP.svg)](https://travis- This repository contains NASA's Platform Support Package (PSP), which is a framework component of the Core Flight System. -This is a collection of APIs abstracting platform specific functionality to be located in the `psp` subdirectory of a cFS Mission Tree. The Core Flight System is bundled at https://github.com/nasa/cFS, which includes build and execution instructions. +This is a collection of APIs abstracting platform specific functionality to be located in the `psp` subdirectory of a cFS Mission Tree. The Core Flight System is bundled at , which includes build and execution instructions. ## Version History +### Development Build: 1.4.11 + +- Removes non-termination string warnings when building with GCC9. +- Exception handling is now implemented on POSIX. There is no longer a separate handler for SIGINT - it is now treated as an exception and goes through the normal process which ends up "restarting" CFE. On pc-linux causes the process to exit normally. There is now a mechanism to capture the CTRL+C exception code and use it during normal test cycles. +- See + #### Development Build: 1.4.10 - - Implements full-precision microsecond conversion - - See https://github.com/nasa/PSP/pull/155 -#### Development Build: 1.4.9 - - RTEMS builds successfully without errors - - Build script uses a proper CMakeLists.txt instead of the aux_source directory - - Minor updates (see https://github.com/nasa/PSP/pull/153) +- Implements full-precision microsecond conversion +- See + +### Development Build: 1.4.9 + +- RTEMS builds successfully without errors +- Build script uses a proper CMakeLists.txt instead of the aux_source directory +- Minor updates (see ) + +### Development Build: 1.4.8 + +- Minor updates (see ) + +### Development Build: 1.4.7 + +- Fixed some build warnings for MCP750 +- Minor updates (see ) + +### Development Build: 1.4.6 + +- Minor updates (see ) + +### Development Build: 1.4.5 + +- Simplifies array handling in VxWorks +- Minor updates (see ) + +### Development Build: 1.4.4 + +- Minor updates (see ) -#### Development Build: 1.4.8 - - Minor updates (see https://github.com/nasa/PSP/pull/151) +### Development Build: 1.4.3 -#### Development Build: 1.4.7 - - Fixed some build warnings for MCP750 - - Minor updates (see https://github.com/nasa/PSP/pull/142) +- Minor updates (see ) -#### Development Build: 1.4.6 - - Minor updates (see https://github.com/nasa/PSP/pull/141) +### Development Build: 1.4.2 -#### Development Build: 1.4.5 - - Simplifies array handling in VxWorks - - Minor updates (see https://github.com/nasa/PSP/pull/138) +- Minor updates (see ) -#### Development Build: 1.4.4 - - Minor updates (see https://github.com/nasa/PSP/pull/132) +### Development Build: 1.4.1 -#### Development Build: 1.4.3 - - Minor updates (see https://github.com/nasa/PSP/pull/130) +- Minor updates (see ) -#### Development Build: 1.4.2 - - Minor updates (see https://github.com/nasa/PSP/pull/127) +### **_1.4.0 OFFICIAL RELEASE_** -#### Development Build: 1.4.1 - - Minor updates (see https://github.com/nasa/PSP/pull/115) +- This is a point release from an internal repository +- Changes are detailed in [cFS repo](https://github.com/nasa/cFS) release documentation +- Released as part of cFE 6.7.0, Apache 2.0 -### \*\*\* 1.4.0 OFFICIAL RELEASE \*\*\* - - This is a point release from an internal repository - - Changes are detailed in [cFS repo](https://github.com/nasa/cFS) release documentation - - Released as part of cFE 6.7.0, Apache 2.0 +### **_1.3.0a OFFICIAL RELEASE_** -### \*\*\* 1.3.0a OFFICIAL RELEASE \*\*\* - - This is a point release from an internal repository - - See [version description document](https://github.com/nasa/PSP/blob/v1.3.0a/doc/PSP%201.3.0.0%20Version%20Description%20Document.pdf) - - Released as part of cFE 6.6.0a, Apache 2.0 +- This is a point release from an internal repository +- See [version description document](https://github.com/nasa/PSP/blob/v1.3.0a/doc/PSP%201.3.0.0%20Version%20Description%20Document.pdf) +- Released as part of cFE 6.6.0a, Apache 2.0 -The open source release does not include all PSPs that have been developed. Only the three PSPs included are managed by the community CCB. PSPs developed by other organizations can be requested through the mechanisms listed below. Note the framework PSPs delivered may change in the future as platforms become obsolete. +The open source release does not include all PSPs that have been developed. Only the three PSPs included are managed by the community CCB. PSPs developed by other organizations can be requested through the mechanisms listed below. Note the framework PSPs delivered may change in the future as platforms become obsolete. ## Known issues @@ -61,6 +79,6 @@ See all open issues and closed to milestones later than this version. ## Getting Help -For best results, submit issues:questions or issues:help wanted requests at https://github.com/nasa/cFS. +For best results, submit issues:questions or issues:help wanted requests at . -Official cFS page: http://cfs.gsfc.nasa.gov +Official cFS page: diff --git a/fsw/mcp750-vxworks/inc/psp_version.h b/fsw/mcp750-vxworks/inc/psp_version.h index 1340246c..baca5dbc 100644 --- a/fsw/mcp750-vxworks/inc/psp_version.h +++ b/fsw/mcp750-vxworks/inc/psp_version.h @@ -35,7 +35,7 @@ */ #define CFE_PSP_IMPL_MAJOR_VERSION 1 #define CFE_PSP_IMPL_MINOR_VERSION 4 -#define CFE_PSP_IMPL_REVISION 10 +#define CFE_PSP_IMPL_REVISION 11 #define CFE_PSP_IMPL_MISSION_REV 0 #endif /* _psp_version_ */ diff --git a/fsw/pc-linux/inc/psp_version.h b/fsw/pc-linux/inc/psp_version.h index 1340246c..baca5dbc 100644 --- a/fsw/pc-linux/inc/psp_version.h +++ b/fsw/pc-linux/inc/psp_version.h @@ -35,7 +35,7 @@ */ #define CFE_PSP_IMPL_MAJOR_VERSION 1 #define CFE_PSP_IMPL_MINOR_VERSION 4 -#define CFE_PSP_IMPL_REVISION 10 +#define CFE_PSP_IMPL_REVISION 11 #define CFE_PSP_IMPL_MISSION_REV 0 #endif /* _psp_version_ */ diff --git a/fsw/pc-rtems/inc/psp_version.h b/fsw/pc-rtems/inc/psp_version.h index 1340246c..baca5dbc 100644 --- a/fsw/pc-rtems/inc/psp_version.h +++ b/fsw/pc-rtems/inc/psp_version.h @@ -35,7 +35,7 @@ */ #define CFE_PSP_IMPL_MAJOR_VERSION 1 #define CFE_PSP_IMPL_MINOR_VERSION 4 -#define CFE_PSP_IMPL_REVISION 10 +#define CFE_PSP_IMPL_REVISION 11 #define CFE_PSP_IMPL_MISSION_REV 0 #endif /* _psp_version_ */