From fc6e9b23985761e168f354919b5e3b91f73b1449 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Fri, 26 Mar 2021 14:39:28 -0400 Subject: [PATCH] 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) {