Merge branch 'mueller/event-update' of https://egit.irs.uni-stuttgart.de/eive/fsfw into mueller/event-update
This commit is contained in:
commit
bc95e7c886
14
CHANGELOG.md
14
CHANGELOG.md
@ -12,17 +12,29 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
|
- 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
|
||||||
|
- GPIO HAL: `Direction`, `GpioOperation` and `Levels` are enum classes now, which prevents
|
||||||
|
name clashes with Windows defines.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||||
|
- New CMake option `FSFW_HAL_LINUX_ADD_LIBGPIOD` to specifically exclude `gpiod` code.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||||
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
||||||
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
||||||
|
|
||||||
## Removed
|
## Removed
|
||||||
|
|
||||||
- Removed the `HkSwitchHelper`. This module should not be needed anymore, now that the local
|
- 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
|
## Additions
|
||||||
|
|
||||||
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
|
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
|
||||||
|
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
||||||
|
inside `fsfw/version.h`
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
||||||
|
|
||||||
# [v4.0.0]
|
# [v4.0.0]
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ option(FSFW_HAL_ADD_LINUX "Add the Linux HAL to the sources. Requires gpiod libr
|
|||||||
# Linux. The only exception from this is the gpiod library which requires a dedicated installation,
|
# Linux. The only exception from this is the gpiod library which requires a dedicated installation,
|
||||||
# but CMake is able to determine whether this library is installed with find_library.
|
# but CMake is able to determine whether this library is installed with find_library.
|
||||||
option(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS "Add peripheral drivers for embedded Linux" ON)
|
option(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS "Add peripheral drivers for embedded Linux" ON)
|
||||||
|
option(FSFW_HAL_LINUX_ADD_LIBGPIOD "Target implements libgpiod" ON)
|
||||||
|
|
||||||
option(FSFW_HAL_ADD_RASPBERRY_PI "Add Raspberry Pi specific code to the sources" OFF)
|
option(FSFW_HAL_ADD_RASPBERRY_PI "Add Raspberry Pi specific code to the sources" OFF)
|
||||||
option(FSFW_HAL_ADD_STM32H7 "Add the STM32H7 HAL to the sources" OFF)
|
option(FSFW_HAL_ADD_STM32H7 "Add the STM32H7 HAL to the sources" OFF)
|
||||||
|
@ -9,11 +9,11 @@ using gpioId_t = uint16_t;
|
|||||||
|
|
||||||
namespace gpio {
|
namespace gpio {
|
||||||
|
|
||||||
enum Levels : uint8_t { LOW = 0, HIGH = 1, NONE = 99 };
|
enum class Levels : int { LOW = 0, HIGH = 1, NONE = 99 };
|
||||||
|
|
||||||
enum Direction : uint8_t { IN = 0, OUT = 1 };
|
enum class Direction : int { IN = 0, OUT = 1 };
|
||||||
|
|
||||||
enum GpioOperation { READ, WRITE };
|
enum class GpioOperation { READ, WRITE };
|
||||||
|
|
||||||
enum class GpioTypes {
|
enum class GpioTypes {
|
||||||
NONE,
|
NONE,
|
||||||
@ -80,7 +80,7 @@ class GpiodRegularByChip : public GpiodRegularBase {
|
|||||||
public:
|
public:
|
||||||
GpiodRegularByChip()
|
GpiodRegularByChip()
|
||||||
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, std::string(), gpio::Direction::IN,
|
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, std::string(), gpio::Direction::IN,
|
||||||
gpio::LOW, 0) {}
|
gpio::Levels::LOW, 0) {}
|
||||||
|
|
||||||
GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_,
|
GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_,
|
||||||
gpio::Direction direction_, gpio::Levels initValue_)
|
gpio::Direction direction_, gpio::Levels initValue_)
|
||||||
@ -90,7 +90,7 @@ class GpiodRegularByChip : public GpiodRegularBase {
|
|||||||
|
|
||||||
GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_)
|
GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_)
|
||||||
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, consumer_, gpio::Direction::IN,
|
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, consumer_, gpio::Direction::IN,
|
||||||
gpio::LOW, lineNum_),
|
gpio::Levels::LOW, lineNum_),
|
||||||
chipname(chipname_) {}
|
chipname(chipname_) {}
|
||||||
|
|
||||||
std::string chipname;
|
std::string chipname;
|
||||||
@ -106,7 +106,7 @@ class GpiodRegularByLabel : public GpiodRegularBase {
|
|||||||
|
|
||||||
GpiodRegularByLabel(std::string label_, int lineNum_, std::string consumer_)
|
GpiodRegularByLabel(std::string label_, int lineNum_, std::string consumer_)
|
||||||
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL, consumer_, gpio::Direction::IN,
|
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL, consumer_, gpio::Direction::IN,
|
||||||
gpio::LOW, lineNum_),
|
gpio::Levels::LOW, lineNum_),
|
||||||
label(label_) {}
|
label(label_) {}
|
||||||
|
|
||||||
std::string label;
|
std::string label;
|
||||||
@ -127,7 +127,7 @@ class GpiodRegularByLineName : public GpiodRegularBase {
|
|||||||
|
|
||||||
GpiodRegularByLineName(std::string lineName_, std::string consumer_)
|
GpiodRegularByLineName(std::string lineName_, std::string consumer_)
|
||||||
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME, consumer_, gpio::Direction::IN,
|
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME, consumer_, gpio::Direction::IN,
|
||||||
gpio::LOW),
|
gpio::Levels::LOW),
|
||||||
lineName(lineName_) {}
|
lineName(lineName_) {}
|
||||||
|
|
||||||
std::string lineName;
|
std::string lineName;
|
||||||
|
@ -9,7 +9,9 @@ target_sources(${LIB_FSFW_NAME} PRIVATE
|
|||||||
)
|
)
|
||||||
|
|
||||||
if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS)
|
if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS)
|
||||||
|
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
|
||||||
add_subdirectory(gpio)
|
add_subdirectory(gpio)
|
||||||
|
endif()
|
||||||
add_subdirectory(spi)
|
add_subdirectory(spi)
|
||||||
add_subdirectory(i2c)
|
add_subdirectory(i2c)
|
||||||
add_subdirectory(uart)
|
add_subdirectory(uart)
|
||||||
|
@ -161,11 +161,12 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
|
|||||||
consumer = regularGpio.consumer;
|
consumer = regularGpio.consumer;
|
||||||
/* Configure direction and add a description to the GPIO */
|
/* Configure direction and add a description to the GPIO */
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case (gpio::OUT): {
|
case (gpio::Direction::OUT): {
|
||||||
result = gpiod_line_request_output(lineHandle, consumer.c_str(), regularGpio.initValue);
|
result = gpiod_line_request_output(lineHandle, consumer.c_str(),
|
||||||
|
static_cast<int>(regularGpio.initValue));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (gpio::IN): {
|
case (gpio::Direction::IN): {
|
||||||
result = gpiod_line_request_input(lineHandle, consumer.c_str());
|
result = gpiod_line_request_input(lineHandle, consumer.c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -211,7 +212,7 @@ ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
|
|||||||
if (regularGpio == nullptr) {
|
if (regularGpio == nullptr) {
|
||||||
return GPIO_TYPE_FAILURE;
|
return GPIO_TYPE_FAILURE;
|
||||||
}
|
}
|
||||||
return driveGpio(gpioId, *regularGpio, gpio::HIGH);
|
return driveGpio(gpioId, *regularGpio, gpio::Levels::HIGH);
|
||||||
} else {
|
} else {
|
||||||
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
|
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
|
||||||
if (gpioCallback->callback == nullptr) {
|
if (gpioCallback->callback == nullptr) {
|
||||||
@ -243,7 +244,7 @@ ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
|
|||||||
if (regularGpio == nullptr) {
|
if (regularGpio == nullptr) {
|
||||||
return GPIO_TYPE_FAILURE;
|
return GPIO_TYPE_FAILURE;
|
||||||
}
|
}
|
||||||
return driveGpio(gpioId, *regularGpio, gpio::LOW);
|
return driveGpio(gpioId, *regularGpio, gpio::Levels::LOW);
|
||||||
} else {
|
} else {
|
||||||
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
|
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
|
||||||
if (gpioCallback->callback == nullptr) {
|
if (gpioCallback->callback == nullptr) {
|
||||||
@ -258,11 +259,11 @@ ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
|
|||||||
|
|
||||||
ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, GpiodRegularBase& regularGpio,
|
ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, GpiodRegularBase& regularGpio,
|
||||||
gpio::Levels logicLevel) {
|
gpio::Levels logicLevel) {
|
||||||
int result = gpiod_line_set_value(regularGpio.lineHandle, logicLevel);
|
int result = gpiod_line_set_value(regularGpio.lineHandle, static_cast<int>(logicLevel));
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID " << gpioId
|
sif::warning << "LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID " << gpioId
|
||||||
<< " to logic level " << logicLevel << std::endl;
|
<< " to logic level " << static_cast<int>(logicLevel) << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning(
|
sif::printWarning(
|
||||||
"LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID %d to "
|
"LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID %d to "
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
ReturnValue_t gpio::createRpiGpioConfig(GpioCookie* cookie, gpioId_t gpioId, int bcmPin,
|
ReturnValue_t gpio::createRpiGpioConfig(GpioCookie* cookie, gpioId_t gpioId, int bcmPin,
|
||||||
std::string consumer, gpio::Direction direction,
|
std::string consumer, gpio::Direction direction,
|
||||||
int initValue) {
|
gpio::Levels initValue) {
|
||||||
if (cookie == nullptr) {
|
if (cookie == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,8 @@ namespace gpio {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t createRpiGpioConfig(GpioCookie* cookie, gpioId_t gpioId, int bcmPin,
|
ReturnValue_t createRpiGpioConfig(GpioCookie* cookie, gpioId_t gpioId, int bcmPin,
|
||||||
std::string consumer, gpio::Direction direction, int initValue);
|
std::string consumer, gpio::Direction direction,
|
||||||
|
gpio::Levels initValue);
|
||||||
} // namespace gpio
|
} // namespace gpio
|
||||||
|
|
||||||
#endif /* BSP_RPI_GPIO_GPIORPI_H_ */
|
#endif /* BSP_RPI_GPIO_GPIORPI_H_ */
|
||||||
|
@ -401,4 +401,12 @@ void SpiComIF::setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed)
|
|||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI speed failed");
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,7 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
|||||||
MutexIF* spiMutex = nullptr;
|
MutexIF* spiMutex = nullptr;
|
||||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||||
uint32_t timeoutMs = 20;
|
uint32_t timeoutMs = 20;
|
||||||
|
spi_ioc_transfer clockUpdateTransfer = {};
|
||||||
|
|
||||||
using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>;
|
using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>;
|
||||||
using SpiDeviceMapIter = SpiDeviceMap::iterator;
|
using SpiDeviceMapIter = SpiDeviceMap::iterator;
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
|
version.cpp
|
||||||
|
)
|
||||||
|
|
||||||
# Core
|
# Core
|
||||||
|
|
||||||
add_subdirectory(action)
|
add_subdirectory(action)
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
#define FSFW_VERSION_H_
|
#define FSFW_VERSION_H_
|
||||||
|
|
||||||
// Versioning is kept in project CMakeLists.txt file
|
// Versioning is kept in project CMakeLists.txt file
|
||||||
#define FSFW_VERSION @FSFW_VERSION@
|
#define FSFW_VERSION_MAJOR @FSFW_VERSION@
|
||||||
#define FSFW_SUBVERSION @FSFW_SUBVERSION@
|
#define FSFW_VERSION_MINOR @FSFW_SUBVERSION@
|
||||||
#define FSFW_REVISION @FSFW_REVISION@
|
#define FSFW_VERSION_REVISION @FSFW_REVISION@
|
||||||
|
|
||||||
#endif /* FSFW_VERSION_H_ */
|
#endif /* FSFW_VERSION_H_ */
|
||||||
|
@ -150,17 +150,14 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval*
|
|||||||
time_tm.tm_hour = from->hour;
|
time_tm.tm_hour = from->hour;
|
||||||
time_tm.tm_min = from->minute;
|
time_tm.tm_min = from->minute;
|
||||||
time_tm.tm_sec = from->second;
|
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_sec = seconds;
|
||||||
to->tv_usec = from->usecond;
|
to->tv_usec = from->usecond;
|
||||||
// Fails in 2038..
|
// Fails in 2038..
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
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) {
|
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
|
||||||
|
@ -140,8 +140,9 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval*
|
|||||||
fromTm.tm_hour = from->hour;
|
fromTm.tm_hour = from->hour;
|
||||||
fromTm.tm_min = from->minute;
|
fromTm.tm_min = from->minute;
|
||||||
fromTm.tm_sec = from->second;
|
fromTm.tm_sec = from->second;
|
||||||
|
fromTm.tm_isdst = 0;
|
||||||
|
|
||||||
to->tv_sec = mktime(&fromTm);
|
to->tv_sec = timegm(&fromTm);
|
||||||
to->tv_usec = from->usecond;
|
to->tv_usec = from->usecond;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
@ -557,6 +557,35 @@ ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, size_t
|
|||||||
return RETURN_OK;
|
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,
|
ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, const uint8_t* from,
|
||||||
size_t* foundLength, size_t maxLength) {
|
size_t* foundLength, size_t maxLength) {
|
||||||
uint32_t secs = 0;
|
uint32_t secs = 0;
|
||||||
|
@ -180,6 +180,8 @@ class CCSDSTime : public HasReturnvaluesIF {
|
|||||||
|
|
||||||
static ReturnValue_t convertFromCDS(timeval *to, uint8_t const *from, size_t *foundLength,
|
static ReturnValue_t convertFromCDS(timeval *to, uint8_t const *from, size_t *foundLength,
|
||||||
size_t maxLength);
|
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,
|
static ReturnValue_t convertFromCCS(Clock::TimeOfDay_t *to, uint8_t const *from,
|
||||||
size_t *foundLength, size_t maxLength);
|
size_t *foundLength, size_t maxLength);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "fsfw/timemanager/Countdown.h"
|
#include "fsfw/timemanager/Countdown.h"
|
||||||
|
|
||||||
Countdown::Countdown(uint32_t initialTimeout) : timeout(initialTimeout) {}
|
Countdown::Countdown(uint32_t initialTimeout) : timeout(initialTimeout) {
|
||||||
|
setTimeout(initialTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
Countdown::~Countdown() {}
|
Countdown::~Countdown() {}
|
||||||
|
|
||||||
|
22
src/fsfw/version.cpp
Normal file
22
src/fsfw/version.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "version.h"
|
||||||
|
#include "fsfw/FSFWVersion.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#ifdef major
|
||||||
|
#undef major
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef minor
|
||||||
|
#undef minor
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const fsfw::Version fsfw::FSFW_VERSION = {FSFW_VERSION_MAJOR, FSFW_VERSION_MINOR,
|
||||||
|
FSFW_VERSION_REVISION};
|
||||||
|
|
||||||
|
fsfw::Version::Version(uint32_t major, uint32_t minor, uint32_t revision)
|
||||||
|
: major(major), minor(minor), revision(revision) {}
|
||||||
|
|
||||||
|
void fsfw::Version::getVersion(char* str, size_t maxLen) const {
|
||||||
|
snprintf(str, maxLen, "%d.%d.%d", major, minor, revision);
|
||||||
|
}
|
64
src/fsfw/version.h
Normal file
64
src/fsfw/version.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef FSFW_SRC_FSFW_VERSION_H_
|
||||||
|
#define FSFW_SRC_FSFW_VERSION_H_
|
||||||
|
|
||||||
|
#include "fsfw/FSFW.h"
|
||||||
|
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
#include <iostream>
|
||||||
|
#endif
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace fsfw {
|
||||||
|
|
||||||
|
class Version {
|
||||||
|
public:
|
||||||
|
Version(uint32_t major, uint32_t minor, uint32_t revision);
|
||||||
|
uint32_t major = 0;
|
||||||
|
uint32_t minor = 0;
|
||||||
|
uint32_t revision = 0;
|
||||||
|
|
||||||
|
friend bool operator==(const Version& v1, const Version& v2) {
|
||||||
|
return (v1.major == v2.major and v1.minor == v2.minor and v1.revision == v2.revision);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const Version& v1, const Version& v2) { return not(v1 == v2); }
|
||||||
|
|
||||||
|
friend bool operator<(const Version& v1, const Version& v2) {
|
||||||
|
return ((v1.major < v2.major) or (v1.major == v2.major and v1.minor < v2.minor) or
|
||||||
|
(v1.major == v2.major and v1.minor == v2.minor and v1.revision < v2.revision));
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator>(const Version& v1, const Version& v2) {
|
||||||
|
return not (v1 < v2) and not (v1 == v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator<=(const Version& v1, const Version& v2) { return ((v1 == v2) or (v1 < v2)); }
|
||||||
|
|
||||||
|
friend bool operator>=(const Version& v1, const Version& v2) { return ((v1 == v2) or (v1 > v2)); }
|
||||||
|
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
/**
|
||||||
|
* Print format to given ostream using format "major.minor.revision"
|
||||||
|
* @param os
|
||||||
|
* @param v
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
friend std::ostream& operator<<(std::ostream& os, const Version& v) {
|
||||||
|
os << v.major << "." << v.minor << "." << v.revision;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get version as format "major.minor.revision"
|
||||||
|
* @param str
|
||||||
|
* @param maxLen
|
||||||
|
*/
|
||||||
|
void getVersion(char* str, size_t maxLen) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const fsfw::Version FSFW_VERSION;
|
||||||
|
|
||||||
|
} // namespace fsfw
|
||||||
|
|
||||||
|
#endif /* FSFW_SRC_FSFW_VERSION_H_ */
|
@ -208,7 +208,7 @@ ReturnValue_t TestDevice::buildNormalModeCommand(DeviceCommandId_t deviceCommand
|
|||||||
const uint8_t* commandData,
|
const uint8_t* commandData,
|
||||||
size_t commandDataLen) {
|
size_t commandDataLen) {
|
||||||
if (fullInfoPrintout) {
|
if (fullInfoPrintout) {
|
||||||
#if OBSW_VERBOSE_LEVEL >= 3
|
#if FSFW_VERBOSE_LEVEL >= 3
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::info << "TestDevice::buildTestCommand1: Building normal command" << std::endl;
|
sif::info << "TestDevice::buildTestCommand1: Building normal command" << std::endl;
|
||||||
#else
|
#else
|
||||||
@ -351,7 +351,7 @@ ReturnValue_t TestDevice::scanForReply(const uint8_t* start, size_t len, DeviceC
|
|||||||
switch (pendingCmd) {
|
switch (pendingCmd) {
|
||||||
case (TEST_NORMAL_MODE_CMD): {
|
case (TEST_NORMAL_MODE_CMD): {
|
||||||
if (fullInfoPrintout) {
|
if (fullInfoPrintout) {
|
||||||
#if OBSW_VERBOSE_LEVEL >= 3
|
#if FSFW_VERBOSE_LEVEL >= 3
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::info << "TestDevice::scanForReply: Reply for normal commnand (ID "
|
sif::info << "TestDevice::scanForReply: Reply for normal commnand (ID "
|
||||||
<< TEST_NORMAL_MODE_CMD << ") received!" << std::endl;
|
<< TEST_NORMAL_MODE_CMD << ") received!" << std::endl;
|
||||||
@ -678,7 +678,6 @@ ReturnValue_t TestDevice::getParameter(uint8_t domainId, uint8_t uniqueId,
|
|||||||
int32_t newValue = 0;
|
int32_t newValue = 0;
|
||||||
ReturnValue_t result = newValues->getElement<int32_t>(&newValue, 0, 0);
|
ReturnValue_t result = newValues->getElement<int32_t>(&newValue, 0, 0);
|
||||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||||
#if OBSW_DEVICE_HANDLER_PRINTOUT == 1
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::info << "TestDevice" << deviceIdx
|
sif::info << "TestDevice" << deviceIdx
|
||||||
<< "::getParameter: Setting parameter 1 to "
|
<< "::getParameter: Setting parameter 1 to "
|
||||||
@ -688,7 +687,6 @@ ReturnValue_t TestDevice::getParameter(uint8_t domainId, uint8_t uniqueId,
|
|||||||
sif::printInfo("TestDevice%d::getParameter: Setting parameter 1 to new value %lu\n",
|
sif::printInfo("TestDevice%d::getParameter: Setting parameter 1 to new value %lu\n",
|
||||||
deviceIdx, static_cast<unsigned long>(newValue));
|
deviceIdx, static_cast<unsigned long>(newValue));
|
||||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
#endif /* OBSW_DEVICE_HANDLER_PRINTOUT == 1 */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parameterWrapper->set(testParameter1);
|
parameterWrapper->set(testParameter1);
|
||||||
@ -702,7 +700,6 @@ ReturnValue_t TestDevice::getParameter(uint8_t domainId, uint8_t uniqueId,
|
|||||||
newValues->getElement<float>(newVector + 2, 0, 2) != RETURN_OK) {
|
newValues->getElement<float>(newVector + 2, 0, 2) != RETURN_OK) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
#if OBSW_DEVICE_HANDLER_PRINTOUT == 1
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::info << "TestDevice" << deviceIdx
|
sif::info << "TestDevice" << deviceIdx
|
||||||
<< "::getParameter: Setting parameter 3 to "
|
<< "::getParameter: Setting parameter 3 to "
|
||||||
@ -715,7 +712,6 @@ ReturnValue_t TestDevice::getParameter(uint8_t domainId, uint8_t uniqueId,
|
|||||||
"[%f, %f, %f]\n",
|
"[%f, %f, %f]\n",
|
||||||
deviceIdx, newVector[0], newVector[1], newVector[2]);
|
deviceIdx, newVector[0], newVector[1], newVector[2]);
|
||||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
#endif /* OBSW_DEVICE_HANDLER_PRINTOUT == 1 */
|
|
||||||
}
|
}
|
||||||
parameterWrapper->setVector(vectorFloatParams2);
|
parameterWrapper->setVector(vectorFloatParams2);
|
||||||
break;
|
break;
|
||||||
|
@ -2,14 +2,13 @@ target_sources(${FSFW_TEST_TGT} PRIVATE
|
|||||||
CatchDefinitions.cpp
|
CatchDefinitions.cpp
|
||||||
CatchFactory.cpp
|
CatchFactory.cpp
|
||||||
printChar.cpp
|
printChar.cpp
|
||||||
|
version.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# if(FSFW_CUSTOM_UNITTEST_RUNNER)
|
|
||||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||||
CatchRunner.cpp
|
CatchRunner.cpp
|
||||||
CatchSetup.cpp
|
CatchSetup.cpp
|
||||||
)
|
)
|
||||||
# endif()
|
|
||||||
|
|
||||||
add_subdirectory(testcfg)
|
add_subdirectory(testcfg)
|
||||||
add_subdirectory(action)
|
add_subdirectory(action)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <fsfw/datapool/PoolReadGuard.h>
|
#include <fsfw/datapool/PoolReadGuard.h>
|
||||||
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
|
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
|
||||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||||
|
#include <fsfw/globalfunctions/timevalOperations.h>
|
||||||
#include <fsfw/housekeeping/HousekeepingSnapshot.h>
|
#include <fsfw/housekeeping/HousekeepingSnapshot.h>
|
||||||
#include <fsfw/ipc/CommandMessageCleaner.h>
|
#include <fsfw/ipc/CommandMessageCleaner.h>
|
||||||
#include <fsfw/objectmanager/ObjectManager.h>
|
#include <fsfw/objectmanager/ObjectManager.h>
|
||||||
@ -93,10 +94,8 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
|
|||||||
poolOwner->dataset.setChanged(true);
|
poolOwner->dataset.setChanged(true);
|
||||||
|
|
||||||
/* Store current time, we are going to check the (approximate) time equality later */
|
/* Store current time, we are going to check the (approximate) time equality later */
|
||||||
CCSDSTime::CDS_short timeCdsNow;
|
|
||||||
timeval now;
|
timeval now;
|
||||||
Clock::getClock_timeval(&now);
|
Clock::getClock_timeval(&now);
|
||||||
CCSDSTime::convertToCcsds(&timeCdsNow, &now);
|
|
||||||
|
|
||||||
/* Trigger generation of snapshot */
|
/* Trigger generation of snapshot */
|
||||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||||
@ -131,13 +130,11 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
|
|||||||
CHECK(newSet.localPoolUint16Vec.value[2] == 42932);
|
CHECK(newSet.localPoolUint16Vec.value[2] == 42932);
|
||||||
|
|
||||||
/* Now we check that both times are equal */
|
/* Now we check that both times are equal */
|
||||||
CHECK(cdsShort.pField == timeCdsNow.pField);
|
timeval timeFromHK;
|
||||||
CHECK(cdsShort.dayLSB == Catch::Approx(timeCdsNow.dayLSB).margin(1));
|
auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort);
|
||||||
CHECK(cdsShort.dayMSB == Catch::Approx(timeCdsNow.dayMSB).margin(1));
|
CHECK(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
CHECK(cdsShort.msDay_h == Catch::Approx(timeCdsNow.msDay_h).margin(1));
|
timeval difference = timeFromHK - now;
|
||||||
CHECK(cdsShort.msDay_hh == Catch::Approx(timeCdsNow.msDay_hh).margin(1));
|
CHECK(timevalOperations::toDouble(difference) < 1.0);
|
||||||
CHECK(cdsShort.msDay_l == Catch::Approx(timeCdsNow.msDay_l).margin(1));
|
|
||||||
CHECK(cdsShort.msDay_ll == Catch::Approx(timeCdsNow.msDay_ll).margin(5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("VariableSnapshotTest") {
|
SECTION("VariableSnapshotTest") {
|
||||||
@ -158,13 +155,10 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
poolVar->setChanged(true);
|
poolVar->setChanged(true);
|
||||||
|
|
||||||
/* Store current time, we are going to check the (approximate) time equality later */
|
/* Store current time, we are going to check the (approximate) time equality later */
|
||||||
CCSDSTime::CDS_short timeCdsNow;
|
CCSDSTime::CDS_short timeCdsNow;
|
||||||
timeval now;
|
timeval now;
|
||||||
Clock::getClock_timeval(&now);
|
Clock::getClock_timeval(&now);
|
||||||
CCSDSTime::convertToCcsds(&timeCdsNow, &now);
|
|
||||||
|
|
||||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||||
|
|
||||||
/* Check update snapshot was sent. */
|
/* Check update snapshot was sent. */
|
||||||
@ -193,13 +187,11 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
|
|||||||
CHECK(varCopy.value == 25);
|
CHECK(varCopy.value == 25);
|
||||||
|
|
||||||
/* Now we check that both times are equal */
|
/* Now we check that both times are equal */
|
||||||
CHECK(cdsShort.pField == timeCdsNow.pField);
|
timeval timeFromHK;
|
||||||
CHECK(cdsShort.dayLSB == Catch::Approx(timeCdsNow.dayLSB).margin(1));
|
auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort);
|
||||||
CHECK(cdsShort.dayMSB == Catch::Approx(timeCdsNow.dayMSB).margin(1));
|
CHECK(result == HasReturnvaluesIF::RETURN_OK);
|
||||||
CHECK(cdsShort.msDay_h == Catch::Approx(timeCdsNow.msDay_h).margin(1));
|
timeval difference = timeFromHK - now;
|
||||||
CHECK(cdsShort.msDay_hh == Catch::Approx(timeCdsNow.msDay_hh).margin(1));
|
CHECK(timevalOperations::toDouble(difference) < 1.0);
|
||||||
CHECK(cdsShort.msDay_l == Catch::Approx(timeCdsNow.msDay_l).margin(1));
|
|
||||||
CHECK(cdsShort.msDay_ll == Catch::Approx(timeCdsNow.msDay_ll).margin(5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("VariableNotificationTest") {
|
SECTION("VariableNotificationTest") {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <fsfw/globalfunctions/timevalOperations.h>
|
||||||
#include <fsfw/timemanager/CCSDSTime.h>
|
#include <fsfw/timemanager/CCSDSTime.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -89,4 +90,43 @@ TEST_CASE("CCSDSTime Tests", "[TestCCSDSTime]") {
|
|||||||
REQUIRE(timeTo.second == 59);
|
REQUIRE(timeTo.second == 59);
|
||||||
REQUIRE(timeTo.usecond == Catch::Approx(123000));
|
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);
|
||||||
|
// 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);
|
||||||
|
// micro seconds precision is lost
|
||||||
|
timeval difference = timeAsTimeval - timeReturnAsTimeval;
|
||||||
|
CHECK(difference.tv_usec == 456);
|
||||||
|
CHECK(difference.tv_sec == 0);
|
||||||
|
}
|
||||||
}
|
}
|
92
tests/src/fsfw_tests/unit/version.cpp
Normal file
92
tests/src/fsfw_tests/unit/version.cpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
#include "fsfw/version.h"
|
||||||
|
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
#include "fsfw/serviceinterface.h"
|
||||||
|
#include "fsfw_tests/unit/CatchDefinitions.h"
|
||||||
|
|
||||||
|
TEST_CASE("Version API Tests", "[TestVersionAPI]") {
|
||||||
|
// Check that major version is non-zero
|
||||||
|
REQUIRE(fsfw::FSFW_VERSION.major > 0);
|
||||||
|
uint32_t fsfwMajor = fsfw::FSFW_VERSION.major;
|
||||||
|
REQUIRE(fsfw::Version(255, 0, 0) > fsfw::FSFW_VERSION);
|
||||||
|
REQUIRE(fsfw::Version(255, 0, 0) >= fsfw::FSFW_VERSION);
|
||||||
|
REQUIRE(fsfw::Version(0, 0, 0) < fsfw::FSFW_VERSION);
|
||||||
|
REQUIRE(fsfw::Version(0, 0, 0) <= fsfw::FSFW_VERSION);
|
||||||
|
fsfw::Version v1 = fsfw::Version(1, 1, 1);
|
||||||
|
fsfw::Version v2 = fsfw::Version(1, 1, 1);
|
||||||
|
REQUIRE(v1 == v2);
|
||||||
|
REQUIRE(not (v1 < v2));
|
||||||
|
REQUIRE(not (v1 > v2));
|
||||||
|
REQUIRE(v1 <= v2);
|
||||||
|
REQUIRE(v1 >= v2);
|
||||||
|
v1.revision -= 1;
|
||||||
|
REQUIRE(v1 != v2);
|
||||||
|
REQUIRE(not (v1 == v2));
|
||||||
|
REQUIRE(not (v1 > v2));
|
||||||
|
REQUIRE(not (v1 >= v2));
|
||||||
|
REQUIRE(v1 < v2);
|
||||||
|
REQUIRE(v1 <= v2);
|
||||||
|
v1.revision += 1;
|
||||||
|
v1.minor -= 1;
|
||||||
|
REQUIRE(v1 != v2);
|
||||||
|
REQUIRE(v1 < v2);
|
||||||
|
REQUIRE(v1 <= v2);
|
||||||
|
REQUIRE(not (v1 == v2));
|
||||||
|
REQUIRE(not (v1 > v2));
|
||||||
|
REQUIRE(not (v1 >= v2));
|
||||||
|
v1.minor += 1;
|
||||||
|
v1.major -= 1;
|
||||||
|
REQUIRE(v1 != v2);
|
||||||
|
REQUIRE(v1 < v2);
|
||||||
|
REQUIRE(v1 <= v2);
|
||||||
|
REQUIRE(not (v1 == v2));
|
||||||
|
REQUIRE(not (v1 > v2));
|
||||||
|
REQUIRE(not (v1 >= v2));
|
||||||
|
v1.major += 1;
|
||||||
|
REQUIRE(v1 == v2);
|
||||||
|
REQUIRE(v1 <= v2);
|
||||||
|
REQUIRE(v1 >= v2);
|
||||||
|
REQUIRE(not (v1 != v2));
|
||||||
|
REQUIRE(not (v1 > v2));
|
||||||
|
REQUIRE(not (v1 < v2));
|
||||||
|
v1.major += 1;
|
||||||
|
v1.minor -= 1;
|
||||||
|
REQUIRE(v1 != v2);
|
||||||
|
REQUIRE(v1 > v2);
|
||||||
|
REQUIRE(v1 >= v2);
|
||||||
|
REQUIRE(not (v1 == v2));
|
||||||
|
REQUIRE(not (v1 < v2));
|
||||||
|
REQUIRE(not (v1 <= v2));
|
||||||
|
v1.major -= 1;
|
||||||
|
v1.minor += 2;
|
||||||
|
v1.revision -= 1;
|
||||||
|
REQUIRE(v1 != v2);
|
||||||
|
REQUIRE(v1 > v2);
|
||||||
|
REQUIRE(v1 >= v2);
|
||||||
|
REQUIRE(not (v1 == v2));
|
||||||
|
REQUIRE(not (v1 < v2));
|
||||||
|
REQUIRE(not (v1 <= v2));
|
||||||
|
v1.minor -= 1;
|
||||||
|
v1.revision += 2;
|
||||||
|
REQUIRE(v1 != v2);
|
||||||
|
REQUIRE(v1 > v2);
|
||||||
|
REQUIRE(v1 >= v2);
|
||||||
|
REQUIRE(not (v1 == v2));
|
||||||
|
REQUIRE(not (v1 < v2));
|
||||||
|
REQUIRE(not (v1 <= v2));
|
||||||
|
v1.revision -= 1;
|
||||||
|
REQUIRE(v1 == v2);
|
||||||
|
REQUIRE(v1 <= v2);
|
||||||
|
REQUIRE(v1 >= v2);
|
||||||
|
REQUIRE(not (v1 != v2));
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::info << "v" << fsfw::FSFW_VERSION << std::endl;
|
||||||
|
#endif
|
||||||
|
char verString[10] = {};
|
||||||
|
fsfw::FSFW_VERSION.getVersion(verString, sizeof(verString));
|
||||||
|
#if FSFW_DISABLE_PRINTOUT == 0
|
||||||
|
printf("v%s\n",verString);
|
||||||
|
#endif
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user