From 32f420c4f0abb9294b6fd178bfd48edb7402de12 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 7 Mar 2022 16:13:04 +0100 Subject: [PATCH 1/5] SPI HAL improvement - Initialize line state --- hal/src/fsfw_hal/linux/spi/SpiComIF.cpp | 8 ++++++++ hal/src/fsfw_hal/linux/spi/SpiComIF.h | 1 + 2 files changed, 9 insertions(+) diff --git a/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp b/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp index d95232c1e..dcf92b5d9 100644 --- a/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp +++ b/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp @@ -401,4 +401,12 @@ void SpiComIF::setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed) if (retval != 0) { utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI speed failed"); } + // This updates the SPI clock default polarity. Only setting the mode does not update + // the line state, which can be an issue on mode switches because the clock line will + // switch the state after the chip select is pulled low + clockUpdateTransfer.len = 0; + retval = ioctl(spiFd, SPI_IOC_MESSAGE(1), &clockUpdateTransfer); + if (retval != 0) { + utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Updating SPI default clock failed"); + } } diff --git a/hal/src/fsfw_hal/linux/spi/SpiComIF.h b/hal/src/fsfw_hal/linux/spi/SpiComIF.h index 1f825d526..357afa2f7 100644 --- a/hal/src/fsfw_hal/linux/spi/SpiComIF.h +++ b/hal/src/fsfw_hal/linux/spi/SpiComIF.h @@ -74,6 +74,7 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject { MutexIF* spiMutex = nullptr; MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; uint32_t timeoutMs = 20; + spi_ioc_transfer clockUpdateTransfer = {}; using SpiDeviceMap = std::unordered_map; using SpiDeviceMapIter = SpiDeviceMap::iterator; From 983fa346b30441e98081992f8abebeb16aa24483 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 7 Mar 2022 16:17:33 +0100 Subject: [PATCH 2/5] update CHANGELOG --- CHANGELOG.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa59651f7..717932c52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,17 +12,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Changes -- HAL Devicehandlers: Periodic printout is run-time configurable now -- `oneShotAction` flag in the `TestTask` class is not static anymore +- HAL Linux SPI: Set the Clock Default State when setting new SPI speed + and mode + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573 +- HAL Devicehandlers: Periodic printout is run-time configurable now. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/561 +- `oneShotAction` flag in the `TestTask` class is not static anymore. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/560 ## Removed - Removed the `HkSwitchHelper`. This module should not be needed anymore, now that the local - datapools have been implemented + datapools have been implemented. + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/557 ## Additions - Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1 + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559 # [v4.0.0] From 8b1af232c37fb5a4a2f6d573ed31076025b2f282 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Mon, 7 Mar 2022 18:22:10 +0100 Subject: [PATCH 3/5] Added Tests for CCSDS Time, fixed LPM Test Changed behaviour of Host and Linux Clock --- src/fsfw/osal/host/Clock.cpp | 7 ++-- src/fsfw/osal/linux/Clock.cpp | 3 +- src/fsfw/timemanager/CCSDSTime.cpp | 29 +++++++++++++++++ src/fsfw/timemanager/CCSDSTime.h | 2 ++ .../datapoollocal/LocalPoolManagerTest.cpp | 18 ++++------- .../unit/timemanager/TestCCSDSTime.cpp | 32 +++++++++++++++++++ 6 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/fsfw/osal/host/Clock.cpp b/src/fsfw/osal/host/Clock.cpp index 62f9d9d5f..d0acdfdf0 100644 --- a/src/fsfw/osal/host/Clock.cpp +++ b/src/fsfw/osal/host/Clock.cpp @@ -150,17 +150,14 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* time_tm.tm_hour = from->hour; time_tm.tm_min = from->minute; time_tm.tm_sec = from->second; + time_tm.tm_isdst = 0; - time_t seconds = mktime(&time_tm); + time_t seconds = timegm(&time_tm); to->tv_sec = seconds; to->tv_usec = from->usecond; // Fails in 2038.. return HasReturnvaluesIF::RETURN_OK; -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "Clock::convertTimeBla: not implemented yet" << std::endl; -#endif - return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { diff --git a/src/fsfw/osal/linux/Clock.cpp b/src/fsfw/osal/linux/Clock.cpp index 7092e6b2b..61eb970ff 100644 --- a/src/fsfw/osal/linux/Clock.cpp +++ b/src/fsfw/osal/linux/Clock.cpp @@ -140,8 +140,9 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* fromTm.tm_hour = from->hour; fromTm.tm_min = from->minute; fromTm.tm_sec = from->second; + fromTm.tm_isdst = 0; - to->tv_sec = mktime(&fromTm); + to->tv_sec = timegm(&fromTm); to->tv_usec = from->usecond; return HasReturnvaluesIF::RETURN_OK; } diff --git a/src/fsfw/timemanager/CCSDSTime.cpp b/src/fsfw/timemanager/CCSDSTime.cpp index 290d58dce..c5132cbb0 100644 --- a/src/fsfw/timemanager/CCSDSTime.cpp +++ b/src/fsfw/timemanager/CCSDSTime.cpp @@ -557,6 +557,35 @@ ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, size_t return RETURN_OK; } +ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const CCSDSTime::CDS_short* from) { + if (to == nullptr or from == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + uint16_t days = (from->dayMSB << 8) + from->dayLSB; + if (days <= DAYS_CCSDS_TO_UNIX_EPOCH) { + return INVALID_TIME_FORMAT; + } + days -= DAYS_CCSDS_TO_UNIX_EPOCH; + to->tv_sec = days * SECONDS_PER_DAY; + uint32_t msDay = + (from->msDay_hh << 24) + (from->msDay_h << 16) + (from->msDay_l << 8) + from->msDay_ll; + to->tv_sec += (msDay / 1000); + to->tv_usec = (msDay % 1000) * 1000; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t CCSDSTime::convertFromCDS(Clock::TimeOfDay_t* to, const CCSDSTime::CDS_short* from) { + if (to == nullptr or from == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + timeval tempTimeval; + ReturnValue_t result = convertFromCDS(&tempTimeval, from); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return CCSDSTime::convertTimevalToTimeOfDay(to, &tempTimeval); +} + ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, const uint8_t* from, size_t* foundLength, size_t maxLength) { uint32_t secs = 0; diff --git a/src/fsfw/timemanager/CCSDSTime.h b/src/fsfw/timemanager/CCSDSTime.h index 4a0e1bfc4..9de41e097 100644 --- a/src/fsfw/timemanager/CCSDSTime.h +++ b/src/fsfw/timemanager/CCSDSTime.h @@ -180,6 +180,8 @@ class CCSDSTime : public HasReturnvaluesIF { static ReturnValue_t convertFromCDS(timeval *to, uint8_t const *from, size_t *foundLength, size_t maxLength); + static ReturnValue_t convertFromCDS(timeval *to, const CCSDSTime::CDS_short *from); + static ReturnValue_t convertFromCDS(Clock::TimeOfDay_t *to, const CCSDSTime::CDS_short *from); static ReturnValue_t convertFromCCS(Clock::TimeOfDay_t *to, uint8_t const *from, size_t *foundLength, size_t maxLength); diff --git a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp index fb22972e3..05436d30b 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp +++ b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -158,13 +159,10 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") { } poolVar->setChanged(true); - /* Store current time, we are going to check the (approximate) time equality later */ CCSDSTime::CDS_short timeCdsNow; timeval now; Clock::getClock_timeval(&now); - CCSDSTime::convertToCcsds(&timeCdsNow, &now); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); /* Check update snapshot was sent. */ @@ -192,14 +190,12 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") { SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); CHECK(varCopy.value == 25); - /* Now we check that both times are equal */ - CHECK(cdsShort.pField == timeCdsNow.pField); - CHECK(cdsShort.dayLSB == Catch::Approx(timeCdsNow.dayLSB).margin(1)); - CHECK(cdsShort.dayMSB == Catch::Approx(timeCdsNow.dayMSB).margin(1)); - CHECK(cdsShort.msDay_h == Catch::Approx(timeCdsNow.msDay_h).margin(1)); - CHECK(cdsShort.msDay_hh == Catch::Approx(timeCdsNow.msDay_hh).margin(1)); - CHECK(cdsShort.msDay_l == Catch::Approx(timeCdsNow.msDay_l).margin(1)); - CHECK(cdsShort.msDay_ll == Catch::Approx(timeCdsNow.msDay_ll).margin(5)); + timeval timeFromHK; + auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); + CHECK(result == HasReturnvaluesIF::RETURN_OK); + /// timeval* to, const uint8_t* from, size_t* foundLength,size_t maxLength) + timeval difference = timeFromHK - now; + CHECK(timevalOperations::toDouble(difference) < 1.0); } SECTION("VariableNotificationTest") { diff --git a/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp b/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp index 89713488b..271e094e4 100644 --- a/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp +++ b/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -89,4 +90,35 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { REQUIRE(timeTo.second == 59); REQUIRE(timeTo.usecond == Catch::Approx(123000)); } + + SECTION("CDS Conversions") { + // Preperation + Clock::TimeOfDay_t time; + time.year = 2020; + time.month = 2; + time.day = 29; + time.hour = 13; + time.minute = 24; + time.second = 45; + time.usecond = 123456; + timeval timeAsTimeval; + auto result = Clock::convertTimeOfDayToTimeval(&time, &timeAsTimeval); + CHECK(result == HasReturnvaluesIF::RETURN_OK); + CHECK(timeAsTimeval.tv_sec == 1582982685); + CHECK(timeAsTimeval.tv_usec == 123456); + + // Conversion to CDS Short + CCSDSTime::CDS_short cdsTime; + result = CCSDSTime::convertToCcsds(&cdsTime, &timeAsTimeval); + CHECK(result == HasReturnvaluesIF::RETURN_OK); + + // Conversion back to timeval + timeval timeReturnAsTimeval; + result = CCSDSTime::convertFromCDS(&timeReturnAsTimeval, &cdsTime); + CHECK(result == HasReturnvaluesIF::RETURN_OK); + // us precision is lost + timeval difference = timeAsTimeval - timeReturnAsTimeval; + CHECK(difference.tv_usec == 456); + CHECK(difference.tv_sec == 0); + } } \ No newline at end of file From a4f97a7ba793f9c1fb277e4f685909d483abf0e0 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Mon, 7 Mar 2022 18:33:24 +0100 Subject: [PATCH 4/5] Fixed another issue of time checks --- .../unit/datapoollocal/LocalPoolManagerTest.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp index 05436d30b..077625959 100644 --- a/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp +++ b/tests/src/fsfw_tests/unit/datapoollocal/LocalPoolManagerTest.cpp @@ -94,10 +94,8 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") { poolOwner->dataset.setChanged(true); /* Store current time, we are going to check the (approximate) time equality later */ - CCSDSTime::CDS_short timeCdsNow; timeval now; Clock::getClock_timeval(&now); - CCSDSTime::convertToCcsds(&timeCdsNow, &now); /* Trigger generation of snapshot */ REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); @@ -132,13 +130,11 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") { CHECK(newSet.localPoolUint16Vec.value[2] == 42932); /* Now we check that both times are equal */ - CHECK(cdsShort.pField == timeCdsNow.pField); - CHECK(cdsShort.dayLSB == Catch::Approx(timeCdsNow.dayLSB).margin(1)); - CHECK(cdsShort.dayMSB == Catch::Approx(timeCdsNow.dayMSB).margin(1)); - CHECK(cdsShort.msDay_h == Catch::Approx(timeCdsNow.msDay_h).margin(1)); - CHECK(cdsShort.msDay_hh == Catch::Approx(timeCdsNow.msDay_hh).margin(1)); - CHECK(cdsShort.msDay_l == Catch::Approx(timeCdsNow.msDay_l).margin(1)); - CHECK(cdsShort.msDay_ll == Catch::Approx(timeCdsNow.msDay_ll).margin(5)); + timeval timeFromHK; + auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); + CHECK(result == HasReturnvaluesIF::RETURN_OK); + timeval difference = timeFromHK - now; + CHECK(timevalOperations::toDouble(difference) < 1.0); } SECTION("VariableSnapshotTest") { @@ -190,10 +186,10 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") { SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); CHECK(varCopy.value == 25); + /* Now we check that both times are equal */ timeval timeFromHK; auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); CHECK(result == HasReturnvaluesIF::RETURN_OK); - /// timeval* to, const uint8_t* from, size_t* foundLength,size_t maxLength) timeval difference = timeFromHK - now; CHECK(timevalOperations::toDouble(difference) < 1.0); } From 445d5dd6f0a1cc67fdb107741d4b3871b38f48cb Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 9 Mar 2022 18:56:08 +0100 Subject: [PATCH 5/5] Added Checks for CDSShort in unittests --- .../src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp b/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp index 271e094e4..2e80487aa 100644 --- a/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp +++ b/tests/src/fsfw_tests/unit/timemanager/TestCCSDSTime.cpp @@ -111,12 +111,20 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") { CCSDSTime::CDS_short cdsTime; result = CCSDSTime::convertToCcsds(&cdsTime, &timeAsTimeval); CHECK(result == HasReturnvaluesIF::RETURN_OK); + // Days in CCSDS Epoch 22704 (0x58B0) + CHECK(cdsTime.dayMSB == 0x58); + CHECK(cdsTime.dayLSB == 0xB0); + // MS of day 48285123.456 (floored here) + CHECK(cdsTime.msDay_hh == 0x2); + CHECK(cdsTime.msDay_h == 0xE0); + CHECK(cdsTime.msDay_l == 0xC5); + CHECK(cdsTime.msDay_ll == 0xC3); // Conversion back to timeval timeval timeReturnAsTimeval; result = CCSDSTime::convertFromCDS(&timeReturnAsTimeval, &cdsTime); CHECK(result == HasReturnvaluesIF::RETURN_OK); - // us precision is lost + // micro seconds precision is lost timeval difference = timeAsTimeval - timeReturnAsTimeval; CHECK(difference.tv_usec == 456); CHECK(difference.tv_sec == 0);