SPI refactoring #80
24
CHANGELOG.md
24
CHANGELOG.md
@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
|
- Bump C++ required version to C++17. Every project which uses the FSFW and every modern
|
||||||
|
compiler supports it
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/622
|
||||||
- HAL Linux SPI: Set the Clock Default State when setting new SPI speed
|
- HAL Linux SPI: Set the Clock Default State when setting new SPI speed
|
||||||
and mode
|
and mode
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
|
||||||
@ -57,15 +60,34 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Additions
|
## Additions
|
||||||
|
|
||||||
- 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
|
||||||
- Added ETL dependency and improved library dependency management
|
- Added ETL dependency and improved library dependency management
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592
|
||||||
|
- `Subsystem`: New API to add table and sequence entries
|
||||||
|
|
||||||
|
## HAL
|
||||||
|
|
||||||
|
- SPI: Cache the SPI device in the communication interface. Architecturally, this makes a
|
||||||
|
lot more sense because each ComIF should be responsible for one SPI bus.
|
||||||
|
- SPI: Move the empty transfer to update the line polarity to separate function. This means
|
||||||
|
it is not automatically called when calling the setter function for SPI speed and mode.
|
||||||
|
The user should call this function after locking the CS mutex if multiple SPI devices with
|
||||||
|
differing speeds and modes are attached to one bus.
|
||||||
|
- SPI: Getter functions for SPI speed and mode.
|
||||||
|
- I2C: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1.
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
- TCP TMTC Server: `MutexGuard` was not created properly in
|
||||||
|
`TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)` call.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/618
|
||||||
|
- Fix infinite recursion in `prepareHealthSetReply` of PUS Health Service 201.
|
||||||
|
Is not currently used right now but might be used in the future
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/617
|
||||||
|
- Move some CMake directives further up top so they are not ignored
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/621
|
||||||
- Small bugfix in STM32 HAL for SPI
|
- Small bugfix in STM32 HAL for SPI
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/599
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/599
|
||||||
- HAL GPIO: Improved error checking in `LinuxLibgpioIF::configureGpios(...)`. If a GPIO
|
- HAL GPIO: Improved error checking in `LinuxLibgpioIF::configureGpios(...)`. If a GPIO
|
||||||
|
@ -2,6 +2,13 @@ cmake_minimum_required(VERSION 3.13)
|
|||||||
set(LIB_FSFW_NAME fsfw)
|
set(LIB_FSFW_NAME fsfw)
|
||||||
project(${LIB_FSFW_NAME})
|
project(${LIB_FSFW_NAME})
|
||||||
|
|
||||||
|
if(NOT CMAKE_CXX_STANDARD)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
elseif(${CMAKE_CXX_STANDARD} LESS 17)
|
||||||
|
message(FATAL_ERROR "Compiling the FSFW requires a minimum of C++17 support")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(FSFW_VERSION_IF_GIT_FAILS 4)
|
set(FSFW_VERSION_IF_GIT_FAILS 4)
|
||||||
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
|
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
|
||||||
set(FSFW_REVISION_IF_GIT_FAILS 0)
|
set(FSFW_REVISION_IF_GIT_FAILS 0)
|
||||||
@ -178,13 +185,6 @@ target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
|||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT CMAKE_CXX_STANDARD)
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
|
||||||
elseif(${CMAKE_CXX_STANDARD} LESS 11)
|
|
||||||
message(FATAL_ERROR "${MSG_PREFIX} Compiling the FSFW requires a minimum of C++11 support")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Backwards comptability
|
# Backwards comptability
|
||||||
if(OS_FSFW AND NOT FSFW_OSAL)
|
if(OS_FSFW AND NOT FSFW_OSAL)
|
||||||
message(WARNING "${MSG_PREFIX} Please pass the FSFW OSAL as FSFW_OSAL instead of OS_FSFW")
|
message(WARNING "${MSG_PREFIX} Please pass the FSFW OSAL as FSFW_OSAL instead of OS_FSFW")
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "fsfw/FSFW.h"
|
#include "fsfw/FSFW.h"
|
||||||
#include "fsfw/serviceinterface.h"
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
UnixFileGuard::UnixFileGuard(std::string device, int* fileDescriptor, int flags,
|
UnixFileGuard::UnixFileGuard(const 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(std::string device, int* fileDescriptor, int flags,
|
UnixFileGuard(const std::string& device, int* fileDescriptor, int flags,
|
||||||
std::string diagnosticPrefix = "");
|
std::string diagnosticPrefix = "");
|
||||||
|
|
||||||
virtual ~UnixFileGuard();
|
virtual ~UnixFileGuard();
|
||||||
|
@ -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, GpioIF* gpioComIF)
|
SpiComIF::SpiComIF(object_id_t objectId, std::string devname, GpioIF* gpioComIF)
|
||||||
: SystemObject(objectId), gpioComIF(gpioComIF) {
|
: SystemObject(objectId), gpioComIF(gpioComIF), dev(std::move(devname)) {
|
||||||
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, GpioIF* gpioComIF)
|
|||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
}
|
}
|
||||||
|
|
||||||
spiMutex = MutexFactory::instance()->createMutex();
|
csMutex = MutexFactory::instance()->createMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) {
|
ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) {
|
||||||
@ -85,8 +85,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) {
|
|||||||
spiCookie->getSpiParameters(spiMode, spiSpeed, ¶ms);
|
spiCookie->getSpiParameters(spiMode, spiSpeed, ¶ms);
|
||||||
|
|
||||||
int fileDescriptor = 0;
|
int fileDescriptor = 0;
|
||||||
UnixFileGuard fileHelper(spiCookie->getSpiDevice(), &fileDescriptor, O_RDWR,
|
UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::initializeInterface");
|
||||||
"SpiComIF::initializeInterface");
|
|
||||||
if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return fileHelper.getOpenResult();
|
return fileHelper.getOpenResult();
|
||||||
}
|
}
|
||||||
@ -182,8 +181,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
int retval = 0;
|
int retval = 0;
|
||||||
/* Prepare transfer */
|
/* Prepare transfer */
|
||||||
int fileDescriptor = 0;
|
int fileDescriptor = 0;
|
||||||
std::string device = spiCookie->getSpiDevice();
|
UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
|
||||||
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;
|
||||||
}
|
}
|
||||||
@ -199,7 +197,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
|
|
||||||
/* Pull SPI CS low. For now, no support for active high given */
|
/* Pull SPI CS low. For now, no support for active high given */
|
||||||
if (gpioId != gpio::NO_GPIO) {
|
if (gpioId != gpio::NO_GPIO) {
|
||||||
result = spiMutex->lockMutex(timeoutType, timeoutMs);
|
result = csMutex->lockMutex(timeoutType, timeoutMs);
|
||||||
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
|
||||||
@ -210,6 +208,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
updateLinePolarity(fileDescriptor);
|
||||||
ReturnValue_t result = gpioComIF->pullLow(gpioId);
|
ReturnValue_t result = gpioComIF->pullLow(gpioId);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
@ -221,6 +220,8 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
updateLinePolarity(fileDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Execute transfer */
|
/* Execute transfer */
|
||||||
@ -250,7 +251,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
|
|
||||||
if (gpioId != gpio::NO_GPIO) {
|
if (gpioId != gpio::NO_GPIO) {
|
||||||
gpioComIF->pullHigh(gpioId);
|
gpioComIF->pullHigh(gpioId);
|
||||||
result = spiMutex->unlockMutex();
|
result = csMutex->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;
|
||||||
@ -278,9 +279,8 @@ 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(device, &fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage");
|
UnixFileGuard fileHelper(dev, &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;
|
||||||
}
|
}
|
||||||
@ -294,7 +294,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
|
|||||||
|
|
||||||
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
||||||
if (gpioId != gpio::NO_GPIO) {
|
if (gpioId != gpio::NO_GPIO) {
|
||||||
result = spiMutex->lockMutex(timeoutType, timeoutMs);
|
result = csMutex->lockMutex(timeoutType, timeoutMs);
|
||||||
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 lock mutex" << std::endl;
|
sif::error << "SpiComIF::getSendSuccess: Failed to lock mutex" << std::endl;
|
||||||
@ -317,7 +317,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
|
|||||||
|
|
||||||
if (gpioId != gpio::NO_GPIO) {
|
if (gpioId != gpio::NO_GPIO) {
|
||||||
gpioComIF->pullHigh(gpioId);
|
gpioComIF->pullHigh(gpioId);
|
||||||
result = spiMutex->unlockMutex();
|
result = csMutex->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;
|
||||||
@ -353,7 +353,7 @@ MutexIF* SpiComIF::getMutex(MutexIF::TimeoutType* timeoutType, uint32_t* timeout
|
|||||||
if (timeoutMs != nullptr) {
|
if (timeoutMs != nullptr) {
|
||||||
*timeoutMs = this->timeoutMs;
|
*timeoutMs = this->timeoutMs;
|
||||||
}
|
}
|
||||||
return spiMutex;
|
return csMutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpiComIF::performSpiWiretapping(SpiCookie* spiCookie) {
|
void SpiComIF::performSpiWiretapping(SpiCookie* spiCookie) {
|
||||||
@ -401,11 +401,29 @@ void SpiComIF::setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed)
|
|||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI speed failed");
|
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI speed failed");
|
||||||
}
|
}
|
||||||
// This updates the SPI clock default polarity. Only setting the mode does not update
|
}
|
||||||
// the line state, which can be an issue on mode switches because the clock line will
|
|
||||||
// switch the state after the chip select is pulled low
|
void SpiComIF::getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const {
|
||||||
|
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;
|
||||||
retval = ioctl(spiFd, SPI_IOC_MESSAGE(1), &clockUpdateTransfer);
|
int 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");
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
|||||||
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED =
|
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED =
|
||||||
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 2);
|
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 2);
|
||||||
|
|
||||||
SpiComIF(object_id_t objectId, GpioIF* gpioComIF);
|
SpiComIF(object_id_t objectId, std::string devname, 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;
|
||||||
@ -59,6 +59,20 @@ 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
void getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const;
|
||||||
|
|
||||||
|
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);
|
||||||
@ -70,8 +84,12 @@ 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
|
||||||
|
* pulled high
|
||||||
|
*/
|
||||||
|
MutexIF* csMutex = nullptr;
|
||||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||||
uint32_t timeoutMs = 20;
|
uint32_t timeoutMs = 20;
|
||||||
spi_ioc_transfer clockUpdateTransfer = {};
|
spi_ioc_transfer clockUpdateTransfer = {};
|
||||||
|
@ -1,26 +1,25 @@
|
|||||||
#include "SpiCookie.h"
|
#include "SpiCookie.h"
|
||||||
|
|
||||||
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
|
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, const size_t maxSize,
|
||||||
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(spiAddress, gpio::NO_GPIO, spiDev, maxSize, spiMode, spiSpeed) {}
|
: SpiCookie(spi::SpiComIfModes::REGULAR, spiAddress, chipSelect, maxSize, spiMode, spiSpeed,
|
||||||
|
nullptr, nullptr) {}
|
||||||
|
|
||||||
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
|
SpiCookie::SpiCookie(address_t spiAddress, const size_t maxSize, spi::SpiModes spiMode,
|
||||||
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed,
|
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)
|
spi::send_callback_function_t callback, void* args)
|
||||||
: SpiCookie(spi::SpiComIfModes::CALLBACK, spiAddress, chipSelect, spiDev, maxSize, spiMode,
|
: SpiCookie(spi::SpiComIfModes::CALLBACK, spiAddress, chipSelect, maxSize, spiMode, spiSpeed,
|
||||||
spiSpeed, callback, args) {}
|
callback, args) {}
|
||||||
|
|
||||||
SpiCookie::SpiCookie(spi::SpiComIfModes comIfMode, address_t spiAddress, gpioId_t chipSelect,
|
SpiCookie::SpiCookie(spi::SpiComIfModes comIfMode, address_t spiAddress, gpioId_t chipSelect,
|
||||||
std::string spiDev, const size_t maxSize, spi::SpiModes spiMode,
|
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed,
|
||||||
uint32_t spiSpeed, spi::send_callback_function_t callback, void* args)
|
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),
|
||||||
@ -50,8 +49,6 @@ 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; }
|
||||||
|
@ -29,23 +29,22 @@ class SpiCookie : public CookieIF {
|
|||||||
* @param spiDev
|
* @param spiDev
|
||||||
* @param maxSize
|
* @param maxSize
|
||||||
*/
|
*/
|
||||||
SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev, const size_t maxSize,
|
SpiCookie(address_t spiAddress, gpioId_t chipSelect, const size_t maxSize, spi::SpiModes spiMode,
|
||||||
spi::SpiModes spiMode, uint32_t spiSpeed);
|
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, std::string spiDev, const size_t maxReplySize,
|
SpiCookie(address_t spiAddress, const size_t maxReplySize, spi::SpiModes spiMode,
|
||||||
spi::SpiModes spiMode, uint32_t spiSpeed);
|
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, std::string spiDev, const size_t maxSize,
|
SpiCookie(address_t spiAddress, gpioId_t chipSelect, const size_t maxSize, spi::SpiModes spiMode,
|
||||||
spi::SpiModes spiMode, uint32_t spiSpeed, spi::send_callback_function_t callback,
|
uint32_t spiSpeed, spi::send_callback_function_t callback, void* args);
|
||||||
void* args);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the callback function
|
* Get the callback function
|
||||||
@ -55,7 +54,6 @@ 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;
|
||||||
|
|
||||||
@ -154,12 +152,11 @@ 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,
|
||||||
std::string spiDev, 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);
|
||||||
|
|
||||||
address_t spiAddress;
|
address_t spiAddress;
|
||||||
gpioId_t chipSelectPin;
|
gpioId_t chipSelectPin;
|
||||||
std::string spiDevice;
|
|
||||||
|
|
||||||
spi::SpiComIfModes comIfMode;
|
spi::SpiComIfModes comIfMode;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define FIXEDARRAYLIST_H_
|
#define FIXEDARRAYLIST_H_
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include "ArrayList.h"
|
#include "ArrayList.h"
|
||||||
/**
|
/**
|
||||||
@ -9,10 +10,9 @@
|
|||||||
*/
|
*/
|
||||||
template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
||||||
class FixedArrayList : public ArrayList<T, count_t> {
|
class FixedArrayList : public ArrayList<T, count_t> {
|
||||||
#if !defined(_MSC_VER) && !defined(__clang__)
|
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
|
||||||
static_assert(MAX_SIZE <= (std::pow(2, sizeof(count_t) * 8) - 1),
|
|
||||||
"count_t is not large enough to hold MAX_SIZE");
|
"count_t is not large enough to hold MAX_SIZE");
|
||||||
#endif
|
|
||||||
private:
|
private:
|
||||||
T data[MAX_SIZE];
|
T data[MAX_SIZE];
|
||||||
|
|
||||||
|
@ -1401,8 +1401,7 @@ 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) {
|
||||||
else if (iter->second.countdown != nullptr) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return iter->second.delayCycles;
|
return iter->second.delayCycles;
|
||||||
|
@ -801,7 +801,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
DeviceCommandMap::iterator command;
|
DeviceCommandMap::iterator command;
|
||||||
//! Instead of using delayCycles to specify the maximum time to wait for the device reply, it
|
//! Instead of using delayCycles to specify the maximum time to wait for the device reply, it
|
||||||
//! is also possible specify a countdown
|
//! is also possible specify a countdown
|
||||||
Countdown* countdown = nullptr;
|
Countdown *countdown = nullptr;
|
||||||
//! will be set to true when reply is enabled
|
//! will be set to true when reply is enabled
|
||||||
bool active = false;
|
bool active = false;
|
||||||
};
|
};
|
||||||
@ -1269,13 +1269,13 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
/**
|
/**
|
||||||
* @brief Handles disabling of replies which use a timeout to detect missed replies.
|
* @brief Handles disabling of replies which use a timeout to detect missed replies.
|
||||||
*/
|
*/
|
||||||
void disableTimeoutControlledReply(DeviceReplyInfo* info);
|
void disableTimeoutControlledReply(DeviceReplyInfo *info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handles disabling of replies which use a number of maximum delay cycles to detect
|
* @brief Handles disabling of replies which use a number of maximum delay cycles to detect
|
||||||
* missed replies.
|
* missed replies.
|
||||||
*/
|
*/
|
||||||
void disableDelayCyclesControlledReply(DeviceReplyInfo* info);
|
void disableDelayCyclesControlledReply(DeviceReplyInfo *info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrive data from the #IPCStore.
|
* Retrive data from the #IPCStore.
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#elif defined(PLATFORM_UNIX)
|
#elif defined(PLATFORM_UNIX)
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
||||||
@ -29,7 +31,7 @@ TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
|
|||||||
: SystemObject(objectId),
|
: SystemObject(objectId),
|
||||||
tmtcBridgeId(tmtcTcpBridge),
|
tmtcBridgeId(tmtcTcpBridge),
|
||||||
receptionMode(receptionMode),
|
receptionMode(receptionMode),
|
||||||
tcpConfig(customTcpServerPort),
|
tcpConfig(std::move(customTcpServerPort)),
|
||||||
receptionBuffer(receptionBufferSize),
|
receptionBuffer(receptionBufferSize),
|
||||||
ringBuffer(ringBufferSize, true) {}
|
ringBuffer(ringBufferSize, true) {}
|
||||||
|
|
||||||
@ -103,7 +105,7 @@ ReturnValue_t TcpTmTcServer::initialize() {
|
|||||||
|
|
||||||
TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
||||||
|
|
||||||
ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
[[noreturn]] ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
||||||
using namespace tcpip;
|
using namespace tcpip;
|
||||||
// If a connection is accepted, the corresponding socket will be assigned to the new socket
|
// If a connection is accepted, the corresponding socket will be assigned to the new socket
|
||||||
socket_t connSocket = 0;
|
socket_t connSocket = 0;
|
||||||
@ -138,7 +140,6 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
|||||||
closeSocket(connSocket);
|
closeSocket(connSocket);
|
||||||
connSocket = 0;
|
connSocket = 0;
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TcpTmTcServer::initializeAfterTaskCreation() {
|
ReturnValue_t TcpTmTcServer::initializeAfterTaskCreation() {
|
||||||
@ -159,7 +160,7 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int retval = recv(connSocket, reinterpret_cast<char*>(receptionBuffer.data()),
|
ssize_t retval = recv(connSocket, reinterpret_cast<char*>(receptionBuffer.data()),
|
||||||
receptionBuffer.capacity(), tcpConfig.tcpFlags);
|
receptionBuffer.capacity(), tcpConfig.tcpFlags);
|
||||||
if (retval == 0) {
|
if (retval == 0) {
|
||||||
size_t availableReadData = ringBuffer.getAvailableReadData();
|
size_t availableReadData = ringBuffer.getAvailableReadData();
|
||||||
@ -252,17 +253,17 @@ ReturnValue_t TcpTmTcServer::handleTcReception(uint8_t* spacePacket, size_t pack
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TcpTmTcServer::getTcpPort() const { return tcpConfig.tcpPort; }
|
const std::string& TcpTmTcServer::getTcpPort() const { return tcpConfig.tcpPort; }
|
||||||
|
|
||||||
void TcpTmTcServer::setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds) {
|
void TcpTmTcServer::setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds_) {
|
||||||
this->validPacketIds = validPacketIds;
|
this->validPacketIds = std::move(validPacketIds_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TcpTmTcServer::TcpConfig& TcpTmTcServer::getTcpConfigStruct() { return tcpConfig; }
|
TcpTmTcServer::TcpConfig& TcpTmTcServer::getTcpConfigStruct() { return tcpConfig; }
|
||||||
|
|
||||||
ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) {
|
ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) {
|
||||||
// Access to the FIFO is mutex protected because it is filled by the bridge
|
// Access to the FIFO is mutex protected because it is filled by the bridge
|
||||||
MutexGuard(tmtcBridge->mutex, tmtcBridge->timeoutType, tmtcBridge->mutexTimeoutMs);
|
MutexGuard mg(tmtcBridge->mutex, tmtcBridge->timeoutType, tmtcBridge->mutexTimeoutMs);
|
||||||
store_address_t storeId;
|
store_address_t storeId;
|
||||||
while ((not tmtcBridge->tmFifo->empty()) and
|
while ((not tmtcBridge->tmFifo->empty()) and
|
||||||
(tmtcBridge->packetSentCounter < tmtcBridge->sentPacketsPerCycle)) {
|
(tmtcBridge->packetSentCounter < tmtcBridge->sentPacketsPerCycle)) {
|
||||||
@ -283,7 +284,7 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)
|
|||||||
#endif
|
#endif
|
||||||
arrayprinter::print(storeAccessor.data(), storeAccessor.size());
|
arrayprinter::print(storeAccessor.data(), storeAccessor.size());
|
||||||
}
|
}
|
||||||
int retval = send(connSocket, reinterpret_cast<const char*>(storeAccessor.data()),
|
ssize_t retval = send(connSocket, reinterpret_cast<const char*>(storeAccessor.data()),
|
||||||
storeAccessor.size(), tcpConfig.tcpTmFlags);
|
storeAccessor.size(), tcpConfig.tcpTmFlags);
|
||||||
if (retval == static_cast<int>(storeAccessor.size())) {
|
if (retval == static_cast<int>(storeAccessor.size())) {
|
||||||
// Packet sent, clear FIFO entry
|
// Packet sent, clear FIFO entry
|
||||||
@ -339,6 +340,9 @@ ReturnValue_t TcpTmTcServer::handleTcRingBufferData(size_t availableReadData) {
|
|||||||
size_t foundSize = 0;
|
size_t foundSize = 0;
|
||||||
size_t readLen = 0;
|
size_t readLen = 0;
|
||||||
while (readLen < readAmount) {
|
while (readLen < readAmount) {
|
||||||
|
if (spacePacketParser == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
result =
|
result =
|
||||||
spacePacketParser->parseSpacePackets(bufPtrPtr, readAmount, startIdx, foundSize, readLen);
|
spacePacketParser->parseSpacePackets(bufPtrPtr, readAmount, startIdx, foundSize, readLen);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class TcpTmTcBridge;
|
class TcpTmTcBridge;
|
||||||
@ -44,7 +45,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
|
|
||||||
struct TcpConfig {
|
struct TcpConfig {
|
||||||
public:
|
public:
|
||||||
TcpConfig(std::string tcpPort) : tcpPort(tcpPort) {}
|
explicit TcpConfig(std::string tcpPort) : tcpPort(std::move(tcpPort)) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Passed to the recv call
|
* Passed to the recv call
|
||||||
@ -84,7 +85,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
size_t ringBufferSize = RING_BUFFER_SIZE,
|
size_t ringBufferSize = RING_BUFFER_SIZE,
|
||||||
std::string customTcpServerPort = DEFAULT_SERVER_PORT,
|
std::string customTcpServerPort = DEFAULT_SERVER_PORT,
|
||||||
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
|
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
|
||||||
virtual ~TcpTmTcServer();
|
~TcpTmTcServer() override;
|
||||||
|
|
||||||
void enableWiretapping(bool enable);
|
void enableWiretapping(bool enable);
|
||||||
|
|
||||||
@ -97,10 +98,10 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
void setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds);
|
void setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds);
|
||||||
|
|
||||||
ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
[[noreturn]] ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
ReturnValue_t initializeAfterTaskCreation() override;
|
ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
|
||||||
std::string getTcpPort() const;
|
[[nodiscard]] const std::string& getTcpPort() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StorageManagerIF* tcStore = nullptr;
|
StorageManagerIF* tcStore = nullptr;
|
||||||
@ -115,7 +116,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
|
|
||||||
ReceptionModes receptionMode;
|
ReceptionModes receptionMode;
|
||||||
TcpConfig tcpConfig;
|
TcpConfig tcpConfig;
|
||||||
struct sockaddr tcpAddress;
|
struct sockaddr tcpAddress = {};
|
||||||
socket_t listenerTcpSocket = 0;
|
socket_t listenerTcpSocket = 0;
|
||||||
|
|
||||||
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;
|
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;
|
||||||
|
@ -13,8 +13,6 @@ CService201HealthCommanding::CService201HealthCommanding(object_id_t objectId, u
|
|||||||
: CommandingServiceBase(objectId, apid, serviceId, numParallelCommands, commandTimeoutSeconds) {
|
: CommandingServiceBase(objectId, apid, serviceId, numParallelCommands, commandTimeoutSeconds) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CService201HealthCommanding::~CService201HealthCommanding() {}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::isValidSubservice(uint8_t subservice) {
|
ReturnValue_t CService201HealthCommanding::isValidSubservice(uint8_t subservice) {
|
||||||
switch (subservice) {
|
switch (subservice) {
|
||||||
case (Subservice::COMMAND_SET_HEALTH):
|
case (Subservice::COMMAND_SET_HEALTH):
|
||||||
@ -43,8 +41,8 @@ ReturnValue_t CService201HealthCommanding::getMessageQueueAndObject(uint8_t subs
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::checkInterfaceAndAcquireMessageQueue(
|
ReturnValue_t CService201HealthCommanding::checkInterfaceAndAcquireMessageQueue(
|
||||||
MessageQueueId_t *messageQueueToSet, object_id_t *objectId) {
|
MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
|
||||||
HasHealthIF *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
|
auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
|
||||||
if (destination == nullptr) {
|
if (destination == nullptr) {
|
||||||
return CommandingServiceBase::INVALID_OBJECT;
|
return CommandingServiceBase::INVALID_OBJECT;
|
||||||
}
|
}
|
||||||
@ -77,6 +75,10 @@ ReturnValue_t CService201HealthCommanding::prepareCommand(CommandMessage *messag
|
|||||||
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL);
|
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default: {
|
||||||
|
// Should never happen, subservice was already checked
|
||||||
|
result = RETURN_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -95,10 +97,10 @@ ReturnValue_t CService201HealthCommanding::handleReply(const CommandMessage *rep
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Not used for now, health state already reported by event
|
// Not used for now, health state already reported by event
|
||||||
ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(const CommandMessage *reply) {
|
[[maybe_unused]] ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(
|
||||||
prepareHealthSetReply(reply);
|
const CommandMessage *reply) {
|
||||||
uint8_t health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
||||||
uint8_t oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
||||||
HealthSetReply healthSetReply(health, oldHealth);
|
HealthSetReply healthSetReply(health, oldHealth);
|
||||||
return sendTmPacket(Subservice::REPLY_HEALTH_SET, &healthSetReply);
|
return sendTmPacket(Subservice::REPLY_HEALTH_SET, &healthSetReply);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
||||||
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
||||||
|
|
||||||
#include "../tmtcservices/CommandingServiceBase.h"
|
#include "fsfw/tmtcservices/CommandingServiceBase.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom PUS service to set health of all objects
|
* @brief Custom PUS service to set health of all objects
|
||||||
@ -21,7 +21,7 @@ class CService201HealthCommanding : public CommandingServiceBase {
|
|||||||
public:
|
public:
|
||||||
CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
||||||
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
|
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
|
||||||
virtual ~CService201HealthCommanding();
|
~CService201HealthCommanding() override = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* CSB abstract function implementations */
|
/* CSB abstract function implementations */
|
||||||
@ -38,12 +38,10 @@ class CService201HealthCommanding : public CommandingServiceBase {
|
|||||||
bool *isStep) override;
|
bool *isStep) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ReturnValue_t checkAndAcquireTargetID(object_id_t *objectIdToSet, const uint8_t *tcData,
|
static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
|
||||||
size_t tcDataLen);
|
const object_id_t *objectId);
|
||||||
ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
|
|
||||||
object_id_t *objectId);
|
|
||||||
|
|
||||||
ReturnValue_t prepareHealthSetReply(const CommandMessage *reply);
|
[[maybe_unused]] ReturnValue_t prepareHealthSetReply(const CommandMessage *reply);
|
||||||
|
|
||||||
enum Subservice {
|
enum Subservice {
|
||||||
//! [EXPORT] : [TC] Set health of target object
|
//! [EXPORT] : [TC] Set health of target object
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
Countdown::Countdown(uint32_t initialTimeout, bool startImmediately) : timeout(initialTimeout) {
|
Countdown::Countdown(uint32_t initialTimeout, bool startImmediately) : timeout(initialTimeout) {
|
||||||
if (startImmediately) {
|
if (startImmediately) {
|
||||||
setTimeout(initialTimeout);
|
setTimeout(initialTimeout);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
timeout = initialTimeout;
|
timeout = initialTimeout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ class CommandingServiceBase : public SystemObject,
|
|||||||
* @param objectId Target object ID
|
* @param objectId Target object ID
|
||||||
* @return
|
* @return
|
||||||
* - @c RETURN_OK to generate a verification start message
|
* - @c RETURN_OK to generate a verification start message
|
||||||
* - @c EXECUTION_COMPELTE Fire-and-forget command. Generate a completion
|
* - @c EXECUTION_COMPLETE Fire-and-forget command. Generate a completion
|
||||||
* verification message.
|
* verification message.
|
||||||
* - @c Anything else rejects the packets and generates a start failure
|
* - @c Anything else rejects the packets and generates a start failure
|
||||||
* verification.
|
* verification.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
class SourceSequenceCounter {
|
class SourceSequenceCounter {
|
||||||
private:
|
private:
|
||||||
uint16_t sequenceCount;
|
uint16_t sequenceCount = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SourceSequenceCounter(uint16_t initialSequenceCount = 0) : sequenceCount(initialSequenceCount) {}
|
SourceSequenceCounter(uint16_t initialSequenceCount = 0) : sequenceCount(initialSequenceCount) {}
|
||||||
|
Loading…
Reference in New Issue
Block a user