From 7426e10f8270cc4988daf45c8bc1bcd3e72b0904 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Thu, 26 Jan 2023 11:33:40 +0100 Subject: [PATCH] clocks suck a little less --- src/fsfw/devicehandlers/DeviceHandlerBase.cpp | 11 ++- src/fsfw/osal/linux/Clock.cpp | 18 +---- src/fsfw/osal/rtems/Clock.cpp | 69 +++++-------------- src/fsfw/pus/Service9TimeManagement.cpp | 7 +- src/fsfw/subsystem/Subsystem.cpp | 5 +- src/fsfw/thermal/Heater.cpp | 5 +- src/fsfw/timemanager/ClockCommon.cpp | 28 ++++++-- src/fsfw/timemanager/Countdown.cpp | 8 +-- .../tmtcservices/CommandingServiceBase.cpp | 5 +- 9 files changed, 59 insertions(+), 97 deletions(-) diff --git a/src/fsfw/devicehandlers/DeviceHandlerBase.cpp b/src/fsfw/devicehandlers/DeviceHandlerBase.cpp index 60966501a..86df52c28 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerBase.cpp +++ b/src/fsfw/devicehandlers/DeviceHandlerBase.cpp @@ -321,8 +321,7 @@ void DeviceHandlerBase::doStateMachine() { if (mode != currentMode) { break; } - uint32_t currentUptime; - Clock::getUptime(¤tUptime); + uint32_t currentUptime = Clock::getUptime_ms(); if (currentUptime - timeoutStart >= childTransitionDelay) { #if FSFW_VERBOSE_LEVEL >= 1 && FSFW_OBJ_EVENT_TRANSLATION == 0 char printout[60]; @@ -346,8 +345,7 @@ void DeviceHandlerBase::doStateMachine() { setMode(_MODE_WAIT_ON); break; case _MODE_WAIT_ON: { - uint32_t currentUptime; - Clock::getUptime(¤tUptime); + uint32_t currentUptime = Clock::getUptime_ms(); if (powerSwitcher != nullptr and currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) { triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0); @@ -366,8 +364,7 @@ void DeviceHandlerBase::doStateMachine() { } } break; case _MODE_WAIT_OFF: { - uint32_t currentUptime; - Clock::getUptime(¤tUptime); + uint32_t currentUptime = Clock::getUptime_ms(); if (powerSwitcher == nullptr) { setMode(MODE_OFF); @@ -577,7 +574,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { modeHelper.modeChanged(newMode, newSubmode); announceMode(false); } - Clock::getUptime(&timeoutStart); + timeoutStart = Clock::getUptime_ms(); if (mode == MODE_OFF and thermalSet != nullptr) { ReturnValue_t result = thermalSet->read(); diff --git a/src/fsfw/osal/linux/Clock.cpp b/src/fsfw/osal/linux/Clock.cpp index c7c92415b..c860e5df2 100644 --- a/src/fsfw/osal/linux/Clock.cpp +++ b/src/fsfw/osal/linux/Clock.cpp @@ -37,20 +37,8 @@ timeval Clock::getUptime() { timeval uptime{0,0}; double uptimeSeconds; if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) { - uptime->tv_sec = uptimeSeconds; - uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6); + uptime.tv_sec = uptimeSeconds; + uptime.tv_usec = uptimeSeconds * (double)1e6 - (uptime.tv_sec * 1e6); } return uptime; -} - -// Wait for new FSFW Clock function delivering seconds uptime. -// uint32_t Clock::getUptimeSeconds() { -// //TODO This is not posix compatible and delivers only seconds precision -// struct sysinfo sysInfo; -// int result = sysinfo(&sysInfo); -// if(result != 0){ -// return returnvalue::FAILED; -// } -// return sysInfo.uptime; -//} - +} \ No newline at end of file diff --git a/src/fsfw/osal/rtems/Clock.cpp b/src/fsfw/osal/rtems/Clock.cpp index d5d61ef78..2cf903c84 100644 --- a/src/fsfw/osal/rtems/Clock.cpp +++ b/src/fsfw/osal/rtems/Clock.cpp @@ -6,20 +6,21 @@ #include "fsfw/ipc/MutexGuard.h" #include "fsfw/osal/rtems/RtemsBasic.h" -uint32_t Clock::getTicksPerSecond(void) { - rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second(); - return static_cast(ticks_per_second); -} -ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { +ReturnValue_t Clock::setClock(const timeval* time) { + TimeOfDay_t time_tod; + ReturnValue_t result = convertTimevalToTimeOfDay(time, &time_tod); + if (result != returnvalue::OK) { + return result; + } rtems_time_of_day timeRtems; - timeRtems.year = time->year; - timeRtems.month = time->month; - timeRtems.day = time->day; - timeRtems.hour = time->hour; - timeRtems.minute = time->minute; - timeRtems.second = time->second; - timeRtems.ticks = time->usecond * getTicksPerSecond() / 1e6; + timeRtems.year = time_tod.year; + timeRtems.month = time_tod.month; + timeRtems.day = time_tod.day; + timeRtems.hour = time_tod.hour; + timeRtems.minute = time_tod.minute; + timeRtems.second = time_tod.second; + timeRtems.ticks = static_cast(time_tod.usecond) * rtems_clock_get_ticks_per_second() / 1e6; rtems_status_code status = rtems_clock_set(&timeRtems); switch (status) { case RTEMS_SUCCESSFUL: @@ -33,15 +34,6 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { } } -ReturnValue_t Clock::setClock(const timeval* time) { - TimeOfDay_t time_tod; - ReturnValue_t result = convertTimevalToTimeOfDay(time, &time_tod); - if (result != returnvalue::OK) { - return result; - } - return setClock(&time_tod); -} - ReturnValue_t Clock::getClock_timeval(timeval* time) { // Callable from ISR rtems_status_code status = rtems_clock_get_tod_timeval(time); @@ -55,36 +47,13 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) { } } -ReturnValue_t Clock::getUptime(timeval* uptime) { +timeval Clock::getUptime() { // According to docs.rtems.org for rtems 5 this method is more accurate than // rtems_clock_get_ticks_since_boot + timeval time_timeval; timespec time; rtems_status_code status = rtems_clock_get_uptime(&time); - uptime->tv_sec = time.tv_sec; - uptime->tv_usec = time.tv_nsec / 1000; - switch (status) { - case RTEMS_SUCCESSFUL: - return returnvalue::OK; - default: - return returnvalue::FAILED; - } -} - -ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { - // 32bit counter overflows after 50 days - uint64_t uptime = rtems_clock_get_uptime_nanoseconds() / 1e6; - *uptimeMs = uptime & 0xffffffff; - return returnvalue::OK; -} - -ReturnValue_t Clock::getClock_usecs(uint64_t* time) { - timeval temp_time; - rtems_status_code returnValue = rtems_clock_get_tod_timeval(&temp_time); - *time = ((uint64_t)temp_time.tv_sec * 1000000) + temp_time.tv_usec; - switch (returnValue) { - case RTEMS_SUCCESSFUL: - return returnvalue::OK; - default: - return returnvalue::FAILED; - } -} + time_timeval.tv_sec = time.tv_sec; + time_timeval.tv_usec = time.tv_nsec / 1000; + return time_timeval; +} \ No newline at end of file diff --git a/src/fsfw/pus/Service9TimeManagement.cpp b/src/fsfw/pus/Service9TimeManagement.cpp index d19cb5182..0ea369f74 100644 --- a/src/fsfw/pus/Service9TimeManagement.cpp +++ b/src/fsfw/pus/Service9TimeManagement.cpp @@ -33,13 +33,12 @@ ReturnValue_t Service9TimeManagement::setTime() { return result; } - uint32_t formerUptime; - Clock::getUptime(&formerUptime); + // TODO maybe switch to getClock_usecs to report more meaningful data + uint32_t formerUptime = Clock::getUptime_ms(); result = Clock::setClock(&timeToSet); if (result == returnvalue::OK) { - uint32_t newUptime; - Clock::getUptime(&newUptime); + uint32_t newUptime = Clock::getUptime_ms(); triggerEvent(CLOCK_SET, newUptime, formerUptime); return returnvalue::OK; } else { diff --git a/src/fsfw/subsystem/Subsystem.cpp b/src/fsfw/subsystem/Subsystem.cpp index b2af5ac37..6624d86ec 100644 --- a/src/fsfw/subsystem/Subsystem.cpp +++ b/src/fsfw/subsystem/Subsystem.cpp @@ -91,11 +91,10 @@ void Subsystem::performChildOperation() { } if (currentSequenceIterator->getWaitSeconds() != 0) { if (uptimeStartTable == 0) { - Clock::getUptime(&uptimeStartTable); + uptimeStartTable = Clock::getUptime_ms(); return; } else { - uint32_t uptimeNow; - Clock::getUptime(&uptimeNow); + uint32_t uptimeNow = Clock::getUptime_ms(); if ((uptimeNow - uptimeStartTable) < (currentSequenceIterator->getWaitSeconds() * 1000)) { return; } diff --git a/src/fsfw/thermal/Heater.cpp b/src/fsfw/thermal/Heater.cpp index 64348106a..a37ae066c 100644 --- a/src/fsfw/thermal/Heater.cpp +++ b/src/fsfw/thermal/Heater.cpp @@ -198,10 +198,9 @@ void Heater::setSwitch(uint8_t number, ReturnValue_t state, uint32_t* uptimeOfSw } else { if ((*uptimeOfSwitching == INVALID_UPTIME)) { powerSwitcher->sendSwitchCommand(number, state); - Clock::getUptime(uptimeOfSwitching); + *uptimeOfSwitching = Clock::getUptime_ms(); } else { - uint32_t currentUptime; - Clock::getUptime(¤tUptime); + uint32_t currentUptime = Clock::getUptime_ms(); if (currentUptime - *uptimeOfSwitching > powerSwitcher->getSwitchDelayMs()) { *uptimeOfSwitching = INVALID_UPTIME; if (healthHelper.healthTable->isHealthy(getObjectId())) { diff --git a/src/fsfw/timemanager/ClockCommon.cpp b/src/fsfw/timemanager/ClockCommon.cpp index a35848277..d5f9c2f83 100644 --- a/src/fsfw/timemanager/ClockCommon.cpp +++ b/src/fsfw/timemanager/ClockCommon.cpp @@ -1,4 +1,5 @@ #include +#include #include "fsfw/ipc/MutexGuard.h" #include "fsfw/timemanager/Clock.h" @@ -91,15 +92,28 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* time_tm.tm_isdst = 0; -#ifdef PLATFORM_WIN - time_t seconds = _mkgmtime(&time_tm); -#else - time_t seconds = timegm(&time_tm); -#endif - + // Windows: + // time_t seconds = _mkgmtime(&time_tm); + // Glibc: + // time_t seconds = timegm(&time_tm); + // Portable (?) + char* tz; + tz = getenv("TZ"); + setenv("TZ", "", 1); + tzset(); + time_t seconds = mktime(&time_tm); + if (tz) + setenv("TZ", tz, 1); + else + unsetenv("TZ"); + tzset(); to->tv_sec = seconds; to->tv_usec = from->usecond; + if (seconds == (time_t) -1) { + return returnvalue::FAILED; + } + return returnvalue::OK; } @@ -152,6 +166,6 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { } uint32_t Clock::getUptime_ms() { timeval uptime = getUptime(); - //TODO verify that overflow is correct + // TODO verify that overflow is correct return uptime.tv_sec * 1e3 + uptime.tv_usec / 1e3; } \ No newline at end of file diff --git a/src/fsfw/timemanager/Countdown.cpp b/src/fsfw/timemanager/Countdown.cpp index a8ba78cbb..9f0152a9e 100644 --- a/src/fsfw/timemanager/Countdown.cpp +++ b/src/fsfw/timemanager/Countdown.cpp @@ -7,9 +7,9 @@ Countdown::Countdown(uint32_t initialTimeout) : timeout(initialTimeout) { Countdown::~Countdown() {} ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) { - ReturnValue_t returnValue = Clock::getUptime(&startTime); + startTime = Clock::getUptime_ms(); timeout = milliseconds; - return returnValue; + return returnvalue::OK; } bool Countdown::hasTimedOut() const { @@ -39,7 +39,5 @@ uint32_t Countdown::getRemainingMillis() const { } uint32_t Countdown::getCurrentTime() const { - uint32_t currentTime; - Clock::getUptime(¤tTime); - return currentTime; + return Clock::getUptime_ms(); } diff --git a/src/fsfw/tmtcservices/CommandingServiceBase.cpp b/src/fsfw/tmtcservices/CommandingServiceBase.cpp index 1ec5c0d81..59addbdfa 100644 --- a/src/fsfw/tmtcservices/CommandingServiceBase.cpp +++ b/src/fsfw/tmtcservices/CommandingServiceBase.cpp @@ -348,7 +348,7 @@ void CommandingServiceBase::startExecution(store_address_t storeId, CommandMapIt sendResult = commandQueue->sendMessage(iter.value->first, &command); } if (sendResult == returnvalue::OK) { - Clock::getUptime(&iter->second.uptimeOfStart); + iter->second.uptimeOfStart = Clock::getUptime_ms(); iter->second.step = 0; iter->second.subservice = tcReader.getSubService(); iter->second.command = command.getCommand(); @@ -434,8 +434,7 @@ inline void CommandingServiceBase::doPeriodicOperation() {} MessageQueueId_t CommandingServiceBase::getCommandQueue() { return commandQueue->getId(); } void CommandingServiceBase::checkTimeout() { - uint32_t uptime; - Clock::getUptime(&uptime); + uint32_t uptime = Clock::getUptime_ms(); CommandMapIter iter; for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) { if ((iter->second.uptimeOfStart + (timeoutSeconds * 1000)) < uptime) {