it appears to work well now
This commit is contained in:
parent
9d59f960a4
commit
c6c92e1140
2
fsfw
2
fsfw
@ -1 +1 @@
|
|||||||
Subproject commit fe41d73895270cbe4d80ebfbc41ff9f0b8b02126
|
Subproject commit a6d707a7db589136ac2bd917cd8b3a3e2c16a0e4
|
@ -4,6 +4,7 @@
|
|||||||
#include <fsfw/globalfunctions/CRC.h>
|
#include <fsfw/globalfunctions/CRC.h>
|
||||||
#include <fsfw/tasks/SemaphoreFactory.h>
|
#include <fsfw/tasks/SemaphoreFactory.h>
|
||||||
#include <fsfw/tasks/TaskFactory.h>
|
#include <fsfw/tasks/TaskFactory.h>
|
||||||
|
#include <fsfw/timemanager/Stopwatch.h>
|
||||||
#include <fsfw_hal/common/spi/spiCommon.h>
|
#include <fsfw_hal/common/spi/spiCommon.h>
|
||||||
#include <fsfw_hal/linux/utility.h>
|
#include <fsfw_hal/linux/utility.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
@ -32,11 +33,14 @@ ReturnValue_t RwPollingTask::performOperation(uint8_t operationCode) {
|
|||||||
state = InternalState::IDLE;
|
state = InternalState::IDLE;
|
||||||
ipcLock->unlockMutex();
|
ipcLock->unlockMutex();
|
||||||
semaphore->acquire();
|
semaphore->acquire();
|
||||||
|
// This loop takes 50 ms on a debug build.
|
||||||
|
// Stopwatch watch;
|
||||||
TaskFactory::delayTask(5);
|
TaskFactory::delayTask(5);
|
||||||
int fd = 0;
|
int fd = 0;
|
||||||
for (auto& skip : skipCommandingForRw) {
|
for (auto& skip : skipCommandingForRw) {
|
||||||
skip = false;
|
skip = false;
|
||||||
}
|
}
|
||||||
|
setAllReadFlagsFalse();
|
||||||
ReturnValue_t result = openSpi(O_RDWR, fd);
|
ReturnValue_t result = openSpi(O_RDWR, fd);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
continue;
|
continue;
|
||||||
@ -55,27 +59,26 @@ ReturnValue_t RwPollingTask::performOperation(uint8_t operationCode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
closeSpi(fd);
|
closeSpi(fd);
|
||||||
usleep(rws::SPI_REPLY_DELAY);
|
|
||||||
if (readAllRws(rws::SET_SPEED) != returnvalue::OK) {
|
if (readAllRws(rws::SET_SPEED) != returnvalue::OK) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// prepareSimpleCommand(rws::GET_LAST_RESET_STATUS);
|
prepareSimpleCommand(rws::GET_LAST_RESET_STATUS);
|
||||||
// if (writeAndReadAllRws(rws::GET_LAST_RESET_STATUS) != returnvalue::OK) {
|
if (writeAndReadAllRws(rws::GET_LAST_RESET_STATUS) != returnvalue::OK) {
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// prepareSimpleCommand(rws::GET_RW_STATUS);
|
prepareSimpleCommand(rws::GET_RW_STATUS);
|
||||||
// if (writeAndReadAllRws(rws::GET_RW_STATUS) != returnvalue::OK) {
|
if (writeAndReadAllRws(rws::GET_RW_STATUS) != returnvalue::OK) {
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// prepareSimpleCommand(rws::GET_TEMPERATURE);
|
prepareSimpleCommand(rws::GET_TEMPERATURE);
|
||||||
// if (writeAndReadAllRws(rws::GET_TEMPERATURE) != returnvalue::OK) {
|
if (writeAndReadAllRws(rws::GET_TEMPERATURE) != returnvalue::OK) {
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// prepareSimpleCommand(rws::CLEAR_LAST_RESET_STATUS);
|
prepareSimpleCommand(rws::CLEAR_LAST_RESET_STATUS);
|
||||||
// if (writeAndReadAllRws(rws::CLEAR_LAST_RESET_STATUS) != returnvalue::OK) {
|
if (writeAndReadAllRws(rws::CLEAR_LAST_RESET_STATUS) != returnvalue::OK) {
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
// handleSpecialRequests();
|
handleSpecialRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
@ -188,7 +191,6 @@ ReturnValue_t RwPollingTask::writeAndReadAllRws(DeviceCommandId_t id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
closeSpi(fd);
|
closeSpi(fd);
|
||||||
usleep(rws::SPI_REPLY_DELAY);
|
|
||||||
return readAllRws(id);
|
return readAllRws(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,50 +210,39 @@ ReturnValue_t RwPollingTask::readNextReply(RwCookie& rwCookie, uint8_t* replyBuf
|
|||||||
int fd = 0;
|
int fd = 0;
|
||||||
gpioId_t gpioId = rwCookie.getChipSelectPin();
|
gpioId_t gpioId = rwCookie.getChipSelectPin();
|
||||||
uint8_t byteRead = 0;
|
uint8_t byteRead = 0;
|
||||||
bool exitOuter = false;
|
result = openSpi(O_RDWR, fd);
|
||||||
for (unsigned retryIdx = 0; retryIdx < MAX_RETRIES_REPLY; retryIdx++) {
|
if (result != returnvalue::OK) {
|
||||||
/**
|
return result;
|
||||||
* The reaction wheel responds with empty frames while preparing the reply data.
|
}
|
||||||
* However, receiving more than 5 empty frames will be interpreted as an error.
|
pullCsLow(gpioId, gpioIF);
|
||||||
*/
|
bool lastByteWasFrameMarker = false;
|
||||||
for (int idx = 0; idx < 5; idx++) {
|
Countdown cd(3000);
|
||||||
result = openSpi(O_RDWR, fd);
|
size_t readIdx = 0;
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
pullCsLow(gpioId, gpioIF);
|
|
||||||
if (read(fd, &byteRead, 1) != 1) {
|
|
||||||
sif::error << "RwPollingTask: Read failed. " << strerror(errno) << std::endl;
|
|
||||||
pullCsHigh(gpioId, gpioIF);
|
|
||||||
closeSpi(fd);
|
|
||||||
return rws::SPI_READ_FAILURE;
|
|
||||||
}
|
|
||||||
if (idx == 0) {
|
|
||||||
if (byteRead != rws::FRAME_DELIMITER) {
|
|
||||||
sif::error << "Invalid data, expected start marker, got " << (int)byteRead << std::endl;
|
|
||||||
pullCsHigh(gpioId, gpioIF);
|
|
||||||
closeSpi(fd);
|
|
||||||
return rws::NO_START_MARKER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (byteRead != rws::FRAME_DELIMITER) {
|
|
||||||
exitOuter = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
lastByteWasFrameMarker = false;
|
||||||
|
if (read(fd, &byteRead, 1) != 1) {
|
||||||
|
sif::error << "RwPollingTask: Read failed. " << strerror(errno) << std::endl;
|
||||||
pullCsHigh(gpioId, gpioIF);
|
pullCsHigh(gpioId, gpioIF);
|
||||||
closeSpi(fd);
|
closeSpi(fd);
|
||||||
if (idx == MAX_RETRIES_REPLY - 1) {
|
return rws::SPI_READ_FAILURE;
|
||||||
sif::error << "rwSpiCallback::spiCallback: Empty frame timeout" << std::endl;
|
|
||||||
return rws::NO_REPLY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(exitOuter) {
|
if (byteRead == rws::FRAME_DELIMITER) {
|
||||||
|
lastByteWasFrameMarker = true;
|
||||||
|
}
|
||||||
|
// Start of frame detected.
|
||||||
|
if (byteRead != rws::FRAME_DELIMITER and not lastByteWasFrameMarker) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
TaskFactory::delayTask(5);
|
|
||||||
|
if (readIdx % 100 == 0 && cd.hasTimedOut()) {
|
||||||
|
pullCsHigh(gpioId, gpioIF);
|
||||||
|
closeSpi(fd);
|
||||||
|
return rws::SPI_READ_FAILURE;
|
||||||
|
}
|
||||||
|
readIdx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FSFW_HAL_SPI_WIRETAPPING == 1
|
#if FSFW_HAL_SPI_WIRETAPPING == 1
|
||||||
sif::info << "RW start marker detected" << std::endl;
|
sif::info << "RW start marker detected" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
@ -339,13 +330,14 @@ ReturnValue_t RwPollingTask::readAllRws(DeviceCommandId_t id) {
|
|||||||
if (((id == rws::SET_SPEED) and !rwCookies[idx]->setSpeed) or skipCommandingForRw[idx]) {
|
if (((id == rws::SET_SPEED) and !rwCookies[idx]->setSpeed) or skipCommandingForRw[idx]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (spiLock == nullptr) {
|
|
||||||
sif::debug << "rwSpiCallback::spiCallback: Mutex or GPIO interface invalid" << std::endl;
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
uint8_t* replyBuf;
|
uint8_t* replyBuf;
|
||||||
size_t maxReadLen = idAndIdxToReadBuffer(id, idx, &replyBuf);
|
size_t maxReadLen = idAndIdxToReadBuffer(id, idx, &replyBuf);
|
||||||
readNextReply(*rwCookies[idx], replyBuf, maxReadLen);
|
ReturnValue_t result = readNextReply(*rwCookies[idx], replyBuf + 1, maxReadLen);
|
||||||
|
if (result == returnvalue::OK) {
|
||||||
|
// The first byte is always a flag which shows whether the value was read
|
||||||
|
// properly at least once.
|
||||||
|
replyBuf[0] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// SPI is closed in readNextReply as well.
|
// SPI is closed in readNextReply as well.
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
@ -440,6 +432,19 @@ void RwPollingTask::handleSpecialRequests() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RwPollingTask::setAllReadFlagsFalse() {
|
||||||
|
for (auto& rwCookie : rwCookies) {
|
||||||
|
RwReplies replies(rwCookie->replyBuf.data());
|
||||||
|
replies.getLastResetStatusReply[0] = false;
|
||||||
|
replies.clearLastResetStatusReply[0] = false;
|
||||||
|
replies.hkDataReply[0] = false;
|
||||||
|
replies.readTemperatureReply[0] = false;
|
||||||
|
replies.rwStatusReply[0] = false;
|
||||||
|
replies.setSpeedReply[0] = false;
|
||||||
|
replies.initRwControllerReply[0] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This closes the SPI
|
// This closes the SPI
|
||||||
void RwPollingTask::closeSpi(int fd) {
|
void RwPollingTask::closeSpi(int fd) {
|
||||||
// This will perform the function to close the SPI
|
// This will perform the function to close the SPI
|
||||||
@ -453,10 +458,10 @@ ReturnValue_t RwPollingTask::sendOneMessage(int fd, RwCookie& rwCookie) {
|
|||||||
sif::debug << "rwSpiCallback::spiCallback: Mutex or GPIO interface invalid" << std::endl;
|
sif::debug << "rwSpiCallback::spiCallback: Mutex or GPIO interface invalid" << std::endl;
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
pullCsLow(gpioId, gpioIF);
|
|
||||||
// Add datalinklayer like specified in the datasheet.
|
// Add datalinklayer like specified in the datasheet.
|
||||||
size_t lenToSend = 0;
|
size_t lenToSend = 0;
|
||||||
rws::encodeHdlc(writeBuffer.data(), writeLen, encodedBuffer.data(), lenToSend);
|
rws::encodeHdlc(writeBuffer.data(), writeLen, encodedBuffer.data(), lenToSend);
|
||||||
|
pullCsLow(gpioId, gpioIF);
|
||||||
if (write(fd, encodedBuffer.data(), lenToSend) != static_cast<ssize_t>(lenToSend)) {
|
if (write(fd, encodedBuffer.data(), lenToSend) != static_cast<ssize_t>(lenToSend)) {
|
||||||
sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl;
|
sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl;
|
||||||
pullCsHigh(gpioId, gpioIF);
|
pullCsHigh(gpioId, gpioIF);
|
||||||
@ -513,7 +518,7 @@ ReturnValue_t RwPollingTask::prepareSetSpeedCmd(uint8_t rwIdx) {
|
|||||||
speedToSet = rwCookies[rwIdx]->currentRwSpeed;
|
speedToSet = rwCookies[rwIdx]->currentRwSpeed;
|
||||||
rampTimeToSet = rwCookies[rwIdx]->currentRampTime;
|
rampTimeToSet = rwCookies[rwIdx]->currentRampTime;
|
||||||
}
|
}
|
||||||
size_t serLen = 0;
|
size_t serLen = 1;
|
||||||
SerializeAdapter::serialize(&speedToSet, &serPtr, &serLen, writeBuffer.size(),
|
SerializeAdapter::serialize(&speedToSet, &serPtr, &serLen, writeBuffer.size(),
|
||||||
SerializeIF::Endianness::LITTLE);
|
SerializeIF::Endianness::LITTLE);
|
||||||
SerializeAdapter::serialize(&rampTimeToSet, &serPtr, &serLen, writeBuffer.size(),
|
SerializeAdapter::serialize(&rampTimeToSet, &serPtr, &serLen, writeBuffer.size(),
|
||||||
|
@ -80,6 +80,7 @@ class RwPollingTask : public SystemObject, public ExecutableObjectIF, public Dev
|
|||||||
|
|
||||||
size_t idAndIdxToReadBuffer(DeviceCommandId_t id, uint8_t rwIdx, uint8_t** readPtr);
|
size_t idAndIdxToReadBuffer(DeviceCommandId_t id, uint8_t rwIdx, uint8_t** readPtr);
|
||||||
void fillSpecialRequestArray();
|
void fillSpecialRequestArray();
|
||||||
|
void setAllReadFlagsFalse();
|
||||||
|
|
||||||
void pullCsHigh(gpioId_t gpioId, GpioIF& gpioIF);
|
void pullCsHigh(gpioId_t gpioId, GpioIF& gpioIF);
|
||||||
void closeSpi(int);
|
void closeSpi(int);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <fsfw/datapool/PoolReadGuard.h>
|
#include <fsfw/datapool/PoolReadGuard.h>
|
||||||
#include <fsfw/globalfunctions/CRC.h>
|
#include <fsfw/globalfunctions/CRC.h>
|
||||||
|
#include <fsfw/globalfunctions/arrayprinter.h>
|
||||||
#include <fsfw_hal/common/gpio/GpioIF.h>
|
#include <fsfw_hal/common/gpio/GpioIF.h>
|
||||||
|
|
||||||
#include "OBSWConfig.h"
|
#include "OBSWConfig.h"
|
||||||
@ -51,26 +52,6 @@ ReturnValue_t RwHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
|||||||
*id = rws::REQUEST_ID;
|
*id = rws::REQUEST_ID;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// case InternalState::SET_SPEED:
|
|
||||||
// *id = rws::SET_SPEED;
|
|
||||||
// internalState = InternalState::GET_RESET_STATUS;
|
|
||||||
// break;
|
|
||||||
// case InternalState::GET_RESET_STATUS:
|
|
||||||
// *id = rws::GET_LAST_RESET_STATUS;
|
|
||||||
// internalState = InternalState::READ_TEMPERATURE;
|
|
||||||
// break;
|
|
||||||
// case InternalState::READ_TEMPERATURE:
|
|
||||||
// *id = rws::GET_TEMPERATURE;
|
|
||||||
// internalState = InternalState::GET_RW_SATUS;
|
|
||||||
// break;
|
|
||||||
// case InternalState::GET_RW_SATUS:
|
|
||||||
// *id = rws::GET_RW_STATUS;
|
|
||||||
// internalState = InternalState::CLEAR_RESET_STATUS;
|
|
||||||
// break;
|
|
||||||
// case InternalState::CLEAR_RESET_STATUS:
|
|
||||||
// *id = rws::CLEAR_LAST_RESET_STATUS;
|
|
||||||
// /** After reset status is cleared, reset status will be polled again for verification
|
|
||||||
// */ internalState = InternalState::GET_RESET_STATUS; break;
|
|
||||||
default:
|
default:
|
||||||
sif::debug << "RwHandler::buildNormalDeviceCommand: Invalid internal step" << std::endl;
|
sif::debug << "RwHandler::buildNormalDeviceCommand: Invalid internal step" << std::endl;
|
||||||
break;
|
break;
|
||||||
@ -88,6 +69,7 @@ ReturnValue_t RwHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand
|
|||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
|
|
||||||
switch (deviceCommand) {
|
switch (deviceCommand) {
|
||||||
|
case (rws::SET_SPEED):
|
||||||
case (rws::REQUEST_ID): {
|
case (rws::REQUEST_ID): {
|
||||||
if (commandData != nullptr && commandDataLen != 6) {
|
if (commandData != nullptr && commandDataLen != 6) {
|
||||||
sif::error << "RwHandler::buildCommandFromCommand: Received set speed command with"
|
sif::error << "RwHandler::buildCommandFromCommand: Received set speed command with"
|
||||||
@ -148,66 +130,6 @@ ReturnValue_t RwHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand
|
|||||||
internalState = InternalState::GET_TM;
|
internalState = InternalState::GET_TM;
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// case (rws::GET_LAST_RESET_STATUS): {
|
|
||||||
// prepareSimpleCommand(deviceCommand);
|
|
||||||
// return returnvalue::OK;
|
|
||||||
// }
|
|
||||||
// case (rws::CLEAR_LAST_RESET_STATUS): {
|
|
||||||
// prepareSimpleCommand(deviceCommand);
|
|
||||||
// return returnvalue::OK;
|
|
||||||
// }
|
|
||||||
// case (rws::GET_RW_STATUS): {
|
|
||||||
// prepareSimpleCommand(deviceCommand);
|
|
||||||
// return returnvalue::OK;
|
|
||||||
// }
|
|
||||||
// case (rws::INIT_RW_CONTROLLER): {
|
|
||||||
// prepareSimpleCommand(deviceCommand);
|
|
||||||
// return returnvalue::OK;
|
|
||||||
// }
|
|
||||||
// case (rws::SET_SPEED): {
|
|
||||||
// if (commandData != nullptr && commandDataLen != 6) {
|
|
||||||
// sif::error << "RwHandler::buildCommandFromCommand: Received set speed command with"
|
|
||||||
// << " invalid length" << std::endl;
|
|
||||||
// return SET_SPEED_COMMAND_INVALID_LENGTH;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// {
|
|
||||||
// PoolReadGuard pg(&rwSpeedActuationSet);
|
|
||||||
// // Commands override anything which was set in the software
|
|
||||||
// if (commandData != nullptr) {
|
|
||||||
// rwSpeedActuationSet.setValidityBufferGeneration(false);
|
|
||||||
// result = rwSpeedActuationSet.deSerialize(&commandData, &commandDataLen,
|
|
||||||
// SerializeIF::Endianness::NETWORK);
|
|
||||||
// rwSpeedActuationSet.setValidityBufferGeneration(true);
|
|
||||||
// if (result != returnvalue::OK) {
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (ACTUATION_WIRETAPPING) {
|
|
||||||
// int32_t speed = 0;
|
|
||||||
// uint16_t rampTime = 0;
|
|
||||||
// rwSpeedActuationSet.getRwSpeed(speed, rampTime);
|
|
||||||
// sif::debug << "Actuating RW " << static_cast<int>(rwIdx) << " with speed = " <<
|
|
||||||
// speed
|
|
||||||
// << " and rampTime = " << rampTime << std::endl;
|
|
||||||
// }
|
|
||||||
// result = checkSpeedAndRampTime();
|
|
||||||
// if (result != returnvalue::OK) {
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
// result = prepareSetSpeedCmd();
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
// case (rws::GET_TEMPERATURE): {
|
|
||||||
// prepareSimpleCommand(deviceCommand);
|
|
||||||
// return returnvalue::OK;
|
|
||||||
// }
|
|
||||||
// case (rws::GET_TM): {
|
|
||||||
// prepareSimpleCommand(deviceCommand);
|
|
||||||
// return returnvalue::OK;
|
|
||||||
// }
|
|
||||||
default:
|
default:
|
||||||
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
|
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
@ -219,20 +141,9 @@ void RwHandler::fillCommandAndReplyMap() {
|
|||||||
insertInReplyMap(rws::REPLY_ID, 5, nullptr, 0, true);
|
insertInReplyMap(rws::REPLY_ID, 5, nullptr, 0, true);
|
||||||
|
|
||||||
insertInCommandMap(rws::RESET_MCU);
|
insertInCommandMap(rws::RESET_MCU);
|
||||||
|
insertInCommandMap(rws::SET_SPEED);
|
||||||
insertInCommandAndReplyMap(rws::INIT_RW_CONTROLLER, 5, nullptr, 0, false, true, rws::REPLY_ID);
|
insertInCommandAndReplyMap(rws::INIT_RW_CONTROLLER, 5, nullptr, 0, false, true, rws::REPLY_ID);
|
||||||
insertInCommandAndReplyMap(rws::GET_TM, 5, nullptr, 0, false, true, rws::REPLY_ID);
|
insertInCommandAndReplyMap(rws::GET_TM, 5, nullptr, 0, false, true, rws::REPLY_ID);
|
||||||
/*
|
|
||||||
this->insertInCommandAndReplyMap(rws::GET_LAST_RESET_STATUS, 1, &lastResetStatusSet,
|
|
||||||
rws::SIZE_GET_RESET_STATUS);
|
|
||||||
this->insertInCommandAndReplyMap(rws::CLEAR_LAST_RESET_STATUS, 1, nullptr,
|
|
||||||
rws::SIZE_CLEAR_RESET_STATUS);
|
|
||||||
this->insertInCommandAndReplyMap(rws::GET_RW_STATUS, 1, &statusSet, rws::SIZE_GET_RW_STATUS);
|
|
||||||
this->insertInCommandAndReplyMap(rws::INIT_RW_CONTROLLER, 1, nullptr, rws::SIZE_INIT_RW);
|
|
||||||
this->insertInCommandAndReplyMap(rws::GET_TEMPERATURE, 1, nullptr,
|
|
||||||
rws::SIZE_GET_TEMPERATURE_REPLY);
|
|
||||||
this->insertInCommandAndReplyMap(rws::SET_SPEED, 1, nullptr, rws::SIZE_SET_SPEED_REPLY);
|
|
||||||
this->insertInCommandAndReplyMap(rws::GET_TM, 1, &tmDataset, rws::SIZE_GET_TELEMETRY_REPLY);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t RwHandler::scanForReply(const uint8_t* start, size_t remainingSize,
|
ReturnValue_t RwHandler::scanForReply(const uint8_t* start, size_t remainingSize,
|
||||||
@ -240,64 +151,28 @@ ReturnValue_t RwHandler::scanForReply(const uint8_t* start, size_t remainingSize
|
|||||||
if (getMode() == _MODE_WAIT_OFF) {
|
if (getMode() == _MODE_WAIT_OFF) {
|
||||||
return IGNORE_FULL_PACKET;
|
return IGNORE_FULL_PACKET;
|
||||||
}
|
}
|
||||||
// sif::debug << "base mode: " << baseMode << std::endl;
|
|
||||||
if (remainingSize > 0) {
|
if (remainingSize > 0) {
|
||||||
*foundLen = remainingSize;
|
*foundLen = remainingSize;
|
||||||
*foundId = rws::REPLY_ID;
|
*foundId = rws::REPLY_ID;
|
||||||
}
|
}
|
||||||
// RwReplies replies(start);
|
|
||||||
// switch (replyByte) {
|
|
||||||
// case (rws::GET_LAST_RESET_STATUS): {
|
|
||||||
// *foundLen = rws::SIZE_GET_RESET_STATUS;
|
|
||||||
// *foundId = rws::GET_LAST_RESET_STATUS;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case (rws::CLEAR_LAST_RESET_STATUS): {
|
|
||||||
// *foundLen = rws::SIZE_CLEAR_RESET_STATUS;
|
|
||||||
// *foundId = rws::CLEAR_LAST_RESET_STATUS;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case (rws::GET_RW_STATUS): {
|
|
||||||
// *foundLen = rws::SIZE_GET_RW_STATUS;
|
|
||||||
// *foundId = rws::GET_RW_STATUS;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case (rws::INIT_RW_CONTROLLER): {
|
|
||||||
// *foundLen = rws::SIZE_INIT_RW;
|
|
||||||
// *foundId = rws::INIT_RW_CONTROLLER;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case (rws::SET_SPEED): {
|
|
||||||
// *foundLen = rws::SIZE_SET_SPEED_REPLY;
|
|
||||||
// *foundId = rws::SET_SPEED;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case (rws::GET_TEMPERATURE): {
|
|
||||||
// *foundLen = rws::SIZE_GET_TEMPERATURE_REPLY;
|
|
||||||
// *foundId = rws::GET_TEMPERATURE;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case (rws::GET_TM): {
|
|
||||||
// *foundLen = rws::SIZE_GET_TELEMETRY_REPLY;
|
|
||||||
// *foundId = rws::GET_TM;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// default: {
|
|
||||||
// sif::warning << "RwHandler::scanForReply: Reply contains invalid command code" <<
|
|
||||||
// std::endl; *foundLen = remainingSize; return returnvalue::FAILED;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t RwHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) {
|
ReturnValue_t RwHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) {
|
||||||
RwReplies replies(packet);
|
RwReplies replies(packet);
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
|
ReturnValue_t status;
|
||||||
auto checkPacket = [&](DeviceCommandId_t id, const uint8_t* packetPtr) {
|
auto checkPacket = [&](DeviceCommandId_t id, const uint8_t* packetPtr) {
|
||||||
|
// This is just the packet length of the frame from the RW. The actual
|
||||||
|
// data is one more flag byte to show whether the value was read at least once.
|
||||||
auto packetLen = rws::idToPacketLen(id);
|
auto packetLen = rws::idToPacketLen(id);
|
||||||
uint16_t replyCrc = (*(packet + packetLen - 1) << 8) | *(packet + packetLen - 2);
|
// arrayprinter::print(packetPtr, packetLen);
|
||||||
if (CRC::crc16ccitt(packet, packetLen - 2, 0xFFFF) != replyCrc) {
|
uint16_t replyCrc;
|
||||||
// sif::error << "RwHandler::interpretDeviceReply: CRC error for ID " << id << std::endl;
|
size_t dummy = 0;
|
||||||
|
SerializeAdapter::deSerialize(&replyCrc, packetPtr + packetLen - 2, &dummy,
|
||||||
|
SerializeIF::Endianness::LITTLE);
|
||||||
|
if (CRC::crc16ccitt(packetPtr, packetLen - 2) != replyCrc) {
|
||||||
|
sif::error << "RwHandler::interpretDeviceReply: CRC error for ID " << id << std::endl;
|
||||||
return CRC_ERROR;
|
return CRC_ERROR;
|
||||||
}
|
}
|
||||||
if (packetPtr[1] == rws::STATE_ERROR) {
|
if (packetPtr[1] == rws::STATE_ERROR) {
|
||||||
@ -307,35 +182,73 @@ ReturnValue_t RwHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_
|
|||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
};
|
};
|
||||||
checkPacket(rws::DeviceCommandId::SET_SPEED, replies.getSetSpeedReply());
|
if (replies.wasSetSpeedReplyRead()) {
|
||||||
if (returnvalue::OK ==
|
status = checkPacket(rws::DeviceCommandId::SET_SPEED, replies.getSetSpeedReply());
|
||||||
checkPacket(rws::DeviceCommandId::GET_RW_STATUS, replies.getRwStatusReply())) {
|
if (status != returnvalue::OK) {
|
||||||
handleGetRwStatusReply(replies.getRwStatusReply());
|
result = status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (returnvalue::OK == checkPacket(rws::DeviceCommandId::GET_LAST_RESET_STATUS,
|
|
||||||
replies.getGetLastResetStatusReply())) {
|
if (replies.wasRwStatusRead()) {
|
||||||
handleResetStatusReply(replies.getGetLastResetStatusReply());
|
status = checkPacket(rws::DeviceCommandId::GET_RW_STATUS, replies.getRwStatusReply());
|
||||||
|
if (status == returnvalue::OK) {
|
||||||
|
handleGetRwStatusReply(replies.getRwStatusReply());
|
||||||
|
} else {
|
||||||
|
result = status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
checkPacket(rws::DeviceCommandId::CLEAR_LAST_RESET_STATUS,
|
|
||||||
replies.getClearLastResetStatusReply());
|
if (replies.wasGetLastStatusReplyRead()) {
|
||||||
if (returnvalue::OK ==
|
status = checkPacket(rws::DeviceCommandId::GET_LAST_RESET_STATUS,
|
||||||
checkPacket(rws::DeviceCommandId::GET_TEMPERATURE, replies.getReadTemperatureReply())) {
|
replies.getGetLastResetStatusReply());
|
||||||
handleTemperatureReply(replies.getReadTemperatureReply());
|
if (status == returnvalue::OK) {
|
||||||
|
handleResetStatusReply(replies.getGetLastResetStatusReply());
|
||||||
|
} else {
|
||||||
|
result = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replies.wasClearLastRsetStatusReplyRead()) {
|
||||||
|
status = checkPacket(rws::DeviceCommandId::CLEAR_LAST_RESET_STATUS,
|
||||||
|
replies.getClearLastResetStatusReply());
|
||||||
|
if (status != returnvalue::OK) {
|
||||||
|
result = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replies.wasReadTemperatureReplySet()) {
|
||||||
|
status = checkPacket(rws::DeviceCommandId::GET_TEMPERATURE, replies.getReadTemperatureReply());
|
||||||
|
if (status == returnvalue::OK) {
|
||||||
|
handleTemperatureReply(replies.getReadTemperatureReply());
|
||||||
|
} else {
|
||||||
|
result = status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (internalState == InternalState::GET_TM) {
|
if (internalState == InternalState::GET_TM) {
|
||||||
if (returnvalue::OK == checkPacket(rws::DeviceCommandId::GET_TM, replies.getHkDataReply())) {
|
if (replies.wasHkDataReplyRead()) {
|
||||||
handleGetTelemetryReply(replies.getHkDataReply());
|
status = checkPacket(rws::DeviceCommandId::GET_TM, replies.getHkDataReply());
|
||||||
|
if (status == returnvalue::OK) {
|
||||||
|
handleGetTelemetryReply(replies.getHkDataReply());
|
||||||
|
} else {
|
||||||
|
result = status;
|
||||||
|
}
|
||||||
|
internalState = InternalState::DEFAULT;
|
||||||
}
|
}
|
||||||
internalState = InternalState::DEFAULT;
|
|
||||||
}
|
}
|
||||||
if (internalState == InternalState::INIT_RW_CONTROLLER) {
|
if (internalState == InternalState::INIT_RW_CONTROLLER) {
|
||||||
checkPacket(rws::DeviceCommandId::INIT_RW_CONTROLLER, replies.getInitRwControllerReply());
|
if (replies.wasInitRwControllerReplyRead()) {
|
||||||
internalState = InternalState::DEFAULT;
|
status =
|
||||||
|
checkPacket(rws::DeviceCommandId::INIT_RW_CONTROLLER, replies.getInitRwControllerReply());
|
||||||
|
if (status != returnvalue::OK) {
|
||||||
|
result = status;
|
||||||
|
}
|
||||||
|
internalState = InternalState::DEFAULT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (internalState == InternalState::RESET_MCU) {
|
if (internalState == InternalState::RESET_MCU) {
|
||||||
internalState = InternalState::DEFAULT;
|
internalState = InternalState::DEFAULT;
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RwHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 5000; }
|
uint32_t RwHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 5000; }
|
||||||
@ -388,17 +301,6 @@ ReturnValue_t RwHandler::initializeLocalDataPool(localpool::DataPool& localDataP
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
void RwHandler::prepareSimpleCommand(DeviceCommandId_t id) {
|
|
||||||
commandBuffer[0] = static_cast<uint8_t>(id);
|
|
||||||
uint16_t crc = CRC::crc16ccitt(commandBuffer, 1, 0xFFFF);
|
|
||||||
commandBuffer[1] = static_cast<uint8_t>(crc & 0xFF);
|
|
||||||
commandBuffer[2] = static_cast<uint8_t>(crc >> 8 & 0xFF);
|
|
||||||
rawPacket = commandBuffer;
|
|
||||||
rawPacketLen = 3;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
ReturnValue_t RwHandler::checkSpeedAndRampTime() {
|
ReturnValue_t RwHandler::checkSpeedAndRampTime() {
|
||||||
int32_t speed = 0;
|
int32_t speed = 0;
|
||||||
uint16_t rampTime = 0;
|
uint16_t rampTime = 0;
|
||||||
@ -416,28 +318,6 @@ ReturnValue_t RwHandler::checkSpeedAndRampTime() {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
ReturnValue_t RwHandler::prepareSetSpeedCmd() {
|
|
||||||
commandBuffer[0] = static_cast<uint8_t>(rws::SET_SPEED);
|
|
||||||
uint8_t* serPtr = commandBuffer + 1;
|
|
||||||
size_t serSize = 1;
|
|
||||||
rwSpeedActuationSet.setValidityBufferGeneration(false);
|
|
||||||
ReturnValue_t result = rwSpeedActuationSet.serialize(&serPtr, &serSize, sizeof(commandBuffer),
|
|
||||||
SerializeIF::Endianness::LITTLE);
|
|
||||||
rwSpeedActuationSet.setValidityBufferGeneration(true);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t crc = CRC::crc16ccitt(commandBuffer, 7, 0xFFFF);
|
|
||||||
commandBuffer[7] = static_cast<uint8_t>(crc & 0xFF);
|
|
||||||
commandBuffer[8] = static_cast<uint8_t>((crc >> 8) & 0xFF);
|
|
||||||
rawPacket = commandBuffer;
|
|
||||||
rawPacketLen = 9;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void RwHandler::handleResetStatusReply(const uint8_t* packet) {
|
void RwHandler::handleResetStatusReply(const uint8_t* packet) {
|
||||||
PoolReadGuard rg(&lastResetStatusSet);
|
PoolReadGuard rg(&lastResetStatusSet);
|
||||||
uint8_t offset = 2;
|
uint8_t offset = 2;
|
||||||
|
@ -70,6 +70,7 @@ class RwHandler : public DeviceHandlerBase {
|
|||||||
static const ReturnValue_t EXECUTION_FAILED = MAKE_RETURN_CODE(0xA3);
|
static const ReturnValue_t EXECUTION_FAILED = MAKE_RETURN_CODE(0xA3);
|
||||||
//! [EXPORT] : [COMMENT] Reaction wheel reply has invalid crc
|
//! [EXPORT] : [COMMENT] Reaction wheel reply has invalid crc
|
||||||
static const ReturnValue_t CRC_ERROR = MAKE_RETURN_CODE(0xA4);
|
static const ReturnValue_t CRC_ERROR = MAKE_RETURN_CODE(0xA4);
|
||||||
|
static const ReturnValue_t VALUE_NOT_READ = MAKE_RETURN_CODE(0xA5);
|
||||||
|
|
||||||
GpioIF* gpioComIF = nullptr;
|
GpioIF* gpioComIF = nullptr;
|
||||||
gpioId_t enableGpio = gpio::NO_GPIO;
|
gpioId_t enableGpio = gpio::NO_GPIO;
|
||||||
|
@ -53,6 +53,8 @@ static const ReturnValue_t MISSING_END_SIGN = MAKE_RETURN_CODE(0xB4);
|
|||||||
static const ReturnValue_t NO_REPLY = MAKE_RETURN_CODE(0xB5);
|
static const ReturnValue_t NO_REPLY = MAKE_RETURN_CODE(0xB5);
|
||||||
//! [EXPORT] : [COMMENT] Expected a start marker as first byte
|
//! [EXPORT] : [COMMENT] Expected a start marker as first byte
|
||||||
static const ReturnValue_t NO_START_MARKER = MAKE_RETURN_CODE(0xB6);
|
static const ReturnValue_t NO_START_MARKER = MAKE_RETURN_CODE(0xB6);
|
||||||
|
//! [EXPORT] : [COMMENT] Timeout when reading reply
|
||||||
|
static const ReturnValue_t SPI_READ_TIMEOUT = MAKE_RETURN_CODE(0xB7);
|
||||||
|
|
||||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::RW_HANDLER;
|
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::RW_HANDLER;
|
||||||
|
|
||||||
@ -62,7 +64,7 @@ static constexpr Event ERROR_STATE = MAKE_EVENT(1, severity::HIGH);
|
|||||||
static constexpr Event RESET_OCCURED = event::makeEvent(SUBSYSTEM_ID, 2, severity::LOW);
|
static constexpr Event RESET_OCCURED = event::makeEvent(SUBSYSTEM_ID, 2, severity::LOW);
|
||||||
|
|
||||||
//! Minimal delay as specified by the datasheet.
|
//! Minimal delay as specified by the datasheet.
|
||||||
static const uint32_t SPI_REPLY_DELAY = 70000; // us
|
static const uint32_t SPI_REPLY_DELAY = 20000; // us
|
||||||
|
|
||||||
enum PoolIds : lp_id_t {
|
enum PoolIds : lp_id_t {
|
||||||
TEMPERATURE_C,
|
TEMPERATURE_C,
|
||||||
@ -272,40 +274,55 @@ class RwSpeedActuationSet : public StaticLocalDataSet<2> {
|
|||||||
|
|
||||||
} // namespace rws
|
} // namespace rws
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw pointer overlay to hold the different frames received from the reaction
|
||||||
|
* wheel in a raw buffer and send them to the device handler.
|
||||||
|
*/
|
||||||
struct RwReplies {
|
struct RwReplies {
|
||||||
friend class RwPollingTask;
|
friend class RwPollingTask;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RwReplies(const uint8_t* rawData) : rawData(const_cast<uint8_t*>(rawData)) { initPointers(); }
|
RwReplies(const uint8_t* rawData) : rawData(const_cast<uint8_t*>(rawData)) { initPointers(); }
|
||||||
|
|
||||||
const uint8_t* getClearLastResetStatusReply() const { return clearLastResetStatusReply; }
|
const uint8_t* getClearLastResetStatusReply() const { return clearLastResetStatusReply + 1; }
|
||||||
|
bool wasClearLastRsetStatusReplyRead() const { return clearLastResetStatusReply[0]; }
|
||||||
|
|
||||||
const uint8_t* getGetLastResetStatusReply() const { return getLastResetStatusReply; }
|
const uint8_t* getGetLastResetStatusReply() const { return getLastResetStatusReply + 1; }
|
||||||
|
bool wasGetLastStatusReplyRead() const { return getLastResetStatusReply[0]; }
|
||||||
|
|
||||||
const uint8_t* getHkDataReply() const { return hkDataReply; }
|
const uint8_t* getHkDataReply() const { return hkDataReply + 1; }
|
||||||
|
bool wasHkDataReplyRead() const { return hkDataReply[0]; }
|
||||||
|
|
||||||
const uint8_t* getInitRwControllerReply() const { return initRwControllerReply; }
|
const uint8_t* getInitRwControllerReply() const { return initRwControllerReply + 1; }
|
||||||
|
bool wasInitRwControllerReplyRead() const { return initRwControllerReply[0]; }
|
||||||
|
|
||||||
const uint8_t* getRawData() const { return rawData; }
|
const uint8_t* getRawData() const { return rawData; }
|
||||||
|
|
||||||
const uint8_t* getReadTemperatureReply() const { return readTemperatureReply; }
|
const uint8_t* getReadTemperatureReply() const { return readTemperatureReply + 1; }
|
||||||
|
bool wasReadTemperatureReplySet() const { return readTemperatureReply[0]; }
|
||||||
|
|
||||||
const uint8_t* getRwStatusReply() const { return rwStatusReply; }
|
const uint8_t* getRwStatusReply() const { return rwStatusReply + 1; }
|
||||||
|
bool wasRwStatusRead() const { return rwStatusReply[0]; }
|
||||||
|
|
||||||
const uint8_t* getSetSpeedReply() const { return setSpeedReply; }
|
const uint8_t* getSetSpeedReply() const { return setSpeedReply + 1; }
|
||||||
|
bool wasSetSpeedReplyRead() const { return setSpeedReply[0]; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RwReplies(uint8_t* rwData) : rawData(rwData) { initPointers(); }
|
RwReplies(uint8_t* rwData) : rawData(rwData) { initPointers(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first byte of the reply buffers contains a flag which shows whether that
|
||||||
|
* frame was read from the reaction wheel at least once.
|
||||||
|
*/
|
||||||
void initPointers() {
|
void initPointers() {
|
||||||
rwStatusReply = rawData;
|
rwStatusReply = rawData;
|
||||||
setSpeedReply = rawData + rws::SIZE_GET_RW_STATUS;
|
setSpeedReply = rawData + rws::SIZE_GET_RW_STATUS + 1;
|
||||||
getLastResetStatusReply = setSpeedReply + rws::SIZE_SET_SPEED_REPLY;
|
getLastResetStatusReply = setSpeedReply + rws::SIZE_SET_SPEED_REPLY + 1;
|
||||||
clearLastResetStatusReply = getLastResetStatusReply + rws::SIZE_GET_RESET_STATUS;
|
clearLastResetStatusReply = getLastResetStatusReply + rws::SIZE_GET_RESET_STATUS + 1;
|
||||||
readTemperatureReply = clearLastResetStatusReply + rws::SIZE_CLEAR_RESET_STATUS;
|
readTemperatureReply = clearLastResetStatusReply + rws::SIZE_CLEAR_RESET_STATUS + 1;
|
||||||
hkDataReply = readTemperatureReply + rws::SIZE_GET_TEMPERATURE_REPLY;
|
hkDataReply = readTemperatureReply + rws::SIZE_GET_TEMPERATURE_REPLY + 1;
|
||||||
initRwControllerReply = hkDataReply + rws::SIZE_GET_TELEMETRY_REPLY;
|
initRwControllerReply = hkDataReply + rws::SIZE_GET_TELEMETRY_REPLY + 1;
|
||||||
dummyPointer = initRwControllerReply + rws::SIZE_INIT_RW;
|
dummyPointer = initRwControllerReply + rws::SIZE_INIT_RW + 1;
|
||||||
}
|
}
|
||||||
uint8_t* rawData;
|
uint8_t* rawData;
|
||||||
uint8_t* rwStatusReply;
|
uint8_t* rwStatusReply;
|
||||||
|
@ -167,7 +167,12 @@ bool RwAssembly::isUseable(object_id_t object, Mode_t mode) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t RwAssembly::initialize() { return AssemblyBase::initialize(); }
|
ReturnValue_t RwAssembly::initialize() {
|
||||||
|
for (auto objId : helper.rwIds) {
|
||||||
|
updateChildModeByObjId(objId, MODE_OFF, SUBMODE_NONE);
|
||||||
|
}
|
||||||
|
return AssemblyBase::initialize();
|
||||||
|
}
|
||||||
|
|
||||||
void RwAssembly::handleModeTransitionFailed(ReturnValue_t result) {
|
void RwAssembly::handleModeTransitionFailed(ReturnValue_t result) {
|
||||||
if (targetMode == MODE_OFF) {
|
if (targetMode == MODE_OFF) {
|
||||||
|
2
tmtc
2
tmtc
@ -1 +1 @@
|
|||||||
Subproject commit 1e143ea6faa608baf3118512416f5a495dbd606c
|
Subproject commit 08c315fbf92a3256663749e5b4dad11fcc1c02e4
|
Loading…
Reference in New Issue
Block a user