From 29e8b7aaf62b3923acbf5c4b667c31854d41089d Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Wed, 17 Mar 2021 16:14:36 -0400 Subject: [PATCH 1/6] Fix #10, modularize the ram, port, and eeprom access Convert the current "cfe_psp_ram.c" and "cfe_psp_port.c" routines into modular components, and remove from "shared" dir. The existing implementations become the corresponding "direct" module, and are enabled based on the psp module selection. Also added is a "notimpl" variant, where all the functions return CFE_PSP_ERR_NOT_IMPLEMENTED. This is used on Linux or any other system where direct access is not possible. Note this also renames the existing "eeprom_stub" module to be "eeprom_notimpl" for consistency and to avoid any confusion with the unit test stubs. --- CMakeLists.txt | 7 +- fsw/mcp750-vxworks/psp_module_list.cmake | 4 +- fsw/mcp750-vxworks/src/cfe_psp_start.c | 6 ++ fsw/modules/eeprom_notimpl/CMakeLists.txt | 3 + .../cfe_psp_eeprom_notimpl.c} | 14 ++-- fsw/modules/eeprom_stub/CMakeLists.txt | 3 - fsw/modules/port_direct/CMakeLists.txt | 3 + .../port_direct/cfe_psp_port_direct.c} | 32 ++++----- fsw/modules/port_notimpl/CMakeLists.txt | 3 + .../port_notimpl/cfe_psp_port_notimpl.c | 69 +++++++++++++++++++ fsw/modules/ram_direct/CMakeLists.txt | 3 + .../ram_direct/cfe_psp_ram_direct.c} | 32 ++++----- fsw/modules/ram_notimpl/CMakeLists.txt | 3 + fsw/modules/ram_notimpl/cfe_psp_ram_notimpl.c | 69 +++++++++++++++++++ fsw/pc-linux/psp_module_list.cmake | 4 +- fsw/pc-rtems/psp_module_list.cmake | 6 +- fsw/shared/CMakeLists.txt | 4 +- 17 files changed, 212 insertions(+), 53 deletions(-) create mode 100644 fsw/modules/eeprom_notimpl/CMakeLists.txt rename fsw/modules/{eeprom_stub/cfe_psp_eeprom_stub.c => eeprom_notimpl/cfe_psp_eeprom_notimpl.c} (82%) delete mode 100644 fsw/modules/eeprom_stub/CMakeLists.txt create mode 100644 fsw/modules/port_direct/CMakeLists.txt rename fsw/{shared/src/cfe_psp_port.c => modules/port_direct/cfe_psp_port_direct.c} (92%) create mode 100644 fsw/modules/port_notimpl/CMakeLists.txt create mode 100644 fsw/modules/port_notimpl/cfe_psp_port_notimpl.c create mode 100644 fsw/modules/ram_direct/CMakeLists.txt rename fsw/{shared/src/cfe_psp_ram.c => modules/ram_direct/cfe_psp_ram_direct.c} (92%) create mode 100644 fsw/modules/ram_notimpl/CMakeLists.txt create mode 100644 fsw/modules/ram_notimpl/cfe_psp_ram_notimpl.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 79bdb5bc..5855677d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,10 +42,13 @@ set(GENERATED_EXTERNS) set(GENERATED_KEYVALS) foreach(PSPMOD ${PSP_TARGET_MODULE_LIST}) add_subdirectory(fsw/modules/${PSPMOD} ${PSPMOD}-${CFE_PSP_TARGETNAME}-impl) - list(APPEND GENERATED_EXTERNS "extern CFE_PSP_ModuleApi_t CFE_PSP_${PSPMOD}_API;\n") + list(APPEND GENERATED_EXTERNS "extern CFE_PSP_ModuleApi_t CFE_PSP_${PSPMOD}_API\;\n") list(APPEND GENERATED_KEYVALS "{ .Name = \"${PSPMOD}\", .Api = &CFE_PSP_${PSPMOD}_API },\n") endforeach() +string(CONCAT GENERATED_EXTERNS ${GENERATED_EXTERNS}) +string(CONCAT GENERATED_KEYVALS ${GENERATED_KEYVALS}) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/module_list.c.in ${CMAKE_CURRENT_BINARY_DIR}/${CFE_PSP_TARGETNAME}_module_list.c @ONLY) add_library(psp-${CFE_PSP_TARGETNAME} STATIC @@ -60,7 +63,7 @@ target_link_libraries(psp-${CFE_PSP_TARGETNAME} PRIVATE psp_module_api ) -target_include_directories(psp-${CFE_PSP_TARGETNAME} INTERFACE +target_include_directories(psp-${CFE_PSP_TARGETNAME} INTERFACE fsw/inc ) diff --git a/fsw/mcp750-vxworks/psp_module_list.cmake b/fsw/mcp750-vxworks/psp_module_list.cmake index ba9cd802..2c52f2bd 100644 --- a/fsw/mcp750-vxworks/psp_module_list.cmake +++ b/fsw/mcp750-vxworks/psp_module_list.cmake @@ -1,4 +1,6 @@ -# This is a list of modules that is included as a fixed/base set +# This is a list of modules that is included as a fixed/base set # when this PSP is selected. They must exist under fsw/modules eeprom_direct +ram_direct +port_direct diff --git a/fsw/mcp750-vxworks/src/cfe_psp_start.c b/fsw/mcp750-vxworks/src/cfe_psp_start.c index c8c2484d..eccac695 100644 --- a/fsw/mcp750-vxworks/src/cfe_psp_start.c +++ b/fsw/mcp750-vxworks/src/cfe_psp_start.c @@ -59,6 +59,7 @@ #include "cfe_psp.h" #include "cfe_psp_memory.h" +#include "cfe_psp_module.h" /* ** External Declarations @@ -146,6 +147,11 @@ void OS_Application_Startup(void) */ CFE_PSP_SetupReservedMemoryMap(); + /* + ** Initialize the statically linked modules (if any) + */ + CFE_PSP_ModuleInit(); + /* ** Determine Reset type by reading the hardware reset register. */ diff --git a/fsw/modules/eeprom_notimpl/CMakeLists.txt b/fsw/modules/eeprom_notimpl/CMakeLists.txt new file mode 100644 index 00000000..a855cfa0 --- /dev/null +++ b/fsw/modules/eeprom_notimpl/CMakeLists.txt @@ -0,0 +1,3 @@ + +# Create the module +add_psp_module(eeprom_notimpl cfe_psp_eeprom_notimpl.c) diff --git a/fsw/modules/eeprom_stub/cfe_psp_eeprom_stub.c b/fsw/modules/eeprom_notimpl/cfe_psp_eeprom_notimpl.c similarity index 82% rename from fsw/modules/eeprom_stub/cfe_psp_eeprom_stub.c rename to fsw/modules/eeprom_notimpl/cfe_psp_eeprom_notimpl.c index ca9d936f..b091bfca 100644 --- a/fsw/modules/eeprom_stub/cfe_psp_eeprom_stub.c +++ b/fsw/modules/eeprom_notimpl/cfe_psp_eeprom_notimpl.c @@ -19,23 +19,23 @@ */ /** - * \file cfe_psp_eeprom_stub.c + * \file cfe_psp_eeprom_notimpl.c * - * Created on: Jul 17, 2015 - * Author: joseph.p.hickey@nasa.gov + * A PSP module to satisfy the "EEPROM" API on systems which + * do not have an EEPROM or otherwise cannot access it. * - * This is a stub implementation of the PSP EEPROM API calls that return CFE_PSP_ERROR_NOT_IMPLEMENTED + * All functions return CFE_PSP_ERR_NOT_IMPLEMENTED */ #include "cfe_psp.h" #include "cfe_psp_module.h" -CFE_PSP_MODULE_DECLARE_SIMPLE(eeprom_stub); +CFE_PSP_MODULE_DECLARE_SIMPLE(eeprom_notimpl); -void eeprom_stub_Init(uint32 PspModuleId) +void eeprom_notimpl_Init(uint32 PspModuleId) { /* Inform the user that this module is in use */ - printf("CFE_PSP: Using STUB EEPROM implementation\n"); + printf("CFE_PSP: EEPROM access not implemented\n"); } int32 CFE_PSP_EepromWrite32(cpuaddr MemoryAddress, uint32 uint32Value) diff --git a/fsw/modules/eeprom_stub/CMakeLists.txt b/fsw/modules/eeprom_stub/CMakeLists.txt deleted file mode 100644 index dfe4b362..00000000 --- a/fsw/modules/eeprom_stub/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ - -# Create the module -add_psp_module(eeprom_stub cfe_psp_eeprom_stub.c) diff --git a/fsw/modules/port_direct/CMakeLists.txt b/fsw/modules/port_direct/CMakeLists.txt new file mode 100644 index 00000000..2b712a23 --- /dev/null +++ b/fsw/modules/port_direct/CMakeLists.txt @@ -0,0 +1,3 @@ + +# Create the module +add_psp_module(port_direct cfe_psp_port_direct.c) diff --git a/fsw/shared/src/cfe_psp_port.c b/fsw/modules/port_direct/cfe_psp_port_direct.c similarity index 92% rename from fsw/shared/src/cfe_psp_port.c rename to fsw/modules/port_direct/cfe_psp_port_direct.c index 695941bf..8adbdd9b 100644 --- a/fsw/shared/src/cfe_psp_port.c +++ b/fsw/modules/port_direct/cfe_psp_port_direct.c @@ -18,25 +18,23 @@ ** limitations under the License. */ -/* -** File : cfe_pep_memport.c -** -** Author : Ezra Yeheskeli -** -** Purpose: -** This file contains some of the cFE Platform Support Layer. -** It contains the processor architecture specific calls. -** -** 16-Nov-2003 Ezra Yeheskeli -** - First Creation. -** -*/ - -/* -** Include section -*/ +/** + * \file cfe_psp_port_direct.c + * + * A PSP module to satisfy the "PORT" API on systems which + * can access I/O ports directly via memory mapped addresses. + */ #include "cfe_psp.h" +#include "cfe_psp_module.h" + +CFE_PSP_MODULE_DECLARE_SIMPLE(port_direct); + +void port_direct_Init(uint32 PspModuleId) +{ + /* Inform the user that this module is in use */ + printf("CFE_PSP: Using DIRECT memory mapped PORT implementation\n"); +} /* ** global memory diff --git a/fsw/modules/port_notimpl/CMakeLists.txt b/fsw/modules/port_notimpl/CMakeLists.txt new file mode 100644 index 00000000..ddb504b8 --- /dev/null +++ b/fsw/modules/port_notimpl/CMakeLists.txt @@ -0,0 +1,3 @@ + +# Create the module +add_psp_module(port_notimpl cfe_psp_port_notimpl.c) diff --git a/fsw/modules/port_notimpl/cfe_psp_port_notimpl.c b/fsw/modules/port_notimpl/cfe_psp_port_notimpl.c new file mode 100644 index 00000000..5d63a339 --- /dev/null +++ b/fsw/modules/port_notimpl/cfe_psp_port_notimpl.c @@ -0,0 +1,69 @@ +/* +** 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_port_notimpl.c + * + * A PSP module to satisfy the "Port" API on systems which + * do not have or otherwise cannot access I/O ports. + * + * All functions return CFE_PSP_ERR_NOT_IMPLEMENTED + */ + +#include "cfe_psp.h" +#include "cfe_psp_module.h" + +CFE_PSP_MODULE_DECLARE_SIMPLE(port_notimpl); + +void port_notimpl_Init(uint32 PspModuleId) +{ + /* Inform the user that this module is in use */ + printf("CFE_PSP: I/O Port access not implemented\n"); +} + +int32 CFE_PSP_PortRead8(cpuaddr PortAddress, uint8 *ByteValue) +{ + return (CFE_PSP_ERROR_NOT_IMPLEMENTED); +} + +int32 CFE_PSP_PortWrite8(cpuaddr PortAddress, uint8 ByteValue) +{ + return (CFE_PSP_ERROR_NOT_IMPLEMENTED); +} + +int32 CFE_PSP_PortRead16(cpuaddr PortAddress, uint16 *uint16Value) +{ + return (CFE_PSP_ERROR_NOT_IMPLEMENTED); +} + +int32 CFE_PSP_PortWrite16(cpuaddr PortAddress, uint16 uint16Value) +{ + return (CFE_PSP_ERROR_NOT_IMPLEMENTED); +} + +int32 CFE_PSP_PortRead32(cpuaddr PortAddress, uint32 *uint32Value) +{ + return (CFE_PSP_ERROR_NOT_IMPLEMENTED); +} + +int32 CFE_PSP_PortWrite32(cpuaddr PortAddress, uint32 uint32Value) +{ + return (CFE_PSP_ERROR_NOT_IMPLEMENTED); +} diff --git a/fsw/modules/ram_direct/CMakeLists.txt b/fsw/modules/ram_direct/CMakeLists.txt new file mode 100644 index 00000000..f81bd6b9 --- /dev/null +++ b/fsw/modules/ram_direct/CMakeLists.txt @@ -0,0 +1,3 @@ + +# Create the module +add_psp_module(ram_direct cfe_psp_ram_direct.c) diff --git a/fsw/shared/src/cfe_psp_ram.c b/fsw/modules/ram_direct/cfe_psp_ram_direct.c similarity index 92% rename from fsw/shared/src/cfe_psp_ram.c rename to fsw/modules/ram_direct/cfe_psp_ram_direct.c index d3653ba8..ce9922a0 100644 --- a/fsw/shared/src/cfe_psp_ram.c +++ b/fsw/modules/ram_direct/cfe_psp_ram_direct.c @@ -18,25 +18,23 @@ ** limitations under the License. */ -/* -** File : cfe_psp_memram.c -** -** Author : Ezra Yeheskeli -** -** Purpose: -** This file contains some of the cFE Platform Support Layer. -** It contains the processor architecture specific calls. -** -** 16-Nov-2003 Ezra Yeheskeli -** - First Creation. -** -*/ - -/* -** Include section -*/ +/** + * \file cfe_psp_ram_direct.c + * + * A PSP module to satisfy the "RAM" API on systems which + * can access physical memory directly. + */ #include "cfe_psp.h" +#include "cfe_psp_module.h" + +CFE_PSP_MODULE_DECLARE_SIMPLE(ram_direct); + +void ram_direct_Init(uint32 PspModuleId) +{ + /* Inform the user that this module is in use */ + printf("CFE_PSP: Using DIRECT memory mapped RAM implementation\n"); +} /* ** global memory diff --git a/fsw/modules/ram_notimpl/CMakeLists.txt b/fsw/modules/ram_notimpl/CMakeLists.txt new file mode 100644 index 00000000..6f7ba325 --- /dev/null +++ b/fsw/modules/ram_notimpl/CMakeLists.txt @@ -0,0 +1,3 @@ + +# Create the module +add_psp_module(ram_notimpl cfe_psp_ram_notimpl.c) diff --git a/fsw/modules/ram_notimpl/cfe_psp_ram_notimpl.c b/fsw/modules/ram_notimpl/cfe_psp_ram_notimpl.c new file mode 100644 index 00000000..573d081d --- /dev/null +++ b/fsw/modules/ram_notimpl/cfe_psp_ram_notimpl.c @@ -0,0 +1,69 @@ +/* +** 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_ram_notimpl.c + * + * A PSP module to satisfy the "RAM" API on systems which + * cannot access physical memory directly. + * + * All functions return CFE_PSP_ERR_NOT_IMPLEMENTED + */ + +#include "cfe_psp.h" +#include "cfe_psp_module.h" + +CFE_PSP_MODULE_DECLARE_SIMPLE(ram_notimpl); + +void ram_notimpl_Init(uint32 PspModuleId) +{ + /* Inform the user that this module is in use */ + printf("CFE_PSP: Physical RAM access not implemented\n"); +} + +int32 CFE_PSP_MemRead8(cpuaddr MemoryAddress, uint8 *ByteValue) +{ + return (CFE_PSP_ERROR_NOT_IMPLEMENTED); +} + +int32 CFE_PSP_MemWrite8(cpuaddr MemoryAddress, uint8 ByteValue) +{ + return (CFE_PSP_ERROR_NOT_IMPLEMENTED); +} + +int32 CFE_PSP_MemRead16(cpuaddr MemoryAddress, uint16 *uint16Value) +{ + return (CFE_PSP_ERROR_NOT_IMPLEMENTED); +} + +int32 CFE_PSP_MemWrite16(cpuaddr MemoryAddress, uint16 uint16Value) +{ + return (CFE_PSP_ERROR_NOT_IMPLEMENTED); +} + +int32 CFE_PSP_MemRead32(cpuaddr MemoryAddress, uint32 *uint32Value) +{ + return (CFE_PSP_ERROR_NOT_IMPLEMENTED); +} + +int32 CFE_PSP_MemWrite32(cpuaddr MemoryAddress, uint32 uint32Value) +{ + return (CFE_PSP_ERROR_NOT_IMPLEMENTED); +} diff --git a/fsw/pc-linux/psp_module_list.cmake b/fsw/pc-linux/psp_module_list.cmake index 54ffb4c5..b1f9dae0 100644 --- a/fsw/pc-linux/psp_module_list.cmake +++ b/fsw/pc-linux/psp_module_list.cmake @@ -1,4 +1,6 @@ -# This is a list of modules that is included as a fixed/base set +# This is a list of modules that is included as a fixed/base set # when this PSP is selected. They must exist under fsw/modules eeprom_mmap_file +ram_notimpl +port_notimpl diff --git a/fsw/pc-rtems/psp_module_list.cmake b/fsw/pc-rtems/psp_module_list.cmake index 38b24e37..21b48ba6 100644 --- a/fsw/pc-rtems/psp_module_list.cmake +++ b/fsw/pc-rtems/psp_module_list.cmake @@ -1,4 +1,6 @@ -# This is a list of modules that is included as a fixed/base set +# This is a list of modules that is included as a fixed/base set # when this PSP is selected. They must exist under fsw/modules -eeprom_stub +eeprom_notimpl +ram_direct +port_notimpl diff --git a/fsw/shared/CMakeLists.txt b/fsw/shared/CMakeLists.txt index b977467c..f4da3c72 100644 --- a/fsw/shared/CMakeLists.txt +++ b/fsw/shared/CMakeLists.txt @@ -18,15 +18,13 @@ add_library(psp-${CFE_PSP_TARGETNAME}-shared OBJECT src/cfe_psp_memrange.c src/cfe_psp_memutils.c src/cfe_psp_module.c - src/cfe_psp_port.c - src/cfe_psp_ram.c ) target_compile_definitions(psp-${CFE_SYSTEM_PSPNAME}-shared PRIVATE $ ) -target_include_directories(psp-${CFE_PSP_TARGETNAME}-shared PRIVATE +target_include_directories(psp-${CFE_PSP_TARGETNAME}-shared PRIVATE $ ) From bfbd1b22e8a77d4611fe600adab0d0a94b1462c3 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Fri, 26 Mar 2021 14:57:14 -0400 Subject: [PATCH 2/6] Fix #171, use OSAL timebase for CFE timers Add a new PSP module that instantiates an OSAL abstract timebase for use with cFE services. This single module is then used across all 3 implementations (mcp750, pc-linux, pc-rtems) and does not need to be duplicated. --- fsw/inc/cfe_psp.h | 7 + fsw/mcp750-vxworks/inc/cfe_psp_config.h | 10 ++ fsw/mcp750-vxworks/psp_module_list.cmake | 3 +- fsw/mcp750-vxworks/src/cfe_psp_start.c | 28 ---- fsw/modules/soft_timebase/CMakeLists.txt | 3 + .../soft_timebase/cfe_psp_soft_timebase.c | 82 ++++++++++ fsw/pc-linux/inc/cfe_psp_config.h | 13 ++ fsw/pc-linux/psp_module_list.cmake | 3 +- fsw/pc-linux/src/cfe_psp_start.c | 142 ------------------ fsw/pc-rtems/inc/cfe_psp_config.h | 13 ++ fsw/pc-rtems/psp_module_list.cmake | 3 +- fsw/pc-rtems/src/cfe_psp_start.c | 48 ------ 12 files changed, 134 insertions(+), 221 deletions(-) create mode 100644 fsw/modules/soft_timebase/CMakeLists.txt create mode 100644 fsw/modules/soft_timebase/cfe_psp_soft_timebase.c diff --git a/fsw/inc/cfe_psp.h b/fsw/inc/cfe_psp.h index 47202913..19da8be7 100644 --- a/fsw/inc/cfe_psp.h +++ b/fsw/inc/cfe_psp.h @@ -153,6 +153,13 @@ #define CFE_PSP_MISSION_REV (GLOBAL_PSP_CONFIGDATA.PSP_VersionInfo.MissionRev) #define CFE_PSP_VERSION (GLOBAL_PSP_CONFIGDATA.PSP_VersionInfo.VersionString) +/** + * \brief The name of the software/RTOS timebase for general system timers. + * + * This name may be referred to by CFE TIME and/or SCH when setting up its own timers. + */ +#define CFE_PSP_SOFT_TIMEBASE_NAME "cFS-Master" + /* ** Type Definitions */ diff --git a/fsw/mcp750-vxworks/inc/cfe_psp_config.h b/fsw/mcp750-vxworks/inc/cfe_psp_config.h index fc88a42f..d109d5e1 100644 --- a/fsw/mcp750-vxworks/inc/cfe_psp_config.h +++ b/fsw/mcp750-vxworks/inc/cfe_psp_config.h @@ -51,6 +51,16 @@ */ #define CFE_PSP_MAX_EXCEPTION_ENTRIES 4 +/* + * The tick period that will be configured in the RTOS for the simulated + * time base, in microseconds. This in turn is used to drive the 1hz clock + * and other functions. + * + * On the MCP750 the sysClockRate runs at 60Hz so this is the same period + * that the cFE software timebase will be configured at. + */ +#define CFE_PSP_SOFT_TIMEBASE_PERIOD 16666 + /* ** Typedef for the layout of the vxWorks boot record structure ** diff --git a/fsw/mcp750-vxworks/psp_module_list.cmake b/fsw/mcp750-vxworks/psp_module_list.cmake index ba9cd802..e9e6bb66 100644 --- a/fsw/mcp750-vxworks/psp_module_list.cmake +++ b/fsw/mcp750-vxworks/psp_module_list.cmake @@ -1,4 +1,5 @@ -# This is a list of modules that is included as a fixed/base set +# This is a list of modules that is included as a fixed/base set # when this PSP is selected. They must exist under fsw/modules +soft_timebase eeprom_direct diff --git a/fsw/mcp750-vxworks/src/cfe_psp_start.c b/fsw/mcp750-vxworks/src/cfe_psp_start.c index c8c2484d..a64c6f3c 100644 --- a/fsw/mcp750-vxworks/src/cfe_psp_start.c +++ b/fsw/mcp750-vxworks/src/cfe_psp_start.c @@ -74,7 +74,6 @@ IMPORT void sysPciWrite32(UINT32, UINT32); #define CFE_PSP_MAIN_FUNCTION (*GLOBAL_CONFIGDATA.CfeConfig->SystemMain) #define CFE_PSP_NONVOL_STARTUP_FILE (GLOBAL_CONFIGDATA.CfeConfig->NonvolStartupFile) -#define CFE_PSP_1HZ_FUNCTION (*GLOBAL_CONFIGDATA.CfeConfig->System1HzISR) /****************************************************************************** ** Function: OS_Application_Startup() @@ -232,30 +231,3 @@ void OS_Application_Startup(void) */ CFE_PSP_MAIN_FUNCTION(reset_type, reset_subtype, 1, CFE_PSP_NONVOL_STARTUP_FILE); } - -/****************************************************************************** -** Function: OS_Application_Run() -** -** Purpose: -** Idle Loop entry point from OSAL BSP. -** -** Arguments: -** (none) -** -** Return: -** (none) -*/ -void OS_Application_Run(void) -{ - int TicksPerSecond; - - /* - ** Main loop for default task and simulated 1hz - */ - for (;;) - { - TicksPerSecond = sysClkRateGet(); - (void)taskDelay(TicksPerSecond); - CFE_PSP_1HZ_FUNCTION(); - } -} diff --git a/fsw/modules/soft_timebase/CMakeLists.txt b/fsw/modules/soft_timebase/CMakeLists.txt new file mode 100644 index 00000000..29a077dc --- /dev/null +++ b/fsw/modules/soft_timebase/CMakeLists.txt @@ -0,0 +1,3 @@ + +# Create the module +add_psp_module(soft_timebase cfe_psp_soft_timebase.c) diff --git a/fsw/modules/soft_timebase/cfe_psp_soft_timebase.c b/fsw/modules/soft_timebase/cfe_psp_soft_timebase.c new file mode 100644 index 00000000..b9d9e4fb --- /dev/null +++ b/fsw/modules/soft_timebase/cfe_psp_soft_timebase.c @@ -0,0 +1,82 @@ +/* +** 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_soft_timebase.c + * + * A PSP module that instantiates an RTOS-backed OSAL timebase to provide + * various timing services. This in turn may be used to drive CFE TIME 1Hz + * signal, the CFS SCH major/minor frame sync and other periodic services + * in CFE. + * + * This module can be used on systems which do not have a hardware + * source for the 1Hz signal or timing info (i.e. simulation, test + * and debug platforms, etc). + */ + +#include "cfe_psp.h" +#include "cfe_psp_module.h" +#include "cfe_psp_config.h" + +CFE_PSP_MODULE_DECLARE_SIMPLE(soft_timebase); + +/* + * Global state data for this module (not exposed publicly) + */ +static struct +{ + osal_id_t sys_timebase_id; +} PSP_SoftTimebase_Global; + +void soft_timebase_Init(uint32 PspModuleId) +{ + int32 status; + + memset(&PSP_SoftTimebase_Global, 0, sizeof(PSP_SoftTimebase_Global)); + + /* Set up the OSAL timebase using the well-known name */ + status = OS_TimeBaseCreate(&PSP_SoftTimebase_Global.sys_timebase_id, CFE_PSP_SOFT_TIMEBASE_NAME, NULL); + if (status == OS_SUCCESS) + { + /* Set the timebase to trigger with desired resolution */ + status = OS_TimeBaseSet(PSP_SoftTimebase_Global.sys_timebase_id, CFE_PSP_SOFT_TIMEBASE_PERIOD, + CFE_PSP_SOFT_TIMEBASE_PERIOD); + } + + /* + * The only way this can fail is through a misconfiguration or API incompatibility - + * if it fails, it means all timing related functions are likely to be broken, + * CFE TIME may not work correctly, and background jobs will not run. + * + * Might even be worth a CFE_PSP_Panic(), but it still may be possible + * to boot CFE and (maybe) save the system by uploading a file with the bug fixed. + */ + if (status != OS_SUCCESS) + { + printf("CFE_PSP: *** Failed to configure software timebase \'%s\', status = %d! ***\n", + CFE_PSP_SOFT_TIMEBASE_NAME, (int)status); + } + else + { + /* Inform the user that this module is in use */ + printf("CFE_PSP: Instantiated software timebase \'%s\' running at %lu usec\n", CFE_PSP_SOFT_TIMEBASE_NAME, + (unsigned long)CFE_PSP_SOFT_TIMEBASE_PERIOD); + } +} diff --git a/fsw/pc-linux/inc/cfe_psp_config.h b/fsw/pc-linux/inc/cfe_psp_config.h index 02c66a2a..316a9529 100644 --- a/fsw/pc-linux/inc/cfe_psp_config.h +++ b/fsw/pc-linux/inc/cfe_psp_config.h @@ -65,6 +65,19 @@ /* use the "USR1" signal to wake the idle thread when an exception occurs */ #define CFE_PSP_EXCEPTION_EVENT_SIGNAL SIGUSR1 +/* + * The tick period that will be configured in the RTOS for the simulated + * time base, in microseconds. This in turn is used to drive the 1hz clock + * and other functions. + * + * To minimize jitter in the resulting callbacks, it should be an even + * divisor of 1000000 usec. + * + * Note - 10ms/100Hz is chosen to also allow this same timebase to be + * used to drive the CFS SCH minor frame callbacks in its default config. + */ +#define CFE_PSP_SOFT_TIMEBASE_PERIOD 10000 + /* ** Global variables */ diff --git a/fsw/pc-linux/psp_module_list.cmake b/fsw/pc-linux/psp_module_list.cmake index 54ffb4c5..0f295787 100644 --- a/fsw/pc-linux/psp_module_list.cmake +++ b/fsw/pc-linux/psp_module_list.cmake @@ -1,4 +1,5 @@ -# This is a list of modules that is included as a fixed/base set +# This is a list of modules that is included as a fixed/base set # when this PSP is selected. They must exist under fsw/modules +soft_timebase eeprom_mmap_file diff --git a/fsw/pc-linux/src/cfe_psp_start.c b/fsw/pc-linux/src/cfe_psp_start.c index ff0479ea..4e709a62 100644 --- a/fsw/pc-linux/src/cfe_psp_start.c +++ b/fsw/pc-linux/src/cfe_psp_start.c @@ -113,10 +113,8 @@ typedef struct /* ** Prototypes for this module */ -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); /* ** Global variables @@ -212,8 +210,6 @@ void OS_Application_Startup(void) { uint32 reset_type; uint32 reset_subtype; - int32 time_status; - osal_id_t sys_timebase_id; osal_id_t fs_id; int opt = 0; int longIndex = 0; @@ -342,41 +338,6 @@ void OS_Application_Startup(void) 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 - ** - ** This is a clock named "cFS-Master" that will serve to drive - ** all time-related CFE functions including the 1Hz signal. - ** - ** Note the timebase is only prepared here; the application is - ** not ready to receive a callback yet, as it hasn't been started. - ** CFE TIME registers its own callback when it is ready to do so. - */ - time_status = OS_TimeBaseCreate(&sys_timebase_id, "cFS-Master", NULL); - if (time_status == OS_SUCCESS) - { - /* - * Set the clock to trigger with 50ms resolution - slow enough that - * it will not hog CPU resources but fast enough to have sufficient resolution - * for most general timing purposes. - * (It may be better to move this to the mission config file) - */ - time_status = OS_TimeBaseSet(sys_timebase_id, 50000, 50000); - } - else - { - /* - * Cannot create a timebase in OSAL. - * - * Note: Most likely this is due to building with - * the old/classic POSIX OSAL which does not support this. - * - * See below for workaround. - */ - sys_timebase_id = OS_OBJECT_ID_UNDEFINED; - } - /* ** Set up the virtual FS mapping for the "/cf" directory ** On this platform it is just a local/relative dir of the same name. @@ -453,15 +414,6 @@ void OS_Application_Startup(void) ** Call cFE entry point. */ CFE_PSP_MAIN_FUNCTION(reset_type, reset_subtype, 1, CFE_PSP_NONVOL_STARTUP_FILE); - - /* - * Backward compatibility for old OSAL. - */ - if (!OS_ObjectIdDefined(sys_timebase_id) || time_status != OS_SUCCESS) - { - OS_printf("CFE_PSP: WARNING - Compatibility mode - using local 1Hz Interrupt\n"); - CFE_PSP_SetupLocal1Hz(); - } } void OS_Application_Run(void) @@ -522,31 +474,6 @@ void OS_Application_Run(void) OS_DeleteAllObjects(); } -/****************************************************************************** -** Function: CFE_PSP_TimerHandler() -** -** Purpose: -** 1hz "isr" routine for linux/OSX -** This timer handler will execute 4 times a second. -** -** Arguments: -** (none) -** -** Return: -** (none) -*/ -void CFE_PSP_TimerHandler(int signum) -{ - /* - ** call the CFE_TIME 1hz ISR - */ - if ((TimerCounter % 4) == 0) - CFE_PSP_1HZ_FUNCTION(); - - /* update timer counter */ - TimerCounter++; -} - /****************************************************************************** ** Function: CFE_PSP_DisplayUsage ** @@ -639,72 +566,3 @@ void CFE_PSP_ProcessArgumentDefaults(CFE_PSP_CommandData_t *CommandDataDefault) CommandDataDefault->GotCpuName = 1; } } - -/****************************************************************************** -** Function: CFE_PSP_SetupLocal1Hz -** -** Purpose: -** This is a backward-compatible timer setup that is invoked when -** there is a failure to set up the timebase in OSAL. It is basically -** the old way of doing things. -** -** IMPORTANT: Note this is technically incorrect as it gives the -** callback directly in the context of the signal handler. It is -** against spec to use most OSAL functions within a signal. -** -** This is included merely to mimic the previous system behavior. It -** should be removed in a future version of the PSP. -** -** -** Arguments: -** (none) -** -** Return: -** (none) -** -*/ - -void CFE_PSP_SetupLocal1Hz(void) -{ - struct sigaction sa; - struct itimerval timer; - int ret; - - /* - ** Init timer counter - */ - TimerCounter = 0; - - /* - ** Install timer_handler as the signal handler for SIGALRM. - */ - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = &CFE_PSP_TimerHandler; - - /* - ** Configure the timer to expire after 250ms - ** - ** (this is historical; the actual callback is invoked - ** only on every 4th timer tick. previous versions of the - ** PSP did it this way, so this is preserved here). - */ - timer.it_value.tv_sec = 0; - timer.it_value.tv_usec = 250000; - timer.it_interval.tv_sec = 0; - timer.it_interval.tv_usec = 250000; - - ret = sigaction(SIGALRM, &sa, NULL); - - if (ret < 0) - { - OS_printf("CFE_PSP: sigaction() error %d: %s \n", ret, strerror(errno)); - } - else - { - ret = setitimer(ITIMER_REAL, &timer, NULL); - if (ret < 0) - { - OS_printf("CFE_PSP: setitimer() error %d: %s \n", ret, strerror(errno)); - } - } -} diff --git a/fsw/pc-rtems/inc/cfe_psp_config.h b/fsw/pc-rtems/inc/cfe_psp_config.h index 376d2f75..2ef50afe 100644 --- a/fsw/pc-rtems/inc/cfe_psp_config.h +++ b/fsw/pc-rtems/inc/cfe_psp_config.h @@ -43,6 +43,19 @@ */ #define CFE_PSP_MAX_EXCEPTION_ENTRIES 1 +/* + * The tick period that will be configured in the RTOS for the simulated + * time base, in microseconds. This in turn is used to drive the 1hz clock + * and other functions. + * + * To minimize jitter in the resulting callbacks, it should be an even + * divisor of 1000000 usec. + * + * Note - 10ms/100Hz is chosen to also allow this same timebase to be + * used to drive the CFS SCH minor frame callbacks in its default config. + */ +#define CFE_PSP_SOFT_TIMEBASE_PERIOD 10000 + /* ** Typedef for the layout of the header in the reserved memory block */ diff --git a/fsw/pc-rtems/psp_module_list.cmake b/fsw/pc-rtems/psp_module_list.cmake index 38b24e37..4eb1ac4f 100644 --- a/fsw/pc-rtems/psp_module_list.cmake +++ b/fsw/pc-rtems/psp_module_list.cmake @@ -1,4 +1,5 @@ -# This is a list of modules that is included as a fixed/base set +# This is a list of modules that is included as a fixed/base set # when this PSP is selected. They must exist under fsw/modules eeprom_stub +soft_timebase diff --git a/fsw/pc-rtems/src/cfe_psp_start.c b/fsw/pc-rtems/src/cfe_psp_start.c index 66361c4a..d3057131 100644 --- a/fsw/pc-rtems/src/cfe_psp_start.c +++ b/fsw/pc-rtems/src/cfe_psp_start.c @@ -131,51 +131,6 @@ int CFE_PSP_Setup(void) return RTEMS_SUCCESSFUL; } -/****************************************************************************** -** Function: CFE_PSP_SetupSystemTimer -** -** Purpose: -** BSP system time base and timer object setup. -** This does the necessary work to start the 1Hz time tick required by CFE -** -** Arguments: -** (none) -** -** Return: -** (none) -** -** NOTE: -** The handles to the timebase/timer objects are "start and forget" -** as they are supposed to run forever as long as CFE runs. -** -** If needed for e.g. additional timer creation, they can be recovered -** using an OSAL GetIdByName() call. -** -** This is preferred anyway -- far cleaner than trying to pass the uint32 value -** up to the application somehow. -*/ - -void CFE_PSP_SetupSystemTimer(void) -{ - osal_id_t SystemTimebase; - int32 Status; - - Status = OS_TimeBaseCreate(&SystemTimebase, "cFS-Master", NULL); - if (Status == OS_SUCCESS) - { - Status = OS_TimeBaseSet(SystemTimebase, 250000, 250000); - } - - /* - * If anything failed, cFE/cFS will not run properly, so a panic is appropriate - */ - if (Status != OS_SUCCESS) - { - OS_printf("CFE_PSP: Error configuring cFS timing: %d\n", (int)Status); - CFE_PSP_Panic(Status); - } -} - /* ** A simple entry point to start from the BSP loader ** @@ -263,9 +218,6 @@ void CFE_PSP_Main(void) */ CFE_PSP_ModuleInit(); - /* Prepare the system timing resources */ - CFE_PSP_SetupSystemTimer(); - /* ** Determine Reset type by reading the hardware reset register. */ From fc6e9b23985761e168f354919b5e3b91f73b1449 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Fri, 26 Mar 2021 14:39:28 -0400 Subject: [PATCH 3/6] Fix #266, psp module to implement timebase Clarifies the use case for CFE_PSP_GetTime and CFE_PSP_GetTimeBase. Moves the implementation of these to separate PSP modules, so MCP750 on VxWorks can use the optimized vxTimeBaseGet() routine while Linux and RTEMS can use the generic posix CLOCK_MONOTONIC. --- fsw/inc/cfe_psp.h | 49 +++- fsw/mcp750-vxworks/CMakeLists.txt | 1 - fsw/mcp750-vxworks/inc/cfe_psp_config.h | 17 ++ fsw/mcp750-vxworks/psp_module_list.cmake | 1 + fsw/mcp750-vxworks/src/cfe_psp_timer.c | 229 ---------------- .../timebase_posix_clock/CMakeLists.txt | 3 + .../cfe_psp_timebase_posix_clock.c | 161 +++++++++++ fsw/modules/timebase_vxworks/CMakeLists.txt | 3 + .../cfe_psp_timebase_vxworks.c | 250 ++++++++++++++++++ fsw/pc-linux/CMakeLists.txt | 4 +- fsw/pc-linux/psp_module_list.cmake | 1 + fsw/pc-linux/src/cfe_psp_timer.c | 192 -------------- fsw/pc-rtems/CMakeLists.txt | 1 - fsw/pc-rtems/psp_module_list.cmake | 1 + fsw/pc-rtems/src/cfe_psp_timer.c | 188 ------------- unit-test-coverage/CMakeLists.txt | 1 + unit-test-coverage/modules/CMakeLists.txt | 67 +++++ .../modules/inc/cfe_psp_config.h | 35 +++ .../inc/coveragetest-timebase_vxworks.h | 29 ++ .../src/coveragetest-timebase_vxworks.c | 224 ++++++++++++++++ unit-test-coverage/ut-stubs/inc/PCS_time.h | 19 ++ .../ut-stubs/override_inc/time.h | 17 ++ .../ut-stubs/src/vxworks-vxLib-stubs.c | 4 +- 23 files changed, 877 insertions(+), 620 deletions(-) delete mode 100644 fsw/mcp750-vxworks/src/cfe_psp_timer.c create mode 100644 fsw/modules/timebase_posix_clock/CMakeLists.txt create mode 100644 fsw/modules/timebase_posix_clock/cfe_psp_timebase_posix_clock.c create mode 100644 fsw/modules/timebase_vxworks/CMakeLists.txt create mode 100644 fsw/modules/timebase_vxworks/cfe_psp_timebase_vxworks.c delete mode 100644 fsw/pc-linux/src/cfe_psp_timer.c delete mode 100644 fsw/pc-rtems/src/cfe_psp_timer.c create mode 100644 unit-test-coverage/modules/CMakeLists.txt create mode 100644 unit-test-coverage/modules/inc/cfe_psp_config.h create mode 100644 unit-test-coverage/modules/inc/coveragetest-timebase_vxworks.h create mode 100644 unit-test-coverage/modules/src/coveragetest-timebase_vxworks.c create mode 100644 unit-test-coverage/ut-stubs/inc/PCS_time.h create mode 100644 unit-test-coverage/ut-stubs/override_inc/time.h diff --git a/fsw/inc/cfe_psp.h b/fsw/inc/cfe_psp.h index 47202913..4d5615b5 100644 --- a/fsw/inc/cfe_psp.h +++ b/fsw/inc/cfe_psp.h @@ -185,10 +185,26 @@ extern void CFE_PSP_Main(void); ** The flight software (i.e. cFE ) should not call this routine. */ +/** + * \brief Sample/Read a monotonic platform clock with normalization + * + * Outputs an OS_time_t value indicating the time elapsed since an epoch. The + * epoch is not defined, but typically represents the system boot time. The + * value increases continously over time and cannot be reset by software. + * + * This is similar to the CFE_PSP_Get_Timebase(), but additionally it normalizes + * the output value to an OS_time_t, thereby providing consistent units to + * the calling application. Any OSAL-provided routine accepts OS_time_t inputs + * may be used to convert this value into other standardized time units. + * + * \note This should refer to the same time domain as CFE_PSP_Get_Timebase(), + * the primary difference being the format and units of the output value. + * + * \sa CFE_PSP_Get_Timebase() + * + * \param[out] LocalTime Value of PSP tick counter as OS_time_t + */ extern void CFE_PSP_GetTime(OS_time_t *LocalTime); -/* This call gets the local time from the hardware on the Vxworks system - * on the mcp750s - * on the other os/hardware setup, it will get the time the normal way */ extern void CFE_PSP_Restart(uint32 resetType); /* @@ -248,10 +264,31 @@ extern uint32 CFE_PSP_GetTimerLow32Rollover(void); ** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. */ +/** + * \brief Sample/Read a monotonic platform clock without normalization + * + * This is defined as a free-running, monotonically-increasing tick counter. The + * epoch is not defined, but typically is the system boot time, and the value increases + * indefinitely as the system runs. The tick period/rate is also not defined. + * + * Rollover events - where the range of representable values is exceeded - are + * theoretically possible, but would take many years of continuous uptime to occur + * (typically hundreds of years, if not thousands). System designers should ensure + * that the actual tick rate and resulting timebase range is sufficiently large to + * ensure that rollover is not a concern. + * + * \note This is a "raw" value from the underlying platform with minimal/no conversions + * or normalization applied. Neither the epoch nor the resolution of this tick + * counter is specified, and it may vary from platform to platform. Use the + * CFE_PSP_GetTime() function to sample the timebase and also convert the units + * into a normalized/more consistent form. + * + * \sa CFE_PSP_GetTime() + * + * \param[out] Tbu Buffer to hold the upper 32 bits of a 64-bit tick counter + * \param[out] Tbl Buffer to hold the lower 32 bits of a 64-bit tick counter + */ extern void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl); -/* -** CFE_PSP_Get_Timebase -*/ extern uint32 CFE_PSP_Get_Dec(void); /* diff --git a/fsw/mcp750-vxworks/CMakeLists.txt b/fsw/mcp750-vxworks/CMakeLists.txt index 1b6972fa..25f1d523 100644 --- a/fsw/mcp750-vxworks/CMakeLists.txt +++ b/fsw/mcp750-vxworks/CMakeLists.txt @@ -15,7 +15,6 @@ add_library(psp-${CFE_PSP_TARGETNAME}-impl OBJECT src/cfe_psp_ssr.c src/cfe_psp_start.c src/cfe_psp_support.c - src/cfe_psp_timer.c src/cfe_psp_watchdog.c ) target_compile_definitions(psp-${CFE_SYSTEM_PSPNAME}-impl PRIVATE diff --git a/fsw/mcp750-vxworks/inc/cfe_psp_config.h b/fsw/mcp750-vxworks/inc/cfe_psp_config.h index fc88a42f..1fee79d8 100644 --- a/fsw/mcp750-vxworks/inc/cfe_psp_config.h +++ b/fsw/mcp750-vxworks/inc/cfe_psp_config.h @@ -37,6 +37,23 @@ #include "taskLib.h" #include "arch/ppc/esfPpc.h" +/** + * \brief Period of the VxWorks timebase, in nanoseconds + * + * This is expressed as a ratio in case it is not a whole number. + * + * Multiplying the timebase register by 60 should yield a result + * in nanoseconds, and then further dividing by the OSAL OS_time_t tick + * resolution will convert to an OS_time_t compatible value. + * + * On the MCP750 - the PPC timebase runs at 60ns period or ~16.67 MHz. + * + * Note this is distinct from the VxWorks system timer tick which runs, + * confusingly, at 60Hz or a ~16.67ms period. + */ +#define CFE_PSP_VX_TIMEBASE_PERIOD_NUMERATOR 60 +#define CFE_PSP_VX_TIMEBASE_PERIOD_DENOMINATOR 1 + /* ** This define sets the number of memory ranges that are defined in the memory range defintion ** table. diff --git a/fsw/mcp750-vxworks/psp_module_list.cmake b/fsw/mcp750-vxworks/psp_module_list.cmake index ba9cd802..122a4201 100644 --- a/fsw/mcp750-vxworks/psp_module_list.cmake +++ b/fsw/mcp750-vxworks/psp_module_list.cmake @@ -1,4 +1,5 @@ # This is a list of modules that is included as a fixed/base set # when this PSP is selected. They must exist under fsw/modules +timebase_vxworks eeprom_direct diff --git a/fsw/mcp750-vxworks/src/cfe_psp_timer.c b/fsw/mcp750-vxworks/src/cfe_psp_timer.c deleted file mode 100644 index 72e7a787..00000000 --- a/fsw/mcp750-vxworks/src/cfe_psp_timer.c +++ /dev/null @@ -1,229 +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: cfe_psp_timer.c -** -** Purpose: -** This file contains glue routines between the cFE and the OS Board Support Package ( BSP ). -** The functions here allow the cFE to interface functions that are board and OS specific -** and usually dont fit well in the OS abstraction layer. -** -** History: -** 2005/06/05 K.Audra | Initial version, -** -*************************************************************************************************/ - -/* -** Include Files -*/ - -/* -** Include Files -*/ -#include -#include -#include -#include "vxWorks.h" -#include "sysLib.h" -#include "vxLib.h" -#include "taskLib.h" -#include "ramDrv.h" -#include "dosFsLib.h" -#include "errnoLib.h" -#include "usrLib.h" -#include "cacheLib.h" -#include "mcpx750.h" -#include "drv/hdisk/ataDrv.h" - -/* -** cFE includes -*/ -#include "common_types.h" -#include "osapi.h" - -/* -** Types and prototypes for this module -*/ -#include "cfe_psp.h" - -IMPORT void sysPciRead32(UINT32, UINT32 *); - -/******************* Macro Definitions ***********************/ - -/** - * \brief Resolution of the least significant 32 bits of the 64 bit - * time stamp returned by CFE_PSP_Get_Timebase in timer ticks per second. - * The timer resolution for accuracy should not be any slower than 1000000 - * ticks per second or 1 us per tick - */ -#define CFE_PSP_TIMER_TICKS_PER_SECOND 16666666 - -/** - * \brief The number that the least significant 32 bits of the 64 bit - * time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 - * bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. - * if the lower 32 bits rolls at its maximum value (2^32) then - * CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. - */ -#define CFE_PSP_TIMER_LOW32_ROLLOVER 0 - -/* -** MCP750/vxWorks timers -*/ -/****************************************************************************** -** Function: CFE_PSP_GetTime() -** -** Purpose: Gets the value of the time from the hardware -** -** Arguments: LocalTime - where the time is returned through -******************************************************************************/ - -void CFE_PSP_GetTime(OS_time_t *LocalTime) -{ - uint32 DecCount; - uint32 Seconds; - - /* Reads the time from the hardware register, then converts it - * into an OS_time_t value */ - sysPciRead32(0xFC0011C0, (UINT32 *)(&DecCount)); - DecCount = DecCount & 0x7FFFFFFF; - DecCount = ((uint32)0x0D6937E5) - DecCount; - - Seconds = DecCount / 8333311; - - /* Get subseconds (discard seconds) */ - DecCount = DecCount % 8333311; - - /* Microsecond conversion - * If speed really matters, recommend testing the following - * options on hardware being used (all should give the exact same answer): - * - long long to avoid overflow: (DecCount*1000000ULL)/8333311 - * - Double w/ divide: DecCount/8.333311 - * - Approximation: ((300 * DecCount) + (DecCount / 1244)) / 2500 - * At cost of up to 2us error (at max value): - * - Approximation: (DecCount * 3) / 25 - * - * Same basic ratio but adjusted to produce units in nanoseconds - * instead of microseconds: - * - ((480 * DecCount) + (DecCount / 777)) / 4 - */ - - DecCount = ((480 * DecCount) + (DecCount / 777)) / 4; - - *LocalTime = OS_TimeAssembleFromNanoseconds(Seconds, DecCount); - -} /* end CFE_PSP_GetLocalTime */ - -/****************************************************************************** -** Function: CFE_PSP_Get_Timer_Tick() -** -** Purpose: -** Provides a common interface to system clock tick. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** OS system clock ticks per second -*/ -uint32 CFE_PSP_Get_Timer_Tick(void) -{ - return (sysClkRateGet()); -} - -/****************************************************************************** -** Function: CFE_PSP_GetTimerTicksPerSecond() -** -** Purpose: -** Provides the resolution of the least significant 32 bits of the 64 bit -** time stamp returned by CFE_PSP_Get_Timebase in timer ticks per second. -** The timer resolution for accuracy should not be any slower than 1000000 -** ticks per second or 1 us per tick -** -** Arguments: -** -** Return: -** The number of timer ticks per second of the time stamp returned -** by CFE_PSP_Get_Timebase -*/ -uint32 CFE_PSP_GetTimerTicksPerSecond(void) -{ - return (CFE_PSP_TIMER_TICKS_PER_SECOND); -} - -/****************************************************************************** -** Function: CFE_PSP_GetTimerLow32Rollover() -** -** Purpose: -** Provides the number that the least significant 32 bits of the 64 bit -** time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 -** bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. -** if the lower 32 bits rolls at its maximum value (2^32) then -** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. -** -** Arguments: -** -** Return: -** The number that the least significant 32 bits of the 64 bit time stamp -** returned by CFE_PSP_Get_Timebase rolls over. -*/ -uint32 CFE_PSP_GetTimerLow32Rollover(void) -{ - return (CFE_PSP_TIMER_LOW32_ROLLOVER); -} - -/****************************************************************************** -** Function: CFE_PSP_Get_Timebase() -** -** Purpose: -** Provides a common interface to system timebase. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** Timebase register value -*/ -void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl) -{ - vxTimeBaseGet((UINT32 *)Tbu, (UINT32 *)Tbl); -} - -/****************************************************************************** -** Function: CFE_PSP_Get_Dec() -** -** Purpose: -** Provides a common interface to decrementer counter. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** Timebase register value -*/ - -uint32 CFE_PSP_Get_Dec(void) -{ - return (vxDecGet()); -} diff --git a/fsw/modules/timebase_posix_clock/CMakeLists.txt b/fsw/modules/timebase_posix_clock/CMakeLists.txt new file mode 100644 index 00000000..7150d1f0 --- /dev/null +++ b/fsw/modules/timebase_posix_clock/CMakeLists.txt @@ -0,0 +1,3 @@ + +# Create the module +add_psp_module(timebase_posix_clock cfe_psp_timebase_posix_clock.c) diff --git a/fsw/modules/timebase_posix_clock/cfe_psp_timebase_posix_clock.c b/fsw/modules/timebase_posix_clock/cfe_psp_timebase_posix_clock.c new file mode 100644 index 00000000..901d6aff --- /dev/null +++ b/fsw/modules/timebase_posix_clock/cfe_psp_timebase_posix_clock.c @@ -0,0 +1,161 @@ +/* +** 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_timebase_posix_clock.c + * + * A PSP module to satisfy the PSP time API on systems which + * do not have a hardware clock register, but do provide a POSIX + * compliant implementation of clock_gettime() and CLOCK_MONOTONIC + * that can fulfill this role. + * + * The POSIX CLOCK_MONOTONIC is defined as a monotonically increasing + * clock that has no specific epoch. It is not affected by local time + * changes and is not settable. + * + * The POSIX interface uses a "struct timespec" which has units in + * nanoseconds, but this is converted down to units of microseconds for + * consistency with previous versions of PSP where CFE_PSP_Get_Timebase() + * returned units of microseconds. + */ + +/* +** System Include Files +*/ +#include +#include +#include + +#include "cfe_psp.h" +#include "cfe_psp_module.h" + +/* + * The specific clock ID to use with clock_gettime + * + * Linux provides some special (non-posix) clock IDs that also + * could be relevant/useful: + * + * CLOCK_MONOTONIC_COARSE - emphasis on read speed at the (possible?) expense of precision + * CLOCK_MONOTONIC_RAW - possibly hardware based, not affected by NTP or other sync software + * CLOCK_BOOTTIME - includes time the system is suspended. + * + * Defaulting to the POSIX-specified "MONOTONIC" but it should be possible to use + * one of the Linux-specific variants if the target system provides it. + */ +#define CFE_PSP_TIMEBASE_REF_CLOCK CLOCK_MONOTONIC + +CFE_PSP_MODULE_DECLARE_SIMPLE(timebase_posix_clock); + +void timebase_posix_clock_Init(uint32 PspModuleId) +{ + /* Inform the user that this module is in use */ + printf("CFE_PSP: Using POSIX monotonic clock as CFE timebase\n"); +} + +/* + * ---------------------------------------------------------------------- + * The CFE_PSP_Get_Timebase() is a wrapper around clock_gettime() + * + * Reads the value of the monotonic POSIX clock, and output the value with + * the whole seconds in the upper 32 and nanoseconds in the lower 32. + * + * This variant does minimal conversions - just enough to meet the API. + * For a normalized output use CFE_PSP_GetTime() + * ---------------------------------------------------------------------- + */ +void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl) +{ + struct timespec now; + + if (clock_gettime(CFE_PSP_TIMEBASE_REF_CLOCK, &now) != 0) + { + /* unlikely - but avoids undefined behavior */ + now.tv_sec = 0; + now.tv_nsec = 0; + } + + *Tbu = now.tv_sec & 0xFFFFFFFF; + *Tbl = now.tv_nsec; +} + +/* + * ---------------------------------------------------------------------- + * The CFE_PSP_GetTime() is also a wrapper around the same clock_gettime() + * + * Reads the value of the monotonic POSIX clock, and output the value + * normalized to an OS_time_t format. + * ---------------------------------------------------------------------- + */ +void CFE_PSP_GetTime(OS_time_t *LocalTime) +{ + struct timespec now; + + if (clock_gettime(CFE_PSP_TIMEBASE_REF_CLOCK, &now) != 0) + { + /* unlikely - but avoids undefined behavior */ + now.tv_sec = 0; + now.tv_nsec = 0; + } + + *LocalTime = OS_TimeAssembleFromNanoseconds(now.tv_sec, now.tv_nsec); +} + +/****************************************************************************** +** Function: CFE_PSP_GetTimerTicksPerSecond() +** +** Purpose: +** Provides the resolution of the least significant 32 bits of the 64 bit +** time stamp returned by CFE_PSP_Get_Timebase in timer ticks per second. +** The timer resolution for accuracy should not be any slower than 1000000 +** ticks per second or 1 us per tick +** +** Arguments: +** +** Return: +** The number of timer ticks per second of the time stamp returned +** by CFE_PSP_Get_Timebase +*/ +uint32 CFE_PSP_GetTimerTicksPerSecond(void) +{ + /* POSIX "struct timespec" resolution is defined as nanoseconds */ + return 1000000000; +} + +/****************************************************************************** +** Function: CFE_PSP_GetTimerLow32Rollover() +** +** Purpose: +** Provides the number that the least significant 32 bits of the 64 bit +** time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 +** bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. +** if the lower 32 bits rolls at its maximum value (2^32) then +** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. +** +** Arguments: +** +** Return: +** The number that the least significant 32 bits of the 64 bit time stamp +** returned by CFE_PSP_Get_Timebase rolls over. +*/ +uint32 CFE_PSP_GetTimerLow32Rollover(void) +{ + /* POSIX "struct timespec" resolution is defined as nanoseconds */ + return 1000000000; +} diff --git a/fsw/modules/timebase_vxworks/CMakeLists.txt b/fsw/modules/timebase_vxworks/CMakeLists.txt new file mode 100644 index 00000000..e8aeecce --- /dev/null +++ b/fsw/modules/timebase_vxworks/CMakeLists.txt @@ -0,0 +1,3 @@ + +# Create the module +add_psp_module(timebase_vxworks cfe_psp_timebase_vxworks.c) diff --git a/fsw/modules/timebase_vxworks/cfe_psp_timebase_vxworks.c b/fsw/modules/timebase_vxworks/cfe_psp_timebase_vxworks.c new file mode 100644 index 00000000..91bb66b5 --- /dev/null +++ b/fsw/modules/timebase_vxworks/cfe_psp_timebase_vxworks.c @@ -0,0 +1,250 @@ +/* +** 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_timebase_vxworks.c + * + * A PSP module to implement the PSP time API via the VxWorks + * vxTimeBaseGet() routine. The VxWorks timebase is a 64 bit + * monotonically increasing counter implemented as a hardware + * register in PowerPC chips, and is described in the Power ISA + * specification v2.06b section 7.2. + * + * The vxTimeBaseGet() function is provided by the VxWorks BSP and + * returns the value of this register as a pair of UINT32 values, + * containing the upper and lower 32 bit words. + * + * Note that the tick rate of the clock is not specified by Power + * architecture and is system-dependent. This needs to have some + * platform-specific tuning to normalize the tick units. + */ + +/* +** System Include Files +*/ +#include +#include +#include + +#include +#include +#include +#include + +#include "osapi-clock.h" + +#include "cfe_psp.h" +#include "cfe_psp_config.h" +#include "cfe_psp_module.h" + +/** + * \brief The number that the least significant 32 bits of the 64 bit + * time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 + * bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. + * if the lower 32 bits rolls at its maximum value (2^32) then + * CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. + */ +#define CFE_PSP_TIMER_LOW32_ROLLOVER 0 + +typedef struct +{ + uint32 TicksPerSecond; + uint32 OSTimeConvNumerator; + uint32 OSTimeConvDenominator; +} PSP_VxWorks_Timebase_Global_t; + +PSP_VxWorks_Timebase_Global_t PSP_VxWorks_Timebase_Global; + +CFE_PSP_MODULE_DECLARE_SIMPLE(timebase_vxworks); + +void timebase_vxworks_Init(uint32 PspModuleId) +{ + uint64 TicksPerSec; + uint32 CheckFactor; + uint32 RatioN; + uint32 RatioD; + uint32 QuotientN; + uint32 QuotientD; + + /* + * The ticks per second is the reciprocal of the period - + * precomputed here so the value can be returned via API. + * Note this may not be an exact value. The API is limited + * in this regard. + */ + TicksPerSec = 1000000000; + TicksPerSec *= CFE_PSP_VX_TIMEBASE_PERIOD_DENOMINATOR; + TicksPerSec /= CFE_PSP_VX_TIMEBASE_PERIOD_NUMERATOR; + + /* + * Precompute the ratio for conversion to OS_time_t. + * + * This is the timebase period divided by OS_TIME_TICK_RESOLUTION_NS, + * which may not be a whole number. + */ + RatioN = CFE_PSP_VX_TIMEBASE_PERIOD_NUMERATOR; + RatioD = CFE_PSP_VX_TIMEBASE_PERIOD_DENOMINATOR; + RatioD *= OS_TIME_TICK_RESOLUTION_NS; + + /* + * This just does a brute-force sequential search for a common factors. + * The numbers are generally not very large, so this should be quick, + * and it is only done once during init. + * + * Reducing the fraction at runtime avoids issues with possibly choosing + * hardcoded values that do not divide evenly. + */ + CheckFactor = 2; + while (RatioN >= CheckFactor && RatioD >= CheckFactor) + { + QuotientN = RatioN / CheckFactor; + QuotientD = RatioD / CheckFactor; + + if ((QuotientN * CheckFactor) == RatioN && (QuotientD * CheckFactor) == RatioD) + { + /* It is a common factor, save quotient try again. */ + RatioN = QuotientN; + RatioD = QuotientD; + + continue; + } + + /* + * Not a common factor, move on. + * + * Technically this only needs to advance to the next prime, + * but for simplicity, just go sequential. + */ + ++CheckFactor; + } + + /* Inform the user that this module is in use */ + printf("CFE_PSP: Set up VxWorks timebase, %lu ticks/sec, OS_time_t ratio=%lu/%lu\n", (unsigned long)TicksPerSec, + (unsigned long)RatioN, (unsigned long)RatioD); + + /* Save the final reduced fraction for use in CFE_PSP_GetTime() */ + PSP_VxWorks_Timebase_Global.OSTimeConvNumerator = RatioN; + PSP_VxWorks_Timebase_Global.OSTimeConvDenominator = RatioD; + PSP_VxWorks_Timebase_Global.TicksPerSecond = TicksPerSec & 0xFFFFFFFF; +} + +/****************************************************************************** +** Function: CFE_PSP_GetTimerTicksPerSecond() +** +** Purpose: +** Provides the resolution of the least significant 32 bits of the 64 bit +** time stamp returned by CFE_PSP_Get_Timebase in timer ticks per second. +** The timer resolution for accuracy should not be any slower than 1000000 +** ticks per second or 1 us per tick +** +** Arguments: +** +** Return: +** The number of timer ticks per second of the time stamp returned +** by CFE_PSP_Get_Timebase +*/ +uint32 CFE_PSP_GetTimerTicksPerSecond(void) +{ + return PSP_VxWorks_Timebase_Global.TicksPerSecond; +} + +/****************************************************************************** +** Function: CFE_PSP_GetTimerLow32Rollover() +** +** Purpose: +** Provides the number that the least significant 32 bits of the 64 bit +** time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 +** bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. +** if the lower 32 bits rolls at its maximum value (2^32) then +** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. +** +** Arguments: +** +** Return: +** The number that the least significant 32 bits of the 64 bit time stamp +** returned by CFE_PSP_Get_Timebase rolls over. +*/ +uint32 CFE_PSP_GetTimerLow32Rollover(void) +{ + return 0; +} + +/****************************************************************************** +** Function: CFE_PSP_Get_Timebase() +** +** Purpose: +** Provides a common interface to system timebase. This routine +** is in the BSP because it is sometimes implemented in hardware and +** sometimes taken care of by the RTOS. +** +** Arguments: +** +** Return: +** Timebase register value +*/ +void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl) +{ + vxTimeBaseGet((UINT32 *)Tbu, (UINT32 *)Tbl); +} + +/****************************************************************************** +** Function: CFE_PSP_GetTime() +** +** Purpose: Gets the value of the timebase from the hardware normalized as OS_time_t +** +** Arguments: LocalTime - where the time is returned through +** +** Note this requires a platform-specific conversion factor to translate timebase +** ticks into real time ticks. +** +******************************************************************************/ + +void CFE_PSP_GetTime(OS_time_t *LocalTime) +{ + uint64 NormalizedTicks; + uint32 RegUpper; + uint32 RegLower; + + vxTimeBaseGet(&RegUpper, &RegLower); + + /* + * Convert to a uint64 value. Per the Power ISA definition, this + * register wraps at (2^60)-1. However at the tick rate implemented + * here this would require running continuously (without a power + * cycle or reset) for over 2000 years to reach that point, so + * for all practical purposes it does not roll over. + */ + NormalizedTicks = RegUpper; + NormalizedTicks <<= 32; + NormalizedTicks |= RegLower; + + /* + * Apply the pre-computed conversion to OS_time_t. + * + * This ratio has been reduced during init such that it should minimize + * the impact on overall range of the 64-bit value. + */ + NormalizedTicks *= PSP_VxWorks_Timebase_Global.OSTimeConvNumerator; + NormalizedTicks /= PSP_VxWorks_Timebase_Global.OSTimeConvDenominator; + + /* Output the value as an OS_time_t */ + *LocalTime = (OS_time_t) {NormalizedTicks}; + +} /* end CFE_PSP_GetLocalTime */ diff --git a/fsw/pc-linux/CMakeLists.txt b/fsw/pc-linux/CMakeLists.txt index 5918683d..4bddfe81 100644 --- a/fsw/pc-linux/CMakeLists.txt +++ b/fsw/pc-linux/CMakeLists.txt @@ -15,8 +15,8 @@ add_library(psp-${CFE_PSP_TARGETNAME}-impl OBJECT src/cfe_psp_ssr.c src/cfe_psp_start.c src/cfe_psp_support.c - src/cfe_psp_timer.c - src/cfe_psp_watchdog.c) + src/cfe_psp_watchdog.c +) # The _GNU_SOURCE directive is required to call non-posix APIs # that are specific to the Linux/glibc environment. diff --git a/fsw/pc-linux/psp_module_list.cmake b/fsw/pc-linux/psp_module_list.cmake index 54ffb4c5..992c679b 100644 --- a/fsw/pc-linux/psp_module_list.cmake +++ b/fsw/pc-linux/psp_module_list.cmake @@ -1,4 +1,5 @@ # This is a list of modules that is included as a fixed/base set # when this PSP is selected. They must exist under fsw/modules +timebase_posix_clock eeprom_mmap_file diff --git a/fsw/pc-linux/src/cfe_psp_timer.c b/fsw/pc-linux/src/cfe_psp_timer.c deleted file mode 100644 index f047dca7..00000000 --- a/fsw/pc-linux/src/cfe_psp_timer.c +++ /dev/null @@ -1,192 +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: cfe_psp_timer.c -** -** Purpose: -** This file contains glue routines between the cFE and the OS Board Support Package ( BSP ). -** The functions here allow the cFE to interface functions that are board and OS specific -** and usually dont fit well in the OS abstraction layer. -** -** History: -** 2005/06/05 K.Audra | Initial version, -** -*************************************************************************************************/ - -/* -** Include Files -*/ - -/* -** cFE includes -*/ -#include "common_types.h" -#include "osapi.h" - -/* -** System Include Files -*/ -#include -#include - -/* -** Types and prototypes for this module -*/ -#include "cfe_psp.h" - -/******************* Macro Definitions ***********************/ - -/** - * \brief Resolution of the least significant 32 bits of the 64 bit - * time stamp returned by OS_BSPGet_Timebase in timer ticks per second. - * The timer resolution for accuracy should not be any slower than 1000000 - * ticks per second or 1 us per tick - */ -#define CFE_PSP_TIMER_TICKS_PER_SECOND 1000000 - -/** - * \brief The number that the least significant 32 bits of the 64 bit - * time stamp returned by OS_BSPGet_Timebase rolls over. If the lower 32 - * bits rolls at 1 second, then the OS_BSP_TIMER_LOW32_ROLLOVER will be 1000000. - * if the lower 32 bits rolls at its maximum value (2^32) then - * OS_BSP_TIMER_LOW32_ROLLOVER will be 0. - */ -#define CFE_PSP_TIMER_LOW32_ROLLOVER 1000000 - -/****************************************************************************** -** Function: CFE_PSP_GetTime() -** -** Purpose: Gets the value of the time from the hardware -** -** Arguments: LocalTime - where the time is returned through -******************************************************************************/ - -void CFE_PSP_GetTime(OS_time_t *LocalTime) -{ - - /* since we don't have a hardware register to access like the mcp750, - * we use a call to the OS to get the time */ - - OS_GetLocalTime(LocalTime); - -} /* end CFE_PSP_GetLocalTime */ - -/****************************************************************************** -** Function: CFE_PSP_Get_Timer_Tick() -** -** Purpose: -** Provides a common interface to system clock tick. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** OS system clock ticks per second -*/ -uint32 CFE_PSP_Get_Timer_Tick(void) -{ - /* SUB -add function call code*/ - return (0); -} - -/****************************************************************************** -** Function: CFE_PSP_GetTimerTicksPerSecond() -** -** Purpose: -** Provides the resolution of the least significant 32 bits of the 64 bit -** time stamp returned by OS_BSPGet_Timebase in timer ticks per second. -** The timer resolution for accuracy should not be any slower than 1000000 -** ticks per second or 1 us per tick -** -** Arguments: -** -** Return: -** The number of timer ticks per second of the time stamp returned -** by CFE_PSP_Get_Timebase -*/ -uint32 CFE_PSP_GetTimerTicksPerSecond(void) -{ - return (CFE_PSP_TIMER_TICKS_PER_SECOND); -} - -/****************************************************************************** -** Function: CFE_PSP_GetTimerLow32Rollover() -** -** Purpose: -** Provides the number that the least significant 32 bits of the 64 bit -** time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 -** bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. -** if the lower 32 bits rolls at its maximum value (2^32) then -** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. -** -** Arguments: -** -** Return: -** The number that the least significant 32 bits of the 64 bit time stamp -** returned by CFE_PSP_Get_Timebase rolls over. -*/ -uint32 CFE_PSP_GetTimerLow32Rollover(void) -{ - return (CFE_PSP_TIMER_LOW32_ROLLOVER); -} - -/****************************************************************************** -** Function: CFE_PSP_Get_Timebase() -** -** Purpose: -** Provides a common interface to system timebase. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** Timebase register value -*/ -void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl) -{ - OS_time_t time; - - OS_GetLocalTime(&time); - *Tbu = OS_TimeGetTotalSeconds(time); - *Tbl = OS_TimeGetMicrosecondsPart(time); -} - -/****************************************************************************** -** Function: CFE_PSP_Get_Dec() -** -** Purpose: -** Provides a common interface to decrementer counter. This routine -** is in the PSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** Timebase register value -*/ - -uint32 CFE_PSP_Get_Dec(void) -{ - /* SUB -add function call code*/ - return (0); -} diff --git a/fsw/pc-rtems/CMakeLists.txt b/fsw/pc-rtems/CMakeLists.txt index 4d55fffc..f60bb374 100644 --- a/fsw/pc-rtems/CMakeLists.txt +++ b/fsw/pc-rtems/CMakeLists.txt @@ -15,7 +15,6 @@ add_library(psp-${CFE_PSP_TARGETNAME}-impl OBJECT src/cfe_psp_ssr.c src/cfe_psp_start.c src/cfe_psp_support.c - src/cfe_psp_timer.c src/cfe_psp_watchdog.c ) diff --git a/fsw/pc-rtems/psp_module_list.cmake b/fsw/pc-rtems/psp_module_list.cmake index 38b24e37..7d03ab30 100644 --- a/fsw/pc-rtems/psp_module_list.cmake +++ b/fsw/pc-rtems/psp_module_list.cmake @@ -2,3 +2,4 @@ # when this PSP is selected. They must exist under fsw/modules eeprom_stub +timebase_posix_clock diff --git a/fsw/pc-rtems/src/cfe_psp_timer.c b/fsw/pc-rtems/src/cfe_psp_timer.c deleted file mode 100644 index 60fcb135..00000000 --- a/fsw/pc-rtems/src/cfe_psp_timer.c +++ /dev/null @@ -1,188 +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: cfe_psp_timer.c -** -** Purpose: -** This file contains glue routines between the cFE and the OS Board Support Package ( BSP ). -** The functions here allow the cFE to interface functions that are board and OS specific -** and usually dont fit well in the OS abstraction layer. -** -** History: -** 2005/06/05 K.Audra | Initial version, -** -*************************************************************************************************/ - -/* -** Include Files -*/ - -/* -** Include Files -*/ -#include -#include - -/* -** cFE includes -*/ -#include "common_types.h" -#include "osapi.h" - -/* -** Types and prototypes for this module -*/ -#include "cfe_psp.h" - -/******************* Macro Definitions ***********************/ -#define WATCHDOG_MIN_TIME 0 -#define WATCHDOG_MAX_TIME 0xFFFFFFFF - -/** - * /brief Resolution of the least significant 32 bits of the 64 bit - * time stamp returned by CFE_PSP_Get_Timebase in timer ticks per second. - * The timer resolution for accuracy should not be any slower than 1000000 - * ticks per second or 1 us per tick - */ -#define CFE_PSP_TIMER_TICKS_PER_SECOND 100 - -/** - * /brief The number that the least significant 32 bits of the 64 bit - * time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 - * bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. - * if the lower 32 bits rolls at its maximum value (2^32) then - * CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. - */ -#define CFE_PSP_TIMER_LOW32_ROLLOVER 0 - -/****************************************************************************** -** Function: CFE_PSP_GetTime() -** -** Purpose: Gets the value of the time from the hardware -** -** Arguments: LocalTime - where the time is returned through -******************************************************************************/ - -void CFE_PSP_GetTime(OS_time_t *LocalTime) -{ - OS_GetLocalTime(LocalTime); - -} /* end CFE_PSP_GetLocalTime */ - -/****************************************************************************** -** Function: CFE_PSP_Get_Timer_Tick() -** -** Purpose: -** Provides a common interface to system clock tick. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** OS system clock ticks per second -*/ -uint32 CFE_PSP_Get_Timer_Tick(void) -{ - return (0); -} - -/****************************************************************************** -** Function: CFE_PSP_GetTimerTicksPerSecond() -** -** Purpose: -** Provides the resolution of the least significant 32 bits of the 64 bit -** time stamp returned by CFE_PSP_Get_Timebase in timer ticks per second. -** The timer resolution for accuracy should not be any slower than 1000000 -** ticks per second or 1 us per tick -** -** Arguments: -** -** Return: -** The number of timer ticks per second of the time stamp returned -** by CFE_PSP_Get_Timebase -*/ -uint32 CFE_PSP_GetTimerTicksPerSecond(void) -{ - return (CFE_PSP_TIMER_TICKS_PER_SECOND); -} - -/****************************************************************************** -** Function: CFE_PSP_GetTimerLow32Rollover() -** -** Purpose: -** Provides the number that the least significant 32 bits of the 64 bit -** time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 -** bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. -** if the lower 32 bits rolls at its maximum value (2^32) then -** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. -** -** Arguments: -** -** Return: -** The number that the least significant 32 bits of the 64 bit time stamp -** returned by CFE_PSP_Get_Timebase rolls over. -*/ -uint32 CFE_PSP_GetTimerLow32Rollover(void) -{ - return (CFE_PSP_TIMER_LOW32_ROLLOVER); -} - -/****************************************************************************** -** Function: CFE_PSP_Get_Timebase() -** -** Purpose: -** Provides a common interface to system timebase. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** Timebase register value -*/ -void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl) -{ - OS_time_t time; - - OS_GetLocalTime(&time); - *Tbu = OS_TimeGetTotalSeconds(time); - *Tbl = OS_TimeGetMicrosecondsPart(time); -} - -/****************************************************************************** -** Function: CFE_PSP_Get_Dec() -** -** Purpose: -** Provides a common interface to decrementer counter. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** Timebase register value -*/ - -uint32 CFE_PSP_Get_Dec(void) -{ - return (0); -} diff --git a/unit-test-coverage/CMakeLists.txt b/unit-test-coverage/CMakeLists.txt index d9836875..447d1484 100644 --- a/unit-test-coverage/CMakeLists.txt +++ b/unit-test-coverage/CMakeLists.txt @@ -30,6 +30,7 @@ include_directories(${UT_ASSERT_SOURCE_DIR}/inc) include_directories(${PSPCOVERAGE_SOURCE_DIR}/ut-stubs/inc) add_subdirectory(ut-stubs) +add_subdirectory(modules) # Build targets for each of the indicated PSPs foreach(SETNAME ${PSPCOVERAGE_TARGETS}) diff --git a/unit-test-coverage/modules/CMakeLists.txt b/unit-test-coverage/modules/CMakeLists.txt new file mode 100644 index 00000000..b28d4a51 --- /dev/null +++ b/unit-test-coverage/modules/CMakeLists.txt @@ -0,0 +1,67 @@ +###################################################################### +# +# CMAKE build recipe for PSP modules white-box coverage tests +# +###################################################################### + +include_directories("${PSPCOVERAGE_SOURCE_DIR}/shared/inc") +include_directories("${PSPCOVERAGE_SOURCE_DIR}/modules/inc") + +# redefine the add_psp_module to make a unit test variant +# this needs to name the target differently, so it doesn't conflict with the FSW target. +# this is similar to add_cfe_coverage_test() on the CFE side, but the set of interfaces +# and link libraries is different from that of a CFS app +function(add_psp_module MODULE_NAME) + + set(TEST_NAME "coverage-pspmod-${MODULE_NAME}") + set(OBJECT_TARGET "${TEST_NAME}-object") + set(RUNNER_TARGET "${TEST_NAME}-testrunner") + # Create the module + + add_library(${OBJECT_TARGET} OBJECT ${ARGN}) + + target_compile_options(${OBJECT_TARGET} PRIVATE + ${UT_COVERAGE_COMPILE_FLAGS} + ) + target_include_directories(${OBJECT_TARGET} PRIVATE + ${PSPCOVERAGE_SOURCE_DIR}/ut-stubs/override_inc # overrides for system headers + ${CFEPSP_SOURCE_DIR}/fsw/inc # PSP public API + ${CFEPSP_SOURCE_DIR}/fsw/shared/inc # all PSP shared headers + ${CFE_SOURCE_DIR}/cmake/target/inc # for sysconfig headers + $ # use headers from OSAL + ) + + # Compile a test runner application, which contains the + # actual coverage test code (test cases) and the unit under test + add_executable(${RUNNER_TARGET} + ${PSPCOVERAGE_SOURCE_DIR}/modules/src/coveragetest-${MODULE_NAME}.c + $ + ) + + # This also needs to be linked with UT_COVERAGE_LINK_FLAGS (for coverage) + # This is also linked with any other stub libraries needed, + # as well as the UT assert framework + target_link_libraries(${RUNNER_TARGET} + ${UT_COVERAGE_LINK_FLAGS} + psp_module_api + ut_psp_libc_stubs + ut_osapi_stubs + ut_assert + ) + + add_test(${TEST_NAME} ${RUNNER_TARGET}) + foreach(TGT ${INSTALL_TARGET_LIST}) + install(TARGETS ${RUNNER_TARGET} DESTINATION ${TGT}/${UT_INSTALL_SUBDIR}) + endforeach() + +endfunction(add_psp_module) + +# a list of modules for which there is a coverage test implemented +set(UT_PSPMODLIST + timebase_vxworks +) + +foreach(UT_PSPMOD ${UT_PSPMODLIST}) + add_subdirectory(${CFEPSP_SOURCE_DIR}/fsw/modules/${UT_PSPMOD} ${UT_PSPMOD}) +endforeach() + diff --git a/unit-test-coverage/modules/inc/cfe_psp_config.h b/unit-test-coverage/modules/inc/cfe_psp_config.h new file mode 100644 index 00000000..55d3294b --- /dev/null +++ b/unit-test-coverage/modules/inc/cfe_psp_config.h @@ -0,0 +1,35 @@ +/* + * + * Copyright (c) 2020, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Goddard + * Space Flight Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + * + */ + +/** + * \file + * \ingroup modules + * + * Stub for "cfe_psp_config.h" to use with coverage testing + */ + +#ifndef COVERAGETEST_CFE_PSP_CONFIG_H +#define COVERAGETEST_CFE_PSP_CONFIG_H + +#define CFE_PSP_VX_TIMEBASE_PERIOD_NUMERATOR (UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodNumerator) +#define CFE_PSP_VX_TIMEBASE_PERIOD_DENOMINATOR (UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodDenominator) + +typedef struct +{ + unsigned long PeriodNumerator; + unsigned long PeriodDenominator; + +} UT_PSP_TimeBase_VxWorks_TestConfig_t; + +extern UT_PSP_TimeBase_VxWorks_TestConfig_t UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG; + +#endif /* COVERAGETEST_CFE_PSP_CONFIG_H */ diff --git a/unit-test-coverage/modules/inc/coveragetest-timebase_vxworks.h b/unit-test-coverage/modules/inc/coveragetest-timebase_vxworks.h new file mode 100644 index 00000000..5a499ee7 --- /dev/null +++ b/unit-test-coverage/modules/inc/coveragetest-timebase_vxworks.h @@ -0,0 +1,29 @@ +/* + * + * Copyright (c) 2020, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Goddard + * Space Flight Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + * + */ + +/** + * \file psp-shared-coveragetest.h + * \ingroup vxworks + * \author joseph.p.hickey@nasa.gov + * + */ + +#ifndef INCLUDE_PSP_SHARED_COVERAGETEST_H_ +#define INCLUDE_PSP_SHARED_COVERAGETEST_H_ + +#include "utassert.h" +#include "uttest.h" +#include "utstubs.h" + +void Test_CFE_PSP_Timebase_Vxworks_Init(void); + +#endif /* INCLUDE_PSP_SHARED_COVERAGETEST_H_ */ diff --git a/unit-test-coverage/modules/src/coveragetest-timebase_vxworks.c b/unit-test-coverage/modules/src/coveragetest-timebase_vxworks.c new file mode 100644 index 00000000..00e76e48 --- /dev/null +++ b/unit-test-coverage/modules/src/coveragetest-timebase_vxworks.c @@ -0,0 +1,224 @@ +/* + * + * Copyright (c) 2020, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Goddard + * Space Flight Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + * + */ + +/** + * \file + * \ingroup modules + * + * Coverage test for VxWorks timebase module implementation + */ + +#include "utassert.h" +#include "utstubs.h" +#include "uttest.h" + +#include "cfe_psp.h" +#include "cfe_psp_config.h" +#include "cfe_psp_module.h" + +#include "PCS_arch_ppc_vxPpcLib.h" + +/* + * Reference to the API entry point for the module + */ +extern CFE_PSP_ModuleApi_t CFE_PSP_timebase_vxworks_API; + +const CFE_PSP_ModuleApi_t *TgtAPI = &CFE_PSP_timebase_vxworks_API; + +UT_PSP_TimeBase_VxWorks_TestConfig_t UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG; + +typedef struct +{ + uint32 u; + uint32 l; +} PSP_VxWorks_TimeBaseVal_t; + +void ModuleTest_ResetState(void) +{ + memset(&UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG, 0, sizeof(UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG)); +} + +int32 UTHOOK_vxTimeBaseGet(void *UserObj, int32 StubRetcode, uint32 CallCount, const UT_StubContext_t *Context) +{ + PSP_VxWorks_TimeBaseVal_t *val = UserObj; + uint32 * u = UT_Hook_GetArgValueByName(Context, "u", uint32 *); + uint32 * l = UT_Hook_GetArgValueByName(Context, "l", uint32 *); + + *u = val->u; + *l = val->l; + + return StubRetcode; +} + +void Test_Nominal(void) +{ + OS_time_t OsTime; + PSP_VxWorks_TimeBaseVal_t VxTime; + + /* Nominal test with a simple 1:1 ratio */ + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodNumerator = 1; + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodDenominator = 1; + TgtAPI->Init(0); + UtAssert_UINT32_EQ(CFE_PSP_GetTimerTicksPerSecond(), 1000000000); + + /* Check operation of CFE_PSP_GetTime() */ + UT_SetHookFunction(UT_KEY(PCS_vxTimeBaseGet), UTHOOK_vxTimeBaseGet, &VxTime); + VxTime.u = 0; + VxTime.l = 10000; + CFE_PSP_GetTime(&OsTime); + + UtAssert_UINT32_EQ(OS_TimeGetNanosecondsPart(OsTime), 10000); +} + +void Test_Non_Reducible(void) +{ + OS_time_t OsTime; + PSP_VxWorks_TimeBaseVal_t VxTime; + int64 TestTime; + + /* Use an oddball ratio of of some primes, will not be reducible */ + /* Ratio is 43*3 / 53*2 => 129/106 */ + /* This translates to about ~1.217ns per tick */ + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodNumerator = 43 * 3; + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodDenominator = 53 * 2; + TgtAPI->Init(0); + UtAssert_UINT32_EQ(CFE_PSP_GetTimerTicksPerSecond(), 821705426); + + /* + * Check operation of CFE_PSP_GetTime() + * + * This test requires that the conversion uses the actual ratio, + * otherwise a rounding error will be noticed. + * For example: + * Conversion using 1.217ns/tick yields 52269758 usec (wrong). + * Conversion using actual ratio yields 52268947 usec. + */ + + UT_SetHookFunction(UT_KEY(PCS_vxTimeBaseGet), UTHOOK_vxTimeBaseGet, &VxTime); + VxTime.u = 10; + VxTime.l = 5000; + CFE_PSP_GetTime(&OsTime); + + TestTime = OS_TimeGetTotalMicroseconds(OsTime); + UtAssert_True(TestTime == 52268947, "CFE_PSP_GetTime() Microseconds (%lld) == 52268947", (long long)TestTime); +} + +void Test_Reducible_1(void) +{ + OS_time_t OsTime; + PSP_VxWorks_TimeBaseVal_t VxTime; + int64 TestTime; + + /* Test with a ratio that is also 1:1, but can be reduced */ + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodNumerator = 1000; + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodDenominator = 1000; + TgtAPI->Init(0); + UtAssert_UINT32_EQ(CFE_PSP_GetTimerTicksPerSecond(), 1000000000); + + /* + * Check operation of CFE_PSP_GetTime() + * + * Externally calculated value should be 10376293541461622 usec. + * If overflow occurs then value will be wrong. + */ + UT_SetHookFunction(UT_KEY(PCS_vxTimeBaseGet), UTHOOK_vxTimeBaseGet, &VxTime); + VxTime.u = 0x90000000; /* nearing 64-bit limit */ + VxTime.l = 0; + CFE_PSP_GetTime(&OsTime); + + TestTime = OS_TimeGetTotalMicroseconds(OsTime); + UtAssert_True(TestTime == 10376293541461622, "CFE_PSP_GetTime() Microseconds (%lld) == 10376293541461622", + (long long)TestTime); +} + +void Test_Reducible_2(void) +{ + OS_time_t OsTime; + PSP_VxWorks_TimeBaseVal_t VxTime; + int64 TestTime; + + /* Test with a ratio that can be reduced */ + /* Final reduced ratio should be 12:5 with 100ns OS ticks */ + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodNumerator = 84000; + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodDenominator = 350; + TgtAPI->Init(0); + UtAssert_UINT32_EQ(CFE_PSP_GetTimerTicksPerSecond(), 4166666); + + /* + * Check operation of CFE_PSP_GetTime() + * + * Externally calculated value should be 276701161105643274 usec. + * If overflow occurs then value will be wrong. + */ + UT_SetHookFunction(UT_KEY(PCS_vxTimeBaseGet), UTHOOK_vxTimeBaseGet, &VxTime); + VxTime.u = 0x10000000; /* nearing 64-bit limit */ + VxTime.l = 0; + CFE_PSP_GetTime(&OsTime); + + TestTime = OS_TimeGetTotalMicroseconds(OsTime); + UtAssert_True(TestTime == 276701161105643274, "CFE_PSP_GetTime() Microseconds(%lld) == 276701161105643274", + (long long)TestTime); +} + +void Test_Rollover(void) +{ + /* This function always returns 0 */ + UtAssert_UINT32_EQ(CFE_PSP_GetTimerLow32Rollover(), 0); +} + +/****************************************************************************** +** Function: CFE_PSP_Get_Timebase() +** +** Purpose: +** Provides a common interface to system timebase. This routine +** is in the BSP because it is sometimes implemented in hardware and +** sometimes taken care of by the RTOS. +** +** Arguments: +** +** Return: +** Timebase register value +*/ +void Test_Get_Timebase(void) +{ + PSP_VxWorks_TimeBaseVal_t VxTime; + uint32 tbu; + uint32 tbl; + + /* The value from vxTimeBaseGet() should be passed through unchanged */ + UT_SetHookFunction(UT_KEY(PCS_vxTimeBaseGet), UTHOOK_vxTimeBaseGet, &VxTime); + VxTime.u = 0x00112233; + VxTime.l = 0x44556677; + + CFE_PSP_Get_Timebase(&tbu, &tbl); + + UtAssert_UINT32_EQ(tbu, VxTime.u); + UtAssert_UINT32_EQ(tbl, VxTime.l); +} + +/* + * Macro to add a test case to the list of tests to execute + */ +#define ADD_TEST(test) UtTest_Add(test, ModuleTest_ResetState, NULL, #test) + +/* + * Register the test cases to execute with the unit test tool + */ +void UtTest_Setup(void) +{ + ADD_TEST(Test_Nominal); + ADD_TEST(Test_Non_Reducible); + ADD_TEST(Test_Reducible_1); + ADD_TEST(Test_Reducible_2); + ADD_TEST(Test_Rollover); + ADD_TEST(Test_Get_Timebase); +} diff --git a/unit-test-coverage/ut-stubs/inc/PCS_time.h b/unit-test-coverage/ut-stubs/inc/PCS_time.h new file mode 100644 index 00000000..5cd9ee08 --- /dev/null +++ b/unit-test-coverage/ut-stubs/inc/PCS_time.h @@ -0,0 +1,19 @@ +/* PSP coverage stub replacement for time.h */ +#ifndef PSP_STUB_TIME_H +#define PSP_STUB_TIME_H + +#include "PCS_basetypes.h" + +/* ----------------------------------------- */ +/* constants normally defined in time.h */ +/* ----------------------------------------- */ + +/* ----------------------------------------- */ +/* types normally defined in time.h */ +/* ----------------------------------------- */ + +/* ----------------------------------------- */ +/* prototypes normally declared in time.h */ +/* ----------------------------------------- */ + +#endif /* PSP_STUB_TIME_H */ diff --git a/unit-test-coverage/ut-stubs/override_inc/time.h b/unit-test-coverage/ut-stubs/override_inc/time.h new file mode 100644 index 00000000..10f78f10 --- /dev/null +++ b/unit-test-coverage/ut-stubs/override_inc/time.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Goddard + * Space Flight Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + */ + +/* PSP coverage stub replacement for time.h */ +#ifndef _PSP_OVERRIDE_TIME_H_ +#define _PSP_OVERRIDE_TIME_H_ + +#include "PCS_time.h" + +#endif /* _PSP_OVERRIDE_TIME_H_ */ diff --git a/unit-test-coverage/ut-stubs/src/vxworks-vxLib-stubs.c b/unit-test-coverage/ut-stubs/src/vxworks-vxLib-stubs.c index 85ea5396..1f6e900f 100644 --- a/unit-test-coverage/ut-stubs/src/vxworks-vxLib-stubs.c +++ b/unit-test-coverage/ut-stubs/src/vxworks-vxLib-stubs.c @@ -18,9 +18,11 @@ void PCS_vxTimeBaseGet(uint32_t *u, uint32_t *l) { - UT_DEFAULT_IMPL(PCS_vxTimeBaseGet); + UT_Stub_RegisterContextGenericArg(UT_KEY(PCS_vxTimeBaseGet), u); + UT_Stub_RegisterContextGenericArg(UT_KEY(PCS_vxTimeBaseGet), l); *u = 0; *l = 0; + UT_DEFAULT_IMPL(PCS_vxTimeBaseGet); } void PCS_vxMsrSet(uint32_t val) { From 3664f884499f3c6ad06ee440f467b82e496814ba Mon Sep 17 00:00:00 2001 From: "Gerardo E. Cruz-Ortiz" <59618057+astrogeco@users.noreply.github.com> Date: Tue, 6 Apr 2021 19:37:19 -0400 Subject: [PATCH 4/6] IC:2021-04-06, Fix merge error from #286 Re-add timebase name definition `CFE_PSP_SOFT_TIMEBASE_NAME` to `cfe_psp.h` --- fsw/inc/cfe_psp.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fsw/inc/cfe_psp.h b/fsw/inc/cfe_psp.h index 41d428c2..f98acb2b 100644 --- a/fsw/inc/cfe_psp.h +++ b/fsw/inc/cfe_psp.h @@ -146,6 +146,13 @@ #define CFE_PSP_RST_SUBTYPE_MAX 10 /** \} */ +/** + * \brief The name of the software/RTOS timebase for general system timers. + * + * This name may be referred to by CFE TIME and/or SCH when setting up its own timers. + */ +#define CFE_PSP_SOFT_TIMEBASE_NAME "cFS-Master" + /* ** Type Definitions */ From 76dbf8062a80af42fbbe8390266950b10ed9b24b Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Fri, 26 Mar 2021 14:39:28 -0400 Subject: [PATCH 5/6] Fix #266, psp module to implement timebase Clarifies the use case for CFE_PSP_GetTime and CFE_PSP_GetTimeBase. Moves the implementation of these to separate PSP modules, so MCP750 on VxWorks can use the optimized vxTimeBaseGet() routine while Linux and RTEMS can use the generic posix CLOCK_MONOTONIC. --- fsw/inc/cfe_psp.h | 49 +++- fsw/mcp750-vxworks/CMakeLists.txt | 1 - fsw/mcp750-vxworks/inc/cfe_psp_config.h | 17 ++ fsw/mcp750-vxworks/psp_module_list.cmake | 1 + fsw/mcp750-vxworks/src/cfe_psp_timer.c | 229 ---------------- .../timebase_posix_clock/CMakeLists.txt | 3 + .../cfe_psp_timebase_posix_clock.c | 161 +++++++++++ fsw/modules/timebase_vxworks/CMakeLists.txt | 3 + .../cfe_psp_timebase_vxworks.c | 250 ++++++++++++++++++ fsw/pc-linux/CMakeLists.txt | 4 +- fsw/pc-linux/psp_module_list.cmake | 1 + fsw/pc-linux/src/cfe_psp_timer.c | 192 -------------- fsw/pc-rtems/CMakeLists.txt | 1 - fsw/pc-rtems/psp_module_list.cmake | 1 + fsw/pc-rtems/src/cfe_psp_timer.c | 188 ------------- unit-test-coverage/CMakeLists.txt | 1 + unit-test-coverage/modules/CMakeLists.txt | 67 +++++ .../modules/inc/cfe_psp_config.h | 35 +++ .../inc/coveragetest-timebase_vxworks.h | 29 ++ .../src/coveragetest-timebase_vxworks.c | 224 ++++++++++++++++ unit-test-coverage/ut-stubs/inc/PCS_time.h | 19 ++ .../ut-stubs/override_inc/time.h | 17 ++ .../ut-stubs/src/vxworks-vxLib-stubs.c | 4 +- 23 files changed, 877 insertions(+), 620 deletions(-) delete mode 100644 fsw/mcp750-vxworks/src/cfe_psp_timer.c create mode 100644 fsw/modules/timebase_posix_clock/CMakeLists.txt create mode 100644 fsw/modules/timebase_posix_clock/cfe_psp_timebase_posix_clock.c create mode 100644 fsw/modules/timebase_vxworks/CMakeLists.txt create mode 100644 fsw/modules/timebase_vxworks/cfe_psp_timebase_vxworks.c delete mode 100644 fsw/pc-linux/src/cfe_psp_timer.c delete mode 100644 fsw/pc-rtems/src/cfe_psp_timer.c create mode 100644 unit-test-coverage/modules/CMakeLists.txt create mode 100644 unit-test-coverage/modules/inc/cfe_psp_config.h create mode 100644 unit-test-coverage/modules/inc/coveragetest-timebase_vxworks.h create mode 100644 unit-test-coverage/modules/src/coveragetest-timebase_vxworks.c create mode 100644 unit-test-coverage/ut-stubs/inc/PCS_time.h create mode 100644 unit-test-coverage/ut-stubs/override_inc/time.h diff --git a/fsw/inc/cfe_psp.h b/fsw/inc/cfe_psp.h index 41d428c2..beb97dd7 100644 --- a/fsw/inc/cfe_psp.h +++ b/fsw/inc/cfe_psp.h @@ -166,10 +166,26 @@ extern void CFE_PSP_Main(void); ** The flight software (i.e. cFE ) should not call this routine. */ +/** + * \brief Sample/Read a monotonic platform clock with normalization + * + * Outputs an OS_time_t value indicating the time elapsed since an epoch. The + * epoch is not defined, but typically represents the system boot time. The + * value increases continously over time and cannot be reset by software. + * + * This is similar to the CFE_PSP_Get_Timebase(), but additionally it normalizes + * the output value to an OS_time_t, thereby providing consistent units to + * the calling application. Any OSAL-provided routine accepts OS_time_t inputs + * may be used to convert this value into other standardized time units. + * + * \note This should refer to the same time domain as CFE_PSP_Get_Timebase(), + * the primary difference being the format and units of the output value. + * + * \sa CFE_PSP_Get_Timebase() + * + * \param[out] LocalTime Value of PSP tick counter as OS_time_t + */ extern void CFE_PSP_GetTime(OS_time_t *LocalTime); -/* This call gets the local time from the hardware on the Vxworks system - * on the mcp750s - * on the other os/hardware setup, it will get the time the normal way */ extern void CFE_PSP_Restart(uint32 resetType); /* @@ -229,10 +245,31 @@ extern uint32 CFE_PSP_GetTimerLow32Rollover(void); ** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. */ +/** + * \brief Sample/Read a monotonic platform clock without normalization + * + * This is defined as a free-running, monotonically-increasing tick counter. The + * epoch is not defined, but typically is the system boot time, and the value increases + * indefinitely as the system runs. The tick period/rate is also not defined. + * + * Rollover events - where the range of representable values is exceeded - are + * theoretically possible, but would take many years of continuous uptime to occur + * (typically hundreds of years, if not thousands). System designers should ensure + * that the actual tick rate and resulting timebase range is sufficiently large to + * ensure that rollover is not a concern. + * + * \note This is a "raw" value from the underlying platform with minimal/no conversions + * or normalization applied. Neither the epoch nor the resolution of this tick + * counter is specified, and it may vary from platform to platform. Use the + * CFE_PSP_GetTime() function to sample the timebase and also convert the units + * into a normalized/more consistent form. + * + * \sa CFE_PSP_GetTime() + * + * \param[out] Tbu Buffer to hold the upper 32 bits of a 64-bit tick counter + * \param[out] Tbl Buffer to hold the lower 32 bits of a 64-bit tick counter + */ extern void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl); -/* -** CFE_PSP_Get_Timebase -*/ extern uint32 CFE_PSP_Get_Dec(void); /* diff --git a/fsw/mcp750-vxworks/CMakeLists.txt b/fsw/mcp750-vxworks/CMakeLists.txt index ecff8a65..ae128104 100644 --- a/fsw/mcp750-vxworks/CMakeLists.txt +++ b/fsw/mcp750-vxworks/CMakeLists.txt @@ -14,7 +14,6 @@ add_library(psp-${CFE_PSP_TARGETNAME}-impl OBJECT src/cfe_psp_ssr.c src/cfe_psp_start.c src/cfe_psp_support.c - src/cfe_psp_timer.c src/cfe_psp_watchdog.c ) target_compile_definitions(psp-${CFE_SYSTEM_PSPNAME}-impl PRIVATE diff --git a/fsw/mcp750-vxworks/inc/cfe_psp_config.h b/fsw/mcp750-vxworks/inc/cfe_psp_config.h index fc88a42f..1fee79d8 100644 --- a/fsw/mcp750-vxworks/inc/cfe_psp_config.h +++ b/fsw/mcp750-vxworks/inc/cfe_psp_config.h @@ -37,6 +37,23 @@ #include "taskLib.h" #include "arch/ppc/esfPpc.h" +/** + * \brief Period of the VxWorks timebase, in nanoseconds + * + * This is expressed as a ratio in case it is not a whole number. + * + * Multiplying the timebase register by 60 should yield a result + * in nanoseconds, and then further dividing by the OSAL OS_time_t tick + * resolution will convert to an OS_time_t compatible value. + * + * On the MCP750 - the PPC timebase runs at 60ns period or ~16.67 MHz. + * + * Note this is distinct from the VxWorks system timer tick which runs, + * confusingly, at 60Hz or a ~16.67ms period. + */ +#define CFE_PSP_VX_TIMEBASE_PERIOD_NUMERATOR 60 +#define CFE_PSP_VX_TIMEBASE_PERIOD_DENOMINATOR 1 + /* ** This define sets the number of memory ranges that are defined in the memory range defintion ** table. diff --git a/fsw/mcp750-vxworks/psp_module_list.cmake b/fsw/mcp750-vxworks/psp_module_list.cmake index ba9cd802..122a4201 100644 --- a/fsw/mcp750-vxworks/psp_module_list.cmake +++ b/fsw/mcp750-vxworks/psp_module_list.cmake @@ -1,4 +1,5 @@ # This is a list of modules that is included as a fixed/base set # when this PSP is selected. They must exist under fsw/modules +timebase_vxworks eeprom_direct diff --git a/fsw/mcp750-vxworks/src/cfe_psp_timer.c b/fsw/mcp750-vxworks/src/cfe_psp_timer.c deleted file mode 100644 index 72e7a787..00000000 --- a/fsw/mcp750-vxworks/src/cfe_psp_timer.c +++ /dev/null @@ -1,229 +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: cfe_psp_timer.c -** -** Purpose: -** This file contains glue routines between the cFE and the OS Board Support Package ( BSP ). -** The functions here allow the cFE to interface functions that are board and OS specific -** and usually dont fit well in the OS abstraction layer. -** -** History: -** 2005/06/05 K.Audra | Initial version, -** -*************************************************************************************************/ - -/* -** Include Files -*/ - -/* -** Include Files -*/ -#include -#include -#include -#include "vxWorks.h" -#include "sysLib.h" -#include "vxLib.h" -#include "taskLib.h" -#include "ramDrv.h" -#include "dosFsLib.h" -#include "errnoLib.h" -#include "usrLib.h" -#include "cacheLib.h" -#include "mcpx750.h" -#include "drv/hdisk/ataDrv.h" - -/* -** cFE includes -*/ -#include "common_types.h" -#include "osapi.h" - -/* -** Types and prototypes for this module -*/ -#include "cfe_psp.h" - -IMPORT void sysPciRead32(UINT32, UINT32 *); - -/******************* Macro Definitions ***********************/ - -/** - * \brief Resolution of the least significant 32 bits of the 64 bit - * time stamp returned by CFE_PSP_Get_Timebase in timer ticks per second. - * The timer resolution for accuracy should not be any slower than 1000000 - * ticks per second or 1 us per tick - */ -#define CFE_PSP_TIMER_TICKS_PER_SECOND 16666666 - -/** - * \brief The number that the least significant 32 bits of the 64 bit - * time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 - * bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. - * if the lower 32 bits rolls at its maximum value (2^32) then - * CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. - */ -#define CFE_PSP_TIMER_LOW32_ROLLOVER 0 - -/* -** MCP750/vxWorks timers -*/ -/****************************************************************************** -** Function: CFE_PSP_GetTime() -** -** Purpose: Gets the value of the time from the hardware -** -** Arguments: LocalTime - where the time is returned through -******************************************************************************/ - -void CFE_PSP_GetTime(OS_time_t *LocalTime) -{ - uint32 DecCount; - uint32 Seconds; - - /* Reads the time from the hardware register, then converts it - * into an OS_time_t value */ - sysPciRead32(0xFC0011C0, (UINT32 *)(&DecCount)); - DecCount = DecCount & 0x7FFFFFFF; - DecCount = ((uint32)0x0D6937E5) - DecCount; - - Seconds = DecCount / 8333311; - - /* Get subseconds (discard seconds) */ - DecCount = DecCount % 8333311; - - /* Microsecond conversion - * If speed really matters, recommend testing the following - * options on hardware being used (all should give the exact same answer): - * - long long to avoid overflow: (DecCount*1000000ULL)/8333311 - * - Double w/ divide: DecCount/8.333311 - * - Approximation: ((300 * DecCount) + (DecCount / 1244)) / 2500 - * At cost of up to 2us error (at max value): - * - Approximation: (DecCount * 3) / 25 - * - * Same basic ratio but adjusted to produce units in nanoseconds - * instead of microseconds: - * - ((480 * DecCount) + (DecCount / 777)) / 4 - */ - - DecCount = ((480 * DecCount) + (DecCount / 777)) / 4; - - *LocalTime = OS_TimeAssembleFromNanoseconds(Seconds, DecCount); - -} /* end CFE_PSP_GetLocalTime */ - -/****************************************************************************** -** Function: CFE_PSP_Get_Timer_Tick() -** -** Purpose: -** Provides a common interface to system clock tick. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** OS system clock ticks per second -*/ -uint32 CFE_PSP_Get_Timer_Tick(void) -{ - return (sysClkRateGet()); -} - -/****************************************************************************** -** Function: CFE_PSP_GetTimerTicksPerSecond() -** -** Purpose: -** Provides the resolution of the least significant 32 bits of the 64 bit -** time stamp returned by CFE_PSP_Get_Timebase in timer ticks per second. -** The timer resolution for accuracy should not be any slower than 1000000 -** ticks per second or 1 us per tick -** -** Arguments: -** -** Return: -** The number of timer ticks per second of the time stamp returned -** by CFE_PSP_Get_Timebase -*/ -uint32 CFE_PSP_GetTimerTicksPerSecond(void) -{ - return (CFE_PSP_TIMER_TICKS_PER_SECOND); -} - -/****************************************************************************** -** Function: CFE_PSP_GetTimerLow32Rollover() -** -** Purpose: -** Provides the number that the least significant 32 bits of the 64 bit -** time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 -** bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. -** if the lower 32 bits rolls at its maximum value (2^32) then -** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. -** -** Arguments: -** -** Return: -** The number that the least significant 32 bits of the 64 bit time stamp -** returned by CFE_PSP_Get_Timebase rolls over. -*/ -uint32 CFE_PSP_GetTimerLow32Rollover(void) -{ - return (CFE_PSP_TIMER_LOW32_ROLLOVER); -} - -/****************************************************************************** -** Function: CFE_PSP_Get_Timebase() -** -** Purpose: -** Provides a common interface to system timebase. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** Timebase register value -*/ -void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl) -{ - vxTimeBaseGet((UINT32 *)Tbu, (UINT32 *)Tbl); -} - -/****************************************************************************** -** Function: CFE_PSP_Get_Dec() -** -** Purpose: -** Provides a common interface to decrementer counter. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** Timebase register value -*/ - -uint32 CFE_PSP_Get_Dec(void) -{ - return (vxDecGet()); -} diff --git a/fsw/modules/timebase_posix_clock/CMakeLists.txt b/fsw/modules/timebase_posix_clock/CMakeLists.txt new file mode 100644 index 00000000..7150d1f0 --- /dev/null +++ b/fsw/modules/timebase_posix_clock/CMakeLists.txt @@ -0,0 +1,3 @@ + +# Create the module +add_psp_module(timebase_posix_clock cfe_psp_timebase_posix_clock.c) diff --git a/fsw/modules/timebase_posix_clock/cfe_psp_timebase_posix_clock.c b/fsw/modules/timebase_posix_clock/cfe_psp_timebase_posix_clock.c new file mode 100644 index 00000000..901d6aff --- /dev/null +++ b/fsw/modules/timebase_posix_clock/cfe_psp_timebase_posix_clock.c @@ -0,0 +1,161 @@ +/* +** 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_timebase_posix_clock.c + * + * A PSP module to satisfy the PSP time API on systems which + * do not have a hardware clock register, but do provide a POSIX + * compliant implementation of clock_gettime() and CLOCK_MONOTONIC + * that can fulfill this role. + * + * The POSIX CLOCK_MONOTONIC is defined as a monotonically increasing + * clock that has no specific epoch. It is not affected by local time + * changes and is not settable. + * + * The POSIX interface uses a "struct timespec" which has units in + * nanoseconds, but this is converted down to units of microseconds for + * consistency with previous versions of PSP where CFE_PSP_Get_Timebase() + * returned units of microseconds. + */ + +/* +** System Include Files +*/ +#include +#include +#include + +#include "cfe_psp.h" +#include "cfe_psp_module.h" + +/* + * The specific clock ID to use with clock_gettime + * + * Linux provides some special (non-posix) clock IDs that also + * could be relevant/useful: + * + * CLOCK_MONOTONIC_COARSE - emphasis on read speed at the (possible?) expense of precision + * CLOCK_MONOTONIC_RAW - possibly hardware based, not affected by NTP or other sync software + * CLOCK_BOOTTIME - includes time the system is suspended. + * + * Defaulting to the POSIX-specified "MONOTONIC" but it should be possible to use + * one of the Linux-specific variants if the target system provides it. + */ +#define CFE_PSP_TIMEBASE_REF_CLOCK CLOCK_MONOTONIC + +CFE_PSP_MODULE_DECLARE_SIMPLE(timebase_posix_clock); + +void timebase_posix_clock_Init(uint32 PspModuleId) +{ + /* Inform the user that this module is in use */ + printf("CFE_PSP: Using POSIX monotonic clock as CFE timebase\n"); +} + +/* + * ---------------------------------------------------------------------- + * The CFE_PSP_Get_Timebase() is a wrapper around clock_gettime() + * + * Reads the value of the monotonic POSIX clock, and output the value with + * the whole seconds in the upper 32 and nanoseconds in the lower 32. + * + * This variant does minimal conversions - just enough to meet the API. + * For a normalized output use CFE_PSP_GetTime() + * ---------------------------------------------------------------------- + */ +void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl) +{ + struct timespec now; + + if (clock_gettime(CFE_PSP_TIMEBASE_REF_CLOCK, &now) != 0) + { + /* unlikely - but avoids undefined behavior */ + now.tv_sec = 0; + now.tv_nsec = 0; + } + + *Tbu = now.tv_sec & 0xFFFFFFFF; + *Tbl = now.tv_nsec; +} + +/* + * ---------------------------------------------------------------------- + * The CFE_PSP_GetTime() is also a wrapper around the same clock_gettime() + * + * Reads the value of the monotonic POSIX clock, and output the value + * normalized to an OS_time_t format. + * ---------------------------------------------------------------------- + */ +void CFE_PSP_GetTime(OS_time_t *LocalTime) +{ + struct timespec now; + + if (clock_gettime(CFE_PSP_TIMEBASE_REF_CLOCK, &now) != 0) + { + /* unlikely - but avoids undefined behavior */ + now.tv_sec = 0; + now.tv_nsec = 0; + } + + *LocalTime = OS_TimeAssembleFromNanoseconds(now.tv_sec, now.tv_nsec); +} + +/****************************************************************************** +** Function: CFE_PSP_GetTimerTicksPerSecond() +** +** Purpose: +** Provides the resolution of the least significant 32 bits of the 64 bit +** time stamp returned by CFE_PSP_Get_Timebase in timer ticks per second. +** The timer resolution for accuracy should not be any slower than 1000000 +** ticks per second or 1 us per tick +** +** Arguments: +** +** Return: +** The number of timer ticks per second of the time stamp returned +** by CFE_PSP_Get_Timebase +*/ +uint32 CFE_PSP_GetTimerTicksPerSecond(void) +{ + /* POSIX "struct timespec" resolution is defined as nanoseconds */ + return 1000000000; +} + +/****************************************************************************** +** Function: CFE_PSP_GetTimerLow32Rollover() +** +** Purpose: +** Provides the number that the least significant 32 bits of the 64 bit +** time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 +** bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. +** if the lower 32 bits rolls at its maximum value (2^32) then +** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. +** +** Arguments: +** +** Return: +** The number that the least significant 32 bits of the 64 bit time stamp +** returned by CFE_PSP_Get_Timebase rolls over. +*/ +uint32 CFE_PSP_GetTimerLow32Rollover(void) +{ + /* POSIX "struct timespec" resolution is defined as nanoseconds */ + return 1000000000; +} diff --git a/fsw/modules/timebase_vxworks/CMakeLists.txt b/fsw/modules/timebase_vxworks/CMakeLists.txt new file mode 100644 index 00000000..e8aeecce --- /dev/null +++ b/fsw/modules/timebase_vxworks/CMakeLists.txt @@ -0,0 +1,3 @@ + +# Create the module +add_psp_module(timebase_vxworks cfe_psp_timebase_vxworks.c) diff --git a/fsw/modules/timebase_vxworks/cfe_psp_timebase_vxworks.c b/fsw/modules/timebase_vxworks/cfe_psp_timebase_vxworks.c new file mode 100644 index 00000000..91bb66b5 --- /dev/null +++ b/fsw/modules/timebase_vxworks/cfe_psp_timebase_vxworks.c @@ -0,0 +1,250 @@ +/* +** 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_timebase_vxworks.c + * + * A PSP module to implement the PSP time API via the VxWorks + * vxTimeBaseGet() routine. The VxWorks timebase is a 64 bit + * monotonically increasing counter implemented as a hardware + * register in PowerPC chips, and is described in the Power ISA + * specification v2.06b section 7.2. + * + * The vxTimeBaseGet() function is provided by the VxWorks BSP and + * returns the value of this register as a pair of UINT32 values, + * containing the upper and lower 32 bit words. + * + * Note that the tick rate of the clock is not specified by Power + * architecture and is system-dependent. This needs to have some + * platform-specific tuning to normalize the tick units. + */ + +/* +** System Include Files +*/ +#include +#include +#include + +#include +#include +#include +#include + +#include "osapi-clock.h" + +#include "cfe_psp.h" +#include "cfe_psp_config.h" +#include "cfe_psp_module.h" + +/** + * \brief The number that the least significant 32 bits of the 64 bit + * time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 + * bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. + * if the lower 32 bits rolls at its maximum value (2^32) then + * CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. + */ +#define CFE_PSP_TIMER_LOW32_ROLLOVER 0 + +typedef struct +{ + uint32 TicksPerSecond; + uint32 OSTimeConvNumerator; + uint32 OSTimeConvDenominator; +} PSP_VxWorks_Timebase_Global_t; + +PSP_VxWorks_Timebase_Global_t PSP_VxWorks_Timebase_Global; + +CFE_PSP_MODULE_DECLARE_SIMPLE(timebase_vxworks); + +void timebase_vxworks_Init(uint32 PspModuleId) +{ + uint64 TicksPerSec; + uint32 CheckFactor; + uint32 RatioN; + uint32 RatioD; + uint32 QuotientN; + uint32 QuotientD; + + /* + * The ticks per second is the reciprocal of the period - + * precomputed here so the value can be returned via API. + * Note this may not be an exact value. The API is limited + * in this regard. + */ + TicksPerSec = 1000000000; + TicksPerSec *= CFE_PSP_VX_TIMEBASE_PERIOD_DENOMINATOR; + TicksPerSec /= CFE_PSP_VX_TIMEBASE_PERIOD_NUMERATOR; + + /* + * Precompute the ratio for conversion to OS_time_t. + * + * This is the timebase period divided by OS_TIME_TICK_RESOLUTION_NS, + * which may not be a whole number. + */ + RatioN = CFE_PSP_VX_TIMEBASE_PERIOD_NUMERATOR; + RatioD = CFE_PSP_VX_TIMEBASE_PERIOD_DENOMINATOR; + RatioD *= OS_TIME_TICK_RESOLUTION_NS; + + /* + * This just does a brute-force sequential search for a common factors. + * The numbers are generally not very large, so this should be quick, + * and it is only done once during init. + * + * Reducing the fraction at runtime avoids issues with possibly choosing + * hardcoded values that do not divide evenly. + */ + CheckFactor = 2; + while (RatioN >= CheckFactor && RatioD >= CheckFactor) + { + QuotientN = RatioN / CheckFactor; + QuotientD = RatioD / CheckFactor; + + if ((QuotientN * CheckFactor) == RatioN && (QuotientD * CheckFactor) == RatioD) + { + /* It is a common factor, save quotient try again. */ + RatioN = QuotientN; + RatioD = QuotientD; + + continue; + } + + /* + * Not a common factor, move on. + * + * Technically this only needs to advance to the next prime, + * but for simplicity, just go sequential. + */ + ++CheckFactor; + } + + /* Inform the user that this module is in use */ + printf("CFE_PSP: Set up VxWorks timebase, %lu ticks/sec, OS_time_t ratio=%lu/%lu\n", (unsigned long)TicksPerSec, + (unsigned long)RatioN, (unsigned long)RatioD); + + /* Save the final reduced fraction for use in CFE_PSP_GetTime() */ + PSP_VxWorks_Timebase_Global.OSTimeConvNumerator = RatioN; + PSP_VxWorks_Timebase_Global.OSTimeConvDenominator = RatioD; + PSP_VxWorks_Timebase_Global.TicksPerSecond = TicksPerSec & 0xFFFFFFFF; +} + +/****************************************************************************** +** Function: CFE_PSP_GetTimerTicksPerSecond() +** +** Purpose: +** Provides the resolution of the least significant 32 bits of the 64 bit +** time stamp returned by CFE_PSP_Get_Timebase in timer ticks per second. +** The timer resolution for accuracy should not be any slower than 1000000 +** ticks per second or 1 us per tick +** +** Arguments: +** +** Return: +** The number of timer ticks per second of the time stamp returned +** by CFE_PSP_Get_Timebase +*/ +uint32 CFE_PSP_GetTimerTicksPerSecond(void) +{ + return PSP_VxWorks_Timebase_Global.TicksPerSecond; +} + +/****************************************************************************** +** Function: CFE_PSP_GetTimerLow32Rollover() +** +** Purpose: +** Provides the number that the least significant 32 bits of the 64 bit +** time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 +** bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. +** if the lower 32 bits rolls at its maximum value (2^32) then +** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. +** +** Arguments: +** +** Return: +** The number that the least significant 32 bits of the 64 bit time stamp +** returned by CFE_PSP_Get_Timebase rolls over. +*/ +uint32 CFE_PSP_GetTimerLow32Rollover(void) +{ + return 0; +} + +/****************************************************************************** +** Function: CFE_PSP_Get_Timebase() +** +** Purpose: +** Provides a common interface to system timebase. This routine +** is in the BSP because it is sometimes implemented in hardware and +** sometimes taken care of by the RTOS. +** +** Arguments: +** +** Return: +** Timebase register value +*/ +void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl) +{ + vxTimeBaseGet((UINT32 *)Tbu, (UINT32 *)Tbl); +} + +/****************************************************************************** +** Function: CFE_PSP_GetTime() +** +** Purpose: Gets the value of the timebase from the hardware normalized as OS_time_t +** +** Arguments: LocalTime - where the time is returned through +** +** Note this requires a platform-specific conversion factor to translate timebase +** ticks into real time ticks. +** +******************************************************************************/ + +void CFE_PSP_GetTime(OS_time_t *LocalTime) +{ + uint64 NormalizedTicks; + uint32 RegUpper; + uint32 RegLower; + + vxTimeBaseGet(&RegUpper, &RegLower); + + /* + * Convert to a uint64 value. Per the Power ISA definition, this + * register wraps at (2^60)-1. However at the tick rate implemented + * here this would require running continuously (without a power + * cycle or reset) for over 2000 years to reach that point, so + * for all practical purposes it does not roll over. + */ + NormalizedTicks = RegUpper; + NormalizedTicks <<= 32; + NormalizedTicks |= RegLower; + + /* + * Apply the pre-computed conversion to OS_time_t. + * + * This ratio has been reduced during init such that it should minimize + * the impact on overall range of the 64-bit value. + */ + NormalizedTicks *= PSP_VxWorks_Timebase_Global.OSTimeConvNumerator; + NormalizedTicks /= PSP_VxWorks_Timebase_Global.OSTimeConvDenominator; + + /* Output the value as an OS_time_t */ + *LocalTime = (OS_time_t) {NormalizedTicks}; + +} /* end CFE_PSP_GetLocalTime */ diff --git a/fsw/pc-linux/CMakeLists.txt b/fsw/pc-linux/CMakeLists.txt index 88efd031..63f406a1 100644 --- a/fsw/pc-linux/CMakeLists.txt +++ b/fsw/pc-linux/CMakeLists.txt @@ -14,8 +14,8 @@ add_library(psp-${CFE_PSP_TARGETNAME}-impl OBJECT src/cfe_psp_ssr.c src/cfe_psp_start.c src/cfe_psp_support.c - src/cfe_psp_timer.c - src/cfe_psp_watchdog.c) + src/cfe_psp_watchdog.c +) # The _GNU_SOURCE directive is required to call non-posix APIs # that are specific to the Linux/glibc environment. diff --git a/fsw/pc-linux/psp_module_list.cmake b/fsw/pc-linux/psp_module_list.cmake index 54ffb4c5..992c679b 100644 --- a/fsw/pc-linux/psp_module_list.cmake +++ b/fsw/pc-linux/psp_module_list.cmake @@ -1,4 +1,5 @@ # This is a list of modules that is included as a fixed/base set # when this PSP is selected. They must exist under fsw/modules +timebase_posix_clock eeprom_mmap_file diff --git a/fsw/pc-linux/src/cfe_psp_timer.c b/fsw/pc-linux/src/cfe_psp_timer.c deleted file mode 100644 index f047dca7..00000000 --- a/fsw/pc-linux/src/cfe_psp_timer.c +++ /dev/null @@ -1,192 +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: cfe_psp_timer.c -** -** Purpose: -** This file contains glue routines between the cFE and the OS Board Support Package ( BSP ). -** The functions here allow the cFE to interface functions that are board and OS specific -** and usually dont fit well in the OS abstraction layer. -** -** History: -** 2005/06/05 K.Audra | Initial version, -** -*************************************************************************************************/ - -/* -** Include Files -*/ - -/* -** cFE includes -*/ -#include "common_types.h" -#include "osapi.h" - -/* -** System Include Files -*/ -#include -#include - -/* -** Types and prototypes for this module -*/ -#include "cfe_psp.h" - -/******************* Macro Definitions ***********************/ - -/** - * \brief Resolution of the least significant 32 bits of the 64 bit - * time stamp returned by OS_BSPGet_Timebase in timer ticks per second. - * The timer resolution for accuracy should not be any slower than 1000000 - * ticks per second or 1 us per tick - */ -#define CFE_PSP_TIMER_TICKS_PER_SECOND 1000000 - -/** - * \brief The number that the least significant 32 bits of the 64 bit - * time stamp returned by OS_BSPGet_Timebase rolls over. If the lower 32 - * bits rolls at 1 second, then the OS_BSP_TIMER_LOW32_ROLLOVER will be 1000000. - * if the lower 32 bits rolls at its maximum value (2^32) then - * OS_BSP_TIMER_LOW32_ROLLOVER will be 0. - */ -#define CFE_PSP_TIMER_LOW32_ROLLOVER 1000000 - -/****************************************************************************** -** Function: CFE_PSP_GetTime() -** -** Purpose: Gets the value of the time from the hardware -** -** Arguments: LocalTime - where the time is returned through -******************************************************************************/ - -void CFE_PSP_GetTime(OS_time_t *LocalTime) -{ - - /* since we don't have a hardware register to access like the mcp750, - * we use a call to the OS to get the time */ - - OS_GetLocalTime(LocalTime); - -} /* end CFE_PSP_GetLocalTime */ - -/****************************************************************************** -** Function: CFE_PSP_Get_Timer_Tick() -** -** Purpose: -** Provides a common interface to system clock tick. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** OS system clock ticks per second -*/ -uint32 CFE_PSP_Get_Timer_Tick(void) -{ - /* SUB -add function call code*/ - return (0); -} - -/****************************************************************************** -** Function: CFE_PSP_GetTimerTicksPerSecond() -** -** Purpose: -** Provides the resolution of the least significant 32 bits of the 64 bit -** time stamp returned by OS_BSPGet_Timebase in timer ticks per second. -** The timer resolution for accuracy should not be any slower than 1000000 -** ticks per second or 1 us per tick -** -** Arguments: -** -** Return: -** The number of timer ticks per second of the time stamp returned -** by CFE_PSP_Get_Timebase -*/ -uint32 CFE_PSP_GetTimerTicksPerSecond(void) -{ - return (CFE_PSP_TIMER_TICKS_PER_SECOND); -} - -/****************************************************************************** -** Function: CFE_PSP_GetTimerLow32Rollover() -** -** Purpose: -** Provides the number that the least significant 32 bits of the 64 bit -** time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 -** bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. -** if the lower 32 bits rolls at its maximum value (2^32) then -** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. -** -** Arguments: -** -** Return: -** The number that the least significant 32 bits of the 64 bit time stamp -** returned by CFE_PSP_Get_Timebase rolls over. -*/ -uint32 CFE_PSP_GetTimerLow32Rollover(void) -{ - return (CFE_PSP_TIMER_LOW32_ROLLOVER); -} - -/****************************************************************************** -** Function: CFE_PSP_Get_Timebase() -** -** Purpose: -** Provides a common interface to system timebase. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** Timebase register value -*/ -void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl) -{ - OS_time_t time; - - OS_GetLocalTime(&time); - *Tbu = OS_TimeGetTotalSeconds(time); - *Tbl = OS_TimeGetMicrosecondsPart(time); -} - -/****************************************************************************** -** Function: CFE_PSP_Get_Dec() -** -** Purpose: -** Provides a common interface to decrementer counter. This routine -** is in the PSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** Timebase register value -*/ - -uint32 CFE_PSP_Get_Dec(void) -{ - /* SUB -add function call code*/ - return (0); -} diff --git a/fsw/pc-rtems/CMakeLists.txt b/fsw/pc-rtems/CMakeLists.txt index 98a963a9..73ef083b 100644 --- a/fsw/pc-rtems/CMakeLists.txt +++ b/fsw/pc-rtems/CMakeLists.txt @@ -14,7 +14,6 @@ add_library(psp-${CFE_PSP_TARGETNAME}-impl OBJECT src/cfe_psp_ssr.c src/cfe_psp_start.c src/cfe_psp_support.c - src/cfe_psp_timer.c src/cfe_psp_watchdog.c ) diff --git a/fsw/pc-rtems/psp_module_list.cmake b/fsw/pc-rtems/psp_module_list.cmake index 38b24e37..7d03ab30 100644 --- a/fsw/pc-rtems/psp_module_list.cmake +++ b/fsw/pc-rtems/psp_module_list.cmake @@ -2,3 +2,4 @@ # when this PSP is selected. They must exist under fsw/modules eeprom_stub +timebase_posix_clock diff --git a/fsw/pc-rtems/src/cfe_psp_timer.c b/fsw/pc-rtems/src/cfe_psp_timer.c deleted file mode 100644 index 60fcb135..00000000 --- a/fsw/pc-rtems/src/cfe_psp_timer.c +++ /dev/null @@ -1,188 +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: cfe_psp_timer.c -** -** Purpose: -** This file contains glue routines between the cFE and the OS Board Support Package ( BSP ). -** The functions here allow the cFE to interface functions that are board and OS specific -** and usually dont fit well in the OS abstraction layer. -** -** History: -** 2005/06/05 K.Audra | Initial version, -** -*************************************************************************************************/ - -/* -** Include Files -*/ - -/* -** Include Files -*/ -#include -#include - -/* -** cFE includes -*/ -#include "common_types.h" -#include "osapi.h" - -/* -** Types and prototypes for this module -*/ -#include "cfe_psp.h" - -/******************* Macro Definitions ***********************/ -#define WATCHDOG_MIN_TIME 0 -#define WATCHDOG_MAX_TIME 0xFFFFFFFF - -/** - * /brief Resolution of the least significant 32 bits of the 64 bit - * time stamp returned by CFE_PSP_Get_Timebase in timer ticks per second. - * The timer resolution for accuracy should not be any slower than 1000000 - * ticks per second or 1 us per tick - */ -#define CFE_PSP_TIMER_TICKS_PER_SECOND 100 - -/** - * /brief The number that the least significant 32 bits of the 64 bit - * time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 - * bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. - * if the lower 32 bits rolls at its maximum value (2^32) then - * CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. - */ -#define CFE_PSP_TIMER_LOW32_ROLLOVER 0 - -/****************************************************************************** -** Function: CFE_PSP_GetTime() -** -** Purpose: Gets the value of the time from the hardware -** -** Arguments: LocalTime - where the time is returned through -******************************************************************************/ - -void CFE_PSP_GetTime(OS_time_t *LocalTime) -{ - OS_GetLocalTime(LocalTime); - -} /* end CFE_PSP_GetLocalTime */ - -/****************************************************************************** -** Function: CFE_PSP_Get_Timer_Tick() -** -** Purpose: -** Provides a common interface to system clock tick. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** OS system clock ticks per second -*/ -uint32 CFE_PSP_Get_Timer_Tick(void) -{ - return (0); -} - -/****************************************************************************** -** Function: CFE_PSP_GetTimerTicksPerSecond() -** -** Purpose: -** Provides the resolution of the least significant 32 bits of the 64 bit -** time stamp returned by CFE_PSP_Get_Timebase in timer ticks per second. -** The timer resolution for accuracy should not be any slower than 1000000 -** ticks per second or 1 us per tick -** -** Arguments: -** -** Return: -** The number of timer ticks per second of the time stamp returned -** by CFE_PSP_Get_Timebase -*/ -uint32 CFE_PSP_GetTimerTicksPerSecond(void) -{ - return (CFE_PSP_TIMER_TICKS_PER_SECOND); -} - -/****************************************************************************** -** Function: CFE_PSP_GetTimerLow32Rollover() -** -** Purpose: -** Provides the number that the least significant 32 bits of the 64 bit -** time stamp returned by CFE_PSP_Get_Timebase rolls over. If the lower 32 -** bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER will be 1000000. -** if the lower 32 bits rolls at its maximum value (2^32) then -** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0. -** -** Arguments: -** -** Return: -** The number that the least significant 32 bits of the 64 bit time stamp -** returned by CFE_PSP_Get_Timebase rolls over. -*/ -uint32 CFE_PSP_GetTimerLow32Rollover(void) -{ - return (CFE_PSP_TIMER_LOW32_ROLLOVER); -} - -/****************************************************************************** -** Function: CFE_PSP_Get_Timebase() -** -** Purpose: -** Provides a common interface to system timebase. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** Timebase register value -*/ -void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl) -{ - OS_time_t time; - - OS_GetLocalTime(&time); - *Tbu = OS_TimeGetTotalSeconds(time); - *Tbl = OS_TimeGetMicrosecondsPart(time); -} - -/****************************************************************************** -** Function: CFE_PSP_Get_Dec() -** -** Purpose: -** Provides a common interface to decrementer counter. This routine -** is in the BSP because it is sometimes implemented in hardware and -** sometimes taken care of by the RTOS. -** -** Arguments: -** -** Return: -** Timebase register value -*/ - -uint32 CFE_PSP_Get_Dec(void) -{ - return (0); -} diff --git a/unit-test-coverage/CMakeLists.txt b/unit-test-coverage/CMakeLists.txt index d9836875..447d1484 100644 --- a/unit-test-coverage/CMakeLists.txt +++ b/unit-test-coverage/CMakeLists.txt @@ -30,6 +30,7 @@ include_directories(${UT_ASSERT_SOURCE_DIR}/inc) include_directories(${PSPCOVERAGE_SOURCE_DIR}/ut-stubs/inc) add_subdirectory(ut-stubs) +add_subdirectory(modules) # Build targets for each of the indicated PSPs foreach(SETNAME ${PSPCOVERAGE_TARGETS}) diff --git a/unit-test-coverage/modules/CMakeLists.txt b/unit-test-coverage/modules/CMakeLists.txt new file mode 100644 index 00000000..b28d4a51 --- /dev/null +++ b/unit-test-coverage/modules/CMakeLists.txt @@ -0,0 +1,67 @@ +###################################################################### +# +# CMAKE build recipe for PSP modules white-box coverage tests +# +###################################################################### + +include_directories("${PSPCOVERAGE_SOURCE_DIR}/shared/inc") +include_directories("${PSPCOVERAGE_SOURCE_DIR}/modules/inc") + +# redefine the add_psp_module to make a unit test variant +# this needs to name the target differently, so it doesn't conflict with the FSW target. +# this is similar to add_cfe_coverage_test() on the CFE side, but the set of interfaces +# and link libraries is different from that of a CFS app +function(add_psp_module MODULE_NAME) + + set(TEST_NAME "coverage-pspmod-${MODULE_NAME}") + set(OBJECT_TARGET "${TEST_NAME}-object") + set(RUNNER_TARGET "${TEST_NAME}-testrunner") + # Create the module + + add_library(${OBJECT_TARGET} OBJECT ${ARGN}) + + target_compile_options(${OBJECT_TARGET} PRIVATE + ${UT_COVERAGE_COMPILE_FLAGS} + ) + target_include_directories(${OBJECT_TARGET} PRIVATE + ${PSPCOVERAGE_SOURCE_DIR}/ut-stubs/override_inc # overrides for system headers + ${CFEPSP_SOURCE_DIR}/fsw/inc # PSP public API + ${CFEPSP_SOURCE_DIR}/fsw/shared/inc # all PSP shared headers + ${CFE_SOURCE_DIR}/cmake/target/inc # for sysconfig headers + $ # use headers from OSAL + ) + + # Compile a test runner application, which contains the + # actual coverage test code (test cases) and the unit under test + add_executable(${RUNNER_TARGET} + ${PSPCOVERAGE_SOURCE_DIR}/modules/src/coveragetest-${MODULE_NAME}.c + $ + ) + + # This also needs to be linked with UT_COVERAGE_LINK_FLAGS (for coverage) + # This is also linked with any other stub libraries needed, + # as well as the UT assert framework + target_link_libraries(${RUNNER_TARGET} + ${UT_COVERAGE_LINK_FLAGS} + psp_module_api + ut_psp_libc_stubs + ut_osapi_stubs + ut_assert + ) + + add_test(${TEST_NAME} ${RUNNER_TARGET}) + foreach(TGT ${INSTALL_TARGET_LIST}) + install(TARGETS ${RUNNER_TARGET} DESTINATION ${TGT}/${UT_INSTALL_SUBDIR}) + endforeach() + +endfunction(add_psp_module) + +# a list of modules for which there is a coverage test implemented +set(UT_PSPMODLIST + timebase_vxworks +) + +foreach(UT_PSPMOD ${UT_PSPMODLIST}) + add_subdirectory(${CFEPSP_SOURCE_DIR}/fsw/modules/${UT_PSPMOD} ${UT_PSPMOD}) +endforeach() + diff --git a/unit-test-coverage/modules/inc/cfe_psp_config.h b/unit-test-coverage/modules/inc/cfe_psp_config.h new file mode 100644 index 00000000..55d3294b --- /dev/null +++ b/unit-test-coverage/modules/inc/cfe_psp_config.h @@ -0,0 +1,35 @@ +/* + * + * Copyright (c) 2020, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Goddard + * Space Flight Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + * + */ + +/** + * \file + * \ingroup modules + * + * Stub for "cfe_psp_config.h" to use with coverage testing + */ + +#ifndef COVERAGETEST_CFE_PSP_CONFIG_H +#define COVERAGETEST_CFE_PSP_CONFIG_H + +#define CFE_PSP_VX_TIMEBASE_PERIOD_NUMERATOR (UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodNumerator) +#define CFE_PSP_VX_TIMEBASE_PERIOD_DENOMINATOR (UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodDenominator) + +typedef struct +{ + unsigned long PeriodNumerator; + unsigned long PeriodDenominator; + +} UT_PSP_TimeBase_VxWorks_TestConfig_t; + +extern UT_PSP_TimeBase_VxWorks_TestConfig_t UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG; + +#endif /* COVERAGETEST_CFE_PSP_CONFIG_H */ diff --git a/unit-test-coverage/modules/inc/coveragetest-timebase_vxworks.h b/unit-test-coverage/modules/inc/coveragetest-timebase_vxworks.h new file mode 100644 index 00000000..5a499ee7 --- /dev/null +++ b/unit-test-coverage/modules/inc/coveragetest-timebase_vxworks.h @@ -0,0 +1,29 @@ +/* + * + * Copyright (c) 2020, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Goddard + * Space Flight Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + * + */ + +/** + * \file psp-shared-coveragetest.h + * \ingroup vxworks + * \author joseph.p.hickey@nasa.gov + * + */ + +#ifndef INCLUDE_PSP_SHARED_COVERAGETEST_H_ +#define INCLUDE_PSP_SHARED_COVERAGETEST_H_ + +#include "utassert.h" +#include "uttest.h" +#include "utstubs.h" + +void Test_CFE_PSP_Timebase_Vxworks_Init(void); + +#endif /* INCLUDE_PSP_SHARED_COVERAGETEST_H_ */ diff --git a/unit-test-coverage/modules/src/coveragetest-timebase_vxworks.c b/unit-test-coverage/modules/src/coveragetest-timebase_vxworks.c new file mode 100644 index 00000000..00e76e48 --- /dev/null +++ b/unit-test-coverage/modules/src/coveragetest-timebase_vxworks.c @@ -0,0 +1,224 @@ +/* + * + * Copyright (c) 2020, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Goddard + * Space Flight Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + * + */ + +/** + * \file + * \ingroup modules + * + * Coverage test for VxWorks timebase module implementation + */ + +#include "utassert.h" +#include "utstubs.h" +#include "uttest.h" + +#include "cfe_psp.h" +#include "cfe_psp_config.h" +#include "cfe_psp_module.h" + +#include "PCS_arch_ppc_vxPpcLib.h" + +/* + * Reference to the API entry point for the module + */ +extern CFE_PSP_ModuleApi_t CFE_PSP_timebase_vxworks_API; + +const CFE_PSP_ModuleApi_t *TgtAPI = &CFE_PSP_timebase_vxworks_API; + +UT_PSP_TimeBase_VxWorks_TestConfig_t UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG; + +typedef struct +{ + uint32 u; + uint32 l; +} PSP_VxWorks_TimeBaseVal_t; + +void ModuleTest_ResetState(void) +{ + memset(&UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG, 0, sizeof(UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG)); +} + +int32 UTHOOK_vxTimeBaseGet(void *UserObj, int32 StubRetcode, uint32 CallCount, const UT_StubContext_t *Context) +{ + PSP_VxWorks_TimeBaseVal_t *val = UserObj; + uint32 * u = UT_Hook_GetArgValueByName(Context, "u", uint32 *); + uint32 * l = UT_Hook_GetArgValueByName(Context, "l", uint32 *); + + *u = val->u; + *l = val->l; + + return StubRetcode; +} + +void Test_Nominal(void) +{ + OS_time_t OsTime; + PSP_VxWorks_TimeBaseVal_t VxTime; + + /* Nominal test with a simple 1:1 ratio */ + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodNumerator = 1; + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodDenominator = 1; + TgtAPI->Init(0); + UtAssert_UINT32_EQ(CFE_PSP_GetTimerTicksPerSecond(), 1000000000); + + /* Check operation of CFE_PSP_GetTime() */ + UT_SetHookFunction(UT_KEY(PCS_vxTimeBaseGet), UTHOOK_vxTimeBaseGet, &VxTime); + VxTime.u = 0; + VxTime.l = 10000; + CFE_PSP_GetTime(&OsTime); + + UtAssert_UINT32_EQ(OS_TimeGetNanosecondsPart(OsTime), 10000); +} + +void Test_Non_Reducible(void) +{ + OS_time_t OsTime; + PSP_VxWorks_TimeBaseVal_t VxTime; + int64 TestTime; + + /* Use an oddball ratio of of some primes, will not be reducible */ + /* Ratio is 43*3 / 53*2 => 129/106 */ + /* This translates to about ~1.217ns per tick */ + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodNumerator = 43 * 3; + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodDenominator = 53 * 2; + TgtAPI->Init(0); + UtAssert_UINT32_EQ(CFE_PSP_GetTimerTicksPerSecond(), 821705426); + + /* + * Check operation of CFE_PSP_GetTime() + * + * This test requires that the conversion uses the actual ratio, + * otherwise a rounding error will be noticed. + * For example: + * Conversion using 1.217ns/tick yields 52269758 usec (wrong). + * Conversion using actual ratio yields 52268947 usec. + */ + + UT_SetHookFunction(UT_KEY(PCS_vxTimeBaseGet), UTHOOK_vxTimeBaseGet, &VxTime); + VxTime.u = 10; + VxTime.l = 5000; + CFE_PSP_GetTime(&OsTime); + + TestTime = OS_TimeGetTotalMicroseconds(OsTime); + UtAssert_True(TestTime == 52268947, "CFE_PSP_GetTime() Microseconds (%lld) == 52268947", (long long)TestTime); +} + +void Test_Reducible_1(void) +{ + OS_time_t OsTime; + PSP_VxWorks_TimeBaseVal_t VxTime; + int64 TestTime; + + /* Test with a ratio that is also 1:1, but can be reduced */ + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodNumerator = 1000; + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodDenominator = 1000; + TgtAPI->Init(0); + UtAssert_UINT32_EQ(CFE_PSP_GetTimerTicksPerSecond(), 1000000000); + + /* + * Check operation of CFE_PSP_GetTime() + * + * Externally calculated value should be 10376293541461622 usec. + * If overflow occurs then value will be wrong. + */ + UT_SetHookFunction(UT_KEY(PCS_vxTimeBaseGet), UTHOOK_vxTimeBaseGet, &VxTime); + VxTime.u = 0x90000000; /* nearing 64-bit limit */ + VxTime.l = 0; + CFE_PSP_GetTime(&OsTime); + + TestTime = OS_TimeGetTotalMicroseconds(OsTime); + UtAssert_True(TestTime == 10376293541461622, "CFE_PSP_GetTime() Microseconds (%lld) == 10376293541461622", + (long long)TestTime); +} + +void Test_Reducible_2(void) +{ + OS_time_t OsTime; + PSP_VxWorks_TimeBaseVal_t VxTime; + int64 TestTime; + + /* Test with a ratio that can be reduced */ + /* Final reduced ratio should be 12:5 with 100ns OS ticks */ + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodNumerator = 84000; + UT_PSP_TIMEBASE_VXWORKS_TESTCONFIG.PeriodDenominator = 350; + TgtAPI->Init(0); + UtAssert_UINT32_EQ(CFE_PSP_GetTimerTicksPerSecond(), 4166666); + + /* + * Check operation of CFE_PSP_GetTime() + * + * Externally calculated value should be 276701161105643274 usec. + * If overflow occurs then value will be wrong. + */ + UT_SetHookFunction(UT_KEY(PCS_vxTimeBaseGet), UTHOOK_vxTimeBaseGet, &VxTime); + VxTime.u = 0x10000000; /* nearing 64-bit limit */ + VxTime.l = 0; + CFE_PSP_GetTime(&OsTime); + + TestTime = OS_TimeGetTotalMicroseconds(OsTime); + UtAssert_True(TestTime == 276701161105643274, "CFE_PSP_GetTime() Microseconds(%lld) == 276701161105643274", + (long long)TestTime); +} + +void Test_Rollover(void) +{ + /* This function always returns 0 */ + UtAssert_UINT32_EQ(CFE_PSP_GetTimerLow32Rollover(), 0); +} + +/****************************************************************************** +** Function: CFE_PSP_Get_Timebase() +** +** Purpose: +** Provides a common interface to system timebase. This routine +** is in the BSP because it is sometimes implemented in hardware and +** sometimes taken care of by the RTOS. +** +** Arguments: +** +** Return: +** Timebase register value +*/ +void Test_Get_Timebase(void) +{ + PSP_VxWorks_TimeBaseVal_t VxTime; + uint32 tbu; + uint32 tbl; + + /* The value from vxTimeBaseGet() should be passed through unchanged */ + UT_SetHookFunction(UT_KEY(PCS_vxTimeBaseGet), UTHOOK_vxTimeBaseGet, &VxTime); + VxTime.u = 0x00112233; + VxTime.l = 0x44556677; + + CFE_PSP_Get_Timebase(&tbu, &tbl); + + UtAssert_UINT32_EQ(tbu, VxTime.u); + UtAssert_UINT32_EQ(tbl, VxTime.l); +} + +/* + * Macro to add a test case to the list of tests to execute + */ +#define ADD_TEST(test) UtTest_Add(test, ModuleTest_ResetState, NULL, #test) + +/* + * Register the test cases to execute with the unit test tool + */ +void UtTest_Setup(void) +{ + ADD_TEST(Test_Nominal); + ADD_TEST(Test_Non_Reducible); + ADD_TEST(Test_Reducible_1); + ADD_TEST(Test_Reducible_2); + ADD_TEST(Test_Rollover); + ADD_TEST(Test_Get_Timebase); +} diff --git a/unit-test-coverage/ut-stubs/inc/PCS_time.h b/unit-test-coverage/ut-stubs/inc/PCS_time.h new file mode 100644 index 00000000..5cd9ee08 --- /dev/null +++ b/unit-test-coverage/ut-stubs/inc/PCS_time.h @@ -0,0 +1,19 @@ +/* PSP coverage stub replacement for time.h */ +#ifndef PSP_STUB_TIME_H +#define PSP_STUB_TIME_H + +#include "PCS_basetypes.h" + +/* ----------------------------------------- */ +/* constants normally defined in time.h */ +/* ----------------------------------------- */ + +/* ----------------------------------------- */ +/* types normally defined in time.h */ +/* ----------------------------------------- */ + +/* ----------------------------------------- */ +/* prototypes normally declared in time.h */ +/* ----------------------------------------- */ + +#endif /* PSP_STUB_TIME_H */ diff --git a/unit-test-coverage/ut-stubs/override_inc/time.h b/unit-test-coverage/ut-stubs/override_inc/time.h new file mode 100644 index 00000000..10f78f10 --- /dev/null +++ b/unit-test-coverage/ut-stubs/override_inc/time.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019, United States government as represented by the + * administrator of the National Aeronautics Space Administration. + * All rights reserved. This software was created at NASA Goddard + * Space Flight Center pursuant to government contracts. + * + * This is governed by the NASA Open Source Agreement and may be used, + * distributed and modified only according to the terms of that agreement. + */ + +/* PSP coverage stub replacement for time.h */ +#ifndef _PSP_OVERRIDE_TIME_H_ +#define _PSP_OVERRIDE_TIME_H_ + +#include "PCS_time.h" + +#endif /* _PSP_OVERRIDE_TIME_H_ */ diff --git a/unit-test-coverage/ut-stubs/src/vxworks-vxLib-stubs.c b/unit-test-coverage/ut-stubs/src/vxworks-vxLib-stubs.c index 85ea5396..1f6e900f 100644 --- a/unit-test-coverage/ut-stubs/src/vxworks-vxLib-stubs.c +++ b/unit-test-coverage/ut-stubs/src/vxworks-vxLib-stubs.c @@ -18,9 +18,11 @@ void PCS_vxTimeBaseGet(uint32_t *u, uint32_t *l) { - UT_DEFAULT_IMPL(PCS_vxTimeBaseGet); + UT_Stub_RegisterContextGenericArg(UT_KEY(PCS_vxTimeBaseGet), u); + UT_Stub_RegisterContextGenericArg(UT_KEY(PCS_vxTimeBaseGet), l); *u = 0; *l = 0; + UT_DEFAULT_IMPL(PCS_vxTimeBaseGet); } void PCS_vxMsrSet(uint32_t val) { From a85e78b24c0b97c6c8fdb873daad2af45781fe26 Mon Sep 17 00:00:00 2001 From: "Gerardo E. Cruz-Ortiz" <59618057+astrogeco@users.noreply.github.com> Date: Thu, 8 Apr 2021 14:58:07 -0400 Subject: [PATCH 6/6] IC:2021-04-06, Bump to v1.5.0-rc1+dev112 --- README.md | 11 +++++++++++ fsw/mcp750-vxworks/inc/psp_version.h | 2 +- fsw/pc-linux/inc/psp_version.h | 2 +- fsw/pc-rtems/inc/psp_version.h | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 69691f83..fcb0630f 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,17 @@ This is a collection of APIs abstracting platform specific functionality to be l ## Version History + +### Development Build: v1.5.0-rc1+dev112 + +- Cleans up stale code from the previous methods of generating 1Hz. Adds a new PSP module that instantiates an OSAL abstract timebase for use with cFE services. This single module is used across all psp implementations (mcp750, pc-linux, pc-rtems). Results in 1Hz timing tick on MCP750 will be more accurate. No changes to Linux or RTEMS +- Fixes segfaults when `CFE_PSP_Port` routines are invoked on Linux. +- Converts `cfe_psp_ram.c` and `cfe_psp_port.c` into modular components and removes from the "shared" directory. The existing implementations become the corresponding "direct" module, and are enabled based on the psp module selection. Adds a "notimpl" variant where all the functions return `CFE_PSP_ERR_NOT_IMPLEMENTED`. This is used on Linux +or any other system where direct access is not possible. Renames the existing `eeprom_stub` module to be `eeprom_notimpl` for consistency and to avoid confusion with the unit test stubs. +- Implements two PSP modules to provide `CFE_PSP_GetTime` and `CFE_PSP_GetTimeBase`, one for POSIX-compliant RTOS using `clock_gettime()` and the other specifically for PowerPC processors on VxWorks that have the `vxTimeBaseGet()` routine. Clarifies and documents the difference and use cases for `CFE_PSP_GetTime` and `CFE_PSP_GetTimeBase`. No impact to behavior. +- Adds a coverage test for the VxWorks PSP timebase module and provides an example of how this can be implemented for other modules. +- See and + ### Development Build: v1.5.0-rc1+dev101 - Removes unnecessary global config structure `Target_PspConfigData` and associated elements infavor of the new version API. diff --git a/fsw/mcp750-vxworks/inc/psp_version.h b/fsw/mcp750-vxworks/inc/psp_version.h index d6608424..2e35b6d9 100644 --- a/fsw/mcp750-vxworks/inc/psp_version.h +++ b/fsw/mcp750-vxworks/inc/psp_version.h @@ -29,7 +29,7 @@ /* * Development Build Macro Definitions */ -#define CFE_PSP_IMPL_BUILD_NUMBER 101 +#define CFE_PSP_IMPL_BUILD_NUMBER 112 #define CFE_PSP_IMPL_BUILD_BASELINE "v1.5.0-rc1" /* diff --git a/fsw/pc-linux/inc/psp_version.h b/fsw/pc-linux/inc/psp_version.h index 07441680..3f98ceb4 100644 --- a/fsw/pc-linux/inc/psp_version.h +++ b/fsw/pc-linux/inc/psp_version.h @@ -29,7 +29,7 @@ /* * Development Build Macro Definitions */ -#define CFE_PSP_IMPL_BUILD_NUMBER 101 +#define CFE_PSP_IMPL_BUILD_NUMBER 112 #define CFE_PSP_IMPL_BUILD_BASELINE "v1.5.0-rc1" /* diff --git a/fsw/pc-rtems/inc/psp_version.h b/fsw/pc-rtems/inc/psp_version.h index 9ef4cf8f..4bcecbdc 100644 --- a/fsw/pc-rtems/inc/psp_version.h +++ b/fsw/pc-rtems/inc/psp_version.h @@ -29,7 +29,7 @@ /* * Development Build Macro Definitions */ -#define CFE_PSP_IMPL_BUILD_NUMBER 101 +#define CFE_PSP_IMPL_BUILD_NUMBER 112 #define CFE_PSP_IMPL_BUILD_BASELINE "v1.5.0-rc1" /*