Compare commits
1 Commits
mueller/up
...
docker_d3
Author | SHA1 | Date | |
---|---|---|---|
7de56f189b |
7
.run/fsfw-tests_coverage.run.xml
Normal file
7
.run/fsfw-tests_coverage.run.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="fsfw-tests_coverage" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="fsfw-tests" TARGET_NAME="fsfw-tests_coverage" CONFIG_NAME="Debug Unittest" RUN_TARGET_PROJECT_NAME="fsfw-tests" RUN_TARGET_NAME="fsfw-tests">
|
||||||
|
<method v="2">
|
||||||
|
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
7
.run/fsfw.run.xml
Normal file
7
.run/fsfw.run.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="fsfw" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="fsfw-tests" TARGET_NAME="fsfw" CONFIG_NAME="Debug Unittest" RUN_TARGET_PROJECT_NAME="fsfw-tests" RUN_TARGET_NAME="fsfw-tests">
|
||||||
|
<method v="2">
|
||||||
|
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
@ -19,6 +19,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- Bump C++ required version to C++17. Every project which uses the FSFW and every modern
|
- Bump C++ required version to C++17. Every project which uses the FSFW and every modern
|
||||||
compiler supports it
|
compiler supports it
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/622
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/622
|
||||||
|
- 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.
|
- New CMake option `FSFW_HAL_LINUX_ADD_LIBGPIOD` to specifically exclude `gpiod` code.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
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
|
||||||
@ -85,7 +91,6 @@ PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/636
|
|||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||||
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
||||||
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
|
|
||||||
|
|
||||||
### Time
|
### Time
|
||||||
|
|
||||||
@ -134,6 +139,7 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
|
|||||||
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
|
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
|
||||||
Easiest solution for now: Keep this option OFF by default.
|
Easiest solution for now: Keep this option OFF by default.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
|
||||||
|
- 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
|
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
||||||
inside `fsfw/version.h`
|
inside `fsfw/version.h`
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
||||||
|
@ -183,10 +183,7 @@ if(FSFW_BUILD_UNITTESTS)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message(
|
message(STATUS "${MSG_PREFIX} Finding and/or providing ETL library")
|
||||||
STATUS
|
|
||||||
"${MSG_PREFIX} Finding and/or providing etl library with version ${FSFW_ETL_LIB_MAJOR_VERSION}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check whether the user has already installed ETL first
|
# Check whether the user has already installed ETL first
|
||||||
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
||||||
@ -194,7 +191,7 @@ find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
|||||||
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
||||||
message(
|
message(
|
||||||
STATUS
|
STATUS
|
||||||
"${MSG_PREFIX} No ETL installation was found with find_package. Installing and providing "
|
"No ETL installation was found with find_package. Installing and providing "
|
||||||
"etl with FindPackage")
|
"etl with FindPackage")
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
|
@ -12,3 +12,9 @@ RUN git clone https://github.com/catchorg/Catch2.git && \
|
|||||||
git checkout v3.0.0-preview5 && \
|
git checkout v3.0.0-preview5 && \
|
||||||
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
|
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
|
||||||
cmake --build build/ --target install
|
cmake --build build/ --target install
|
||||||
|
|
||||||
|
RUN git clone https://github.com/ETLCPP/etl.git && \
|
||||||
|
cd etl && \
|
||||||
|
git checkout 20.28.0 && \
|
||||||
|
cmake -B build . && \
|
||||||
|
cmake --install build/
|
||||||
|
@ -46,9 +46,9 @@ class GpioIF : public HasReturnvaluesIF {
|
|||||||
* an ouput or input gpio.
|
* an ouput or input gpio.
|
||||||
*
|
*
|
||||||
* @param gpioId A unique number which specifies the GPIO to read.
|
* @param gpioId A unique number which specifies the GPIO to read.
|
||||||
* @param gpioState State of GPIO will be written to this reference
|
* @param gpioState State of GPIO will be written to this pointer.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t readGpio(gpioId_t gpioId, gpio::Levels& gpioState) = 0;
|
virtual ReturnValue_t readGpio(gpioId_t gpioId, int* gpioState) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* COMMON_GPIO_GPIOIF_H_ */
|
#endif /* COMMON_GPIO_GPIOIF_H_ */
|
||||||
|
@ -9,7 +9,7 @@ using gpioId_t = uint16_t;
|
|||||||
|
|
||||||
namespace gpio {
|
namespace gpio {
|
||||||
|
|
||||||
enum class Levels : int { LOW = 0, HIGH = 1, FAILED = -1, NONE = 99 };
|
enum class Levels : int { LOW = 0, HIGH = 1, NONE = 99 };
|
||||||
|
|
||||||
enum class Direction : int { IN = 0, OUT = 1 };
|
enum class Direction : int { IN = 0, OUT = 1 };
|
||||||
|
|
||||||
|
@ -252,7 +252,6 @@ ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool(localpool::DataPool &l
|
|||||||
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Y, new PoolEntry<float>({0.0}));
|
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Y, new PoolEntry<float>({0.0}));
|
||||||
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Z, new PoolEntry<float>({0.0}));
|
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Z, new PoolEntry<float>({0.0}));
|
||||||
localDataPoolMap.emplace(L3GD20H::TEMPERATURE, new PoolEntry<float>({0.0}));
|
localDataPoolMap.emplace(L3GD20H::TEMPERATURE, new PoolEntry<float>({0.0}));
|
||||||
poolManager.subscribeForPeriodicPacket(dataset.getSid(), false, 10.0, false);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,16 +375,13 @@ float MgmLIS3MDLHandler::getSensitivityFactor(MGMLIS3MDL::Sensitivies sens) {
|
|||||||
|
|
||||||
ReturnValue_t MgmLIS3MDLHandler::enableTemperatureSensor(const uint8_t *commandData,
|
ReturnValue_t MgmLIS3MDLHandler::enableTemperatureSensor(const uint8_t *commandData,
|
||||||
size_t commandDataLen) {
|
size_t commandDataLen) {
|
||||||
if (commandData == nullptr) {
|
|
||||||
return INVALID_COMMAND_PARAMETER;
|
|
||||||
}
|
|
||||||
triggerEvent(CHANGE_OF_SETUP_PARAMETER);
|
triggerEvent(CHANGE_OF_SETUP_PARAMETER);
|
||||||
uint32_t size = 2;
|
uint32_t size = 2;
|
||||||
commandBuffer[0] = writeCommand(MGMLIS3MDL::CTRL_REG1);
|
commandBuffer[0] = writeCommand(MGMLIS3MDL::CTRL_REG1);
|
||||||
if (commandDataLen > 1) {
|
if (commandDataLen > 1) {
|
||||||
return INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS;
|
return INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS;
|
||||||
}
|
}
|
||||||
switch (commandData[0]) {
|
switch (*commandData) {
|
||||||
case (MGMLIS3MDL::ON): {
|
case (MGMLIS3MDL::ON): {
|
||||||
commandBuffer[1] = registers[0] | (1 << 7);
|
commandBuffer[1] = registers[0] | (1 << 7);
|
||||||
break;
|
break;
|
||||||
@ -475,7 +472,6 @@ ReturnValue_t MgmLIS3MDLHandler::initializeLocalDataPool(localpool::DataPool &lo
|
|||||||
localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTH_Y, new PoolEntry<float>({0.0}));
|
localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTH_Y, new PoolEntry<float>({0.0}));
|
||||||
localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTH_Z, new PoolEntry<float>({0.0}));
|
localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTH_Z, new PoolEntry<float>({0.0}));
|
||||||
localDataPoolMap.emplace(MGMLIS3MDL::TEMPERATURE_CELCIUS, new PoolEntry<float>({0.0}));
|
localDataPoolMap.emplace(MGMLIS3MDL::TEMPERATURE_CELCIUS, new PoolEntry<float>({0.0}));
|
||||||
poolManager.subscribeForPeriodicPacket(dataset.getSid(), false, 10.0, false);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +312,6 @@ ReturnValue_t MgmRM3100Handler::initializeLocalDataPool(localpool::DataPool &loc
|
|||||||
localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_X, new PoolEntry<float>({0.0}));
|
localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_X, new PoolEntry<float>({0.0}));
|
||||||
localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_Y, new PoolEntry<float>({0.0}));
|
localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_Y, new PoolEntry<float>({0.0}));
|
||||||
localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_Z, new PoolEntry<float>({0.0}));
|
localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_Z, new PoolEntry<float>({0.0}));
|
||||||
poolManager.subscribeForPeriodicPacket(primaryDataset.getSid(), false, 10.0, false);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,8 +32,6 @@ ReturnValue_t CommandExecutor::execute() {
|
|||||||
} else if (state == States::PENDING) {
|
} else if (state == States::PENDING) {
|
||||||
return COMMAND_PENDING;
|
return COMMAND_PENDING;
|
||||||
}
|
}
|
||||||
// Reset data in read vector
|
|
||||||
std::memset(readVec.data(), 0, readVec.size());
|
|
||||||
currentCmdFile = popen(currentCmd.c_str(), "r");
|
currentCmdFile = popen(currentCmd.c_str(), "r");
|
||||||
if (currentCmdFile == nullptr) {
|
if (currentCmdFile == nullptr) {
|
||||||
lastError = errno;
|
lastError = errno;
|
||||||
@ -207,5 +205,3 @@ ReturnValue_t CommandExecutor::executeBlocking() {
|
|||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<char>& CommandExecutor::getReadVector() const { return readVec; }
|
|
||||||
|
@ -109,8 +109,6 @@ class CommandExecutor {
|
|||||||
*/
|
*/
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
const std::vector<char>& getReadVector() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string currentCmd;
|
std::string currentCmd;
|
||||||
bool blocking = true;
|
bool blocking = true;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "fsfw/FSFW.h"
|
#include "fsfw/FSFW.h"
|
||||||
#include "fsfw/serviceinterface.h"
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
UnixFileGuard::UnixFileGuard(const std::string& device, int* fileDescriptor, int flags,
|
UnixFileGuard::UnixFileGuard(std::string device, int* fileDescriptor, int flags,
|
||||||
std::string diagnosticPrefix)
|
std::string diagnosticPrefix)
|
||||||
: fileDescriptor(fileDescriptor) {
|
: fileDescriptor(fileDescriptor) {
|
||||||
if (fileDescriptor == nullptr) {
|
if (fileDescriptor == nullptr) {
|
||||||
|
@ -15,7 +15,7 @@ class UnixFileGuard {
|
|||||||
|
|
||||||
static constexpr ReturnValue_t OPEN_FILE_FAILED = 1;
|
static constexpr ReturnValue_t OPEN_FILE_FAILED = 1;
|
||||||
|
|
||||||
UnixFileGuard(const std::string& device, int* fileDescriptor, int flags,
|
UnixFileGuard(std::string device, int* fileDescriptor, int flags,
|
||||||
std::string diagnosticPrefix = "");
|
std::string diagnosticPrefix = "");
|
||||||
|
|
||||||
virtual ~UnixFileGuard();
|
virtual ~UnixFileGuard();
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
#ifndef FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_
|
|
||||||
#define FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_
|
|
||||||
|
|
||||||
#include "fsfw_hal/common/gpio/GpioIF.h"
|
|
||||||
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Additional abstraction layer for handling GPIOs.
|
|
||||||
*
|
|
||||||
* @author J. Meier
|
|
||||||
*/
|
|
||||||
class Gpio {
|
|
||||||
public:
|
|
||||||
Gpio(gpioId_t gpioId, GpioIF* gpioIF) : gpioId(gpioId), gpioIF(gpioIF) {
|
|
||||||
if (gpioIF == nullptr) {
|
|
||||||
sif::error << "Gpio::Gpio: Invalid GpioIF" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ReturnValue_t pullHigh() { return gpioIF->pullHigh(gpioId); }
|
|
||||||
ReturnValue_t pullLow() { return gpioIF->pullLow(gpioId); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
gpioId_t gpioId = gpio::NO_GPIO;
|
|
||||||
GpioIF* gpioIF = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_ */
|
|
@ -294,7 +294,7 @@ ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, GpiodRegularBase& regul
|
|||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, gpio::Levels& gpioState) {
|
ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, int* gpioState) {
|
||||||
gpioMapIter = gpioMap.find(gpioId);
|
gpioMapIter = gpioMap.find(gpioId);
|
||||||
if (gpioMapIter == gpioMap.end()) {
|
if (gpioMapIter == gpioMap.end()) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
@ -313,10 +313,7 @@ ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, gpio::Levels& gpioState)
|
|||||||
if (regularGpio == nullptr) {
|
if (regularGpio == nullptr) {
|
||||||
return GPIO_TYPE_FAILURE;
|
return GPIO_TYPE_FAILURE;
|
||||||
}
|
}
|
||||||
gpioState = static_cast<gpio::Levels>(gpiod_line_get_value(regularGpio->lineHandle));
|
*gpioState = gpiod_line_get_value(regularGpio->lineHandle);
|
||||||
if (gpioState == gpio::Levels::FAILED) {
|
|
||||||
return GPIO_GET_VALUE_FAILED;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
|
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
|
||||||
if (gpioCallback->callback == nullptr) {
|
if (gpioCallback->callback == nullptr) {
|
||||||
|
@ -31,16 +31,14 @@ class LinuxLibgpioIF : public GpioIF, public SystemObject {
|
|||||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 5);
|
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 5);
|
||||||
static constexpr ReturnValue_t GPIO_INIT_FAILED =
|
static constexpr ReturnValue_t GPIO_INIT_FAILED =
|
||||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 6);
|
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 6);
|
||||||
// Will be returned if getting the line value failed. Error type will be set to errno in this case
|
|
||||||
static constexpr ReturnValue_t GPIO_GET_VALUE_FAILED =
|
|
||||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 7);
|
|
||||||
LinuxLibgpioIF(object_id_t objectId);
|
LinuxLibgpioIF(object_id_t objectId);
|
||||||
virtual ~LinuxLibgpioIF();
|
virtual ~LinuxLibgpioIF();
|
||||||
|
|
||||||
ReturnValue_t addGpios(GpioCookie* gpioCookie) override;
|
ReturnValue_t addGpios(GpioCookie* gpioCookie) override;
|
||||||
ReturnValue_t pullHigh(gpioId_t gpioId) override;
|
ReturnValue_t pullHigh(gpioId_t gpioId) override;
|
||||||
ReturnValue_t pullLow(gpioId_t gpioId) override;
|
ReturnValue_t pullLow(gpioId_t gpioId) override;
|
||||||
ReturnValue_t readGpio(gpioId_t gpioId, gpio::Levels& gpioState) override;
|
ReturnValue_t readGpio(gpioId_t gpioId, int* gpioState) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const size_t MAX_CHIPNAME_LENGTH = 11;
|
static const size_t MAX_CHIPNAME_LENGTH = 11;
|
||||||
|
@ -170,20 +170,18 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
|
|||||||
|
|
||||||
int readLen = read(fd, replyBuffer, requestLen);
|
int readLen = read(fd, replyBuffer, requestLen);
|
||||||
if (readLen != static_cast<int>(requestLen)) {
|
if (readLen != static_cast<int>(requestLen)) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1 and FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
sif::error << "I2cComIF::requestReceiveMessage: Reading from I2C "
|
||||||
if (readLen < 0) {
|
<< "device failed with error code " << errno << ". Description"
|
||||||
sif::warning << "I2cComIF::requestReceiveMessage: Reading from I2C "
|
<< " of error: " << strerror(errno) << std::endl;
|
||||||
<< "device failed with error code " << errno << " | " << strerror(errno)
|
sif::error << "I2cComIF::requestReceiveMessage: Read only " << readLen << " from " << requestLen
|
||||||
<< std::endl;
|
<< " bytes" << std::endl;
|
||||||
} else {
|
|
||||||
sif::warning << "I2cComIF::requestReceiveMessage: Read only " << readLen << " from "
|
|
||||||
<< requestLen << " bytes" << std::endl;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
i2cDeviceMapIter->second.replyLen = 0;
|
i2cDeviceMapIter->second.replyLen = 0;
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::debug << "I2cComIF::requestReceiveMessage: Read " << readLen << " of " << requestLen
|
||||||
|
<< " bytes" << std::endl;
|
||||||
|
#endif
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "fsfw/ipc/MutexIF.h"
|
|
||||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
|
||||||
#include "fsfw_hal/common/gpio/GpioIF.h"
|
|
||||||
|
|
||||||
class ManualCsLockWrapper : public HasReturnvaluesIF {
|
|
||||||
public:
|
|
||||||
ManualCsLockWrapper(MutexIF* lock, GpioIF* gpioIF, SpiCookie* cookie,
|
|
||||||
MutexIF::TimeoutType type = MutexIF::TimeoutType::BLOCKING,
|
|
||||||
uint32_t timeoutMs = 0)
|
|
||||||
: lock(lock), gpioIF(gpioIF), cookie(cookie), type(type), timeoutMs(timeoutMs) {
|
|
||||||
if (cookie == nullptr) {
|
|
||||||
// TODO: Error? Or maybe throw exception..
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cookie->setCsLockManual(true);
|
|
||||||
lockResult = lock->lockMutex(type, timeoutMs);
|
|
||||||
if (lockResult != RETURN_OK) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gpioResult = gpioIF->pullLow(cookie->getChipSelectPin());
|
|
||||||
}
|
|
||||||
|
|
||||||
~ManualCsLockWrapper() {
|
|
||||||
if (gpioResult == RETURN_OK) {
|
|
||||||
gpioIF->pullHigh(cookie->getChipSelectPin());
|
|
||||||
}
|
|
||||||
cookie->setCsLockManual(false);
|
|
||||||
if (lockResult == RETURN_OK) {
|
|
||||||
lock->unlockMutex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ReturnValue_t lockResult;
|
|
||||||
ReturnValue_t gpioResult;
|
|
||||||
|
|
||||||
private:
|
|
||||||
MutexIF* lock;
|
|
||||||
GpioIF* gpioIF;
|
|
||||||
SpiCookie* cookie;
|
|
||||||
MutexIF::TimeoutType type;
|
|
||||||
uint32_t timeoutMs = 0;
|
|
||||||
};
|
|
@ -15,8 +15,8 @@
|
|||||||
#include "fsfw_hal/linux/spi/SpiCookie.h"
|
#include "fsfw_hal/linux/spi/SpiCookie.h"
|
||||||
#include "fsfw_hal/linux/utility.h"
|
#include "fsfw_hal/linux/utility.h"
|
||||||
|
|
||||||
SpiComIF::SpiComIF(object_id_t objectId, std::string devname, GpioIF* gpioComIF)
|
SpiComIF::SpiComIF(object_id_t objectId, GpioIF* gpioComIF)
|
||||||
: SystemObject(objectId), gpioComIF(gpioComIF), dev(std::move(devname)) {
|
: SystemObject(objectId), gpioComIF(gpioComIF) {
|
||||||
if (gpioComIF == nullptr) {
|
if (gpioComIF == nullptr) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
@ -27,7 +27,7 @@ SpiComIF::SpiComIF(object_id_t objectId, std::string devname, GpioIF* gpioComIF)
|
|||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
}
|
}
|
||||||
|
|
||||||
csMutex = MutexFactory::instance()->createMutex();
|
spiMutex = MutexFactory::instance()->createMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) {
|
ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) {
|
||||||
@ -85,7 +85,8 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) {
|
|||||||
spiCookie->getSpiParameters(spiMode, spiSpeed, ¶ms);
|
spiCookie->getSpiParameters(spiMode, spiSpeed, ¶ms);
|
||||||
|
|
||||||
int fileDescriptor = 0;
|
int fileDescriptor = 0;
|
||||||
UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::initializeInterface");
|
UnixFileGuard fileHelper(spiCookie->getSpiDevice(), &fileDescriptor, O_RDWR,
|
||||||
|
"SpiComIF::initializeInterface");
|
||||||
if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return fileHelper.getOpenResult();
|
return fileHelper.getOpenResult();
|
||||||
}
|
}
|
||||||
@ -181,7 +182,8 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
int retval = 0;
|
int retval = 0;
|
||||||
/* Prepare transfer */
|
/* Prepare transfer */
|
||||||
int fileDescriptor = 0;
|
int fileDescriptor = 0;
|
||||||
UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
|
std::string device = spiCookie->getSpiDevice();
|
||||||
|
UnixFileGuard fileHelper(device, &fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
|
||||||
if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return OPENING_FILE_FAILED;
|
return OPENING_FILE_FAILED;
|
||||||
}
|
}
|
||||||
@ -194,27 +196,20 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
|
|
||||||
bool fullDuplex = spiCookie->isFullDuplex();
|
bool fullDuplex = spiCookie->isFullDuplex();
|
||||||
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
||||||
bool csLockManual = spiCookie->getCsLockManual();
|
|
||||||
|
|
||||||
MutexIF::TimeoutType csType;
|
/* Pull SPI CS low. For now, no support for active high given */
|
||||||
dur_millis_t csTimeout = 0;
|
if (gpioId != gpio::NO_GPIO) {
|
||||||
// Pull SPI CS low. For now, no support for active high given
|
result = spiMutex->lockMutex(timeoutType, timeoutMs);
|
||||||
if (gpioId != gpio::NO_GPIO and not csLockManual) {
|
|
||||||
spiCookie->getMutexParams(csType, csTimeout);
|
|
||||||
result = csMutex->lockMutex(csType, csTimeout);
|
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "SpiComIF::sendMessage: Failed to lock mutex with code "
|
sif::error << "SpiComIF::sendMessage: Failed to lock mutex" << std::endl;
|
||||||
<< "0x" << std::hex << std::setfill('0') << std::setw(4) << result << std::dec
|
|
||||||
<< std::endl;
|
|
||||||
#else
|
#else
|
||||||
sif::printError("SpiComIF::sendMessage: Failed to lock mutex with code %d\n", result);
|
sif::printError("SpiComIF::sendMessage: Failed to lock mutex\n");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
updateLinePolarity(fileDescriptor);
|
|
||||||
result = gpioComIF->pullLow(gpioId);
|
result = gpioComIF->pullLow(gpioId);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
@ -226,8 +221,6 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
updateLinePolarity(fileDescriptor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Execute transfer */
|
/* Execute transfer */
|
||||||
@ -255,9 +248,9 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gpioId != gpio::NO_GPIO and not csLockManual) {
|
if (gpioId != gpio::NO_GPIO) {
|
||||||
gpioComIF->pullHigh(gpioId);
|
gpioComIF->pullHigh(gpioId);
|
||||||
result = csMutex->unlockMutex();
|
result = spiMutex->unlockMutex();
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "SpiComIF::sendMessage: Failed to unlock mutex" << std::endl;
|
sif::error << "SpiComIF::sendMessage: Failed to unlock mutex" << std::endl;
|
||||||
@ -285,8 +278,9 @@ ReturnValue_t SpiComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
|
|||||||
|
|
||||||
ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
|
ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||||
|
std::string device = spiCookie->getSpiDevice();
|
||||||
int fileDescriptor = 0;
|
int fileDescriptor = 0;
|
||||||
UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage");
|
UnixFileGuard fileHelper(device, &fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage");
|
||||||
if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return OPENING_FILE_FAILED;
|
return OPENING_FILE_FAILED;
|
||||||
}
|
}
|
||||||
@ -298,22 +292,12 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool csLockManual = spiCookie->getCsLockManual();
|
|
||||||
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
||||||
MutexIF::TimeoutType csType;
|
if (gpioId != gpio::NO_GPIO) {
|
||||||
dur_millis_t csTimeout = 0;
|
result = spiMutex->lockMutex(timeoutType, timeoutMs);
|
||||||
if (gpioId != gpio::NO_GPIO and not csLockManual) {
|
|
||||||
spiCookie->getMutexParams(csType, csTimeout);
|
|
||||||
result = csMutex->lockMutex(csType, csTimeout);
|
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "SpiComIF::sendMessage: Failed to lock mutex with code "
|
sif::error << "SpiComIF::getSendSuccess: Failed to lock mutex" << std::endl;
|
||||||
<< "0x" << std::hex << std::setfill('0') << std::setw(4) << result << std::dec
|
|
||||||
<< std::endl;
|
|
||||||
#else
|
|
||||||
sif::printError("SpiComIF::sendMessage: Failed to lock mutex with code %d\n", result);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -331,9 +315,9 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
|
|||||||
result = HALF_DUPLEX_TRANSFER_FAILED;
|
result = HALF_DUPLEX_TRANSFER_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gpioId != gpio::NO_GPIO and not csLockManual) {
|
if (gpioId != gpio::NO_GPIO) {
|
||||||
gpioComIF->pullHigh(gpioId);
|
gpioComIF->pullHigh(gpioId);
|
||||||
result = csMutex->unlockMutex();
|
result = spiMutex->unlockMutex();
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "SpiComIF::getSendSuccess: Failed to unlock mutex" << std::endl;
|
sif::error << "SpiComIF::getSendSuccess: Failed to unlock mutex" << std::endl;
|
||||||
@ -362,7 +346,15 @@ ReturnValue_t SpiComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MutexIF* SpiComIF::getCsMutex() { return csMutex; }
|
MutexIF* SpiComIF::getMutex(MutexIF::TimeoutType* timeoutType, uint32_t* timeoutMs) {
|
||||||
|
if (timeoutType != nullptr) {
|
||||||
|
*timeoutType = this->timeoutType;
|
||||||
|
}
|
||||||
|
if (timeoutMs != nullptr) {
|
||||||
|
*timeoutMs = this->timeoutMs;
|
||||||
|
}
|
||||||
|
return spiMutex;
|
||||||
|
}
|
||||||
|
|
||||||
void SpiComIF::performSpiWiretapping(SpiCookie* spiCookie) {
|
void SpiComIF::performSpiWiretapping(SpiCookie* spiCookie) {
|
||||||
if (spiCookie == nullptr) {
|
if (spiCookie == nullptr) {
|
||||||
@ -409,27 +401,11 @@ 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
|
||||||
void SpiComIF::getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const {
|
// switch the state after the chip select is pulled low
|
||||||
uint8_t tmpMode = 0;
|
|
||||||
int retval = ioctl(spiFd, SPI_IOC_RD_MODE, &tmpMode);
|
|
||||||
if (retval != 0) {
|
|
||||||
utility::handleIoctlError("SpiComIF::getSpiSpeedAndMode: Reading SPI mode failed");
|
|
||||||
}
|
|
||||||
mode = static_cast<spi::SpiModes>(tmpMode);
|
|
||||||
|
|
||||||
retval = ioctl(spiFd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
|
|
||||||
if (retval != 0) {
|
|
||||||
utility::handleIoctlError("SpiComIF::getSpiSpeedAndMode: Getting SPI speed failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& SpiComIF::getSpiDev() const { return dev; }
|
|
||||||
|
|
||||||
void SpiComIF::updateLinePolarity(int spiFd) {
|
|
||||||
clockUpdateTransfer.len = 0;
|
clockUpdateTransfer.len = 0;
|
||||||
int retval = ioctl(spiFd, SPI_IOC_MESSAGE(1), &clockUpdateTransfer);
|
retval = ioctl(spiFd, SPI_IOC_MESSAGE(1), &clockUpdateTransfer);
|
||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Updating SPI default clock failed");
|
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Updating SPI default clock failed");
|
||||||
}
|
}
|
||||||
|
@ -22,17 +22,17 @@ class SpiCookie;
|
|||||||
*/
|
*/
|
||||||
class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t CLASS_ID = CLASS_ID::HAL_SPI;
|
static constexpr uint8_t spiRetvalId = CLASS_ID::HAL_SPI;
|
||||||
static constexpr ReturnValue_t OPENING_FILE_FAILED =
|
static constexpr ReturnValue_t OPENING_FILE_FAILED =
|
||||||
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 0);
|
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 0);
|
||||||
/* Full duplex (ioctl) transfer failure */
|
/* Full duplex (ioctl) transfer failure */
|
||||||
static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED =
|
static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED =
|
||||||
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 1);
|
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 1);
|
||||||
/* Half duplex (read/write) transfer failure */
|
/* Half duplex (read/write) transfer failure */
|
||||||
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED =
|
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED =
|
||||||
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 2);
|
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 2);
|
||||||
|
|
||||||
SpiComIF(object_id_t objectId, std::string devname, GpioIF* gpioComIF);
|
SpiComIF(object_id_t objectId, GpioIF* gpioComIF);
|
||||||
|
|
||||||
ReturnValue_t initializeInterface(CookieIF* cookie) override;
|
ReturnValue_t initializeInterface(CookieIF* cookie) override;
|
||||||
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
|
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
|
||||||
@ -44,8 +44,7 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
|||||||
* @brief This function returns the mutex which can be used to protect the spi bus when
|
* @brief This function returns the mutex which can be used to protect the spi bus when
|
||||||
* the chip select must be driven from outside of the com if.
|
* the chip select must be driven from outside of the com if.
|
||||||
*/
|
*/
|
||||||
MutexIF* getCsMutex();
|
MutexIF* getMutex(MutexIF::TimeoutType* timeoutType = nullptr, uint32_t* timeoutMs = nullptr);
|
||||||
void setMutexParams(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a regular send operation using Linux iotcl. This is public so it can be used
|
* Perform a regular send operation using Linux iotcl. This is public so it can be used
|
||||||
@ -60,20 +59,6 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
|||||||
|
|
||||||
GpioIF* getGpioInterface();
|
GpioIF* getGpioInterface();
|
||||||
void setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed);
|
void setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed);
|
||||||
void getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* It is recommended to call this function after #setSpiSpeedAndMode and after locking the
|
|
||||||
* CS mutex if the SPI bus has multiple SPI devices with different speed and SPI modes attached.
|
|
||||||
* @param spiFd
|
|
||||||
*/
|
|
||||||
void updateLinePolarity(int spiFd);
|
|
||||||
|
|
||||||
const std::string& getSpiDev() const;
|
|
||||||
void performSpiWiretapping(SpiCookie* spiCookie);
|
void performSpiWiretapping(SpiCookie* spiCookie);
|
||||||
|
|
||||||
ReturnValue_t getReadBuffer(address_t spiAddress, uint8_t** buffer);
|
ReturnValue_t getReadBuffer(address_t spiAddress, uint8_t** buffer);
|
||||||
@ -85,14 +70,10 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
|||||||
};
|
};
|
||||||
|
|
||||||
GpioIF* gpioComIF = nullptr;
|
GpioIF* gpioComIF = nullptr;
|
||||||
std::string dev = "";
|
|
||||||
/**
|
MutexIF* spiMutex = nullptr;
|
||||||
* Protects the chip select operations. Lock when GPIO is pulled low, unlock after it was
|
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||||
* pulled high
|
uint32_t timeoutMs = 20;
|
||||||
*/
|
|
||||||
MutexIF* csMutex = nullptr;
|
|
||||||
// MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
|
||||||
// uint32_t timeoutMs = DEFAULT_MUTEX_TIMEOUT;
|
|
||||||
spi_ioc_transfer clockUpdateTransfer = {};
|
spi_ioc_transfer clockUpdateTransfer = {};
|
||||||
|
|
||||||
using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>;
|
using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>;
|
||||||
|
@ -1,25 +1,26 @@
|
|||||||
#include "SpiCookie.h"
|
#include "SpiCookie.h"
|
||||||
|
|
||||||
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, const size_t maxSize,
|
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
|
||||||
|
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed)
|
||||||
|
: SpiCookie(spi::SpiComIfModes::REGULAR, spiAddress, chipSelect, spiDev, maxSize, spiMode,
|
||||||
|
spiSpeed, nullptr, nullptr) {}
|
||||||
|
|
||||||
|
SpiCookie::SpiCookie(address_t spiAddress, std::string spiDev, const size_t maxSize,
|
||||||
spi::SpiModes spiMode, uint32_t spiSpeed)
|
spi::SpiModes spiMode, uint32_t spiSpeed)
|
||||||
: SpiCookie(spi::SpiComIfModes::REGULAR, spiAddress, chipSelect, maxSize, spiMode, spiSpeed,
|
: SpiCookie(spiAddress, gpio::NO_GPIO, spiDev, maxSize, spiMode, spiSpeed) {}
|
||||||
nullptr, nullptr) {}
|
|
||||||
|
|
||||||
SpiCookie::SpiCookie(address_t spiAddress, const size_t maxSize, spi::SpiModes spiMode,
|
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
|
||||||
uint32_t spiSpeed)
|
|
||||||
: SpiCookie(spiAddress, gpio::NO_GPIO, maxSize, spiMode, spiSpeed) {}
|
|
||||||
|
|
||||||
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, const size_t maxSize,
|
|
||||||
spi::SpiModes spiMode, uint32_t spiSpeed,
|
|
||||||
spi::send_callback_function_t callback, void* args)
|
|
||||||
: SpiCookie(spi::SpiComIfModes::CALLBACK, spiAddress, chipSelect, maxSize, spiMode, spiSpeed,
|
|
||||||
callback, args) {}
|
|
||||||
|
|
||||||
SpiCookie::SpiCookie(spi::SpiComIfModes comIfMode, address_t spiAddress, gpioId_t chipSelect,
|
|
||||||
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed,
|
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed,
|
||||||
spi::send_callback_function_t callback, void* args)
|
spi::send_callback_function_t callback, void* args)
|
||||||
|
: SpiCookie(spi::SpiComIfModes::CALLBACK, spiAddress, chipSelect, spiDev, maxSize, spiMode,
|
||||||
|
spiSpeed, callback, args) {}
|
||||||
|
|
||||||
|
SpiCookie::SpiCookie(spi::SpiComIfModes comIfMode, address_t spiAddress, gpioId_t chipSelect,
|
||||||
|
std::string spiDev, const size_t maxSize, spi::SpiModes spiMode,
|
||||||
|
uint32_t spiSpeed, spi::send_callback_function_t callback, void* args)
|
||||||
: spiAddress(spiAddress),
|
: spiAddress(spiAddress),
|
||||||
chipSelectPin(chipSelect),
|
chipSelectPin(chipSelect),
|
||||||
|
spiDevice(spiDev),
|
||||||
comIfMode(comIfMode),
|
comIfMode(comIfMode),
|
||||||
maxSize(maxSize),
|
maxSize(maxSize),
|
||||||
spiMode(spiMode),
|
spiMode(spiMode),
|
||||||
@ -49,6 +50,8 @@ size_t SpiCookie::getMaxBufferSize() const { return maxSize; }
|
|||||||
|
|
||||||
address_t SpiCookie::getSpiAddress() const { return spiAddress; }
|
address_t SpiCookie::getSpiAddress() const { return spiAddress; }
|
||||||
|
|
||||||
|
std::string SpiCookie::getSpiDevice() const { return spiDevice; }
|
||||||
|
|
||||||
void SpiCookie::setThreeWireSpi(bool enable) { uncommonParameters.threeWireSpi = enable; }
|
void SpiCookie::setThreeWireSpi(bool enable) { uncommonParameters.threeWireSpi = enable; }
|
||||||
|
|
||||||
void SpiCookie::setLsbFirst(bool enable) { uncommonParameters.lsbFirst = enable; }
|
void SpiCookie::setLsbFirst(bool enable) { uncommonParameters.lsbFirst = enable; }
|
||||||
@ -104,17 +107,3 @@ void SpiCookie::getCallback(spi::send_callback_function_t* callback, void** args
|
|||||||
*callback = this->sendCallback;
|
*callback = this->sendCallback;
|
||||||
*args = this->callbackArgs;
|
*args = this->callbackArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpiCookie::setCsLockManual(bool enable) { manualCsLock = enable; }
|
|
||||||
|
|
||||||
bool SpiCookie::getCsLockManual() const { return manualCsLock; }
|
|
||||||
|
|
||||||
void SpiCookie::getMutexParams(MutexIF::TimeoutType& csTimeoutType, dur_millis_t& csTimeout) const {
|
|
||||||
csTimeoutType = this->csTimeoutType;
|
|
||||||
csTimeout = this->csTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpiCookie::setMutexParams(MutexIF::TimeoutType csTimeoutType, dur_millis_t csTimeout) {
|
|
||||||
this->csTimeoutType = csTimeoutType;
|
|
||||||
this->csTimeout = csTimeout;
|
|
||||||
}
|
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
#define LINUX_SPI_SPICOOKIE_H_
|
#define LINUX_SPI_SPICOOKIE_H_
|
||||||
|
|
||||||
#include <fsfw/devicehandlers/CookieIF.h>
|
#include <fsfw/devicehandlers/CookieIF.h>
|
||||||
#include <fsfw/ipc/MutexIF.h>
|
|
||||||
#include <fsfw/timemanager/clockDefinitions.h>
|
|
||||||
#include <linux/spi/spidev.h>
|
#include <linux/spi/spidev.h>
|
||||||
|
|
||||||
#include "../../common/gpio/gpioDefinitions.h"
|
#include "../../common/gpio/gpioDefinitions.h"
|
||||||
@ -22,8 +20,6 @@
|
|||||||
*/
|
*/
|
||||||
class SpiCookie : public CookieIF {
|
class SpiCookie : public CookieIF {
|
||||||
public:
|
public:
|
||||||
static constexpr dur_millis_t DEFAULT_MUTEX_TIMEOUT = 20;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each SPI device will have a corresponding cookie. The cookie is used by the communication
|
* Each SPI device will have a corresponding cookie. The cookie is used by the communication
|
||||||
* interface and contains device specific information like the largest expected size to be
|
* interface and contains device specific information like the largest expected size to be
|
||||||
@ -33,22 +29,23 @@ class SpiCookie : public CookieIF {
|
|||||||
* @param spiDev
|
* @param spiDev
|
||||||
* @param maxSize
|
* @param maxSize
|
||||||
*/
|
*/
|
||||||
SpiCookie(address_t spiAddress, gpioId_t chipSelect, const size_t maxSize, spi::SpiModes spiMode,
|
SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev, const size_t maxSize,
|
||||||
uint32_t spiSpeed);
|
spi::SpiModes spiMode, uint32_t spiSpeed);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like constructor above, but without a dedicated GPIO CS. Can be used for hardware
|
* Like constructor above, but without a dedicated GPIO CS. Can be used for hardware
|
||||||
* slave select or if CS logic is performed with decoders.
|
* slave select or if CS logic is performed with decoders.
|
||||||
*/
|
*/
|
||||||
SpiCookie(address_t spiAddress, const size_t maxReplySize, spi::SpiModes spiMode,
|
SpiCookie(address_t spiAddress, std::string spiDev, const size_t maxReplySize,
|
||||||
uint32_t spiSpeed);
|
spi::SpiModes spiMode, uint32_t spiSpeed);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use the callback mode of the SPI communication interface. The user can pass the callback
|
* Use the callback mode of the SPI communication interface. The user can pass the callback
|
||||||
* function here or by using the setter function #setCallbackMode
|
* function here or by using the setter function #setCallbackMode
|
||||||
*/
|
*/
|
||||||
SpiCookie(address_t spiAddress, gpioId_t chipSelect, const size_t maxSize, spi::SpiModes spiMode,
|
SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev, const size_t maxSize,
|
||||||
uint32_t spiSpeed, spi::send_callback_function_t callback, void* args);
|
spi::SpiModes spiMode, uint32_t spiSpeed, spi::send_callback_function_t callback,
|
||||||
|
void* args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the callback function
|
* Get the callback function
|
||||||
@ -58,6 +55,7 @@ class SpiCookie : public CookieIF {
|
|||||||
void getCallback(spi::send_callback_function_t* callback, void** args);
|
void getCallback(spi::send_callback_function_t* callback, void** args);
|
||||||
|
|
||||||
address_t getSpiAddress() const;
|
address_t getSpiAddress() const;
|
||||||
|
std::string getSpiDevice() const;
|
||||||
gpioId_t getChipSelectPin() const;
|
gpioId_t getChipSelectPin() const;
|
||||||
size_t getMaxBufferSize() const;
|
size_t getMaxBufferSize() const;
|
||||||
|
|
||||||
@ -141,42 +139,9 @@ class SpiCookie : public CookieIF {
|
|||||||
*/
|
*/
|
||||||
void activateCsDeselect(bool deselectCs, uint16_t delayUsecs);
|
void activateCsDeselect(bool deselectCs, uint16_t delayUsecs);
|
||||||
|
|
||||||
void getMutexParams(MutexIF::TimeoutType& csTimeoutType, dur_millis_t& csTimeout) const;
|
|
||||||
void setMutexParams(MutexIF::TimeoutType csTimeoutType, dur_millis_t csTimeout);
|
|
||||||
|
|
||||||
void setCsLockManual(bool enable);
|
|
||||||
bool getCsLockManual() const;
|
|
||||||
|
|
||||||
spi_ioc_transfer* getTransferStructHandle();
|
spi_ioc_transfer* getTransferStructHandle();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
address_t spiAddress;
|
|
||||||
gpioId_t chipSelectPin;
|
|
||||||
|
|
||||||
spi::SpiComIfModes comIfMode;
|
|
||||||
|
|
||||||
// Required for regular mode
|
|
||||||
const size_t maxSize;
|
|
||||||
spi::SpiModes spiMode;
|
|
||||||
/**
|
|
||||||
* If this is set to true, the SPI ComIF will not perform any mutex locking for the
|
|
||||||
* CS mechanism. The user is responsible to locking and unlocking the mutex for the
|
|
||||||
* whole duration of the transfers.
|
|
||||||
*/
|
|
||||||
bool manualCsLock = false;
|
|
||||||
uint32_t spiSpeed;
|
|
||||||
bool halfDuplex = false;
|
|
||||||
|
|
||||||
MutexIF::TimeoutType csTimeoutType = MutexIF::TimeoutType::WAITING;
|
|
||||||
dur_millis_t csTimeout = DEFAULT_MUTEX_TIMEOUT;
|
|
||||||
|
|
||||||
// Required for callback mode
|
|
||||||
spi::send_callback_function_t sendCallback = nullptr;
|
|
||||||
void* callbackArgs = nullptr;
|
|
||||||
|
|
||||||
struct spi_ioc_transfer spiTransferStruct = {};
|
|
||||||
UncommonParameters uncommonParameters;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal constructor which initializes every field
|
* Internal constructor which initializes every field
|
||||||
* @param spiAddress
|
* @param spiAddress
|
||||||
@ -189,8 +154,27 @@ class SpiCookie : public CookieIF {
|
|||||||
* @param args
|
* @param args
|
||||||
*/
|
*/
|
||||||
SpiCookie(spi::SpiComIfModes comIfMode, address_t spiAddress, gpioId_t chipSelect,
|
SpiCookie(spi::SpiComIfModes comIfMode, address_t spiAddress, gpioId_t chipSelect,
|
||||||
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed,
|
std::string spiDev, const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed,
|
||||||
spi::send_callback_function_t callback, void* args);
|
spi::send_callback_function_t callback, void* args);
|
||||||
|
|
||||||
|
address_t spiAddress;
|
||||||
|
gpioId_t chipSelectPin;
|
||||||
|
std::string spiDevice;
|
||||||
|
|
||||||
|
spi::SpiComIfModes comIfMode;
|
||||||
|
|
||||||
|
// Required for regular mode
|
||||||
|
const size_t maxSize;
|
||||||
|
spi::SpiModes spiMode;
|
||||||
|
uint32_t spiSpeed;
|
||||||
|
bool halfDuplex = false;
|
||||||
|
|
||||||
|
// Required for callback mode
|
||||||
|
spi::send_callback_function_t sendCallback = nullptr;
|
||||||
|
void* callbackArgs = nullptr;
|
||||||
|
|
||||||
|
struct spi_ioc_transfer spiTransferStruct = {};
|
||||||
|
UncommonParameters uncommonParameters;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* LINUX_SPI_SPICOOKIE_H_ */
|
#endif /* LINUX_SPI_SPICOOKIE_H_ */
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
#include <fsfw/serviceinterface.h>
|
#include <fsfw/serviceinterface.h>
|
||||||
|
|
||||||
UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate,
|
UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode,
|
||||||
size_t maxReplyLen, UartModes uartMode)
|
UartBaudRate baudrate, size_t maxReplyLen)
|
||||||
: handlerId(handlerId),
|
: handlerId(handlerId),
|
||||||
deviceFile(deviceFile),
|
deviceFile(deviceFile),
|
||||||
uartMode(uartMode),
|
uartMode(uartMode),
|
||||||
|
@ -69,8 +69,8 @@ class UartCookie : public CookieIF {
|
|||||||
* 8 databits (number of bits transfered with one uart frame)
|
* 8 databits (number of bits transfered with one uart frame)
|
||||||
* One stop bit
|
* One stop bit
|
||||||
*/
|
*/
|
||||||
UartCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate,
|
UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode,
|
||||||
size_t maxReplyLen, UartModes uartMode = UartModes::NON_CANONICAL);
|
UartBaudRate baudrate, size_t maxReplyLen);
|
||||||
|
|
||||||
virtual ~UartCookie();
|
virtual ~UartCookie();
|
||||||
|
|
||||||
|
@ -3,12 +3,6 @@ if [[ ! -f README.md ]]; then
|
|||||||
cd ..
|
cd ..
|
||||||
fi
|
fi
|
||||||
|
|
||||||
folder_list=(
|
|
||||||
"./src"
|
|
||||||
"./hal"
|
|
||||||
"./tests"
|
|
||||||
)
|
|
||||||
|
|
||||||
cmake_fmt="cmake-format"
|
cmake_fmt="cmake-format"
|
||||||
file_selectors="-iname CMakeLists.txt"
|
file_selectors="-iname CMakeLists.txt"
|
||||||
if command -v ${cmake_fmt} &> /dev/null; then
|
if command -v ${cmake_fmt} &> /dev/null; then
|
||||||
@ -21,10 +15,9 @@ fi
|
|||||||
cpp_format="clang-format"
|
cpp_format="clang-format"
|
||||||
file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp"
|
file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp"
|
||||||
if command -v ${cpp_format} &> /dev/null; then
|
if command -v ${cpp_format} &> /dev/null; then
|
||||||
for dir in ${folder_list[@]}; do
|
find ./src ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||||
echo "Auto-formatting ${dir} recursively"
|
find ./hal ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||||
find ${dir} ${file_selectors} | xargs clang-format --style=file -i
|
find ./tests ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||||
done
|
|
||||||
else
|
else
|
||||||
echo "No ${cpp_format} tool found, not formatting C++/C files"
|
echo "No ${cpp_format} tool found, not formatting C++/C files"
|
||||||
fi
|
fi
|
||||||
|
@ -16,8 +16,8 @@ class CommandActionHelper {
|
|||||||
public:
|
public:
|
||||||
CommandActionHelper(CommandsActionsIF* owner);
|
CommandActionHelper(CommandsActionsIF* owner);
|
||||||
virtual ~CommandActionHelper();
|
virtual ~CommandActionHelper();
|
||||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId,
|
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, const uint8_t* data,
|
||||||
const uint8_t* data = nullptr, uint32_t size = 0);
|
uint32_t size);
|
||||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
|
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
|
||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize();
|
||||||
ReturnValue_t handleReply(CommandMessage* reply);
|
ReturnValue_t handleReply(CommandMessage* reply);
|
||||||
|
@ -12,9 +12,7 @@ object_id_t CFDPHandler::packetDestination = 0;
|
|||||||
|
|
||||||
CFDPHandler::CFDPHandler(object_id_t setObjectId, CFDPDistributor* dist)
|
CFDPHandler::CFDPHandler(object_id_t setObjectId, CFDPDistributor* dist)
|
||||||
: SystemObject(setObjectId) {
|
: SystemObject(setObjectId) {
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
requestQueue = QueueFactory::instance()->createMessageQueue(CFDP_HANDLER_MAX_RECEPTION);
|
||||||
requestQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
CFDP_HANDLER_MAX_RECEPTION, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
distributor = dist;
|
distributor = dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,9 +13,7 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
|||||||
submode(SUBMODE_NONE),
|
submode(SUBMODE_NONE),
|
||||||
modeHelper(this),
|
modeHelper(this),
|
||||||
healthHelper(this, setObjectId) {
|
healthHelper(this, setObjectId) {
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
commandQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||||
|
@ -7,26 +7,24 @@
|
|||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
PoolEntry<T>::PoolEntry(uint8_t len, bool setValid) : length(len), valid(setValid) {
|
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, bool setValid)
|
||||||
this->address = new T[this->length]();
|
: length(static_cast<uint8_t>(initValue.size())), valid(setValid) {
|
||||||
std::memset(this->address, 0, this->getByteSize());
|
this->address = new T[this->length];
|
||||||
}
|
if (initValue.size() == 0) {
|
||||||
|
std::memset(this->address, 0, this->getByteSize());
|
||||||
template <typename T>
|
} else {
|
||||||
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValues, bool setValid)
|
std::copy(initValue.begin(), initValue.end(), this->address);
|
||||||
: length(static_cast<uint8_t>(initValues.size())), valid(setValid) {
|
|
||||||
this->address = new T[this->length]();
|
|
||||||
if (initValues.size() > 0) {
|
|
||||||
std::copy(initValues.begin(), initValues.end(), this->address);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
PoolEntry<T>::PoolEntry(const T* initValue, uint8_t setLength, bool setValid)
|
PoolEntry<T>::PoolEntry(T* initValue, uint8_t setLength, bool setValid)
|
||||||
: length(setLength), valid(setValid) {
|
: length(setLength), valid(setValid) {
|
||||||
this->address = new T[this->length]();
|
this->address = new T[this->length];
|
||||||
if (initValue != nullptr) {
|
if (initValue != nullptr) {
|
||||||
std::memcpy(this->address, initValue, this->getByteSize());
|
std::memcpy(this->address, initValue, this->getByteSize());
|
||||||
|
} else {
|
||||||
|
std::memset(this->address, 0, this->getByteSize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,9 +33,6 @@ class PoolEntry : public PoolEntryIF {
|
|||||||
"instead! The ECSS standard defines a boolean as a one bit "
|
"instead! The ECSS standard defines a boolean as a one bit "
|
||||||
"field. Therefore it is preferred to store a boolean as an "
|
"field. Therefore it is preferred to store a boolean as an "
|
||||||
"uint8_t");
|
"uint8_t");
|
||||||
|
|
||||||
PoolEntry(uint8_t len = 1, bool setValid = false);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief In the classe's constructor, space is allocated on the heap and
|
* @brief In the classe's constructor, space is allocated on the heap and
|
||||||
* potential initialization values are copied to that space.
|
* potential initialization values are copied to that space.
|
||||||
@ -52,7 +49,7 @@ class PoolEntry : public PoolEntryIF {
|
|||||||
* @param setValid
|
* @param setValid
|
||||||
* Sets the initialization flag. It is invalid by default.
|
* Sets the initialization flag. It is invalid by default.
|
||||||
*/
|
*/
|
||||||
PoolEntry(std::initializer_list<T> initValue, bool setValid = false);
|
PoolEntry(std::initializer_list<T> initValue = {0}, bool setValid = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief In the classe's constructor, space is allocated on the heap and
|
* @brief In the classe's constructor, space is allocated on the heap and
|
||||||
@ -65,7 +62,7 @@ class PoolEntry : public PoolEntryIF {
|
|||||||
* @param setValid
|
* @param setValid
|
||||||
* Sets the initialization flag. It is invalid by default.
|
* Sets the initialization flag. It is invalid by default.
|
||||||
*/
|
*/
|
||||||
PoolEntry(const T* initValue, uint8_t setLength = 1, bool setValid = false);
|
PoolEntry(T* initValue, uint8_t setLength = 1, bool setValid = false);
|
||||||
|
|
||||||
//! Explicitely deleted copy ctor, copying is not allowed.
|
//! Explicitely deleted copy ctor, copying is not allowed.
|
||||||
PoolEntry(const PoolEntry&) = delete;
|
PoolEntry(const PoolEntry&) = delete;
|
||||||
|
@ -577,10 +577,6 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
|
|||||||
|
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
if (result == WRONG_HK_PACKET_TYPE) {
|
|
||||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage",
|
|
||||||
WRONG_HK_PACKET_TYPE);
|
|
||||||
}
|
|
||||||
HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result);
|
HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result);
|
||||||
} else {
|
} else {
|
||||||
HousekeepingMessage::setHkRequestSuccessReply(&reply, sid);
|
HousekeepingMessage::setHkRequestSuccessReply(&reply, sid);
|
||||||
@ -838,8 +834,6 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
|
|||||||
errorPrint = "Dataset not found";
|
errorPrint = "Dataset not found";
|
||||||
} else if (error == POOLOBJECT_NOT_FOUND) {
|
} else if (error == POOLOBJECT_NOT_FOUND) {
|
||||||
errorPrint = "Pool Object not found";
|
errorPrint = "Pool Object not found";
|
||||||
} else if (error == WRONG_HK_PACKET_TYPE) {
|
|
||||||
errorPrint = "Wrong Packet Type";
|
|
||||||
} else if (error == HasReturnvaluesIF::RETURN_FAILED) {
|
} else if (error == HasReturnvaluesIF::RETURN_FAILED) {
|
||||||
if (outputType == sif::OutputTypes::OUT_WARNING) {
|
if (outputType == sif::OutputTypes::OUT_WARNING) {
|
||||||
errorPrint = "Generic Warning";
|
errorPrint = "Generic Warning";
|
||||||
|
@ -162,7 +162,6 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
|
|||||||
object_id_t getCreatorObjectId();
|
object_id_t getCreatorObjectId();
|
||||||
|
|
||||||
bool getReportingEnabled() const;
|
bool getReportingEnabled() const;
|
||||||
void setReportingEnabled(bool enabled);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current periodic HK generation interval this set
|
* Returns the current periodic HK generation interval this set
|
||||||
@ -190,6 +189,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
|
|||||||
* Used for periodic generation.
|
* Used for periodic generation.
|
||||||
*/
|
*/
|
||||||
bool reportingEnabled = false;
|
bool reportingEnabled = false;
|
||||||
|
void setReportingEnabled(bool enabled);
|
||||||
|
|
||||||
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
|
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
|
||||||
uint8_t nonDiagIntervalFactor = 5);
|
uint8_t nonDiagIntervalFactor = 5);
|
||||||
|
@ -26,7 +26,11 @@ void AssemblyBase::performChildOperation() {
|
|||||||
|
|
||||||
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
|
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||||
doStartTransition(mode, submode);
|
doStartTransition(mode, submode);
|
||||||
triggerModeHelperEvents(mode, submode);
|
if (modeHelper.isForced()) {
|
||||||
|
triggerEvent(FORCING_MODE, mode, submode);
|
||||||
|
} else {
|
||||||
|
triggerEvent(CHANGING_MODE, mode, submode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
|
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
|
||||||
@ -73,10 +77,9 @@ bool AssemblyBase::handleChildrenChangedHealth() {
|
|||||||
}
|
}
|
||||||
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
|
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
|
||||||
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
|
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
|
||||||
triggerEvent(TRYING_RECOVERY, iter->first, 0);
|
triggerEvent(TRYING_RECOVERY);
|
||||||
recoveryState = RECOVERY_STARTED;
|
recoveryState = RECOVERY_STARTED;
|
||||||
recoveringDevice = iter;
|
recoveringDevice = iter;
|
||||||
// The user needs to take care of commanding the children off in commandChildren
|
|
||||||
doStartTransition(targetMode, targetSubmode);
|
doStartTransition(targetMode, targetSubmode);
|
||||||
} else {
|
} else {
|
||||||
triggerEvent(CHILD_CHANGED_HEALTH);
|
triggerEvent(CHILD_CHANGED_HEALTH);
|
||||||
@ -225,9 +228,6 @@ ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
|
|||||||
bool AssemblyBase::checkAndHandleRecovery() {
|
bool AssemblyBase::checkAndHandleRecovery() {
|
||||||
switch (recoveryState) {
|
switch (recoveryState) {
|
||||||
case RECOVERY_STARTED:
|
case RECOVERY_STARTED:
|
||||||
// The recovery was already start in #handleChildrenChangedHealth and we just need
|
|
||||||
// to wait for an off time period.
|
|
||||||
// TODO: make time period configurable
|
|
||||||
recoveryState = RECOVERY_WAIT;
|
recoveryState = RECOVERY_WAIT;
|
||||||
recoveryOffTimer.resetTimer();
|
recoveryOffTimer.resetTimer();
|
||||||
return true;
|
return true;
|
||||||
@ -266,11 +266,3 @@ void AssemblyBase::overwriteDeviceHealth(object_id_t objectId, HasHealthIF::Heal
|
|||||||
modeHelper.setForced(true);
|
modeHelper.setForced(true);
|
||||||
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
|
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) {
|
|
||||||
if (modeHelper.isForced()) {
|
|
||||||
triggerEvent(FORCING_MODE, mode, submode);
|
|
||||||
} else {
|
|
||||||
triggerEvent(CHANGING_MODE, mode, submode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -12,8 +12,7 @@
|
|||||||
* Documentation: Dissertation Baetz p.156, 157.
|
* Documentation: Dissertation Baetz p.156, 157.
|
||||||
*
|
*
|
||||||
* This class reduces the complexity of controller components which would
|
* This class reduces the complexity of controller components which would
|
||||||
* otherwise be needed for the handling of redundant devices. However, it can also be used to
|
* otherwise be needed for the handling of redundant devices.
|
||||||
* manage the mode keeping and recovery of non-redundant devices
|
|
||||||
*
|
*
|
||||||
* The template class monitors mode and health state of its children
|
* The template class monitors mode and health state of its children
|
||||||
* and checks availability of devices on every detected change.
|
* and checks availability of devices on every detected change.
|
||||||
@ -27,9 +26,11 @@
|
|||||||
*
|
*
|
||||||
* Important:
|
* Important:
|
||||||
*
|
*
|
||||||
* The implementation must call #registerChild for all commanded children during initialization.
|
* The implementation must call registerChild(object_id_t child)
|
||||||
|
* for all commanded children during initialization.
|
||||||
* The implementation must call the initialization function of the base class.
|
* The implementation must call the initialization function of the base class.
|
||||||
* (This will call the function in SubsystemBase)
|
* (This will call the function in SubsystemBase)
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
class AssemblyBase : public SubsystemBase {
|
class AssemblyBase : public SubsystemBase {
|
||||||
public:
|
public:
|
||||||
@ -46,14 +47,13 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Command children to reach [mode,submode] combination. Can be done by setting
|
* Command children to reach [mode,submode] combination
|
||||||
* #commandsOutstanding correctly, or using #executeTable. In case of an FDIR recovery,
|
* Can be done by setting #commandsOutstanding correctly,
|
||||||
* the user needs to ensure that the target devices are healthy. If a device is not healthy,
|
* or using executeTable()
|
||||||
* a recovery might be on-going and the device needs to be commanded to off first.
|
|
||||||
* @param mode
|
* @param mode
|
||||||
* @param submode
|
* @param submode
|
||||||
* @return
|
* @return
|
||||||
* - @c RETURN_OK if OK
|
* - @c RETURN_OK if ok
|
||||||
* - @c NEED_SECOND_STEP if children need to be commanded again
|
* - @c NEED_SECOND_STEP if children need to be commanded again
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0;
|
virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0;
|
||||||
@ -120,19 +120,8 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
|
|
||||||
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
|
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
|
||||||
|
|
||||||
/**
|
virtual void performChildOperation();
|
||||||
* @brief Default periodic handler
|
|
||||||
* @details
|
|
||||||
* This is the default periodic handler which will be called by the SubsystemBase
|
|
||||||
* performOperation. It performs the child transitions or reacts to changed health/mode states
|
|
||||||
* of children objects
|
|
||||||
*/
|
|
||||||
virtual void performChildOperation() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function handles changed mode or health states of children
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool handleChildrenChanged();
|
bool handleChildrenChanged();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,37 +134,12 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
|
|
||||||
bool handleChildrenChangedHealth();
|
bool handleChildrenChangedHealth();
|
||||||
|
|
||||||
/**
|
|
||||||
* Core transition handler. The default implementation will only do something if
|
|
||||||
* #commandsOutstanding is smaller or equal to zero, which means that all mode commands
|
|
||||||
* from the #doPerformTransition call were executed successfully.
|
|
||||||
*
|
|
||||||
* Unless a second step was requested, the function will then use #checkChildrenState to
|
|
||||||
* determine whether the target mode was reached.
|
|
||||||
*
|
|
||||||
* There is some special handling for certain (internal) modes:
|
|
||||||
* - A second step is necessary. #commandChildren will be performed again
|
|
||||||
* - The device health was overwritten. #commandChildren will be called
|
|
||||||
* - A recovery is ongoing. #checkAndHandleRecovery will be called.
|
|
||||||
*/
|
|
||||||
virtual void handleChildrenTransition();
|
virtual void handleChildrenTransition();
|
||||||
|
|
||||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode);
|
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode);
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls #doStartTransition and triggers an informative event as well that the mode will
|
|
||||||
* change
|
|
||||||
* @param mode
|
|
||||||
* @param submode
|
|
||||||
*/
|
|
||||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||||
|
|
||||||
/**
|
|
||||||
* This function starts the transition by setting the internal #targetSubmode and #targetMode
|
|
||||||
* variables and then calling the #commandChildren function.
|
|
||||||
* @param mode
|
|
||||||
* @param submode
|
|
||||||
*/
|
|
||||||
virtual void doStartTransition(Mode_t mode, Submode_t submode);
|
virtual void doStartTransition(Mode_t mode, Submode_t submode);
|
||||||
|
|
||||||
virtual bool isInTransition();
|
virtual bool isInTransition();
|
||||||
@ -196,7 +160,7 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
* Manages recovery of a device
|
* Manages recovery of a device
|
||||||
* @return true if recovery is still ongoing, false else.
|
* @return true if recovery is still ongoing, false else.
|
||||||
*/
|
*/
|
||||||
virtual bool checkAndHandleRecovery();
|
bool checkAndHandleRecovery();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to overwrite health state of one of the children.
|
* Helper method to overwrite health state of one of the children.
|
||||||
@ -204,8 +168,6 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
* @param objectId Must be a registered child.
|
* @param objectId Must be a registered child.
|
||||||
*/
|
*/
|
||||||
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
|
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
|
||||||
|
|
||||||
void triggerModeHelperEvents(Mode_t mode, Submode_t submode);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */
|
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */
|
||||||
|
@ -39,9 +39,8 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
|
|||||||
childTransitionDelay(5000),
|
childTransitionDelay(5000),
|
||||||
transitionSourceMode(_MODE_POWER_DOWN),
|
transitionSourceMode(_MODE_POWER_DOWN),
|
||||||
transitionSourceSubMode(SUBMODE_NONE) {
|
transitionSourceSubMode(SUBMODE_NONE) {
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||||
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||||
insertInCommandMap(RAW_COMMAND_ID);
|
insertInCommandMap(RAW_COMMAND_ID);
|
||||||
cookieInfo.state = COOKIE_UNUSED;
|
cookieInfo.state = COOKIE_UNUSED;
|
||||||
cookieInfo.pendingCommand = deviceCommandMap.end();
|
cookieInfo.pendingCommand = deviceCommandMap.end();
|
||||||
@ -49,6 +48,9 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
|
|||||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase",
|
printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase",
|
||||||
HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie");
|
HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie");
|
||||||
}
|
}
|
||||||
|
if (this->fdirInstance == nullptr) {
|
||||||
|
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, defaultFdirParentId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
|
void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
|
||||||
@ -124,18 +126,6 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
|||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (this->fdirInstance == nullptr) {
|
|
||||||
this->fdirInstance =
|
|
||||||
new DeviceHandlerFailureIsolation(this->getObjectId(), defaultFdirParentId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->parent != objects::NO_OBJECT) {
|
|
||||||
HasModesIF* modeIF = ObjectManager::instance()->get<HasModesIF>(this->parent);
|
|
||||||
HasHealthIF* healthIF = ObjectManager::instance()->get<HasHealthIF>(this->parent);
|
|
||||||
if (modeIF != nullptr and healthIF != nullptr) {
|
|
||||||
setParentQueue(modeIF->getCommandQueue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
communicationInterface =
|
communicationInterface =
|
||||||
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
|
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
|
||||||
@ -243,28 +233,17 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::decrementDeviceReplyMap() {
|
void DeviceHandlerBase::decrementDeviceReplyMap() {
|
||||||
bool timedOut = false;
|
|
||||||
for (std::pair<const DeviceCommandId_t, DeviceReplyInfo>& replyPair : deviceReplyMap) {
|
for (std::pair<const DeviceCommandId_t, DeviceReplyInfo>& replyPair : deviceReplyMap) {
|
||||||
if (replyPair.second.countdown != nullptr && replyPair.second.active) {
|
if (replyPair.second.delayCycles != 0) {
|
||||||
if (replyPair.second.countdown->hasTimedOut()) {
|
|
||||||
timedOut = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (replyPair.second.delayCycles != 0 && replyPair.second.countdown == nullptr) {
|
|
||||||
replyPair.second.delayCycles--;
|
replyPair.second.delayCycles--;
|
||||||
if (replyPair.second.delayCycles == 0) {
|
if (replyPair.second.delayCycles == 0) {
|
||||||
if (replyPair.second.periodic) {
|
if (replyPair.second.periodic) {
|
||||||
replyPair.second.delayCycles = replyPair.second.maxDelayCycles;
|
replyPair.second.delayCycles = replyPair.second.maxDelayCycles;
|
||||||
}
|
}
|
||||||
timedOut = true;
|
replyToReply(replyPair.first, replyPair.second, TIMEOUT);
|
||||||
|
missedReply(replyPair.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (timedOut) {
|
|
||||||
replyToReply(replyPair.first, replyPair.second, TIMEOUT);
|
|
||||||
missedReply(replyPair.first);
|
|
||||||
timedOut = false;
|
|
||||||
replyPair.second.active = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,12 +352,14 @@ void DeviceHandlerBase::doStateMachine() {
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case _MODE_WAIT_OFF: {
|
case _MODE_WAIT_OFF: {
|
||||||
|
uint32_t currentUptime;
|
||||||
|
Clock::getUptime(¤tUptime);
|
||||||
|
|
||||||
if (powerSwitcher == nullptr) {
|
if (powerSwitcher == nullptr) {
|
||||||
setMode(MODE_OFF);
|
setMode(MODE_OFF);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint32_t currentUptime;
|
|
||||||
Clock::getUptime(¤tUptime);
|
|
||||||
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
|
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
|
||||||
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
|
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
|
||||||
setMode(MODE_ERROR_ON);
|
setMode(MODE_ERROR_ON);
|
||||||
@ -427,22 +408,20 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, Submode_t s
|
|||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
|
ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
|
||||||
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
|
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
|
||||||
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId,
|
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) {
|
||||||
Countdown* countdown) {
|
|
||||||
// No need to check, as we may try to insert multiple times.
|
// No need to check, as we may try to insert multiple times.
|
||||||
insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId);
|
insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId);
|
||||||
if (hasDifferentReplyId) {
|
if (hasDifferentReplyId) {
|
||||||
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic, countdown);
|
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic);
|
||||||
} else {
|
} else {
|
||||||
return insertInReplyMap(deviceCommand, maxDelayCycles, replyDataSet, replyLen, periodic,
|
return insertInReplyMap(deviceCommand, maxDelayCycles, replyDataSet, replyLen, periodic);
|
||||||
countdown);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
|
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
|
||||||
uint16_t maxDelayCycles,
|
uint16_t maxDelayCycles,
|
||||||
LocalPoolDataSetBase* dataSet, size_t replyLen,
|
LocalPoolDataSetBase* dataSet, size_t replyLen,
|
||||||
bool periodic, Countdown* countdown) {
|
bool periodic) {
|
||||||
DeviceReplyInfo info;
|
DeviceReplyInfo info;
|
||||||
info.maxDelayCycles = maxDelayCycles;
|
info.maxDelayCycles = maxDelayCycles;
|
||||||
info.periodic = periodic;
|
info.periodic = periodic;
|
||||||
@ -450,10 +429,6 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
|
|||||||
info.replyLen = replyLen;
|
info.replyLen = replyLen;
|
||||||
info.dataSet = dataSet;
|
info.dataSet = dataSet;
|
||||||
info.command = deviceCommandMap.end();
|
info.command = deviceCommandMap.end();
|
||||||
info.countdown = countdown;
|
|
||||||
if (info.periodic) {
|
|
||||||
info.active = true;
|
|
||||||
}
|
|
||||||
auto resultPair = deviceReplyMap.emplace(replyId, info);
|
auto resultPair = deviceReplyMap.emplace(replyId, info);
|
||||||
if (resultPair.second) {
|
if (resultPair.second) {
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
@ -489,8 +464,7 @@ size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) {
|
|||||||
}
|
}
|
||||||
DeviceReplyIter iter = deviceReplyMap.find(replyId);
|
DeviceReplyIter iter = deviceReplyMap.find(replyId);
|
||||||
if (iter != deviceReplyMap.end()) {
|
if (iter != deviceReplyMap.end()) {
|
||||||
if ((iter->second.delayCycles != 0 && iter->second.countdown == nullptr) ||
|
if (iter->second.delayCycles != 0) {
|
||||||
(iter->second.active && iter->second.countdown != nullptr)) {
|
|
||||||
return iter->second.replyLen;
|
return iter->second.replyLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -572,9 +546,6 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
|||||||
mode = newMode;
|
mode = newMode;
|
||||||
modeChanged();
|
modeChanged();
|
||||||
setNormalDatapoolEntriesInvalid();
|
setNormalDatapoolEntriesInvalid();
|
||||||
if (newMode == MODE_OFF) {
|
|
||||||
disableCommandsAndReplies();
|
|
||||||
}
|
|
||||||
if (!isTransitionalMode()) {
|
if (!isTransitionalMode()) {
|
||||||
modeHelper.modeChanged(newMode, newSubmode);
|
modeHelper.modeChanged(newMode, newSubmode);
|
||||||
announceMode(false);
|
announceMode(false);
|
||||||
@ -837,18 +808,17 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId
|
|||||||
|
|
||||||
DeviceReplyInfo* info = &(iter->second);
|
DeviceReplyInfo* info = &(iter->second);
|
||||||
|
|
||||||
if ((info->delayCycles != 0 && info->countdown == nullptr) ||
|
if (info->delayCycles != 0) {
|
||||||
(info->active && info->countdown != nullptr)) {
|
|
||||||
result = interpretDeviceReply(foundId, receivedData);
|
result = interpretDeviceReply(foundId, receivedData);
|
||||||
|
|
||||||
if (result == IGNORE_REPLY_DATA) {
|
if (result == IGNORE_REPLY_DATA) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->active && info->countdown != nullptr) {
|
if (info->periodic) {
|
||||||
disableTimeoutControlledReply(info);
|
info->delayCycles = info->maxDelayCycles;
|
||||||
} else if (info->delayCycles != 0) {
|
} else {
|
||||||
disableDelayCyclesControlledReply(info);
|
info->delayCycles = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
@ -867,24 +837,6 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::disableTimeoutControlledReply(DeviceReplyInfo* info) {
|
|
||||||
if (info->periodic) {
|
|
||||||
info->countdown->resetTimer();
|
|
||||||
} else {
|
|
||||||
info->active = false;
|
|
||||||
info->countdown->timeOut();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceHandlerBase::disableDelayCyclesControlledReply(DeviceReplyInfo* info) {
|
|
||||||
if (info->periodic) {
|
|
||||||
info->delayCycles = info->maxDelayCycles;
|
|
||||||
} else {
|
|
||||||
info->delayCycles = 0;
|
|
||||||
info->active = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, uint8_t** data,
|
ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, uint8_t** data,
|
||||||
size_t* len) {
|
size_t* len) {
|
||||||
size_t lenTmp;
|
size_t lenTmp;
|
||||||
@ -1010,10 +962,6 @@ ReturnValue_t DeviceHandlerBase::enableReplyInReplyMap(DeviceCommandMap::iterato
|
|||||||
info->delayCycles = info->maxDelayCycles;
|
info->delayCycles = info->maxDelayCycles;
|
||||||
info->command = command;
|
info->command = command;
|
||||||
command->second.expectedReplies = expectedReplies;
|
command->second.expectedReplies = expectedReplies;
|
||||||
if (info->countdown != nullptr) {
|
|
||||||
info->countdown->resetTimer();
|
|
||||||
}
|
|
||||||
info->active = true;
|
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
} else {
|
} else {
|
||||||
return NO_REPLY_EXPECTED;
|
return NO_REPLY_EXPECTED;
|
||||||
@ -1248,8 +1196,7 @@ void DeviceHandlerBase::setParentQueue(MessageQueueId_t parentQueueId) {
|
|||||||
bool DeviceHandlerBase::isAwaitingReply() {
|
bool DeviceHandlerBase::isAwaitingReply() {
|
||||||
std::map<DeviceCommandId_t, DeviceReplyInfo>::iterator iter;
|
std::map<DeviceCommandId_t, DeviceReplyInfo>::iterator iter;
|
||||||
for (iter = deviceReplyMap.begin(); iter != deviceReplyMap.end(); ++iter) {
|
for (iter = deviceReplyMap.begin(); iter != deviceReplyMap.end(); ++iter) {
|
||||||
if ((iter->second.delayCycles != 0 && iter->second.countdown == nullptr) ||
|
if (iter->second.delayCycles != 0) {
|
||||||
(iter->second.active && iter->second.countdown != nullptr)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1404,8 +1351,6 @@ uint8_t DeviceHandlerBase::getReplyDelayCycles(DeviceCommandId_t deviceCommand)
|
|||||||
DeviceReplyMap::iterator iter = deviceReplyMap.find(deviceCommand);
|
DeviceReplyMap::iterator iter = deviceReplyMap.find(deviceCommand);
|
||||||
if (iter == deviceReplyMap.end()) {
|
if (iter == deviceReplyMap.end()) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (iter->second.countdown != nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return iter->second.delayCycles;
|
return iter->second.delayCycles;
|
||||||
}
|
}
|
||||||
@ -1454,8 +1399,6 @@ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task) { executingTask = task;
|
|||||||
void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId,
|
void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId,
|
||||||
uint32_t parameter) {}
|
uint32_t parameter) {}
|
||||||
|
|
||||||
Submode_t DeviceHandlerBase::getInitialSubmode() { return SUBMODE_NONE; }
|
|
||||||
|
|
||||||
void DeviceHandlerBase::performOperationHook() {}
|
void DeviceHandlerBase::performOperationHook() {}
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||||
@ -1478,7 +1421,7 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
|
|||||||
this->poolManager.initializeAfterTaskCreation();
|
this->poolManager.initializeAfterTaskCreation();
|
||||||
|
|
||||||
if (setStartupImmediately) {
|
if (setStartupImmediately) {
|
||||||
startTransition(MODE_ON, getInitialSubmode());
|
startTransition(MODE_ON, SUBMODE_NONE);
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
@ -1562,29 +1505,3 @@ MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyI
|
|||||||
}
|
}
|
||||||
return commandIter->second.sendReplyTo;
|
return commandIter->second.sendReplyTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::setCustomFdir(FailureIsolationBase* fdir) { this->fdirInstance = fdir; }
|
|
||||||
|
|
||||||
void DeviceHandlerBase::setParent(object_id_t parent) { this->parent = parent; }
|
|
||||||
|
|
||||||
void DeviceHandlerBase::setPowerSwitcher(PowerSwitchIF* switcher) {
|
|
||||||
this->powerSwitcher = switcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceHandlerBase::disableCommandsAndReplies() {
|
|
||||||
for (auto& command : deviceCommandMap) {
|
|
||||||
if (command.second.isExecuting) {
|
|
||||||
command.second.isExecuting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (auto& reply : deviceReplyMap) {
|
|
||||||
if (!reply.second.periodic) {
|
|
||||||
if (reply.second.countdown != nullptr) {
|
|
||||||
reply.second.countdown->timeOut();
|
|
||||||
} else {
|
|
||||||
reply.second.delayCycles = 0;
|
|
||||||
}
|
|
||||||
reply.second.active = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include "DeviceHandlerFailureIsolation.h"
|
#include "DeviceHandlerFailureIsolation.h"
|
||||||
#include "DeviceHandlerIF.h"
|
#include "DeviceHandlerIF.h"
|
||||||
#include "DeviceHandlerThermalSet.h"
|
#include "DeviceHandlerThermalSet.h"
|
||||||
#include "DhbCfgHelpers.h"
|
|
||||||
#include "fsfw/action/ActionHelper.h"
|
#include "fsfw/action/ActionHelper.h"
|
||||||
#include "fsfw/action/HasActionsIF.h"
|
#include "fsfw/action/HasActionsIF.h"
|
||||||
#include "fsfw/datapool/PoolVariableIF.h"
|
#include "fsfw/datapool/PoolVariableIF.h"
|
||||||
@ -104,9 +103,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF *comCookie,
|
DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF *comCookie,
|
||||||
FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20);
|
FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20);
|
||||||
|
|
||||||
void setCustomFdir(FailureIsolationBase *fdir);
|
|
||||||
void setParent(object_id_t parent);
|
|
||||||
void setPowerSwitcher(PowerSwitchIF *switcher);
|
|
||||||
void setHkDestination(object_id_t hkDestination);
|
void setHkDestination(object_id_t hkDestination);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -452,9 +448,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* by the device repeatedly without request) or not. Default is aperiodic (0).
|
* by the device repeatedly without request) or not. Default is aperiodic (0).
|
||||||
* Please note that periodic replies are disabled by default. You can enable them with
|
* Please note that periodic replies are disabled by default. You can enable them with
|
||||||
* #updatePeriodicReply
|
* #updatePeriodicReply
|
||||||
* @param countdown Instead of using maxDelayCycles to timeout a device reply it is also possible
|
|
||||||
* to provide a pointer to a Countdown object which will signal the timeout
|
|
||||||
* when expired
|
|
||||||
* @return - @c RETURN_OK when the command was successfully inserted,
|
* @return - @c RETURN_OK when the command was successfully inserted,
|
||||||
* - @c RETURN_FAILED else.
|
* - @c RETURN_FAILED else.
|
||||||
*/
|
*/
|
||||||
@ -462,26 +455,22 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
LocalPoolDataSetBase *replyDataSet = nullptr,
|
LocalPoolDataSetBase *replyDataSet = nullptr,
|
||||||
size_t replyLen = 0, bool periodic = false,
|
size_t replyLen = 0, bool periodic = false,
|
||||||
bool hasDifferentReplyId = false,
|
bool hasDifferentReplyId = false,
|
||||||
DeviceCommandId_t replyId = 0,
|
DeviceCommandId_t replyId = 0);
|
||||||
Countdown *countdown = nullptr);
|
|
||||||
/**
|
/**
|
||||||
* @brief This is a helper method to insert replies in the reply map.
|
* @brief This is a helper method to insert replies in the reply map.
|
||||||
* @param deviceCommand Identifier of the reply to add.
|
* @param deviceCommand Identifier of the reply to add.
|
||||||
* @param maxDelayCycles The maximum number of delay cycles the reply waits
|
* @param maxDelayCycles The maximum number of delay cycles the reply waits
|
||||||
* until it times out.
|
* until it times out.
|
||||||
* @param periodic Indicates if the command is periodic (i.e. it is sent
|
* @param periodic Indicates if the command is periodic (i.e. it is sent
|
||||||
* by the device repeatedly without request) or not. Default is aperiodic (0).
|
* by the device repeatedly without request) or not. Default is aperiodic (0).
|
||||||
* Please note that periodic replies are disabled by default. You can enable them with
|
* Please note that periodic replies are disabled by default. You can enable them with
|
||||||
* #updatePeriodicReply
|
* #updatePeriodicReply
|
||||||
* @param countdown Instead of using maxDelayCycles to timeout a device reply it is also possible
|
|
||||||
* to provide a pointer to a Countdown object which will signal the timeout
|
|
||||||
* when expired
|
|
||||||
* @return - @c RETURN_OK when the command was successfully inserted,
|
* @return - @c RETURN_OK when the command was successfully inserted,
|
||||||
* - @c RETURN_FAILED else.
|
* - @c RETURN_FAILED else.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
|
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
|
||||||
LocalPoolDataSetBase *dataSet = nullptr, size_t replyLen = 0,
|
LocalPoolDataSetBase *dataSet = nullptr, size_t replyLen = 0,
|
||||||
bool periodic = false, Countdown *countdown = nullptr);
|
bool periodic = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A simple command to add a command to the commandList.
|
* @brief A simple command to add a command to the commandList.
|
||||||
@ -489,9 +478,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* @return - @c RETURN_OK when the command was successfully inserted,
|
* @return - @c RETURN_OK when the command was successfully inserted,
|
||||||
* - @c RETURN_FAILED else.
|
* - @c RETURN_FAILED else.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t insertInCommandMap(
|
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand,
|
||||||
DeviceCommandId_t deviceCommand, bool useAlternativeReply = false,
|
bool useAlternativeReply = false,
|
||||||
DeviceCommandId_t alternativeReplyId = DeviceHandlerIF::NO_COMMAND_ID);
|
DeviceCommandId_t alternativeReplyId = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables a periodic reply for a given command. It sets to delay cycles to the specified
|
* Enables a periodic reply for a given command. It sets to delay cycles to the specified
|
||||||
@ -660,12 +649,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0,
|
virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0,
|
||||||
uint32_t parameter = 0);
|
uint32_t parameter = 0);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Can be overwritten by a child to specify the initial submode when device has been set
|
|
||||||
* to startup immediately.
|
|
||||||
*/
|
|
||||||
virtual Submode_t getInitialSubmode();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
|
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
|
||||||
|
|
||||||
@ -784,18 +767,11 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* This is used to keep track of pending replies.
|
* This is used to keep track of pending replies.
|
||||||
*/
|
*/
|
||||||
struct DeviceReplyInfo {
|
struct DeviceReplyInfo {
|
||||||
//! For Command-Reply combinations:
|
|
||||||
//! The maximum number of cycles the handler should wait for a reply
|
//! The maximum number of cycles the handler should wait for a reply
|
||||||
//! to this command.
|
//! to this command.
|
||||||
//!
|
|
||||||
//! Reply Only:
|
|
||||||
//! For periodic replies, this variable will be the number of delay cycles between the replies.
|
|
||||||
//! For the non-periodic variant, this variable is not used as there is no meaningful
|
|
||||||
//! definition for delay
|
|
||||||
uint16_t maxDelayCycles;
|
uint16_t maxDelayCycles;
|
||||||
//! This variable will be set to #maxDelayCycles if a reply is expected.
|
//! The currently remaining cycles the handler should wait for a reply,
|
||||||
//! For non-periodic replies without a command, this variable is unused.
|
//! 0 means there is no reply expected
|
||||||
//! A runtime value of 0 means there is no reply is currently expected.
|
|
||||||
uint16_t delayCycles;
|
uint16_t delayCycles;
|
||||||
size_t replyLen = 0; //!< Expected size of the reply.
|
size_t replyLen = 0; //!< Expected size of the reply.
|
||||||
//! if this is !=0, the delayCycles will not be reset to 0 but to
|
//! if this is !=0, the delayCycles will not be reset to 0 but to
|
||||||
@ -807,11 +783,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
LocalPoolDataSetBase *dataSet = nullptr;
|
LocalPoolDataSetBase *dataSet = nullptr;
|
||||||
//! The command that expects this reply.
|
//! The command that expects this reply.
|
||||||
DeviceCommandMap::iterator command;
|
DeviceCommandMap::iterator command;
|
||||||
//! Instead of using delayCycles to specify the maximum time to wait for the device reply, it
|
|
||||||
//! is also possible specify a countdown
|
|
||||||
Countdown *countdown = nullptr;
|
|
||||||
//! will be set to true when reply is enabled
|
|
||||||
bool active = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using DeviceReplyMap = std::map<DeviceCommandId_t, DeviceReplyInfo>;
|
using DeviceReplyMap = std::map<DeviceCommandId_t, DeviceReplyInfo>;
|
||||||
@ -851,7 +822,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
/** Pointer to the used FDIR instance. If not provided by child,
|
/** Pointer to the used FDIR instance. If not provided by child,
|
||||||
* default class is instantiated. */
|
* default class is instantiated. */
|
||||||
FailureIsolationBase *fdirInstance;
|
FailureIsolationBase *fdirInstance;
|
||||||
object_id_t parent = objects::NO_OBJECT;
|
|
||||||
|
|
||||||
//! To correctly delete the default instance.
|
//! To correctly delete the default instance.
|
||||||
bool defaultFDIRUsed;
|
bool defaultFDIRUsed;
|
||||||
@ -1274,17 +1244,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
*/
|
*/
|
||||||
void doGetRead(void);
|
void doGetRead(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handles disabling of replies which use a timeout to detect missed replies.
|
|
||||||
*/
|
|
||||||
void disableTimeoutControlledReply(DeviceReplyInfo *info);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handles disabling of replies which use a number of maximum delay cycles to detect
|
|
||||||
* missed replies.
|
|
||||||
*/
|
|
||||||
void disableDelayCyclesControlledReply(DeviceReplyInfo *info);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrive data from the #IPCStore.
|
* Retrive data from the #IPCStore.
|
||||||
*
|
*
|
||||||
@ -1326,11 +1285,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
void printWarningOrError(sif::OutputTypes errorType, const char *functionName,
|
void printWarningOrError(sif::OutputTypes errorType, const char *functionName,
|
||||||
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
|
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
|
||||||
const char *errorPrint = nullptr);
|
const char *errorPrint = nullptr);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Disables all commands and replies when device is set to MODE_OFF
|
|
||||||
*/
|
|
||||||
void disableCommandsAndReplies();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */
|
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */
|
||||||
|
@ -29,7 +29,6 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event)
|
|||||||
switch (event->getEvent()) {
|
switch (event->getEvent()) {
|
||||||
case HasModesIF::MODE_TRANSITION_FAILED:
|
case HasModesIF::MODE_TRANSITION_FAILED:
|
||||||
case HasModesIF::OBJECT_IN_INVALID_MODE:
|
case HasModesIF::OBJECT_IN_INVALID_MODE:
|
||||||
case DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT:
|
|
||||||
// We'll try a recovery as long as defined in MAX_REBOOT.
|
// We'll try a recovery as long as defined in MAX_REBOOT.
|
||||||
// Might cause some AssemblyBase cycles, so keep number low.
|
// Might cause some AssemblyBase cycles, so keep number low.
|
||||||
handleRecovery(event->getEvent());
|
handleRecovery(event->getEvent());
|
||||||
|
@ -109,7 +109,6 @@ class DeviceHandlerIF {
|
|||||||
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW);
|
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW);
|
||||||
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
|
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
|
||||||
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
|
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
|
||||||
static const Event DEVICE_WANTS_HARD_REBOOT = MAKE_EVENT(11, severity::HIGH);
|
|
||||||
|
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;
|
||||||
|
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
#ifndef FSFW_SRC_FSFW_DEVICEHANDLERS_DHBCFGHELPERS_H_
|
|
||||||
#define FSFW_SRC_FSFW_DEVICEHANDLERS_DHBCFGHELPERS_H_
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This is the base class for configuration related to both DHB commands, replies and their
|
|
||||||
* combination
|
|
||||||
*/
|
|
||||||
struct CfgBase {
|
|
||||||
public:
|
|
||||||
explicit CfgBase(DeviceCommandId_t cmdAndOrReplyId) : cmdAndOrReplyId(cmdAndOrReplyId){};
|
|
||||||
DeviceCommandId_t cmdAndOrReplyId;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Configuration class for commands
|
|
||||||
*/
|
|
||||||
struct CmdCfg {
|
|
||||||
public:
|
|
||||||
explicit CmdCfg(DeviceCommandId_t cmdId) : baseCfg(cmdId){};
|
|
||||||
|
|
||||||
CfgBase baseCfg;
|
|
||||||
//! This can be used if a command can trigger multiple replies
|
|
||||||
std::pair<bool, DeviceCommandId_t> alternativeReply = {false, DeviceHandlerIF::NO_COMMAND_ID};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Configuration class for replies
|
|
||||||
*/
|
|
||||||
struct ReplyCfg {
|
|
||||||
public:
|
|
||||||
ReplyCfg(DeviceCommandId_t replyId, uint16_t maxDelayCycles)
|
|
||||||
: baseCfg(replyId), maxDelayCycles(maxDelayCycles){};
|
|
||||||
ReplyCfg(DeviceCommandId_t replyId, uint16_t maxDelayCycles, LocalPoolDataSetBase* set)
|
|
||||||
: ReplyCfg(replyId, maxDelayCycles) {
|
|
||||||
dataSet = set;
|
|
||||||
};
|
|
||||||
|
|
||||||
CfgBase baseCfg;
|
|
||||||
//! A data set can be mapped to a reply ID. This allows to omit the #getDataSetHandle
|
|
||||||
//! override in a user device handler as this pointer will be passed as long as the device
|
|
||||||
//! command ID is equal to the set ID.
|
|
||||||
LocalPoolDataSetBase* dataSet = nullptr;
|
|
||||||
//! For Command-Reply combinations:
|
|
||||||
//! The maximum number of cycles the handler should wait for a reply
|
|
||||||
//! to this command.
|
|
||||||
//!
|
|
||||||
//! Reply Only:
|
|
||||||
//! For periodic replies, this variable will be the number of delay cycles between the replies.
|
|
||||||
//! For the non-periodic variant, this variable is not used as there is no meaningful
|
|
||||||
//! definition for delay
|
|
||||||
uint16_t maxDelayCycles = 0;
|
|
||||||
//! First parameter: Specify whether reply is arriving periodically
|
|
||||||
//! Second parameter: Specify whether periodic reply should be enabled immediately
|
|
||||||
std::pair<bool, bool> periodicCfg = {false, false};
|
|
||||||
//! If a reply needs to be requested with a specific length, the length can be specified here
|
|
||||||
size_t replyLen = 0;
|
|
||||||
//! It is also possible to use a time based instead of a cycle based mechanism to specify
|
|
||||||
//! how long a reply takes. For non-periodic replies without a command, this variable is not used.
|
|
||||||
Countdown* countdown = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Configuration class for commands and replies
|
|
||||||
*/
|
|
||||||
struct CmdReplyCfg {
|
|
||||||
public:
|
|
||||||
CmdReplyCfg(CmdCfg cmdCfg, ReplyCfg replyCfg) : cmdCfg(cmdCfg), replyCfg(replyCfg) {}
|
|
||||||
CmdCfg cmdCfg;
|
|
||||||
ReplyCfg replyCfg;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* FSFW_SRC_FSFW_DEVICEHANDLERS_DHBCFGHELPERS_H_ */
|
|
@ -8,9 +8,7 @@ HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue
|
|||||||
parentQueue(parentQueue),
|
parentQueue(parentQueue),
|
||||||
commandQueue(),
|
commandQueue(),
|
||||||
healthHelper(this, setObjectId) {
|
healthHelper(this, setObjectId) {
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
commandQueue = QueueFactory::instance()->createMessageQueue(3);
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||||
|
@ -18,9 +18,8 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
|
|||||||
EventManager::EventManager(object_id_t setObjectId)
|
EventManager::EventManager(object_id_t setObjectId)
|
||||||
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
|
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE,
|
||||||
eventReportQueue = QueueFactory::instance()->createMessageQueue(
|
EventMessage::EVENT_MESSAGE_SIZE);
|
||||||
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EventManager::~EventManager() {
|
EventManager::~EventManager() {
|
||||||
@ -47,20 +46,9 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
|
|||||||
|
|
||||||
void EventManager::notifyListeners(EventMessage* message) {
|
void EventManager::notifyListeners(EventMessage* message) {
|
||||||
lockMutex();
|
lockMutex();
|
||||||
for (auto& listener : listenerList) {
|
for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) {
|
||||||
if (listener.second.match(message)) {
|
if (iter->second.match(message)) {
|
||||||
ReturnValue_t result =
|
MessageQueueSenderIF::sendMessage(iter->first, message, message->getSender());
|
||||||
MessageQueueSenderIF::sendMessage(listener.first, message, message->getSender());
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
|
|
||||||
<< std::setw(8) << listener.first << " failed with result 0x" << std::setw(4)
|
|
||||||
<< result << std::setfill(' ') << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
|
|
||||||
listener.first, result);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unlockMutex();
|
unlockMutex();
|
||||||
@ -201,19 +189,4 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage* messag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventManager::printListeners() {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::info << "Event manager listener MQ IDs:" << std::setfill('0') << std::hex << std::endl;
|
|
||||||
for (auto& listener : listenerList) {
|
|
||||||
sif::info << "0x" << std::setw(8) << listener.first << std::endl;
|
|
||||||
}
|
|
||||||
sif::info << std::dec << std::setfill(' ');
|
|
||||||
#else
|
|
||||||
sif::printInfo("Event manager listener MQ IDs:\n");
|
|
||||||
for (auto& listener : listenerList) {
|
|
||||||
sif::printInfo("0x%08x\n", listener.first);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */
|
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */
|
||||||
|
@ -42,7 +42,6 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
|
|||||||
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
|
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
|
||||||
bool reporterInverted = false);
|
bool reporterInverted = false);
|
||||||
ReturnValue_t performOperation(uint8_t opCode);
|
ReturnValue_t performOperation(uint8_t opCode);
|
||||||
void printListeners();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MessageQueueIF* eventReportQueue = nullptr;
|
MessageQueueIF* eventReportQueue = nullptr;
|
||||||
|
@ -9,9 +9,8 @@
|
|||||||
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent,
|
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent,
|
||||||
uint8_t messageDepth, uint8_t parameterDomainBase)
|
uint8_t messageDepth, uint8_t parameterDomainBase)
|
||||||
: ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
|
: ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
|
||||||
auto mqArgs = MqArgs(owner, static_cast<void*>(this));
|
eventQueue =
|
||||||
eventQueue = QueueFactory::instance()->createMessageQueue(
|
QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE);
|
||||||
messageDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FailureIsolationBase::~FailureIsolationBase() {
|
FailureIsolationBase::~FailureIsolationBase() {
|
||||||
@ -52,12 +51,11 @@ ReturnValue_t FailureIsolationBase::initialize() {
|
|||||||
ObjectManager::instance()->get<ConfirmsFailuresIF>(faultTreeParent);
|
ObjectManager::instance()->get<ConfirmsFailuresIF>(faultTreeParent);
|
||||||
if (parentIF == nullptr) {
|
if (parentIF == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "FailureIsolationBase::intialize: Parent object "
|
sif::error << "FailureIsolationBase::intialize: Parent object"
|
||||||
<< "invalid" << std::endl;
|
<< "invalid." << std::endl;
|
||||||
sif::error << "Make sure it implements ConfirmsFailuresIF" << std::endl;
|
#endif
|
||||||
#else
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::printError("FailureIsolationBase::intialize: Parent object invalid\n");
|
sif::error << "Make sure it implements ConfirmsFailuresIF." << std::endl;
|
||||||
sif::printError("Make sure it implements ConfirmsFailuresIF\n");
|
|
||||||
#endif
|
#endif
|
||||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
|
@ -14,12 +14,13 @@ class FailureIsolationBase : public HasReturnvaluesIF,
|
|||||||
public HasParametersIF {
|
public HasParametersIF {
|
||||||
public:
|
public:
|
||||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
|
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
|
||||||
//! FDIR has an internal state, which changed from par2 (oldState) to par1 (newState).
|
static const Event FDIR_CHANGED_STATE =
|
||||||
static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, severity::INFO);
|
MAKE_EVENT(1, severity::INFO); //!< FDIR has an internal state, which changed from par2
|
||||||
//! FDIR tries to restart device. Par1: event that caused recovery.
|
//!< (oldState) to par1 (newState).
|
||||||
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, severity::MEDIUM);
|
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(
|
||||||
//! FDIR turns off device. Par1: event that caused recovery.
|
2, severity::MEDIUM); //!< FDIR tries to restart device. Par1: event that caused recovery.
|
||||||
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, severity::MEDIUM);
|
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(
|
||||||
|
3, severity::MEDIUM); //!< FDIR turns off device. Par1: event that caused recovery.
|
||||||
|
|
||||||
FailureIsolationBase(object_id_t owner, object_id_t parent = objects::NO_OBJECT,
|
FailureIsolationBase(object_id_t owner, object_id_t parent = objects::NO_OBJECT,
|
||||||
uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0);
|
uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0);
|
||||||
|
@ -4,7 +4,6 @@ target_sources(
|
|||||||
AsciiConverter.cpp
|
AsciiConverter.cpp
|
||||||
CRC.cpp
|
CRC.cpp
|
||||||
DleEncoder.cpp
|
DleEncoder.cpp
|
||||||
DleParser.cpp
|
|
||||||
PeriodicOperationDivider.cpp
|
PeriodicOperationDivider.cpp
|
||||||
timevalOperations.cpp
|
timevalOperations.cpp
|
||||||
Type.cpp
|
Type.cpp
|
||||||
|
@ -1,230 +0,0 @@
|
|||||||
#include "DleParser.h"
|
|
||||||
|
|
||||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
DleParser::DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
|
|
||||||
BufPair decodedBuf, UserHandler handler, void* args)
|
|
||||||
: decodeRingBuf(decodeRingBuf),
|
|
||||||
decoder(decoder),
|
|
||||||
encodedBuf(encodedBuf),
|
|
||||||
decodedBuf(decodedBuf),
|
|
||||||
handler(handler),
|
|
||||||
ctx(args) {
|
|
||||||
if (handler == nullptr) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "DleParser::DleParser: Invalid user handler" << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printError("DleParser::DleParser: Invalid user handler\n");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t DleParser::passData(uint8_t* data, size_t len) {
|
|
||||||
if (data == nullptr or len == 0 or handler == nullptr) {
|
|
||||||
return RETURN_FAILED;
|
|
||||||
}
|
|
||||||
size_t copyIntoRingBufFromHere = 0;
|
|
||||||
size_t copyAmount = len;
|
|
||||||
size_t startIdx = 0;
|
|
||||||
ReturnValue_t result = RETURN_OK;
|
|
||||||
bool startFoundInThisPacket = false;
|
|
||||||
for (size_t idx = 0; idx < len; idx++) {
|
|
||||||
if (data[idx] == DleEncoder::STX_CHAR) {
|
|
||||||
if (not startFound and not startFoundInThisPacket) {
|
|
||||||
startIdx = idx;
|
|
||||||
copyIntoRingBufFromHere = idx;
|
|
||||||
copyAmount = len - idx;
|
|
||||||
} else {
|
|
||||||
// Maybe print warning, should not happen
|
|
||||||
decodeRingBuf.clear();
|
|
||||||
ErrorInfo info;
|
|
||||||
info.len = idx;
|
|
||||||
prepareErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info);
|
|
||||||
handler(ctx);
|
|
||||||
copyIntoRingBufFromHere = idx;
|
|
||||||
copyAmount = len - idx;
|
|
||||||
}
|
|
||||||
startFound = true;
|
|
||||||
startFoundInThisPacket = true;
|
|
||||||
} else if (data[idx] == DleEncoder::ETX_CHAR) {
|
|
||||||
if (startFoundInThisPacket) {
|
|
||||||
size_t readLen = 0;
|
|
||||||
size_t decodedLen = 0;
|
|
||||||
result = decoder.decode(data + startIdx, idx + 1 - startIdx, &readLen, decodedBuf.first,
|
|
||||||
decodedBuf.second, &decodedLen);
|
|
||||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
ctx.setType(ContextType::PACKET_FOUND);
|
|
||||||
ctx.decodedPacket.first = decodedBuf.first;
|
|
||||||
ctx.decodedPacket.second = decodedLen;
|
|
||||||
this->handler(ctx);
|
|
||||||
} else if (result == DleEncoder::STREAM_TOO_SHORT) {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.res = result;
|
|
||||||
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
|
||||||
handler(ctx);
|
|
||||||
} else {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.res = result;
|
|
||||||
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
|
||||||
handler(ctx);
|
|
||||||
}
|
|
||||||
decodeRingBuf.clear();
|
|
||||||
if ((idx + 1) < len) {
|
|
||||||
copyIntoRingBufFromHere = idx + 1;
|
|
||||||
copyAmount = len - idx - 1;
|
|
||||||
} else {
|
|
||||||
copyAmount = 0;
|
|
||||||
}
|
|
||||||
} else if (startFound) {
|
|
||||||
// ETX found but STX was found in another mini packet. Reconstruct the full packet
|
|
||||||
// to decode it
|
|
||||||
result = decodeRingBuf.writeData(data, idx + 1);
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.res = result;
|
|
||||||
prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
|
|
||||||
handler(ctx);
|
|
||||||
}
|
|
||||||
size_t fullEncodedLen = decodeRingBuf.getAvailableReadData();
|
|
||||||
if (fullEncodedLen > encodedBuf.second) {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.len = fullEncodedLen;
|
|
||||||
prepareErrorContext(ErrorTypes::ENCODED_BUF_TOO_SMALL, info);
|
|
||||||
handler(ctx);
|
|
||||||
decodeRingBuf.clear();
|
|
||||||
} else {
|
|
||||||
size_t decodedLen = 0;
|
|
||||||
size_t readLen = 0;
|
|
||||||
decodeRingBuf.readData(encodedBuf.first, fullEncodedLen, true);
|
|
||||||
result = decoder.decode(encodedBuf.first, fullEncodedLen, &readLen, decodedBuf.first,
|
|
||||||
decodedBuf.second, &decodedLen);
|
|
||||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
if (this->handler != nullptr) {
|
|
||||||
ctx.setType(ContextType::PACKET_FOUND);
|
|
||||||
ctx.decodedPacket.first = decodedBuf.first;
|
|
||||||
ctx.decodedPacket.second = decodedLen;
|
|
||||||
this->handler(ctx);
|
|
||||||
}
|
|
||||||
} else if (result == DleEncoder::STREAM_TOO_SHORT) {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.res = result;
|
|
||||||
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
|
||||||
handler(ctx);
|
|
||||||
} else {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.res = result;
|
|
||||||
prepareErrorContext(ErrorTypes::DECODE_ERROR, info);
|
|
||||||
handler(ctx);
|
|
||||||
}
|
|
||||||
decodeRingBuf.clear();
|
|
||||||
startFound = false;
|
|
||||||
startFoundInThisPacket = false;
|
|
||||||
if ((idx + 1) < len) {
|
|
||||||
copyIntoRingBufFromHere = idx + 1;
|
|
||||||
copyAmount = len - idx - 1;
|
|
||||||
} else {
|
|
||||||
copyAmount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// End data without preceeding STX
|
|
||||||
ErrorInfo info;
|
|
||||||
info.len = idx + 1;
|
|
||||||
prepareErrorContext(ErrorTypes::CONSECUTIVE_ETX_CHARS, info);
|
|
||||||
handler(ctx);
|
|
||||||
decodeRingBuf.clear();
|
|
||||||
if ((idx + 1) < len) {
|
|
||||||
copyIntoRingBufFromHere = idx + 1;
|
|
||||||
copyAmount = len - idx - 1;
|
|
||||||
} else {
|
|
||||||
copyAmount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
startFoundInThisPacket = false;
|
|
||||||
startFound = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (copyAmount > 0) {
|
|
||||||
result = decodeRingBuf.writeData(data + copyIntoRingBufFromHere, copyAmount);
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
ErrorInfo info;
|
|
||||||
info.res = result;
|
|
||||||
prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
|
|
||||||
handler(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DleParser::defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args) {
|
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::info << "DleParserBase::handleFoundPacket: Detected DLE packet with " << len << " bytes"
|
|
||||||
<< std::endl;
|
|
||||||
#else
|
|
||||||
sif::printInfo("DleParserBase::handleFoundPacket: Detected DLE packet with %d bytes\n", len);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void DleParser::defaultErrorHandler(ErrorTypes err, ErrorInfo ctx) {
|
|
||||||
switch (err) {
|
|
||||||
case (ErrorTypes::NONE): {
|
|
||||||
errorPrinter("No error");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (ErrorTypes::DECODE_ERROR): {
|
|
||||||
errorPrinter("Decode Error");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (ErrorTypes::RING_BUF_ERROR): {
|
|
||||||
errorPrinter("Ring Buffer Error");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (ErrorTypes::ENCODED_BUF_TOO_SMALL):
|
|
||||||
case (ErrorTypes::DECODING_BUF_TOO_SMALL): {
|
|
||||||
char opt[64];
|
|
||||||
snprintf(opt, sizeof(opt), ": Too small for packet with length %zu", ctx.len);
|
|
||||||
if (err == ErrorTypes::ENCODED_BUF_TOO_SMALL) {
|
|
||||||
errorPrinter("Encoded buf too small", opt);
|
|
||||||
} else {
|
|
||||||
errorPrinter("Decoding buf too small", opt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (ErrorTypes::CONSECUTIVE_STX_CHARS): {
|
|
||||||
errorPrinter("Consecutive STX chars detected");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (ErrorTypes::CONSECUTIVE_ETX_CHARS): {
|
|
||||||
errorPrinter("Consecutive ETX chars detected");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DleParser::errorPrinter(const char* str, const char* opt) {
|
|
||||||
if (opt == nullptr) {
|
|
||||||
opt = "";
|
|
||||||
}
|
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::info << "DleParserBase::handleParseError: " << str << opt << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printInfo("DleParserBase::handleParseError: %s%s\n", str, opt);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void DleParser::prepareErrorContext(ErrorTypes err, ErrorInfo info) {
|
|
||||||
ctx.setType(ContextType::ERROR);
|
|
||||||
ctx.error.first = err;
|
|
||||||
ctx.error.second = info;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DleParser::reset() {
|
|
||||||
startFound = false;
|
|
||||||
decodeRingBuf.clear();
|
|
||||||
}
|
|
@ -1,124 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <fsfw/container/SimpleRingBuffer.h>
|
|
||||||
#include <fsfw/globalfunctions/DleEncoder.h>
|
|
||||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This base helper class can be used to extract DLE encoded packets from a data stream
|
|
||||||
* @details
|
|
||||||
* The core API of the parser takes received packets which can contains DLE packets. The parser
|
|
||||||
* can deal with DLE packets split across multiple packets. It does so by using a dedicated
|
|
||||||
* decoding ring buffer. The user can process received packets and detect errors by
|
|
||||||
* overriding two provided virtual methods. This also allows detecting multiple DLE packets
|
|
||||||
* inside one passed packet.
|
|
||||||
*/
|
|
||||||
class DleParser : public HasReturnvaluesIF {
|
|
||||||
public:
|
|
||||||
using BufPair = std::pair<uint8_t*, size_t>;
|
|
||||||
|
|
||||||
enum class ContextType { PACKET_FOUND, ERROR };
|
|
||||||
|
|
||||||
enum class ErrorTypes {
|
|
||||||
NONE,
|
|
||||||
ENCODED_BUF_TOO_SMALL,
|
|
||||||
DECODING_BUF_TOO_SMALL,
|
|
||||||
DECODE_ERROR,
|
|
||||||
RING_BUF_ERROR,
|
|
||||||
CONSECUTIVE_STX_CHARS,
|
|
||||||
CONSECUTIVE_ETX_CHARS
|
|
||||||
};
|
|
||||||
|
|
||||||
union ErrorInfo {
|
|
||||||
size_t len;
|
|
||||||
ReturnValue_t res;
|
|
||||||
};
|
|
||||||
|
|
||||||
using ErrorPair = std::pair<ErrorTypes, ErrorInfo>;
|
|
||||||
|
|
||||||
struct Context {
|
|
||||||
public:
|
|
||||||
Context(void* args) : userArgs(args) { setType(ContextType::PACKET_FOUND); }
|
|
||||||
|
|
||||||
void setType(ContextType type) {
|
|
||||||
if (type == ContextType::PACKET_FOUND) {
|
|
||||||
error.first = ErrorTypes::NONE;
|
|
||||||
error.second.len = 0;
|
|
||||||
} else {
|
|
||||||
decodedPacket.first = nullptr;
|
|
||||||
decodedPacket.second = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ContextType getType() const { return type; }
|
|
||||||
|
|
||||||
BufPair decodedPacket = {};
|
|
||||||
ErrorPair error;
|
|
||||||
void* userArgs;
|
|
||||||
|
|
||||||
private:
|
|
||||||
ContextType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
using UserHandler = void (*)(const Context& ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class constructor
|
|
||||||
* @param decodeRingBuf Ring buffer used to store multiple packets to allow detecting DLE packets
|
|
||||||
* split across multiple packets
|
|
||||||
* @param decoder Decoder instance
|
|
||||||
* @param encodedBuf Buffer used to store encoded packets. It has to be large enough to hold
|
|
||||||
* the largest expected encoded DLE packet size
|
|
||||||
* @param decodedBuf Buffer used to store decoded packets. It has to be large enough to hold the
|
|
||||||
* largest expected decoded DLE packet size
|
|
||||||
* @param handler Function which will be called on a found packet
|
|
||||||
* @param args Arbitrary user argument
|
|
||||||
*/
|
|
||||||
DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
|
|
||||||
BufPair decodedBuf, UserHandler handler, void* args);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function allows to pass new data into the parser. It then scans for DLE packets
|
|
||||||
* automatically and inserts (part of) the packet into a ring buffer if necessary.
|
|
||||||
* @param data
|
|
||||||
* @param len
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
ReturnValue_t passData(uint8_t* data, size_t len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example found packet handler
|
|
||||||
* function call
|
|
||||||
* @param packet Decoded packet
|
|
||||||
* @param len Length of detected packet
|
|
||||||
*/
|
|
||||||
void defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args);
|
|
||||||
/**
|
|
||||||
* Will be called if an error occured in the #passData call
|
|
||||||
* @param err
|
|
||||||
* @param ctx Context information depending on the error type
|
|
||||||
* - For buffer length errors, will be set to the detected packet length which is too large
|
|
||||||
* - For decode or ring buffer errors, will be set to the result returned from the failed call
|
|
||||||
*/
|
|
||||||
static void defaultErrorHandler(ErrorTypes err, ErrorInfo ctx);
|
|
||||||
|
|
||||||
static void errorPrinter(const char* str, const char* opt = nullptr);
|
|
||||||
|
|
||||||
void prepareErrorContext(ErrorTypes err, ErrorInfo ctx);
|
|
||||||
/**
|
|
||||||
* Resets the parser by resetting the internal states and clearing the decoding ring buffer
|
|
||||||
*/
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
private:
|
|
||||||
SimpleRingBuffer& decodeRingBuf;
|
|
||||||
DleEncoder& decoder;
|
|
||||||
BufPair encodedBuf;
|
|
||||||
BufPair decodedBuf;
|
|
||||||
UserHandler handler = nullptr;
|
|
||||||
Context ctx;
|
|
||||||
bool startFound = false;
|
|
||||||
};
|
|
@ -16,27 +16,26 @@ class HasHealthIF {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
|
||||||
static constexpr ReturnValue_t OBJECT_NOT_HEALTHY =
|
static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1);
|
||||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 1);
|
static const ReturnValue_t INVALID_HEALTH_STATE = MAKE_RETURN_CODE(2);
|
||||||
static constexpr ReturnValue_t INVALID_HEALTH_STATE =
|
|
||||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 2);
|
|
||||||
static constexpr ReturnValue_t IS_EXTERNALLY_CONTROLLED =
|
|
||||||
HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 3);
|
|
||||||
|
|
||||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1;
|
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1;
|
||||||
//! P1: New Health, P2: Old Health
|
|
||||||
static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
|
static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
|
||||||
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
|
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
|
||||||
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
|
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
|
||||||
//! Assembly overwrites health information of children to keep satellite alive.
|
static const Event OVERWRITING_HEALTH =
|
||||||
static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW);
|
MAKE_EVENT(9, severity::LOW); //!< Assembly overwrites health information of children to keep
|
||||||
//! Someone starts a recovery of a component (typically power-cycle). No parameters.
|
//!< satellite alive.
|
||||||
static const Event TRYING_RECOVERY = MAKE_EVENT(10, severity::MEDIUM);
|
static const Event TRYING_RECOVERY =
|
||||||
//! Recovery is ongoing. Comes twice during recovery.
|
MAKE_EVENT(10, severity::MEDIUM); //!< Someone starts a recovery of a component (typically
|
||||||
//! P1: 0 for the first, 1 for the second event. P2: 0
|
//!< power-cycle). No parameters.
|
||||||
static const Event RECOVERY_STEP = MAKE_EVENT(11, severity::MEDIUM);
|
static const Event RECOVERY_STEP =
|
||||||
//! Recovery was completed. Not necessarily successful. No parameters.
|
MAKE_EVENT(11, severity::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1:
|
||||||
static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM);
|
//!< 0 for the first, 1 for the second event. P2: 0
|
||||||
|
static const Event RECOVERY_DONE = MAKE_EVENT(
|
||||||
|
12,
|
||||||
|
severity::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters.
|
||||||
|
|
||||||
virtual ~HasHealthIF() {}
|
virtual ~HasHealthIF() {}
|
||||||
|
|
||||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||||
|
@ -7,13 +7,11 @@
|
|||||||
|
|
||||||
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
|
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
|
||||||
: SystemObject(setObjectId),
|
: SystemObject(setObjectId),
|
||||||
|
commandQueue(QueueFactory::instance()->createMessageQueue(messageQueueDepth)),
|
||||||
poolManager(this, commandQueue),
|
poolManager(this, commandQueue),
|
||||||
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
||||||
internalErrorDataset(this) {
|
internalErrorDataset(this) {
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void *>(this));
|
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
|
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
|
||||||
@ -38,14 +36,15 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
|
|||||||
if ((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
|
if ((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::debug << "InternalErrorReporter::performOperation: Errors "
|
sif::debug << "InternalErrorReporter::performOperation: Errors "
|
||||||
<< "occured: Queue | TM | Store : " << newQueueHits << " | " << newTmHits << " | "
|
<< "occured!" << std::endl;
|
||||||
<< newStoreHits << std::endl;
|
sif::debug << "Queue errors: " << newQueueHits << std::endl;
|
||||||
|
sif::debug << "TM errors: " << newTmHits << std::endl;
|
||||||
|
sif::debug << "Store errors: " << newStoreHits << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printDebug(
|
sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n");
|
||||||
"InternalErrorReporter::performOperation: Errors occured: Queue | TM | Store: %lu | %lu "
|
sif::printDebug("Queue errors: %lu\n", static_cast<unsigned int>(newQueueHits));
|
||||||
"| %lu\n",
|
sif::printDebug("TM errors: %lu\n", static_cast<unsigned int>(newTmHits));
|
||||||
static_cast<unsigned int>(newQueueHits), static_cast<unsigned int>(newTmHits),
|
sif::printDebug("Store errors: %lu\n", static_cast<unsigned int>(newStoreHits));
|
||||||
static_cast<unsigned int>(newStoreHits));
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ class CommandMessageIF {
|
|||||||
static const Command_t CMD_NONE = MAKE_COMMAND_ID(0);
|
static const Command_t CMD_NONE = MAKE_COMMAND_ID(0);
|
||||||
static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID(1);
|
static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID(1);
|
||||||
//! Reply indicating that the current command was rejected,
|
//! Reply indicating that the current command was rejected,
|
||||||
//! Parameter 1 should contain the error code
|
//! par1 should contain the error code
|
||||||
static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID(2);
|
static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID(2);
|
||||||
|
|
||||||
virtual ~CommandMessageIF(){};
|
virtual ~CommandMessageIF(){};
|
||||||
|
@ -19,33 +19,32 @@ class HasModesIF {
|
|||||||
static const ReturnValue_t INVALID_SUBMODE = MAKE_RETURN_CODE(0x04);
|
static const ReturnValue_t INVALID_SUBMODE = MAKE_RETURN_CODE(0x04);
|
||||||
|
|
||||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER;
|
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER;
|
||||||
//! An object announces changing the mode. p1: target mode. p2: target submode
|
static const Event CHANGING_MODE =
|
||||||
static const Event CHANGING_MODE = MAKE_EVENT(0, severity::INFO);
|
MAKE_EVENT(0, severity::INFO); //!< An object announces changing the mode. p1: target mode.
|
||||||
//! An Object announces its mode; parameter1 is mode, parameter2 is submode
|
//!< p2: target submode
|
||||||
static const Event MODE_INFO = MAKE_EVENT(1, severity::INFO);
|
static const Event MODE_INFO = MAKE_EVENT(
|
||||||
|
1,
|
||||||
|
severity::INFO); //!< An Object announces its mode; parameter1 is mode, parameter2 is submode
|
||||||
static const Event FALLBACK_FAILED = MAKE_EVENT(2, severity::HIGH);
|
static const Event FALLBACK_FAILED = MAKE_EVENT(2, severity::HIGH);
|
||||||
static const Event MODE_TRANSITION_FAILED = MAKE_EVENT(3, severity::LOW);
|
static const Event MODE_TRANSITION_FAILED = MAKE_EVENT(3, severity::LOW);
|
||||||
static const Event CANT_KEEP_MODE = MAKE_EVENT(4, severity::HIGH);
|
static const Event CANT_KEEP_MODE = MAKE_EVENT(4, severity::HIGH);
|
||||||
//! Indicates a bug or configuration failure: Object is in a mode it should never be in.
|
static const Event OBJECT_IN_INVALID_MODE =
|
||||||
static const Event OBJECT_IN_INVALID_MODE = MAKE_EVENT(5, severity::LOW);
|
MAKE_EVENT(5, severity::LOW); //!< Indicates a bug or configuration failure: Object is in a
|
||||||
//! The mode is changed, but for some reason, the change is forced, i.e. EXTERNAL_CONTROL ignored.
|
//!< mode it should never be in.
|
||||||
//! p1: target mode. p2: target submode
|
static const Event FORCING_MODE = MAKE_EVENT(
|
||||||
static const Event FORCING_MODE = MAKE_EVENT(6, severity::MEDIUM);
|
6, severity::MEDIUM); //!< The mode is changed, but for some reason, the change is forced,
|
||||||
//! A mode command was rejected by the called object. Par1: called object id, Par2: return code.
|
//!< i.e. EXTERNAL_CONTROL ignored. p1: target mode. p2: target submode
|
||||||
static const Event MODE_CMD_REJECTED = MAKE_EVENT(7, severity::LOW);
|
static const Event MODE_CMD_REJECTED =
|
||||||
|
MAKE_EVENT(7, severity::LOW); //!< A mode command was rejected by the called object. Par1:
|
||||||
|
//!< called object id, Par2: return code.
|
||||||
|
|
||||||
//! The device is powered and ready to perform operations. In this mode, no commands are
|
static const Mode_t MODE_ON =
|
||||||
//! sent by the device handler itself, but direct commands van be commanded and will be
|
1; //!< The device is powered and ready to perform operations. In this mode, no commands are
|
||||||
//! interpreted
|
//!< sent by the device handler itself, but direct commands van be commanded and will be
|
||||||
static constexpr Mode_t MODE_ON = 1;
|
//!< interpreted
|
||||||
//! The device is powered off. The only command accepted in this mode is a mode change to on.
|
static const Mode_t MODE_OFF = 0; //!< The device is powered off. The only command accepted in
|
||||||
static constexpr Mode_t MODE_OFF = 0;
|
//!< this mode is a mode change to on.
|
||||||
|
static const Submode_t SUBMODE_NONE = 0; //!< To avoid checks against magic number "0".
|
||||||
static constexpr Mode_t MODE_INVALID = -1;
|
|
||||||
static constexpr Mode_t MODE_UNDEFINED = -2;
|
|
||||||
|
|
||||||
//! To avoid checks against magic number "0".
|
|
||||||
static const Submode_t SUBMODE_NONE = 0;
|
|
||||||
|
|
||||||
virtual ~HasModesIF() {}
|
virtual ~HasModesIF() {}
|
||||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||||
|
@ -95,16 +95,13 @@ void ObjectManager::initialize() {
|
|||||||
for (auto const& it : objectList) {
|
for (auto const& it : objectList) {
|
||||||
result = it.second->initialize();
|
result = it.second->initialize();
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
object_id_t var = it.first;
|
||||||
sif::error << "ObjectManager::initialize: Object 0x" << std::hex << std::setw(8)
|
sif::error << "ObjectManager::initialize: Object 0x" << std::hex << std::setw(8)
|
||||||
<< std::setfill('0') << it.first << " failed to initialize with code 0x" << result
|
<< std::setfill('0') << var
|
||||||
<< std::dec << std::setfill(' ') << std::endl;
|
<< " failed to "
|
||||||
#else
|
"initialize with code 0x"
|
||||||
sif::printError(
|
<< result << std::dec << std::setfill(' ') << std::endl;
|
||||||
"ObjectManager::initialize: Object 0x%08x failed to initialize with code 0x%04x\n", var,
|
|
||||||
it.first);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
errorCount++;
|
errorCount++;
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,7 @@ elseif(FSFW_OSAL MATCHES "host")
|
|||||||
|
|
||||||
else()
|
else()
|
||||||
|
|
||||||
message(
|
message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
|
||||||
WARNING
|
|
||||||
"${MSG_PREFIX} The FSFW_OSAL variable was not set. Assuming host OS..")
|
|
||||||
# Not set. Assumuing this is a host build, try to determine host OS
|
# Not set. Assumuing this is a host build, try to determine host OS
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_subdirectory(host)
|
add_subdirectory(host)
|
||||||
|
@ -66,7 +66,7 @@ class HasParametersIF {
|
|||||||
* @param newValues
|
* @param newValues
|
||||||
* @param startAtIndex Linear index, runs left to right, top to bottom for
|
* @param startAtIndex Linear index, runs left to right, top to bottom for
|
||||||
* matrix indexes.
|
* matrix indexes.
|
||||||
* @return RETURN_OK if parameter is valid and a set function of the parameter wrapper was called.
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper,
|
||||||
|
@ -211,13 +211,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
|||||||
if (data == nullptr) {
|
if (data == nullptr) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable or "
|
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable!" << std::endl;
|
||||||
"data pointer not set"
|
|
||||||
<< std::endl;
|
|
||||||
#else
|
#else
|
||||||
sif::printWarning(
|
sif::printWarning("ParameterWrapper::copyFrom: Called on read-only variable!\n");
|
||||||
"ParameterWrapper::copyFrom: Called on read-only variable "
|
|
||||||
"or data pointer not set\n");
|
|
||||||
#endif
|
#endif
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return READONLY;
|
return READONLY;
|
||||||
@ -226,9 +222,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
|||||||
if (from->readonlyData == nullptr) {
|
if (from->readonlyData == nullptr) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "ParameterWrapper::copyFrom: Source not set" << std::endl;
|
sif::warning << "ParameterWrapper::copyFrom: Source not set!" << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning("ParameterWrapper::copyFrom: Source not set\n");
|
sif::printWarning("ParameterWrapper::copyFrom: Source not set!\n");
|
||||||
#endif
|
#endif
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return SOURCE_NOT_SET;
|
return SOURCE_NOT_SET;
|
||||||
@ -237,9 +233,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
|||||||
if (type != from->type) {
|
if (type != from->type) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch" << std::endl;
|
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch!" << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch\n");
|
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch!\n");
|
||||||
#endif
|
#endif
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return DATATYPE_MISSMATCH;
|
return DATATYPE_MISSMATCH;
|
||||||
@ -249,9 +245,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
|||||||
if (rows == 0 or columns == 0) {
|
if (rows == 0 or columns == 0) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero" << std::endl;
|
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero!" << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero\n");
|
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero!\n");
|
||||||
#endif
|
#endif
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return COLUMN_OR_ROWS_ZERO;
|
return COLUMN_OR_ROWS_ZERO;
|
||||||
|
@ -29,9 +29,9 @@ class PowerSwitchIF : public HasReturnvaluesIF {
|
|||||||
static const ReturnValue_t FUSE_ON = MAKE_RETURN_CODE(3);
|
static const ReturnValue_t FUSE_ON = MAKE_RETURN_CODE(3);
|
||||||
static const ReturnValue_t FUSE_OFF = MAKE_RETURN_CODE(4);
|
static const ReturnValue_t FUSE_OFF = MAKE_RETURN_CODE(4);
|
||||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_2;
|
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_2;
|
||||||
//!< Someone detected that a switch went off which shouldn't. Severity:
|
static const Event SWITCH_WENT_OFF = MAKE_EVENT(
|
||||||
//!< Low, Parameter1: switchId1, Parameter2: switchId2
|
0, severity::LOW); //!< Someone detected that a switch went off which shouldn't. Severity:
|
||||||
static const Event SWITCH_WENT_OFF = MAKE_EVENT(0, severity::LOW);
|
//!< Low, Parameter1: switchId1, Parameter2: switchId2
|
||||||
/**
|
/**
|
||||||
* send a direct command to the Power Unit to enable/disable the specified switch.
|
* send a direct command to the Power Unit to enable/disable the specified switch.
|
||||||
*
|
*
|
||||||
|
@ -78,7 +78,7 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::performService
|
|||||||
// NOTE: The iterator is increased in the loop here. Increasing the iterator as for-loop arg
|
// NOTE: The iterator is increased in the loop here. Increasing the iterator as for-loop arg
|
||||||
// does not work in this case as we are deleting the current element here.
|
// does not work in this case as we are deleting the current element here.
|
||||||
for (auto it = telecommandMap.begin(); it != telecommandMap.end();) {
|
for (auto it = telecommandMap.begin(); it != telecommandMap.end();) {
|
||||||
if (it->first <= static_cast<uint32_t>(tNow.tv_sec)) {
|
if (it->first <= tNow.tv_sec) {
|
||||||
if (schedulingEnabled) {
|
if (schedulingEnabled) {
|
||||||
// release tc
|
// release tc
|
||||||
TmTcMessage releaseMsg(it->second.storeAddr);
|
TmTcMessage releaseMsg(it->second.storeAddr);
|
||||||
|
@ -16,9 +16,7 @@ Service1TelecommandVerification::Service1TelecommandVerification(object_id_t obj
|
|||||||
apid(apid),
|
apid(apid),
|
||||||
serviceId(serviceId),
|
serviceId(serviceId),
|
||||||
targetDestination(targetDestination) {
|
targetDestination(targetDestination) {
|
||||||
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
|
tmQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
|
||||||
tmQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Service1TelecommandVerification::~Service1TelecommandVerification() {
|
Service1TelecommandVerification::~Service1TelecommandVerification() {
|
||||||
|
@ -208,17 +208,17 @@ ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply,
|
|||||||
ReturnValue_t error = HasReturnvaluesIF::RETURN_FAILED;
|
ReturnValue_t error = HasReturnvaluesIF::RETURN_FAILED;
|
||||||
HousekeepingMessage::getHkRequestFailureReply(reply, &error);
|
HousekeepingMessage::getHkRequestFailureReply(reply, &error);
|
||||||
failureParameter2 = error;
|
failureParameter2 = error;
|
||||||
return RETURN_FAILED;
|
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "Service3Housekeeping::handleReply: Invalid reply with "
|
sif::warning << "Service3Housekeeping::handleReply: Invalid reply with "
|
||||||
<< "reply command " << command << std::endl;
|
<< "reply command " << command << "!" << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning(
|
sif::printWarning(
|
||||||
"Service3Housekeeping::handleReply: Invalid reply with "
|
"Service3Housekeeping::handleReply: Invalid reply with "
|
||||||
"reply command %hu\n",
|
"reply command %hu!\n",
|
||||||
command);
|
command);
|
||||||
#endif
|
#endif
|
||||||
return CommandingServiceBase::INVALID_REPLY;
|
return CommandingServiceBase::INVALID_REPLY;
|
||||||
@ -248,25 +248,19 @@ void Service3Housekeeping::handleUnrequestedReply(CommandMessage* reply) {
|
|||||||
case (HousekeepingMessage::HK_REQUEST_FAILURE): {
|
case (HousekeepingMessage::HK_REQUEST_FAILURE): {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (CommandMessage::REPLY_REJECTED): {
|
|
||||||
sif::warning << "Service3Housekeeping::handleUnrequestedReply: Unexpected reply "
|
|
||||||
"rejected with error code"
|
|
||||||
<< reply->getParameter() << std::endl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "Service3Housekeeping::handleUnrequestedReply: Invalid reply with reply "
|
sif::warning << "Service3Housekeeping::handleUnrequestedReply: Invalid reply with reply "
|
||||||
"command "
|
"command "
|
||||||
<< command << "" << std::endl;
|
<< command << "!" << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning(
|
sif::printWarning(
|
||||||
"Service3Housekeeping::handleUnrequestedReply: Invalid reply with "
|
"Service3Housekeeping::handleUnrequestedReply: Invalid reply with "
|
||||||
"reply command %hu\n",
|
"reply command %hu!\n",
|
||||||
command);
|
command);
|
||||||
#endif
|
#endif
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +275,6 @@ void Service3Housekeeping::handleUnrequestedReply(CommandMessage* reply) {
|
|||||||
"Could not generate reply!\n");
|
"Could not generate reply!\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
CommandingServiceBase::handleUnrequestedReply(reply);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t Service3Housekeeping::getHkQueue() const { return commandQueue->getId(); }
|
MessageQueueId_t Service3Housekeeping::getHkQueue() const { return commandQueue->getId(); }
|
||||||
|
@ -12,9 +12,7 @@ Service5EventReporting::Service5EventReporting(object_id_t objectId, uint16_t ap
|
|||||||
uint32_t messageQueueDepth)
|
uint32_t messageQueueDepth)
|
||||||
: PusServiceBase(objectId, apid, serviceId),
|
: PusServiceBase(objectId, apid, serviceId),
|
||||||
maxNumberReportsPerCycle(maxNumberReportsPerCycle) {
|
maxNumberReportsPerCycle(maxNumberReportsPerCycle) {
|
||||||
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
|
eventQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
|
||||||
eventQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Service5EventReporting::~Service5EventReporting() {
|
Service5EventReporting::~Service5EventReporting() {
|
||||||
@ -38,6 +36,9 @@ ReturnValue_t Service5EventReporting::performService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "Service5EventReporting::generateEventReport: Too many events" << std::endl;
|
||||||
|
#endif
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
class Service5EventReporting : public PusServiceBase {
|
class Service5EventReporting : public PusServiceBase {
|
||||||
public:
|
public:
|
||||||
Service5EventReporting(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
Service5EventReporting(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
||||||
size_t maxNumberReportsPerCycle, uint32_t messageQueueDepth);
|
size_t maxNumberReportsPerCycle = 10, uint32_t messageQueueDepth = 10);
|
||||||
virtual ~Service5EventReporting();
|
virtual ~Service5EventReporting();
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
class Service9TimeManagement : public PusServiceBase {
|
class Service9TimeManagement : public PusServiceBase {
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
|
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
|
||||||
//!< Clock has been set. P1: New Uptime. P2: Old Uptime
|
static constexpr Event CLOCK_SET =
|
||||||
static constexpr Event CLOCK_SET = MAKE_EVENT(0, severity::INFO);
|
MAKE_EVENT(0, severity::INFO); //!< Clock has been set. P1: New Uptime. P2: Old Uptime
|
||||||
//!< Clock could not be set. P1: Returncode.
|
static constexpr Event CLOCK_SET_FAILURE =
|
||||||
static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(1, severity::LOW);
|
MAKE_EVENT(1, severity::LOW); //!< Clock could not be set. P1: Returncode.
|
||||||
|
|
||||||
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
|
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
|
||||||
|
|
||||||
|
@ -33,12 +33,8 @@ struct SequenceEntry : public TableSequenceBase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class extends the SubsystemBase to perform the management of mode tables
|
* @brief TODO: documentation missing
|
||||||
* and mode sequences
|
|
||||||
* @details
|
* @details
|
||||||
* This class is able to use mode tables and sequences to command all its children into the
|
|
||||||
* right mode. Fallback sequences can be used to handle failed transitions or have a fallback
|
|
||||||
* in case a component can't keep its current mode.
|
|
||||||
*/
|
*/
|
||||||
class Subsystem : public SubsystemBase, public HasModeSequenceIF {
|
class Subsystem : public SubsystemBase, public HasModeSequenceIF {
|
||||||
public:
|
public:
|
||||||
|
@ -8,13 +8,11 @@ SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t
|
|||||||
uint16_t commandQueueDepth)
|
uint16_t commandQueueDepth)
|
||||||
: SystemObject(setObjectId),
|
: SystemObject(setObjectId),
|
||||||
mode(initialMode),
|
mode(initialMode),
|
||||||
|
commandQueue(QueueFactory::instance()->createMessageQueue(commandQueueDepth,
|
||||||
|
CommandMessage::MAX_MESSAGE_SIZE)),
|
||||||
healthHelper(this, setObjectId),
|
healthHelper(this, setObjectId),
|
||||||
modeHelper(this),
|
modeHelper(this),
|
||||||
parentId(parent) {
|
parentId(parent) {}
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
commandQueueDepth, CommandMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||||
|
|
||||||
@ -33,9 +31,8 @@ ReturnValue_t SubsystemBase::registerChild(object_id_t objectId) {
|
|||||||
info.mode = MODE_OFF;
|
info.mode = MODE_OFF;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// intentional to force an initial command during system startup
|
|
||||||
info.commandQueue = child->getCommandQueue();
|
info.commandQueue = child->getCommandQueue();
|
||||||
info.mode = HasModesIF::MODE_UNDEFINED;
|
info.mode = -1; // intentional to force an initial command during system startup
|
||||||
}
|
}
|
||||||
|
|
||||||
info.submode = SUBMODE_NONE;
|
info.submode = SUBMODE_NONE;
|
||||||
|
@ -15,14 +15,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup subsystems Subsystem Objects
|
* @defgroup subsystems Subsystem Objects
|
||||||
* All Subsystem and Assemblies can derive from this class. It contains helper classes to
|
* Contains all Subsystem and Assemblies
|
||||||
* perform mode and health handling, which allows OBSW developers to build a mode tree for
|
|
||||||
* the whole satellite.
|
|
||||||
*
|
|
||||||
* Aside from setting up a mode tree and being able to executing mode tables, this class does not
|
|
||||||
* provide an implementation on what to do with the features. To build a mode tree, helper classes
|
|
||||||
* like the #AssemblyBase or the #Subsystem class extend and use the functionality of the base
|
|
||||||
* class.
|
|
||||||
*/
|
*/
|
||||||
class SubsystemBase : public SystemObject,
|
class SubsystemBase : public SystemObject,
|
||||||
public HasModesIF,
|
public HasModesIF,
|
||||||
@ -103,7 +96,6 @@ class SubsystemBase : public SystemObject,
|
|||||||
Submode_t targetSubmode);
|
Submode_t targetSubmode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function takes care of sending all according mode commands specified inside a mode table.
|
|
||||||
* We need to know the target Submode, as children are able to inherit the submode
|
* We need to know the target Submode, as children are able to inherit the submode
|
||||||
* Still, we have a default for all child implementations which do not use submode inheritance
|
* Still, we have a default for all child implementations which do not use submode inheritance
|
||||||
*/
|
*/
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||||
|
|
||||||
TcDistributor::TcDistributor(object_id_t objectId) : SystemObject(objectId) {
|
TcDistributor::TcDistributor(object_id_t objectId) : SystemObject(objectId) {
|
||||||
auto mqArgs = MqArgs(objectId);
|
tcQueue = QueueFactory::instance()->createMessageQueue(DISTRIBUTER_MAX_PACKETS);
|
||||||
tcQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
DISTRIBUTER_MAX_PACKETS, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TcDistributor::~TcDistributor() { QueueFactory::instance()->deleteMessageQueue(tcQueue); }
|
TcDistributor::~TcDistributor() { QueueFactory::instance()->deleteMessageQueue(tcQueue); }
|
||||||
|
@ -4,13 +4,14 @@
|
|||||||
|
|
||||||
AbstractTemperatureSensor::AbstractTemperatureSensor(object_id_t setObjectid,
|
AbstractTemperatureSensor::AbstractTemperatureSensor(object_id_t setObjectid,
|
||||||
ThermalModuleIF *thermalModule)
|
ThermalModuleIF *thermalModule)
|
||||||
: SystemObject(setObjectid), healthHelper(this, setObjectid), parameterHelper(this) {
|
: SystemObject(setObjectid),
|
||||||
if (thermalModule != nullptr) {
|
commandQueue(NULL),
|
||||||
|
healthHelper(this, setObjectid),
|
||||||
|
parameterHelper(this) {
|
||||||
|
if (thermalModule != NULL) {
|
||||||
thermalModule->registerSensor(this);
|
thermalModule->registerSensor(this);
|
||||||
}
|
}
|
||||||
auto mqArgs = MqArgs(setObjectid, static_cast<void *>(this));
|
commandQueue = QueueFactory::instance()->createMessageQueue();
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractTemperatureSensor::~AbstractTemperatureSensor() {
|
AbstractTemperatureSensor::~AbstractTemperatureSensor() {
|
||||||
|
@ -51,7 +51,7 @@ class AbstractTemperatureSensor : public HasHealthIF,
|
|||||||
HasHealthIF::HealthState getHealth();
|
HasHealthIF::HealthState getHealth();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MessageQueueIF* commandQueue = nullptr;
|
MessageQueueIF* commandQueue;
|
||||||
HealthHelper healthHelper;
|
HealthHelper healthHelper;
|
||||||
ParameterHelper parameterHelper;
|
ParameterHelper parameterHelper;
|
||||||
|
|
||||||
|
@ -12,9 +12,7 @@ Heater::Heater(uint32_t objectId, uint8_t switch0, uint8_t switch1)
|
|||||||
switch1(switch1),
|
switch1(switch1),
|
||||||
heaterOnCountdown(10800000) /*about two orbits*/,
|
heaterOnCountdown(10800000) /*about two orbits*/,
|
||||||
parameterHelper(this) {
|
parameterHelper(this) {
|
||||||
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
|
eventQueue = QueueFactory::instance()->createMessageQueue();
|
||||||
eventQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Heater::~Heater() { QueueFactory::instance()->deleteMessageQueue(eventQueue); }
|
Heater::~Heater() { QueueFactory::instance()->deleteMessageQueue(eventQueue); }
|
||||||
|
@ -13,9 +13,9 @@ class ThermalComponentIF : public HasParametersIF {
|
|||||||
static const Event COMPONENT_TEMP_HIGH = MAKE_EVENT(2, severity::LOW);
|
static const Event COMPONENT_TEMP_HIGH = MAKE_EVENT(2, severity::LOW);
|
||||||
static const Event COMPONENT_TEMP_OOL_LOW = MAKE_EVENT(3, severity::LOW);
|
static const Event COMPONENT_TEMP_OOL_LOW = MAKE_EVENT(3, severity::LOW);
|
||||||
static const Event COMPONENT_TEMP_OOL_HIGH = MAKE_EVENT(4, severity::LOW);
|
static const Event COMPONENT_TEMP_OOL_HIGH = MAKE_EVENT(4, severity::LOW);
|
||||||
//!< Is thrown when a device should start-up, but the temperature is out
|
static const Event TEMP_NOT_IN_OP_RANGE = MAKE_EVENT(
|
||||||
//!< of OP range. P1: thermalState of the component, P2: 0
|
5, severity::LOW); //!< Is thrown when a device should start-up, but the temperature is out
|
||||||
static const Event TEMP_NOT_IN_OP_RANGE = MAKE_EVENT(5, severity::LOW);
|
//!< of OP range. P1: thermalState of the component, P2: 0
|
||||||
|
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::THERMAL_COMPONENT_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::THERMAL_COMPONENT_IF;
|
||||||
static const ReturnValue_t INVALID_TARGET_STATE = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t INVALID_TARGET_STATE = MAKE_RETURN_CODE(1);
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
#include "fsfw/timemanager/Countdown.h"
|
#include "fsfw/timemanager/Countdown.h"
|
||||||
|
|
||||||
Countdown::Countdown(uint32_t initialTimeout, bool startImmediately) : timeout(initialTimeout) {
|
Countdown::Countdown(uint32_t initialTimeout) : timeout(initialTimeout) {
|
||||||
if (startImmediately) {
|
setTimeout(initialTimeout);
|
||||||
setTimeout(initialTimeout);
|
|
||||||
} else {
|
|
||||||
timeout = initialTimeout;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Countdown::~Countdown() {}
|
Countdown::~Countdown() {}
|
||||||
|
@ -26,9 +26,8 @@ class Countdown {
|
|||||||
* Otherwise a call to hasTimedOut might return True.
|
* Otherwise a call to hasTimedOut might return True.
|
||||||
*
|
*
|
||||||
* @param initialTimeout Countdown duration in milliseconds
|
* @param initialTimeout Countdown duration in milliseconds
|
||||||
* @param startImmediately Set to false if countdown should not be started immediately
|
|
||||||
*/
|
*/
|
||||||
Countdown(uint32_t initialTimeout = 0, bool startImmediately = true);
|
Countdown(uint32_t initialTimeout = 0);
|
||||||
~Countdown();
|
~Countdown();
|
||||||
/**
|
/**
|
||||||
* Call to set a new countdown duration.
|
* Call to set a new countdown duration.
|
||||||
|
@ -33,47 +33,50 @@ class TmStoreBackendIF : public HasParametersIF {
|
|||||||
static const ReturnValue_t INVALID_REQUEST = MAKE_RETURN_CODE(15);
|
static const ReturnValue_t INVALID_REQUEST = MAKE_RETURN_CODE(15);
|
||||||
|
|
||||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::MEMORY;
|
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::MEMORY;
|
||||||
//! Initiating sending data to store failed. Low, par1:
|
static const Event STORE_SEND_WRITE_FAILED =
|
||||||
//! returnCode, par2: integer (debug info)
|
MAKE_EVENT(0, severity::LOW); //!< Initiating sending data to store failed. Low, par1:
|
||||||
static const Event STORE_SEND_WRITE_FAILED = MAKE_EVENT(0, severity::LOW);
|
//!< returnCode, par2: integer (debug info)
|
||||||
//! Data was sent, but writing failed. Low, par1: returnCode, par2: 0
|
static const Event STORE_WRITE_FAILED = MAKE_EVENT(
|
||||||
static const Event STORE_WRITE_FAILED = MAKE_EVENT(1, severity::LOW);
|
1, severity::LOW); //!< Data was sent, but writing failed. Low, par1: returnCode, par2: 0
|
||||||
//! Initiating reading data from store failed. Low, par1: returnCode, par2: 0
|
static const Event STORE_SEND_READ_FAILED =
|
||||||
static const Event STORE_SEND_READ_FAILED = MAKE_EVENT(2, severity::LOW);
|
MAKE_EVENT(2, severity::LOW); //!< Initiating reading data from store failed. Low, par1:
|
||||||
//! Data was requested, but access failed. Low, par1: returnCode, par2: 0
|
//!< returnCode, par2: 0
|
||||||
static const Event STORE_READ_FAILED = MAKE_EVENT(3, severity::LOW);
|
static const Event STORE_READ_FAILED = MAKE_EVENT(
|
||||||
//! An unexpected TM packet or data message occurred. Low, par1: 0, par2: integer (debug info)
|
3, severity::LOW); //!< Data was requested, but access failed. Low, par1: returnCode, par2: 0
|
||||||
static const Event UNEXPECTED_MSG = MAKE_EVENT(4, severity::LOW);
|
static const Event UNEXPECTED_MSG =
|
||||||
//! Storing data failed. May simply be a full store. Low, par1: returnCode,
|
MAKE_EVENT(4, severity::LOW); //!< An unexpected TM packet or data message occurred. Low,
|
||||||
//! par2: integer (sequence count of failed packet).
|
//!< par1: 0, par2: integer (debug info)
|
||||||
static const Event STORING_FAILED = MAKE_EVENT(5, severity::LOW);
|
static const Event STORING_FAILED = MAKE_EVENT(
|
||||||
//! Dumping retrieved data failed. Low, par1: returnCode,
|
5, severity::LOW); //!< Storing data failed. May simply be a full store. Low, par1:
|
||||||
//! par2: integer (sequence count of failed packet).
|
//!< returnCode, par2: integer (sequence count of failed packet).
|
||||||
static const Event TM_DUMP_FAILED = MAKE_EVENT(6, severity::LOW);
|
static const Event TM_DUMP_FAILED =
|
||||||
//! Corrupted init data or read error. Low, par1: returnCode, par2: integer (debug info)
|
MAKE_EVENT(6, severity::LOW); //!< Dumping retrieved data failed. Low, par1: returnCode,
|
||||||
//! Store was not initialized. Starts empty. Info, parameters both zero.
|
//!< par2: integer (sequence count of failed packet).
|
||||||
static const Event STORE_INIT_FAILED = MAKE_EVENT(7, severity::LOW);
|
static const Event STORE_INIT_FAILED =
|
||||||
//! Data was read out, but it is inconsistent. Low par1:
|
MAKE_EVENT(7, severity::LOW); //!< Corrupted init data or read error. Low, par1: returnCode,
|
||||||
//! Memory address of corruption, par2: integer (debug info)
|
//!< par2: integer (debug info)
|
||||||
static const Event STORE_INIT_EMPTY = MAKE_EVENT(8, severity::INFO);
|
static const Event STORE_INIT_EMPTY = MAKE_EVENT(
|
||||||
|
8, severity::INFO); //!< Store was not initialized. Starts empty. Info, parameters both zero.
|
||||||
static const Event STORE_CONTENT_CORRUPTED = MAKE_EVENT(9, severity::LOW);
|
static const Event STORE_CONTENT_CORRUPTED =
|
||||||
//! Info event indicating the store will be initialized, either at boot or after IOB switch.
|
MAKE_EVENT(9, severity::LOW); //!< Data was read out, but it is inconsistent. Low par1:
|
||||||
//! Info. pars: 0
|
//!< Memory address of corruption, par2: integer (debug info)
|
||||||
static const Event STORE_INITIALIZE = MAKE_EVENT(10, severity::INFO);
|
static const Event STORE_INITIALIZE =
|
||||||
//! Info event indicating the store was successfully initialized, either at boot or after
|
MAKE_EVENT(10, severity::INFO); //!< Info event indicating the store will be initialized,
|
||||||
//! IOB switch. Info. pars: 0
|
//!< either at boot or after IOB switch. Info. pars: 0
|
||||||
static const Event INIT_DONE = MAKE_EVENT(11, severity::INFO);
|
static const Event INIT_DONE = MAKE_EVENT(
|
||||||
//! Info event indicating that dumping finished successfully.
|
11, severity::INFO); //!< Info event indicating the store was successfully initialized,
|
||||||
//! par1: Number of dumped packets. par2: APID/SSC (16bits each)
|
//!< either at boot or after IOB switch. Info. pars: 0
|
||||||
static const Event DUMP_FINISHED = MAKE_EVENT(12, severity::INFO);
|
static const Event DUMP_FINISHED = MAKE_EVENT(
|
||||||
//! Info event indicating that deletion finished successfully.
|
12, severity::INFO); //!< Info event indicating that dumping finished successfully. par1:
|
||||||
//! par1:Number of deleted packets. par2: APID/SSC (16bits each)
|
//!< Number of dumped packets. par2: APID/SSC (16bits each)
|
||||||
static const Event DELETION_FINISHED = MAKE_EVENT(13, severity::INFO);
|
static const Event DELETION_FINISHED = MAKE_EVENT(
|
||||||
//! Info event indicating that something went wrong during deletion. pars: 0
|
13, severity::INFO); //!< Info event indicating that deletion finished successfully. par1:
|
||||||
static const Event DELETION_FAILED = MAKE_EVENT(14, severity::LOW);
|
//!< Number of deleted packets. par2: APID/SSC (16bits each)
|
||||||
//! Info that the a auto catalog report failed
|
static const Event DELETION_FAILED = MAKE_EVENT(
|
||||||
static const Event AUTO_CATALOGS_SENDING_FAILED = MAKE_EVENT(15, severity::INFO);
|
14,
|
||||||
|
severity::LOW); //!< Info event indicating that something went wrong during deletion. pars: 0
|
||||||
|
static const Event AUTO_CATALOGS_SENDING_FAILED =
|
||||||
|
MAKE_EVENT(15, severity::INFO); //!< Info that the a auto catalog report failed
|
||||||
|
|
||||||
virtual ~TmStoreBackendIF() {}
|
virtual ~TmStoreBackendIF() {}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ class SpacePacket : public SpacePacketBase {
|
|||||||
* @param apid Sets the packet's APID field. The default value describes an idle packet.
|
* @param apid Sets the packet's APID field. The default value describes an idle packet.
|
||||||
* @param sequenceCount ets the packet's Source Sequence Count field.
|
* @param sequenceCount ets the packet's Source Sequence Count field.
|
||||||
*/
|
*/
|
||||||
SpacePacket(uint16_t packetDataLength = 0, bool isTelecommand = false,
|
SpacePacket(uint16_t packetDataLength, bool isTelecommand = false,
|
||||||
uint16_t apid = APID_IDLE_PACKET, uint16_t sequenceCount = 0);
|
uint16_t apid = APID_IDLE_PACKET, uint16_t sequenceCount = 0);
|
||||||
/**
|
/**
|
||||||
* The class's default destructor.
|
* The class's default destructor.
|
||||||
|
@ -20,10 +20,8 @@ CommandingServiceBase::CommandingServiceBase(object_id_t setObjectId, uint16_t a
|
|||||||
service(service),
|
service(service),
|
||||||
timeoutSeconds(commandTimeoutSeconds),
|
timeoutSeconds(commandTimeoutSeconds),
|
||||||
commandMap(numberOfParallelCommands) {
|
commandMap(numberOfParallelCommands) {
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
|
||||||
size_t mqSz = MessageQueueMessage::MAX_MESSAGE_SIZE;
|
requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth, mqSz, &mqArgs);
|
|
||||||
requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth, mqSz, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandingServiceBase::setPacketSource(object_id_t packetSource) {
|
void CommandingServiceBase::setPacketSource(object_id_t packetSource) {
|
||||||
|
@ -13,9 +13,7 @@ object_id_t PusServiceBase::packetDestination = 0;
|
|||||||
|
|
||||||
PusServiceBase::PusServiceBase(object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId)
|
PusServiceBase::PusServiceBase(object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId)
|
||||||
: SystemObject(setObjectId), apid(setApid), serviceId(setServiceId) {
|
: SystemObject(setObjectId), apid(setApid), serviceId(setServiceId) {
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
requestQueue = QueueFactory::instance()->createMessageQueue(PUS_SERVICE_MAX_RECEPTION);
|
||||||
requestQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
PUS_SERVICE_MAX_RECEPTION, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PusServiceBase::~PusServiceBase() { QueueFactory::instance()->deleteMessageQueue(requestQueue); }
|
PusServiceBase::~PusServiceBase() { QueueFactory::instance()->deleteMessageQueue(requestQueue); }
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
class SourceSequenceCounter {
|
class SourceSequenceCounter {
|
||||||
private:
|
private:
|
||||||
uint16_t sequenceCount = 0;
|
uint16_t sequenceCount;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SourceSequenceCounter(uint16_t initialSequenceCount = 0) : sequenceCount(initialSequenceCount) {}
|
SourceSequenceCounter() : sequenceCount(0) {}
|
||||||
void increment() {
|
void increment() {
|
||||||
sequenceCount = (sequenceCount + 1) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
|
sequenceCount = (sequenceCount + 1) % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
|
||||||
}
|
}
|
||||||
@ -19,20 +19,6 @@ class SourceSequenceCounter {
|
|||||||
void reset(uint16_t toValue = 0) {
|
void reset(uint16_t toValue = 0) {
|
||||||
sequenceCount = toValue % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
|
sequenceCount = toValue % (SpacePacketBase::LIMIT_SEQUENCE_COUNT);
|
||||||
}
|
}
|
||||||
SourceSequenceCounter& operator++(int) {
|
|
||||||
this->increment();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
SourceSequenceCounter& operator--(int) {
|
|
||||||
this->decrement();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
SourceSequenceCounter& operator=(const uint16_t& newCount) {
|
|
||||||
sequenceCount = newCount;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator uint16_t() { return this->get(); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_TMTCSERVICES_SOURCESEQUENCECOUNTER_H_ */
|
#endif /* FSFW_TMTCSERVICES_SOURCESEQUENCECOUNTER_H_ */
|
||||||
|
@ -15,9 +15,7 @@ TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination, object_i
|
|||||||
tcDestination(tcDestination)
|
tcDestination(tcDestination)
|
||||||
|
|
||||||
{
|
{
|
||||||
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
|
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH);
|
||||||
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
TMTC_RECEPTION_QUEUE_DEPTH, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }
|
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }
|
||||||
@ -36,7 +34,7 @@ ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored) {
|
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored) {
|
||||||
if (maxNumberOfPacketsStored <= LIMIT_DOWNLINK_PACKETS_STORED) {
|
if (maxNumberOfPacketsStored <= LIMIT_DOWNLINK_PACKETS_STORED) {
|
||||||
this->maxNumberOfPacketsStored = maxNumberOfPacketsStored;
|
this->maxNumberOfPacketsStored = maxNumberOfPacketsStored;
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
@ -174,18 +172,15 @@ ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage* message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tmFifo->full()) {
|
if (tmFifo->full()) {
|
||||||
if (warningSwitch) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
|
sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
|
||||||
"of stored packet IDs reached!"
|
"of stored packet IDs reached!"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning(
|
sif::printWarning(
|
||||||
"TmTcBridge::storeDownlinkData: TM downlink max. number "
|
"TmTcBridge::storeDownlinkData: TM downlink max. number "
|
||||||
"of stored packet IDs reached!\n");
|
"of stored packet IDs reached!\n");
|
||||||
#endif
|
#endif
|
||||||
warningSwitch = true;
|
|
||||||
}
|
|
||||||
if (overwriteOld) {
|
if (overwriteOld) {
|
||||||
tmFifo->retrieve(&storeId);
|
tmFifo->retrieve(&storeId);
|
||||||
tmStore->deleteData(storeId);
|
tmStore->deleteData(storeId);
|
||||||
|
@ -18,7 +18,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
|||||||
public:
|
public:
|
||||||
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
|
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
|
||||||
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
|
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
|
||||||
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 1000;
|
static constexpr uint8_t LIMIT_DOWNLINK_PACKETS_STORED = 200;
|
||||||
|
|
||||||
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
|
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
|
||||||
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
|
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
|
||||||
@ -43,7 +43,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
|||||||
* @return -@c RETURN_OK if value was set successfully
|
* @return -@c RETURN_OK if value was set successfully
|
||||||
* -@c RETURN_FAILED otherwise, stored value stays the same
|
* -@c RETURN_FAILED otherwise, stored value stays the same
|
||||||
*/
|
*/
|
||||||
ReturnValue_t setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored);
|
ReturnValue_t setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will set up the bridge to overwrite old data in the FIFO.
|
* This will set up the bridge to overwrite old data in the FIFO.
|
||||||
@ -72,8 +72,6 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
|||||||
virtual uint16_t getIdentifier() override;
|
virtual uint16_t getIdentifier() override;
|
||||||
virtual MessageQueueId_t getRequestQueue() override;
|
virtual MessageQueueId_t getRequestQueue() override;
|
||||||
|
|
||||||
bool warningSwitch = true;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Cached for initialize function.
|
//! Cached for initialize function.
|
||||||
object_id_t tmStoreId = objects::NO_OBJECT;
|
object_id_t tmStoreId = objects::NO_OBJECT;
|
||||||
@ -152,7 +150,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
|||||||
*/
|
*/
|
||||||
DynamicFIFO<store_address_t>* tmFifo = nullptr;
|
DynamicFIFO<store_address_t>* tmFifo = nullptr;
|
||||||
uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
|
uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
|
||||||
unsigned int maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
|
uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_TMTCSERVICES_TMTCBRIDGE_H_ */
|
#endif /* FSFW_TMTCSERVICES_TMTCBRIDGE_H_ */
|
||||||
|
@ -78,7 +78,7 @@ TEST_CASE("Command Executor", "[cmd-exec]") {
|
|||||||
REQUIRE(result != CommandExecutor::COMMAND_ERROR);
|
REQUIRE(result != CommandExecutor::COMMAND_ERROR);
|
||||||
// This ensures that the tests do not block indefinitely
|
// This ensures that the tests do not block indefinitely
|
||||||
usleep(500);
|
usleep(500);
|
||||||
REQUIRE(limitIdx < 50000);
|
REQUIRE(limitIdx < 500);
|
||||||
}
|
}
|
||||||
limitIdx = 0;
|
limitIdx = 0;
|
||||||
CHECK(bytesHaveBeenRead == true);
|
CHECK(bytesHaveBeenRead == true);
|
||||||
|
Reference in New Issue
Block a user