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..926a987e 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,36 +246,19 @@ 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 */ 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 */ 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 +272,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 +327,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 +397,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 +541,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..7f9068a0 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,104 @@ 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; - } - 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; + abort(); } - 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; + + /* + * 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); +} + +/****************************************************************************** +** 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..83732f64 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() ** @@ -79,19 +87,7 @@ 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); - /* 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); - /* 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); @@ -131,7 +127,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; +} + +