Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage
This commit is contained in:
commit
70b785984c
@ -12,15 +12,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## Fixes
|
||||
|
||||
- Bugfix in `Service11TelecommandScheduling` which allowed commands
|
||||
time tagged in the past to be inserted.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/738
|
||||
- `CService200ModeManagement`: Various bugfixes which lead to now execution complete being generated
|
||||
on mode announcements, duplicate mode reply generated on announce commands, and the mode read
|
||||
subservice not working properly.
|
||||
- Memory leak fixes for the TCP/IP TMTC bridge.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/737
|
||||
- `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval
|
||||
seconds instead of uptime.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726
|
||||
- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously,
|
||||
only the X scaling factor was used.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724
|
||||
- Bugfix for RM3100 MGM sensors. Z value was previously calculated
|
||||
with bytes of the X value.
|
||||
- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
|
||||
to false correctly because the `read` and `write` calls were missing.
|
||||
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
|
||||
@ -43,6 +50,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
- `CServiceHealthCommanding`: Add announce all health info implementation
|
||||
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122
|
||||
- Empty constructor for `CdsShortTimeStamper` which does not do an object manager registration.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/730
|
||||
- `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice.
|
||||
- `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT`
|
||||
option on the TCP server. CTOR prototype has changed and expects an explicit
|
||||
|
@ -153,12 +153,12 @@ if(FSFW_BUILD_TESTS)
|
||||
"${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
|
||||
)
|
||||
# Check whether the user has already installed Catch2 first
|
||||
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION})
|
||||
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION} QUIET)
|
||||
# Not installed, so use FetchContent to download and provide Catch2
|
||||
if(NOT Catch2_FOUND)
|
||||
message(
|
||||
STATUS
|
||||
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent"
|
||||
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent."
|
||||
)
|
||||
include(FetchContent)
|
||||
|
||||
@ -196,13 +196,13 @@ message(
|
||||
)
|
||||
|
||||
# Check whether the user has already installed ETL first
|
||||
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET)
|
||||
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
||||
# Not installed, so use FetchContent to download and provide etl
|
||||
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
||||
message(
|
||||
STATUS
|
||||
"${MSG_PREFIX} No ETL installation was found with find_package. Installing and providing "
|
||||
"etl with FindPackage")
|
||||
"${MSG_PREFIX} ETL installation not found. Downloading ETL with FetchContent."
|
||||
)
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
|
@ -58,12 +58,7 @@ void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
|
||||
this->hkDestination = hkDestination;
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId,
|
||||
lp_id_t heaterRequestPoolId,
|
||||
uint32_t thermalSetId) {
|
||||
thermalSet =
|
||||
new DeviceHandlerThermalSet(this, thermalSetId, thermalStatePoolId, heaterRequestPoolId);
|
||||
}
|
||||
void DeviceHandlerBase::enableThermalModule(ThermalStateCfg cfg) { this->thermalStateCfg = cfg; }
|
||||
|
||||
DeviceHandlerBase::~DeviceHandlerBase() {
|
||||
if (comCookie != nullptr) {
|
||||
@ -227,12 +222,11 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
fillCommandAndReplyMap();
|
||||
|
||||
if (thermalSet != nullptr) {
|
||||
PoolReadGuard pg(thermalSet);
|
||||
// Set temperature target state to NON_OP.
|
||||
result = thermalSet->read();
|
||||
if (result == returnvalue::OK) {
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
||||
thermalSet->heaterRequest.setValid(true);
|
||||
thermalSet->commit();
|
||||
}
|
||||
}
|
||||
|
||||
@ -594,12 +588,12 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
||||
Clock::getUptime(&timeoutStart);
|
||||
|
||||
if (mode == MODE_OFF and thermalSet != nullptr) {
|
||||
ReturnValue_t result = thermalSet->read();
|
||||
if (result == returnvalue::OK) {
|
||||
PoolReadGuard pg(thermalSet);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
||||
}
|
||||
thermalSet->heaterRequest.commit(PoolVariableIF::VALID);
|
||||
thermalSet->heaterRequest.setValid(true);
|
||||
}
|
||||
}
|
||||
/* TODO: This will probably be done by the LocalDataPoolManager now */
|
||||
@ -1088,8 +1082,8 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_
|
||||
// Do not check thermal state for MODE_RAW
|
||||
if ((mode == MODE_OFF) and ((commandedMode == MODE_ON) or (commandedMode == MODE_NORMAL)) and
|
||||
(thermalSet != nullptr)) {
|
||||
ReturnValue_t result = thermalSet->read();
|
||||
if (result == returnvalue::OK) {
|
||||
PoolReadGuard pg(thermalSet);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and
|
||||
(not ThermalComponentIF::isOperational(thermalSet->thermalState.value))) {
|
||||
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalSet->thermalState.value);
|
||||
@ -1150,11 +1144,10 @@ void DeviceHandlerBase::handleTransitionToOnMode(Mode_t commandedMode, Submode_t
|
||||
childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON);
|
||||
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
|
||||
if (thermalSet != nullptr) {
|
||||
ReturnValue_t result = thermalSet->read();
|
||||
if (result == returnvalue::OK) {
|
||||
PoolReadGuard pg(thermalSet);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
if (thermalSet->heaterRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||
thermalSet->heaterRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
|
||||
thermalSet->commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1477,11 +1470,11 @@ void DeviceHandlerBase::performOperationHook() {}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) {
|
||||
if (thermalSet != nullptr) {
|
||||
localDataPoolMap.emplace(thermalSet->thermalStatePoolId,
|
||||
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>);
|
||||
localDataPoolMap.emplace(thermalSet->heaterRequestPoolId,
|
||||
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>);
|
||||
if (thermalStateCfg.has_value()) {
|
||||
localDataPoolMap.emplace(thermalStateCfg.value().thermalStatePoolId,
|
||||
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>());
|
||||
localDataPoolMap.emplace(thermalStateCfg.value().thermalRequestPoolId,
|
||||
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>());
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
@ -1494,6 +1487,10 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
|
||||
}
|
||||
this->poolManager.initializeAfterTaskCreation();
|
||||
|
||||
if (thermalStateCfg.has_value()) {
|
||||
ThermalStateCfg& cfg = thermalStateCfg.value();
|
||||
thermalSet = new DeviceHandlerThermalSet(this, cfg);
|
||||
}
|
||||
if (setStartupImmediately) {
|
||||
startTransition(MODE_ON, getInitialSubmode());
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
#include "DeviceCommunicationIF.h"
|
||||
#include "DeviceHandlerFailureIsolation.h"
|
||||
@ -163,13 +164,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
* The device handler will then take care of creating local pool entries
|
||||
* for the device thermal state and device heating request.
|
||||
* Custom local pool IDs can be assigned as well.
|
||||
* @param thermalStatePoolId
|
||||
* @param thermalRequestPoolId
|
||||
*/
|
||||
void setThermalStateRequestPoolIds(
|
||||
lp_id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
|
||||
lp_id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID,
|
||||
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID);
|
||||
void enableThermalModule(ThermalStateCfg cfg);
|
||||
|
||||
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
|
||||
ModeTreeChildIF &getModeTreeChildIF() override;
|
||||
@ -931,6 +927,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
//! Object which may be the root cause of an identified fault.
|
||||
static object_id_t defaultFdirParentId;
|
||||
|
||||
std::optional<ThermalStateCfg> thermalStateCfg;
|
||||
|
||||
/**
|
||||
* @brief Send a reply to a received device handler command.
|
||||
*
|
||||
|
@ -136,4 +136,10 @@ class DeviceHandlerIF {
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
};
|
||||
|
||||
struct ThermalStateCfg {
|
||||
lp_id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID;
|
||||
lp_id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID;
|
||||
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID;
|
||||
};
|
||||
|
||||
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */
|
||||
|
@ -7,27 +7,21 @@
|
||||
|
||||
class DeviceHandlerThermalSet : public StaticLocalDataSet<2> {
|
||||
public:
|
||||
DeviceHandlerThermalSet(
|
||||
HasLocalDataPoolIF* hkOwner, uint32_t setId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID,
|
||||
lp_id_t thermalStateId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
|
||||
lp_id_t heaterRequestId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID)
|
||||
: DeviceHandlerThermalSet(hkOwner->getObjectId(), setId, thermalStateId, heaterRequestId) {}
|
||||
DeviceHandlerThermalSet(HasLocalDataPoolIF* hkOwner, ThermalStateCfg cfg)
|
||||
: DeviceHandlerThermalSet(hkOwner->getObjectId(), cfg) {}
|
||||
|
||||
DeviceHandlerThermalSet(
|
||||
object_id_t deviceHandler, uint32_t setId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID,
|
||||
lp_id_t thermalStateId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
|
||||
lp_id_t thermalStateRequestId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID)
|
||||
: StaticLocalDataSet(sid_t(deviceHandler, setId)),
|
||||
thermalStatePoolId(thermalStateId),
|
||||
heaterRequestPoolId(thermalStateRequestId) {}
|
||||
DeviceHandlerThermalSet(object_id_t deviceHandler, ThermalStateCfg cfg)
|
||||
: StaticLocalDataSet(sid_t(deviceHandler, cfg.thermalSetId)),
|
||||
thermalStatePoolId(cfg.thermalStatePoolId),
|
||||
heaterRequestPoolId(cfg.thermalRequestPoolId) {}
|
||||
|
||||
const lp_id_t thermalStatePoolId;
|
||||
const lp_id_t heaterRequestPoolId;
|
||||
|
||||
lp_var_t<DeviceHandlerIF::dh_thermal_state_t> thermalState =
|
||||
lp_var_t<DeviceHandlerIF::dh_thermal_state_t>(thermalStatePoolId, sid.objectId, this);
|
||||
lp_var_t<DeviceHandlerIF::dh_thermal_state_t>(sid.objectId, thermalStatePoolId, this);
|
||||
lp_var_t<DeviceHandlerIF::dh_heater_request_t> heaterRequest =
|
||||
lp_var_t<DeviceHandlerIF::dh_heater_request_t>(heaterRequestPoolId, sid.objectId, this);
|
||||
lp_var_t<DeviceHandlerIF::dh_heater_request_t>(sid.objectId, heaterRequestPoolId, this);
|
||||
};
|
||||
|
||||
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_ */
|
||||
|
@ -41,6 +41,7 @@ int TcpIpBase::closeSocket(socket_t socket) {
|
||||
#elif defined(PLATFORM_UNIX)
|
||||
return close(socket);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int TcpIpBase::getLastSocketError() {
|
||||
@ -49,4 +50,5 @@ int TcpIpBase::getLastSocketError() {
|
||||
#elif defined(PLATFORM_UNIX)
|
||||
return errno;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) {
|
||||
switch (subservice) {
|
||||
case (Subservice::COMMAND_MODE_COMMAND):
|
||||
case (Subservice::COMMAND_MODE_READ):
|
||||
case (Subservice::COMMAND_MODE_ANNCOUNCE):
|
||||
case (Subservice::COMMAND_MODE_ANNOUNCE):
|
||||
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
|
||||
return returnvalue::OK;
|
||||
default:
|
||||
@ -54,6 +54,7 @@ ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue(
|
||||
ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
|
||||
const uint8_t *tcData, size_t tcDataLen,
|
||||
uint32_t *state, object_id_t objectId) {
|
||||
bool recursive = false;
|
||||
switch (subservice) {
|
||||
case (Subservice::COMMAND_MODE_COMMAND): {
|
||||
ModePacket modeCommandPacket;
|
||||
@ -67,22 +68,17 @@ ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message,
|
||||
modeCommandPacket.getMode(), modeCommandPacket.getSubmode());
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (Subservice::COMMAND_MODE_ANNCOUNCE):
|
||||
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY): {
|
||||
bool recursive = true;
|
||||
if (subservice == Subservice::COMMAND_MODE_ANNCOUNCE) {
|
||||
recursive = false;
|
||||
}
|
||||
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
|
||||
recursive = true;
|
||||
[[fallthrough]];
|
||||
case (Subservice::COMMAND_MODE_ANNOUNCE):
|
||||
ModeMessage::setModeAnnounceMessage(*message, recursive);
|
||||
return EXECUTION_COMPLETE;
|
||||
}
|
||||
case (Subservice::COMMAND_MODE_READ): {
|
||||
case (Subservice::COMMAND_MODE_READ):
|
||||
ModeMessage::setModeReadMessage(*message);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
default: {
|
||||
default:
|
||||
return CommandingServiceBase::INVALID_SUBSERVICE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ class CService200ModeCommanding : public CommandingServiceBase {
|
||||
COMMAND_MODE_READ = 3,
|
||||
//!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event.
|
||||
//! This command does NOT have a reply
|
||||
COMMAND_MODE_ANNCOUNCE = 4,
|
||||
COMMAND_MODE_ANNOUNCE = 4,
|
||||
//!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this
|
||||
//! command to every child. This command does NOT have a reply.
|
||||
COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5,
|
||||
|
@ -160,7 +160,7 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
|
||||
// (See requirement for Time margin)
|
||||
timeval tNow = {};
|
||||
Clock::getClock_timeval(&tNow);
|
||||
if (timestamp - tNow.tv_sec <= RELEASE_TIME_MARGIN_SECONDS) {
|
||||
if (timestamp < tNow.tv_sec + RELEASE_TIME_MARGIN_SECONDS) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Service11TelecommandScheduling::doInsertActivity: Release time too close to "
|
||||
"current time"
|
||||
|
@ -145,13 +145,17 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 3 */
|
||||
|
||||
if (communicationLinkUp == false or packetSentCounter >= sentPacketsPerCycle) {
|
||||
storeDownlinkData(&message);
|
||||
ReturnValue_t result = storeDownlinkData(&message);
|
||||
if (result != returnvalue::OK) {
|
||||
tmStore->deleteData(message.getStorageId());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
result = tmStore->getData(message.getStorageId(), &data, &size);
|
||||
if (result != returnvalue::OK) {
|
||||
status = result;
|
||||
tmStore->deleteData(message.getStorageId());
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -159,9 +163,9 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
|
||||
if (result != returnvalue::OK) {
|
||||
status = result;
|
||||
} else {
|
||||
tmStore->deleteData(message.getStorageId());
|
||||
packetSentCounter++;
|
||||
}
|
||||
tmStore->deleteData(message.getStorageId());
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
||||
public:
|
||||
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
|
||||
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
|
||||
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 1000;
|
||||
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 500;
|
||||
|
||||
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
|
||||
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "version.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "fsfw/FSFWVersion.h"
|
||||
|
||||
@ -20,7 +21,7 @@ fsfw::Version::Version(int major, int minor, int revision, const char* addInfo)
|
||||
|
||||
void fsfw::Version::getVersion(char* str, size_t maxLen) const {
|
||||
size_t len = snprintf(str, maxLen, "%d.%d.%d", major, minor, revision);
|
||||
if (addInfo != nullptr) {
|
||||
if (addInfo != nullptr and std::strcmp(addInfo, "") != 0) {
|
||||
snprintf(str + len, maxLen - len, "-%s", addInfo);
|
||||
}
|
||||
}
|
||||
@ -30,7 +31,7 @@ namespace fsfw {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
std::ostream& operator<<(std::ostream& os, const Version& v) {
|
||||
os << v.major << "." << v.minor << "." << v.revision;
|
||||
if (v.addInfo != nullptr) {
|
||||
if (v.addInfo != nullptr and std::strcmp(v.addInfo, "") != 0) {
|
||||
os << "-" << v.addInfo;
|
||||
}
|
||||
return os;
|
||||
|
@ -179,12 +179,11 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
||||
uint32_t spiSpeed = 0;
|
||||
spiCookie->getSpiParameters(spiMode, spiSpeed, nullptr);
|
||||
setSpiSpeedAndMode(fileDescriptor, spiMode, spiSpeed);
|
||||
spiCookie->assignWriteBuffer(sendData);
|
||||
spiCookie->setTransferSize(sendLen);
|
||||
|
||||
bool fullDuplex = spiCookie->isFullDuplex();
|
||||
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
||||
bool csLockManual = spiCookie->getCsLockManual();
|
||||
spiCookie->setTransferSize(0);
|
||||
|
||||
MutexIF::TimeoutType csType;
|
||||
dur_millis_t csTimeout = 0;
|
||||
@ -195,9 +194,13 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
||||
if (result != returnvalue::OK) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "SpiComIF::sendMessage: Failed to lock mutex with code "
|
||||
<< "0x" << std::hex << std::setfill('0') << std::setw(4) << result << std::dec
|
||||
<< std::endl;
|
||||
if (result == MutexIF::MUTEX_TIMEOUT) {
|
||||
sif::error << "SpiComIF::sendMessage: Lock timeout" << std::endl;
|
||||
} else {
|
||||
sif::error << "SpiComIF::sendMessage: Failed to lock mutex with code "
|
||||
<< "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
|
||||
@ -214,17 +217,22 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
||||
sif::printWarning("SpiComIF::sendMessage: Pulling low CS pin failed");
|
||||
#endif
|
||||
#endif
|
||||
csMutex->unlockMutex();
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
updateLinePolarity(fileDescriptor);
|
||||
}
|
||||
|
||||
spiCookie->assignWriteBuffer(sendData);
|
||||
spiCookie->setTransferSize(sendLen);
|
||||
|
||||
/* Execute transfer */
|
||||
if (fullDuplex) {
|
||||
/* Initiate a full duplex SPI transfer. */
|
||||
retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), spiCookie->getTransferStructHandle());
|
||||
if (retval < 0) {
|
||||
spiCookie->setTransferSize(0);
|
||||
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
|
||||
result = FULL_DUPLEX_TRANSFER_FAILED;
|
||||
}
|
||||
@ -234,6 +242,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
||||
} else {
|
||||
/* We write with a blocking half-duplex transfer here */
|
||||
if (write(fileDescriptor, sendData, sendLen) != static_cast<ssize_t>(sendLen)) {
|
||||
spiCookie->setTransferSize(0);
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "SpiComIF::sendMessage: Half-Duplex write operation failed!" << std::endl;
|
||||
|
Loading…
Reference in New Issue
Block a user