Merge remote-tracking branch 'origin/develop' into meier/plocTmCamCmdReport
Some checks are pending
EIVE/eive-obsw/pipeline/pr-develop Build queued...

This commit is contained in:
2023-03-13 11:08:31 +01:00
752 changed files with 48077 additions and 31153 deletions

View File

@ -0,0 +1,732 @@
#include "AcsBoardPolling.h"
#include <fcntl.h>
#include <fsfw/globalfunctions/arrayprinter.h>
#include <fsfw/tasks/SemaphoreFactory.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h>
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.h>
#include <fsfw_hal/linux/UnixFileGuard.h>
#include <fsfw_hal/linux/spi/SpiCookie.h>
#include <fsfw_hal/linux/utility.h>
#include <mission/devices/devicedefinitions/gyroAdisHelpers.h>
#include <sys/ioctl.h>
#include "devices/gpioIds.h"
using namespace returnvalue;
AcsBoardPolling::AcsBoardPolling(object_id_t objectId, SpiComIF& lowLevelComIF, GpioIF& gpioIF)
: SystemObject(objectId), spiComIF(lowLevelComIF), gpioIF(gpioIF) {
semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
semaphore->acquire();
ipcLock = MutexFactory::instance()->createMutex();
}
ReturnValue_t AcsBoardPolling::performOperation(uint8_t operationCode) {
while (true) {
ipcLock->lockMutex(LOCK_TYPE, LOCK_TIMEOUT);
state = InternalState::IDLE;
ipcLock->unlockMutex();
semaphore->acquire();
// Give all tasks or the PST some time to submit all consecutive requests.
TaskFactory::delayTask(2);
{
// Measured to take 0-1 ms in debug build.
// Stopwatch watch;
gyroAdisHandler(gyro0Adis);
gyroAdisHandler(gyro2Adis);
gyroL3gHandler(gyro1L3g);
gyroL3gHandler(gyro3L3g);
mgmRm3100Handler(mgm1Rm3100);
mgmRm3100Handler(mgm3Rm3100);
mgmLis3Handler(mgm0Lis3);
mgmLis3Handler(mgm2Lis3);
}
// To prevent task being not reactivated by tardy tasks
TaskFactory::delayTask(20);
}
return returnvalue::OK;
}
ReturnValue_t AcsBoardPolling::initialize() { return returnvalue::OK; }
ReturnValue_t AcsBoardPolling::initializeInterface(CookieIF* cookie) {
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
if (spiCookie == nullptr) {
return returnvalue::FAILED;
}
switch (spiCookie->getChipSelectPin()) {
case (gpioIds::MGM_0_LIS3_CS): {
mgm0Lis3.cookie = spiCookie;
break;
}
case (gpioIds::MGM_1_RM3100_CS): {
mgm1Rm3100.cookie = spiCookie;
break;
}
case (gpioIds::MGM_2_LIS3_CS): {
mgm2Lis3.cookie = spiCookie;
break;
}
case (gpioIds::MGM_3_RM3100_CS): {
mgm3Rm3100.cookie = spiCookie;
break;
}
case (gpioIds::GYRO_0_ADIS_CS): {
gyro0Adis.cookie = spiCookie;
break;
}
case (gpioIds::GYRO_1_L3G_CS): {
gyro1L3g.cookie = spiCookie;
break;
}
case (gpioIds::GYRO_2_ADIS_CS): {
gyro2Adis.cookie = spiCookie;
break;
}
case (gpioIds::GYRO_3_L3G_CS): {
gyro3L3g.cookie = spiCookie;
break;
}
default: {
sif::error << "AcsBoardPollingTask: invalid spi cookie" << std::endl;
}
}
return spiComIF.initializeInterface(cookie);
}
ReturnValue_t AcsBoardPolling::sendMessage(CookieIF* cookie, const uint8_t* sendData,
size_t sendLen) {
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
if (spiCookie == nullptr) {
return returnvalue::FAILED;
}
auto handleAdisRequest = [&](GyroAdis& adis) {
if (sendLen != sizeof(acs::Adis1650XRequest)) {
sif::error << "AcsBoardPolling: invalid adis request send length";
adis.replyResult = returnvalue::FAILED;
return returnvalue::FAILED;
}
auto* req = reinterpret_cast<const acs::Adis1650XRequest*>(sendData);
if (req->mode != adis.mode) {
if (req->mode == acs::SimpleSensorMode::NORMAL) {
adis.type = req->type;
adis.countdown.setTimeout(adis1650x::START_UP_TIME);
if (adis.type == adis1650x::Type::ADIS16507) {
adis.ownReply.data.accelScaling = adis1650x::ACCELEROMETER_RANGE_16507;
} else if (adis.type == adis1650x::Type::ADIS16505) {
adis.ownReply.data.accelScaling = adis1650x::ACCELEROMETER_RANGE_16505;
} else {
sif::warning << "AcsBoardPolling: Unknown ADIS type" << std::endl;
}
adis.performStartup = true;
} else if (req->mode == acs::SimpleSensorMode::OFF) {
adis.performStartup = false;
adis.ownReply.cfgWasSet = false;
adis.ownReply.dataWasSet = false;
}
adis.mode = req->mode;
}
return returnvalue::OK;
};
auto handleL3gRequest = [&](GyroL3g& gyro) {
if (sendLen != sizeof(acs::GyroL3gRequest)) {
sif::error << "AcsBoardPolling: invalid l3g request send length";
gyro.replyResult = returnvalue::FAILED;
return returnvalue::FAILED;
}
auto* req = reinterpret_cast<const acs::GyroL3gRequest*>(sendData);
if (req->mode != gyro.mode) {
if (req->mode == acs::SimpleSensorMode::NORMAL) {
std::memcpy(gyro.sensorCfg, req->ctrlRegs, 5);
gyro.performStartup = true;
} else {
gyro.ownReply.cfgWasSet = false;
}
gyro.mode = req->mode;
}
return returnvalue::OK;
};
auto handleLis3Request = [&](MgmLis3& mgm) {
if (sendLen != sizeof(acs::MgmLis3Request)) {
sif::error << "AcsBoardPolling: invalid lis3 request send length";
mgm.replyResult = returnvalue::FAILED;
return returnvalue::FAILED;
}
auto* req = reinterpret_cast<const acs::MgmLis3Request*>(sendData);
if (req->mode != mgm.mode) {
if (req->mode == acs::SimpleSensorMode::NORMAL) {
mgm.performStartup = true;
} else {
mgm.ownReply.dataWasSet = false;
mgm.ownReply.temperatureWasSet = false;
}
mgm.mode = req->mode;
}
return returnvalue::OK;
};
auto handleRm3100Request = [&](MgmRm3100& mgm) {
if (sendLen != sizeof(acs::MgmRm3100Request)) {
sif::error << "AcsBoardPolling: invalid rm3100 request send length";
mgm.replyResult = returnvalue::FAILED;
return returnvalue::FAILED;
}
auto* req = reinterpret_cast<const acs::MgmRm3100Request*>(sendData);
if (req->mode != mgm.mode) {
if (req->mode == acs::SimpleSensorMode::NORMAL) {
mgm.performStartup = true;
} else {
mgm.ownReply.dataWasRead = false;
}
mgm.mode = req->mode;
}
return returnvalue::OK;
};
{
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
switch (spiCookie->getChipSelectPin()) {
case (gpioIds::MGM_0_LIS3_CS): {
handleLis3Request(mgm0Lis3);
break;
}
case (gpioIds::MGM_1_RM3100_CS): {
handleRm3100Request(mgm1Rm3100);
break;
}
case (gpioIds::MGM_2_LIS3_CS): {
handleLis3Request(mgm2Lis3);
break;
}
case (gpioIds::MGM_3_RM3100_CS): {
handleRm3100Request(mgm3Rm3100);
break;
}
case (gpioIds::GYRO_0_ADIS_CS): {
handleAdisRequest(gyro0Adis);
break;
}
case (gpioIds::GYRO_2_ADIS_CS): {
handleAdisRequest(gyro2Adis);
break;
}
case (gpioIds::GYRO_1_L3G_CS): {
handleL3gRequest(gyro1L3g);
break;
}
case (gpioIds::GYRO_3_L3G_CS): {
handleL3gRequest(gyro3L3g);
break;
}
}
if (state == InternalState::IDLE) {
state = InternalState::BUSY;
}
}
semaphore->release();
return returnvalue::OK;
}
ReturnValue_t AcsBoardPolling::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
ReturnValue_t AcsBoardPolling::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
return returnvalue::OK;
}
ReturnValue_t AcsBoardPolling::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
size_t* size) {
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
if (spiCookie == nullptr) {
return returnvalue::FAILED;
}
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
auto handleAdisReply = [&](GyroAdis& gyro) {
std::memcpy(&gyro.readerReply, &gyro.ownReply, sizeof(acs::Adis1650XReply));
*buffer = reinterpret_cast<uint8_t*>(&gyro.readerReply);
*size = sizeof(acs::Adis1650XReply);
return gyro.replyResult;
};
auto handleL3gReply = [&](GyroL3g& gyro) {
std::memcpy(&gyro.readerReply, &gyro.ownReply, sizeof(acs::GyroL3gReply));
*buffer = reinterpret_cast<uint8_t*>(&gyro.readerReply);
*size = sizeof(acs::GyroL3gReply);
return gyro.replyResult;
};
auto handleRm3100Reply = [&](MgmRm3100& mgm) {
std::memcpy(&mgm.readerReply, &mgm.ownReply, sizeof(acs::MgmRm3100Reply));
*buffer = reinterpret_cast<uint8_t*>(&mgm.readerReply);
*size = sizeof(acs::MgmRm3100Reply);
return mgm.replyResult;
};
auto handleLis3Reply = [&](MgmLis3& mgm) {
std::memcpy(&mgm.readerReply, &mgm.ownReply, sizeof(acs::MgmLis3Reply));
*buffer = reinterpret_cast<uint8_t*>(&mgm.readerReply);
*size = sizeof(acs::MgmLis3Reply);
return mgm.replyResult;
};
switch (spiCookie->getChipSelectPin()) {
case (gpioIds::MGM_0_LIS3_CS): {
return handleLis3Reply(mgm0Lis3);
}
case (gpioIds::MGM_1_RM3100_CS): {
return handleRm3100Reply(mgm1Rm3100);
}
case (gpioIds::MGM_2_LIS3_CS): {
return handleLis3Reply(mgm2Lis3);
}
case (gpioIds::MGM_3_RM3100_CS): {
return handleRm3100Reply(mgm3Rm3100);
}
case (gpioIds::GYRO_0_ADIS_CS): {
return handleAdisReply(gyro0Adis);
}
case (gpioIds::GYRO_2_ADIS_CS): {
return handleAdisReply(gyro2Adis);
}
case (gpioIds::GYRO_1_L3G_CS): {
return handleL3gReply(gyro1L3g);
}
case (gpioIds::GYRO_3_L3G_CS): {
return handleL3gReply(gyro3L3g);
}
}
return returnvalue::OK;
}
void AcsBoardPolling::gyroL3gHandler(GyroL3g& l3g) {
ReturnValue_t result;
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
bool gyroPerformStartup = false;
{
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
mode = l3g.mode;
gyroPerformStartup = l3g.performStartup;
}
if (mode == acs::SimpleSensorMode::NORMAL) {
if (gyroPerformStartup) {
cmdBuf[0] = l3gd20h::CTRL_REG_1 | l3gd20h::AUTO_INCREMENT_MASK;
std::memcpy(cmdBuf.data() + 1, l3g.sensorCfg, 5);
result = spiComIF.sendMessage(l3g.cookie, cmdBuf.data(), 6);
if (result != returnvalue::OK) {
l3g.replyResult = returnvalue::OK;
}
// Ignore useless reply and red config
cmdBuf[0] = l3gd20h::CTRL_REG_1 | l3gd20h::AUTO_INCREMENT_MASK | l3gd20h::READ_MASK;
std::memset(cmdBuf.data() + 1, 0, 5);
result = spiComIF.sendMessage(l3g.cookie, cmdBuf.data(), 6);
if (result != returnvalue::OK) {
l3g.replyResult = returnvalue::OK;
}
result = spiComIF.readReceivedMessage(l3g.cookie, &rawReply, &dummy);
if (result != returnvalue::OK) {
l3g.replyResult = returnvalue::OK;
}
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
// Cross check configuration as verification that communication is working
for (uint8_t idx = 0; idx < 5; idx++) {
if (rawReply[idx + 1] != l3g.sensorCfg[idx]) {
sif::warning << "AcsBoardPolling: l3g config check missmatch" << std::endl;
l3g.replyResult = returnvalue::FAILED;
return;
}
}
l3g.performStartup = false;
l3g.ownReply.cfgWasSet = true;
l3g.ownReply.sensitivity = l3gd20h::ctrlReg4ToSensitivity(l3g.sensorCfg[3]);
}
cmdBuf[0] = l3gd20h::READ_START | l3gd20h::AUTO_INCREMENT_MASK | l3gd20h::READ_MASK;
std::memset(cmdBuf.data() + 1, 0, l3gd20h::READ_LEN);
result = spiComIF.sendMessage(l3g.cookie, cmdBuf.data(), l3gd20h::READ_LEN + 1);
if (result != returnvalue::OK) {
l3g.replyResult = returnvalue::FAILED;
return;
}
result = spiComIF.readReceivedMessage(l3g.cookie, &rawReply, &dummy);
if (result != returnvalue::OK) {
l3g.replyResult = returnvalue::FAILED;
return;
}
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
// The regular read function always returns the full sensor config as well. Use that
// to verify communications.
for (uint8_t idx = 0; idx < 5; idx++) {
if (rawReply[idx + 1] != l3g.sensorCfg[idx]) {
sif::warning << "AcsBoardPolling: l3g config check missmatch" << std::endl;
l3g.replyResult = returnvalue::FAILED;
return;
}
}
l3g.ownReply.statusReg = rawReply[l3gd20h::STATUS_IDX];
l3g.ownReply.angVelocities[0] = (rawReply[l3gd20h::OUT_X_H] << 8) | rawReply[l3gd20h::OUT_X_L];
l3g.ownReply.angVelocities[1] = (rawReply[l3gd20h::OUT_Y_H] << 8) | rawReply[l3gd20h::OUT_Y_L];
l3g.ownReply.angVelocities[2] = (rawReply[l3gd20h::OUT_Z_H] << 8) | rawReply[l3gd20h::OUT_Z_L];
l3g.ownReply.tempOffsetRaw = rawReply[l3gd20h::TEMPERATURE_IDX];
}
}
ReturnValue_t AcsBoardPolling::readAdisCfg(SpiCookie& cookie, size_t transferLen) {
ReturnValue_t result = returnvalue::OK;
int retval = 0;
// Prepare transfer
int fileDescriptor = 0;
std::string device = spiComIF.getSpiDev();
UnixFileGuard fileHelper(device, fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return SpiComIF::OPENING_FILE_FAILED;
}
spi::SpiModes spiMode = spi::SpiModes::MODE_0;
uint32_t spiSpeed = 0;
cookie.getSpiParameters(spiMode, spiSpeed, nullptr);
spiComIF.setSpiSpeedAndMode(fileDescriptor, spiMode, spiSpeed);
cookie.assignWriteBuffer(cmdBuf.data());
cookie.setTransferSize(2);
gpioId_t gpioId = cookie.getChipSelectPin();
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t timeoutMs = 0;
MutexIF* mutex = spiComIF.getCsMutex();
cookie.getMutexParams(timeoutType, timeoutMs);
if (mutex == nullptr) {
sif::warning << "GyroADIS16507Handler::spiSendCallback: "
"Mutex or GPIO interface invalid"
<< std::endl;
return returnvalue::FAILED;
}
size_t idx = 0;
spi_ioc_transfer* transferStruct = cookie.getTransferStructHandle();
uint64_t origTx = transferStruct->tx_buf;
uint64_t origRx = transferStruct->rx_buf;
while (idx < transferLen) {
result = mutex->lockMutex(timeoutType, timeoutMs);
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "AcsBoardPolling: Failed to lock mutex" << std::endl;
#endif
return result;
}
// Pull SPI CS low. For now, no support for active high given
if (gpioId != gpio::NO_GPIO) {
gpioIF.pullLow(gpioId);
}
// Execute transfer
// Initiate a full duplex SPI transfer.
retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie.getTransferStructHandle());
if (retval < 0) {
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
result = SpiComIF::FULL_DUPLEX_TRANSFER_FAILED;
}
#if FSFW_HAL_SPI_WIRETAPPING == 1
comIf->performSpiWiretapping(cookie);
#endif /* FSFW_LINUX_SPI_WIRETAPPING == 1 */
if (gpioId != gpio::NO_GPIO) {
gpioIF.pullHigh(gpioId);
}
mutex->unlockMutex();
idx += 2;
transferStruct->tx_buf += 2;
transferStruct->rx_buf += 2;
if (idx < transferLen) {
usleep(adis1650x::STALL_TIME_MICROSECONDS);
}
}
transferStruct->tx_buf = origTx;
transferStruct->rx_buf = origRx;
cookie.setTransferSize(transferLen);
return returnvalue::OK;
}
void AcsBoardPolling::gyroAdisHandler(GyroAdis& gyro) {
ReturnValue_t result;
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
bool cdHasTimedOut = false;
bool mustPerformStartup = false;
{
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
mode = gyro.mode;
cdHasTimedOut = gyro.countdown.hasTimedOut();
mustPerformStartup = gyro.performStartup;
}
if (mode == acs::SimpleSensorMode::NORMAL and cdHasTimedOut) {
if (mustPerformStartup) {
uint8_t regList[6];
// Read configuration
regList[0] = adis1650x::DIAG_STAT_REG;
regList[1] = adis1650x::FILTER_CTRL_REG;
regList[2] = adis1650x::RANG_MDL_REG;
regList[3] = adis1650x::MSC_CTRL_REG;
regList[4] = adis1650x::DEC_RATE_REG;
regList[5] = adis1650x::PROD_ID_REG;
size_t transferLen =
adis1650x::prepareReadCommand(regList, sizeof(regList), cmdBuf.data(), cmdBuf.size());
result = readAdisCfg(*gyro.cookie, transferLen);
if (result != returnvalue::OK) {
gyro.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(gyro.cookie, &rawReply, &dummy);
if (result != returnvalue::OK or rawReply == nullptr) {
gyro.replyResult = result;
return;
}
uint16_t prodId = (rawReply[12] << 8) | rawReply[13];
if (((gyro.type == adis1650x::Type::ADIS16505) and (prodId != adis1650x::PROD_ID_16505)) or
((gyro.type == adis1650x::Type::ADIS16507) and (prodId != adis1650x::PROD_ID_16507))) {
sif::warning << "AcsPollingTask: Invalid ADIS product ID " << prodId << std::endl;
gyro.replyResult = returnvalue::FAILED;
return;
}
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
gyro.ownReply.cfgWasSet = true;
gyro.ownReply.cfg.diagStat = (rawReply[2] << 8) | rawReply[3];
gyro.ownReply.cfg.filterSetting = (rawReply[4] << 8) | rawReply[5];
gyro.ownReply.cfg.rangMdl = (rawReply[6] << 8) | rawReply[7];
gyro.ownReply.cfg.mscCtrlReg = (rawReply[8] << 8) | rawReply[9];
gyro.ownReply.cfg.decRateReg = (rawReply[10] << 8) | rawReply[11];
gyro.ownReply.cfg.prodId = prodId;
gyro.ownReply.data.sensitivity = adis1650x::rangMdlToSensitivity(gyro.ownReply.cfg.rangMdl);
gyro.performStartup = false;
}
// Read regular registers
std::memcpy(cmdBuf.data(), adis1650x::BURST_READ_ENABLE.data(),
adis1650x::BURST_READ_ENABLE.size());
std::memset(cmdBuf.data() + 2, 0, 10 * 2);
result = spiComIF.sendMessage(gyro.cookie, cmdBuf.data(), adis1650x::SENSOR_READOUT_SIZE);
if (result != returnvalue::OK) {
gyro.replyResult = returnvalue::FAILED;
return;
}
result = spiComIF.readReceivedMessage(gyro.cookie, &rawReply, &dummy);
if (result != returnvalue::OK or rawReply == nullptr) {
gyro.replyResult = returnvalue::FAILED;
return;
}
uint16_t checksum = (rawReply[20] << 8) | rawReply[21];
// Now verify the read checksum with the expected checksum according to datasheet p. 20
uint16_t calcChecksum = 0;
for (size_t idx = 2; idx < 20; idx++) {
calcChecksum += rawReply[idx];
}
if (checksum != calcChecksum) {
sif::warning << "AcsPollingTask: Invalid ADIS reply checksum" << std::endl;
gyro.replyResult = returnvalue::FAILED;
return;
}
auto burstMode = adis1650x::burstModeFromMscCtrl(gyro.ownReply.cfg.mscCtrlReg);
if (burstMode != adis1650x::BurstModes::BURST_16_BURST_SEL_0) {
sif::error << "GyroADIS1650XHandler::interpretDeviceReply: Analysis for select burst mode"
" not implemented!"
<< std::endl;
gyro.replyResult = returnvalue::FAILED;
return;
}
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
gyro.ownReply.dataWasSet = true;
gyro.ownReply.cfg.diagStat = rawReply[2] << 8 | rawReply[3];
gyro.ownReply.data.angVelocities[0] = (rawReply[4] << 8) | rawReply[5];
gyro.ownReply.data.angVelocities[1] = (rawReply[6] << 8) | rawReply[7];
gyro.ownReply.data.angVelocities[2] = (rawReply[8] << 8) | rawReply[9];
gyro.ownReply.data.accelerations[0] = (rawReply[10] << 8) | rawReply[11];
gyro.ownReply.data.accelerations[1] = (rawReply[12] << 8) | rawReply[13];
gyro.ownReply.data.accelerations[2] = (rawReply[14] << 8) | rawReply[15];
gyro.ownReply.data.temperatureRaw = (rawReply[16] << 8) | rawReply[17];
}
}
void AcsBoardPolling::mgmLis3Handler(MgmLis3& mgm) {
ReturnValue_t result;
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
bool mustPerformStartup = false;
{
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
mode = mgm.mode;
mustPerformStartup = mgm.performStartup;
}
if (mode == acs::SimpleSensorMode::NORMAL) {
if (mustPerformStartup) {
// To check valid communication, read back identification
// register which should always be the same value.
cmdBuf[0] = mgmLis3::readCommand(mgmLis3::IDENTIFY_DEVICE_REG_ADDR);
cmdBuf[1] = 0x00;
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
if (result != OK) {
mgm.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
if (result != OK) {
mgm.replyResult = result;
return;
}
if (rawReply[1] != mgmLis3::DEVICE_ID) {
sif::error << "AcsPollingTask: invalid MGM lis3 device ID" << std::endl;
mgm.replyResult = result;
return;
}
mgm.cfg[0] = mgmLis3::CTRL_REG1_DEFAULT;
mgm.cfg[1] = mgmLis3::CTRL_REG2_DEFAULT;
mgm.cfg[2] = mgmLis3::CTRL_REG3_DEFAULT;
mgm.cfg[3] = mgmLis3::CTRL_REG4_DEFAULT;
mgm.cfg[4] = mgmLis3::CTRL_REG5_DEFAULT;
cmdBuf[0] = mgmLis3::writeCommand(mgmLis3::CTRL_REG1, true);
std::memcpy(cmdBuf.data() + 1, mgm.cfg, 5);
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 6);
if (result != OK) {
mgm.replyResult = result;
return;
}
// Done here. We can always read back config and data during periodic handling
mgm.performStartup = false;
}
cmdBuf[0] = mgmLis3::readCommand(mgmLis3::CTRL_REG1, true);
std::memset(cmdBuf.data() + 1, 0, mgmLis3::NR_OF_DATA_AND_CFG_REGISTERS);
result =
spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), mgmLis3::NR_OF_DATA_AND_CFG_REGISTERS + 1);
if (result != returnvalue::OK) {
mgm.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
if (result != returnvalue::OK) {
mgm.replyResult = result;
return;
}
// Verify communication by re-checking config
if (rawReply[1] != mgm.cfg[0] or rawReply[2] != mgm.cfg[1] or rawReply[3] != mgm.cfg[2] or
rawReply[4] != mgm.cfg[3] or rawReply[5] != mgm.cfg[4]) {
mgm.replyResult = result;
return;
}
{
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
mgm.ownReply.dataWasSet = true;
mgm.ownReply.sensitivity = mgmLis3::getSensitivityFactor(mgmLis3::getSensitivity(mgm.cfg[1]));
mgm.ownReply.mgmValuesRaw[0] =
(rawReply[mgmLis3::X_HIGHBYTE_IDX] << 8) | rawReply[mgmLis3::X_LOWBYTE_IDX];
mgm.ownReply.mgmValuesRaw[1] =
(rawReply[mgmLis3::Y_HIGHBYTE_IDX] << 8) | rawReply[mgmLis3::Y_LOWBYTE_IDX];
mgm.ownReply.mgmValuesRaw[2] =
(rawReply[mgmLis3::Z_HIGHBYTE_IDX] << 8) | rawReply[mgmLis3::Z_LOWBYTE_IDX];
}
// Read tempetature
cmdBuf[0] = mgmLis3::readCommand(mgmLis3::TEMP_LOWBYTE, true);
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 3);
if (result != returnvalue::OK) {
mgm.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
if (result != returnvalue::OK) {
mgm.replyResult = result;
return;
}
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
mgm.ownReply.temperatureWasSet = true;
mgm.ownReply.temperatureRaw = (rawReply[2] << 8) | rawReply[1];
}
}
void AcsBoardPolling::mgmRm3100Handler(MgmRm3100& mgm) {
ReturnValue_t result;
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
bool mustPerformStartup = false;
{
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
mode = mgm.mode;
mustPerformStartup = mgm.performStartup;
}
if (mode == acs::SimpleSensorMode::NORMAL) {
if (mustPerformStartup) {
// Configure CMM first
cmdBuf[0] = mgmRm3100::CMM_REGISTER;
cmdBuf[1] = mgmRm3100::CMM_VALUE;
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
if (result != OK) {
mgm.replyResult = result;
return;
}
// Read back register
cmdBuf[0] = mgmRm3100::CMM_REGISTER | mgmRm3100::READ_MASK;
cmdBuf[1] = 0;
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
if (result != OK) {
mgm.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
if (result != OK) {
mgm.replyResult = result;
return;
}
if (rawReply[1] != mgmRm3100::CMM_VALUE) {
sif::error << "AcsBoardPolling: MGM RM3100 read back CMM invalid" << std::endl;
mgm.replyResult = result;
return;
}
// Configure TMRC register
cmdBuf[0] = mgmRm3100::TMRC_REGISTER;
// hardcoded for now
cmdBuf[1] = mgm.tmrcValue;
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
if (result != OK) {
mgm.replyResult = result;
return;
}
// Read back and verify value
cmdBuf[0] = mgmRm3100::TMRC_REGISTER | mgmRm3100::READ_MASK;
cmdBuf[1] = 0;
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
if (result != OK) {
mgm.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
if (result != OK) {
mgm.replyResult = result;
return;
}
if (rawReply[1] != mgm.tmrcValue) {
sif::error << "AcsBoardPolling: MGM RM3100 read back TMRC invalid" << std::endl;
mgm.replyResult = result;
return;
}
mgm.performStartup = false;
}
// Regular read operation
cmdBuf[0] = mgmRm3100::MEASUREMENT_REG_START | mgmRm3100::READ_MASK;
std::memset(cmdBuf.data() + 1, 0, 9);
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 10);
if (result != OK) {
mgm.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
if (result != OK) {
mgm.replyResult = result;
return;
}
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
for (uint8_t idx = 0; idx < 3; idx++) {
// Hardcoded, but note that the gain depends on the cycle count
// value which is configurable!
mgm.ownReply.scaleFactors[idx] = 1.0 / mgmRm3100::DEFAULT_GAIN;
}
mgm.ownReply.dataWasRead = true;
// Bitshift trickery to account for 24 bit signed value.
mgm.ownReply.mgmValuesRaw[0] =
((rawReply[1] << 24) | (rawReply[2] << 16) | (rawReply[3] << 8)) >> 8;
mgm.ownReply.mgmValuesRaw[1] =
((rawReply[4] << 24) | (rawReply[5] << 16) | (rawReply[6] << 8)) >> 8;
mgm.ownReply.mgmValuesRaw[2] =
((rawReply[7] << 24) | (rawReply[8] << 16) | (rawReply[9] << 8)) >> 8;
}
}

View File

@ -0,0 +1,91 @@
#ifndef LINUX_DEVICES_ACSBOARDPOLLING_H_
#define LINUX_DEVICES_ACSBOARDPOLLING_H_
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/tasks/SemaphoreIF.h>
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmRm3100Helpers.h>
#include <fsfw_hal/linux/spi/SpiComIF.h>
#include <mission/devices/devicedefinitions/acsPolling.h>
#include <mission/devices/devicedefinitions/gyroAdisHelpers.h>
class AcsBoardPolling : public SystemObject,
public ExecutableObjectIF,
public DeviceCommunicationIF {
public:
AcsBoardPolling(object_id_t objectId, SpiComIF& lowLevelComIF, GpioIF& gpioIF);
ReturnValue_t performOperation(uint8_t operationCode) override;
ReturnValue_t initialize() override;
private:
enum class InternalState { IDLE, BUSY } state = InternalState::IDLE;
MutexIF* ipcLock;
static constexpr MutexIF::TimeoutType LOCK_TYPE = MutexIF::TimeoutType::WAITING;
static constexpr uint32_t LOCK_TIMEOUT = 20;
static constexpr char LOCK_CTX[] = "AcsBoardPolling";
SemaphoreIF* semaphore;
std::array<uint8_t, 32> cmdBuf;
struct DevBase {
SpiCookie* cookie = nullptr;
bool performStartup = false;
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
ReturnValue_t replyResult = returnvalue::OK;
};
struct GyroAdis : public DevBase {
adis1650x::Type type;
Countdown countdown;
acs::Adis1650XReply ownReply;
acs::Adis1650XReply readerReply;
};
GyroAdis gyro0Adis{};
GyroAdis gyro2Adis{};
struct GyroL3g : public DevBase {
uint8_t sensorCfg[5];
acs::GyroL3gReply ownReply;
acs::GyroL3gReply readerReply;
};
GyroL3g gyro1L3g{};
GyroL3g gyro3L3g{};
struct MgmRm3100 : public DevBase {
uint8_t tmrcValue = mgmRm3100::TMRC_DEFAULT_37HZ_VALUE;
acs::MgmRm3100Reply ownReply;
acs::MgmRm3100Reply readerReply;
};
MgmRm3100 mgm1Rm3100;
MgmRm3100 mgm3Rm3100;
struct MgmLis3 : public DevBase {
uint8_t cfg[5]{};
acs::MgmLis3Reply ownReply;
acs::MgmLis3Reply readerReply;
};
MgmLis3 mgm0Lis3;
MgmLis3 mgm2Lis3;
uint8_t* rawReply = nullptr;
size_t dummy = 0;
SpiComIF& spiComIF;
GpioIF& gpioIF;
ReturnValue_t initializeInterface(CookieIF* cookie) override;
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
ReturnValue_t getSendSuccess(CookieIF* cookie) override;
ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override;
ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override;
void gyroL3gHandler(GyroL3g& l3g);
void gyroAdisHandler(GyroAdis& gyro);
void mgmLis3Handler(MgmLis3& mgm);
void mgmRm3100Handler(MgmRm3100& mgm);
// Special readout: 16us stall time between small 2 byte transfers.
ReturnValue_t readAdisCfg(SpiCookie& spiCookie, size_t transferLen);
};
#endif /* LINUX_DEVICES_ACSBOARDPOLLING_H_ */

View File

@ -1,8 +1,21 @@
if(EIVE_BUILD_GPSD_GPS_HANDLER)
target_sources(${OBSW_NAME} PRIVATE
GPSHyperionLinuxController.cpp
)
target_sources(${OBSW_NAME} PRIVATE GpsHyperionLinuxController.cpp)
endif()
target_sources(
${OBSW_NAME}
PRIVATE Max31865RtdPolling.cpp
ScexUartReader.cpp
ImtqPollingTask.cpp
SusPolling.cpp
ScexDleParser.cpp
ScexHelper.cpp
RwPollingTask.cpp
AcsBoardPolling.cpp)
add_subdirectory(ploc)
add_subdirectory(startracker)
# Dependency on proprietary library
if(TGT_BSP MATCHES "arm/q7s")
add_subdirectory(startracker)
endif()

View File

@ -1,317 +0,0 @@
#include "GPSHyperionLinuxController.h"
#include <fsfw/timemanager/Stopwatch.h>
#include "OBSWConfig.h"
#include "fsfw/FSFW.h"
#include "fsfw/datapool/PoolReadGuard.h"
#include "fsfw/timemanager/Clock.h"
#include "linux/utility/utility.h"
#include "mission/utility/compileTime.h"
#if FSFW_DEV_HYPERION_GPS_CREATE_NMEA_CSV == 1
#include <filesystem>
#include <fstream>
#endif
#include <cmath>
#include <ctime>
GPSHyperionLinuxController::GPSHyperionLinuxController(object_id_t objectId, object_id_t parentId,
bool debugHyperionGps)
: ExtendedControllerBase(objectId, objects::NO_OBJECT),
gpsSet(this),
debugHyperionGps(debugHyperionGps) {
timeUpdateCd.resetTimer();
}
GPSHyperionLinuxController::~GPSHyperionLinuxController() {
gps_stream(&gps, WATCH_DISABLE, nullptr);
gps_close(&gps);
}
void GPSHyperionLinuxController::performControlOperation() {
#ifdef FSFW_OSAL_LINUX
readGpsDataFromGpsd();
#endif
}
LocalPoolDataSetBase *GPSHyperionLinuxController::getDataSetHandle(sid_t sid) { return &gpsSet; }
ReturnValue_t GPSHyperionLinuxController::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) {
if (not modeCommanded) {
if (mode == MODE_ON or mode == MODE_OFF) {
gpsNotOpenSwitch = true;
// 5h time to reach fix
*msToReachTheMode = MAX_SECONDS_TO_REACH_FIX;
maxTimeToReachFix.resetTimer();
modeCommanded = true;
} else if (mode == MODE_NORMAL) {
return HasModesIF::INVALID_MODE;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t GPSHyperionLinuxController::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) {
switch (actionId) {
case (GpsHyperion::TRIGGER_RESET_PIN): {
if (resetCallback != nullptr) {
PoolReadGuard pg(&gpsSet);
// Set HK entries invalid
gpsSet.setValidity(false, true);
resetCallback(resetCallbackArgs);
return HasActionsIF::EXECUTION_FINISHED;
}
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t GPSHyperionLinuxController::initializeLocalDataPool(
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(GpsHyperion::ALTITUDE, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(GpsHyperion::LONGITUDE, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(GpsHyperion::LATITUDE, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(GpsHyperion::SPEED, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(GpsHyperion::YEAR, new PoolEntry<uint16_t>());
localDataPoolMap.emplace(GpsHyperion::MONTH, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::DAY, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::HOURS, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::MINUTES, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::SECONDS, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::UNIX_SECONDS, new PoolEntry<uint32_t>());
localDataPoolMap.emplace(GpsHyperion::SATS_IN_USE, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::SATS_IN_VIEW, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
poolManager.subscribeForPeriodicPacket(gpsSet.getSid(), false, 30.0, false);
return HasReturnvaluesIF::RETURN_OK;
}
void GPSHyperionLinuxController::setResetPinTriggerFunction(gpioResetFunction_t resetCallback,
void *args) {
this->resetCallback = resetCallback;
resetCallbackArgs = args;
}
ReturnValue_t GPSHyperionLinuxController::initialize() {
ReturnValue_t result = ExtendedControllerBase::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
auto openError = [&](const char *type, int error) {
if (gpsNotOpenSwitch) {
// Opening failed
#if FSFW_VERBOSE_LEVEL >= 1
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Opening GPSMM " << type
<< " failed | Error " << error << " | " << gps_errstr(error) << std::endl;
#endif
gpsNotOpenSwitch = false;
}
};
if (readMode == ReadModes::SOCKET) {
int retval = gps_open("localhost", DEFAULT_GPSD_PORT, &gps);
if (retval != 0) {
openError("Socket", retval);
}
} else if (readMode == ReadModes::SHM) {
int retval = gps_open(GPSD_SHARED_MEMORY, "", &gps);
if (retval != 0) {
openError("SHM", retval);
}
}
return result;
}
ReturnValue_t GPSHyperionLinuxController::handleCommandMessage(CommandMessage *message) {
return ExtendedControllerBase::handleCommandMessage(message);
}
#ifdef FSFW_OSAL_LINUX
void GPSHyperionLinuxController::readGpsDataFromGpsd() {
auto readError = [&](int error) {
if (gpsReadFailedSwitch) {
gpsReadFailedSwitch = false;
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Reading GPS data failed | "
"Error "
<< error << " | " << gps_errstr(error) << std::endl;
}
};
currentClientBuf = gps_data(&gps);
if (readMode == ReadModes::SOCKET) {
gps_stream(&gps, WATCH_ENABLE | WATCH_JSON, nullptr);
// Exit if no data is seen in 2 seconds (should not happen)
if (not gps_waiting(&gps, 2000000)) {
return;
}
int result = gps_read(&gps);
if (result == -1) {
readError(result);
return;
}
if (MODE_SET != (MODE_SET & gps.set)) {
if (noModeSetCntr >= 0) {
noModeSetCntr++;
}
if (noModeSetCntr == 10) {
// TODO: Trigger event here
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: No mode could be "
"read for 10 consecutive reads"
<< std::endl;
noModeSetCntr = -1;
}
}
noModeSetCntr = 0;
} else if (readMode == ReadModes::SHM) {
int result = gps_read(&gps);
if (result == -1) {
readError(result);
return;
}
}
handleGpsRead();
}
ReturnValue_t GPSHyperionLinuxController::handleGpsRead() {
PoolReadGuard pg(&gpsSet);
if (pg.getReadResult() != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Reading dataset failed" << std::endl;
#endif
return RETURN_FAILED;
}
bool validFix = false;
static_cast<void>(validFix);
// 0: Not seen, 1: No fix, 2: 2D-Fix, 3: 3D-Fix
int newFixMode = gps.fix.mode;
if (newFixMode == 2 or newFixMode == 3) {
validFix = true;
}
if (gpsSet.fixMode.value != newFixMode) {
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, newFixMode);
}
gpsSet.fixMode.value = newFixMode;
if (gps.fix.mode == 0 or gps.fix.mode == 1) {
if (modeCommanded and maxTimeToReachFix.hasTimedOut()) {
// We are supposed to be on and functioning, but not fix was found
if (mode == MODE_ON or mode == MODE_NORMAL) {
mode = MODE_OFF;
}
modeCommanded = false;
}
gpsSet.setValidity(false, true);
} else if (gps.satellites_used > 0) {
gpsSet.setValidity(true, true);
}
gpsSet.satInUse.value = gps.satellites_used;
gpsSet.satInView.value = gps.satellites_visible;
if (std::isfinite(gps.fix.latitude)) {
// Negative latitude -> South direction
gpsSet.latitude.value = gps.fix.latitude;
} else {
gpsSet.latitude.setValid(false);
}
if (std::isfinite(gps.fix.longitude)) {
// Negative longitude -> West direction
gpsSet.longitude.value = gps.fix.longitude;
} else {
gpsSet.longitude.setValid(false);
}
if (std::isfinite(gps.fix.altitude)) {
gpsSet.altitude.value = gps.fix.altitude;
} else {
gpsSet.altitude.setValid(false);
}
if (std::isfinite(gps.fix.speed)) {
gpsSet.speed.value = gps.fix.speed;
} else {
gpsSet.speed.setValid(false);
}
#if LIBGPS_VERSION_MINOR <= 17
gpsSet.unixSeconds.value = gps.fix.time;
#else
gpsSet.unixSeconds.value = gps.fix.time.tv_sec;
#endif
timeval time = {};
time.tv_sec = gpsSet.unixSeconds.value;
#if LIBGPS_VERSION_MINOR <= 17
double fractionalPart = gps.fix.time - std::floor(gps.fix.time);
time.tv_usec = fractionalPart * 1000.0 * 1000.0;
#else
time.tv_usec = gps.fix.time.tv_nsec / 1000;
#endif
std::time_t t = std::time(nullptr);
if (time.tv_sec == t) {
timeIsConstantCounter++;
} else {
timeIsConstantCounter = 0;
}
if (timeInit and validFix) {
if (not utility::timeSanityCheck()) {
#if OBSW_VERBOSE_LEVEL >= 1
time_t timeRaw = time.tv_sec;
std::tm *timeTm = std::gmtime(&timeRaw);
sif::info << "Setting invalid system time from GPS data directly: "
<< std::put_time(timeTm, "%c %Z") << std::endl;
#endif
// For some reason, the clock needs to be somewhat correct for NTP to work. Really dumb..
Clock::setClock(&time);
}
timeInit = false;
}
// If the received time does not change anymore for whatever reason, do not set it here
// to avoid stale times. Also, don't do it too often often to avoid jumping times
if (timeIsConstantCounter < 20 and timeUpdateCd.hasTimedOut()) {
// Update the system time here for now. NTP seems to be unable to do so for whatever reason.
// Further tests have shown that the time seems to be set by NTPD after some time..
// Clock::setClock(&time);
timeUpdateCd.resetTimer();
}
Clock::TimeOfDay_t timeOfDay = {};
Clock::convertTimevalToTimeOfDay(&time, &timeOfDay);
gpsSet.year = timeOfDay.year;
gpsSet.month = timeOfDay.month;
gpsSet.day = timeOfDay.day;
gpsSet.hours = timeOfDay.hour;
gpsSet.minutes = timeOfDay.minute;
gpsSet.seconds = timeOfDay.second;
if (debugHyperionGps) {
sif::info << "-- Hyperion GPS Data --" << std::endl;
#if LIBGPS_VERSION_MINOR <= 17
time_t timeRaw = gps.fix.time;
#else
time_t timeRaw = gps.fix.time.tv_sec;
#endif
std::tm *time = gmtime(&timeRaw);
std::cout << "Time: " << std::put_time(time, "%c %Z") << std::endl;
std::cout << "Visible satellites: " << gps.satellites_visible << std::endl;
std::cout << "Satellites used: " << gps.satellites_used << std::endl;
std::cout << "Fix (0:Not Seen|1:No Fix|2:2D|3:3D): " << gps.fix.mode << std::endl;
std::cout << "Latitude: " << gps.fix.latitude << std::endl;
std::cout << "Longitude: " << gps.fix.longitude << std::endl;
#if LIBGPS_VERSION_MINOR <= 17
std::cout << "Altitude(MSL): " << gps.fix.altitude << std::endl;
#else
std::cout << "Altitude(MSL): " << gps.fix.altMSL << std::endl;
#endif
std::cout << "Speed(m/s): " << gps.fix.speed << std::endl;
std::time_t t = std::time(nullptr);
std::tm tm = *std::gmtime(&t);
std::cout << "C Time: " << std::put_time(&tm, "%c") << std::endl;
}
return RETURN_OK;
}
#endif

View File

@ -0,0 +1,379 @@
#include "GpsHyperionLinuxController.h"
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include "OBSWConfig.h"
#include "fsfw/FSFW.h"
#include "fsfw/datapool/PoolReadGuard.h"
#include "fsfw/timemanager/Clock.h"
#include "linux/utility/utility.h"
#include "mission/utility/compileTime.h"
#if FSFW_DEV_HYPERION_GPS_CREATE_NMEA_CSV == 1
#include <filesystem>
#include <fstream>
#endif
#include <cmath>
#include <ctime>
GpsHyperionLinuxController::GpsHyperionLinuxController(object_id_t objectId, object_id_t parentId,
bool debugHyperionGps)
: ExtendedControllerBase(objectId), gpsSet(this), debugHyperionGps(debugHyperionGps) {}
GpsHyperionLinuxController::~GpsHyperionLinuxController() {
gps_stream(&gps, WATCH_DISABLE, nullptr);
gps_close(&gps);
}
LocalPoolDataSetBase *GpsHyperionLinuxController::getDataSetHandle(sid_t sid) { return &gpsSet; }
ReturnValue_t GpsHyperionLinuxController::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) {
if (not modeCommanded) {
if (mode == MODE_ON or mode == MODE_OFF) {
// 5h time to reach fix
*msToReachTheMode = MAX_SECONDS_TO_REACH_FIX;
maxTimeToReachFix.resetTimer();
modeCommanded = true;
} else if (mode == MODE_NORMAL) {
return HasModesIF::INVALID_MODE;
}
}
if (mode == MODE_OFF) {
PoolReadGuard pg(&gpsSet);
gpsSet.setValidity(false, true);
// There can't be a fix with a device that is off.
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, 0);
gpsSet.fixMode.value = 0;
oneShotSwitches.reset();
modeCommanded = false;
}
return returnvalue::OK;
}
ReturnValue_t GpsHyperionLinuxController::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) {
switch (actionId) {
case (GpsHyperion::TRIGGER_RESET_PIN_GNSS): {
if (resetCallback != nullptr) {
PoolReadGuard pg(&gpsSet);
// Set HK entries invalid
gpsSet.setValidity(false, true);
resetCallback(data, size, resetCallbackArgs);
return HasActionsIF::EXECUTION_FINISHED;
}
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
}
return returnvalue::OK;
}
ReturnValue_t GpsHyperionLinuxController::initializeLocalDataPool(
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(GpsHyperion::ALTITUDE, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(GpsHyperion::LONGITUDE, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(GpsHyperion::LATITUDE, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(GpsHyperion::SPEED, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(GpsHyperion::YEAR, new PoolEntry<uint16_t>());
localDataPoolMap.emplace(GpsHyperion::MONTH, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::DAY, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::HOURS, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::MINUTES, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::SECONDS, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::UNIX_SECONDS, new PoolEntry<uint32_t>());
localDataPoolMap.emplace(GpsHyperion::SATS_IN_USE, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::SATS_IN_VIEW, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
poolManager.subscribeForRegularPeriodicPacket({gpsSet.getSid(), false, 30.0});
return returnvalue::OK;
}
void GpsHyperionLinuxController::setResetPinTriggerFunction(gpioResetFunction_t resetCallback,
void *args) {
this->resetCallback = resetCallback;
resetCallbackArgs = args;
}
ReturnValue_t GpsHyperionLinuxController::performOperation(uint8_t opCode) {
handleQueue();
poolManager.performHkOperation();
while (true) {
#if OBSW_THREAD_TRACING == 1
trace::threadTrace(opCounter, "GPS CTRL");
#endif
bool callAgainImmediately = readGpsDataFromGpsd();
if (not callAgainImmediately) {
handleQueue();
poolManager.performHkOperation();
TaskFactory::delayTask(250);
}
}
// Should never be reached.
return returnvalue::OK;
}
ReturnValue_t GpsHyperionLinuxController::initialize() {
ReturnValue_t result = ExtendedControllerBase::initialize();
if (result != returnvalue::OK) {
return result;
}
auto openError = [&](const char *type, int error) {
// Opening failed
#if FSFW_VERBOSE_LEVEL >= 1
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Opening GPSMM " << type
<< " failed | Error " << error << " | " << gps_errstr(error) << std::endl;
#endif
};
if (readMode == ReadModes::SOCKET) {
int retval = gps_open("localhost", DEFAULT_GPSD_PORT, &gps);
if (retval != 0) {
openError("Socket", retval);
return ObjectManager::CHILD_INIT_FAILED;
}
gps_stream(&gps, WATCH_ENABLE | WATCH_JSON, nullptr);
} else if (readMode == ReadModes::SHM) {
int retval = gps_open(GPSD_SHARED_MEMORY, "", &gps);
if (retval != 0) {
openError("SHM", retval);
return ObjectManager::CHILD_INIT_FAILED;
}
}
return result;
}
ReturnValue_t GpsHyperionLinuxController::handleCommandMessage(CommandMessage *message) {
return ExtendedControllerBase::handleCommandMessage(message);
}
void GpsHyperionLinuxController::performControlOperation() {}
bool GpsHyperionLinuxController::readGpsDataFromGpsd() {
auto readError = [&]() {
if (oneShotSwitches.gpsReadFailedSwitch) {
oneShotSwitches.gpsReadFailedSwitch = false;
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Reading GPS data failed | "
"Error "
<< errno << " | " << gps_errstr(errno) << std::endl;
}
};
// GPS is off, no point in reading data from GPSD.
if (mode == MODE_OFF) {
return false;
}
if (readMode == ReadModes::SOCKET) {
// Poll the GPS.
if (gps_waiting(&gps, 0)) {
if (-1 == gps_read(&gps)) {
readError();
return false;
}
oneShotSwitches.gpsReadFailedSwitch = true;
ReturnValue_t result = handleGpsReadData();
if (result == returnvalue::OK) {
return true;
} else {
return false;
}
noModeSetCntr = 0;
} else {
return false;
}
} else if (readMode == ReadModes::SHM) {
sif::error << "GpsHyperionLinuxController::readGpsDataFromGpsdPermanentLoop: "
"SHM read not implemented"
<< std::endl;
}
return true;
}
ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
bool modeIsSet = true;
if (MODE_SET != (MODE_SET & gps.set)) {
if (mode != MODE_OFF) {
if (maxTimeToReachFix.hasTimedOut() and oneShotSwitches.cantGetFixSwitch) {
sif::warning << "GpsHyperionLinuxController: No mode could be set in allowed "
<< maxTimeToReachFix.getTimeoutMs() / 1000 << " seconds" << std::endl;
triggerEvent(GpsHyperion::CANT_GET_FIX, maxTimeToReachFix.getTimeoutMs());
oneShotSwitches.cantGetFixSwitch = false;
}
modeIsSet = false;
} else {
// GPS device is off anyway, so do other handling
return returnvalue::FAILED;
}
}
PoolReadGuard pg(&gpsSet);
if (pg.getReadResult() != returnvalue::OK) {
#if FSFW_VERBOSE_LEVEL >= 1
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Reading dataset failed" << std::endl;
#endif
return returnvalue::FAILED;
}
bool validFix = false;
uint8_t newFix = 0;
if (modeIsSet) {
// 0: Not seen, 1: No fix, 2: 2D-Fix, 3: 3D-Fix
if (gps.fix.mode == 2 or gps.fix.mode == 3) {
validFix = true;
}
newFix = gps.fix.mode;
if (newFix == 0 or newFix == 1) {
if (modeCommanded and maxTimeToReachFix.hasTimedOut()) {
// We are supposed to be on and functioning, but no fix was found
if (mode == MODE_ON or mode == MODE_NORMAL) {
mode = MODE_OFF;
}
modeCommanded = false;
}
}
}
if (gpsSet.fixMode.value != newFix) {
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, newFix);
}
gpsSet.fixMode = newFix;
gpsSet.fixMode.setValid(modeIsSet);
// Only set on specific messages, so only set a valid flag to invalid
// if not set for more than a full message set (10 messages here)
if (SATELLITE_SET == (SATELLITE_SET & gps.set)) {
gpsSet.satInUse.value = gps.satellites_used;
gpsSet.satInView.value = gps.satellites_visible;
if (not gpsSet.satInUse.isValid()) {
gpsSet.satInUse.setValid(true);
gpsSet.satInView.setValid(true);
}
satNotSetCounter = 0;
} else {
satNotSetCounter++;
if (gpsSet.satInUse.isValid() and satNotSetCounter >= 10) {
gpsSet.satInUse.setValid(false);
gpsSet.satInView.setValid(false);
}
}
// LATLON is set for every message, no need for a counter
bool latValid = false;
bool longValid = false;
if (LATLON_SET == (LATLON_SET & gps.set)) {
if (std::isfinite(gps.fix.latitude)) {
// Negative latitude -> South direction
gpsSet.latitude.value = gps.fix.latitude;
// As specified in gps.h: Only valid if mode >= 2
if (gps.fix.mode >= 2) {
latValid = true;
}
}
if (std::isfinite(gps.fix.longitude)) {
// Negative longitude -> West direction
gpsSet.longitude.value = gps.fix.longitude;
// As specified in gps.h: Only valid if mode >= 2
if (gps.fix.mode >= 2) {
longValid = true;
}
}
}
gpsSet.latitude.setValid(latValid);
gpsSet.longitude.setValid(longValid);
// ALTITUDE is set for every message, no need for a counter
bool altitudeValid = false;
if (ALTITUDE_SET == (ALTITUDE_SET & gps.set) && std::isfinite(gps.fix.altitude)) {
gpsSet.altitude.value = gps.fix.altitude;
// As specified in gps.h: Only valid if mode == 3
if (gps.fix.mode == 3) {
altitudeValid = true;
}
}
gpsSet.altitude.setValid(altitudeValid);
// SPEED is set for every message, no need for a counter
bool speedValid = false;
if (SPEED_SET == (SPEED_SET & gps.set) && std::isfinite(gps.fix.speed)) {
gpsSet.speed.value = gps.fix.speed;
speedValid = true;
}
gpsSet.speed.setValid(speedValid);
// TIME is set for every message, no need for a counter
bool timeValid = false;
if (TIME_SET == (TIME_SET & gps.set)) {
timeValid = true;
timeval time = {};
#if LIBGPS_VERSION_MINOR <= 17
gpsSet.unixSeconds.value = std::floor(gps.fix.time);
double fractionalPart = gps.fix.time - gpsSet.unixSeconds.value;
time.tv_usec = fractionalPart * 1000.0 * 1000.0;
#else
gpsSet.unixSeconds.value = gps.fix.time.tv_sec;
time.tv_usec = gps.fix.time.tv_nsec / 1000;
#endif
time.tv_sec = gpsSet.unixSeconds.value;
// If the time is totally wrong (e.g. year 2000 after system reset because we do not have a RTC
// and no time file available) we set it with the roughly valid time from the GPS.
// NTP might only work if the time difference between sys time and current time is not too
// large.
overwriteTimeIfNotSane(time, validFix);
Clock::TimeOfDay_t timeOfDay = {};
Clock::convertTimevalToTimeOfDay(&time, &timeOfDay);
gpsSet.year = timeOfDay.year;
gpsSet.month = timeOfDay.month;
gpsSet.day = timeOfDay.day;
gpsSet.hours = timeOfDay.hour;
gpsSet.minutes = timeOfDay.minute;
gpsSet.seconds = timeOfDay.second;
}
gpsSet.unixSeconds.setValid(timeValid);
gpsSet.year.setValid(timeValid);
gpsSet.month.setValid(timeValid);
gpsSet.day.setValid(timeValid);
gpsSet.hours.setValid(timeValid);
gpsSet.minutes.setValid(timeValid);
gpsSet.seconds.setValid(timeValid);
if (debugHyperionGps) {
sif::info << "-- Hyperion GPS Data --" << std::endl;
#if LIBGPS_VERSION_MINOR <= 17
time_t timeRaw = gpsSet.unixSeconds.value;
#else
time_t timeRaw = gps.fix.time.tv_sec;
#endif
std::tm *time = gmtime(&timeRaw);
std::cout << "Time: " << std::put_time(time, "%c %Z") << std::endl;
std::cout << "Visible satellites: " << gps.satellites_visible << std::endl;
std::cout << "Satellites used: " << gps.satellites_used << std::endl;
std::cout << "Fix (0:Not Seen|1:No Fix|2:2D|3:3D): " << gps.fix.mode << std::endl;
std::cout << "Latitude: " << gps.fix.latitude << std::endl;
std::cout << "Longitude: " << gps.fix.longitude << std::endl;
#if LIBGPS_VERSION_MINOR <= 17
std::cout << "Altitude(MSL): " << gps.fix.altitude << std::endl;
#else
std::cout << "Altitude(MSL): " << gps.fix.altMSL << std::endl;
#endif
std::cout << "Speed(m/s): " << gps.fix.speed << std::endl;
std::time_t t = std::time(nullptr);
std::tm tm = *std::gmtime(&t);
std::cout << "C Time: " << std::put_time(&tm, "%c") << std::endl;
}
return returnvalue::OK;
}
void GpsHyperionLinuxController::overwriteTimeIfNotSane(timeval time, bool validFix) {
if (not timeInit and validFix) {
if (not utility::timeSanityCheck()) {
#if OBSW_VERBOSE_LEVEL >= 1
time_t timeRaw = time.tv_sec;
std::tm *timeTm = std::gmtime(&timeRaw);
sif::info << "Overwriting invalid system time from GPS data directly: "
<< std::put_time(timeTm, "%c %Z") << std::endl;
#endif
// For some reason, the clock needs to be somewhat correct for NTP to work. Really dumb..
Clock::setClock(&time);
}
timeInit = true;
}
}

View File

@ -1,11 +1,12 @@
#ifndef MISSION_DEVICES_GPSHYPERIONHANDLER_H_
#define MISSION_DEVICES_GPSHYPERIONHANDLER_H_
#include "commonSubsystemIds.h"
#include "eive/eventSubsystemIds.h"
#include "fsfw/FSFW.h"
#include "fsfw/controller/ExtendedControllerBase.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "mission/devices/devicedefinitions/GPSDefinitions.h"
#include "mission/trace.h"
#ifdef FSFW_OSAL_LINUX
#include <gps.h>
@ -20,18 +21,20 @@
* This device handler can only be used on Linux system where the gpsd daemon with shared memory
* export is running.
*/
class GPSHyperionLinuxController : public ExtendedControllerBase {
class GpsHyperionLinuxController : public ExtendedControllerBase {
public:
static constexpr uint32_t MAX_SECONDS_TO_REACH_FIX = 60 * 60 * 5;
// 30 minutes
static constexpr uint32_t MAX_SECONDS_TO_REACH_FIX = 60 * 30;
enum ReadModes { SHM = 0, SOCKET = 1 };
GPSHyperionLinuxController(object_id_t objectId, object_id_t parentId,
GpsHyperionLinuxController(object_id_t objectId, object_id_t parentId,
bool debugHyperionGps = false);
virtual ~GPSHyperionLinuxController();
virtual ~GpsHyperionLinuxController();
using gpioResetFunction_t = ReturnValue_t (*)(void* args);
using gpioResetFunction_t = ReturnValue_t (*)(const uint8_t* actionData, size_t len, void* args);
ReturnValue_t performOperation(uint8_t opCode) override;
void setResetPinTriggerFunction(gpioResetFunction_t resetCallback, void* args);
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
void performControlOperation() override;
@ -49,7 +52,7 @@ class GPSHyperionLinuxController : public ExtendedControllerBase {
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
ReturnValue_t handleGpsRead();
ReturnValue_t handleGpsReadData();
private:
GpsPrimaryDataset gpsSet;
@ -57,16 +60,34 @@ class GPSHyperionLinuxController : public ExtendedControllerBase {
const char* currentClientBuf = nullptr;
ReadModes readMode = ReadModes::SOCKET;
Countdown maxTimeToReachFix = Countdown(MAX_SECONDS_TO_REACH_FIX * 1000);
bool modeCommanded = true;
bool timeInit = true;
bool gpsNotOpenSwitch = true;
bool gpsReadFailedSwitch = true;
bool modeCommanded = false;
bool timeInit = false;
uint8_t satNotSetCounter = 0;
#if OBSW_THREAD_TRACING == 1
uint32_t opCounter = 0;
#endif
struct OneShotSwitches {
void reset() {
gpsReadFailedSwitch = true;
cantGetFixSwitch = true;
}
bool gpsReadFailedSwitch = true;
bool cantGetFixSwitch = true;
} oneShotSwitches;
bool debugHyperionGps = false;
int32_t noModeSetCntr = 0;
uint32_t timeIsConstantCounter = 0;
Countdown timeUpdateCd = Countdown(60);
void readGpsDataFromGpsd();
// Returns true if the function should be called again or false if other
// controller handling can be done.
bool readGpsDataFromGpsd();
// If the time is totally wrong (e.g. year 2000 after system reset because we do not have a RTC)
// we set it with the roughly valid time from the GPS. For some reason, NTP might only work
// if the time difference between sys time and current time is not too large
void overwriteTimeIfNotSane(timeval time, bool validFix);
};
#endif /* MISSION_DEVICES_GPSHYPERIONHANDLER_H_ */

View File

@ -0,0 +1,477 @@
#include "ImtqPollingTask.h"
#include <fcntl.h>
#include <fsfw/tasks/SemaphoreFactory.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <fsfw_hal/linux/UnixFileGuard.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include "fsfw/FSFW.h"
ImtqPollingTask::ImtqPollingTask(object_id_t imtqPollingTask) : SystemObject(imtqPollingTask) {
semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
semaphore->acquire();
ipcLock = MutexFactory::instance()->createMutex();
bufLock = MutexFactory::instance()->createMutex();
}
ReturnValue_t ImtqPollingTask::performOperation(uint8_t operationCode) {
while (true) {
ipcLock->lockMutex();
state = InternalState::IDLE;
ipcLock->unlockMutex();
semaphore->acquire();
comStatus = returnvalue::OK;
// Stopwatch watch;
switch (currentRequest) {
case imtq::RequestType::MEASURE_NO_ACTUATION: {
// Measured to take 24 ms for debug and release builds.
// Stopwatch watch;
handleMeasureStep();
break;
}
case imtq::RequestType::ACTUATE: {
handleActuateStep();
break;
}
default: {
break;
}
};
}
return returnvalue::OK;
}
void ImtqPollingTask::handleMeasureStep() {
size_t replyLen = 0;
uint8_t* replyPtr;
ImtqRepliesDefault replies(replyBuf.data());
// If some startup handling is added later, set configured after it was done once.
replies.setConfigured();
// Can be used later to verify correct timing (e.g. all data has been read)
clearReadFlagsDefault(replies);
auto i2cCmdExecMeasure = [&](imtq::CC::CC cc) {
ccToReplyPtrMeasure(replies, cc, &replyPtr, replyLen);
return i2cCmdExecDefault(cc, replyPtr, replyLen, imtq::MGM_MEASUREMENT_LOW_LEVEL_ERROR);
};
cmdLen = 1;
cmdBuf[0] = imtq::CC::GET_SYSTEM_STATE;
if (i2cCmdExecMeasure(imtq::CC::GET_SYSTEM_STATE) != returnvalue::OK) {
return;
}
ignoreNextActuateRequest =
(replies.getSystemState()[2] == static_cast<uint8_t>(imtq::mode::SELF_TEST));
if (ignoreNextActuateRequest) {
// Do not command anything until self-test is done.
return;
}
if (specialRequest != imtq::SpecialRequest::NONE) {
auto executeSelfTest = [&](imtq::selfTest::Axis axis) {
cmdBuf[0] = imtq::CC::SELF_TEST_CMD;
cmdBuf[1] = axis;
return i2cCmdExecMeasure(imtq::CC::SELF_TEST_CMD);
};
// If a self-test is already ongoing, ignore the request.
if (replies.getSystemState()[2] != static_cast<uint8_t>(imtq::mode::SELF_TEST)) {
switch (specialRequest) {
case (imtq::SpecialRequest::DO_SELF_TEST_POS_X): {
executeSelfTest(imtq::selfTest::Axis::X_POSITIVE);
break;
}
case (imtq::SpecialRequest::DO_SELF_TEST_NEG_X): {
executeSelfTest(imtq::selfTest::Axis::X_NEGATIVE);
break;
}
case (imtq::SpecialRequest::DO_SELF_TEST_POS_Y): {
executeSelfTest(imtq::selfTest::Axis::Y_POSITIVE);
break;
}
case (imtq::SpecialRequest::DO_SELF_TEST_NEG_Y): {
executeSelfTest(imtq::selfTest::Axis::Y_NEGATIVE);
break;
}
case (imtq::SpecialRequest::DO_SELF_TEST_POS_Z): {
executeSelfTest(imtq::selfTest::Axis::Z_POSITIVE);
break;
}
case (imtq::SpecialRequest::DO_SELF_TEST_NEG_Z): {
executeSelfTest(imtq::selfTest::Axis::Z_NEGATIVE);
break;
}
case (imtq::SpecialRequest::GET_SELF_TEST_RESULT): {
cmdBuf[0] = imtq::CC::GET_SELF_TEST_RESULT;
i2cCmdExecMeasure(imtq::CC::GET_SELF_TEST_RESULT);
break;
}
default: {
// Should never happen
break;
}
}
// We are done. Only request self test or results here.
return;
}
}
// The I2C IP core on EIVE sometimes glitches out. Send start MTM measurement twice.
cmdBuf[0] = imtq::CC::START_MTM_MEASUREMENT;
if (i2cCmdExecMeasure(imtq::CC::START_MTM_MEASUREMENT) != returnvalue::OK) {
return;
}
cmdBuf[0] = imtq::CC::START_MTM_MEASUREMENT;
if (i2cCmdExecMeasure(imtq::CC::START_MTM_MEASUREMENT) != returnvalue::OK) {
return;
}
// Takes a bit of time to take measurements. Subtract a bit because of the delay of previous
// commands.
TaskFactory::delayTask(currentIntegrationTimeMs + MGM_READ_BUFFER_TIME_MS);
cmdBuf[0] = imtq::CC::GET_RAW_MTM_MEASUREMENT;
if (i2cCmdExecMeasure(imtq::CC::GET_RAW_MTM_MEASUREMENT) != returnvalue::OK) {
return;
}
bool mgmMeasurementTooOld = false;
// See p.39 of the iMTQ user manual. If the NEW bit of the STAT bitfield is not set, we probably
// have old data. Which can be really bad for ACS. And everything.
if ((replyPtr[2] >> 7) == 0) {
replyPtr[0] = false;
mgmMeasurementTooOld = true;
}
cmdBuf[0] = imtq::CC::GET_ENG_HK_DATA;
if (i2cCmdExecMeasure(imtq::CC::GET_ENG_HK_DATA) != returnvalue::OK) {
return;
}
cmdBuf[0] = imtq::CC::GET_CAL_MTM_MEASUREMENT;
if (i2cCmdExecMeasure(imtq::CC::GET_CAL_MTM_MEASUREMENT) != returnvalue::OK) {
return;
}
if (mgmMeasurementTooOld) {
sif::error << "IMTQ: MGM measurement too old" << std::endl;
}
return;
}
void ImtqPollingTask::handleActuateStep() {
uint8_t* replyPtr = nullptr;
size_t replyLen = 0;
// No point when self-test mode is active.
if (ignoreNextActuateRequest) {
return;
}
ImtqRepliesWithTorque replies(replyBufActuation.data());
// Can be used later to verify correct timing (e.g. all data has been read)
clearReadFlagsWithTorque(replies);
auto i2cCmdExecActuate = [&](imtq::CC::CC cc) {
ccToReplyPtrActuate(replies, cc, &replyPtr, replyLen);
return i2cCmdExecDefault(cc, replyPtr, replyLen, imtq::ACTUATE_CMD_LOW_LEVEL_ERROR);
};
buildDipoleCommand();
if (i2cCmdExecActuate(imtq::CC::START_ACTUATION_DIPOLE) != returnvalue::OK) {
return;
}
TaskFactory::delayTask(10);
cmdLen = 1;
// The I2C IP core on EIVE sometimes glitches out. Send start MTM measurement twice.
cmdBuf[0] = imtq::CC::START_MTM_MEASUREMENT;
if (i2cCmdExecActuate(imtq::CC::START_MTM_MEASUREMENT) != returnvalue::OK) {
return;
}
cmdBuf[0] = imtq::CC::START_MTM_MEASUREMENT;
if (i2cCmdExecActuate(imtq::CC::START_MTM_MEASUREMENT) != returnvalue::OK) {
return;
}
TaskFactory::delayTask(currentIntegrationTimeMs + MGM_READ_BUFFER_TIME_MS);
cmdBuf[0] = imtq::CC::GET_RAW_MTM_MEASUREMENT;
if (i2cCmdExecActuate(imtq::CC::GET_RAW_MTM_MEASUREMENT) != returnvalue::OK) {
return;
}
bool measurementWasTooOld = false;
// See p.39 of the iMTQ user manual. If the NEW bit of the STAT bitfield is not set, we probably
// have old data. Which can be really bad for ACS. And everything.
if ((replyPtr[2] >> 7) == 0) {
measurementWasTooOld = true;
replyPtr[0] = false;
}
cmdBuf[0] = imtq::CC::GET_ENG_HK_DATA;
if (i2cCmdExecActuate(imtq::CC::GET_ENG_HK_DATA) != returnvalue::OK) {
return;
}
if (measurementWasTooOld) {
sif::error << "IMTQ: MGM measurement too old" << std::endl;
}
return;
}
ReturnValue_t ImtqPollingTask::initialize() { return returnvalue::OK; }
ReturnValue_t ImtqPollingTask::initializeInterface(CookieIF* cookie) {
i2cCookie = dynamic_cast<I2cCookie*>(cookie);
if (i2cCookie == nullptr) {
sif::error << "ImtqPollingTask::initializeInterface: Invalid I2C cookie" << std::endl;
return returnvalue::FAILED;
}
i2cDev = i2cCookie->getDeviceFile().c_str();
i2cAddr = i2cCookie->getAddress();
return returnvalue::OK;
}
ReturnValue_t ImtqPollingTask::sendMessage(CookieIF* cookie, const uint8_t* sendData,
size_t sendLen) {
const auto* imtqReq = reinterpret_cast<const imtq::Request*>(sendData);
{
MutexGuard mg(ipcLock);
if (imtqReq->request == imtq::RequestType::ACTUATE) {
std::memcpy(dipoles, imtqReq->dipoles, sizeof(dipoles));
torqueDuration = imtqReq->torqueDuration;
}
currentRequest = imtqReq->request;
specialRequest = imtqReq->specialRequest;
if (state != InternalState::IDLE) {
return returnvalue::FAILED;
}
state = InternalState::BUSY;
}
semaphore->release();
return returnvalue::OK;
}
ReturnValue_t ImtqPollingTask::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
ReturnValue_t ImtqPollingTask::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
return returnvalue::OK;
}
void ImtqPollingTask::ccToReplyPtrMeasure(ImtqRepliesDefault& replies, imtq::CC::CC cc,
uint8_t** replyBuf, size_t& replyLen) {
replyLen = imtq::getReplySize(cc);
switch (cc) {
case (imtq::CC::CC::GET_ENG_HK_DATA): {
*replyBuf = replies.engHk;
break;
}
case (imtq::CC::CC::SOFTWARE_RESET): {
*replyBuf = replies.swReset;
break;
}
case (imtq::CC::CC::GET_SYSTEM_STATE): {
*replyBuf = replies.systemState;
break;
}
case (imtq::CC::CC::START_MTM_MEASUREMENT): {
*replyBuf = replies.startMtmMeasurement;
break;
}
case (imtq::CC::CC::GET_RAW_MTM_MEASUREMENT): {
*replyBuf = replies.rawMgmMeasurement;
break;
}
case (imtq::CC::CC::GET_CAL_MTM_MEASUREMENT): {
*replyBuf = replies.calibMgmMeasurement;
break;
}
default: {
*replyBuf = replies.specialRequestReply;
break;
}
}
}
void ImtqPollingTask::ccToReplyPtrActuate(ImtqRepliesWithTorque& replies, imtq::CC::CC cc,
uint8_t** replyBuf, size_t& replyLen) {
replyLen = imtq::getReplySize(cc);
switch (cc) {
case (imtq::CC::CC::START_ACTUATION_DIPOLE): {
*replyBuf = replies.dipoleActuation;
break;
}
case (imtq::CC::CC::GET_ENG_HK_DATA): {
*replyBuf = replies.engHk;
break;
}
case (imtq::CC::CC::START_MTM_MEASUREMENT): {
*replyBuf = replies.startMtmMeasurement;
break;
}
case (imtq::CC::CC::GET_RAW_MTM_MEASUREMENT): {
*replyBuf = replies.rawMgmMeasurement;
break;
}
default: {
*replyBuf = nullptr;
replyLen = 0;
break;
}
}
}
size_t ImtqPollingTask::getExchangeBufLen(imtq::SpecialRequest specialRequest) {
size_t baseLen = ImtqRepliesDefault::BASE_LEN;
switch (specialRequest) {
case (imtq::SpecialRequest::NONE):
case (imtq::SpecialRequest::DO_SELF_TEST_POS_X):
case (imtq::SpecialRequest::DO_SELF_TEST_NEG_X):
case (imtq::SpecialRequest::DO_SELF_TEST_POS_Y):
case (imtq::SpecialRequest::DO_SELF_TEST_NEG_Y):
case (imtq::SpecialRequest::DO_SELF_TEST_POS_Z):
case (imtq::SpecialRequest::DO_SELF_TEST_NEG_Z): {
break;
}
case (imtq::SpecialRequest::GET_SELF_TEST_RESULT): {
baseLen += imtq::replySize::SELF_TEST_RESULTS;
break;
}
}
return baseLen;
}
void ImtqPollingTask::buildDipoleCommand() {
cmdBuf[0] = imtq::CC::CC::START_ACTUATION_DIPOLE;
uint8_t* serPtr = cmdBuf.data() + 1;
size_t serLen = 0;
for (uint8_t idx = 0; idx < 3; idx++) {
SerializeAdapter::serialize(&dipoles[idx], &serPtr, &serLen, cmdBuf.size(),
SerializeIF::Endianness::LITTLE);
}
SerializeAdapter::serialize(&torqueDuration, &serPtr, &serLen, cmdBuf.size(),
SerializeIF::Endianness::LITTLE);
// sif::debug << "Dipole X: " << dipoles[0] << std::endl;
// sif::debug << "Torqeu Dur: " << torqueDuration << std::endl;
cmdLen = 1 + serLen;
}
ReturnValue_t ImtqPollingTask::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
size_t* size) {
imtq::RequestType currentRequest;
{
MutexGuard mg(ipcLock);
currentRequest = this->currentRequest;
}
size_t replyLen = 0;
MutexGuard mg(bufLock);
if (currentRequest == imtq::RequestType::MEASURE_NO_ACTUATION) {
replyLen = getExchangeBufLen(specialRequest);
memcpy(exchangeBuf.data(), replyBuf.data(), replyLen);
} else if (currentRequest == imtq::RequestType::ACTUATE) {
replyLen = ImtqRepliesWithTorque::BASE_LEN;
memcpy(exchangeBuf.data(), replyBufActuation.data(), replyLen);
} else {
*size = 0;
}
*buffer = exchangeBuf.data();
*size = replyLen;
return comStatus;
}
void ImtqPollingTask::clearReadFlagsDefault(ImtqRepliesDefault& replies) {
replies.calibMgmMeasurement[0] = false;
replies.rawMgmMeasurement[0] = false;
replies.systemState[0] = false;
replies.specialRequestReply[0] = false;
replies.engHk[0] = false;
}
ReturnValue_t ImtqPollingTask::i2cCmdExecDefault(imtq::CC::CC cc, uint8_t* replyPtr,
size_t replyLen, ReturnValue_t comErrIfFails) {
ReturnValue_t res = performI2cFullRequest(replyPtr + 1, replyLen);
if (res != returnvalue::OK) {
sif::error << "IMTQ: I2C transaction for command 0x" << std::hex << std::setw(2) << cc
<< " failed" << std::dec << std::endl;
comStatus = comErrIfFails;
return returnvalue::FAILED;
}
if (replyPtr[1] != cc) {
sif::warning << "IMTQ: Unexpected CC 0x" << std::hex << std::setw(2)
<< static_cast<int>(replyPtr[1]) << " for command 0x" << cc << std::dec
<< std::endl;
comStatus = comErrIfFails;
return returnvalue::FAILED;
}
replyPtr[0] = true;
return returnvalue::OK;
}
void ImtqPollingTask::clearReadFlagsWithTorque(ImtqRepliesWithTorque& replies) {
replies.dipoleActuation[0] = false;
replies.engHk[0] = false;
replies.rawMgmMeasurement[0] = false;
replies.startMtmMeasurement[0] = false;
}
ReturnValue_t ImtqPollingTask::performI2cFullRequest(uint8_t* reply, size_t replyLen) {
int fd = 0;
if (cmdLen == 0 or reply == nullptr) {
return returnvalue::FAILED;
}
{
UnixFileGuard fileHelper(i2cDev, fd, O_RDWR, "ImtqPollingTask::performI2cFullRequest");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return fileHelper.getOpenResult();
}
if (ioctl(fd, I2C_SLAVE, i2cAddr) < 0) {
sif::warning << "Opening IMTQ slave device failed with code " << errno << ": "
<< strerror(errno) << std::endl;
}
int written = write(fd, cmdBuf.data(), cmdLen);
if (written < 0) {
sif::error << "IMTQ: Failed to send with error code " << errno
<< ". Error description: " << strerror(errno) << std::endl;
return returnvalue::FAILED;
} else if (static_cast<size_t>(written) != cmdLen) {
sif::error << "IMTQ: Could not write all bytes" << std::endl;
return returnvalue::FAILED;
}
}
#if FSFW_HAL_I2C_WIRETAPPING == 1
sif::info << "Sent I2C data to bus " << deviceFile << ":" << std::endl;
arrayprinter::print(sendData, sendLen);
#endif
// wait 1 ms like specified in the datasheet. This is the time the IMTQ needs
// to prepare a reply.
usleep(1000);
{
UnixFileGuard fileHelper(i2cDev, fd, O_RDWR, "ImtqPollingTask::performI2cFullRequest");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return fileHelper.getOpenResult();
}
if (ioctl(fd, I2C_SLAVE, i2cAddr) < 0) {
sif::warning << "Opening IMTQ slave device failed with code " << errno << ": "
<< strerror(errno) << std::endl;
}
MutexGuard mg(bufLock);
int readLen = read(fd, reply, replyLen);
if (readLen != static_cast<int>(replyLen)) {
if (readLen < 0) {
sif::warning << "IMTQ: Reading failed with error code " << errno << " | " << strerror(errno)
<< std::endl;
} else {
sif::warning << "IMTQ: Read only" << readLen << " from " << replyLen << " bytes"
<< std::endl;
}
}
}
if (reply[0] == 0xff or reply[1] == 0xff) {
sif::warning << "IMTQ: No reply available after 1 millisecond";
return NO_REPLY_AVAILABLE;
}
return returnvalue::OK;
}

View File

@ -0,0 +1,71 @@
#ifndef LINUX_DEVICES_IMTQPOLLINGTASK_H_
#define LINUX_DEVICES_IMTQPOLLINGTASK_H_
#include <fsfw/tasks/SemaphoreIF.h>
#include <fsfw_hal/linux/i2c/I2cCookie.h>
#include "fsfw/devicehandlers/DeviceCommunicationIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "mission/devices/devicedefinitions/imtqHelpers.h"
class ImtqPollingTask : public SystemObject,
public ExecutableObjectIF,
public DeviceCommunicationIF {
public:
ImtqPollingTask(object_id_t imtqPollingTask);
ReturnValue_t performOperation(uint8_t operationCode) override;
ReturnValue_t initialize() override;
private:
static constexpr ReturnValue_t NO_REPLY_AVAILABLE = returnvalue::makeCode(2, 0);
enum class InternalState { IDLE, BUSY } state = InternalState::IDLE;
imtq::RequestType currentRequest = imtq::RequestType::MEASURE_NO_ACTUATION;
SemaphoreIF* semaphore;
ReturnValue_t comStatus = returnvalue::OK;
MutexIF* ipcLock;
MutexIF* bufLock;
I2cCookie* i2cCookie = nullptr;
const char* i2cDev = nullptr;
address_t i2cAddr = 0;
uint32_t currentIntegrationTimeMs = 10;
// Required in addition to integration time, otherwise old data might be read.
static constexpr uint32_t MGM_READ_BUFFER_TIME_MS = 6;
bool ignoreNextActuateRequest = false;
imtq::SpecialRequest specialRequest = imtq::SpecialRequest::NONE;
int16_t dipoles[3] = {};
uint16_t torqueDuration = 0;
std::array<uint8_t, 32> cmdBuf;
std::array<uint8_t, 524> replyBuf;
std::array<uint8_t, 524> replyBufActuation;
std::array<uint8_t, 524> exchangeBuf;
size_t cmdLen = 0;
// DeviceCommunicationIF overrides
ReturnValue_t initializeInterface(CookieIF* cookie) override;
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
ReturnValue_t getSendSuccess(CookieIF* cookie) override;
ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override;
ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override;
void ccToReplyPtrMeasure(ImtqRepliesDefault& replies, imtq::CC::CC cc, uint8_t** replyBuf,
size_t& replyLen);
void ccToReplyPtrActuate(ImtqRepliesWithTorque& replies, imtq::CC::CC cc, uint8_t** replyBuf,
size_t& replyLen);
void clearReadFlagsDefault(ImtqRepliesDefault& replies);
void clearReadFlagsWithTorque(ImtqRepliesWithTorque& replies);
size_t getExchangeBufLen(imtq::SpecialRequest specialRequest);
void buildDipoleCommand();
void handleMeasureStep();
void handleActuateStep();
ReturnValue_t i2cCmdExecDefault(imtq::CC::CC cc, uint8_t* replyPtr, size_t replyLen,
ReturnValue_t comErrIfFails);
ReturnValue_t performI2cFullRequest(uint8_t* reply, size_t replyLen);
};
#endif /* LINUX_DEVICES_IMTQPOLLINGTASK_H_ */

View File

@ -0,0 +1,473 @@
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <fsfw_hal/linux/spi/ManualCsLockGuard.h>
#include <linux/devices/Max31865RtdPolling.h>
#define OBSW_RTD_AUTO_MODE 1
#if OBSW_RTD_AUTO_MODE == 1
static constexpr uint8_t BASE_CFG = (MAX31865::Bias::ON << MAX31865::CfgBitPos::BIAS_SEL) |
(MAX31865::Wires::FOUR_WIRE << MAX31865::CfgBitPos::WIRE_SEL) |
(MAX31865::ConvMode::AUTO << MAX31865::CfgBitPos::CONV_MODE);
#else
static constexpr uint8_t BASE_CFG =
(MAX31865::Bias::OFF << MAX31865::CfgBitPos::BIAS_SEL) |
(MAX31865::Wires::FOUR_WIRE << MAX31865::CfgBitPos::WIRE_SEL) |
(MAX31865::ConvMode::NORM_OFF << MAX31865::CfgBitPos::CONV_MODE);
#endif
Max31865RtdPolling::Max31865RtdPolling(object_id_t objectId, SpiComIF* lowLevelComIF,
GpioIF* gpioIF)
: SystemObject(objectId), rtds(EiveMax31855::NUM_RTDS), comIF(lowLevelComIF), gpioIF(gpioIF) {
readerLock = MutexFactory::instance()->createMutex();
}
ReturnValue_t Max31865RtdPolling::performOperation(uint8_t operationCode) {
using namespace MAX31865;
ReturnValue_t result = returnvalue::OK;
static_cast<void>(result);
// Measured to take 0-1 ms in debug build
// Stopwatch watch;
periodicInitHandling();
#if OBSW_RTD_AUTO_MODE == 0
// 10 ms delay for VBIAS startup
TaskFactory::delayTask(10);
result = periodicReadReqHandling();
if (result != returnvalue::OK) {
return result;
}
// After requesting, 65 milliseconds delay required
TaskFactory::delayTask(65);
#endif
return periodicReadHandling();
}
bool Max31865RtdPolling::rtdIsActive(uint8_t idx) {
if (rtds[idx]->on and rtds[idx]->db.active and rtds[idx]->db.configured) {
return true;
}
return false;
}
ReturnValue_t Max31865RtdPolling::periodicInitHandling() {
using namespace MAX31865;
ReturnValue_t result = returnvalue::OK;
for (auto& rtd : rtds) {
if (rtd == nullptr) {
continue;
}
bool mustPerformInitHandling = false;
bool doWriteLowThreshold = false;
bool doWriteHighThreshold = false;
{
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
if (mg.getLockResult() != returnvalue::OK) {
sif::warning << "Max31865RtdReader::periodicInitHandling: Mutex lock failed" << std::endl;
continue;
}
mustPerformInitHandling =
(rtd->on or rtd->db.active) and not rtd->db.configured and rtd->cd.hasTimedOut();
doWriteHighThreshold = rtd->writeHighThreshold;
doWriteLowThreshold = rtd->writeLowThreshold;
}
if (mustPerformInitHandling) {
// Please note that using the manual CS lock wrapper here is problematic. Might be a SPI
// or hardware specific issue where the CS needs to be pulled high and then low again
// between transfers
result = writeCfgReg(rtd->spiCookie, BASE_CFG);
if (result != returnvalue::OK) {
handleSpiError(rtd, result, "writeCfgReg");
continue;
}
if (doWriteLowThreshold) {
result = writeLowThreshold(rtd->spiCookie, rtd->lowThreshold);
if (result != returnvalue::OK) {
handleSpiError(rtd, result, "writeLowThreshold");
}
}
if (doWriteHighThreshold) {
result = writeHighThreshold(rtd->spiCookie, rtd->highThreshold);
if (result != returnvalue::OK) {
handleSpiError(rtd, result, "writeHighThreshold");
}
}
result = clearFaultStatus(rtd->spiCookie);
if (result != returnvalue::OK) {
handleSpiError(rtd, result, "clearFaultStatus");
}
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
rtd->db.configured = true;
rtd->db.active = true;
}
}
return returnvalue::OK;
}
ReturnValue_t Max31865RtdPolling::periodicReadReqHandling() {
using namespace MAX31865;
updateActiveRtdsArray();
// Now request one shot config for all active RTDs
for (auto& rtd : rtds) {
if (rtd == nullptr) {
continue;
}
if (activeRtdsArray[rtd->idx]) {
ReturnValue_t result = writeCfgReg(rtd->spiCookie, BASE_CFG | (1 << CfgBitPos::ONE_SHOT));
if (result != returnvalue::OK) {
handleSpiError(rtd, result, "writeCfgReg");
// Release mutex ASAP
return returnvalue::FAILED;
}
}
}
return returnvalue::OK;
}
ReturnValue_t Max31865RtdPolling::periodicReadHandling() {
using namespace MAX31865;
auto result = returnvalue::OK;
updateActiveRtdsArray();
// Now read the RTD values
for (auto& rtd : rtds) {
if (rtd == nullptr) {
continue;
}
if (activeRtdsArray[rtd->idx]) {
// Please note that using the manual CS lock wrapper here is problematic. Might be a SPI
// or hardware specific issue where the CS needs to be pulled high and then low again
// between transfers
uint16_t rtdVal = 0;
bool faultBitSet = false;
result = writeCfgReg(rtd->spiCookie, BASE_CFG);
if (result != returnvalue::OK) {
handleSpiError(rtd, result, "writeCfgReg");
continue;
}
result = readRtdVal(rtd->spiCookie, rtdVal, faultBitSet);
// sif::debug << "RTD Val: " << rtdVal << std::endl;
if (result != returnvalue::OK) {
handleSpiError(rtd, result, "readRtdVal");
continue;
}
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
if (faultBitSet) {
rtd->db.faultBitSet = faultBitSet;
}
rtd->db.adcCode = rtdVal;
}
}
#if OBSW_RTD_AUTO_MODE == 0
for (auto& rtd : rtds) {
if (rtd == nullptr) {
continue;
}
// Even if a device was made inactive, turn off the bias here. If it was turned off, not
// necessary anymore..
if (rtd->on) {
result = writeBiasSel(Bias::OFF, rtd->spiCookie, BASE_CFG);
}
}
#endif
return returnvalue::OK;
}
ReturnValue_t Max31865RtdPolling::initializeInterface(CookieIF* cookie) {
if (cookie == nullptr) {
throw std::invalid_argument("Invalid MAX31865 Reader Cookie");
}
auto* rtdCookie = dynamic_cast<Max31865ReaderCookie*>(cookie);
ReturnValue_t result = comIF->initializeInterface(rtdCookie->spiCookie);
if (result != returnvalue::OK) {
return result;
}
if (rtdCookie->idx > EiveMax31855::NUM_RTDS) {
throw std::invalid_argument("Invalid RTD index");
}
rtds[rtdCookie->idx] = rtdCookie;
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
if (dbLen == 0) {
dbLen = rtdCookie->db.getSerializedSize();
}
return returnvalue::OK;
}
ReturnValue_t Max31865RtdPolling::sendMessage(CookieIF* cookie, const uint8_t* sendData,
size_t sendLen) {
if (cookie == nullptr) {
return returnvalue::FAILED;
}
auto* rtdCookie = dynamic_cast<Max31865ReaderCookie*>(cookie);
if (rtdCookie == nullptr) {
return returnvalue::FAILED;
}
// Empty command.. don't fail for now
if (sendLen < 1) {
return returnvalue::OK;
}
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
if (mg.getLockResult() != returnvalue::OK) {
sif::warning << "Max31865RtdReader::sendMessage: Mutex lock failed" << std::endl;
return returnvalue::FAILED;
}
uint8_t cmdRaw = sendData[0];
if (cmdRaw > EiveMax31855::RtdCommands::NUM_CMDS) {
sif::warning << "Max31865RtdReader::sendMessage: Invalid command" << std::endl;
return returnvalue::FAILED;
}
auto thresholdHandler = [&]() {
rtdCookie->lowThreshold = (sendData[1] << 8) | sendData[2];
rtdCookie->highThreshold = (sendData[3] << 8) | sendData[4];
rtdCookie->writeLowThreshold = true;
rtdCookie->writeHighThreshold = true;
};
auto cmd = static_cast<EiveMax31855::RtdCommands>(sendData[0]);
switch (cmd) {
case (EiveMax31855::RtdCommands::ON): {
if (not rtdCookie->on) {
rtdCookie->cd.setTimeout(MAX31865::WARMUP_MS);
rtdCookie->on = true;
rtdCookie->db.active = false;
rtdCookie->db.configured = false;
if (sendLen == 5) {
thresholdHandler();
}
}
break;
}
case (EiveMax31855::RtdCommands::ACTIVE): {
if (not rtdCookie->on) {
rtdCookie->cd.setTimeout(MAX31865::WARMUP_MS);
rtdCookie->on = true;
rtdCookie->db.active = true;
rtdCookie->db.configured = false;
} else {
rtdCookie->db.active = true;
}
if (sendLen == 5) {
thresholdHandler();
}
break;
}
case (EiveMax31855::RtdCommands::OFF): {
rtdCookie->on = false;
rtdCookie->db.active = false;
rtdCookie->db.configured = false;
break;
}
case (EiveMax31855::RtdCommands::HIGH_TRESHOLD): {
if (sendLen == 3) {
rtdCookie->highThreshold = (sendData[1] << 8) | sendData[2];
rtdCookie->writeHighThreshold = true;
} else {
return returnvalue::FAILED;
}
break;
}
case (EiveMax31855::RtdCommands::LOW_THRESHOLD): {
if (sendLen == 3) {
rtdCookie->lowThreshold = (sendData[1] << 8) | sendData[2];
rtdCookie->writeLowThreshold = true;
} else {
return returnvalue::FAILED;
}
break;
}
case (EiveMax31855::RtdCommands::CFG): {
ReturnValue_t result = writeCfgReg(rtdCookie->spiCookie, BASE_CFG);
if (result != returnvalue::OK) {
handleSpiError(rtdCookie, result, "writeCfgReg");
}
break;
}
default: {
// TODO: Only implement if needed
break;
}
}
return returnvalue::OK;
}
ReturnValue_t Max31865RtdPolling::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
ReturnValue_t Max31865RtdPolling::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
return returnvalue::OK;
}
ReturnValue_t Max31865RtdPolling::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
size_t* size) {
auto* rtdCookie = dynamic_cast<Max31865ReaderCookie*>(cookie);
if (rtdCookie == nullptr) {
return returnvalue::FAILED;
}
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
if (mg.getLockResult() != returnvalue::OK) {
// TODO: Emit warning
return returnvalue::FAILED;
}
uint8_t* exchangePtr = rtdCookie->exchangeBuf.data();
size_t serLen = 0;
auto result = rtdCookie->db.serialize(&exchangePtr, &serLen, rtdCookie->exchangeBuf.size(),
SerializeIF::Endianness::MACHINE);
if (result != returnvalue::OK) {
// TODO: Emit warning
return returnvalue::FAILED;
}
*buffer = reinterpret_cast<uint8_t*>(rtdCookie->exchangeBuf.data());
*size = serLen;
return returnvalue::OK;
}
ReturnValue_t Max31865RtdPolling::writeCfgReg(SpiCookie* cookie, uint8_t cfg) {
using namespace MAX31865;
return writeNToReg(cookie, CONFIG, 1, &cfg, nullptr);
}
ReturnValue_t Max31865RtdPolling::writeBiasSel(MAX31865::Bias bias, SpiCookie* cookie,
uint8_t baseCfg) {
using namespace MAX31865;
if (bias == MAX31865::Bias::OFF) {
baseCfg &= ~(1 << CfgBitPos::BIAS_SEL);
} else {
baseCfg |= (1 << CfgBitPos::BIAS_SEL);
}
return writeCfgReg(cookie, baseCfg);
}
ReturnValue_t Max31865RtdPolling::clearFaultStatus(SpiCookie* cookie) {
using namespace MAX31865;
// Read back the current configuration to avoid overwriting it when clearing te fault status
uint8_t currentCfg = 0;
auto result = readCfgReg(cookie, currentCfg);
if (result != returnvalue::OK) {
return result;
}
// Clear bytes 5, 3 and 2 which need to be 0
currentCfg &= ~0x2C;
currentCfg |= (1 << CfgBitPos::FAULT_STATUS_CLEAR);
return writeCfgReg(cookie, currentCfg);
}
ReturnValue_t Max31865RtdPolling::readCfgReg(SpiCookie* cookie, uint8_t& cfg) {
using namespace MAX31865;
uint8_t* replyPtr = nullptr;
auto result = readNFromReg(cookie, CONFIG, 1, &replyPtr);
if (result == returnvalue::OK) {
cfg = replyPtr[0];
}
return result;
}
ReturnValue_t Max31865RtdPolling::writeLowThreshold(SpiCookie* cookie, uint16_t val) {
using namespace MAX31865;
uint8_t cmd[2] = {static_cast<uint8_t>((val >> 8) & 0xff), static_cast<uint8_t>(val & 0xff)};
return writeNToReg(cookie, LOW_THRESHOLD, 2, cmd, nullptr);
}
ReturnValue_t Max31865RtdPolling::writeHighThreshold(SpiCookie* cookie, uint16_t val) {
using namespace MAX31865;
uint8_t cmd[2] = {static_cast<uint8_t>((val >> 8) & 0xff), static_cast<uint8_t>(val & 0xff)};
return writeNToReg(cookie, HIGH_THRESHOLD, 2, cmd, nullptr);
}
ReturnValue_t Max31865RtdPolling::readLowThreshold(SpiCookie* cookie, uint16_t& lowThreshold) {
using namespace MAX31865;
uint8_t* replyPtr = nullptr;
auto result = readNFromReg(cookie, LOW_THRESHOLD, 2, &replyPtr);
if (result == returnvalue::OK) {
lowThreshold = (replyPtr[0] << 8) | replyPtr[1];
}
return result;
}
ReturnValue_t Max31865RtdPolling::readHighThreshold(SpiCookie* cookie, uint16_t& highThreshold) {
using namespace MAX31865;
uint8_t* replyPtr = nullptr;
auto result = readNFromReg(cookie, HIGH_THRESHOLD, 2, &replyPtr);
if (result == returnvalue::OK) {
highThreshold = (replyPtr[0] << 8) | replyPtr[1];
}
return result;
}
ReturnValue_t Max31865RtdPolling::writeNToReg(SpiCookie* cookie, uint8_t reg, size_t n,
uint8_t* cmd, uint8_t** reply) {
using namespace MAX31865;
if (n > cmdBuf.size() - 1) {
return returnvalue::FAILED;
}
cmdBuf[0] = reg | WRITE_BIT;
for (size_t idx = 0; idx < n; idx++) {
cmdBuf[idx + 1] = cmd[idx];
}
return comIF->sendMessage(cookie, cmdBuf.data(), n + 1);
}
ReturnValue_t Max31865RtdPolling::readRtdVal(SpiCookie* cookie, uint16_t& val, bool& faultBitSet) {
using namespace MAX31865;
uint8_t* replyPtr = nullptr;
auto result = readNFromReg(cookie, RTD, 2, &replyPtr);
if (result != returnvalue::OK) {
return result;
}
if (replyPtr[1] & 0b0000'0001) {
faultBitSet = true;
}
// Shift 1 to the right to remove fault bit
val = ((replyPtr[0] << 8) | replyPtr[1]) >> 1;
return result;
}
ReturnValue_t Max31865RtdPolling::readNFromReg(SpiCookie* cookie, uint8_t reg, size_t n,
uint8_t** reply) {
using namespace MAX31865;
if (n > 4) {
return returnvalue::FAILED;
}
// Clear write bit in any case
reg &= ~WRITE_BIT;
cmdBuf[0] = reg;
std::memset(cmdBuf.data() + 1, 0, n);
ReturnValue_t result = comIF->sendMessage(cookie, cmdBuf.data(), n + 1);
if (result != returnvalue::OK) {
return returnvalue::FAILED;
}
size_t dummyLen = 0;
uint8_t* replyPtr = nullptr;
result = comIF->readReceivedMessage(cookie, &replyPtr, &dummyLen);
if (result != returnvalue::OK) {
return result;
}
if (reply != nullptr) {
*reply = replyPtr + 1;
}
return returnvalue::OK;
}
ReturnValue_t Max31865RtdPolling::updateActiveRtdsArray() {
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
if (mg.getLockResult() != returnvalue::OK) {
sif::warning << "Max31865RtdReader::periodicReadHandling: Mutex lock failed" << std::endl;
return returnvalue::FAILED;
}
for (const auto& rtd : rtds) {
activeRtdsArray[rtd->idx] = rtdIsActive(rtd->idx);
}
return returnvalue::OK;
}
ReturnValue_t Max31865RtdPolling::handleSpiError(Max31865ReaderCookie* cookie, ReturnValue_t result,
const char* ctx) {
cookie->db.spiErrorCount.value += 1;
sif::warning << "Max31865RtdReader::handleSpiError: " << ctx << " | Failed with result " << result
<< std::endl;
return result;
}
ReturnValue_t Max31865RtdPolling::initialize() {
csLock = comIF->getCsMutex();
return SystemObject::initialize();
}

View File

@ -0,0 +1,93 @@
#ifndef LINUX_DEVICES_MAX31865RTDREADER_H_
#define LINUX_DEVICES_MAX31865RTDREADER_H_
#include <fsfw/ipc/MutexIF.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/timemanager/clockDefinitions.h>
#include <fsfw_hal/linux/spi/SpiComIF.h>
#include <fsfw_hal/linux/spi/SpiCookie.h>
#include "devConf.h"
#include "fsfw/devicehandlers/DeviceCommunicationIF.h"
#include "mission/devices/devicedefinitions/Max31865Definitions.h"
struct Max31865ReaderCookie : public CookieIF {
Max31865ReaderCookie(){};
Max31865ReaderCookie(object_id_t handlerId_, uint8_t idx_, const std::string& locString_,
SpiCookie* spiCookie_)
: idx(idx_), handlerId(handlerId_), locString(locString_), spiCookie(spiCookie_) {}
uint8_t idx = 0;
object_id_t handlerId = objects::NO_OBJECT;
std::string locString = "";
std::array<uint8_t, 12> exchangeBuf{};
Countdown cd = Countdown(MAX31865::WARMUP_MS);
bool on = false;
bool writeLowThreshold = false;
bool writeHighThreshold = false;
uint16_t lowThreshold = 0;
uint16_t highThreshold = 0;
SpiCookie* spiCookie = nullptr;
// Exchange data buffer struct
EiveMax31855::ReadOutStruct db;
};
class Max31865RtdPolling : public SystemObject,
public ExecutableObjectIF,
public DeviceCommunicationIF {
public:
Max31865RtdPolling(object_id_t objectId, SpiComIF* lowLevelComIF, GpioIF* gpioIF);
ReturnValue_t performOperation(uint8_t operationCode) override;
ReturnValue_t initialize() override;
private:
std::vector<Max31865ReaderCookie*> rtds;
std::array<uint8_t, 4> cmdBuf = {};
std::array<bool, 12> activeRtdsArray{};
size_t dbLen = 0;
MutexIF* readerLock;
static constexpr MutexIF::TimeoutType LOCK_TYPE = MutexIF::TimeoutType::WAITING;
static constexpr uint32_t LOCK_TIMEOUT = 20;
static constexpr char LOCK_CTX[] = "Max31865RtdPolling";
SpiComIF* comIF;
GpioIF* gpioIF;
MutexIF::TimeoutType csTimeoutType = MutexIF::TimeoutType::WAITING;
uint32_t csTimeoutMs = spi::RTD_CS_TIMEOUT;
MutexIF* csLock = nullptr;
ReturnValue_t periodicInitHandling();
ReturnValue_t periodicReadReqHandling();
ReturnValue_t periodicReadHandling();
bool rtdIsActive(uint8_t idx);
ReturnValue_t writeCfgReg(SpiCookie* cookie, uint8_t cfg);
ReturnValue_t writeBiasSel(MAX31865::Bias bias, SpiCookie* cookie, uint8_t baseCfg);
ReturnValue_t readCfgReg(SpiCookie* cookie, uint8_t& cfg);
ReturnValue_t readRtdVal(SpiCookie* cookie, uint16_t& val, bool& faultBitSet);
ReturnValue_t writeLowThreshold(SpiCookie* cookie, uint16_t val);
ReturnValue_t writeHighThreshold(SpiCookie* cookie, uint16_t val);
ReturnValue_t readLowThreshold(SpiCookie* cookie, uint16_t& val);
ReturnValue_t readHighThreshold(SpiCookie* cookie, uint16_t& val);
ReturnValue_t clearFaultStatus(SpiCookie* cookie);
ReturnValue_t readNFromReg(SpiCookie* cookie, uint8_t reg, size_t n, uint8_t** reply);
ReturnValue_t writeNToReg(SpiCookie* cookie, uint8_t reg, size_t n, uint8_t* cmd,
uint8_t** reply);
ReturnValue_t initializeInterface(CookieIF* cookie) override;
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
ReturnValue_t getSendSuccess(CookieIF* cookie) override;
ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override;
ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override;
ReturnValue_t updateActiveRtdsArray();
ReturnValue_t handleSpiError(Max31865ReaderCookie* cookie, ReturnValue_t result, const char* ctx);
};
#endif /* LINUX_DEVICES_MAX31865RTDREADER_H_ */

View File

@ -0,0 +1,542 @@
#include "RwPollingTask.h"
#include <fcntl.h>
#include <fsfw/globalfunctions/CRC.h>
#include <fsfw/tasks/SemaphoreFactory.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <fsfw_hal/common/spi/spiCommon.h>
#include <fsfw_hal/linux/utility.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "devConf.h"
#include "mission/devices/devicedefinitions/rwHelpers.h"
RwPollingTask::RwPollingTask(object_id_t objectId, const char* spiDev, GpioIF& gpioIF)
: SystemObject(objectId), spiDev(spiDev), gpioIF(gpioIF) {
semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
semaphore->acquire();
ipcLock = MutexFactory::instance()->createMutex();
spiLock = MutexFactory::instance()->createMutex();
}
ReturnValue_t RwPollingTask::performOperation(uint8_t operationCode) {
for (unsigned i = 0; i < 4; i++) {
if (rwCookies[i] == nullptr) {
sif::error << "Invalid RW cookie at index" << i << std::endl;
return returnvalue::FAILED;
}
}
while (true) {
ipcLock->lockMutex();
state = InternalState::IDLE;
ipcLock->unlockMutex();
semaphore->acquire();
// This loop takes 50 ms on a debug build.
// Stopwatch watch;
TaskFactory::delayTask(5);
int fd = 0;
for (auto& skip : skipCommandingForRw) {
skip = false;
}
setAllReadFlagsFalse();
ReturnValue_t result = openSpi(O_RDWR, fd);
if (result != returnvalue::OK) {
continue;
}
for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
if (rwCookies[idx]->specialRequest == rws::SpecialRwRequest::RESET_MCU) {
prepareSimpleCommand(rws::RESET_MCU);
// No point in commanding that specific RW for the cycle.
skipCommandingForRw[idx] = true;
writeOneRwCmd(idx, fd);
} else if (rwCookies[idx]->setSpeed) {
prepareSetSpeedCmd(idx);
if (writeOneRwCmd(idx, fd) != returnvalue::OK) {
continue;
}
}
}
closeSpi(fd);
if (readAllRws(rws::SET_SPEED) != returnvalue::OK) {
continue;
}
prepareSimpleCommand(rws::GET_LAST_RESET_STATUS);
if (writeAndReadAllRws(rws::GET_LAST_RESET_STATUS) != returnvalue::OK) {
continue;
}
prepareSimpleCommand(rws::GET_RW_STATUS);
if (writeAndReadAllRws(rws::GET_RW_STATUS) != returnvalue::OK) {
continue;
}
prepareSimpleCommand(rws::GET_TEMPERATURE);
if (writeAndReadAllRws(rws::GET_TEMPERATURE) != returnvalue::OK) {
continue;
}
prepareSimpleCommand(rws::CLEAR_LAST_RESET_STATUS);
if (writeAndReadAllRws(rws::CLEAR_LAST_RESET_STATUS) != returnvalue::OK) {
continue;
}
handleSpecialRequests();
}
return returnvalue::OK;
}
ReturnValue_t RwPollingTask::initialize() { return returnvalue::OK; }
ReturnValue_t RwPollingTask::initializeInterface(CookieIF* cookie) {
// We don't need to set the speed because a SPI core is used, but the mode has to be set once
// correctly for all RWs
if (not modeAndSpeedWasSet) {
int fd = open(spiDev, O_RDWR);
if (fd < 0) {
sif::error << "could not open RW SPI bus" << std::endl;
return returnvalue::FAILED;
}
spi::SpiModes mode = spi::RW_MODE;
int retval = ioctl(fd, SPI_IOC_WR_MODE, reinterpret_cast<uint8_t*>(&mode));
if (retval != 0) {
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI mode failed");
}
retval = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi::RW_SPEED);
if (retval != 0) {
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI speed failed");
}
close(fd);
modeAndSpeedWasSet = true;
}
auto* rwCookie = dynamic_cast<RwCookie*>(cookie);
if (rwCookie == nullptr) {
sif::error << "RwPollingTask::initializeInterface: Wrong cookie" << std::endl;
return returnvalue::FAILED;
}
rwCookies[rwCookie->rwIdx] = rwCookie;
return returnvalue::OK;
}
ReturnValue_t RwPollingTask::sendMessage(CookieIF* cookie, const uint8_t* sendData,
size_t sendLen) {
if (sendData == nullptr or sendLen < 8) {
return DeviceHandlerIF::INVALID_DATA;
}
int32_t speed = 0;
uint16_t rampTime = 0;
const uint8_t* currentBuf = sendData;
bool setSpeed = currentBuf[0];
currentBuf += 1;
sendLen -= 1;
SerializeAdapter::deSerialize(&speed, &currentBuf, &sendLen, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&rampTime, &currentBuf, &sendLen, SerializeIF::Endianness::MACHINE);
rws::SpecialRwRequest specialRequest = rws::SpecialRwRequest::REQUEST_NONE;
if (sendLen == 8 and sendData[7] < static_cast<uint8_t>(rws::SpecialRwRequest::NUM_REQUESTS)) {
specialRequest = static_cast<rws::SpecialRwRequest>(sendData[7]);
}
RwCookie* rwCookie = dynamic_cast<RwCookie*>(cookie);
if (rwCookie == nullptr) {
return returnvalue::FAILED;
}
{
MutexGuard mg(ipcLock);
rwCookie->setSpeed = setSpeed;
rwCookie->currentRwSpeed = speed;
rwCookie->currentRampTime = rampTime;
rwCookie->specialRequest = specialRequest;
if (state == InternalState::IDLE) {
state = InternalState::BUSY;
semaphore->release();
}
}
return returnvalue::OK;
}
ReturnValue_t RwPollingTask::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
ReturnValue_t RwPollingTask::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
return returnvalue::OK;
}
ReturnValue_t RwPollingTask::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
RwCookie* rwCookie = dynamic_cast<RwCookie*>(cookie);
if (rwCookie == nullptr or rwCookie->bufLock == nullptr) {
return returnvalue::FAILED;
}
{
MutexGuard mg(rwCookie->bufLock);
memcpy(rwCookie->exchangeBuf.data(), rwCookie->replyBuf.data(), rwCookie->replyBuf.size());
}
*buffer = rwCookie->exchangeBuf.data();
*size = rwCookie->exchangeBuf.size();
return returnvalue::OK;
}
ReturnValue_t RwPollingTask::writeAndReadAllRws(DeviceCommandId_t id) {
// Stopwatch watch;
ReturnValue_t result = returnvalue::OK;
int fd = 0;
result = openSpi(O_RDWR, fd);
if (result != returnvalue::OK) {
return result;
}
for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
if (skipCommandingForRw[idx]) {
continue;
}
result = sendOneMessage(fd, *rwCookies[idx]);
if (result != returnvalue::OK) {
closeSpi(fd);
return returnvalue::FAILED;
}
}
closeSpi(fd);
return readAllRws(id);
}
ReturnValue_t RwPollingTask::openSpi(int flags, int& fd) {
fd = open(spiDev, flags);
if (fd < 0) {
sif::error << "RwPollingTask::openSpi: Failed to open device file" << std::endl;
return SpiComIF::OPENING_FILE_FAILED;
}
return returnvalue::OK;
}
ReturnValue_t RwPollingTask::readNextReply(RwCookie& rwCookie, uint8_t* replyBuf,
size_t maxReplyLen) {
ReturnValue_t result = returnvalue::OK;
int fd = 0;
gpioId_t gpioId = rwCookie.getChipSelectPin();
uint8_t byteRead = 0;
result = openSpi(O_RDWR, fd);
if (result != returnvalue::OK) {
return result;
}
pullCsLow(gpioId, gpioIF);
bool lastByteWasFrameMarker = false;
Countdown cd(2000);
size_t readIdx = 0;
while (true) {
lastByteWasFrameMarker = false;
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 (byteRead == rws::FRAME_DELIMITER) {
lastByteWasFrameMarker = true;
}
// Start of frame detected.
if (byteRead != rws::FRAME_DELIMITER and not lastByteWasFrameMarker) {
break;
}
if (readIdx % 100 == 0 && cd.hasTimedOut()) {
pullCsHigh(gpioId, gpioIF);
closeSpi(fd);
return rws::SPI_READ_FAILURE;
}
readIdx++;
}
#if FSFW_HAL_SPI_WIRETAPPING == 1
sif::info << "RW start marker detected" << std::endl;
#endif
size_t decodedFrameLen = 0;
MutexGuard mg(rwCookie.bufLock);
while (decodedFrameLen < maxReplyLen) {
// First byte already read in
if (decodedFrameLen != 0) {
byteRead = 0;
if (read(fd, &byteRead, 1) != 1) {
sif::error << "RwPollingTask: Read failed" << std::endl;
result = rws::SPI_READ_FAILURE;
break;
}
}
if (byteRead == rws::FRAME_DELIMITER) {
// Reached end of frame
break;
} else if (byteRead == 0x7D) {
if (read(fd, &byteRead, 1) != 1) {
sif::error << "RwPollingTask: Read failed" << std::endl;
result = rws::SPI_READ_FAILURE;
break;
}
if (byteRead == 0x5E) {
*(replyBuf + decodedFrameLen) = 0x7E;
decodedFrameLen++;
continue;
} else if (byteRead == 0x5D) {
*(replyBuf + decodedFrameLen) = 0x7D;
decodedFrameLen++;
continue;
} else {
sif::error << "RwPollingTask: Invalid substitute" << std::endl;
result = rws::INVALID_SUBSTITUTE;
break;
}
} else {
*(replyBuf + decodedFrameLen) = byteRead;
decodedFrameLen++;
continue;
}
// Check end marker.
/**
* There might be the unlikely case that each byte in a get-telemetry reply has been
* replaced by its substitute. Then the next byte must correspond to the end sign 0x7E.
* Otherwise there might be something wrong.
*/
if (decodedFrameLen == maxReplyLen) {
if (read(fd, &byteRead, 1) != 1) {
sif::error << "rwSpiCallback::spiCallback: Failed to read last byte" << std::endl;
result = rws::SPI_READ_FAILURE;
break;
}
if (byteRead != rws::FRAME_DELIMITER) {
sif::error << "rwSpiCallback::spiCallback: Missing end sign "
<< static_cast<int>(rws::FRAME_DELIMITER) << std::endl;
decodedFrameLen--;
result = rws::MISSING_END_SIGN;
break;
}
}
result = returnvalue::OK;
}
pullCsHigh(gpioId, gpioIF);
closeSpi(fd);
return result;
}
ReturnValue_t RwPollingTask::writeOneRwCmd(uint8_t rwIdx, int fd) {
ReturnValue_t result = sendOneMessage(fd, *rwCookies[rwIdx]);
if (result != returnvalue::OK) {
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t RwPollingTask::readAllRws(DeviceCommandId_t id) {
// SPI dev will be opened in readNextReply on demand.
for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
if (((id == rws::SET_SPEED) and !rwCookies[idx]->setSpeed) or skipCommandingForRw[idx]) {
continue;
}
uint8_t* replyBuf;
size_t maxReadLen = idAndIdxToReadBuffer(id, idx, &replyBuf);
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.
return returnvalue::OK;
}
size_t RwPollingTask::idAndIdxToReadBuffer(DeviceCommandId_t id, uint8_t rwIdx, uint8_t** ptr) {
uint8_t* rawStart = rwCookies[rwIdx]->replyBuf.data();
RwReplies replies(rawStart);
switch (id) {
case (rws::GET_RW_STATUS): {
*ptr = replies.rwStatusReply;
break;
}
case (rws::SET_SPEED): {
*ptr = replies.setSpeedReply;
break;
}
case (rws::CLEAR_LAST_RESET_STATUS): {
*ptr = replies.clearLastResetStatusReply;
break;
}
case (rws::GET_LAST_RESET_STATUS): {
*ptr = replies.getLastResetStatusReply;
break;
}
case (rws::GET_TEMPERATURE): {
*ptr = replies.readTemperatureReply;
break;
}
case (rws::GET_TM): {
*ptr = replies.hkDataReply;
break;
}
case (rws::INIT_RW_CONTROLLER): {
*ptr = replies.initRwControllerReply;
break;
}
default: {
sif::error << "no reply buffer for rw command " << id << std::endl;
*ptr = replies.dummyPointer;
return 0;
}
}
return rws::idToPacketLen(id);
}
void RwPollingTask::fillSpecialRequestArray() {
for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
if (skipCommandingForRw[idx]) {
specialRequestIds[idx] = DeviceHandlerIF::NO_COMMAND_ID;
continue;
}
switch (rwCookies[idx]->specialRequest) {
case (rws::SpecialRwRequest::GET_TM): {
specialRequestIds[idx] = rws::GET_TM;
break;
}
case (rws::SpecialRwRequest::INIT_RW_CONTROLLER): {
specialRequestIds[idx] = rws::INIT_RW_CONTROLLER;
break;
}
default: {
specialRequestIds[idx] = DeviceHandlerIF::NO_COMMAND_ID;
}
}
}
}
void RwPollingTask::handleSpecialRequests() {
int fd = 0;
fillSpecialRequestArray();
ReturnValue_t result = openSpi(O_RDWR, fd);
if (result != returnvalue::OK) {
return;
}
for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
if (specialRequestIds[idx] == DeviceHandlerIF::NO_COMMAND_ID) {
continue;
}
prepareSimpleCommand(specialRequestIds[idx]);
writeOneRwCmd(idx, fd);
}
closeSpi(fd);
usleep(rws::SPI_REPLY_DELAY);
for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
if (specialRequestIds[idx] == DeviceHandlerIF::NO_COMMAND_ID) {
continue;
}
uint8_t* replyBuf;
size_t maxReadLen = idAndIdxToReadBuffer(specialRequestIds[idx], idx, &replyBuf);
result = readNextReply(*rwCookies[idx], replyBuf, 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;
}
}
}
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
void RwPollingTask::closeSpi(int fd) {
// This will perform the function to close the SPI
close(fd);
// The SPI is now closed.
}
ReturnValue_t RwPollingTask::sendOneMessage(int fd, RwCookie& rwCookie) {
gpioId_t gpioId = rwCookie.getChipSelectPin();
if (spiLock == nullptr) {
sif::debug << "rwSpiCallback::spiCallback: Mutex or GPIO interface invalid" << std::endl;
return returnvalue::FAILED;
}
// Add datalinklayer like specified in the datasheet.
size_t lenToSend = 0;
rws::encodeHdlc(writeBuffer.data(), writeLen, encodedBuffer.data(), lenToSend);
pullCsLow(gpioId, gpioIF);
if (write(fd, encodedBuffer.data(), lenToSend) != static_cast<ssize_t>(lenToSend)) {
sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl;
pullCsHigh(gpioId, gpioIF);
return rws::SPI_WRITE_FAILURE;
}
pullCsHigh(gpioId, gpioIF);
return returnvalue::OK;
}
ReturnValue_t RwPollingTask::pullCsLow(gpioId_t gpioId, GpioIF& gpioIF) {
ReturnValue_t result = spiLock->lockMutex(TIMEOUT_TYPE, TIMEOUT_MS);
if (result != returnvalue::OK) {
sif::debug << "RwPollingTask::pullCsLow: Failed to lock mutex" << std::endl;
return result;
}
// Pull SPI CS low. For now, no support for active high given
if (gpioId != gpio::NO_GPIO) {
result = gpioIF.pullLow(gpioId);
if (result != returnvalue::OK) {
sif::error << "RwPollingTask::pullCsLow: Failed to pull chip select low" << std::endl;
return result;
}
}
return returnvalue::OK;
}
void RwPollingTask::pullCsHigh(gpioId_t gpioId, GpioIF& gpioIF) {
if (gpioId != gpio::NO_GPIO) {
if (gpioIF.pullHigh(gpioId) != returnvalue::OK) {
sif::error << "closeSpi: Failed to pull chip select high" << std::endl;
}
}
if (spiLock->unlockMutex() != returnvalue::OK) {
sif::error << "RwPollingTask::pullCsHigh: Failed to unlock mutex" << std::endl;
;
}
}
void RwPollingTask::prepareSimpleCommand(DeviceCommandId_t id) {
writeBuffer[0] = static_cast<uint8_t>(id);
uint16_t crc = CRC::crc16ccitt(writeBuffer.data(), 1, 0xFFFF);
writeBuffer[1] = static_cast<uint8_t>(crc & 0xFF);
writeBuffer[2] = static_cast<uint8_t>(crc >> 8 & 0xFF);
writeLen = 3;
}
ReturnValue_t RwPollingTask::prepareSetSpeedCmd(uint8_t rwIdx) {
writeBuffer[0] = static_cast<uint8_t>(rws::SET_SPEED);
uint8_t* serPtr = writeBuffer.data() + 1;
int32_t speedToSet = 0;
uint16_t rampTimeToSet = 10;
{
MutexGuard mg(ipcLock);
speedToSet = rwCookies[rwIdx]->currentRwSpeed;
rampTimeToSet = rwCookies[rwIdx]->currentRampTime;
}
size_t serLen = 1;
SerializeAdapter::serialize(&speedToSet, &serPtr, &serLen, writeBuffer.size(),
SerializeIF::Endianness::LITTLE);
SerializeAdapter::serialize(&rampTimeToSet, &serPtr, &serLen, writeBuffer.size(),
SerializeIF::Endianness::LITTLE);
uint16_t crc = CRC::crc16ccitt(writeBuffer.data(), 7, 0xFFFF);
writeBuffer[7] = static_cast<uint8_t>(crc & 0xFF);
writeBuffer[8] = static_cast<uint8_t>((crc >> 8) & 0xFF);
writeLen = 9;
return returnvalue::OK;
}

View File

@ -0,0 +1,91 @@
#ifndef LINUX_DEVICES_RWPOLLINGTASK_H_
#define LINUX_DEVICES_RWPOLLINGTASK_H_
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/tasks/SemaphoreIF.h>
#include <fsfw_hal/common/gpio/GpioIF.h>
#include <fsfw_hal/linux/spi/SpiComIF.h>
#include <fsfw_hal/linux/spi/SpiCookie.h>
#include "mission/devices/devicedefinitions/rwHelpers.h"
class RwCookie : public SpiCookie {
friend class RwPollingTask;
public:
static constexpr size_t REPLY_BUF_LEN = 524;
RwCookie(uint8_t rwIdx, address_t spiAddress, gpioId_t chipSelect, const size_t maxSize,
spi::SpiModes spiMode, uint32_t spiSpeed)
: SpiCookie(spiAddress, chipSelect, maxSize, spiMode, spiSpeed), rwIdx(rwIdx) {
bufLock = MutexFactory::instance()->createMutex();
}
private:
std::array<uint8_t, REPLY_BUF_LEN> replyBuf{};
std::array<uint8_t, REPLY_BUF_LEN> exchangeBuf{};
MutexIF* bufLock;
bool setSpeed = true;
int32_t currentRwSpeed = 0;
uint16_t currentRampTime = 0;
rws::SpecialRwRequest specialRequest = rws::SpecialRwRequest::REQUEST_NONE;
uint8_t rwIdx;
};
class RwPollingTask : public SystemObject, public ExecutableObjectIF, public DeviceCommunicationIF {
public:
RwPollingTask(object_id_t objectId, const char* spiDev, GpioIF& gpioIF);
ReturnValue_t performOperation(uint8_t operationCode) override;
ReturnValue_t initialize() override;
private:
enum class InternalState { IDLE, BUSY } state = InternalState::IDLE;
SemaphoreIF* semaphore;
bool debugMode = false;
bool modeAndSpeedWasSet = false;
MutexIF* ipcLock;
MutexIF* spiLock;
const char* spiDev;
GpioIF& gpioIF;
std::array<bool, 4> skipCommandingForRw;
std::array<DeviceCommandId_t, 4> specialRequestIds;
std::array<RwCookie*, 4> rwCookies;
std::array<uint8_t, rws::MAX_CMD_SIZE> writeBuffer;
std::array<uint8_t, rws::MAX_CMD_SIZE * 2> encodedBuffer;
size_t writeLen = 0;
static constexpr MutexIF::TimeoutType TIMEOUT_TYPE = MutexIF::TimeoutType::WAITING;
static constexpr uint32_t TIMEOUT_MS = 20;
static constexpr uint8_t MAX_RETRIES_REPLY = 5;
// DeviceCommunicationIF overrides
ReturnValue_t initializeInterface(CookieIF* cookie) override;
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
ReturnValue_t getSendSuccess(CookieIF* cookie) override;
ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override;
ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override;
ReturnValue_t writeAndReadAllRws(DeviceCommandId_t id);
ReturnValue_t writeOneRwCmd(uint8_t rwIdx, int fd);
ReturnValue_t readAllRws(DeviceCommandId_t id);
ReturnValue_t sendOneMessage(int fd, RwCookie& rwCookie);
ReturnValue_t readNextReply(RwCookie& rwCookie, uint8_t* replyBuf, size_t maxReplyLen);
void handleSpecialRequests();
ReturnValue_t openSpi(int flags, int& fd);
ReturnValue_t pullCsLow(gpioId_t gpioId, GpioIF& gpioIF);
void prepareSimpleCommand(DeviceCommandId_t id);
ReturnValue_t prepareSetSpeedCmd(uint8_t rwIdx);
size_t idAndIdxToReadBuffer(DeviceCommandId_t id, uint8_t rwIdx, uint8_t** readPtr);
void fillSpecialRequestArray();
void setAllReadFlagsFalse();
void pullCsHigh(gpioId_t gpioId, GpioIF& gpioIF);
void closeSpi(int);
};
#endif /* LINUX_DEVICES_RWPOLLINGTASK_H_ */

View File

@ -0,0 +1,7 @@
#include "ScexDleParser.h"
ScexDleParser::ScexDleParser(SimpleRingBuffer &decodeRingBuf, DleEncoder &decoder,
BufPair encodedBuf, BufPair decodedBuf)
: DleParser(decodeRingBuf, decoder, encodedBuf, decodedBuf){};
ScexDleParser::~ScexDleParser(){};

View File

@ -0,0 +1,13 @@
#pragma once
#include <fsfw/globalfunctions/DleParser.h>
class ScexDleParser : public DleParser {
public:
ScexDleParser(SimpleRingBuffer &decodeRingBuf, DleEncoder &decoder, BufPair encodedBuf,
BufPair decodedBuf);
virtual ~ScexDleParser();
private:
};

View File

@ -0,0 +1,86 @@
#include "ScexHelper.h"
#include <fsfw/globalfunctions/CRC.h>
#include "fsfw/serviceinterface.h"
using namespace returnvalue;
ScexHelper::ScexHelper() {}
ReturnValue_t ScexHelper::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const {
return FAILED;
}
size_t ScexHelper::getSerializedSize() const { return totalPacketLen; }
ReturnValue_t ScexHelper::deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) {
if (buffer == nullptr or size == nullptr) {
return FAILED;
}
if (*size < 7) {
return STREAM_TOO_SHORT;
}
start = *buffer;
cmdByteRaw = **buffer;
cmd = static_cast<scex::Cmds>((cmdByteRaw >> 1) & 0b11111);
*buffer += 1;
packetCounter = **buffer;
*buffer += 1;
totalPacketCounter = **buffer;
*buffer += 1;
payloadLen = (**buffer << 8) | *(*buffer + 1);
*buffer += 2;
payloadStart = *buffer;
totalPacketLen = payloadLen + scex::HEADER_LEN + scex::CRC_LEN;
if (totalPacketLen >= *size) {
return STREAM_TOO_SHORT;
}
*buffer += payloadLen;
crc = (**buffer << 8) | *(*buffer + 1);
if (CRC::crc16ccitt(start, totalPacketLen) != 0) {
return INVALID_CRC;
}
return OK;
}
scex::Cmds ScexHelper::getCmd() const { return cmd; }
uint8_t ScexHelper::getCmdByteRaw() const { return cmdByteRaw; }
uint16_t ScexHelper::getCrc() const { return crc; }
size_t ScexHelper::getExpectedPacketLen() const { return totalPacketLen; }
uint8_t ScexHelper::getPacketCounter() const { return packetCounter; }
uint16_t ScexHelper::getPayloadLen() const { return payloadLen; }
const uint8_t* ScexHelper::getStart() const { return start; }
uint8_t ScexHelper::getTotalPacketCounter() const { return totalPacketCounter; }
std::ostream& operator<<(std::ostream& os, const ScexHelper& h) {
using namespace std;
sif::info << "Command Byte Raw: 0x" << std::setw(2) << std::setfill('0') << std::hex
<< (int)h.cmdByteRaw << " | Command: 0x" << std::setw(2) << std::setfill('0')
<< std::hex << static_cast<int>(h.cmd) << std::dec << std::endl;
sif::info << "PacketCounter: " << h.packetCounter << endl;
sif::info << "TotalPacketCount: " << h.totalPacketCounter << endl;
sif::info << "PayloadLength: " << h.payloadLen << endl;
sif::info << "TotalPacketLength: " << h.totalPacketLen;
return os;
}
std::ofstream& operator<<(std::ofstream& of, const ScexHelper& h) {
of.write(reinterpret_cast<const char*>(h.start), h.getSerializedSize());
return of;
}

View File

@ -0,0 +1,46 @@
#ifndef LINUX_DEVICES_SCEXHELPER_H_
#define LINUX_DEVICES_SCEXHELPER_H_
#include <fsfw/serialize/SerializeIF.h>
#include <mission/devices/devicedefinitions/ScexDefinitions.h>
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <iostream>
class ScexHelper : public SerializeIF {
public:
static const ReturnValue_t INVALID_CRC = returnvalue::makeCode(0, 2);
ScexHelper();
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness = Endianness::BIG) override;
friend std::ostream &operator<<(std::ostream &os, const ScexHelper &h);
friend std::ofstream &operator<<(std::ofstream &os, const ScexHelper &h);
scex::Cmds getCmd() const;
uint8_t getCmdByteRaw() const;
uint16_t getCrc() const;
size_t getExpectedPacketLen() const;
uint8_t getPacketCounter() const;
uint16_t getPayloadLen() const;
const uint8_t *getStart() const;
uint8_t getTotalPacketCounter() const;
private:
const uint8_t *start = nullptr;
uint16_t crc = 0;
uint8_t cmdByteRaw = 0;
scex::Cmds cmd = scex::Cmds::INVALID;
int packetCounter = 0;
int totalPacketCounter = 0;
uint16_t payloadLen = 0;
const uint8_t *payloadStart = 0;
size_t totalPacketLen = 0;
};
#endif /* LINUX_DEVICES_SCEXHELPER_H_ */

View File

@ -0,0 +1,230 @@
#include "ScexUartReader.h"
#include <fcntl.h> // Contains file controls like O_RDWR
#include <fsfw/globalfunctions/arrayprinter.h>
#include <fsfw/ipc/MutexFactory.h>
#include <fsfw/ipc/MutexGuard.h>
#include <fsfw/tasks/SemaphoreFactory.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw_hal/linux/serial/SerialCookie.h>
#include <unistd.h> // write(), read(), close()
#include <cerrno> // Error integer and strerror() function
#include <iostream>
#include "OBSWConfig.h"
using namespace returnvalue;
ScexUartReader::ScexUartReader(object_id_t objectId)
: SystemObject(objectId),
decodeRingBuf(4096, true),
ipcRingBuf(200 * 2048, true),
ipcQueue(200),
dleParser(decodeRingBuf, dleEncoder, {encodedBuf.data(), encodedBuf.size()},
{decodedBuf.data(), decodedBuf.size()}) {
semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
semaphore->acquire();
lock = MutexFactory::instance()->createMutex();
}
ReturnValue_t ScexUartReader::performOperation(uint8_t operationCode) {
lock->lockMutex();
state = States::IDLE;
lock->unlockMutex();
while (true) {
semaphore->acquire();
int bytesRead = 0;
// debugMode = true;
while (true) {
bytesRead = read(serialPort, reinterpret_cast<void *>(recBuf.data()),
static_cast<unsigned int>(recBuf.size()));
if (bytesRead == 0) {
{
MutexGuard mg(lock);
if (state == States::FINISH) {
dleParser.reset();
// Flush received and unread data
tcflush(serialPort, TCIOFLUSH);
state = States::IDLE;
break;
}
}
ReturnValue_t result = returnvalue::OK;
// Can be used to read frame, parity and overrun errors
// serial_icounter_struct icounter{};
// uart::readCountersAndErrors(serialPort, icounter);
while (result != DleParser::NO_PACKET_FOUND) {
result = tryDleParsing();
}
TaskFactory::delayTask(150);
} else if (bytesRead < 0) {
sif::warning << "ScexUartReader::performOperation: read call failed with error [" << errno
<< ", " << strerror(errno) << "]" << std::endl;
break;
} else if (bytesRead >= static_cast<int>(recBuf.size())) {
sif::error << "ScexUartReader::performOperation: Receive buffer too small for " << bytesRead
<< " bytes" << std::endl;
} else if (bytesRead > 0) {
if (debugMode) {
sif::info << "Received " << bytesRead
<< " bytes from the Solar Cell Experiment:" << std::endl;
}
ReturnValue_t result = dleParser.passData(recBuf.data(), bytesRead);
if (result != OK) {
sif::warning << "ScexUartReader::performOperation: Passing data to DLE parser failed"
<< std::endl;
}
result = tryDleParsing();
}
};
}
return OK;
}
ReturnValue_t ScexUartReader::initializeInterface(CookieIF *cookie) {
SerialCookie *uartCookie = dynamic_cast<SerialCookie *>(cookie);
if (uartCookie == nullptr) {
return FAILED;
}
std::string devname = uartCookie->getDeviceFile();
/* Get file descriptor */
serialPort = open(devname.c_str(), O_RDWR);
if (serialPort < 0) {
sif::warning << "ScexUartReader::initializeInterface: open call failed with error [" << errno
<< ", " << strerror(errno) << std::endl;
return FAILED;
}
// Setting up UART parameters
tty.c_cflag &= ~PARENB; // Clear parity bit
uart::setStopbits(tty, uartCookie->getStopBits());
uart::setBitsPerWord(tty, BitsPerWord::BITS_8);
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control
uart::enableRead(tty);
uart::ignoreCtrlLines(tty);
// Use non-canonical mode and clear echo flag
tty.c_lflag &= ~(ICANON | ECHO);
// Non-blocking mode, use polling
tty.c_cc[VTIME] = 0;
tty.c_cc[VMIN] = 0;
uart::setBaudrate(tty, uartCookie->getBaudrate());
if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
sif::warning << "ScexUartReader::initializeInterface: tcsetattr call failed with error ["
<< errno << ", " << strerror(errno) << std::endl;
}
// Flush received and unread data
tcflush(serialPort, TCIOFLUSH);
return OK;
}
ReturnValue_t ScexUartReader::sendMessage(CookieIF *cookie, const uint8_t *sendData,
size_t sendLen) {
ReturnValue_t result;
if (sendData == nullptr or sendLen == 0) {
return FAILED;
}
lock->lockMutex();
if (state == States::NOT_READY or state == States::RUNNING) {
lock->unlockMutex();
return FAILED;
}
tcflush(serialPort, TCIFLUSH);
state = States::RUNNING;
lock->unlockMutex();
result = semaphore->release();
if (result != OK) {
std::cout << "ScexUartReader::sendMessage: Releasing semaphore failed" << std::endl;
}
size_t encodedLen = 0;
result = dleEncoder.encode(sendData, sendLen, cmdbuf.data(), cmdbuf.size(), &encodedLen, true);
if (result != OK) {
sif::warning << "ScexUartReader::sendMessage: Encoding failed" << std::endl;
return FAILED;
}
size_t bytesWritten = write(serialPort, cmdbuf.data(), encodedLen);
if (bytesWritten != encodedLen) {
sif::warning << "ScexUartReader::sendMessage: Sending ping command to solar experiment failed"
<< std::endl;
return FAILED;
}
return OK;
}
ReturnValue_t ScexUartReader::getSendSuccess(CookieIF *cookie) { return OK; }
ReturnValue_t ScexUartReader::requestReceiveMessage(CookieIF *cookie, size_t requestLen) {
return OK;
}
void ScexUartReader::setDebugMode(bool enable) { this->debugMode = enable; }
ReturnValue_t ScexUartReader::finish() {
MutexGuard mg(lock);
if (state == States::IDLE) {
return FAILED;
}
state = States::FINISH;
return OK;
}
void ScexUartReader::handleFoundDlePacket(uint8_t *packet, size_t len) {
MutexGuard mg(lock);
ReturnValue_t result = ipcQueue.insert(len);
if (result != OK) {
sif::warning << "ScexUartReader::handleFoundDlePacket: IPCQueue error" << std::endl;
}
result = ipcRingBuf.writeData(packet, len);
if (result != OK) {
sif::warning << "ScexUartReader::handleFoundDlePacket: IPCRingBuf error" << std::endl;
}
}
ReturnValue_t ScexUartReader::tryDleParsing() {
size_t bytesRead = 0;
ReturnValue_t result = dleParser.parseRingBuf(bytesRead);
if (result == returnvalue::OK) {
// Packet found, advance read pointer.
auto &decodedPacket = dleParser.getContext().decodedPacket;
handleFoundDlePacket(decodedPacket.first, decodedPacket.second);
dleParser.confirmBytesRead(bytesRead);
} else if (result != DleParser::NO_PACKET_FOUND) {
sif::warning << "ScexUartReader::performOperation: Possible packet loss" << std::endl;
// Markers found at wrong place
// which might be a hint for a possibly lost packet.
dleParser.defaultErrorHandler();
dleParser.confirmBytesRead(bytesRead);
}
return result;
}
void ScexUartReader::reset() {
lock->lockMutex();
state = States::FINISH;
ipcRingBuf.clear();
while (not ipcQueue.empty()) {
ipcQueue.pop();
}
lock->unlockMutex();
}
ReturnValue_t ScexUartReader::readReceivedMessage(CookieIF *cookie, uint8_t **buffer,
size_t *size) {
MutexGuard mg(lock);
if (ipcQueue.empty()) {
*size = 0;
return OK;
}
ipcQueue.retrieve(size);
*buffer = ipcBuffer.data();
ReturnValue_t result = ipcRingBuf.readData(ipcBuffer.data(), *size, true);
if (result != OK) {
sif::warning << "ScexUartReader::readReceivedMessage: Reading RingBuffer failed" << std::endl;
}
return OK;
}

View File

@ -0,0 +1,61 @@
#pragma once
#include <fsfw/container/DynamicFIFO.h>
#include <fsfw/container/SimpleRingBuffer.h>
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <fsfw/globalfunctions/DleEncoder.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/timemanager/Countdown.h>
#include <linux/devices/ScexDleParser.h>
#include <termios.h> // Contains POSIX terminal control definitions
class SemaphoreIF;
class MutexIF;
class ScexUartReader : public SystemObject,
public ExecutableObjectIF,
public DeviceCommunicationIF {
friend class UartTestClass;
public:
enum class States { NOT_READY, IDLE, RUNNING, FINISH };
ScexUartReader(object_id_t objectId);
void reset();
ReturnValue_t finish();
void setDebugMode(bool enable);
private:
SemaphoreIF *semaphore;
bool debugMode = false;
MutexIF *lock;
int serialPort = 0;
States state = States::IDLE;
struct termios tty = {};
bool doFinish = false;
DleEncoder dleEncoder = DleEncoder();
SimpleRingBuffer decodeRingBuf;
std::array<uint8_t, 256> cmdbuf = {};
std::array<uint8_t, 4096> recBuf = {};
std::array<uint8_t, 4096> encodedBuf = {};
std::array<uint8_t, 4096> decodedBuf = {};
std::array<uint8_t, 4096> ipcBuffer = {};
SimpleRingBuffer ipcRingBuf;
DynamicFIFO<size_t> ipcQueue;
ScexDleParser dleParser;
static void foundDlePacketHandler(const DleParser::Context &ctx);
void handleFoundDlePacket(uint8_t *packet, size_t len);
ReturnValue_t tryDleParsing();
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
// DeviceCommunicationIF implementation
ReturnValue_t initializeInterface(CookieIF *cookie) override;
ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) override;
ReturnValue_t getSendSuccess(CookieIF *cookie) override;
ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) override;
ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) override;
};

View File

@ -0,0 +1,220 @@
#include "SusPolling.h"
#include <fsfw/tasks/SemaphoreFactory.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <fsfw_hal/linux/spi/SpiCookie.h>
#include <mission/controller/acs/AcsParameters.h>
#include <mission/devices/max1227.h>
#include <unistd.h>
#include "mission/devices/devicedefinitions/susMax1227Helpers.h"
using namespace returnvalue;
SusPolling::SusPolling(object_id_t objectId, SpiComIF& spiComIF, GpioIF& gpioIF)
: SystemObject(objectId), spiComIF(spiComIF), gpioIF(gpioIF) {
semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
semaphore->acquire();
ipcLock = MutexFactory::instance()->createMutex();
}
ReturnValue_t SusPolling::performOperation(uint8_t operationCode) {
while (true) {
ipcLock->lockMutex();
state = InternalState::IDLE;
ipcLock->unlockMutex();
semaphore->acquire();
// Give SUS handlers a chance to submit all requests.
TaskFactory::delayTask(2);
{
// Takes 4-5 ms in debug mode.
// Stopwatch watch;
handleSusPolling();
}
// Protection against tardy tasks unlocking the thread again immediately.
TaskFactory::delayTask(20);
}
return OK;
}
ReturnValue_t SusPolling::initialize() { return OK; }
ReturnValue_t SusPolling::initializeInterface(CookieIF* cookie) {
auto* spiCookie = dynamic_cast<SpiCookie*>(cookie);
if (spiCookie == nullptr) {
return FAILED;
}
int susIdx = addressToIndex(spiCookie->getSpiAddress());
if (susIdx < 0) {
return FAILED;
}
susDevs[susIdx].cookie = spiCookie;
return spiComIF.initializeInterface(cookie);
}
ReturnValue_t SusPolling::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) {
auto* spiCookie = dynamic_cast<SpiCookie*>(cookie);
if (spiCookie == nullptr) {
return FAILED;
}
int susIdx = addressToIndex(spiCookie->getSpiAddress());
if (susIdx < 0) {
return FAILED;
}
if (sendLen != sizeof(acs::SusRequest)) {
return FAILED;
}
const auto* susReq = reinterpret_cast<const acs::SusRequest*>(sendData);
MutexGuard mg(ipcLock);
if (susDevs[susIdx].mode != susReq->mode) {
if (susReq->mode == acs::SimpleSensorMode::NORMAL) {
susDevs[susIdx].performStartup = true;
} else {
susDevs[susIdx].ownReply.cfgWasSet = false;
susDevs[susIdx].ownReply.dataWasSet = false;
}
susDevs[susIdx].mode = susReq->mode;
}
if (state == InternalState::IDLE) {
state = InternalState::BUSY;
semaphore->release();
}
return OK;
}
ReturnValue_t SusPolling::getSendSuccess(CookieIF* cookie) { return OK; }
ReturnValue_t SusPolling::requestReceiveMessage(CookieIF* cookie, size_t requestLen) { return OK; }
ReturnValue_t SusPolling::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
auto* spiCookie = dynamic_cast<SpiCookie*>(cookie);
if (spiCookie == nullptr) {
return FAILED;
}
int susIdx = addressToIndex(spiCookie->getSpiAddress());
if (susIdx < 0) {
return FAILED;
}
MutexGuard mg(ipcLock);
std::memcpy(&susDevs[susIdx].readerReply, &susDevs[susIdx].ownReply, sizeof(acs::SusReply));
*buffer = reinterpret_cast<uint8_t*>(&susDevs[susIdx].readerReply);
*size = sizeof(acs::SusReply);
return OK;
}
ReturnValue_t SusPolling::handleSusPolling() {
ReturnValue_t result;
acs::SimpleSensorMode modes[12];
bool performStartups[12]{};
bool cfgsWereSet[12]{};
uint8_t idx = 0;
{
MutexGuard mg(ipcLock);
for (idx = 0; idx < 12; idx++) {
modes[idx] = susDevs[idx].mode;
performStartups[idx] = susDevs[idx].performStartup;
}
}
for (idx = 0; idx < 12; idx++) {
if (modes[idx] == acs::SimpleSensorMode::NORMAL) {
if (performStartups[idx]) {
// Startup handling.
cmdBuf[0] = susMax1227::SETUP_INT_CLOKED;
result = spiComIF.sendMessage(susDevs[idx].cookie, cmdBuf.data(), 1);
if (result != OK) {
susDevs[idx].replyResult = result;
continue;
}
MutexGuard mg(ipcLock);
susDevs[idx].ownReply.cfgWasSet = true;
cfgsWereSet[idx] = true;
susDevs[idx].performStartup = true;
}
}
}
for (idx = 0; idx < 12; idx++) {
if (modes[idx] == acs::SimpleSensorMode::NORMAL and cfgsWereSet[idx]) {
// Regular sensor polling.
cmdBuf[0] = max1227::buildResetByte(true);
cmdBuf[1] = susMax1227::CONVERSION;
result = spiComIF.sendMessage(susDevs[idx].cookie, cmdBuf.data(), 2);
if (result != OK) {
susDevs[idx].replyResult = result;
continue;
}
}
}
// Internal conversion time is 3.5 us
usleep(4);
for (idx = 0; idx < 12; idx++) {
if (modes[idx] == acs::SimpleSensorMode::NORMAL and cfgsWereSet[idx]) {
std::memset(cmdBuf.data(), 0, susMax1227::SIZE_READ_INT_CONVERSIONS);
result = spiComIF.sendMessage(susDevs[idx].cookie, cmdBuf.data(),
susMax1227::SIZE_READ_INT_CONVERSIONS);
if (result != OK) {
susDevs[idx].replyResult = result;
continue;
}
result = spiComIF.readReceivedMessage(susDevs[idx].cookie, &rawReply, &dummy);
if (result != OK) {
susDevs[idx].replyResult = result;
continue;
}
MutexGuard mg(ipcLock);
susDevs[idx].ownReply.tempRaw = ((rawReply[0] & 0x0f) << 8) | rawReply[1];
for (unsigned chIdx = 0; chIdx < 6; chIdx++) {
susDevs[idx].ownReply.channelsRaw[chIdx] =
(rawReply[chIdx * 2 + 2] << 8) | rawReply[chIdx * 2 + 3];
}
susDevs[idx].ownReply.dataWasSet = true;
}
}
return OK;
}
int SusPolling::addressToIndex(address_t addr) {
switch (addr) {
case (addresses::SUS_0):
return 0;
break;
case (addresses::SUS_1):
return 1;
break;
case (addresses::SUS_2):
return 2;
break;
case (addresses::SUS_3):
return 3;
break;
case (addresses::SUS_4):
return 4;
break;
case (addresses::SUS_5):
return 5;
break;
case (addresses::SUS_6):
return 6;
break;
case (addresses::SUS_7):
return 7;
break;
case (addresses::SUS_8):
return 8;
break;
case (addresses::SUS_9):
return 9;
break;
case (addresses::SUS_10):
return 10;
break;
case (addresses::SUS_11):
return 11;
break;
default: {
return -1;
}
}
}

View File

@ -0,0 +1,52 @@
#ifndef LINUX_DEVICES_SUSPOLLING_H_
#define LINUX_DEVICES_SUSPOLLING_H_
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/tasks/SemaphoreIF.h>
#include <fsfw_hal/linux/spi/SpiComIF.h>
#include "devices/addresses.h"
#include "mission/devices/devicedefinitions/acsPolling.h"
class SusPolling : public SystemObject, public ExecutableObjectIF, public DeviceCommunicationIF {
public:
SusPolling(object_id_t objectId, SpiComIF& spiComIF, GpioIF& gpioIF);
ReturnValue_t performOperation(uint8_t operationCode) override;
ReturnValue_t initialize() override;
private:
enum class InternalState { IDLE, BUSY } state = InternalState::IDLE;
struct SusDev {
SpiCookie* cookie = nullptr;
bool performStartup = false;
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
ReturnValue_t replyResult = returnvalue::OK;
acs::SusReply ownReply{};
acs::SusReply readerReply{};
};
MutexIF* ipcLock;
SemaphoreIF* semaphore;
uint8_t* rawReply = nullptr;
size_t dummy = 0;
SpiComIF& spiComIF;
GpioIF& gpioIF;
std::array<SusDev, 12> susDevs;
std::array<uint8_t, 32> cmdBuf;
ReturnValue_t initializeInterface(CookieIF* cookie) override;
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
ReturnValue_t getSendSuccess(CookieIF* cookie) override;
ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override;
ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override;
ReturnValue_t handleSusPolling();
static int addressToIndex(address_t addr);
};
#endif /* LINUX_DEVICES_SUSPOLLING_H_ */

View File

@ -1,7 +1,8 @@
#ifndef MPSOC_RETURN_VALUES_IF_H_
#define MPSOC_RETURN_VALUES_IF_H_
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "eive/resultClassIds.h"
#include "fsfw/returnvalues/returnvalue.h"
class MPSoCReturnValuesIF {
public:

View File

@ -6,7 +6,7 @@
#include "eive/definitions.h"
#include "fsfw/globalfunctions/CRC.h"
#include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/tmtcpacket/SpacePacket.h"
#include "mission/devices/devicedefinitions/SpBase.h"
namespace mpsoc {
@ -73,6 +73,8 @@ static const char NULL_TERMINATOR = '\0';
static const uint8_t MIN_SPACE_PACKET_LENGTH = 7;
static const uint8_t SPACE_PACKET_HEADER_SIZE = 6;
static constexpr size_t CRC_SIZE = 2;
/**
* The size of payload data which will be forwarded to the requesting object. e.g. PUS Service
* 8.
@ -88,8 +90,14 @@ static const size_t MAX_FILENAME_SIZE = 256;
static const uint16_t LENGTH_TC_MEM_WRITE = 12;
static const uint16_t LENGTH_TC_MEM_READ = 8;
static const size_t MAX_REPLY_SIZE = SpacePacket::PACKET_MAX_SIZE * 3;
static const size_t MAX_COMMAND_SIZE = SpacePacket::PACKET_MAX_SIZE;
/**
* Maximum SP packet size as specified in the TAS Supversior ICD.
* https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_TAS-ILH-IRS/ICD-PLOC/TAS&fileid=942896
* at sheet README
*/
static constexpr size_t SP_MAX_SIZE = 1024;
static const size_t MAX_REPLY_SIZE = SP_MAX_SIZE * 3;
static const size_t MAX_COMMAND_SIZE = SP_MAX_SIZE;
static const size_t MAX_DATA_SIZE = 1016;
/**
@ -100,13 +108,42 @@ static const uint16_t TC_WRITE_SEQ_EXECUTION_DELAY = 80;
// Requires approx. 2 seconds for execution. 8 => 4 seconds
static const uint16_t TC_DOWNLINK_PWR_ON_EXECUTION_DELAY = 8;
namespace status_code {
static const uint16_t UNKNOWN_APID = 0x5DD;
static const uint16_t INCORRECT_LENGTH = 0x5DE;
static const uint16_t INCORRECT_CRC = 0x5DF;
static const uint16_t INCORRECT_PKT_SEQ_CNT = 0x5E0;
static const uint16_t TC_NOT_ALLOWED_IN_MODE = 0x5E1;
static const uint16_t TC_EXEUTION_DISABLED = 0x5E2;
static const uint16_t FLASH_MOUNT_FAILED = 0x5E3;
static const uint16_t FLASH_FILE_ALREADY_CLOSED = 0x5E4;
static const uint16_t FLASH_FILE_OPEN_FAILED = 0x5E5;
static const uint16_t FLASH_FILE_ALREDY_OPEN = 0x5E6;
static const uint16_t FLASH_FILE_NOT_OPEN = 0x5E7;
static const uint16_t FLASH_UNMOUNT_FAILED = 0x5E8;
static const uint16_t HEAP_ALLOCATION_FAILED = 0x5E9;
static const uint16_t INVALID_PARAMETER = 0x5EA;
static const uint16_t NOT_INITIALIZED = 0x5EB;
static const uint16_t REBOOT_IMMINENT = 0x5EC;
static const uint16_t CORRUPT_DATA = 0x5ED;
static const uint16_t FLASH_CORRECTABLE_MISMATCH = 0x5EE;
static const uint16_t FLASH_UNCORRECTABLE_MISMATCH = 0x5EF;
static const uint16_t RESERVED_0 = 0x5F0;
static const uint16_t RESERVED_1 = 0x5F1;
static const uint16_t RESERVED_2 = 0x5F2;
static const uint16_t RESERVED_3 = 0x5F3;
static const uint16_t RESERVED_4 = 0x5F4;
} // namespace status_code
/**
* @brief Abstract base class for TC space packet of MPSoC.
*/
class TcBase : public SpacePacket, public MPSoCReturnValuesIF {
class TcBase : public ploc::SpTcBase, public MPSoCReturnValuesIF {
public:
virtual ~TcBase() = default;
// Initial length field of space packet. Will always be updated when packet is created.
static const uint16_t INIT_LENGTH = 1;
static const uint16_t INIT_LENGTH = 2;
/**
* @brief Constructor
@ -114,8 +151,12 @@ class TcBase : public SpacePacket, public MPSoCReturnValuesIF {
* @param sequenceCount Sequence count of space packet which will be incremented with each
* sent and received packets.
*/
TcBase(uint16_t apid, uint16_t sequenceCount)
: SpacePacket(INIT_LENGTH, true, apid, sequenceCount) {}
TcBase(ploc::SpTcParams params, uint16_t apid, uint16_t sequenceCount)
: ploc::SpTcBase(params, apid, 0, sequenceCount) {
spParams.setFullPayloadLen(INIT_LENGTH);
}
ReturnValue_t buildPacket() { return buildPacket(nullptr, 0); }
/**
* @brief Function to initialize the space packet
@ -123,19 +164,24 @@ class TcBase : public SpacePacket, public MPSoCReturnValuesIF {
* @param commandData Pointer to command specific data
* @param commandDataLen Length of command data
*
* @return RETURN_OK if packet creation was successful, otherwise error return value
* @return returnvalue::OK if packet creation was successful, otherwise error return value
*/
virtual ReturnValue_t createPacket(const uint8_t* commandData, size_t commandDataLen) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
result = initPacket(commandData, commandDataLen);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
ReturnValue_t buildPacket(const uint8_t* commandData, size_t commandDataLen) {
payloadStart = spParams.buf + ccsds::HEADER_LEN;
ReturnValue_t res;
if (commandData != nullptr and commandDataLen > 0) {
res = initPacket(commandData, commandDataLen);
if (res != returnvalue::OK) {
return res;
}
}
result = addCrc();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
updateSpFields();
res = checkSizeAndSerializeHeader();
if (res != returnvalue::OK) {
return res;
}
return result;
return calcAndSetCrc();
}
protected:
@ -146,46 +192,7 @@ class TcBase : public SpacePacket, public MPSoCReturnValuesIF {
* @param commandDataLen Length of received command data
*/
virtual ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
return HasReturnvaluesIF::RETURN_OK;
}
/**
* @brief Calculates and adds the CRC
*/
ReturnValue_t addCrc() {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
size_t serializedSize = 0;
uint32_t full_size = getFullSize();
uint16_t crc = CRC::crc16ccitt(getWholeData(), full_size - CRC_SIZE);
result = SerializeAdapter::serialize<uint16_t>(
&crc, this->localData.byteStream + full_size - CRC_SIZE, &serializedSize, sizeof(crc),
SerializeIF::Endianness::BIG);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "TcBase::addCrc: Failed to serialize crc field" << std::endl;
}
return result;
}
};
/**
* @brief Class for handling tm replies of the PLOC MPSoC.
*/
class TmPacket : public SpacePacket, public MPSoCReturnValuesIF {
public:
/**
* @brief Constructor creates idle packet and sets length field to maximum allowed size.
*/
TmPacket() : SpacePacket(PACKET_MAX_SIZE) {}
ReturnValue_t checkCrc() {
uint8_t* crcPtr = this->getPacketData() + this->getPacketDataLength() - 1;
uint16_t receivedCrc = *(crcPtr) << 8 | *(crcPtr + 1);
uint16_t recalculatedCrc =
CRC::crc16ccitt(this->localData.byteStream, this->getFullSize() - CRC_SIZE);
if (recalculatedCrc != receivedCrc) {
return CRC_FAILURE;
}
return HasReturnvaluesIF::RETURN_OK;
return returnvalue::OK;
}
};
@ -197,27 +204,27 @@ class TcMemRead : public TcBase {
/**
* @brief Constructor
*/
TcMemRead(uint16_t sequenceCount) : TcBase(apid::TC_MEM_READ, sequenceCount) {
this->setPacketDataLength(PACKET_LENGTH);
TcMemRead(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_MEM_READ, sequenceCount) {
spParams.setFullPayloadLen(COMMAND_LENGTH + CRC_SIZE);
}
uint16_t getMemLen() const { return memLen; }
protected:
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override {
ReturnValue_t result = returnvalue::OK;
result = lengthCheck(commandDataLen);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
std::memcpy(this->localData.fields.buffer, commandData, MEM_ADDRESS_SIZE);
std::memcpy(this->localData.fields.buffer + MEM_ADDRESS_SIZE, commandData + MEM_ADDRESS_SIZE,
MEM_LEN_SIZE);
std::memcpy(payloadStart, commandData, MEM_ADDRESS_SIZE);
std::memcpy(payloadStart + MEM_ADDRESS_SIZE, commandData + MEM_ADDRESS_SIZE, MEM_LEN_SIZE);
size_t size = sizeof(memLen);
const uint8_t* memLenPtr = commandData + MEM_ADDRESS_SIZE;
result =
SerializeAdapter::deSerialize(&memLen, &memLenPtr, &size, SerializeIF::Endianness::BIG);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
return result;
@ -232,10 +239,10 @@ class TcMemRead : public TcBase {
uint16_t memLen = 0;
ReturnValue_t lengthCheck(size_t commandDataLen) {
if (commandDataLen != COMMAND_LENGTH) {
if (commandDataLen != COMMAND_LENGTH or checkPayloadLen() != returnvalue::OK) {
return INVALID_LENGTH;
}
return HasReturnvaluesIF::RETURN_OK;
return returnvalue::OK;
}
};
@ -248,43 +255,56 @@ class TcMemWrite : public TcBase {
/**
* @brief Constructor
*/
TcMemWrite(uint16_t sequenceCount) : TcBase(apid::TC_MEM_WRITE, sequenceCount) {}
TcMemWrite(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_MEM_WRITE, sequenceCount) {}
protected:
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override {
ReturnValue_t result = returnvalue::OK;
result = lengthCheck(commandDataLen);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
std::memcpy(this->localData.fields.buffer, commandData, commandDataLen);
uint16_t memLen =
*(commandData + MEM_ADDRESS_SIZE) << 8 | *(commandData + MEM_ADDRESS_SIZE + 1);
this->setPacketDataLength(memLen * 4 + FIX_LENGTH - 1);
spParams.setFullPayloadLen(MIN_FIXED_PAYLOAD_LENGTH + memLen * 4 + CRC_SIZE);
result = checkPayloadLen();
if (result != returnvalue::OK) {
return result;
}
std::memcpy(payloadStart, commandData, commandDataLen);
return result;
}
private:
// Min length consists of 4 byte address, 2 byte mem length field, 4 byte data (1 word)
static const size_t MIN_COMMAND_DATA_LENGTH = 10;
// 4 byte address, 2 byte mem length field
static const size_t MEM_ADDRESS_SIZE = 4;
static const size_t FIX_LENGTH = 8;
static const size_t MIN_FIXED_PAYLOAD_LENGTH = MEM_ADDRESS_SIZE + 2;
// Min length consists of 4 byte address, 2 byte mem length field, 4 byte data (1 word)
static const size_t MIN_COMMAND_DATA_LENGTH = MIN_FIXED_PAYLOAD_LENGTH + 4;
ReturnValue_t lengthCheck(size_t commandDataLen) {
if (commandDataLen < MIN_COMMAND_DATA_LENGTH) {
sif::warning << "TcMemWrite: Command has invalid length " << commandDataLen << std::endl;
sif::warning << "TcMemWrite: Length " << commandDataLen << " smaller than minimum "
<< MIN_COMMAND_DATA_LENGTH << std::endl;
return INVALID_LENGTH;
}
return HasReturnvaluesIF::RETURN_OK;
if (commandDataLen + CRC_SIZE > spParams.maxSize) {
sif::warning << "TcMemWrite: Length " << commandDataLen << " larger than allowed "
<< spParams.maxSize - CRC_SIZE << std::endl;
return INVALID_LENGTH;
}
return returnvalue::OK;
}
};
/**
* @brief Class to help creation of flash fopen command.
*/
class FlashFopen : public TcBase {
class FlashFopen : public ploc::SpTcBase {
public:
FlashFopen(uint16_t sequenceCount) : TcBase(apid::TC_FLASHFOPEN, sequenceCount) {}
FlashFopen(ploc::SpTcParams params, uint16_t sequenceCount)
: ploc::SpTcBase(params, apid::TC_FLASHFOPEN, sequenceCount) {}
static const char APPEND = 'a';
static const char WRITE = 'w';
@ -292,19 +312,17 @@ class FlashFopen : public TcBase {
ReturnValue_t createPacket(std::string filename, char accessMode_) {
accessMode = accessMode_;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
size_t nameSize = filename.size();
std::memcpy(this->getPacketData(), filename.c_str(), nameSize);
*(this->getPacketData() + nameSize) = NULL_TERMINATOR;
std::memcpy(this->getPacketData() + nameSize + sizeof(NULL_TERMINATOR), &accessMode,
sizeof(accessMode));
this->setPacketDataLength(nameSize + sizeof(NULL_TERMINATOR) + sizeof(accessMode) + CRC_SIZE -
1);
result = addCrc();
if (result != HasReturnvaluesIF::RETURN_OK) {
spParams.setFullPayloadLen(nameSize + sizeof(NULL_TERMINATOR) + sizeof(accessMode) + CRC_SIZE);
ReturnValue_t result = checkPayloadLen();
if (result != returnvalue::OK) {
return result;
}
return result;
std::memcpy(payloadStart, filename.c_str(), nameSize);
*(spParams.buf + nameSize) = NULL_TERMINATOR;
std::memcpy(payloadStart + nameSize + sizeof(NULL_TERMINATOR), &accessMode, sizeof(accessMode));
updateSpFields();
return calcAndSetCrc();
}
private:
@ -314,52 +332,57 @@ class FlashFopen : public TcBase {
/**
* @brief Class to help creation of flash fclose command.
*/
class FlashFclose : public TcBase {
class FlashFclose : public ploc::SpTcBase {
public:
FlashFclose(uint16_t sequenceCount) : TcBase(apid::TC_FLASHFCLOSE, sequenceCount) {}
FlashFclose(ploc::SpTcParams params, uint16_t sequenceCount)
: ploc::SpTcBase(params, apid::TC_FLASHFCLOSE, sequenceCount) {}
ReturnValue_t createPacket(std::string filename) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
size_t nameSize = filename.size();
std::memcpy(this->getPacketData(), filename.c_str(), nameSize);
*(this->getPacketData() + nameSize) = NULL_TERMINATOR;
this->setPacketDataLength(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE - 1);
result = addCrc();
if (result != HasReturnvaluesIF::RETURN_OK) {
spParams.setFullPayloadLen(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE);
ReturnValue_t result = checkPayloadLen();
if (result != returnvalue::OK) {
return result;
}
return result;
std::memcpy(payloadStart, filename.c_str(), nameSize);
*(payloadStart + nameSize) = NULL_TERMINATOR;
return calcAndSetCrc();
}
};
/**
* @brief Class to build flash write space packet.
*/
class TcFlashWrite : public TcBase {
class TcFlashWrite : public ploc::SpTcBase {
public:
TcFlashWrite(uint16_t sequenceCount) : TcBase(apid::TC_FLASHWRITE, sequenceCount) {}
TcFlashWrite(ploc::SpTcParams params, uint16_t sequenceCount)
: ploc::SpTcBase(params, apid::TC_FLASHWRITE, sequenceCount) {}
ReturnValue_t createPacket(const uint8_t* writeData, uint32_t writeLen_) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
ReturnValue_t buildPacket(const uint8_t* writeData, uint32_t writeLen_) {
ReturnValue_t result = returnvalue::OK;
writeLen = writeLen_;
if (writeLen > MAX_DATA_SIZE) {
sif::debug << "FlashWrite::createPacket: Command data too big" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
return returnvalue::FAILED;
}
size_t serializedSize = 0;
result =
SerializeAdapter::serialize<uint32_t>(&writeLen, this->getPacketData(), &serializedSize,
sizeof(writeLen), SerializeIF::Endianness::BIG);
if (result != HasReturnvaluesIF::RETURN_OK) {
spParams.setFullPayloadLen(static_cast<uint16_t>(writeLen) + 4 + CRC_SIZE);
result = checkPayloadLen();
if (result != returnvalue::OK) {
return result;
}
std::memcpy(this->getPacketData() + sizeof(writeLen), writeData, writeLen);
this->setPacketDataLength(static_cast<uint16_t>(writeLen + CRC_SIZE - 1));
result = addCrc();
if (result != HasReturnvaluesIF::RETURN_OK) {
size_t serializedSize = ccsds::HEADER_LEN;
result = SerializeAdapter::serialize(&writeLen, payloadStart, &serializedSize, spParams.maxSize,
SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {
return result;
}
return HasReturnvaluesIF::RETURN_OK;
std::memcpy(payloadStart + sizeof(writeLen), writeData, writeLen);
updateSpFields();
auto res = checkSizeAndSerializeHeader();
if (res != returnvalue::OK) {
return res;
}
return calcAndSetCrc();
}
private:
@ -369,21 +392,27 @@ class TcFlashWrite : public TcBase {
/**
* @brief Class to help creation of flash delete command.
*/
class TcFlashDelete : public TcBase {
class TcFlashDelete : public ploc::SpTcBase {
public:
TcFlashDelete(uint16_t sequenceCount) : TcBase(apid::TC_FLASHDELETE, sequenceCount) {}
TcFlashDelete(ploc::SpTcParams params, uint16_t sequenceCount)
: ploc::SpTcBase(params, apid::TC_FLASHDELETE, sequenceCount) {}
ReturnValue_t createPacket(std::string filename) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
ReturnValue_t buildPacket(std::string filename) {
size_t nameSize = filename.size();
std::memcpy(this->getPacketData(), filename.c_str(), nameSize);
*(this->getPacketData() + nameSize) = NULL_TERMINATOR;
this->setPacketDataLength(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE - 1);
result = addCrc();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
spParams.setFullPayloadLen(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE);
auto res = checkPayloadLen();
if (res != returnvalue::OK) {
return res;
}
return result;
std::memcpy(payloadStart, filename.c_str(), nameSize);
*(payloadStart + nameSize) = NULL_TERMINATOR;
updateSpFields();
res = checkSizeAndSerializeHeader();
if (res != returnvalue::OK) {
return res;
}
return calcAndSetCrc();
}
};
@ -392,17 +421,8 @@ class TcFlashDelete : public TcBase {
*/
class TcReplayStop : public TcBase {
public:
TcReplayStop(uint16_t sequenceCount) : TcBase(apid::TC_REPLAY_STOP, sequenceCount) {}
ReturnValue_t createPacket() {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
result = addCrc();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
this->setPacketDataLength(static_cast<uint16_t>(CRC_SIZE - 1));
return HasReturnvaluesIF::RETURN_OK;
}
TcReplayStop(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_REPLAY_STOP, sequenceCount) {}
};
/**
@ -413,21 +433,22 @@ class TcReplayStart : public TcBase {
/**
* @brief Constructor
*/
TcReplayStart(uint16_t sequenceCount) : TcBase(apid::TC_REPLAY_START, sequenceCount) {}
TcReplayStart(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_REPLAY_START, sequenceCount) {}
protected:
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override {
ReturnValue_t result = returnvalue::OK;
spParams.setFullPayloadLen(commandDataLen + CRC_SIZE);
result = lengthCheck(commandDataLen);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = checkData(*commandData);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
std::memcpy(this->localData.fields.buffer, commandData, commandDataLen);
this->setPacketDataLength(commandDataLen + CRC_SIZE - 1);
std::memcpy(payloadStart, commandData, commandDataLen);
return result;
}
@ -437,11 +458,11 @@ class TcReplayStart : public TcBase {
static const uint8_t ONCE = 1;
ReturnValue_t lengthCheck(size_t commandDataLen) {
if (commandDataLen != COMMAND_DATA_LENGTH) {
if (commandDataLen != COMMAND_DATA_LENGTH or checkPayloadLen() != returnvalue::OK) {
sif::warning << "TcReplayStart: Command has invalid length " << commandDataLen << std::endl;
return INVALID_LENGTH;
}
return HasReturnvaluesIF::RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t checkData(uint8_t replay) {
@ -449,7 +470,7 @@ class TcReplayStart : public TcBase {
sif::warning << "TcReplayStart::checkData: Invalid replay value" << std::endl;
return INVALID_PARAMETER;
}
return HasReturnvaluesIF::RETURN_OK;
return returnvalue::OK;
}
};
@ -461,27 +482,31 @@ class TcDownlinkPwrOn : public TcBase {
/**
* @brief Constructor
*/
TcDownlinkPwrOn(uint16_t sequenceCount) : TcBase(apid::TC_DOWNLINK_PWR_ON, sequenceCount) {}
TcDownlinkPwrOn(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_DOWNLINK_PWR_ON, sequenceCount) {}
protected:
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override {
ReturnValue_t result = returnvalue::OK;
result = lengthCheck(commandDataLen);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = modeCheck(*commandData);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = laneRateCheck(*(commandData + 1));
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
std::memcpy(this->localData.fields.buffer, commandData, commandDataLen);
std::memcpy(this->localData.fields.buffer + commandDataLen, &MAX_AMPLITUDE,
sizeof(MAX_AMPLITUDE));
this->setPacketDataLength(commandDataLen + sizeof(MAX_AMPLITUDE) + CRC_SIZE - 1);
spParams.setFullPayloadLen(commandDataLen + sizeof(MAX_AMPLITUDE) + CRC_SIZE);
result = checkPayloadLen();
if (result != returnvalue::OK) {
return result;
}
std::memcpy(payloadStart, commandData, commandDataLen);
std::memcpy(payloadStart + commandDataLen, &MAX_AMPLITUDE, sizeof(MAX_AMPLITUDE));
return result;
}
@ -503,7 +528,7 @@ class TcDownlinkPwrOn : public TcBase {
sif::warning << "TcDownlinkPwrOn: Command has invalid length " << commandDataLen << std::endl;
return INVALID_LENGTH;
}
return HasReturnvaluesIF::RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t modeCheck(uint8_t mode) {
@ -511,7 +536,7 @@ class TcDownlinkPwrOn : public TcBase {
sif::warning << "TcDwonlinkPwrOn::modeCheck: Invalid JESD mode" << std::endl;
return INVALID_MODE;
}
return HasReturnvaluesIF::RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t laneRateCheck(uint8_t laneRate) {
@ -519,7 +544,7 @@ class TcDownlinkPwrOn : public TcBase {
sif::warning << "TcReplayStart::laneRateCheck: Invalid lane rate" << std::endl;
return INVALID_LANE_RATE;
}
return HasReturnvaluesIF::RETURN_OK;
return returnvalue::OK;
}
};
@ -528,17 +553,8 @@ class TcDownlinkPwrOn : public TcBase {
*/
class TcDownlinkPwrOff : public TcBase {
public:
TcDownlinkPwrOff(uint16_t sequenceCount) : TcBase(apid::TC_DOWNLINK_PWR_OFF, sequenceCount) {}
ReturnValue_t createPacket() {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
result = addCrc();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
this->setPacketDataLength(static_cast<uint16_t>(CRC_SIZE - 1));
return HasReturnvaluesIF::RETURN_OK;
}
TcDownlinkPwrOff(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_DOWNLINK_PWR_OFF, sequenceCount) {}
};
/**
@ -549,19 +565,19 @@ class TcReplayWriteSeq : public TcBase {
/**
* @brief Constructor
*/
TcReplayWriteSeq(uint16_t sequenceCount)
: TcBase(apid::TC_REPLAY_WRITE_SEQUENCE, sequenceCount) {}
TcReplayWriteSeq(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_REPLAY_WRITE_SEQUENCE, sequenceCount) {}
protected:
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override {
ReturnValue_t result = returnvalue::OK;
spParams.setFullPayloadLen(commandDataLen + sizeof(NULL_TERMINATOR) + CRC_SIZE);
result = lengthCheck(commandDataLen);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
std::memcpy(this->localData.fields.buffer, commandData, commandDataLen);
*(this->localData.fields.buffer + commandDataLen) = NULL_TERMINATOR;
this->setPacketDataLength(commandDataLen + sizeof(NULL_TERMINATOR) + CRC_SIZE - 1);
std::memcpy(payloadStart, commandData, commandDataLen);
*(payloadStart + commandDataLen) = NULL_TERMINATOR;
return result;
}
@ -569,12 +585,13 @@ class TcReplayWriteSeq : public TcBase {
static const size_t USE_DECODING_LENGTH = 1;
ReturnValue_t lengthCheck(size_t commandDataLen) {
if (commandDataLen > USE_DECODING_LENGTH + MAX_FILENAME_SIZE) {
if (commandDataLen > USE_DECODING_LENGTH + MAX_FILENAME_SIZE or
checkPayloadLen() != returnvalue::OK) {
sif::warning << "TcReplayWriteSeq: Command has invalid length " << commandDataLen
<< std::endl;
return INVALID_LENGTH;
}
return HasReturnvaluesIF::RETURN_OK;
return returnvalue::OK;
}
};
@ -598,7 +615,7 @@ class FlashWritePusCmd : public MPSoCReturnValuesIF {
if (mpsocFile.size() > MAX_FILENAME_SIZE) {
return MPSOC_FILENAME_TOO_LONG;
}
return HasReturnvaluesIF::RETURN_OK;
return returnvalue::OK;
}
std::string getObcFile() { return obcFile; }
@ -616,17 +633,8 @@ class FlashWritePusCmd : public MPSoCReturnValuesIF {
*/
class TcModeReplay : public TcBase {
public:
TcModeReplay(uint16_t sequenceCount) : TcBase(apid::TC_MODE_REPLAY, sequenceCount) {}
ReturnValue_t createPacket() {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
result = addCrc();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
this->setPacketDataLength(static_cast<uint16_t>(CRC_SIZE - 1));
return HasReturnvaluesIF::RETURN_OK;
}
TcModeReplay(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_MODE_REPLAY, sequenceCount) {}
};
/**
@ -634,33 +642,34 @@ class TcModeReplay : public TcBase {
*/
class TcModeIdle : public TcBase {
public:
TcModeIdle(uint16_t sequenceCount) : TcBase(apid::TC_MODE_IDLE, sequenceCount) {}
ReturnValue_t createPacket() {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
result = addCrc();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
this->setPacketDataLength(static_cast<uint16_t>(CRC_SIZE - 1));
return HasReturnvaluesIF::RETURN_OK;
}
TcModeIdle(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_MODE_IDLE, sequenceCount) {}
};
class TcCamcmdSend : public TcBase {
public:
TcCamcmdSend(uint16_t sequenceCount) : TcBase(apid::TC_CAM_CMD_SEND, sequenceCount) {}
TcCamcmdSend(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_CAM_CMD_SEND, sequenceCount) {}
protected:
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override {
if (commandDataLen > MAX_DATA_LENGTH) {
return INVALID_LENGTH;
}
std::memcpy(this->getPacketData(), commandData, commandDataLen);
*(this->getPacketData() + commandDataLen) = CARRIAGE_RETURN;
uint16_t trueLength = commandDataLen + sizeof(CARRIAGE_RETURN) + CRC_SIZE;
this->setPacketDataLength(trueLength - 1);
return HasReturnvaluesIF::RETURN_OK;
uint16_t dataLen = static_cast<uint16_t>(commandDataLen + sizeof(CARRIAGE_RETURN));
spParams.setFullPayloadLen(sizeof(dataLen) + commandDataLen + sizeof(CARRIAGE_RETURN) +
CRC_SIZE);
auto res = checkPayloadLen();
if (res != returnvalue::OK) {
return res;
}
size_t size = ccsds::HEADER_LEN;
SerializeAdapter::serialize(&dataLen, payloadStart, &size, spParams.maxSize,
SerializeIF::Endianness::BIG);
std::memcpy(payloadStart + sizeof(dataLen), commandData, commandDataLen);
*(payloadStart + sizeof(dataLen) + commandDataLen) = CARRIAGE_RETURN;
return returnvalue::OK;
}
private:

File diff suppressed because it is too large Load Diff

View File

@ -821,27 +821,27 @@ class ChecksumReply {
*
*/
ChecksumReply(const uint8_t* datafield) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
ReturnValue_t result = returnvalue::OK;
region = *(datafield);
const uint8_t* addressData = datafield + ADDRESS_OFFSET;
size_t size = sizeof(address);
result = SerializeAdapter::deSerialize(&address, &addressData, &size,
SerializeIF::Endianness::LITTLE);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
sif::debug << "ChecksumReply::ChecksumReply: Failed to deserialize address" << std::endl;
}
const uint8_t* lengthData = datafield + LENGTH_OFFSET;
size = sizeof(length);
result =
SerializeAdapter::deSerialize(&length, &lengthData, &size, SerializeIF::Endianness::LITTLE);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
sif::debug << "ChecksumReply::ChecksumReply: Failed to deserialize length" << std::endl;
}
const uint8_t* checksumData = datafield + CHECKSUM_OFFSET;
size = sizeof(checksum);
result = SerializeAdapter::deSerialize(&checksum, &checksumData, &size,
SerializeIF::Endianness::LITTLE);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
sif::debug << "ChecksumReply::ChecksumReply: Failed to deserialize checksum" << std::endl;
}
}

View File

@ -1,61 +0,0 @@
#ifndef SUPV_RETURN_VALUES_IF_H_
#define SUPV_RETURN_VALUES_IF_H_
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
class SupvReturnValuesIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::SUPV_RETURN_VALUES_IF;
//! [EXPORT] : [COMMENT] Space Packet received from PLOC supervisor has invalid CRC
static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0);
//! [EXPORT] : [COMMENT] Received ACK failure reply from PLOC supervisor
static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1);
//! [EXPORT] : [COMMENT] Received execution failure reply from PLOC supervisor
static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2);
//! [EXPORT] : [COMMENT] Received space packet with invalid APID from PLOC supervisor
static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3);
//! [EXPORT] : [COMMENT] Failed to read current system time
static const ReturnValue_t GET_TIME_FAILURE = MAKE_RETURN_CODE(0xA4);
//! [EXPORT] : [COMMENT] Received command with invalid watchdog parameter. Valid watchdogs are 0
//! for PS, 1 for PL and 2 for INT
static const ReturnValue_t INVALID_WATCHDOG = MAKE_RETURN_CODE(0xA5);
//! [EXPORT] : [COMMENT] Received watchdog timeout config command with invalid timeout. Valid
//! timeouts must be in the range between 1000 and 360000 ms.
static const ReturnValue_t INVALID_WATCHDOG_TIMEOUT = MAKE_RETURN_CODE(0xA6);
//! [EXPORT] : [COMMENT] Received latchup config command with invalid latchup ID
static const ReturnValue_t INVALID_LATCHUP_ID = MAKE_RETURN_CODE(0xA7);
//! [EXPORT] : [COMMENT] Received set adc sweep period command with invalid sweep period. Must be
//! larger than 21.
static const ReturnValue_t SWEEP_PERIOD_TOO_SMALL = MAKE_RETURN_CODE(0xA8);
//! [EXPORT] : [COMMENT] Receive auto EM test command with invalid test param. Valid params are 1
//! and 2.
static const ReturnValue_t INVALID_TEST_PARAM = MAKE_RETURN_CODE(0xA9);
//! [EXPORT] : [COMMENT] Returned when scanning for MRAM dump packets failed.
static const ReturnValue_t MRAM_PACKET_PARSING_FAILURE = MAKE_RETURN_CODE(0xAA);
//! [EXPORT] : [COMMENT] Returned when the start and stop addresses of the MRAM dump or MRAM wipe
//! commands are invalid (e.g. start address bigger than stop address)
static const ReturnValue_t INVALID_MRAM_ADDRESSES = MAKE_RETURN_CODE(0xAB);
//! [EXPORT] : [COMMENT] Expect reception of an MRAM dump packet but received space packet with
//! other apid.
static const ReturnValue_t NO_MRAM_PACKET = MAKE_RETURN_CODE(0xAC);
//! [EXPORT] : [COMMENT] Path to PLOC directory on SD card does not exist
static const ReturnValue_t PATH_DOES_NOT_EXIST = MAKE_RETURN_CODE(0xAD);
//! [EXPORT] : [COMMENT] MRAM dump file does not exists. The file should actually already have
//! been created with the reception of the first dump packet.
static const ReturnValue_t MRAM_FILE_NOT_EXISTS = MAKE_RETURN_CODE(0xAE);
//! [EXPORT] : [COMMENT] Received action command has invalid length
static const ReturnValue_t INVALID_LENGTH = MAKE_RETURN_CODE(0xAF);
//! [EXPORT] : [COMMENT] Filename too long
static const ReturnValue_t FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xB0);
//! [EXPORT] : [COMMENT] Received update status report with invalid packet length field
static const ReturnValue_t UPDATE_STATUS_REPORT_INVALID_LENGTH = MAKE_RETURN_CODE(0xB1);
//! [EXPORT] : [COMMENT] Update status report does not contain expected CRC. There might be a bit
//! flip in the update memory region.
static const ReturnValue_t UPDATE_CRC_FAILURE = MAKE_RETURN_CODE(0xB2);
//! [EXPORT] : [COMMENT] Supervisor helper task ist currently executing a command (wait until
//! helper tas has finished or interrupt by sending the terminate command)
static const ReturnValue_t SUPV_HELPER_EXECUTING = MAKE_RETURN_CODE(0xB3);
};
#endif /* SUPV_RETURN_VALUES_IF_H_ */

View File

@ -1,7 +1,4 @@
target_sources(${OBSW_NAME} PRIVATE
PlocSupervisorHandler.cpp
PlocMemoryDumper.cpp
PlocMPSoCHandler.cpp
PlocMPSoCHelper.cpp
PlocSupvHelper.cpp
)
target_sources(
${OBSW_NAME}
PRIVATE PlocSupervisorHandler.cpp PlocMemoryDumper.cpp PlocMPSoCHandler.cpp
PlocMPSoCHelper.cpp PlocSupvUartMan.cpp)

View File

@ -19,17 +19,19 @@ PlocMPSoCHandler::PlocMPSoCHandler(object_id_t objectId, object_id_t uartComIFid
eventQueue = QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5);
commandActionHelperQueue =
QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5);
spParams.maxSize = sizeof(commandBuffer);
spParams.buf = commandBuffer;
}
PlocMPSoCHandler::~PlocMPSoCHandler() {}
ReturnValue_t PlocMPSoCHandler::initialize() {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
result = DeviceHandlerBase::initialize();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
uartComIf = dynamic_cast<UartComIF*>(communicationInterface);
uartComIf = dynamic_cast<SerialComIF*>(communicationInterface);
if (uartComIf == nullptr) {
sif::warning << "PlocMPSoCHandler::initialize: Invalid uart com if" << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
@ -44,13 +46,13 @@ ReturnValue_t PlocMPSoCHandler::initialize() {
;
}
result = manager->registerListener(eventQueue->getId());
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = manager->subscribeToEventRange(
eventQueue->getId(), event::getEventId(PlocMPSoCHelper::MPSOC_FLASH_WRITE_FAILED),
event::getEventId(PlocMPSoCHelper::MPSOC_FLASH_WRITE_SUCCESSFUL));
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "PlocMPSoCHandler::initialize: Failed to subscribe to events from "
" ploc mpsoc helper"
@ -60,13 +62,13 @@ ReturnValue_t PlocMPSoCHandler::initialize() {
}
result = plocMPSoCHelper->setComIF(communicationInterface);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
plocMPSoCHelper->setComCookie(comCookie);
plocMPSoCHelper->setSequenceCount(&sequenceCount);
result = commandActionHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
return result;
@ -74,7 +76,7 @@ ReturnValue_t PlocMPSoCHandler::initialize() {
void PlocMPSoCHandler::performOperationHook() {
EventMessage event;
for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == RETURN_OK;
for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK;
result = eventQueue->receiveMessage(&event)) {
switch (event.getMessageId()) {
case EventMessage::EVENT_MESSAGE:
@ -88,9 +90,9 @@ void PlocMPSoCHandler::performOperationHook() {
}
CommandMessage message;
for (ReturnValue_t result = commandActionHelperQueue->receiveMessage(&message);
result == RETURN_OK; result = commandActionHelperQueue->receiveMessage(&message)) {
result == returnvalue::OK; result = commandActionHelperQueue->receiveMessage(&message)) {
result = commandActionHelper.handleReply(&message);
if (result == RETURN_OK) {
if (result == returnvalue::OK) {
continue;
}
}
@ -98,7 +100,7 @@ void PlocMPSoCHandler::performOperationHook() {
ReturnValue_t PlocMPSoCHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
switch (actionId) {
case mpsoc::SET_UART_TX_TRISTATE: {
uartIsolatorSwitch.pullLow();
@ -125,12 +127,12 @@ ReturnValue_t PlocMPSoCHandler::executeAction(ActionId_t actionId, MessageQueueI
}
mpsoc::FlashWritePusCmd flashWritePusCmd;
result = flashWritePusCmd.extractFields(data, size);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = plocMPSoCHelper->startFlashWrite(flashWritePusCmd.getObcFile(),
flashWritePusCmd.getMPSoCFile());
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
plocMPSoCHelperExecuting = true;
@ -182,12 +184,14 @@ void PlocMPSoCHandler::doShutDown() {
powerState = PowerState::SHUTDOWN;
break;
case PowerState::OFF:
sequenceCount = 0;
setMode(_MODE_POWER_DOWN);
break;
default:
break;
}
#else
sequenceCount = 0;
uartIsolatorSwitch.pullLow();
setMode(_MODE_POWER_DOWN);
powerState = PowerState::OFF;
@ -206,7 +210,8 @@ ReturnValue_t PlocMPSoCHandler::buildTransitionDeviceCommand(DeviceCommandId_t*
ReturnValue_t PlocMPSoCHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t* commandData,
size_t commandDataLen) {
ReturnValue_t result = RETURN_OK;
spParams.buf = commandBuffer;
ReturnValue_t result = returnvalue::OK;
switch (deviceCommand) {
case (mpsoc::TC_MEM_WRITE): {
result = prepareTcMemWrite(commandData, commandDataLen);
@ -259,7 +264,7 @@ ReturnValue_t PlocMPSoCHandler::buildCommandFromCommand(DeviceCommandId_t device
break;
}
if (result == RETURN_OK) {
if (result == returnvalue::OK) {
/**
* Flushing the receive buffer to make sure there are no data left from a faulty reply.
*/
@ -286,16 +291,23 @@ void PlocMPSoCHandler::fillCommandAndReplyMap() {
this->insertInReplyMap(mpsoc::ACK_REPORT, 3, nullptr, mpsoc::SIZE_ACK_REPORT);
this->insertInReplyMap(mpsoc::EXE_REPORT, 50, nullptr, mpsoc::SIZE_EXE_REPORT);
this->insertInReplyMap(mpsoc::TM_MEMORY_READ_REPORT, 2, nullptr, mpsoc::SIZE_TM_MEM_READ_REPORT);
this->insertInReplyMap(mpsoc::TM_CAM_CMD_RPT, 50, nullptr, SpacePacket::PACKET_MAX_SIZE);
this->insertInReplyMap(mpsoc::TM_CAM_CMD_RPT, 50, nullptr, mpsoc::SP_MAX_SIZE);
}
ReturnValue_t PlocMPSoCHandler::scanForReply(const uint8_t* start, size_t remainingSize,
DeviceCommandId_t* foundId, size_t* foundLen) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
SpacePacket spacePacket;
std::memcpy(spacePacket.getWholeData(), start, remainingSize);
uint16_t apid = spacePacket.getAPID();
SpacePacketReader spacePacket;
spacePacket.setReadOnlyData(start, remainingSize);
if (spacePacket.isNull()) {
return returnvalue::FAILED;
}
auto res = spacePacket.checkSize();
if (res != returnvalue::OK) {
return res;
}
uint16_t apid = spacePacket.getApid();
switch (apid) {
case (mpsoc::apid::ACK_SUCCESS):
@ -311,7 +323,7 @@ ReturnValue_t PlocMPSoCHandler::scanForReply(const uint8_t* start, size_t remain
*foundId = mpsoc::TM_MEMORY_READ_REPORT;
break;
case (mpsoc::apid::TM_CAM_CMD_RPT):
*foundLen = spacePacket.getFullSize();
*foundLen = spacePacket.getFullPacketLen();
tmCamCmdRpt.rememberSpacePacketSize = *foundLen;
*foundId = mpsoc::TM_CAM_CMD_RPT;
break;
@ -330,17 +342,18 @@ ReturnValue_t PlocMPSoCHandler::scanForReply(const uint8_t* start, size_t remain
}
}
sequenceCount++;
uint16_t recvSeqCnt = (*(start + 2) << 8 | *(start + 3)) & PACKET_SEQUENCE_COUNT_MASK;
if (recvSeqCnt != sequenceCount) {
triggerEvent(MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH, sequenceCount, recvSeqCnt);
sequenceCount = recvSeqCnt;
}
// This sequence count ping pong does not make any sense but it is how the MPSoC expects it.
sequenceCount++;
return result;
}
ReturnValue_t PlocMPSoCHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
switch (id) {
case mpsoc::ACK_REPORT: {
@ -374,7 +387,7 @@ uint32_t PlocMPSoCHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo)
ReturnValue_t PlocMPSoCHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
return HasReturnvaluesIF::RETURN_OK;
return returnvalue::OK;
}
void PlocMPSoCHandler::handleEvent(EventMessage* eventMessage) {
@ -392,31 +405,27 @@ void PlocMPSoCHandler::handleEvent(EventMessage* eventMessage) {
ReturnValue_t PlocMPSoCHandler::prepareTcMemWrite(const uint8_t* commandData,
size_t commandDataLen) {
ReturnValue_t result = RETURN_OK;
sequenceCount++;
mpsoc::TcMemWrite tcMemWrite(sequenceCount);
result = tcMemWrite.createPacket(commandData, commandDataLen);
if (result != RETURN_OK) {
sequenceCount--;
ReturnValue_t result = returnvalue::OK;
mpsoc::TcMemWrite tcMemWrite(spParams, sequenceCount);
result = tcMemWrite.buildPacket(commandData, commandDataLen);
if (result != returnvalue::OK) {
return result;
}
copyToCommandBuffer(&tcMemWrite);
return RETURN_OK;
finishTcPrep(tcMemWrite.getFullPacketLen());
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHandler::prepareTcMemRead(const uint8_t* commandData,
size_t commandDataLen) {
ReturnValue_t result = RETURN_OK;
sequenceCount++;
mpsoc::TcMemRead tcMemRead(sequenceCount);
result = tcMemRead.createPacket(commandData, commandDataLen);
if (result != RETURN_OK) {
sequenceCount--;
ReturnValue_t result = returnvalue::OK;
mpsoc::TcMemRead tcMemRead(spParams, sequenceCount);
result = tcMemRead.buildPacket(commandData, commandDataLen);
if (result != returnvalue::OK) {
return result;
}
copyToCommandBuffer(&tcMemRead);
finishTcPrep(tcMemRead.getFullPacketLen());
tmMemReadReport.rememberRequestedSize = tcMemRead.getMemLen() * 4 + TmMemReadReport::FIX_SIZE;
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHandler::prepareTcFlashDelete(const uint8_t* commandData,
@ -424,155 +433,126 @@ ReturnValue_t PlocMPSoCHandler::prepareTcFlashDelete(const uint8_t* commandData,
if (commandDataLen > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) {
return MPSoCReturnValuesIF::NAME_TOO_LONG;
}
ReturnValue_t result = RETURN_OK;
sequenceCount++;
mpsoc::TcFlashDelete tcFlashDelete(sequenceCount);
result = tcFlashDelete.createPacket(
ReturnValue_t result = returnvalue::OK;
mpsoc::TcFlashDelete tcFlashDelete(spParams, sequenceCount);
result = tcFlashDelete.buildPacket(
std::string(reinterpret_cast<const char*>(commandData), commandDataLen));
if (result != RETURN_OK) {
sequenceCount--;
if (result != returnvalue::OK) {
return result;
}
copyToCommandBuffer(&tcFlashDelete);
return RETURN_OK;
finishTcPrep(tcFlashDelete.getFullPacketLen());
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHandler::prepareTcReplayStart(const uint8_t* commandData,
size_t commandDataLen) {
ReturnValue_t result = RETURN_OK;
sequenceCount++;
mpsoc::TcReplayStart tcReplayStart(sequenceCount);
result = tcReplayStart.createPacket(commandData, commandDataLen);
if (result != RETURN_OK) {
sequenceCount--;
ReturnValue_t result = returnvalue::OK;
mpsoc::TcReplayStart tcReplayStart(spParams, sequenceCount);
result = tcReplayStart.buildPacket(commandData, commandDataLen);
if (result != returnvalue::OK) {
return result;
}
copyToCommandBuffer(&tcReplayStart);
return RETURN_OK;
finishTcPrep(tcReplayStart.getFullPacketLen());
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHandler::prepareTcReplayStop() {
ReturnValue_t result = RETURN_OK;
sequenceCount++;
mpsoc::TcReplayStop tcReplayStop(sequenceCount);
result = tcReplayStop.createPacket();
if (result != RETURN_OK) {
sequenceCount--;
ReturnValue_t result = returnvalue::OK;
mpsoc::TcReplayStop tcReplayStop(spParams, sequenceCount);
result = tcReplayStop.buildPacket();
if (result != returnvalue::OK) {
return result;
}
copyToCommandBuffer(&tcReplayStop);
return RETURN_OK;
finishTcPrep(tcReplayStop.getFullPacketLen());
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHandler::prepareTcDownlinkPwrOn(const uint8_t* commandData,
size_t commandDataLen) {
ReturnValue_t result = RETURN_OK;
sequenceCount++;
mpsoc::TcDownlinkPwrOn tcDownlinkPwrOn(sequenceCount);
result = tcDownlinkPwrOn.createPacket(commandData, commandDataLen);
if (result != RETURN_OK) {
sequenceCount--;
ReturnValue_t result = returnvalue::OK;
mpsoc::TcDownlinkPwrOn tcDownlinkPwrOn(spParams, sequenceCount);
result = tcDownlinkPwrOn.buildPacket(commandData, commandDataLen);
if (result != returnvalue::OK) {
return result;
}
copyToCommandBuffer(&tcDownlinkPwrOn);
return RETURN_OK;
finishTcPrep(tcDownlinkPwrOn.getFullPacketLen());
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHandler::prepareTcDownlinkPwrOff() {
ReturnValue_t result = RETURN_OK;
sequenceCount++;
mpsoc::TcDownlinkPwrOff tcDownlinkPwrOff(sequenceCount);
result = tcDownlinkPwrOff.createPacket();
if (result != RETURN_OK) {
sequenceCount--;
ReturnValue_t result = returnvalue::OK;
mpsoc::TcDownlinkPwrOff tcDownlinkPwrOff(spParams, sequenceCount);
result = tcDownlinkPwrOff.buildPacket();
if (result != returnvalue::OK) {
return result;
}
copyToCommandBuffer(&tcDownlinkPwrOff);
return RETURN_OK;
finishTcPrep(tcDownlinkPwrOff.getFullPacketLen());
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHandler::prepareTcReplayWriteSequence(const uint8_t* commandData,
size_t commandDataLen) {
ReturnValue_t result = RETURN_OK;
sequenceCount++;
mpsoc::TcReplayWriteSeq tcReplayWriteSeq(sequenceCount);
result = tcReplayWriteSeq.createPacket(commandData, commandDataLen);
if (result != RETURN_OK) {
sequenceCount--;
ReturnValue_t result = returnvalue::OK;
mpsoc::TcReplayWriteSeq tcReplayWriteSeq(spParams, sequenceCount);
result = tcReplayWriteSeq.buildPacket(commandData, commandDataLen);
if (result != returnvalue::OK) {
return result;
}
copyToCommandBuffer(&tcReplayWriteSeq);
return RETURN_OK;
finishTcPrep(tcReplayWriteSeq.getFullPacketLen());
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHandler::prepareTcModeReplay() {
ReturnValue_t result = RETURN_OK;
sequenceCount++;
mpsoc::TcModeReplay tcModeReplay(sequenceCount);
result = tcModeReplay.createPacket();
if (result != RETURN_OK) {
sequenceCount--;
ReturnValue_t result = returnvalue::OK;
mpsoc::TcModeReplay tcModeReplay(spParams, sequenceCount);
result = tcModeReplay.buildPacket();
if (result != returnvalue::OK) {
return result;
}
memcpy(commandBuffer, tcModeReplay.getWholeData(), tcModeReplay.getFullSize());
rawPacket = commandBuffer;
rawPacketLen = tcModeReplay.getFullSize();
nextReplyId = mpsoc::ACK_REPORT;
return RETURN_OK;
finishTcPrep(tcModeReplay.getFullPacketLen());
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHandler::prepareTcModeIdle() {
ReturnValue_t result = RETURN_OK;
sequenceCount++;
mpsoc::TcModeIdle tcModeIdle(sequenceCount);
result = tcModeIdle.createPacket();
if (result != RETURN_OK) {
sequenceCount--;
ReturnValue_t result = returnvalue::OK;
mpsoc::TcModeIdle tcModeIdle(spParams, sequenceCount);
result = tcModeIdle.buildPacket();
if (result != returnvalue::OK) {
return result;
}
memcpy(commandBuffer, tcModeIdle.getWholeData(), tcModeIdle.getFullSize());
rawPacket = commandBuffer;
rawPacketLen = tcModeIdle.getFullSize();
nextReplyId = mpsoc::ACK_REPORT;
return RETURN_OK;
finishTcPrep(tcModeIdle.getFullPacketLen());
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHandler::prepareTcCamCmdSend(const uint8_t* commandData,
size_t commandDataLen) {
ReturnValue_t result = RETURN_OK;
sequenceCount++;
mpsoc::TcCamcmdSend tcCamCmdSend(sequenceCount);
result = tcCamCmdSend.createPacket(commandData, commandDataLen);
if (result != RETURN_OK) {
sequenceCount--;
ReturnValue_t result = returnvalue::OK;
mpsoc::TcCamcmdSend tcCamCmdSend(spParams, sequenceCount);
result = tcCamCmdSend.buildPacket(commandData, commandDataLen);
if (result != returnvalue::OK) {
return result;
}
copyToCommandBuffer(&tcCamCmdSend);
finishTcPrep(tcCamCmdSend.getFullPacketLen());
nextReplyId = mpsoc::ACK_REPORT;
return RETURN_OK;
return returnvalue::OK;
}
void PlocMPSoCHandler::copyToCommandBuffer(mpsoc::TcBase* tc) {
if (tc == nullptr) {
sif::debug << "PlocMPSoCHandler::copyToCommandBuffer: Invalid TC" << std::endl;
}
memcpy(commandBuffer, tc->getWholeData(), tc->getFullSize());
rawPacket = commandBuffer;
rawPacketLen = tc->getFullSize();
void PlocMPSoCHandler::finishTcPrep(size_t packetLen) {
nextReplyId = mpsoc::ACK_REPORT;
rawPacket = commandBuffer;
rawPacketLen = packetLen;
sequenceCount++;
}
ReturnValue_t PlocMPSoCHandler::verifyPacket(const uint8_t* start, size_t foundLen) {
uint16_t receivedCrc = *(start + foundLen - 2) << 8 | *(start + foundLen - 1);
uint16_t recalculatedCrc = CRC::crc16ccitt(start, foundLen - 2);
if (receivedCrc != recalculatedCrc) {
if (CRC::crc16ccitt(start, foundLen) != 0) {
return MPSoCReturnValuesIF::CRC_FAILURE;
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHandler::handleAckReport(const uint8_t* data) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
result = verifyPacket(data, mpsoc::SIZE_ACK_REPORT);
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
@ -589,14 +569,14 @@ ReturnValue_t PlocMPSoCHandler::handleAckReport(const uint8_t* data) {
switch (apid) {
case mpsoc::apid::ACK_FAILURE: {
// TODO: Interpretation of status field in acknowledgment report
sif::debug << "PlocMPSoCHandler::handleAckReport: Received Ack failure report" << std::endl;
DeviceCommandId_t commandId = getPendingCommand();
uint16_t status = getStatus(data);
printStatus(data);
if (commandId != DeviceHandlerIF::NO_COMMAND_ID) {
triggerEvent(ACK_FAILURE, commandId, status);
}
sendFailureReport(mpsoc::ACK_REPORT, MPSoCReturnValuesIF::RECEIVED_ACK_FAILURE);
sendFailureReport(mpsoc::ACK_REPORT, status);
disableAllReplies();
nextReplyId = mpsoc::NONE;
result = IGNORE_REPLY_DATA;
@ -608,7 +588,7 @@ ReturnValue_t PlocMPSoCHandler::handleAckReport(const uint8_t* data) {
}
default: {
sif::debug << "PlocMPSoCHandler::handleAckReport: Invalid APID in Ack report" << std::endl;
result = RETURN_FAILED;
result = returnvalue::FAILED;
break;
}
}
@ -617,7 +597,7 @@ ReturnValue_t PlocMPSoCHandler::handleAckReport(const uint8_t* data) {
}
ReturnValue_t PlocMPSoCHandler::handleExecutionReport(const uint8_t* data) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
result = verifyPacket(data, mpsoc::SIZE_EXE_REPORT);
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
@ -651,7 +631,7 @@ ReturnValue_t PlocMPSoCHandler::handleExecutionReport(const uint8_t* data) {
}
default: {
sif::warning << "PlocMPSoCHandler::handleExecutionReport: Unknown APID" << std::endl;
result = RETURN_FAILED;
result = returnvalue::FAILED;
break;
}
}
@ -660,7 +640,7 @@ ReturnValue_t PlocMPSoCHandler::handleExecutionReport(const uint8_t* data) {
}
ReturnValue_t PlocMPSoCHandler::handleMemoryReadReport(const uint8_t* data) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
result = verifyPacket(data, tmMemReadReport.rememberRequestedSize);
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
sif::warning << "PlocMPSoCHandler::handleMemoryReadReport: Memory read report has invalid crc"
@ -676,31 +656,31 @@ ReturnValue_t PlocMPSoCHandler::handleMemoryReadReport(const uint8_t* data) {
}
ReturnValue_t PlocMPSoCHandler::handleCamCmdRpt(const uint8_t* data) {
ReturnValue_t result = RETURN_OK;
SpacePacket packet;
std::memcpy(packet.getWholeData(), data, tmCamCmdRpt.rememberSpacePacketSize);
ReturnValue_t result = returnvalue::OK;
result = verifyPacket(data, tmCamCmdRpt.rememberSpacePacketSize);
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
sif::warning << "PlocMPSoCHandler::handleCamCmdRpt: CRC failure" << std::endl;
}
const uint8_t* dataFieldPtr = data + mpsoc::SPACE_PACKET_HEADER_SIZE;
SpacePacketReader packetReader(data, tmCamCmdRpt.rememberSpacePacketSize);
const uint8_t* dataFieldPtr = data + mpsoc::SPACE_PACKET_HEADER_SIZE + sizeof(uint16_t);
std::string camCmdRptMsg(
reinterpret_cast<const char*>(dataFieldPtr),
tmCamCmdRpt.rememberSpacePacketSize - mpsoc::SPACE_PACKET_HEADER_SIZE - 3);
tmCamCmdRpt.rememberSpacePacketSize - mpsoc::SPACE_PACKET_HEADER_SIZE - sizeof(uint16_t) - 3);
#if OBSW_DEBUG_PLOC_MPSOC == 1
uint8_t ackValue = *(packet.getPacketData() + packet.getPacketDataLength() - 2);
uint8_t ackValue = *(packetReader.getFullData() + packetReader.getFullPacketLen() - 2);
sif::info << "PlocMPSoCHandler: CamCmdRpt message: " << camCmdRptMsg << std::endl;
sif::info << "PlocMPSoCHandler: CamCmdRpt Ack value: 0x" << std::hex
<< static_cast<unsigned int>(ackValue) << std::endl;
#endif /* OBSW_DEBUG_PLOC_MPSOC == 1 */
handleDeviceTM(packet.getPacketData(), packet.getPacketDataLength() - 1, mpsoc::TM_CAM_CMD_RPT);
handleDeviceTM(packetReader.getPacketData() + sizeof(uint16_t),
packetReader.getPacketDataLen() - 1, mpsoc::TM_CAM_CMD_RPT);
return result;
}
ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command,
uint8_t expectedReplies, bool useAlternateId,
DeviceCommandId_t alternateReplyID) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
uint8_t enabledReplies = 0;
@ -720,7 +700,7 @@ ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator
enabledReplies = 3;
result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true,
mpsoc::TM_MEMORY_READ_REPORT);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Reply with id "
<< mpsoc::TM_MEMORY_READ_REPORT << " not in replyMap" << std::endl;
return result;
@ -731,7 +711,7 @@ ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator
enabledReplies = 3;
result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true,
mpsoc::TM_CAM_CMD_RPT);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Reply with id "
<< mpsoc::TM_CAM_CMD_RPT << " not in replyMap" << std::endl;
return result;
@ -751,14 +731,14 @@ ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator
*/
result =
DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, mpsoc::ACK_REPORT);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Reply with id " << mpsoc::ACK_REPORT
<< " not in replyMap" << std::endl;
}
result =
DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, mpsoc::EXE_REPORT);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Reply with id " << mpsoc::EXE_REPORT
<< " not in replyMap" << std::endl;
}
@ -781,7 +761,7 @@ ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator
break;
}
return RETURN_OK;
return returnvalue::OK;
}
void PlocMPSoCHandler::setNextReplyId() {
@ -820,7 +800,7 @@ size_t PlocMPSoCHandler::getNextReplyLength(DeviceCommandId_t commandId) {
case mpsoc::TM_CAM_CMD_RPT:
// Read acknowledgment, camera and execution report in one go because length of camera
// report is not fixed
replyLen = SpacePacket::PACKET_MAX_SIZE;
replyLen = mpsoc::SP_MAX_SIZE;
break;
default: {
replyLen = iter->second.replyLen;
@ -838,9 +818,9 @@ size_t PlocMPSoCHandler::getNextReplyLength(DeviceCommandId_t commandId) {
ReturnValue_t PlocMPSoCHandler::doSendReadHook() {
// Prevent DHB from polling UART during commands executed by the mpsoc helper task
if (plocMPSoCHelperExecuting) {
return RETURN_FAILED;
return returnvalue::FAILED;
}
return RETURN_OK;
return returnvalue::OK;
}
MessageQueueIF* PlocMPSoCHandler::getCommandQueuePtr() { return commandActionHelperQueue; }
@ -901,7 +881,7 @@ void PlocMPSoCHandler::completionFailedReceived(ActionId_t actionId, ReturnValue
void PlocMPSoCHandler::handleDeviceTM(const uint8_t* data, size_t dataSize,
DeviceCommandId_t replyId) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
if (wiretappingMode == RAW) {
/* Data already sent in doGetRead() */
@ -920,7 +900,7 @@ void PlocMPSoCHandler::handleDeviceTM(const uint8_t* data, size_t dataSize,
}
result = actionHelper.reportData(queueId, replyId, data, dataSize);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::debug << "PlocMPSoCHandler::handleDeviceTM: Failed to report data" << std::endl;
}
}
@ -997,7 +977,7 @@ void PlocMPSoCHandler::disableExeReportReply() {
void PlocMPSoCHandler::printStatus(const uint8_t* data) {
uint16_t status = *(data + STATUS_OFFSET) << 8 | *(data + STATUS_OFFSET + 1);
sif::info << "Verification report status: 0x" << std::hex << status << std::endl;
sif::info << "Verification report status: " << getStatusString(status) << std::endl;
}
uint16_t PlocMPSoCHandler::getStatus(const uint8_t* data) {
@ -1036,3 +1016,79 @@ void PlocMPSoCHandler::handleActionCommandFailure(ActionId_t actionId) {
}
return;
}
std::string PlocMPSoCHandler::getStatusString(uint16_t status) {
switch (status) {
case (mpsoc::status_code::UNKNOWN_APID): {
return "Unknown APID";
break;
}
case (mpsoc::status_code::INCORRECT_LENGTH): {
return "Incorrect length";
break;
}
case (mpsoc::status_code::INCORRECT_CRC): {
return "Incorrect crc";
break;
}
case (mpsoc::status_code::INCORRECT_PKT_SEQ_CNT): {
return "Incorrect packet sequence count";
break;
}
case (mpsoc::status_code::TC_NOT_ALLOWED_IN_MODE): {
return "TC not allowed in this mode";
break;
}
case (mpsoc::status_code::TC_EXEUTION_DISABLED): {
return "TC execution disabled";
break;
}
case (mpsoc::status_code::FLASH_MOUNT_FAILED): {
return "Flash mount failed";
break;
}
case (mpsoc::status_code::FLASH_FILE_ALREADY_CLOSED): {
return "Flash file already closed";
break;
}
case (mpsoc::status_code::FLASH_FILE_NOT_OPEN): {
return "Flash file not open";
break;
}
case (mpsoc::status_code::FLASH_UNMOUNT_FAILED): {
return "Flash unmount failed";
break;
}
case (mpsoc::status_code::HEAP_ALLOCATION_FAILED): {
return "Heap allocation failed";
break;
}
case (mpsoc::status_code::INVALID_PARAMETER): {
return "Invalid parameter";
break;
}
case (mpsoc::status_code::NOT_INITIALIZED): {
return "Not initialized";
break;
}
case (mpsoc::status_code::REBOOT_IMMINENT): {
return "Reboot imminent";
break;
}
case (mpsoc::status_code::CORRUPT_DATA): {
return "Corrupt data";
break;
}
case (mpsoc::status_code::FLASH_CORRECTABLE_MISMATCH): {
return "Flash correctable mismatch";
break;
}
case (mpsoc::status_code::FLASH_UNCORRECTABLE_MISMATCH): {
return "Flash uncorrectable mismatch";
break;
}
default:
break;
}
return "";
}

View File

@ -8,10 +8,9 @@
#include "fsfw/action/CommandsActionsIF.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/tmtcpacket/SpacePacket.h"
#include "fsfw/tmtcservices/SourceSequenceCounter.h"
#include "fsfw_hal/linux/gpio/Gpio.h"
#include "fsfw_hal/linux/uart/UartComIF.h"
#include "fsfw_hal/linux/serial/SerialComIF.h"
#include "linux/devices/devicedefinitions/MPSoCReturnValuesIF.h"
#include "linux/devices/devicedefinitions/PlocMPSoCDefinitions.h"
#include "linux/devices/devicedefinitions/PlocSupervisorDefinitions.h"
@ -108,10 +107,11 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
MessageQueueIF* eventQueue = nullptr;
MessageQueueIF* commandActionHelperQueue = nullptr;
SourceSequenceCounter sequenceCount =
SourceSequenceCounter(SpacePacketBase::LIMIT_SEQUENCE_COUNT - 1);
SourceSequenceCounter sequenceCount = SourceSequenceCounter(0);
uint8_t commandBuffer[mpsoc::MAX_COMMAND_SIZE];
SpacePacketCreator creator;
ploc::SpTcParams spParams = ploc::SpTcParams(creator);
/**
* This variable is used to store the id of the next reply to receive. This is necessary
@ -120,7 +120,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
*/
DeviceCommandId_t nextReplyId = mpsoc::NONE;
UartComIF* uartComIf = nullptr;
SerialComIF* uartComIf = nullptr;
PlocMPSoCHelper* plocMPSoCHelper = nullptr;
Gpio uartIsolatorSwitch;
@ -145,7 +145,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
struct TelemetryBuffer {
uint16_t length = 0;
uint8_t buffer[SpacePacket::PACKET_MAX_SIZE];
uint8_t buffer[mpsoc::SP_MAX_SIZE];
};
TelemetryBuffer tmBuffer;
@ -169,10 +169,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
ReturnValue_t prepareTcReplayWriteSequence(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcCamCmdSend(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareTcModeIdle();
/**
* @brief Copies space packet into command buffer
*/
void copyToCommandBuffer(mpsoc::TcBase* tc);
void finishTcPrep(size_t packetLen);
/**
* @brief This function checks the crc of the received PLOC reply.
@ -180,7 +177,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
* @param start Pointer to the first byte of the reply.
* @param foundLen Pointer to the length of the whole packet.
*
* @return RETURN_OK if CRC is ok, otherwise CRC_FAILURE.
* @return returnvalue::OK if CRC is ok, otherwise CRC_FAILURE.
*/
ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen);
@ -189,7 +186,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
*
* @param data Pointer to the data holding the acknowledgment report.
*
* @return RETURN_OK if successful, otherwise an error code.
* @return returnvalue::OK if successful, otherwise an error code.
*/
ReturnValue_t handleAckReport(const uint8_t* data);
@ -198,7 +195,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
*
* @param data Pointer to the received data packet.
*
* @return RETURN_OK if successful, otherwise an error code.
* @return returnvalue::OK if successful, otherwise an error code.
*/
ReturnValue_t handleExecutionReport(const uint8_t* data);
@ -207,7 +204,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
*
* @param data Pointer to the data buffer holding the memory read report.
*
* @return RETURN_OK if successful, otherwise an error code.
* @return returnvalue::OK if successful, otherwise an error code.
*/
ReturnValue_t handleMemoryReadReport(const uint8_t* data);
@ -260,6 +257,8 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
uint16_t getStatus(const uint8_t* data);
void handleActionCommandFailure(ActionId_t actionId);
std::string getStatusString(uint16_t status);
};
#endif /* BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_ */

View File

@ -3,14 +3,18 @@
#include <filesystem>
#include <fstream>
#include "OBSWConfig.h"
#ifdef XIPHOS_Q7S
#include "bsp_q7s/memory/FilesystemHelper.h"
#include "bsp_q7s/fs/FilesystemHelper.h"
#endif
#include "mission/utility/Timestamp.h"
PlocMPSoCHelper::PlocMPSoCHelper(object_id_t objectId) : SystemObject(objectId) {}
using namespace ploc;
PlocMPSoCHelper::PlocMPSoCHelper(object_id_t objectId) : SystemObject(objectId) {
spParams.buf = commandBuffer;
spParams.maxSize = sizeof(commandBuffer);
}
PlocMPSoCHelper::~PlocMPSoCHelper() {}
@ -19,16 +23,19 @@ ReturnValue_t PlocMPSoCHelper::initialize() {
sdcMan = SdCardManager::instance();
if (sdcMan == nullptr) {
sif::warning << "PlocMPSoCHelper::initialize: Invalid SD Card Manager" << std::endl;
return RETURN_FAILED;
return returnvalue::FAILED;
}
#endif
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHelper::performOperation(uint8_t operationCode) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
semaphore.acquire();
while (true) {
#if OBSW_THREAD_TRACING == 1
trace::threadTrace(opCounter, "PLOC MPSOC Helper");
#endif
switch (internalState) {
case InternalState::IDLE: {
semaphore.acquire();
@ -36,7 +43,7 @@ ReturnValue_t PlocMPSoCHelper::performOperation(uint8_t operationCode) {
}
case InternalState::FLASH_WRITE: {
result = performFlashWrite();
if (result == RETURN_OK) {
if (result == returnvalue::OK) {
triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL);
} else {
triggerEvent(MPSOC_FLASH_WRITE_FAILED);
@ -52,12 +59,12 @@ ReturnValue_t PlocMPSoCHelper::performOperation(uint8_t operationCode) {
}
ReturnValue_t PlocMPSoCHelper::setComIF(DeviceCommunicationIF* communicationInterface_) {
uartComIF = dynamic_cast<UartComIF*>(communicationInterface_);
uartComIF = dynamic_cast<SerialComIF*>(communicationInterface_);
if (uartComIF == nullptr) {
sif::warning << "PlocMPSoCHelper::initialize: Invalid uart com if" << std::endl;
return RETURN_FAILED;
return returnvalue::FAILED;
}
return RETURN_OK;
return returnvalue::OK;
}
void PlocMPSoCHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
@ -67,14 +74,14 @@ void PlocMPSoCHelper::setSequenceCount(SourceSequenceCounter* sequenceCount_) {
}
ReturnValue_t PlocMPSoCHelper::startFlashWrite(std::string obcFile, std::string mpsocFile) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
#ifdef XIPHOS_Q7S
result = FilesystemHelper::checkPath(obcFile);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = FilesystemHelper::fileExists(mpsocFile);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
#endif
@ -82,7 +89,7 @@ ReturnValue_t PlocMPSoCHelper::startFlashWrite(std::string obcFile, std::string
if (not std::filesystem::exists(obcFile)) {
sif::warning << "PlocMPSoCHelper::startFlashWrite: File " << obcFile << "does not exist"
<< std::endl;
return RETURN_FAILED;
return returnvalue::FAILED;
}
#endif
@ -90,15 +97,16 @@ ReturnValue_t PlocMPSoCHelper::startFlashWrite(std::string obcFile, std::string
flashWrite.mpsocFile = mpsocFile;
internalState = InternalState::FLASH_WRITE;
result = resetHelper();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
return result;
}
ReturnValue_t PlocMPSoCHelper::resetHelper() {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
semaphore.release();
spParams.buf = commandBuffer;
terminate = false;
result = uartComIF->flushUartRxBuffer(comCookie);
return result;
@ -107,9 +115,9 @@ ReturnValue_t PlocMPSoCHelper::resetHelper() {
void PlocMPSoCHelper::stopProcess() { terminate = true; }
ReturnValue_t PlocMPSoCHelper::performFlashWrite() {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
result = flashfopen();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
uint8_t tempData[mpsoc::MAX_DATA_SIZE];
@ -122,7 +130,7 @@ ReturnValue_t PlocMPSoCHelper::performFlashWrite() {
size_t bytesRead = 0;
while (remainingSize > 0) {
if (terminate) {
return RETURN_OK;
return returnvalue::OK;
}
if (remainingSize > mpsoc::MAX_DATA_SIZE) {
dataLength = mpsoc::MAX_DATA_SIZE;
@ -138,71 +146,76 @@ ReturnValue_t PlocMPSoCHelper::performFlashWrite() {
return FILE_CLOSED_ACCIDENTALLY;
}
(*sequenceCount)++;
mpsoc::TcFlashWrite tc(*sequenceCount);
tc.createPacket(tempData, dataLength);
mpsoc::TcFlashWrite tc(spParams, *sequenceCount);
result = tc.buildPacket(tempData, dataLength);
if (result != returnvalue::OK) {
return result;
}
result = handlePacketTransmission(tc);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
}
result = flashfclose();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
return result;
}
ReturnValue_t PlocMPSoCHelper::flashfopen() {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
spParams.buf = commandBuffer;
(*sequenceCount)++;
mpsoc::FlashFopen flashFopen(*sequenceCount);
mpsoc::FlashFopen flashFopen(spParams, *sequenceCount);
result = flashFopen.createPacket(flashWrite.mpsocFile, mpsoc::FlashFopen::APPEND);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = handlePacketTransmission(flashFopen);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHelper::flashfclose() {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
spParams.buf = commandBuffer;
(*sequenceCount)++;
mpsoc::FlashFclose flashFclose(*sequenceCount);
mpsoc::FlashFclose flashFclose(spParams, *sequenceCount);
result = flashFclose.createPacket(flashWrite.mpsocFile);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = handlePacketTransmission(flashFclose);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHelper::handlePacketTransmission(mpsoc::TcBase& tc) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t PlocMPSoCHelper::handlePacketTransmission(ploc::SpTcBase& tc) {
ReturnValue_t result = returnvalue::OK;
result = sendCommand(tc);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = handleAck();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = handleExe();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHelper::sendCommand(mpsoc::TcBase& tc) {
ReturnValue_t result = RETURN_OK;
result = uartComIF->sendMessage(comCookie, tc.getWholeData(), tc.getFullSize());
if (result != RETURN_OK) {
ReturnValue_t PlocMPSoCHelper::sendCommand(ploc::SpTcBase& tc) {
ReturnValue_t result = returnvalue::OK;
result = uartComIF->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen());
if (result != returnvalue::OK) {
sif::warning << "PlocMPSoCHelper::sendCommand: Failed to send command" << std::endl;
triggerEvent(MPSOC_SENDING_COMMAND_FAILED, result, static_cast<uint32_t>(internalState));
return result;
@ -211,18 +224,22 @@ ReturnValue_t PlocMPSoCHelper::sendCommand(mpsoc::TcBase& tc) {
}
ReturnValue_t PlocMPSoCHelper::handleAck() {
ReturnValue_t result = RETURN_OK;
mpsoc::TmPacket tmPacket;
result = handleTmReception(&tmPacket, mpsoc::SIZE_ACK_REPORT);
if (result != RETURN_OK) {
ReturnValue_t result = returnvalue::OK;
result = handleTmReception(mpsoc::SIZE_ACK_REPORT);
if (result != returnvalue::OK) {
return result;
}
uint16_t apid = tmPacket.getAPID();
SpTmReader tmPacket(tmBuf.data(), tmBuf.size());
result = checkReceivedTm(tmPacket);
if (result != returnvalue::OK) {
return result;
}
uint16_t apid = tmPacket.getApid();
if (apid != mpsoc::apid::ACK_SUCCESS) {
handleAckApidFailure(apid);
return RETURN_FAILED;
return returnvalue::FAILED;
}
return RETURN_OK;
return returnvalue::OK;
}
void PlocMPSoCHelper::handleAckApidFailure(uint16_t apid) {
@ -238,18 +255,23 @@ void PlocMPSoCHelper::handleAckApidFailure(uint16_t apid) {
}
ReturnValue_t PlocMPSoCHelper::handleExe() {
ReturnValue_t result = RETURN_OK;
mpsoc::TmPacket tmPacket;
result = handleTmReception(&tmPacket, mpsoc::SIZE_EXE_REPORT);
if (result != RETURN_OK) {
ReturnValue_t result = returnvalue::OK;
result = handleTmReception(mpsoc::SIZE_EXE_REPORT);
if (result != returnvalue::OK) {
return result;
}
uint16_t apid = tmPacket.getAPID();
ploc::SpTmReader tmPacket(tmBuf.data(), tmBuf.size());
result = checkReceivedTm(tmPacket);
if (result != returnvalue::OK) {
return result;
}
uint16_t apid = tmPacket.getApid();
if (apid != mpsoc::apid::EXE_SUCCESS) {
handleExeApidFailure(apid);
return RETURN_FAILED;
return returnvalue::FAILED;
}
return RETURN_OK;
return returnvalue::OK;
}
void PlocMPSoCHelper::handleExeApidFailure(uint16_t apid) {
@ -264,13 +286,13 @@ void PlocMPSoCHelper::handleExeApidFailure(uint16_t apid) {
}
}
ReturnValue_t PlocMPSoCHelper::handleTmReception(mpsoc::TmPacket* tmPacket, size_t remainingBytes) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t PlocMPSoCHelper::handleTmReception(size_t remainingBytes) {
ReturnValue_t result = returnvalue::OK;
size_t readBytes = 0;
size_t currentBytes = 0;
for (int retries = 0; retries < RETRIES; retries++) {
result = receive(tmPacket->getWholeData() + readBytes, &currentBytes, remainingBytes);
if (result != RETURN_OK) {
result = receive(tmBuf.data() + readBytes, &currentBytes, remainingBytes);
if (result != returnvalue::OK) {
return result;
}
readBytes += currentBytes;
@ -282,37 +304,49 @@ ReturnValue_t PlocMPSoCHelper::handleTmReception(mpsoc::TmPacket* tmPacket, size
if (remainingBytes != 0) {
sif::warning << "PlocMPSoCHelper::handleTmReception: Failed to receive reply" << std::endl;
triggerEvent(MPSOC_MISSING_EXE, remainingBytes, static_cast<uint32_t>(internalState));
return RETURN_FAILED;
}
result = tmPacket->checkCrc();
if (result != RETURN_OK) {
sif::warning << "PlocMPSoCHelper::handleTmReception: CRC check failed" << std::endl;
return result;
}
(*sequenceCount)++;
uint16_t recvSeqCnt = tmPacket->getPacketSequenceCount();
if (recvSeqCnt != *sequenceCount) {
triggerEvent(MPSOC_HELPER_SEQ_CNT_MISMATCH, *sequenceCount, recvSeqCnt);
*sequenceCount = recvSeqCnt;
return returnvalue::FAILED;
}
return result;
}
ReturnValue_t PlocMPSoCHelper::checkReceivedTm(SpTmReader& reader) {
ReturnValue_t result = reader.checkSize();
if (result != returnvalue::OK) {
sif::error << "PlocMPSoCHelper::handleTmReception: Size check on received TM failed"
<< std::endl;
triggerEvent(MPSOC_TM_SIZE_ERROR);
return result;
}
reader.checkCrc();
if (result != returnvalue::OK) {
sif::warning << "PlocMPSoCHelper::handleTmReception: CRC check failed" << std::endl;
triggerEvent(MPSOC_TM_CRC_MISSMATCH, *sequenceCount);
return result;
}
(*sequenceCount)++;
uint16_t recvSeqCnt = reader.getSequenceCount();
if (recvSeqCnt != *sequenceCount) {
triggerEvent(MPSOC_HELPER_SEQ_CNT_MISMATCH, *sequenceCount, recvSeqCnt);
*sequenceCount = recvSeqCnt;
}
return returnvalue::OK;
}
ReturnValue_t PlocMPSoCHelper::receive(uint8_t* data, size_t* readBytes, size_t requestBytes) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
uint8_t* buffer = nullptr;
result = uartComIF->requestReceiveMessage(comCookie, requestBytes);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::warning << "PlocMPSoCHelper::receive: Failed to request reply" << std::endl;
triggerEvent(MPSOC_HELPER_REQUESTING_REPLY_FAILED, result,
static_cast<uint32_t>(static_cast<uint32_t>(internalState)));
return RETURN_FAILED;
return returnvalue::FAILED;
}
result = uartComIF->readReceivedMessage(comCookie, &buffer, readBytes);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::warning << "PlocMPSoCHelper::receive: Failed to read received message" << std::endl;
triggerEvent(MPSOC_HELPER_READING_REPLY_FAILED, result, static_cast<uint32_t>(internalState));
return RETURN_FAILED;
return returnvalue::FAILED;
}
if (*readBytes > 0) {
std::memcpy(data, buffer, *readBytes);

View File

@ -6,13 +6,14 @@
#include "fsfw/devicehandlers/CookieIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/osal/linux/BinarySemaphore.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tmtcservices/SourceSequenceCounter.h"
#include "fsfw_hal/linux/uart/UartComIF.h"
#include "fsfw_hal/linux/serial/SerialComIF.h"
#include "linux/devices/devicedefinitions/PlocMPSoCDefinitions.h"
#include "mission/trace.h"
#ifdef XIPHOS_Q7S
#include "bsp_q7s/memory/SdCardManager.h"
#include "bsp_q7s/fs/SdCardManager.h"
#endif
/**
@ -20,7 +21,7 @@
* MPSoC and OBC.
* @author J. Meier
*/
class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF {
class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MPSOC_HELPER;
@ -67,6 +68,8 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF, public H
//! P1: Expected sequence count
//! P2: Received sequence count
static const Event MPSOC_HELPER_SEQ_CNT_MISMATCH = MAKE_EVENT(11, severity::LOW);
static const Event MPSOC_TM_SIZE_ERROR = MAKE_EVENT(12, severity::LOW);
static const Event MPSOC_TM_CRC_MISSMATCH = MAKE_EVENT(13, severity::LOW);
PlocMPSoCHelper(object_id_t objectId);
virtual ~PlocMPSoCHelper();
@ -83,7 +86,7 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF, public H
* @param obcFile File where to read from the data
* @param mpsocFile The file of the MPSoC where should be written to
*
* @return RETURN_OK if successful, otherwise error return value
* @return returnvalue::OK if successful, otherwise error return value
*/
ReturnValue_t startFlashWrite(std::string obcFile, std::string mpsocFile);
@ -114,6 +117,10 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF, public H
struct FlashWrite flashWrite;
#if OBSW_THREAD_TRACING == 1
uint32_t opCounter = 0;
#endif
enum class InternalState { IDLE, FLASH_WRITE, FLASH_READ };
InternalState internalState = InternalState::IDLE;
@ -123,6 +130,10 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF, public H
SdCardManager* sdcMan = nullptr;
#endif
uint8_t commandBuffer[mpsoc::MAX_COMMAND_SIZE];
SpacePacketCreator creator;
ploc::SpTcParams spParams = ploc::SpTcParams(creator);
std::array<uint8_t, mpsoc::MAX_REPLY_SIZE> tmBuf;
bool terminate = false;
@ -130,24 +141,25 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF, public H
* Communication interface of MPSoC responsible for low level access. Must be set by the
* MPSoC Handler.
*/
UartComIF* uartComIF = nullptr;
SerialComIF* uartComIF = nullptr;
// Communication cookie. Must be set by the MPSoC Handler
CookieIF* comCookie = nullptr;
// Sequence count, must be set by Ploc MPSoC Handler
SourceSequenceCounter* sequenceCount;
SourceSequenceCounter* sequenceCount = nullptr;
ReturnValue_t resetHelper();
ReturnValue_t performFlashWrite();
ReturnValue_t flashfopen();
ReturnValue_t flashfclose();
ReturnValue_t handlePacketTransmission(mpsoc::TcBase& tc);
ReturnValue_t sendCommand(mpsoc::TcBase& tc);
ReturnValue_t handlePacketTransmission(ploc::SpTcBase& tc);
ReturnValue_t sendCommand(ploc::SpTcBase& tc);
ReturnValue_t receive(uint8_t* data, size_t* readBytes, size_t requestBytes);
ReturnValue_t handleAck();
ReturnValue_t handleExe();
void handleAckApidFailure(uint16_t apid);
void handleExeApidFailure(uint16_t apid);
ReturnValue_t handleTmReception(mpsoc::TmPacket* tmPacket, size_t remainingBytes);
ReturnValue_t handleTmReception(size_t remainingBytes);
ReturnValue_t checkReceivedTm(ploc::SpTmReader& reader);
};
#endif /* BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_ */

View File

@ -19,25 +19,25 @@ PlocMemoryDumper::~PlocMemoryDumper() {}
ReturnValue_t PlocMemoryDumper::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = commandActionHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = actionHelper.initialize(commandQueue);
if (result != HasReturnvaluesIF::RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
return HasReturnvaluesIF::RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t PlocMemoryDumper::performOperation(uint8_t operationCode) {
readCommandQueue();
doStateMachine();
return HasReturnvaluesIF::RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t PlocMemoryDumper::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
@ -78,20 +78,20 @@ MessageQueueIF* PlocMemoryDumper::getCommandQueuePtr() { return commandQueue; }
void PlocMemoryDumper::readCommandQueue() {
CommandMessage message;
ReturnValue_t result;
ReturnValue_t result = returnvalue::OK;
for (result = commandQueue->receiveMessage(&message); result == HasReturnvaluesIF::RETURN_OK;
for (result = commandQueue->receiveMessage(&message); result == returnvalue::OK;
result = commandQueue->receiveMessage(&message)) {
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
continue;
}
result = actionHelper.handleActionMessage(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
if (result == returnvalue::OK) {
continue;
}
result = commandActionHelper.handleReply(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
if (result == returnvalue::OK) {
continue;
}
@ -161,7 +161,7 @@ void PlocMemoryDumper::completionFailedReceived(ActionId_t actionId, ReturnValue
}
void PlocMemoryDumper::commandNextMramDump(ActionId_t dumpCommand) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
uint32_t tempStartAddress = 0;
uint32_t tempEndAddress = 0;
@ -181,7 +181,7 @@ void PlocMemoryDumper::commandNextMramDump(ActionId_t dumpCommand) {
result =
commandActionHelper.commandAction(objects::PLOC_SUPERVISOR_HANDLER, dumpCommand, &params);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::warning << "PlocMemoryDumper::commandNextMramDump: Failed to send mram dump command "
<< "with start address " << tempStartAddress << " and end address "
<< tempEndAddress << std::endl;

View File

@ -5,16 +5,20 @@
#include <linux/devices/devicedefinitions/PlocSupervisorDefinitions.h>
#include "OBSWConfig.h"
#include "bsp_q7s/memory/SdCardManager.h"
#ifdef XIPHOS_Q7S
#include "bsp_q7s/fs/SdCardManager.h"
#endif
#include "eive/eventSubsystemIds.h"
#include "fsfw/action/ActionHelper.h"
#include "fsfw/action/CommandActionHelper.h"
#include "fsfw/action/CommandsActionsIF.h"
#include "fsfw/action/HasActionsIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tmtcpacket/SpacePacket.h"
#include "linux/fsfwconfig/objects/systemObjectList.h"
#include "objects/systemObjectList.h"
/**
* @brief Because the buffer of the linux tty driver is limited to 2 x 65535 bytes, this class is
@ -27,7 +31,6 @@
class PlocMemoryDumper : public SystemObject,
public HasActionsIF,
public ExecutableObjectIF,
public HasReturnvaluesIF,
public CommandsActionsIF {
public:
static const ActionId_t NONE = 0;

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,22 @@
#ifndef MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_
#define MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_
#include <linux/devices/ploc/PlocSupvUartMan.h>
#include "OBSWConfig.h"
#include "PlocSupvHelper.h"
#include "bsp_q7s/memory/SdCardManager.h"
#include "devices/powerSwitcherList.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/timemanager/Countdown.h"
#include "fsfw_hal/linux/gpio/Gpio.h"
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
#include "fsfw_hal/linux/uart/UartComIF.h"
#include "fsfw_hal/linux/serial/SerialComIF.h"
#include "linux/devices/devicedefinitions/PlocSupervisorDefinitions.h"
#include "linux/devices/devicedefinitions/SupvReturnValuesIF.h"
#ifdef XIPHOS_Q7S
#include "bsp_q7s/fs/SdCardManager.h"
#endif
using supv::ExecutionReport;
/**
* @brief This is the device handler for the supervisor of the PLOC which is programmed by
@ -27,9 +32,8 @@
*/
class PlocSupervisorHandler : public DeviceHandlerBase {
public:
PlocSupervisorHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF* comCookie,
Gpio uartIsolatorSwitch, power::Switch_t powerSwitch,
PlocSupvHelper* supvHelper);
PlocSupervisorHandler(object_id_t objectId, CookieIF* comCookie, Gpio uartIsolatorSwitch,
power::Switch_t powerSwitch, PlocSupvUartManager& supvHelper);
virtual ~PlocSupervisorHandler();
virtual ReturnValue_t initialize() override;
@ -48,7 +52,6 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
ReturnValue_t scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId,
size_t* foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override;
void setNormalDatapoolEntriesInvalid() override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
@ -56,7 +59,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
uint8_t expectedReplies = 1, bool useAlternateId = false,
DeviceCommandId_t alternateReplyID = 0) override;
size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override;
ReturnValue_t doSendReadHook() override;
// ReturnValue_t doSendReadHook() override;
void doOffActivity() override;
private:
@ -64,18 +67,21 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
//! [EXPORT] : [COMMENT] PLOC supervisor crc failure in telemetry packet
static const Event SUPV_MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] Unhandled event. P1: APID, P2: Service ID
static constexpr Event SUPV_UNKNOWN_TM = MAKE_EVENT(2, severity::LOW);
static constexpr Event SUPV_UNINIMPLEMENTED_TM = MAKE_EVENT(3, severity::LOW);
//! [EXPORT] : [COMMENT] PLOC supervisor received acknowledgment failure report
static const Event SUPV_ACK_FAILURE = MAKE_EVENT(2, severity::LOW);
static const Event SUPV_ACK_FAILURE = MAKE_EVENT(4, severity::LOW);
//! [EXPORT] : [COMMENT] PLOC received execution failure report
//! P1: ID of command for which the execution failed
//! P2: Status code sent by the supervisor handler
static const Event SUPV_EXE_FAILURE = MAKE_EVENT(3, severity::LOW);
static const Event SUPV_EXE_FAILURE = MAKE_EVENT(5, severity::LOW);
//! [EXPORT] : [COMMENT] PLOC supervisor reply has invalid crc
static const Event SUPV_CRC_FAILURE_EVENT = MAKE_EVENT(4, severity::LOW);
static const Event SUPV_CRC_FAILURE_EVENT = MAKE_EVENT(6, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor helper currently executing a command
static const Event SUPV_HELPER_EXECUTING = MAKE_EVENT(5, severity::LOW);
static const Event SUPV_HELPER_EXECUTING = MAKE_EVENT(7, severity::LOW);
//! [EXPORT] : [COMMENT] Failed to build the command to shutdown the MPSoC
static const Event SUPV_MPSOC_SHUWDOWN_BUILD_FAILED = MAKE_EVENT(5, severity::LOW);
static const Event SUPV_MPSOC_SHUTDOWN_BUILD_FAILED = MAKE_EVENT(8, severity::LOW);
static const uint16_t APID_MASK = 0x7FF;
static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF;
@ -91,13 +97,17 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
static const uint32_t COPY_ADC_TO_MRAM_TIMEOUT = 70000;
// 60 s
static const uint32_t MRAM_DUMP_TIMEOUT = 60000;
// 2 s
static const uint32_t BOOT_TIMEOUT = 2000;
// 4 s
static const uint32_t BOOT_TIMEOUT = 4000;
enum class StartupState : uint8_t { OFF, BOOTING, SET_TIME, SET_TIME_EXECUTING, ON };
static constexpr bool SET_TIME_DURING_BOOT = true;
StartupState startupState = StartupState::OFF;
uint8_t commandBuffer[supv::MAX_COMMAND_SIZE];
SpacePacketCreator creator;
supv::TcParams spParams = supv::TcParams(creator);
/**
* This variable is used to store the id of the next reply to receive. This is necessary
@ -106,9 +116,10 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
*/
DeviceCommandId_t nextReplyId = supv::NONE;
UartComIF* uartComIf = nullptr;
SerialComIF* uartComIf = nullptr;
LinuxLibgpioIF* gpioComIF = nullptr;
Gpio uartIsolatorSwitch;
bool shutdownCmdSent = false;
supv::HkSet hkset;
supv::BootStatusReport bootStatusReport;
@ -117,8 +128,9 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
supv::AdcReport adcReport;
const power::Switch_t powerSwitch = power::NO_SWITCH;
supv::TmBase tmReader;
PlocSupvHelper* supvHelper = nullptr;
PlocSupvUartManager& uartManager;
MessageQueueIF* eventQueue = nullptr;
/** Number of expected replies following the MRAM dump command */
@ -126,29 +138,29 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
uint32_t receivedMramDumpPackets = 0;
/** Set to true as soon as a complete space packet is present in the spacePacketBuffer */
bool packetInBuffer = false;
/** Points to the next free position in the space packet buffer */
uint16_t bufferTop = 0;
/** This buffer is used to concatenate space packets received in two different read steps */
uint8_t spacePacketBuffer[supv::MAX_PACKET_SIZE];
#ifndef TE0720_1CFA
#ifdef XIPHOS_Q7S
SdCardManager* sdcMan = nullptr;
#endif /* BOARD_TE0720 == 0 */
#endif
// Path to supervisor specific files on SD card
std::string supervisorFilePath = "ploc/supervisor";
std::string activeMramFile;
// Supervisor helper class currently executing a command
bool plocSupvHelperExecuting = false;
Countdown executionReportTimeout = Countdown(EXECUTION_DEFAULT_TIMEOUT, false);
Countdown acknowledgementReportTimeout = Countdown(ACKNOWLEDGE_DEFAULT_TIMEOUT, false);
// Vorago nees some time to boot properly
Countdown bootTimeout = Countdown(BOOT_TIMEOUT);
Countdown mramDumpTimeout = Countdown(MRAM_DUMP_TIMEOUT);
PoolEntry<uint8_t> fmcStateEntry = PoolEntry<uint8_t>(1);
PoolEntry<uint8_t> bootStateEntry = PoolEntry<uint8_t>(1);
PoolEntry<uint8_t> bootCyclesEntry = PoolEntry<uint8_t>(1);
PoolEntry<uint32_t> tempSupEntry = PoolEntry<uint32_t>(1);
/**
* @brief Adjusts the timeout of the execution report dependent on command
*/
@ -167,7 +179,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
* @param start Pointer to the first byte of the reply.
* @param foundLen Pointer to the length of the whole packet.
*
* @return RETURN_OK if CRC is ok, otherwise CRC_FAILURE.
* @return returnvalue::OK if CRC is ok, otherwise CRC_FAILURE.
*/
ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen);
@ -176,7 +188,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
*
* @param data Pointer to the data holding the acknowledgment report.
*
* @return RETURN_OK if successful, otherwise an error code.
* @return returnvalue::OK if successful, otherwise an error code.
*/
ReturnValue_t handleAckReport(const uint8_t* data);
@ -185,7 +197,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
*
* @param data Pointer to the received data packet.
*
* @return RETURN_OK if successful, otherwise an error code.
* @return returnvalue::OK if successful, otherwise an error code.
*/
ReturnValue_t handleExecutionReport(const uint8_t* data);
@ -195,7 +207,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
*
* @param data Pointer to the data buffer holding the housekeeping read report.
*
* @return RETURN_OK if successful, otherwise an error code.
* @return returnvalue::OK if successful, otherwise an error code.
*/
ReturnValue_t handleHkReport(const uint8_t* data);
@ -206,7 +218,8 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
ReturnValue_t handleBootStatusReport(const uint8_t* data);
ReturnValue_t handleLatchupStatusReport(const uint8_t* data);
ReturnValue_t handleLoggingReport(const uint8_t* data);
void handleBadApidServiceCombination(Event result, unsigned int apid, unsigned int serviceId);
// ReturnValue_t handleLoggingReport(const uint8_t* data);
ReturnValue_t handleAdcReport(const uint8_t* data);
/**
@ -225,20 +238,20 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
* @param dataSize Size of telemetry in bytes.
* @param replyId Id of the reply. This will be added to the ActionMessage.
*/
void handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId);
void handleDeviceTm(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId);
/**
* @brief This function prepares a space packet which does not transport any data in the
* packet data field apart from the crc.
*/
void prepareEmptyCmd(uint16_t apid);
ReturnValue_t prepareEmptyCmd(uint16_t apid, uint8_t serviceId);
/**
* @brief This function initializes the space packet to select the boot image of the MPSoC.
*/
void prepareSelBootImageCmd(const uint8_t* commandData);
ReturnValue_t prepareSelBootImageCmd(const uint8_t* commandData);
void prepareDisableHk();
ReturnValue_t prepareDisableHk();
/**
* @brief This function fills the commandBuffer with the data to update the time of the
@ -250,9 +263,11 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
* @brief This function fills the commandBuffer with the data to change the boot timeout
* value in the PLOC supervisor.
*/
void prepareSetBootTimeoutCmd(const uint8_t* commandData);
ReturnValue_t prepareSetBootTimeoutCmd(const uint8_t* commandData);
void prepareRestartTriesCmd(const uint8_t* commandData);
ReturnValue_t prepareRestartTriesCmd(const uint8_t* commandData);
ReturnValue_t prepareFactoryResetCmd(const uint8_t* commandData, size_t len);
/**
* @brief This function fills the command buffer with the packet to enable or disable the
@ -269,21 +284,21 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
ReturnValue_t prepareLatchupConfigCmd(const uint8_t* commandData,
DeviceCommandId_t deviceCommand);
ReturnValue_t prepareSetAlertLimitCmd(const uint8_t* commandData);
void prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData);
void prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData);
void prepareSetAdcThresholdCmd(const uint8_t* commandData);
ReturnValue_t prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData);
ReturnValue_t prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData);
ReturnValue_t prepareSetAdcThresholdCmd(const uint8_t* commandData);
ReturnValue_t prepareRunAutoEmTest(const uint8_t* commandData);
ReturnValue_t prepareWipeMramCmd(const uint8_t* commandData);
ReturnValue_t prepareDumpMramCmd(const uint8_t* commandData);
void prepareSetGpioCmd(const uint8_t* commandData);
void prepareReadGpioCmd(const uint8_t* commandData);
ReturnValue_t prepareLoggingRequest(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t prepareEnableNvmsCommand(const uint8_t* commandData);
// ReturnValue_t prepareDumpMramCmd(const uint8_t* commandData);
ReturnValue_t prepareSetGpioCmd(const uint8_t* commandData);
ReturnValue_t prepareReadGpioCmd(const uint8_t* commandData);
// ReturnValue_t prepareLoggingRequest(const uint8_t* commandData, size_t commandDataLen);
// ReturnValue_t prepareEnableNvmsCommand(const uint8_t* commandData);
/**
* @brief Copies the content of a space packet to the command buffer.
*/
void packetToOutBuffer(uint8_t* packetData, size_t fullSize);
void finishTcPrep(size_t packetLen);
/**
* @brief In case an acknowledgment failure reply has been received this function disables
@ -313,7 +328,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
* @brief Function is called in scanForReply and fills the spacePacketBuffer with the read
* data until a full packet has been received.
*/
ReturnValue_t parseMramPackets(const uint8_t* packet, size_t remainingSize, size_t* foundlen);
// ReturnValue_t parseMramPackets(const uint8_t* packet, size_t remainingSize, size_t* foundlen);
/**
* @brief This function generates the Service 8 packets for the MRAM dump data.
@ -331,7 +346,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
* @brief Function checks if the packet written to the space packet buffer is really a
* MRAM dump packet.
*/
ReturnValue_t checkMramPacketApid();
// ReturnValue_t checkMramPacketApid();
/**
* @brief Writes the data of the MRAM dump to a file. The file will be created when receiving
@ -361,14 +376,18 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
ReturnValue_t createMramDumpFile();
ReturnValue_t getTimeStampString(std::string& timeStamp);
void prepareSetShutdownTimeoutCmd(const uint8_t* commandData);
ReturnValue_t prepareSetShutdownTimeoutCmd(const uint8_t* commandData);
ReturnValue_t extractUpdateCommand(const uint8_t* commandData, size_t size, std::string* file,
uint8_t* memoryId, uint32_t* startAddress);
ReturnValue_t extractUpdateCommand(const uint8_t* commandData, size_t size,
supv::UpdateParams& params);
ReturnValue_t extractBaseParams(const uint8_t** commandData, size_t& remSize,
supv::UpdateParams& params);
ReturnValue_t eventSubscription();
void handleExecutionSuccessReport(const uint8_t* data);
void handleExecutionFailureReport(uint16_t statusCode);
ReturnValue_t handleExecutionSuccessReport(ExecutionReport& report);
void handleExecutionFailureReport(ExecutionReport& report);
void printAckFailureInfo(uint16_t statusCode, DeviceCommandId_t commandId);
};
#endif /* MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ */

View File

@ -1,562 +0,0 @@
#include "PlocSupvHelper.h"
#include <filesystem>
#include <fstream>
#include "OBSWConfig.h"
#ifdef XIPHOS_Q7S
#include "bsp_q7s/memory/FilesystemHelper.h"
#include "bsp_q7s/memory/SdCardManager.h"
#endif
#include "fsfw/globalfunctions/CRC.h"
#include "fsfw/timemanager/Countdown.h"
#include "fsfw/tasks/TaskFactory.h"
#include "mission/utility/Filenaming.h"
#include "mission/utility/ProgressPrinter.h"
#include "mission/utility/Timestamp.h"
PlocSupvHelper::PlocSupvHelper(object_id_t objectId) : SystemObject(objectId) {}
PlocSupvHelper::~PlocSupvHelper() {}
ReturnValue_t PlocSupvHelper::initialize() {
#ifdef XIPHOS_Q7S
sdcMan = SdCardManager::instance();
if (sdcMan == nullptr) {
sif::warning << "PlocSupvHelper::initialize: Invalid SD Card Manager" << std::endl;
return RETURN_FAILED;
}
#endif
return RETURN_OK;
}
ReturnValue_t PlocSupvHelper::performOperation(uint8_t operationCode) {
ReturnValue_t result = RETURN_OK;
semaphore.acquire();
while (true) {
switch (internalState) {
case InternalState::IDLE: {
semaphore.acquire();
break;
}
case InternalState::UPDATE: {
result = performUpdate();
if (result == RETURN_OK) {
triggerEvent(SUPV_UPDATE_SUCCESSFUL, result);
} else if (result == PROCESS_TERMINATED) {
// Event already triggered
} else {
triggerEvent(SUPV_UPDATE_FAILED, result);
}
internalState = InternalState::IDLE;
break;
}
case InternalState::CONTINUE_UPDATE: {
result = continueUpdate();
if (result == RETURN_OK) {
triggerEvent(SUPV_CONTINUE_UPDATE_SUCCESSFUL, result);
} else if (result == PROCESS_TERMINATED) {
// Event already triggered
} else {
triggerEvent(SUPV_CONTINUE_UPDATE_FAILED, result);
}
internalState = InternalState::IDLE;
break;
}
case InternalState::REQUEST_EVENT_BUFFER: {
result = performEventBufferRequest();
if (result == RETURN_OK) {
triggerEvent(SUPV_EVENT_BUFFER_REQUEST_SUCCESSFUL, result);
} else if (result == PROCESS_TERMINATED) {
// Event already triggered
break;
} else {
triggerEvent(SUPV_EVENT_BUFFER_REQUEST_FAILED, result);
}
internalState = InternalState::IDLE;
break;
}
default:
sif::debug << "PlocSupvHelper::performOperation: Invalid state" << std::endl;
break;
}
}
}
ReturnValue_t PlocSupvHelper::setComIF(UartComIF* uartComIF_) {
if (uartComIF_ == nullptr) {
sif::warning << "PlocSupvHelper::initialize: Provided invalid uart com if" << std::endl;
return RETURN_FAILED;
}
uartComIF = uartComIF_;
return RETURN_OK;
}
void PlocSupvHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
ReturnValue_t PlocSupvHelper::startUpdate(std::string file, uint8_t memoryId,
uint32_t startAddress) {
ReturnValue_t result = RETURN_OK;
#ifdef XIPHOS_Q7S
result = FilesystemHelper::checkPath(file);
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::startUpdate: File " << file << " does not exist" << std::endl;
return result;
}
result = FilesystemHelper::fileExists(file);
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::startUpdate: The file " << file << " does not exist"
<< std::endl;
return result;
}
#endif
#ifdef TE0720_1CFA
if (not std::filesystem::exists(file)) {
sif::warning << "PlocSupvHelper::startUpdate: The file " << file << " does not exist"
<< std::endl;
return RETURN_FAILED;
}
#endif
update.file = file;
update.length = getFileSize(update.file);
update.memoryId = memoryId;
update.startAddress = startAddress;
update.remainingSize = update.length;
update.bytesWritten = 0;
update.packetNum = 1;
update.sequenceCount = 1;
internalState = InternalState::UPDATE;
uartComIF->flushUartTxAndRxBuf(comCookie);
semaphore.release();
return result;
}
void PlocSupvHelper::initiateUpdateContinuation() {
internalState = InternalState::CONTINUE_UPDATE;
semaphore.release();
}
ReturnValue_t PlocSupvHelper::startEventbBufferRequest(std::string path) {
#ifdef XIPHOS_Q7S
ReturnValue_t result = FilesystemHelper::checkPath(path);
if (result != RETURN_OK) {
return result;
}
#endif
if (not std::filesystem::exists(path)) {
return PATH_NOT_EXISTS;
}
eventBufferReq.path = path;
internalState = InternalState::REQUEST_EVENT_BUFFER;
uartComIF->flushUartTxAndRxBuf(comCookie);
semaphore.release();
return RETURN_OK;
}
void PlocSupvHelper::stopProcess() { terminate = true; }
ReturnValue_t PlocSupvHelper::performUpdate() {
ReturnValue_t result = RETURN_OK;
result = calcImageCrc();
if (result != RETURN_OK) {
return result;
}
result = selectMemory();
if (result != RETURN_OK) {
return result;
}
result = prepareUpdate();
if (result != RETURN_OK) {
return result;
}
result = eraseMemory();
if (result != RETURN_OK) {
return result;
}
result = writeUpdatePackets();
if (result != RETURN_OK) {
return result;
}
result = handleCheckMemoryCommand();
if (result != RETURN_OK) {
return result;
}
return result;
}
ReturnValue_t PlocSupvHelper::continueUpdate() {
ReturnValue_t result = prepareUpdate();
if (result != RETURN_OK) {
return result;
}
result = writeUpdatePackets();
if (result != RETURN_OK) {
return result;
}
result = handleCheckMemoryCommand();
if (result != RETURN_OK) {
return result;
}
return result;
}
ReturnValue_t PlocSupvHelper::writeUpdatePackets() {
ReturnValue_t result = RETURN_OK;
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
ProgressPrinter progressPrinter("Supervisor update", update.length,
ProgressPrinter::HALF_PERCENT);
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
uint8_t tempData[supv::WriteMemory::CHUNK_MAX];
std::ifstream file(update.file, std::ifstream::binary);
uint16_t dataLength = 0;
supv::SequenceFlags seqFlags;
while (update.remainingSize > 0) {
if (terminate) {
terminate = false;
return PROCESS_TERMINATED;
}
if (update.remainingSize > supv::WriteMemory::CHUNK_MAX) {
dataLength = supv::WriteMemory::CHUNK_MAX;
} else {
dataLength = static_cast<uint16_t>(update.remainingSize);
}
if (file.is_open()) {
file.seekg(update.bytesWritten, file.beg);
file.read(reinterpret_cast<char*>(tempData), dataLength);
if (!file) {
sif::warning << "PlocSupvHelper::performUpdate: Read only " << file.gcount() << " of "
<< dataLength << " bytes" << std::endl;
sif::info << "PlocSupvHelper::performUpdate: Failed when trying to read byte "
<< update.bytesWritten << std::endl;
}
} else {
return FILE_CLOSED_ACCIDENTALLY;
}
if (update.bytesWritten == 0) {
seqFlags = supv::SequenceFlags::FIRST_PKT;
} else if (update.remainingSize == 0) {
seqFlags = supv::SequenceFlags::LAST_PKT;
} else {
seqFlags = supv::SequenceFlags::CONTINUED_PKT;
}
supv::WriteMemory packet(seqFlags, update.sequenceCount++, update.memoryId,
update.startAddress + update.bytesWritten, dataLength, tempData);
result = handlePacketTransmission(packet);
if (result != RETURN_OK) {
update.sequenceCount--;
triggerEvent(WRITE_MEMORY_FAILED, update.packetNum);
return result;
}
update.remainingSize -= dataLength;
update.packetNum += 1;
update.bytesWritten += dataLength;
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
progressPrinter.print(update.bytesWritten);
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
}
return result;
}
ReturnValue_t PlocSupvHelper::performEventBufferRequest() {
using namespace supv;
ReturnValue_t result = RETURN_OK;
RequestLoggingData packet(RequestLoggingData::Sa::REQUEST_EVENT_BUFFERS);
result = sendCommand(packet);
if (result != RETURN_OK) {
return result;
}
result = handleAck();
if (result != RETURN_OK) {
return result;
}
result = handleEventBufferReception();
if (result != RETURN_OK) {
return result;
}
result = handleExe();
if (result != RETURN_OK) {
return result;
}
return result;
}
ReturnValue_t PlocSupvHelper::selectMemory() {
ReturnValue_t result = RETURN_OK;
supv::MPSoCBootSelect packet(update.memoryId);
result = handlePacketTransmission(packet);
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
ReturnValue_t PlocSupvHelper::prepareUpdate() {
ReturnValue_t result = RETURN_OK;
supv::ApidOnlyPacket packet(supv::APID_PREPARE_UPDATE);
result = handlePacketTransmission(packet, PREPARE_UPDATE_EXECUTION_REPORT);
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
ReturnValue_t PlocSupvHelper::eraseMemory() {
ReturnValue_t result = RETURN_OK;
supv::EraseMemory eraseMemory(update.memoryId, update.startAddress, update.length);
result = handlePacketTransmission(eraseMemory, supv::recv_timeout::ERASE_MEMORY);
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
ReturnValue_t PlocSupvHelper::handlePacketTransmission(SpacePacket& packet,
uint32_t timeoutExecutionReport) {
ReturnValue_t result = RETURN_OK;
result = sendCommand(packet);
if (result != RETURN_OK) {
return result;
}
result = handleAck();
if (result != RETURN_OK) {
return result;
}
result = handleExe(timeoutExecutionReport);
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
ReturnValue_t PlocSupvHelper::sendCommand(SpacePacket& packet) {
ReturnValue_t result = RETURN_OK;
rememberApid = packet.getAPID();
result = uartComIF->sendMessage(comCookie, packet.getWholeData(), packet.getFullSize());
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::sendCommand: Failed to send command" << std::endl;
triggerEvent(SUPV_SENDING_COMMAND_FAILED, result, static_cast<uint32_t>(internalState));
return result;
}
return result;
}
ReturnValue_t PlocSupvHelper::handleAck() {
ReturnValue_t result = RETURN_OK;
supv::AcknowledgmentReport ackReport;
result = handleTmReception(&ackReport, supv::SIZE_ACK_REPORT);
if (result != RETURN_OK) {
triggerEvent(ACK_RECEPTION_FAILURE, result, static_cast<uint32_t>(rememberApid));
sif::warning << "PlocSupvHelper::handleAck: Error in reception of acknowledgment report"
<< std::endl;
return result;
}
result = ackReport.checkApid();
if (result != RETURN_OK) {
if (result == SupvReturnValuesIF::RECEIVED_ACK_FAILURE) {
triggerEvent(SUPV_ACK_FAILURE_REPORT, static_cast<uint32_t>(ackReport.getRefApid()));
} else if (result == SupvReturnValuesIF::INVALID_APID) {
triggerEvent(SUPV_ACK_INVALID_APID, static_cast<uint32_t>(rememberApid));
}
return result;
}
return RETURN_OK;
}
ReturnValue_t PlocSupvHelper::handleExe(uint32_t timeout) {
ReturnValue_t result = RETURN_OK;
supv::ExecutionReport exeReport;
result = handleTmReception(&exeReport, supv::SIZE_EXE_REPORT, timeout);
if (result != RETURN_OK) {
triggerEvent(EXE_RECEPTION_FAILURE, result, static_cast<uint32_t>(rememberApid));
sif::warning << "PlocSupvHelper::handleExe: Error in reception of execution report"
<< std::endl;
return result;
}
result = exeReport.checkApid();
if (result != RETURN_OK) {
if (result == SupvReturnValuesIF::RECEIVED_EXE_FAILURE) {
triggerEvent(SUPV_EXE_FAILURE_REPORT, static_cast<uint32_t>(exeReport.getRefApid()));
} else if (result == SupvReturnValuesIF::INVALID_APID) {
triggerEvent(SUPV_EXE_INVALID_APID, static_cast<uint32_t>(rememberApid));
}
return result;
}
return RETURN_OK;
}
ReturnValue_t PlocSupvHelper::handleTmReception(supv::TmPacket* tmPacket, size_t remainingBytes,
uint32_t timeout) {
ReturnValue_t result = RETURN_OK;
size_t readBytes = 0;
size_t currentBytes = 0;
Countdown countdown(timeout);
while (!countdown.hasTimedOut()) {
result = receive(tmPacket->getWholeData() + readBytes, &currentBytes, remainingBytes);
if (result != RETURN_OK) {
return result;
}
readBytes += currentBytes;
remainingBytes = remainingBytes - currentBytes;
if (remainingBytes == 0) {
break;
}
}
if (remainingBytes != 0) {
sif::warning << "PlocSupvHelper::handleTmReception: Failed to read " << std::dec
<< remainingBytes << " bytes" << std::endl;
return RETURN_FAILED;
}
result = tmPacket->checkCrc();
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::handleTmReception: CRC check failed" << std::endl;
return result;
}
return result;
}
ReturnValue_t PlocSupvHelper::receive(uint8_t* data, size_t* readBytes, size_t requestBytes) {
ReturnValue_t result = RETURN_OK;
uint8_t* buffer = nullptr;
result = uartComIF->requestReceiveMessage(comCookie, requestBytes);
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::receive: Failed to request reply" << std::endl;
triggerEvent(SUPV_HELPER_REQUESTING_REPLY_FAILED, result,
static_cast<uint32_t>(static_cast<uint32_t>(internalState)));
return RETURN_FAILED;
}
result = uartComIF->readReceivedMessage(comCookie, &buffer, readBytes);
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::receive: Failed to read received message" << std::endl;
triggerEvent(SUPV_HELPER_READING_REPLY_FAILED, result, static_cast<uint32_t>(internalState));
return RETURN_FAILED;
}
if (*readBytes > 0) {
std::memcpy(data, buffer, *readBytes);
}
else {
TaskFactory::delayTask(40);
}
return result;
}
ReturnValue_t PlocSupvHelper::calcImageCrc() {
ReturnValue_t result = RETURN_OK;
#ifdef XIPHOS_Q7S
result = FilesystemHelper::checkPath(update.file);
#endif
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::calcImageCrc: File " << update.file << " does not exist"
<< std::endl;
return result;
}
std::ifstream file(update.file, std::ifstream::binary);
uint16_t remainder = CRC16_INIT;
uint8_t input;
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
ProgressPrinter progress("Supervisor update crc calculation", update.length,
ProgressPrinter::ONE_PERCENT);
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
uint32_t byteCount = 0;
for (byteCount = 0; byteCount < update.length; byteCount++) {
file.seekg(byteCount, file.beg);
file.read(reinterpret_cast<char*>(&input), 1);
remainder = CRC::crc16ccitt(&input, sizeof(input), remainder);
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
progress.print(byteCount);
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
}
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
progress.print(byteCount);
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
file.close();
update.crc = remainder;
return result;
}
ReturnValue_t PlocSupvHelper::handleCheckMemoryCommand() {
ReturnValue_t result = RETURN_OK;
// Verification of update write procedure
supv::CheckMemory packet(update.memoryId, update.startAddress, update.length);
result = sendCommand(packet);
if (result != RETURN_OK) {
return result;
}
result = handleAck();
if (result != RETURN_OK) {
return result;
}
supv::UpdateStatusReport updateStatusReport;
result = handleTmReception(&updateStatusReport,
static_cast<size_t>(updateStatusReport.getNominalSize()),
supv::recv_timeout::UPDATE_STATUS_REPORT);
if (result != RETURN_OK) {
sif::warning
<< "PlocSupvHelper::handleCheckMemoryCommand: Failed to receive update status report"
<< std::endl;
return result;
}
result = handleExe(CRC_EXECUTION_TIMEOUT);
if (result != RETURN_OK) {
return result;
}
result = updateStatusReport.parseDataField();
if (result != RETURN_OK) {
return result;
}
result = updateStatusReport.verifycrc(update.crc);
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::handleCheckMemoryCommand: CRC failure. Expected CRC 0x"
<< std::hex << update.crc << " but received CRC 0x" << updateStatusReport.getCrc()
<< std::endl;
return result;
}
return result;
}
uint32_t PlocSupvHelper::getFileSize(std::string filename) {
std::ifstream file(filename, std::ifstream::binary);
file.seekg(0, file.end);
uint32_t size = file.tellg();
file.close();
return size;
}
ReturnValue_t PlocSupvHelper::handleEventBufferReception() {
ReturnValue_t result = RETURN_OK;
std::string filename = Filenaming::generateAbsoluteFilename(
eventBufferReq.path, eventBufferReq.filename, timestamping);
std::ofstream file(filename, std::ios_base::app | std::ios_base::out);
uint32_t packetsRead = 0;
size_t requestLen = 0;
supv::TmPacket tmPacket;
for (packetsRead = 0; packetsRead < NUM_EVENT_BUFFER_PACKETS; packetsRead++) {
if (terminate) {
triggerEvent(SUPV_EVENT_BUFFER_REQUEST_TERMINATED, packetsRead - 1);
file.close();
return PROCESS_TERMINATED;
}
if (packetsRead == NUM_EVENT_BUFFER_PACKETS - 1) {
requestLen = SIZE_EVENT_BUFFER_LAST_PACKET;
} else {
requestLen = SIZE_EVENT_BUFFER_FULL_PACKET;
}
result = handleTmReception(&tmPacket, requestLen);
if (result != RETURN_OK) {
sif::debug << "PlocSupvHelper::handleEventBufferReception: Failed while trying to read packet"
<< " " << packetsRead + 1 << std::endl;
file.close();
return result;
}
uint16_t apid = tmPacket.getAPID();
if (apid != supv::APID_MRAM_DUMP_TM) {
sif::warning << "PlocSupvHelper::handleEventBufferReception: Did not expect space packet "
<< "with APID 0x" << std::hex << apid << std::endl;
file.close();
return EVENT_BUFFER_REPLY_INVALID_APID;
}
file.write(reinterpret_cast<const char*>(tmPacket.getPacketData()),
tmPacket.getPayloadDataLength());
}
return result;
}

View File

@ -1,241 +0,0 @@
#ifndef BSP_Q7S_DEVICES_PLOCSUPVHELPER_H_
#define BSP_Q7S_DEVICES_PLOCSUPVHELPER_H_
#include <string>
#include "OBSWConfig.h"
#include "fsfw/devicehandlers/CookieIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/osal/linux/BinarySemaphore.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw_hal/linux/uart/UartComIF.h"
#include "linux/devices/devicedefinitions/PlocSupervisorDefinitions.h"
#ifdef XIPHOS_Q7S
#include "bsp_q7s/memory/SdCardManager.h"
#endif
/**
* @brief Helper class for supervisor of PLOC intended to accelerate large data transfers between
* the supervisor and the OBC.
* @author J. Meier
*/
class PlocSupvHelper : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_SUPV_HELPER;
//! [EXPORT] : [COMMENT] update failed
static const Event SUPV_UPDATE_FAILED = MAKE_EVENT(0, severity::LOW);
//! [EXPORT] : [COMMENT] update successful
static const Event SUPV_UPDATE_SUCCESSFUL = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] Continue update command failed
static const Event SUPV_CONTINUE_UPDATE_FAILED = MAKE_EVENT(2, severity::LOW);
//! [EXPORT] : [COMMENT] Continue update command successful
static const Event SUPV_CONTINUE_UPDATE_SUCCESSFUL = MAKE_EVENT(3, severity::LOW);
//! [EXPORT] : [COMMENT] Terminated update procedure by command
static const Event TERMINATED_UPDATE_PROCEDURE = MAKE_EVENT(4, severity::LOW);
//! [EXPORT] : [COMMENT] Requesting event buffer was successful
static const Event SUPV_EVENT_BUFFER_REQUEST_SUCCESSFUL = MAKE_EVENT(5, severity::LOW);
//! [EXPORT] : [COMMENT] Requesting event buffer failed
static const Event SUPV_EVENT_BUFFER_REQUEST_FAILED = MAKE_EVENT(6, severity::LOW);
//! [EXPORT] : [COMMENT] Terminated event buffer request by command
//! P1: Number of packets read before process was terminated
static const Event SUPV_EVENT_BUFFER_REQUEST_TERMINATED = MAKE_EVENT(7, severity::LOW);
//! [EXPORT] : [COMMENT] Communication interface returned failure when trying to send the command
//! to the supervisor
//! P1: Return value returned by the communication interface sendMessage function
//! P2: Internal state of supervisor helper
static const Event SUPV_SENDING_COMMAND_FAILED = MAKE_EVENT(8, severity::LOW);
//! [EXPORT] : [COMMENT] Request receive message of communication interface failed
//! P1: Return value returned by the communication interface requestReceiveMessage function
//! P2: Internal state of supervisor helper
static const Event SUPV_HELPER_REQUESTING_REPLY_FAILED = MAKE_EVENT(9, severity::LOW);
//! [EXPORT] : [COMMENT] Reading receive message of communication interface failed
//! P1: Return value returned by the communication interface readingReceivedMessage function
//! P2: Internal state of supervisor helper
static const Event SUPV_HELPER_READING_REPLY_FAILED = MAKE_EVENT(10, severity::LOW);
//! [EXPORT] : [COMMENT] Did not receive acknowledgement report
//! P1: Number of bytes missing
//! P2: Internal state of MPSoC helper
static const Event SUPV_MISSING_ACK = MAKE_EVENT(11, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor did not receive execution report
//! P1: Number of bytes missing
//! P2: Internal state of supervisor helper
static const Event SUPV_MISSING_EXE = MAKE_EVENT(12, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor received acknowledgment failure report
//! P1: Internal state of supervisor helper
static const Event SUPV_ACK_FAILURE_REPORT = MAKE_EVENT(13, severity::LOW);
//! [EXPORT] : [COMMENT] Execution report failure
//! P1:
static const Event SUPV_EXE_FAILURE_REPORT = MAKE_EVENT(14, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor expected acknowledgment report but received space packet with
//! other apid P1: Apid of received space packet P2: Internal state of supervisor helper
static const Event SUPV_ACK_INVALID_APID = MAKE_EVENT(15, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor helper expected execution report but received space packet
//! with other apid P1: Apid of received space packet P2: Internal state of supervisor helper
static const Event SUPV_EXE_INVALID_APID = MAKE_EVENT(16, severity::LOW);
//! [EXPORT] : [COMMENT] Failed to receive acknowledgment report
//! P1: Return value
//! P2: Apid of command for which the reception of the acknowledgment report failed
static const Event ACK_RECEPTION_FAILURE = MAKE_EVENT(17, severity::LOW);
//! [EXPORT] : [COMMENT] Failed to receive execution report
//! P1: Return value
//! P2: Apid of command for which the reception of the execution report failed
static const Event EXE_RECEPTION_FAILURE = MAKE_EVENT(18, severity::LOW);
//! [EXPORT] : [COMMENT] Update procedure failed when sending packet with number P1
//! P1: Packet number for which the memory write command fails
static const Event WRITE_MEMORY_FAILED = MAKE_EVENT(19, severity::LOW);
PlocSupvHelper(object_id_t objectId);
virtual ~PlocSupvHelper();
ReturnValue_t initialize() override;
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
ReturnValue_t setComIF(UartComIF* uartComfIF_);
void setComCookie(CookieIF* comCookie_);
/**
* @brief Starts update procedure
*
* @param file File containing the update data
* @param memoryId ID of the memory where to write to
* @param startAddress Address where to write data
*
* @return RETURN_OK if successful, otherwise error return value
*/
ReturnValue_t startUpdate(std::string file, uint8_t memoryId, uint32_t startAddress);
/**
* @brief This initiate the continuation of a failed update.
*/
void initiateUpdateContinuation();
/**
* @brief Calling this function will initiate the procedure to request the event buffer
*/
ReturnValue_t startEventbBufferRequest(std::string path);
/**
* @brief Can be used to interrupt a running data transfer.
*/
void stopProcess();
private:
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_SUPV_HELPER;
//! [EXPORT] : [COMMENT] File accidentally close
static const ReturnValue_t FILE_CLOSED_ACCIDENTALLY = MAKE_RETURN_CODE(0xA0);
//! [EXPORT] : [COMMENT] Process has been terminated by command
static const ReturnValue_t PROCESS_TERMINATED = MAKE_RETURN_CODE(0xA1);
//! [EXPORT] : [COMMENT] Received command with invalid pathname
static const ReturnValue_t PATH_NOT_EXISTS = MAKE_RETURN_CODE(0xA2);
//! [EXPORT] : [COMMENT] Expected event buffer TM but received space packet with other APID
static const ReturnValue_t EVENT_BUFFER_REPLY_INVALID_APID = MAKE_RETURN_CODE(0xA3);
static const uint16_t CRC16_INIT = 0xFFFF;
// Event buffer reply will carry 24 space packets with 1016 bytes and one space packet with
// 192 bytes
static const uint8_t NUM_EVENT_BUFFER_PACKETS = 25;
static const size_t SIZE_EVENT_BUFFER_FULL_PACKET = 1024;
static const size_t SIZE_EVENT_BUFFER_LAST_PACKET = 200;
static const uint32_t CRC_EXECUTION_TIMEOUT = 60000;
static const uint32_t PREPARE_UPDATE_EXECUTION_REPORT = 2000;
struct Update {
uint8_t memoryId;
uint32_t startAddress;
// Absolute name of file containing update data
std::string file;
// Size of update
uint32_t length;
uint32_t crc;
size_t remainingSize;
size_t bytesWritten;
uint32_t packetNum;
uint16_t sequenceCount;
};
struct Update update;
struct EventBufferRequest {
std::string path = "";
// Default name of file where event buffer data will be written to. Timestamp will be added to
// name when new file is created
std::string filename = "event-buffer.bin";
};
EventBufferRequest eventBufferReq;
enum class InternalState { IDLE, UPDATE, CONTINUE_UPDATE, REQUEST_EVENT_BUFFER };
InternalState internalState = InternalState::IDLE;
BinarySemaphore semaphore;
#ifdef XIPHOS_Q7S
SdCardManager* sdcMan = nullptr;
#endif
uint8_t commandBuffer[supv::MAX_COMMAND_SIZE];
bool terminate = false;
/**
* Communication interface responsible for data transactions between OBC and Supervisor.
*/
UartComIF* uartComIF = nullptr;
// Communication cookie. Must be set by the supervisor Handler
CookieIF* comCookie = nullptr;
bool timestamping = true;
// Remembers APID to know at which command a procedure failed
uint16_t rememberApid = 0;
ReturnValue_t performUpdate();
ReturnValue_t continueUpdate();
ReturnValue_t writeUpdatePackets();
ReturnValue_t performEventBufferRequest();
ReturnValue_t handlePacketTransmission(SpacePacket& packet,
uint32_t timeoutExecutionReport = 60000);
ReturnValue_t sendCommand(SpacePacket& packet);
/**
* @brief Function which reads form the communication interface
*
* @param data Pointer to buffer where read data will be written to
* @param raedBytes Actual number of bytes read
* @param requestBytes Number of bytes to read
*/
ReturnValue_t receive(uint8_t* data, size_t* readBytes, size_t requestBytes);
ReturnValue_t handleAck();
ReturnValue_t handleExe(uint32_t timeout = 1000);
/**
* @brief Handles reading of TM packets from the communication interface
*
* @param tmPacket Pointer to space packet where received data will be written to
* @param reaminingBytes Number of bytes to read in the space packet
* @param timeout Receive timeout in milliseconds
*
* @note It can take up to 70 seconds until the supervisor replies with an acknowledgment
* failure report.
*/
ReturnValue_t handleTmReception(supv::TmPacket* tmPacket, size_t remainingBytes,
uint32_t timeout = 70000);
ReturnValue_t selectMemory();
ReturnValue_t prepareUpdate();
ReturnValue_t eraseMemory();
// Calculates CRC over image. Will be used for verification after update writing has
// finished.
ReturnValue_t calcImageCrc();
ReturnValue_t handleCheckMemoryCommand();
/**
* @brief Return size of file with name filename
*
* @param filename
*
* @return The size of the file
*/
uint32_t getFileSize(std::string filename);
ReturnValue_t handleEventBufferReception();
};
#endif /* BSP_Q7S_DEVICES_PLOCSUPVHELPER_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,378 @@
#ifndef BSP_Q7S_DEVICES_PLOCSUPVHELPER_H_
#define BSP_Q7S_DEVICES_PLOCSUPVHELPER_H_
#include <fsfw/container/SimpleRingBuffer.h>
#include <termios.h>
#include <string>
#include "OBSWConfig.h"
#include "fsfw/container/FIFO.h"
#include "fsfw/devicehandlers/CookieIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/osal/linux/BinarySemaphore.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw_hal/linux/serial/SerialComIF.h"
#include "linux/devices/devicedefinitions/PlocSupervisorDefinitions.h"
#include "mission/trace.h"
#include "tas/crc.h"
#ifdef XIPHOS_Q7S
#include "bsp_q7s/fs/SdCardManager.h"
#endif
/**
* @brief Helper class for supervisor of PLOC intended to accelerate large data transfers between
* the supervisor and the OBC.
* @author J. Meier
*/
class PlocSupvUartManager : public DeviceCommunicationIF,
public SystemObject,
public ExecutableObjectIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_SUPV_HELPER;
//! [EXPORT] : [COMMENT] File accidentally close
static const ReturnValue_t FILE_CLOSED_ACCIDENTALLY = MAKE_RETURN_CODE(0xA0);
//! [EXPORT] : [COMMENT] Process has been terminated by command
static const ReturnValue_t PROCESS_TERMINATED = MAKE_RETURN_CODE(0xA1);
//! [EXPORT] : [COMMENT] Received command with invalid pathname
static const ReturnValue_t PATH_NOT_EXISTS = MAKE_RETURN_CODE(0xA2);
//! [EXPORT] : [COMMENT] Expected event buffer TM but received space packet with other APID
static const ReturnValue_t EVENT_BUFFER_REPLY_INVALID_APID = MAKE_RETURN_CODE(0xA3);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_SUPV_HELPER;
//! [EXPORT] : [COMMENT] update failed
static const Event SUPV_UPDATE_FAILED = MAKE_EVENT(0, severity::LOW);
//! [EXPORT] : [COMMENT] update successful
static const Event SUPV_UPDATE_SUCCESSFUL = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] Continue update command failed
static const Event SUPV_CONTINUE_UPDATE_FAILED = MAKE_EVENT(2, severity::LOW);
//! [EXPORT] : [COMMENT] Continue update command successful
static const Event SUPV_CONTINUE_UPDATE_SUCCESSFUL = MAKE_EVENT(3, severity::LOW);
//! [EXPORT] : [COMMENT] Terminated update procedure by command
static const Event TERMINATED_UPDATE_PROCEDURE = MAKE_EVENT(4, severity::LOW);
//! [EXPORT] : [COMMENT] Requesting event buffer was successful
static const Event SUPV_EVENT_BUFFER_REQUEST_SUCCESSFUL = MAKE_EVENT(5, severity::LOW);
//! [EXPORT] : [COMMENT] Requesting event buffer failed
static const Event SUPV_EVENT_BUFFER_REQUEST_FAILED = MAKE_EVENT(6, severity::LOW);
//! [EXPORT] : [COMMENT] Terminated event buffer request by command
//! P1: Number of packets read before process was terminated
static const Event SUPV_EVENT_BUFFER_REQUEST_TERMINATED = MAKE_EVENT(7, severity::LOW);
//! Status of memory check command
//! P1: Returncode, 0 for success, other value with returncode for failure
static constexpr Event SUPV_MEM_CHECK_OK = MAKE_EVENT(8, severity::INFO);
static constexpr Event SUPV_MEM_CHECK_FAIL = MAKE_EVENT(9, severity::INFO);
//! [EXPORT] : [COMMENT] Communication interface returned failure when trying to send the command
//! to the supervisor
//! P1: Return value returned by the communication interface sendMessage function
//! P2: Internal state of supervisor helper
static const Event SUPV_SENDING_COMMAND_FAILED = MAKE_EVENT(16, severity::LOW);
//! [EXPORT] : [COMMENT] Request receive message of communication interface failed
//! P1: Return value returned by the communication interface requestReceiveMessage function
//! P2: Internal state of supervisor helper
static const Event SUPV_HELPER_REQUESTING_REPLY_FAILED = MAKE_EVENT(17, severity::LOW);
//! [EXPORT] : [COMMENT] Reading receive message of communication interface failed
//! P1: Return value returned by the communication interface readingReceivedMessage function
//! P2: Internal state of supervisor helper
static const Event SUPV_HELPER_READING_REPLY_FAILED = MAKE_EVENT(18, severity::LOW);
//! [EXPORT] : [COMMENT] Did not receive acknowledgement report
//! P1: Number of bytes missing
//! P2: Internal state of MPSoC helper
static const Event SUPV_MISSING_ACK = MAKE_EVENT(19, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor did not receive execution report
//! P1: Number of bytes missing
//! P2: Internal state of supervisor helper
static const Event SUPV_MISSING_EXE = MAKE_EVENT(20, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor received acknowledgment failure report
//! P1: Internal state of supervisor helper
static const Event SUPV_ACK_FAILURE_REPORT = MAKE_EVENT(21, severity::LOW);
//! [EXPORT] : [COMMENT] Execution report failure
//! P1:
static const Event SUPV_EXE_FAILURE_REPORT = MAKE_EVENT(22, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor expected acknowledgment report but received space packet with
//! other apid P1: Apid of received space packet P2: Internal state of supervisor helper
static const Event SUPV_ACK_INVALID_APID = MAKE_EVENT(23, severity::LOW);
//! [EXPORT] : [COMMENT] Supervisor helper expected execution report but received space packet
//! with other apid P1: Apid of received space packet P2: Internal state of supervisor helper
static const Event SUPV_EXE_INVALID_APID = MAKE_EVENT(24, severity::LOW);
//! [EXPORT] : [COMMENT] Failed to receive acknowledgment report
//! P1: Return value
//! P2: Apid of command for which the reception of the acknowledgment report failed
static const Event ACK_RECEPTION_FAILURE = MAKE_EVENT(25, severity::LOW);
//! [EXPORT] : [COMMENT] Failed to receive execution report
//! P1: Return value
//! P2: Apid of command for which the reception of the execution report failed
static const Event EXE_RECEPTION_FAILURE = MAKE_EVENT(26, severity::LOW);
//! [EXPORT] : [COMMENT] Update procedure failed when sending packet.
//! P1: First byte percent, third and fourth byte Sequence Count, P2: Bytes written
static const Event WRITE_MEMORY_FAILED = MAKE_EVENT(27, severity::LOW);
static const Event SUPV_REPLY_SIZE_MISSMATCH = MAKE_EVENT(28, severity::LOW);
static const Event SUPV_REPLY_CRC_MISSMATCH = MAKE_EVENT(29, severity::LOW);
//! [EXPORT] : [COMMENT] Will be triggered every 5 percent of the update progress.
//! P1: First byte percent, third and fourth byte Sequence Count, P2: Bytes written
static constexpr Event SUPV_UPDATE_PROGRESS = MAKE_EVENT(30, severity::INFO);
static constexpr Event HDLC_FRAME_REMOVAL_ERROR = MAKE_EVENT(31, severity::INFO);
static constexpr Event HDLC_CRC_ERROR = MAKE_EVENT(32, severity::INFO);
PlocSupvUartManager(object_id_t objectId);
virtual ~PlocSupvUartManager();
ReturnValue_t initialize() override;
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
/**
* @brief Starts update procedure
*
* @param file File containing the update data
* @param memoryId ID of the memory where to write to
* @param startAddress Address where to write data
*
* @return returnvalue::OK if successful, otherwise error return value
*/
ReturnValue_t performUpdate(const supv::UpdateParams& params);
ReturnValue_t startUpdate(std::string file, uint8_t memoryId, uint32_t startAddress);
ReturnValue_t performMemCheck(std::string file, uint8_t memoryId, uint32_t startAddress,
size_t sizeToCheck, bool checkCrc);
ReturnValue_t performMemCheck(std::string file, uint8_t memoryId, uint32_t startAddress);
/**
* @brief This initiate the continuation of a failed update.
*/
ReturnValue_t initiateUpdateContinuation();
/**
* @brief Calling this function will initiate the procedure to request the event buffer
*/
// ReturnValue_t startEventBufferRequest(std::string path);
/**
* @brief Can be used to stop the UART reception and put the task to sleep
*/
void stop();
/**
* @brief Can be used to start the UART reception
*/
void start();
bool longerRequestActive() const;
static uint32_t buildProgParams1(uint8_t percent, uint16_t seqCount);
static uint32_t buildApidServiceParam1(uint8_t apid, uint8_t serviceId);
private:
static constexpr ReturnValue_t REQUEST_DONE = returnvalue::makeCode(1, 0);
static constexpr ReturnValue_t NO_PACKET_FOUND = returnvalue::makeCode(1, 1);
static constexpr ReturnValue_t DECODE_BUF_TOO_SMALL = returnvalue::makeCode(1, 2);
static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS_CONSECUTIVE_START =
returnvalue::makeCode(1, 3);
static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS_CONSECUTIVE_END = returnvalue::makeCode(1, 4);
static constexpr ReturnValue_t HDLC_ERROR = returnvalue::makeCode(1, 5);
static const uint16_t CRC16_INIT = 0xFFFF;
// Event buffer reply will carry 24 space packets with 1016 bytes and one space packet with
// 192 bytes
static const uint8_t NUM_EVENT_BUFFER_PACKETS = 25;
static const size_t SIZE_EVENT_BUFFER_FULL_PACKET = 1024;
static const size_t SIZE_EVENT_BUFFER_LAST_PACKET = 200;
static const uint32_t PREPARE_UPDATE_EXECUTION_REPORT = 2000;
static constexpr uint8_t MAX_STORED_DECODED_PACKETS = 4;
static constexpr uint8_t HDLC_START_MARKER = 0x7E;
static constexpr uint8_t HDLC_END_MARKER = 0x7C;
struct Update {
uint8_t memoryId;
uint32_t startAddress;
// Absolute name of file containing update data
std::string file;
// Length of full file
size_t fullFileSize = 0;
// Size of update
uint32_t length = 0;
uint32_t crc = 0;
bool crcShouldBeChecked = true;
size_t bytesWritten;
uint32_t packetNum;
uint16_t sequenceCount;
uint8_t progressPercent;
bool deleteMemory = false;
};
struct Update update;
SemaphoreIF* semaphore;
MutexIF* lock;
MutexIF* ipcLock;
supv::TmBase tmReader;
int serialPort = 0;
struct termios tty = {};
#if OBSW_THREAD_TRACING == 1
uint32_t opCounter = 0;
#endif
struct EventBufferRequest {
std::string path = "";
// Default name of file where event buffer data will be written to. Timestamp will be added to
// name when new file is created
std::string filename = "event-buffer.bin";
};
EventBufferRequest eventBufferReq;
enum class InternalState { SLEEPING, DEFAULT, DEDICATED_REQUEST, GO_TO_SLEEP };
enum class Request {
DEFAULT,
UPDATE,
CONTINUE_UPDATE,
REQUEST_EVENT_BUFFER,
CHECK_MEMORY,
};
InternalState state = InternalState::SLEEPING;
Request request = Request::DEFAULT;
#ifdef XIPHOS_Q7S
SdCardManager* sdcMan = nullptr;
#endif
SimpleRingBuffer recRingBuf;
std::array<uint8_t, 1200> cmdBuf = {};
std::array<uint8_t, 2048> encodedSendBuf = {};
std::array<uint8_t, 2048> recBuf = {};
std::array<uint8_t, 2048> encodedBuf = {};
std::array<uint8_t, 1200> decodedBuf = {};
std::array<uint8_t, 1200> ipcBuffer = {};
SimpleRingBuffer decodedRingBuf;
FIFO<size_t, MAX_STORED_DECODED_PACKETS> decodedQueue;
SimpleRingBuffer ipcRingBuf;
FIFO<size_t, MAX_STORED_DECODED_PACKETS> ipcQueue;
SpacePacketCreator creator;
supv::TcParams spParams = supv::TcParams(creator);
std::array<uint8_t, supv::MAX_COMMAND_SIZE> tmBuf{};
bool printTc = false;
bool debugMode = false;
bool timestamping = true;
// Remembers APID to know at which command a procedure failed
uint16_t rememberApid = 0;
ReturnValue_t handleRunningLongerRequest();
ReturnValue_t handleUartReception();
void addHdlcFraming(const uint8_t* src, size_t slen, uint8_t* dst, size_t* dlen, size_t maxDest);
int removeHdlcFramingWithCrcCheck(const uint8_t* src, size_t slen, uint8_t* dst, size_t* dlen);
ReturnValue_t encodeAndSendPacket(const uint8_t* sendData, size_t sendLen);
void executeFullCheckMemoryCommand();
ReturnValue_t tryHdlcParsing();
ReturnValue_t parseRecRingBufForHdlc(size_t& readSize, size_t& decodedLen);
ReturnValue_t executeUpdate();
ReturnValue_t continueUpdate();
ReturnValue_t updateOperation();
ReturnValue_t writeUpdatePackets();
// ReturnValue_t performEventBufferRequest();
ReturnValue_t handlePacketTransmissionNoReply(supv::TcBase& packet,
uint32_t timeoutExecutionReport);
int handleAckReception(supv::TcBase& tc, size_t packetLen);
int handleExeAckReception(supv::TcBase& tc, size_t packetLen);
/**
* @brief Handles reading of TM packets from the communication interface
*
* @param tmPacket Pointer to space packet where received data will be written to
* @param reaminingBytes Number of bytes to read in the space packet
* @param timeout Receive timeout in milliseconds
*
* @note It can take up to 70 seconds until the supervisor replies with an acknowledgment
* failure report.
*/
ReturnValue_t handleTmReception(size_t remainingBytes, uint8_t* readBuf = nullptr,
uint32_t timeout = 70000);
ReturnValue_t checkReceivedTm();
ReturnValue_t selectMemory();
ReturnValue_t prepareUpdate();
ReturnValue_t eraseMemory();
// Calculates CRC over image. Will be used for verification after update writing has
// finished.
ReturnValue_t calcImageCrc();
ReturnValue_t handleCheckMemoryCommand(uint8_t failStep);
ReturnValue_t exeReportHandling();
/**
* @brief Return size of file with name filename
*
* @param filename
*
* @return The size of the file
*/
uint32_t getFileSize(std::string filename);
ReturnValue_t handleEventBufferReception(ploc::SpTmReader& reader);
void resetSpParams();
void pushIpcData(const uint8_t* data, size_t len);
/**
* @brief Device specific initialization, using the cookie.
* @details
* The cookie is already prepared in the factory. If the communication
* interface needs to be set up in some way and requires cookie information,
* this can be performed in this function, which is called on device handler
* initialization.
* @param cookie
* @return
* - @c returnvalue::OK if initialization was successfull
* - Everything else triggers failure event with returnvalue as parameter 1
*/
ReturnValue_t initializeInterface(CookieIF* cookie) override;
/**
* Called by DHB in the SEND_WRITE doSendWrite().
* This function is used to send data to the physical device
* by implementing and calling related drivers or wrapper functions.
* @param cookie
* @param data
* @param len If this is 0, nothing shall be sent.
* @return
* - @c returnvalue::OK for successfull send
* - Everything else triggers failure event with returnvalue as parameter 1
*/
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
/**
* Called by DHB in the GET_WRITE doGetWrite().
* Get send confirmation that the data in sendMessage() was sent successfully.
* @param cookie
* @return
* - @c returnvalue::OK if data was sent successfully but a reply is expected
* - NO_REPLY_EXPECTED if data was sent successfully and no reply is expected
* - Everything else to indicate failure
*/
ReturnValue_t getSendSuccess(CookieIF* cookie) override;
/**
* Called by DHB in the SEND_WRITE doSendRead().
* It is assumed that it is always possible to request a reply
* from a device. If a requestLen of 0 is supplied, no reply was enabled
* and communication specific action should be taken (e.g. read nothing
* or read everything).
*
* @param cookie
* @param requestLen Size of data to read
* @return - @c returnvalue::OK to confirm the request for data has been sent.
* - Everything else triggers failure event with
* returnvalue as parameter 1
*/
ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override;
ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override;
void performUartShutdown();
void updateVtime(uint8_t vtime);
};
#endif /* BSP_Q7S_DEVICES_PLOCSUPVHELPER_H_ */

View File

@ -34,15 +34,15 @@ ReturnValue_t ArcsecDatalinkLayer::decodeFrame(const uint8_t* rawData, size_t ra
case ARC_DEC_SYNC: {
// Reset length of SLIP struct for next frame
slipInfo.length = 0;
return RETURN_OK;
return returnvalue::OK;
}
default:
sif::debug << "ArcsecDatalinkLayer::decodeFrame: Unknown result code" << std::endl;
break;
return RETURN_FAILED;
return returnvalue::FAILED;
}
}
return RETURN_FAILED;
return returnvalue::FAILED;
}
uint8_t ArcsecDatalinkLayer::getReplyFrameType() { return decodedFrame[0]; }

View File

@ -1,7 +1,8 @@
#ifndef BSP_Q7S_DEVICES_ARCSECDATALINKLAYER_H_
#define BSP_Q7S_DEVICES_ARCSECDATALINKLAYER_H_
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "eive/resultClassIds.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
extern "C" {
@ -11,7 +12,7 @@ extern "C" {
/**
* @brief Helper class to handle the datalinklayer of replies from the star tracker of arcsec.
*/
class ArcsecDatalinkLayer : public HasReturnvaluesIF {
class ArcsecDatalinkLayer {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::STR_HANDLER;

View File

@ -5,15 +5,15 @@
ArcsecJsonParamBase::ArcsecJsonParamBase(std::string setName) : setName(setName) {}
ReturnValue_t ArcsecJsonParamBase::create(std::string fullname, uint8_t* buffer) {
ReturnValue_t result = RETURN_OK;
result = init(fullname);
if (result != RETURN_OK) {
sif::warning << "ArcsecJsonParamBase::create: Failed to init parameter command for set "
<< setName << std::endl;
return result;
}
result = createCommand(buffer);
if (result != RETURN_OK) {
// ReturnValue_t result = returnvalue::OK;
// result = init(fullname);
// if (result != returnvalue::OK) {
// sif::warning << "ArcsecJsonParamBase::create: Failed to init parameter command for set "
// << setName << std::endl;
// return result;
// }
ReturnValue_t result = createCommand(buffer);
if (result != returnvalue::OK) {
sif::warning << "ArcsecJsonParamBase::create: Failed to create parameter command for set "
<< setName << std::endl;
}
@ -25,7 +25,7 @@ ReturnValue_t ArcsecJsonParamBase::getParam(const std::string name, std::string&
if ((*it)[arcseckeys::NAME] == name) {
value = (*it)[arcseckeys::VALUE];
convertEmpty(value);
return RETURN_OK;
return returnvalue::OK;
}
}
return PARAM_NOT_EXISTS;
@ -68,18 +68,23 @@ void ArcsecJsonParamBase::addSetParamHeader(uint8_t* buffer, uint8_t setId) {
}
ReturnValue_t ArcsecJsonParamBase::init(const std::string filename) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
if (not std::filesystem::exists(filename)) {
sif::warning << "ArcsecJsonParamBase::init: JSON file " << filename << " does not exist"
<< std::endl;
return JSON_FILE_NOT_EXISTS;
}
createJsonObject(filename);
result = initSet();
if (result != RETURN_OK) {
return result;
try {
createJsonObject(filename);
result = initSet();
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
} catch (json::exception& e) {
// TODO: Re-create json file from backup here.
return returnvalue::FAILED;
}
return RETURN_OK;
}
void ArcsecJsonParamBase::createJsonObject(const std::string fullname) {
@ -94,7 +99,7 @@ ReturnValue_t ArcsecJsonParamBase::initSet() {
for (json::iterator it = properties.begin(); it != properties.end(); ++it) {
if ((*it)["name"] == setName) {
set = (*it)["fields"];
return RETURN_OK;
return returnvalue::OK;
}
}
sif::warning << "ArcsecJsonParamBase::initSet: Set " << setName << "not present in json file"

View File

@ -5,7 +5,8 @@
#include <fstream>
#include <nlohmann/json.hpp>
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "eive/resultClassIds.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
extern "C" {
@ -22,7 +23,7 @@ using json = nlohmann::json;
*
* @author J. Meier
*/
class ArcsecJsonParamBase : public HasReturnvaluesIF {
class ArcsecJsonParamBase {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::ARCSEC_JSON_BASE;
//! [EXPORT] : [COMMENT] Specified json file does not exist
@ -32,6 +33,7 @@ class ArcsecJsonParamBase : public HasReturnvaluesIF {
//! [EXPORT] : [COMMENT] Requested parameter does not exist in json file
static const ReturnValue_t PARAM_NOT_EXISTS = MAKE_RETURN_CODE(3);
virtual ~ArcsecJsonParamBase() = default;
/**
* @brief Constructor
*
@ -39,6 +41,17 @@ class ArcsecJsonParamBase : public HasReturnvaluesIF {
*/
ArcsecJsonParamBase(std::string setName);
/**
* @brief Initializes the properties json object and the set json object
*
* @param fullname Name including absolute path to json file
* @param setName The name of the set to work on
*
* @param return JSON_FILE_NOT_EXISTS if specified file does not exist, otherwise
* returnvalue::OK
*/
ReturnValue_t init(const std::string filename);
/**
* @brief Fills a buffer with a parameter set
*
@ -60,7 +73,7 @@ class ArcsecJsonParamBase : public HasReturnvaluesIF {
* @param name The name of the parameter
* @param value The string representation of the read value
*
* @return RETURN_OK if successful, otherwise PARAM_NOT_EXISTS
* @return returnvalue::OK if successful, otherwise PARAM_NOT_EXISTS
*/
ReturnValue_t getParam(const std::string name, std::string& value);
@ -122,17 +135,6 @@ class ArcsecJsonParamBase : public HasReturnvaluesIF {
*/
virtual ReturnValue_t createCommand(uint8_t* buffer) = 0;
/**
* @brief Initializes the properties json object and the set json object
*
* @param fullname Name including absolute path to json file
* @param setName The name of the set to work on
*
* @param return JSON_FILE_NOT_EXISTS if specified file does not exist, otherwise
* RETURN_OK
*/
ReturnValue_t init(const std::string filename);
void createJsonObject(const std::string fullname);
/**

View File

@ -1,7 +1,4 @@
target_sources(${OBSW_NAME} PRIVATE
StarTrackerHandler.cpp
StarTrackerJsonCommands.cpp
ArcsecDatalinkLayer.cpp
ArcsecJsonParamBase.cpp
StrHelper.cpp
)
target_sources(
${OBSW_NAME}
PRIVATE StarTrackerHandler.cpp StarTrackerJsonCommands.cpp
ArcsecDatalinkLayer.cpp ArcsecJsonParamBase.cpp StrHelper.cpp)

View File

@ -1,8 +1,11 @@
#include "StarTrackerHandler.h"
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <atomic>
#include <fstream>
#include <thread>
#include "OBSWConfig.h"
#include "StarTrackerJsonCommands.h"
@ -14,8 +17,11 @@ extern "C" {
#include "common/misc.h"
}
std::atomic_bool JCFG_DONE(false);
StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
StrHelper* strHelper, power::Switch_t powerSwitch)
const char* jsonFileStr, StrHelper* strHelper,
power::Switch_t powerSwitch)
: DeviceHandlerBase(objectId, comIF, comCookie),
temperatureSet(this),
versionSet(this),
@ -40,6 +46,7 @@ StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF,
logSubscriptionSet(this),
debugCameraSet(this),
strHelper(strHelper),
paramJsonFile(jsonFileStr),
powerSwitch(powerSwitch) {
if (comCookie == nullptr) {
sif::error << "StarTrackerHandler: Invalid com cookie" << std::endl;
@ -53,12 +60,17 @@ StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF,
StarTrackerHandler::~StarTrackerHandler() {}
ReturnValue_t StarTrackerHandler::initialize() {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
result = DeviceHandlerBase::initialize();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
// Spin up a thread to do the JSON initialization, takes 200-250 ms which would
// delay whole satellite boot process.
jcfgCountdown.resetTimer();
jsonCfgTask = std::thread{setUpJsonCfgs, std::ref(jcfgs), paramJsonFile.c_str()};
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
if (manager == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@ -68,13 +80,13 @@ ReturnValue_t StarTrackerHandler::initialize() {
;
}
result = manager->registerListener(eventQueue->getId());
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = manager->subscribeToEventRange(eventQueue->getId(),
event::getEventId(StrHelper::IMAGE_UPLOAD_FAILED),
event::getEventId(StrHelper::FIRMWARE_UPDATE_FAILED));
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "StarTrackerHandler::initialize: Failed to subscribe to events from "
" str helper"
@ -84,16 +96,16 @@ ReturnValue_t StarTrackerHandler::initialize() {
}
result = strHelper->setComIF(communicationInterface);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
strHelper->setComCookie(comCookie);
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
switch (actionId) {
case (startracker::STOP_IMAGE_LOADER): {
@ -122,12 +134,12 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
}
result = checkMode(actionId);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = checkCommand(actionId);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
@ -135,14 +147,14 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
switch (actionId) {
case (startracker::UPLOAD_IMAGE): {
result = DeviceHandlerBase::acceptExternalDeviceCommands();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
if (size > MAX_PATH_SIZE + MAX_FILE_NAME) {
return FILE_PATH_TOO_LONG;
}
result = strHelper->startImageUpload(std::string(reinterpret_cast<const char*>(data), size));
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
strHelperExecuting = true;
@ -150,7 +162,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
}
case (startracker::DOWNLOAD_IMAGE): {
result = DeviceHandlerBase::acceptExternalDeviceCommands();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
if (size > MAX_PATH_SIZE) {
@ -158,7 +170,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
}
result =
strHelper->startImageDownload(std::string(reinterpret_cast<const char*>(data), size));
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
strHelperExecuting = true;
@ -166,11 +178,11 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
}
case (startracker::FLASH_READ): {
result = DeviceHandlerBase::acceptExternalDeviceCommands();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = executeFlashReadCommand(data, size);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
strHelperExecuting = true;
@ -192,7 +204,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
}
case (startracker::FIRMWARE_UPDATE): {
result = DeviceHandlerBase::acceptExternalDeviceCommands();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
if (size > MAX_PATH_SIZE + MAX_FILE_NAME) {
@ -200,7 +212,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
}
result =
strHelper->startFirmwareUpdate(std::string(reinterpret_cast<const char*>(data), size));
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
strHelperExecuting = true;
@ -214,7 +226,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
void StarTrackerHandler::performOperationHook() {
EventMessage event;
for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == RETURN_OK;
for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK;
result = eventQueue->receiveMessage(&event)) {
switch (event.getMessageId()) {
case EventMessage::EVENT_MESSAGE:
@ -240,13 +252,23 @@ void StarTrackerHandler::doStartUp() {
// the device handler's submode to the star tracker's mode
return;
case StartupState::DONE:
submode = SUBMODE_BOOTLOADER;
if (jcfgCountdown.isBusy()) {
startupState = StartupState::WAIT_JCFG;
return;
}
startupState = StartupState::IDLE;
break;
case StartupState::WAIT_JCFG: {
if (jcfgCountdown.hasTimedOut()) {
startupState = StartupState::IDLE;
break;
}
return;
}
default:
return;
}
setMode(_MODE_TO_ON);
setMode(_MODE_TO_ON, SUBMODE_BOOTLOADER);
}
void StarTrackerHandler::doShutDown() {
@ -385,120 +407,106 @@ ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t
ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t* commandData,
size_t commandDataLen) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
switch (deviceCommand) {
case (startracker::PING_REQUEST): {
preparePingRequest();
return RETURN_OK;
return returnvalue::OK;
}
case (startracker::REQ_TIME): {
prepareTimeRequest();
return RETURN_OK;
return returnvalue::OK;
}
case (startracker::BOOT): {
prepareBootCommand();
return RETURN_OK;
return returnvalue::OK;
}
case (startracker::REQ_VERSION): {
prepareVersionRequest();
return RETURN_OK;
return returnvalue::OK;
}
case (startracker::REQ_INTERFACE): {
prepareInterfaceRequest();
return RETURN_OK;
return returnvalue::OK;
}
case (startracker::REQ_POWER): {
preparePowerRequest();
return RETURN_OK;
return returnvalue::OK;
}
case (startracker::SWITCH_TO_BOOTLOADER_PROGRAM): {
prepareSwitchToBootloaderCmd();
return RETURN_OK;
return returnvalue::OK;
}
case (startracker::TAKE_IMAGE): {
prepareTakeImageCommand(commandData);
return RETURN_OK;
return returnvalue::OK;
}
case (startracker::SUBSCRIPTION): {
Subscription subscription;
result = prepareParamCommand(commandData, commandDataLen, subscription);
return RETURN_OK;
result = prepareParamCommand(commandData, commandDataLen, jcfgs.subscription);
return returnvalue::OK;
}
case (startracker::REQ_SOLUTION): {
prepareSolutionRequest();
return RETURN_OK;
return returnvalue::OK;
}
case (startracker::REQ_TEMPERATURE): {
prepareTemperatureRequest();
return RETURN_OK;
return returnvalue::OK;
}
case (startracker::REQ_HISTOGRAM): {
prepareHistogramRequest();
return RETURN_OK;
return returnvalue::OK;
}
case (startracker::LIMITS): {
Limits limits;
result = prepareParamCommand(commandData, commandDataLen, limits);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.limits);
return result;
}
case (startracker::MOUNTING): {
Mounting mounting;
result = prepareParamCommand(commandData, commandDataLen, mounting);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.mounting);
return result;
}
case (startracker::IMAGE_PROCESSOR): {
ImageProcessor imageProcessor;
result = prepareParamCommand(commandData, commandDataLen, imageProcessor);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.imageProcessor);
return result;
}
case (startracker::CAMERA): {
Camera camera;
result = prepareParamCommand(commandData, commandDataLen, camera);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.camera);
return result;
}
case (startracker::CENTROIDING): {
Centroiding centroiding;
result = prepareParamCommand(commandData, commandDataLen, centroiding);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.centroiding);
return result;
}
case (startracker::LISA): {
Lisa lisa;
result = prepareParamCommand(commandData, commandDataLen, lisa);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.lisa);
return result;
}
case (startracker::MATCHING): {
Matching matching;
result = prepareParamCommand(commandData, commandDataLen, matching);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.matching);
return result;
}
case (startracker::VALIDATION): {
Validation validation;
result = prepareParamCommand(commandData, commandDataLen, validation);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.validation);
return result;
}
case (startracker::ALGO): {
Algo algo;
result = prepareParamCommand(commandData, commandDataLen, algo);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.algo);
return result;
}
case (startracker::TRACKING): {
Tracking tracking;
result = prepareParamCommand(commandData, commandDataLen, tracking);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.tracking);
return result;
}
case (startracker::LOGLEVEL): {
LogLevel logLevel;
result = prepareParamCommand(commandData, commandDataLen, logLevel);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logLevel);
return result;
}
case (startracker::LOGSUBSCRIPTION): {
LogSubscription logSubscription;
result = prepareParamCommand(commandData, commandDataLen, logSubscription);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logSubscription);
return result;
}
case (startracker::DEBUG_CAMERA): {
DebugCamera debugCamera;
result = prepareParamCommand(commandData, commandDataLen, debugCamera);
result = prepareParamCommand(commandData, commandDataLen, jcfgs.debugCamera);
return result;
}
case (startracker::CHECKSUM): {
@ -564,7 +572,7 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
default:
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
return HasReturnvaluesIF::RETURN_FAILED;
return returnvalue::FAILED;
}
void StarTrackerHandler::fillCommandAndReplyMap() {
@ -654,7 +662,7 @@ void StarTrackerHandler::fillCommandAndReplyMap() {
}
ReturnValue_t StarTrackerHandler::isModeCombinationValid(Mode_t mode, Submode_t submode) {
if (this->mode == MODE_NORMAL && mode == MODE_ON) {
if (getMode() == MODE_NORMAL && mode == MODE_ON) {
return TRANS_NOT_ALLOWED;
}
switch (mode) {
@ -662,13 +670,13 @@ ReturnValue_t StarTrackerHandler::isModeCombinationValid(Mode_t mode, Submode_t
case MODE_NORMAL:
case MODE_RAW:
if (submode == SUBMODE_NONE) {
return RETURN_OK;
return returnvalue::OK;
} else {
return INVALID_SUBMODE;
}
case MODE_ON:
if (submode == SUBMODE_BOOTLOADER || submode == SUBMODE_FIRMWARE) {
return RETURN_OK;
return returnvalue::OK;
} else {
return INVALID_SUBMODE;
}
@ -678,7 +686,7 @@ ReturnValue_t StarTrackerHandler::isModeCombinationValid(Mode_t mode, Submode_t
}
void StarTrackerHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
switch (mode) {
switch (getMode()) {
case _MODE_TO_ON:
doOnTransition(subModeFrom);
break;
@ -698,17 +706,18 @@ void StarTrackerHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
}
void StarTrackerHandler::doOnTransition(Submode_t subModeFrom) {
if (submode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_FIRMWARE) {
uint8_t dhbSubmode = getSubmode();
if (dhbSubmode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_FIRMWARE) {
bootBootloader();
} else if (submode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_FIRMWARE) {
} else if (dhbSubmode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_FIRMWARE) {
setMode(MODE_ON);
} else if (submode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_BOOTLOADER) {
} else if (dhbSubmode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_BOOTLOADER) {
bootFirmware(MODE_ON);
} else if (submode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_BOOTLOADER) {
} else if (dhbSubmode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_BOOTLOADER) {
setMode(MODE_ON);
} else if (submode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_NONE) {
} else if (dhbSubmode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_NONE) {
setMode(MODE_ON);
} else if (submode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_NONE) {
} else if (dhbSubmode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_NONE) {
setMode(MODE_ON);
}
}
@ -746,6 +755,24 @@ void StarTrackerHandler::bootFirmware(Mode_t toMode) {
}
}
void StarTrackerHandler::setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonFile) {
cfgs.tracking.init(paramJsonFile);
cfgs.logLevel.init(paramJsonFile);
cfgs.logSubscription.init(paramJsonFile);
cfgs.debugCamera.init(paramJsonFile);
cfgs.algo.init(paramJsonFile);
cfgs.validation.init(paramJsonFile);
cfgs.matching.init(paramJsonFile);
cfgs.lisa.init(paramJsonFile);
cfgs.centroiding.init(paramJsonFile);
cfgs.camera.init(paramJsonFile);
cfgs.imageProcessor.init(paramJsonFile);
cfgs.mounting.init(paramJsonFile);
cfgs.limits.init(paramJsonFile);
cfgs.subscription.init(paramJsonFile);
JCFG_DONE = true;
}
void StarTrackerHandler::bootBootloader() {
if (internalState == InternalState::IDLE) {
internalState = InternalState::BOOT_BOOTLOADER;
@ -759,7 +786,7 @@ void StarTrackerHandler::bootBootloader() {
ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t remainingSize,
DeviceCommandId_t* foundId, size_t* foundLen) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
size_t bytesLeft = 0;
result = dataLinkLayer.decodeFrame(start, remainingSize, &bytesLeft);
@ -769,7 +796,7 @@ ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t rema
// Need a second doSendRead pass to reaa in whole packet
return IGNORE_REPLY_DATA;
}
case RETURN_OK: {
case returnvalue::OK: {
break;
}
default:
@ -801,7 +828,7 @@ ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t rema
}
default: {
sif::debug << "StarTrackerHandler::scanForReply: Reply has invalid type id" << std::endl;
result = RETURN_FAILED;
result = returnvalue::FAILED;
}
}
@ -812,7 +839,7 @@ ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t rema
ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
const uint8_t* packet) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
switch (id) {
case (startracker::REQ_TIME): {
@ -832,11 +859,11 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
}
case (startracker::REQ_VERSION): {
result = handleTm(versionSet, startracker::VersionSet::SIZE);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = checkProgram();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
break;
@ -1209,7 +1236,22 @@ ReturnValue_t StarTrackerHandler::initializeLocalDataPool(localpool::DataPool& l
localDataPoolMap.emplace(startracker::DEBUG_CAMERA_TEST, new PoolEntry<uint32_t>({0}));
localDataPoolMap.emplace(startracker::CHKSUM, new PoolEntry<uint32_t>({0}));
return RETURN_OK;
poolManager.subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams(temperatureSet.getSid(), false, 10.0));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(powerSet.getSid(), false, 10.0));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(interfaceSet.getSid(), false, 10.0));
poolManager.subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams(solutionSet.getSid(), false, 5.0));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(cameraSet.getSid(), false, 10.0));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(histogramSet.getSid(), false, 10.0));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(lisaSet.getSid(), false, 10.0));
return returnvalue::OK;
}
size_t StarTrackerHandler::getNextReplyLength(DeviceCommandId_t commandId) {
@ -1219,9 +1261,9 @@ size_t StarTrackerHandler::getNextReplyLength(DeviceCommandId_t commandId) {
ReturnValue_t StarTrackerHandler::doSendReadHook() {
// Prevent DHB from polling UART during commands executed by the image loader task
if (strHelperExecuting) {
return RETURN_FAILED;
return returnvalue::FAILED;
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::getSwitches(const uint8_t** switches, uint8_t* numberOfSwitches) {
@ -1230,7 +1272,7 @@ ReturnValue_t StarTrackerHandler::getSwitches(const uint8_t** switches, uint8_t*
}
*numberOfSwitches = 1;
*switches = &powerSwitch;
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::checkMode(ActionId_t actionId) {
@ -1244,7 +1286,7 @@ ReturnValue_t StarTrackerHandler::checkMode(ActionId_t actionId) {
break;
}
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::scanForActionReply(DeviceCommandId_t* foundId) {
@ -1273,9 +1315,9 @@ ReturnValue_t StarTrackerHandler::scanForActionReply(DeviceCommandId_t* foundId)
default:
sif::warning << "StarTrackerHandler::scanForActionReply: Unknown parameter reply id"
<< std::endl;
return RETURN_FAILED;
return returnvalue::FAILED;
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::scanForSetParameterReply(DeviceCommandId_t* foundId) {
@ -1340,9 +1382,9 @@ ReturnValue_t StarTrackerHandler::scanForSetParameterReply(DeviceCommandId_t* fo
default:
sif::debug << "StarTrackerHandler::scanForParameterReply: Unknown parameter reply id"
<< std::endl;
return RETURN_FAILED;
return returnvalue::FAILED;
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::scanForGetParameterReply(DeviceCommandId_t* foundId) {
@ -1406,11 +1448,11 @@ ReturnValue_t StarTrackerHandler::scanForGetParameterReply(DeviceCommandId_t* fo
}
default: {
sif::warning << "tarTrackerHandler::scanForGetParameterReply: UnkNown ID" << std::endl;
return RETURN_FAILED;
return returnvalue::FAILED;
break;
}
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::scanForTmReply(DeviceCommandId_t* foundId) {
@ -1447,11 +1489,11 @@ ReturnValue_t StarTrackerHandler::scanForTmReply(DeviceCommandId_t* foundId) {
default: {
sif::debug << "StarTrackerHandler::scanForTmReply: Reply contains invalid reply id: "
<< static_cast<unsigned int>(*reply) << std::endl;
return RETURN_FAILED;
return returnvalue::FAILED;
break;
}
}
return RETURN_OK;
return returnvalue::OK;
}
void StarTrackerHandler::handleEvent(EventMessage* eventMessage) {
@ -1471,7 +1513,7 @@ void StarTrackerHandler::handleEvent(EventMessage* eventMessage) {
ReturnValue_t StarTrackerHandler::executeFlashReadCommand(const uint8_t* commandData,
size_t commandDataLen) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
if (commandDataLen < FlashReadCmd::MIN_LENGTH) {
sif::warning << "StarTrackerHandler::executeFlashReadCommand: Command too short" << std::endl;
return COMMAND_TOO_SHORT;
@ -1481,7 +1523,7 @@ ReturnValue_t StarTrackerHandler::executeFlashReadCommand(const uint8_t* command
size_t size = sizeof(length);
const uint8_t* lengthPtr = commandData + sizeof(startRegion);
result = SerializeAdapter::deSerialize(&length, lengthPtr, &size, SerializeIF::Endianness::BIG);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::debug << "StarTrackerHandler::executeFlashReadCommand: Deserialization of length failed"
<< std::endl;
return result;
@ -1495,7 +1537,7 @@ ReturnValue_t StarTrackerHandler::executeFlashReadCommand(const uint8_t* command
std::string fullname = std::string(reinterpret_cast<const char*>(filePtr),
commandDataLen - sizeof(startRegion) - sizeof(length));
result = strHelper->startFlashRead(fullname, startRegion, length);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
return result;
@ -1513,7 +1555,7 @@ void StarTrackerHandler::prepareBootCommand() {
ReturnValue_t StarTrackerHandler::prepareChecksumCommand(const uint8_t* commandData,
size_t commandDataLen) {
struct ChecksumActionRequest req;
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
if (commandDataLen != ChecksumCmd::LENGTH) {
sif::warning << "StarTrackerHandler::prepareChecksumCommand: Invalid length" << std::endl;
return INVALID_LENGTH;
@ -1523,7 +1565,7 @@ ReturnValue_t StarTrackerHandler::prepareChecksumCommand(const uint8_t* commandD
const uint8_t* addressPtr = commandData + ChecksumCmd::ADDRESS_OFFSET;
result =
SerializeAdapter::deSerialize(&req.address, addressPtr, &size, SerializeIF::Endianness::BIG);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::debug << "StarTrackerHandler::prepareChecksumCommand: Deserialization of address "
<< "failed" << std::endl;
return result;
@ -1532,7 +1574,7 @@ ReturnValue_t StarTrackerHandler::prepareChecksumCommand(const uint8_t* commandD
const uint8_t* lengthPtr = commandData + ChecksumCmd::LENGTH_OFFSET;
result =
SerializeAdapter::deSerialize(&req.length, lengthPtr, &size, SerializeIF::Endianness::BIG);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::debug << "StarTrackerHandler::prepareChecksumCommand: Deserialization of length failed"
<< std::endl;
return result;
@ -1591,7 +1633,7 @@ void StarTrackerHandler::preparePowerRequest() {
void StarTrackerHandler::prepareSwitchToBootloaderCmd() {
uint32_t length = 0;
struct RebootActionRequest rebootReq;
struct RebootActionRequest rebootReq {};
arc_pack_reboot_action_req(&rebootReq, commandBuffer, &length);
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
@ -1635,20 +1677,21 @@ void StarTrackerHandler::prepareHistogramRequest() {
ReturnValue_t StarTrackerHandler::prepareParamCommand(const uint8_t* commandData,
size_t commandDataLen,
ArcsecJsonParamBase& paramSet) {
ReturnValue_t result = RETURN_OK;
// Stopwatch watch;
ReturnValue_t result = returnvalue::OK;
if (commandDataLen > MAX_PATH_SIZE) {
return FILE_PATH_TOO_LONG;
}
std::string fullName(reinterpret_cast<const char*>(commandData), commandDataLen);
result = paramSet.create(fullName, commandBuffer);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
dataLinkLayer.encodeFrame(commandBuffer, paramSet.getSize());
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestCameraParams() {
@ -1657,7 +1700,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestCameraParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestLimitsParams() {
@ -1666,7 +1709,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestLimitsParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestLogLevelParams() {
@ -1675,7 +1718,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestLogLevelParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestMountingParams() {
@ -1684,7 +1727,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestMountingParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestImageProcessorParams() {
@ -1693,7 +1736,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestImageProcessorParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestCentroidingParams() {
@ -1702,7 +1745,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestCentroidingParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestLisaParams() {
@ -1711,7 +1754,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestLisaParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestMatchingParams() {
@ -1720,7 +1763,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestMatchingParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestTrackingParams() {
@ -1729,7 +1772,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestTrackingParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestValidationParams() {
@ -1738,7 +1781,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestValidationParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestAlgoParams() {
@ -1747,7 +1790,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestAlgoParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestSubscriptionParams() {
@ -1756,7 +1799,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestSubscriptionParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestLogSubscriptionParams() {
@ -1765,7 +1808,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestLogSubscriptionParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::prepareRequestDebugCameraParams() {
@ -1774,7 +1817,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestDebugCameraParams() {
dataLinkLayer.encodeFrame(commandBuffer, length);
rawPacket = dataLinkLayer.getEncodedFrame();
rawPacketLen = dataLinkLayer.getEncodedLength();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::handleSetParamReply() {
@ -1792,7 +1835,7 @@ ReturnValue_t StarTrackerHandler::handleSetParamReply() {
if (internalState != InternalState::IDLE) {
handleStartup(reply + PARAMETER_ID_OFFSET);
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::handleActionReply() {
@ -1805,13 +1848,13 @@ ReturnValue_t StarTrackerHandler::handleActionReply() {
<< static_cast<unsigned int>(status) << std::endl;
return ACTION_FAILED;
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::handleChecksumReply() {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
result = handleActionReply();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
const uint8_t* replyData = dataLinkLayer.getReply() + ACTION_DATA_OFFSET;
@ -1830,29 +1873,29 @@ ReturnValue_t StarTrackerHandler::handleChecksumReply() {
}
PoolReadGuard rg(&checksumSet);
checksumSet.checksum = checksumReply.getChecksum();
handleDeviceTM(&checksumSet, startracker::CHECKSUM);
handleDeviceTm(checksumSet, startracker::CHECKSUM);
#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1
checksumReply.printChecksum();
#endif /* OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1 */
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::handleParamRequest(LocalPoolDataSetBase& dataset, size_t size) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
result = dataset.read(TIMEOUT_TYPE, MUTEX_TIMEOUT);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
const uint8_t* reply = dataLinkLayer.getReply() + PARAMS_OFFSET;
dataset.setValidityBufferGeneration(false);
result = dataset.deSerialize(&reply, &size, SerializeIF::Endianness::LITTLE);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::warning << "StarTrackerHandler::handleParamRequest Deserialization failed" << std::endl;
}
dataset.setValidityBufferGeneration(true);
dataset.setValidity(true, true);
result = dataset.commit(TIMEOUT_TYPE, MUTEX_TIMEOUT);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1
@ -1862,7 +1905,7 @@ ReturnValue_t StarTrackerHandler::handleParamRequest(LocalPoolDataSetBase& datas
}
ReturnValue_t StarTrackerHandler::handlePingReply() {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
uint32_t pingId = 0;
const uint8_t* reply = dataLinkLayer.getReply();
uint8_t status = dataLinkLayer.getStatusField();
@ -1894,7 +1937,7 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
if (internalState == InternalState::VERIFY_BOOT) {
sif::warning << "StarTrackerHandler::checkProgram: Failed to boot firmware" << std::endl;
// Device handler will run into timeout and fall back to transition source mode
triggerEvent(BOOTING_FIRMWARE_FAILED);
triggerEvent(BOOTING_FIRMWARE_FAILED_EVENT);
internalState = InternalState::FAILED_FIRMWARE_BOOT;
} else if (internalState == InternalState::BOOTLOADER_CHECK) {
internalState = InternalState::DONE;
@ -1907,7 +1950,7 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
if (internalState == InternalState::VERIFY_BOOT) {
internalState = InternalState::LOGLEVEL;
} else if (internalState == InternalState::BOOTLOADER_CHECK) {
triggerEvent(BOOTING_BOOTLOADER_FAILED);
triggerEvent(BOOTING_BOOTLOADER_FAILED_EVENT);
internalState = InternalState::BOOTING_BOOTLOADER_FAILED;
}
break;
@ -1916,11 +1959,11 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
<< std::endl;
return INVALID_PROGRAM;
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::handleTm(LocalPoolDataSetBase& dataset, size_t size) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
uint8_t status = *(dataLinkLayer.getReply() + STATUS_OFFSET);
if (status != startracker::STATUS_OK) {
sif::warning << "StarTrackerHandler::handleTm: Reply error: "
@ -1928,19 +1971,19 @@ ReturnValue_t StarTrackerHandler::handleTm(LocalPoolDataSetBase& dataset, size_t
return REPLY_ERROR;
}
result = dataset.read(TIMEOUT_TYPE, MUTEX_TIMEOUT);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
const uint8_t* reply = dataLinkLayer.getReply() + TICKS_OFFSET;
dataset.setValidityBufferGeneration(false);
result = dataset.deSerialize(&reply, &size, SerializeIF::Endianness::LITTLE);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::warning << "StarTrackerHandler::handleTm: Deserialization failed" << std::endl;
}
dataset.setValidityBufferGeneration(true);
dataset.setValidity(true, true);
result = dataset.commit(TIMEOUT_TYPE, MUTEX_TIMEOUT);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1
@ -1950,7 +1993,7 @@ ReturnValue_t StarTrackerHandler::handleTm(LocalPoolDataSetBase& dataset, size_t
}
ReturnValue_t StarTrackerHandler::handleActionReplySet(LocalPoolDataSetBase& dataset, size_t size) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
uint8_t status = *(dataLinkLayer.getReply() + STATUS_OFFSET);
if (status != startracker::STATUS_OK) {
sif::warning << "StarTrackerHandler::handleActionReplySet: Reply error: "
@ -1958,19 +2001,19 @@ ReturnValue_t StarTrackerHandler::handleActionReplySet(LocalPoolDataSetBase& dat
return REPLY_ERROR;
}
result = dataset.read(TIMEOUT_TYPE, MUTEX_TIMEOUT);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
const uint8_t* reply = dataLinkLayer.getReply() + ACTION_DATA_OFFSET;
dataset.setValidityBufferGeneration(false);
result = dataset.deSerialize(&reply, &size, SerializeIF::Endianness::LITTLE);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::warning << "StarTrackerHandler::handleActionReplySet Deserialization failed" << std::endl;
}
dataset.setValidityBufferGeneration(true);
dataset.setValidity(true, true);
result = dataset.commit(TIMEOUT_TYPE, MUTEX_TIMEOUT);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1
@ -2067,18 +2110,18 @@ ReturnValue_t StarTrackerHandler::checkCommand(ActionId_t actionId) {
case startracker::REQ_SUBSCRIPTION:
case startracker::REQ_LOG_SUBSCRIPTION:
case startracker::REQ_DEBUG_CAMERA:
if (not(mode == MODE_ON && submode == startracker::Program::FIRMWARE)) {
if (not(getMode() == MODE_ON && getSubmode() == startracker::Program::FIRMWARE)) {
return STARTRACKER_RUNNING_BOOTLOADER;
}
break;
case startracker::FIRMWARE_UPDATE:
case startracker::FLASH_READ:
if (not(mode == MODE_ON && submode == startracker::Program::BOOTLOADER)) {
if (not(getMode() == MODE_ON && getSubmode() == startracker::Program::BOOTLOADER)) {
return STARTRACKER_RUNNING_FIRMWARE;
}
break;
default:
break;
}
return RETURN_OK;
return returnvalue::OK;
}

View File

@ -2,6 +2,9 @@
#define MISSION_DEVICES_STARTRACKERHANDLER_H_
#include <fsfw/datapool/PoolReadGuard.h>
#include <linux/devices/startracker/StarTrackerJsonCommands.h>
#include <thread>
#include "ArcsecDatalinkLayer.h"
#include "ArcsecJsonParamBase.h"
@ -35,7 +38,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
* to high to enable the device.
*/
StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
StrHelper* strHelper, power::Switch_t powerSwitch);
const char* jsonFileStr, StrHelper* strHelper, power::Switch_t powerSwitch);
virtual ~StarTrackerHandler();
ReturnValue_t initialize() override;
@ -72,7 +75,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
/**
* @brief Overwritten here to always read all available data from the UartComIF.
* @brief Overwritten here to always read all available data from theSerialComIF.
*/
virtual size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override;
virtual ReturnValue_t doSendReadHook() override;
@ -140,9 +143,9 @@ class StarTrackerHandler : public DeviceHandlerBase {
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::STR_HANDLER;
//! [EXPORT] : [COMMENT] Failed to boot firmware
static const Event BOOTING_FIRMWARE_FAILED = MAKE_EVENT(1, severity::LOW);
static const Event BOOTING_FIRMWARE_FAILED_EVENT = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] Failed to boot star tracker into bootloader mode
static const Event BOOTING_BOOTLOADER_FAILED = MAKE_EVENT(2, severity::LOW);
static const Event BOOTING_BOOTLOADER_FAILED_EVENT = MAKE_EVENT(2, severity::LOW);
static const size_t MAX_PATH_SIZE = 50;
static const size_t MAX_FILE_NAME = 30;
@ -216,15 +219,29 @@ class StarTrackerHandler : public DeviceHandlerBase {
// Loading firmware requires some time and the command will not trigger a reply when executed
Countdown bootCountdown;
#ifdef EGSE
std::string paramJsonFile = "/home/pi/arcsec/json/flight-config.json";
#else
#if OBSW_STAR_TRACKER_GROUND_CONFIG == 1
std::string paramJsonFile = "/mnt/sd0/startracker/ground-config.json";
#else
std::string paramJsonFile = "/mnt/sd0/startracker/flight-config.json";
#endif
#endif
struct JsonConfigs {
Tracking tracking;
LogLevel logLevel;
LogSubscription logSubscription;
DebugCamera debugCamera;
Algo algo;
Validation validation;
Matching matching;
Lisa lisa;
Centroiding centroiding;
Camera camera;
ImageProcessor imageProcessor;
Mounting mounting;
Limits limits;
Subscription subscription;
};
JsonConfigs jcfgs;
Countdown jcfgCountdown = Countdown(250);
bool commandExecuted = false;
std::thread jsonCfgTask;
static void setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonFile);
std::string paramJsonFile;
enum class NormalState { TEMPERATURE_REQUEST, SOLUTION_REQUEST };
@ -262,7 +279,14 @@ class StarTrackerHandler : public DeviceHandlerBase {
InternalState internalState = InternalState::IDLE;
enum class StartupState { IDLE, CHECK_PROGRAM, WAIT_CHECK_PROGRAM, BOOT_BOOTLOADER, DONE };
enum class StartupState {
IDLE,
CHECK_PROGRAM,
WAIT_CHECK_PROGRAM,
BOOT_BOOTLOADER,
WAIT_JCFG,
DONE
};
StartupState startupState = StartupState::IDLE;
@ -314,7 +338,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
* @param commandData Pointer to received command data
* @param commandDataLen Size of received command data
*
* @return RETURN_OK if start of execution was successful, otherwise error return value
* @return returnvalue::OK if start of execution was successful, otherwise error return value
*/
ReturnValue_t executeFlashReadCommand(const uint8_t* commandData, size_t commandDataLen);
@ -385,7 +409,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
* @param commandDataLen Length of command
* @param paramSet The object defining the command generation
*
* @return RETURN_OK if successful, otherwise error return Value
* @return returnvalue::OK if successful, otherwise error return Value
*/
ReturnValue_t prepareParamCommand(const uint8_t* commandData, size_t commandDataLen,
ArcsecJsonParamBase& paramSet);
@ -454,7 +478,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
* @param dataset Dataset where reply data will be written to
* @param size Size of the dataset
*
* @return RETURN_OK if successful, otherwise error return value
* @return returnvalue::OK if successful, otherwise error return value
*/
ReturnValue_t handleTm(LocalPoolDataSetBase& dataset, size_t size);
@ -463,7 +487,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
*
* @param actioId Id of received command
*
* @return RETURN_OK if star tracker is in valid mode, otherwise error return value
* @return returnvalue::OK if star tracker is in valid mode, otherwise error return value
*/
ReturnValue_t checkCommand(ActionId_t actionId);

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,12 @@
#include "StrHelper.h"
#include <fsfw/filesystem/HasFileSystemIF.h>
#include <filesystem>
#include <fstream>
#include "OBSWConfig.h"
#include "eive/definitions.h"
#include "fsfw/timemanager/Countdown.h"
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
#include "mission/utility/Filenaming.h"
@ -19,14 +22,14 @@ ReturnValue_t StrHelper::initialize() {
sdcMan = SdCardManager::instance();
if (sdcMan == nullptr) {
sif::warning << "StrHelper::initialize: Invalid SD Card Manager" << std::endl;
return RETURN_FAILED;
return returnvalue::FAILED;
}
#endif
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
semaphore.acquire();
while (true) {
switch (internalState) {
@ -36,7 +39,7 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
}
case InternalState::UPLOAD_IMAGE: {
result = performImageUpload();
if (result == RETURN_OK) {
if (result == returnvalue::OK) {
triggerEvent(IMAGE_UPLOAD_SUCCESSFUL);
} else {
triggerEvent(IMAGE_UPLOAD_FAILED);
@ -46,7 +49,7 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
}
case InternalState::DOWNLOAD_IMAGE: {
result = performImageDownload();
if (result == RETURN_OK) {
if (result == returnvalue::OK) {
triggerEvent(IMAGE_DOWNLOAD_SUCCESSFUL);
} else {
triggerEvent(IMAGE_DOWNLOAD_FAILED);
@ -56,7 +59,7 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
}
case InternalState::FLASH_READ: {
result = performFlashRead();
if (result == RETURN_OK) {
if (result == returnvalue::OK) {
triggerEvent(FLASH_READ_SUCCESSFUL);
} else {
triggerEvent(FLASH_READ_FAILED);
@ -66,7 +69,7 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
}
case InternalState::FIRMWARE_UPDATE: {
result = performFirmwareUpdate();
if (result == RETURN_OK) {
if (result == returnvalue::OK) {
triggerEvent(FIRMWARE_UPDATE_SUCCESSFUL);
} else {
triggerEvent(FIRMWARE_UPDATE_FAILED);
@ -82,12 +85,12 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
}
ReturnValue_t StrHelper::setComIF(DeviceCommunicationIF* communicationInterface_) {
uartComIF = dynamic_cast<UartComIF*>(communicationInterface_);
uartComIF = dynamic_cast<SerialComIF*>(communicationInterface_);
if (uartComIF == nullptr) {
sif::warning << "StrHelper::initialize: Invalid uart com if" << std::endl;
return RETURN_FAILED;
return returnvalue::FAILED;
}
return RETURN_OK;
return returnvalue::OK;
}
void StrHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
@ -95,7 +98,7 @@ void StrHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
ReturnValue_t StrHelper::startImageUpload(std::string fullname) {
#ifdef XIPHOS_Q7S
ReturnValue_t result = checkPath(fullname);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
#endif
@ -106,13 +109,13 @@ ReturnValue_t StrHelper::startImageUpload(std::string fullname) {
internalState = InternalState::UPLOAD_IMAGE;
semaphore.release();
terminate = false;
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StrHelper::startImageDownload(std::string path) {
#ifdef XIPHOS_Q7S
ReturnValue_t result = checkPath(path);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
#endif
@ -123,7 +126,7 @@ ReturnValue_t StrHelper::startImageDownload(std::string path) {
internalState = InternalState::DOWNLOAD_IMAGE;
terminate = false;
semaphore.release();
return RETURN_OK;
return returnvalue::OK;
}
void StrHelper::stopProcess() { terminate = true; }
@ -135,7 +138,7 @@ void StrHelper::setFlashReadFilename(std::string filename) { flashRead.filename
ReturnValue_t StrHelper::startFirmwareUpdate(std::string fullname) {
#ifdef XIPHOS_Q7S
ReturnValue_t result = checkPath(fullname);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
#endif
@ -148,13 +151,13 @@ ReturnValue_t StrHelper::startFirmwareUpdate(std::string fullname) {
internalState = InternalState::FIRMWARE_UPDATE;
semaphore.release();
terminate = false;
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StrHelper::startFlashRead(std::string path, uint8_t startRegion, uint32_t length) {
#ifdef XIPHOS_Q7S
ReturnValue_t result = checkPath(path);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
#endif
@ -167,7 +170,7 @@ ReturnValue_t StrHelper::startFlashRead(std::string path, uint8_t startRegion, u
internalState = InternalState::FLASH_READ;
semaphore.release();
terminate = false;
return RETURN_OK;
return returnvalue::OK;
}
void StrHelper::disableTimestamping() { timestamping = false; }
@ -175,6 +178,11 @@ void StrHelper::disableTimestamping() { timestamping = false; }
void StrHelper::enableTimestamping() { timestamping = true; }
ReturnValue_t StrHelper::performImageDownload() {
#ifdef XIPHOS_Q7S
if (not sdcMan->getActiveSdCard()) {
return HasFileSystemIF::FILESYSTEM_INACTIVE;
}
#endif
ReturnValue_t result;
#if OBSW_DEBUG_STARTRACKER == 1
ProgressPrinter progressPrinter("Image download", ImageDownload::LAST_POSITION);
@ -192,11 +200,11 @@ ReturnValue_t StrHelper::performImageDownload() {
while (downloadReq.position < ImageDownload::LAST_POSITION) {
if (terminate) {
file.close();
return RETURN_OK;
return returnvalue::OK;
}
arc_pack_download_action_req(&downloadReq, commandBuffer, &size);
result = sendAndRead(size, downloadReq.position);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
uartComIF->flushUartRxBuffer(comCookie);
retries++;
@ -206,7 +214,7 @@ ReturnValue_t StrHelper::performImageDownload() {
return result;
}
result = checkActionReply();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
uartComIF->flushUartRxBuffer(comCookie);
retries++;
@ -216,7 +224,7 @@ ReturnValue_t StrHelper::performImageDownload() {
return result;
}
result = checkReplyPosition(downloadReq.position);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
uartComIF->flushUartRxBuffer(comCookie);
retries++;
@ -234,20 +242,25 @@ ReturnValue_t StrHelper::performImageDownload() {
retries = 0;
}
file.close();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StrHelper::performImageUpload() {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
uint32_t size = 0;
uint32_t imageSize = 0;
struct UploadActionRequest uploadReq;
uploadReq.position = 0;
#ifdef XIPHOS_Q7S
if (not sdcMan->getActiveSdCard()) {
return HasFileSystemIF::FILESYSTEM_INACTIVE;
}
#endif
std::memset(&uploadReq.data, 0, sizeof(uploadReq.data));
if (not std::filesystem::exists(uploadImage.uploadFile)) {
triggerEvent(STR_HELPER_FILE_NOT_EXISTS, static_cast<uint32_t>(internalState));
internalState = InternalState::IDLE;
return RETURN_FAILED;
return returnvalue::FAILED;
}
std::ifstream file(uploadImage.uploadFile, std::ifstream::binary);
// Set position of next character to end of file input stream
@ -260,18 +273,18 @@ ReturnValue_t StrHelper::performImageUpload() {
while ((uploadReq.position + 1) * SIZE_IMAGE_PART < imageSize) {
if (terminate) {
file.close();
return RETURN_OK;
return returnvalue::OK;
}
file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg);
file.read(reinterpret_cast<char*>(uploadReq.data), SIZE_IMAGE_PART);
arc_pack_upload_action_req(&uploadReq, commandBuffer, &size);
result = sendAndRead(size, uploadReq.position);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
file.close();
return RETURN_FAILED;
return returnvalue::FAILED;
}
result = checkActionReply();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
file.close();
return result;
}
@ -288,25 +301,25 @@ ReturnValue_t StrHelper::performImageUpload() {
uploadReq.position++;
arc_pack_upload_action_req(&uploadReq, commandBuffer, &size);
result = sendAndRead(size, uploadReq.position);
if (result != RETURN_OK) {
return RETURN_FAILED;
if (result != returnvalue::OK) {
return returnvalue::FAILED;
}
result = checkActionReply();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
#if OBSW_DEBUG_STARTRACKER == 1
progressPrinter.print((uploadReq.position + 1) * SIZE_IMAGE_PART);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StrHelper::performFirmwareUpdate() {
using namespace startracker;
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
result = unlockAndEraseRegions(static_cast<uint32_t>(startracker::FirmwareRegions::FIRST),
static_cast<uint32_t>(startracker::FirmwareRegions::LAST));
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = performFlashWrite();
@ -314,7 +327,12 @@ ReturnValue_t StrHelper::performFirmwareUpdate() {
}
ReturnValue_t StrHelper::performFlashWrite() {
ReturnValue_t result = RETURN_OK;
#ifdef XIPHOS_Q7S
if (not sdcMan->getActiveSdCard()) {
return HasFileSystemIF::FILESYSTEM_INACTIVE;
}
#endif
ReturnValue_t result = returnvalue::OK;
uint32_t size = 0;
uint32_t bytesWritten = 0;
uint32_t fileSize = 0;
@ -322,14 +340,14 @@ ReturnValue_t StrHelper::performFlashWrite() {
if (not std::filesystem::exists(flashWrite.fullname)) {
triggerEvent(STR_HELPER_FILE_NOT_EXISTS, static_cast<uint32_t>(internalState));
internalState = InternalState::IDLE;
return RETURN_FAILED;
return returnvalue::FAILED;
}
std::ifstream file(flashWrite.fullname, std::ifstream::binary);
file.seekg(0, file.end);
fileSize = file.tellg();
if (fileSize > FLASH_REGION_SIZE * (flashWrite.lastRegion - flashWrite.firstRegion)) {
sif::warning << "StrHelper::performFlashWrite: Invalid file" << std::endl;
return RETURN_FAILED;
return returnvalue::FAILED;
}
#if OBSW_DEBUG_STARTRACKER == 1
ProgressPrinter progressPrinter("Flash write", fileSize);
@ -341,7 +359,7 @@ ReturnValue_t StrHelper::performFlashWrite() {
for (uint32_t idx = 0; idx < fileChunks; idx++) {
if (terminate) {
file.close();
return RETURN_OK;
return returnvalue::OK;
}
file.seekg(idx * CHUNK_SIZE, file.beg);
file.read(reinterpret_cast<char*>(req.data), CHUNK_SIZE);
@ -352,12 +370,12 @@ ReturnValue_t StrHelper::performFlashWrite() {
req.address = bytesWritten;
arc_pack_write_action_req(&req, commandBuffer, &size);
result = sendAndRead(size, req.address);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
file.close();
return result;
}
result = checkActionReply();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
file.close();
return result;
}
@ -379,20 +397,25 @@ ReturnValue_t StrHelper::performFlashWrite() {
bytesWritten += remainingBytes;
arc_pack_write_action_req(&req, commandBuffer, &size);
result = sendAndRead(size, req.address);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
result = checkActionReply();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
return result;
}
#if OBSW_DEBUG_STARTRACKER == 1
progressPrinter.print(fileSize);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StrHelper::performFlashRead() {
#ifdef XIPHOS_Q7S
if (not sdcMan->getActiveSdCard()) {
return HasFileSystemIF::FILESYSTEM_INACTIVE;
}
#endif
ReturnValue_t result;
#if OBSW_DEBUG_STARTRACKER == 1
ProgressPrinter progressPrinter("Flash read", flashRead.size);
@ -412,7 +435,7 @@ ReturnValue_t StrHelper::performFlashRead() {
req.address = 0;
while (bytesRead < flashRead.size) {
if (terminate) {
return RETURN_OK;
return returnvalue::OK;
}
if ((flashRead.size - bytesRead) < CHUNK_SIZE) {
req.length = flashRead.size - bytesRead;
@ -421,7 +444,7 @@ ReturnValue_t StrHelper::performFlashRead() {
}
arc_pack_read_action_req(&req, commandBuffer, &size);
result = sendAndRead(size, req.address);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
uartComIF->flushUartRxBuffer(comCookie);
retries++;
@ -431,7 +454,7 @@ ReturnValue_t StrHelper::performFlashRead() {
return result;
}
result = checkActionReply();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
uartComIF->flushUartRxBuffer(comCookie);
retries++;
@ -454,12 +477,12 @@ ReturnValue_t StrHelper::performFlashRead() {
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
}
file.close();
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StrHelper::sendAndRead(size_t size, uint32_t parameter, uint32_t delayMs) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t decResult = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
ReturnValue_t decResult = returnvalue::OK;
size_t receivedDataLen = 0;
uint8_t* receivedData = nullptr;
size_t bytesLeft = 0;
@ -467,10 +490,10 @@ ReturnValue_t StrHelper::sendAndRead(size_t size, uint32_t parameter, uint32_t d
datalinkLayer.encodeFrame(commandBuffer, size);
result = uartComIF->sendMessage(comCookie, datalinkLayer.getEncodedFrame(),
datalinkLayer.getEncodedLength());
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::warning << "StrHelper::sendAndRead: Failed to send packet" << std::endl;
triggerEvent(STR_HELPER_SENDING_PACKET_FAILED, result, parameter);
return RETURN_FAILED;
return returnvalue::FAILED;
}
decResult = ArcsecDatalinkLayer::DEC_IN_PROGRESS;
while (decResult == ArcsecDatalinkLayer::DEC_IN_PROGRESS) {
@ -479,23 +502,23 @@ ReturnValue_t StrHelper::sendAndRead(size_t size, uint32_t parameter, uint32_t d
while (delay.isBusy()) {
}
result = uartComIF->requestReceiveMessage(comCookie, startracker::MAX_FRAME_SIZE * 2 + 2);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::warning << "StrHelper::sendAndRead: Failed to request reply" << std::endl;
triggerEvent(STR_HELPER_REQUESTING_MSG_FAILED, result, parameter);
return RETURN_FAILED;
return returnvalue::FAILED;
}
result = uartComIF->readReceivedMessage(comCookie, &receivedData, &receivedDataLen);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::warning << "StrHelper::sendAndRead: Failed to read received message" << std::endl;
triggerEvent(STR_HELPER_READING_REPLY_FAILED, result, parameter);
return RETURN_FAILED;
return returnvalue::FAILED;
}
if (receivedDataLen == 0 && missedReplies < MAX_POLLS) {
missedReplies++;
continue;
} else if ((receivedDataLen == 0) && (missedReplies >= MAX_POLLS)) {
triggerEvent(STR_HELPER_NO_REPLY, parameter);
return RETURN_FAILED;
return returnvalue::FAILED;
} else {
missedReplies = 0;
}
@ -504,14 +527,14 @@ ReturnValue_t StrHelper::sendAndRead(size_t size, uint32_t parameter, uint32_t d
// This should never happen
sif::warning << "StrHelper::sendAndRead: Bytes left after decoding" << std::endl;
triggerEvent(STR_HELPER_COM_ERROR, result, parameter);
return RETURN_FAILED;
return returnvalue::FAILED;
}
}
if (decResult != RETURN_OK) {
if (decResult != returnvalue::OK) {
triggerEvent(STR_HELPER_DEC_ERROR, decResult, parameter);
return RETURN_FAILED;
return returnvalue::FAILED;
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StrHelper::checkActionReply() {
@ -526,7 +549,7 @@ ReturnValue_t StrHelper::checkActionReply() {
<< static_cast<unsigned int>(status) << std::endl;
return STATUS_ERROR;
}
return RETURN_OK;
return returnvalue::OK;
}
ReturnValue_t StrHelper::checkReplyPosition(uint32_t expectedPosition) {
@ -534,32 +557,31 @@ ReturnValue_t StrHelper::checkReplyPosition(uint32_t expectedPosition) {
std::memcpy(&receivedPosition, datalinkLayer.getReply() + POS_OFFSET, sizeof(receivedPosition));
if (receivedPosition != expectedPosition) {
triggerEvent(POSITION_MISMATCH, receivedPosition);
return RETURN_FAILED;
return returnvalue::FAILED;
}
return RETURN_OK;
return returnvalue::OK;
}
#ifdef XIPHOS_Q7S
ReturnValue_t StrHelper::checkPath(std::string name) {
if (name.substr(0, sizeof(SdCardManager::SD_0_MOUNT_POINT)) ==
std::string(SdCardManager::SD_0_MOUNT_POINT)) {
if (!sdcMan->isSdCardMounted(sd::SLOT_0)) {
if (name.substr(0, sizeof(config::SD_0_MOUNT_POINT)) == std::string(config::SD_0_MOUNT_POINT)) {
if (!sdcMan->isSdCardUsable(sd::SLOT_0)) {
sif::warning << "StrHelper::checkPath: SD card 0 not mounted" << std::endl;
return SD_NOT_MOUNTED;
}
} else if (name.substr(0, sizeof(SdCardManager::SD_1_MOUNT_POINT)) ==
std::string(SdCardManager::SD_1_MOUNT_POINT)) {
if (!sdcMan->isSdCardMounted(sd::SLOT_0)) {
} else if (name.substr(0, sizeof(config::SD_1_MOUNT_POINT)) ==
std::string(config::SD_1_MOUNT_POINT)) {
if (!sdcMan->isSdCardUsable(sd::SLOT_0)) {
sif::warning << "StrHelper::checkPath: SD card 1 not mounted" << std::endl;
return SD_NOT_MOUNTED;
}
}
return RETURN_OK;
return returnvalue::OK;
}
#endif
ReturnValue_t StrHelper::unlockAndEraseRegions(uint32_t from, uint32_t to) {
ReturnValue_t result = RETURN_OK;
ReturnValue_t result = returnvalue::OK;
#if OBSW_DEBUG_STARTRACKER == 1
ProgressPrinter progressPrinter("Unlock and erase", to - from);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
@ -572,7 +594,7 @@ ReturnValue_t StrHelper::unlockAndEraseRegions(uint32_t from, uint32_t to) {
arc_pack_unlock_action_req(&unlockReq, commandBuffer, &size);
sendAndRead(size, unlockReq.region);
result = checkActionReply();
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::warning << "StrHelper::unlockAndEraseRegions: Failed to unlock region with id "
<< static_cast<unsigned int>(unlockReq.region) << std::endl;
return result;
@ -580,7 +602,7 @@ ReturnValue_t StrHelper::unlockAndEraseRegions(uint32_t from, uint32_t to) {
eraseReq.region = idx;
arc_pack_erase_action_req(&eraseReq, commandBuffer, &size);
result = sendAndRead(size, eraseReq.region, FLASH_ERASE_DELAY);
if (result != RETURN_OK) {
if (result != returnvalue::OK) {
sif::warning << "StrHelper::unlockAndEraseRegions: Failed to erase region with id "
<< static_cast<unsigned int>(eraseReq.region) << std::endl;
return result;

View File

@ -7,15 +7,15 @@
#include "OBSWConfig.h"
#ifdef XIPHOS_Q7S
#include "bsp_q7s/memory/SdCardManager.h"
#include "bsp_q7s/fs/SdCardManager.h"
#endif
#include "fsfw/devicehandlers/CookieIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/osal/linux/BinarySemaphore.h"
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw_hal/linux/uart/UartComIF.h"
#include "fsfw_hal/linux/serial/SerialComIF.h"
extern "C" {
#include "thirdparty/arcsec_star_tracker/client/generated/actionreq.h"
@ -27,7 +27,7 @@ extern "C" {
*
* @author J. Meier
*/
class StrHelper : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF {
class StrHelper : public SystemObject, public ExecutableObjectIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::STR_HELPER;
@ -255,7 +255,7 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
* UART communication object responsible for low level access of star tracker
* Must be set by star tracker handler
*/
UartComIF* uartComIF = nullptr;
SerialComIF* uartComIF = nullptr;
// Communication cookie. Must be set by the star tracker handler
CookieIF* comCookie = nullptr;
@ -270,7 +270,7 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
/**
* @brief Performs firmware update
*
* @return RETURN_OK if successful, otherwise error return value
* @return returnvalue::OK if successful, otherwise error return value
*/
ReturnValue_t performFirmwareUpdate();
@ -289,7 +289,7 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
*
* @param ID of first region to write to
*
* @return RETURN_OK if successful, otherwise RETURN_FAILED
* @return returnvalue::OK if successful, otherwise returnvalue::FAILED
*/
ReturnValue_t performFlashWrite();
@ -307,14 +307,14 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
* @param parameter Parameter 2 of trigger event function
* @param delayMs Delay in milliseconds between send and receive call
*
* @return RETURN_OK if successful, otherwise RETURN_FAILED
* @return returnvalue::OK if successful, otherwise returnvalue::FAILED
*/
ReturnValue_t sendAndRead(size_t size, uint32_t parameter, uint32_t delayMs = 0);
/**
* @brief Checks the header (type id and status fields) of the action reply
*
* @return RETURN_OK if reply confirms success of packet transfer, otherwise REUTRN_FAILED
* @return returnvalue::OK if reply confirms success of packet transfer, otherwise REUTRN_FAILED
*/
ReturnValue_t checkActionReply();
@ -323,7 +323,8 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
*
* @param expectedPosition Value of expected position
*
* @return RETURN_OK if received position matches expected position, otherwise RETURN_FAILED
* @return returnvalue::OK if received position matches expected position, otherwise
* returnvalue::FAILED
*/
ReturnValue_t checkReplyPosition(uint32_t expectedPosition);
@ -331,7 +332,7 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
/**
* @brief Checks if a path points to an sd card and whether the SD card is monuted.
*
* @return SD_NOT_MOUNTED id SD card is not mounted, otherwise RETURN_OK
* @return SD_NOT_MOUNTED id SD card is not mounted, otherwise returnvalue::OK
*/
ReturnValue_t checkPath(std::string name);
#endif