Merge remote-tracking branch 'origin/develop' into feature_i2c_fatal_error_counter
All checks were successful
EIVE/eive-obsw/pipeline/pr-develop This commit looks good

This commit is contained in:
Robin Müller 2023-03-20 18:02:09 +01:00
commit 3e3355a926
9 changed files with 288 additions and 217 deletions

View File

@ -16,6 +16,18 @@ will consitute of a breaking change warranting a new major release:
# [unreleased] # [unreleased]
## Fixed
- Fixed transition for dual power lane assemblies: When going from dual side submode to single side
submode, perform logical commanding first, similarly to when going to OFF mode.
## Changed
- Bugfixes for STR mode transitions: Booting to mode ON with submode FIRMWARE now works properly.
Furthermore, the submode in the NORMAL mode now should be 0 instead of some ON mode submode.
- Updated GYR bias values to newest measurements. This also corrects the ADIS values to always
consit of just one digit.
# [v1.38.0] 2023-03-17 # [v1.38.0] 2023-03-17
eive-tmtc: v2.19.2 eive-tmtc: v2.19.2

2
fsfw

@ -1 +1 @@
Subproject commit 43fd0b2f59c3aeb2d3f4db10cfad56ee3709d68d Subproject commit 227524a21da755d125bcb1a5ff67bcbc452f8cf9

View File

@ -451,95 +451,99 @@ void AcsBoardPolling::gyroAdisHandler(GyroAdis& gyro) {
cdHasTimedOut = gyro.countdown.hasTimedOut(); cdHasTimedOut = gyro.countdown.hasTimedOut();
mustPerformStartup = gyro.performStartup; mustPerformStartup = gyro.performStartup;
} }
if (mode == acs::SimpleSensorMode::NORMAL and cdHasTimedOut) { if (mode == acs::SimpleSensorMode::OFF) {
if (mustPerformStartup) { return;
uint8_t regList[6]; }
// Read configuration if (not cdHasTimedOut) {
regList[0] = adis1650x::DIAG_STAT_REG; return;
regList[1] = adis1650x::FILTER_CTRL_REG; }
regList[2] = adis1650x::RANG_MDL_REG; if (mustPerformStartup) {
regList[3] = adis1650x::MSC_CTRL_REG; uint8_t regList[6];
regList[4] = adis1650x::DEC_RATE_REG; // Read configuration
regList[5] = adis1650x::PROD_ID_REG; regList[0] = adis1650x::DIAG_STAT_REG;
size_t transferLen = regList[1] = adis1650x::FILTER_CTRL_REG;
adis1650x::prepareReadCommand(regList, sizeof(regList), cmdBuf.data(), cmdBuf.size()); regList[2] = adis1650x::RANG_MDL_REG;
result = readAdisCfg(*gyro.cookie, transferLen); regList[3] = adis1650x::MSC_CTRL_REG;
if (result != returnvalue::OK) { regList[4] = adis1650x::DEC_RATE_REG;
gyro.replyResult = result; regList[5] = adis1650x::PROD_ID_REG;
return; size_t transferLen =
} adis1650x::prepareReadCommand(regList, sizeof(regList), cmdBuf.data(), cmdBuf.size());
result = spiComIF.readReceivedMessage(gyro.cookie, &rawReply, &dummy); result = readAdisCfg(*gyro.cookie, transferLen);
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) { if (result != returnvalue::OK) {
gyro.replyResult = returnvalue::FAILED; gyro.replyResult = result;
return; return;
} }
result = spiComIF.readReceivedMessage(gyro.cookie, &rawReply, &dummy); result = spiComIF.readReceivedMessage(gyro.cookie, &rawReply, &dummy);
if (result != returnvalue::OK or rawReply == nullptr) { 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; gyro.replyResult = returnvalue::FAILED;
return; 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); MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
gyro.ownReply.dataWasSet = true; gyro.ownReply.cfgWasSet = true;
gyro.ownReply.cfg.diagStat = rawReply[2] << 8 | rawReply[3]; gyro.ownReply.cfg.diagStat = (rawReply[2] << 8) | rawReply[3];
gyro.ownReply.data.angVelocities[0] = (rawReply[4] << 8) | rawReply[5]; gyro.ownReply.cfg.filterSetting = (rawReply[4] << 8) | rawReply[5];
gyro.ownReply.data.angVelocities[1] = (rawReply[6] << 8) | rawReply[7]; gyro.ownReply.cfg.rangMdl = (rawReply[6] << 8) | rawReply[7];
gyro.ownReply.data.angVelocities[2] = (rawReply[8] << 8) | rawReply[9]; gyro.ownReply.cfg.mscCtrlReg = (rawReply[8] << 8) | rawReply[9];
gyro.ownReply.cfg.decRateReg = (rawReply[10] << 8) | rawReply[11];
gyro.ownReply.data.accelerations[0] = (rawReply[10] << 8) | rawReply[11]; gyro.ownReply.cfg.prodId = prodId;
gyro.ownReply.data.accelerations[1] = (rawReply[12] << 8) | rawReply[13]; gyro.ownReply.data.sensitivity = adis1650x::rangMdlToSensitivity(gyro.ownReply.cfg.rangMdl);
gyro.ownReply.data.accelerations[2] = (rawReply[14] << 8) | rawReply[15]; gyro.performStartup = false;
gyro.ownReply.data.temperatureRaw = (rawReply[16] << 8) | rawReply[17];
} }
// 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) { void AcsBoardPolling::mgmLis3Handler(MgmLis3& mgm) {

View File

@ -268,18 +268,18 @@ void StarTrackerHandler::doStartUp() {
default: default:
return; return;
} }
setMode(_MODE_TO_ON, SUBMODE_BOOTLOADER); startupState = StartupState::DONE;
internalState = InternalState::IDLE;
setMode(_MODE_TO_ON);
} }
void StarTrackerHandler::doShutDown() { void StarTrackerHandler::doShutDown() {
// If the star tracker is shutdown also stop all running processes in the image loader task // If the star tracker is shutdown also stop all running processes in the image loader task
strHelper->stopProcess(); strHelper->stopProcess();
setMode(_MODE_POWER_DOWN);
}
void StarTrackerHandler::doOffActivity() {
startupState = StartupState::IDLE;
internalState = InternalState::IDLE; internalState = InternalState::IDLE;
startupState = StartupState::IDLE;
bootState = FwBootState::NONE;
setMode(_MODE_POWER_DOWN);
} }
ReturnValue_t StarTrackerHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { ReturnValue_t StarTrackerHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
@ -302,81 +302,103 @@ ReturnValue_t StarTrackerHandler::buildNormalDeviceCommand(DeviceCommandId_t* id
ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
switch (internalState) { switch (internalState) {
case InternalState::BOOT: case InternalState::BOOT_FIRMWARE: {
*id = startracker::BOOT; if (bootState == FwBootState::WAIT_FOR_EXECUTION or bootState == FwBootState::VERIFY_BOOT) {
bootCountdown.setTimeout(BOOT_TIMEOUT); return NOTHING_TO_SEND;
internalState = InternalState::BOOT_DELAY; }
return buildCommandFromCommand(*id, nullptr, 0); if (bootState == FwBootState::NONE) {
case InternalState::REQ_VERSION: *id = startracker::BOOT;
internalState = InternalState::VERIFY_BOOT; bootCountdown.setTimeout(BOOT_TIMEOUT);
// Again read program to check if firmware boot was successful bootState = FwBootState::BOOT_DELAY;
*id = startracker::REQ_VERSION; return buildCommandFromCommand(*id, nullptr, 0);
return buildCommandFromCommand(*id, nullptr, 0); }
case InternalState::LOGLEVEL: if (bootState == FwBootState::BOOT_DELAY) {
internalState = InternalState::WAIT_FOR_EXECUTION; if (bootCountdown.isBusy()) {
*id = startracker::LOGLEVEL; return NOTHING_TO_SEND;
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), }
paramJsonFile.size()); bootState = FwBootState::REQ_VERSION;
case InternalState::LIMITS: }
internalState = InternalState::WAIT_FOR_EXECUTION; switch (bootState) {
*id = startracker::LIMITS; case (FwBootState::REQ_VERSION): {
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), bootState = FwBootState::VERIFY_BOOT;
paramJsonFile.size()); // Again read program to check if firmware boot was successful
case InternalState::TRACKING: *id = startracker::REQ_VERSION;
internalState = InternalState::WAIT_FOR_EXECUTION; return buildCommandFromCommand(*id, nullptr, 0);
*id = startracker::TRACKING; }
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), case (FwBootState::LOGLEVEL): {
paramJsonFile.size()); bootState = FwBootState::WAIT_FOR_EXECUTION;
case InternalState::MOUNTING: *id = startracker::LOGLEVEL;
internalState = InternalState::WAIT_FOR_EXECUTION; return buildCommandFromCommand(
*id = startracker::MOUNTING; *id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), }
paramJsonFile.size()); case (FwBootState::LIMITS): {
case InternalState::IMAGE_PROCESSOR: bootState = FwBootState::WAIT_FOR_EXECUTION;
internalState = InternalState::WAIT_FOR_EXECUTION; *id = startracker::LIMITS;
*id = startracker::IMAGE_PROCESSOR; return buildCommandFromCommand(
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), *id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
paramJsonFile.size()); }
case InternalState::CAMERA: case (FwBootState::TRACKING): {
internalState = InternalState::WAIT_FOR_EXECUTION; bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::CAMERA; *id = startracker::TRACKING;
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), return buildCommandFromCommand(
paramJsonFile.size()); *id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case InternalState::CENTROIDING: }
internalState = InternalState::WAIT_FOR_EXECUTION; case FwBootState::MOUNTING:
*id = startracker::CENTROIDING; bootState = FwBootState::WAIT_FOR_EXECUTION;
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), *id = startracker::MOUNTING;
paramJsonFile.size()); return buildCommandFromCommand(
case InternalState::LISA: *id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
internalState = InternalState::WAIT_FOR_EXECUTION; case FwBootState::IMAGE_PROCESSOR:
*id = startracker::LISA; bootState = FwBootState::WAIT_FOR_EXECUTION;
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), *id = startracker::IMAGE_PROCESSOR;
paramJsonFile.size()); return buildCommandFromCommand(
case InternalState::MATCHING: *id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
internalState = InternalState::WAIT_FOR_EXECUTION; case FwBootState::CAMERA:
*id = startracker::MATCHING; bootState = FwBootState::WAIT_FOR_EXECUTION;
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), *id = startracker::CAMERA;
paramJsonFile.size()); return buildCommandFromCommand(
case InternalState::VALIDATION: *id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
internalState = InternalState::WAIT_FOR_EXECUTION; case FwBootState::CENTROIDING:
*id = startracker::VALIDATION; bootState = FwBootState::WAIT_FOR_EXECUTION;
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), *id = startracker::CENTROIDING;
paramJsonFile.size()); return buildCommandFromCommand(
case InternalState::ALGO: *id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
internalState = InternalState::WAIT_FOR_EXECUTION; case FwBootState::LISA:
*id = startracker::ALGO; bootState = FwBootState::WAIT_FOR_EXECUTION;
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), *id = startracker::LISA;
paramJsonFile.size()); return buildCommandFromCommand(
case InternalState::LOG_SUBSCRIPTION: *id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
internalState = InternalState::WAIT_FOR_EXECUTION; case FwBootState::MATCHING:
*id = startracker::LOGSUBSCRIPTION; bootState = FwBootState::WAIT_FOR_EXECUTION;
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), *id = startracker::MATCHING;
paramJsonFile.size()); return buildCommandFromCommand(
case InternalState::DEBUG_CAMERA: *id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
internalState = InternalState::WAIT_FOR_EXECUTION; case FwBootState::VALIDATION:
*id = startracker::DEBUG_CAMERA; bootState = FwBootState::WAIT_FOR_EXECUTION;
return buildCommandFromCommand(*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), *id = startracker::VALIDATION;
paramJsonFile.size()); return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::ALGO:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::ALGO;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::LOG_SUBSCRIPTION:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::LOGSUBSCRIPTION;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::DEBUG_CAMERA:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::DEBUG_CAMERA;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
default: {
sif::error << "STR: Unexpected boot state" << (int)bootState << std::endl;
return NOTHING_TO_SEND;
}
}
}
case InternalState::BOOT_BOOTLOADER: case InternalState::BOOT_BOOTLOADER:
internalState = InternalState::BOOTLOADER_CHECK; internalState = InternalState::BOOTLOADER_CHECK;
*id = startracker::SWITCH_TO_BOOTLOADER_PROGRAM; *id = startracker::SWITCH_TO_BOOTLOADER_PROGRAM;
@ -707,6 +729,15 @@ void StarTrackerHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
void StarTrackerHandler::doOnTransition(Submode_t subModeFrom) { void StarTrackerHandler::doOnTransition(Submode_t subModeFrom) {
uint8_t dhbSubmode = getSubmode(); uint8_t dhbSubmode = getSubmode();
// We hide that the transition to submode firmware actually goes through the submode bootloader.
// This is because the startracker always starts in bootloader mode but we want to allow direct
// transitions to firmware mode.
if (startupState == StartupState::DONE) {
subModeFrom = SUBMODE_BOOTLOADER;
}
if (dhbSubmode == SUBMODE_NONE) {
bootFirmware(MODE_ON);
}
if (dhbSubmode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_FIRMWARE) { if (dhbSubmode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_FIRMWARE) {
bootBootloader(); bootBootloader();
} else if (dhbSubmode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_FIRMWARE) { } else if (dhbSubmode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_FIRMWARE) {
@ -736,19 +767,23 @@ void StarTrackerHandler::doNormalTransition(Mode_t modeFrom, Submode_t subModeFr
void StarTrackerHandler::bootFirmware(Mode_t toMode) { void StarTrackerHandler::bootFirmware(Mode_t toMode) {
switch (internalState) { switch (internalState) {
case InternalState::IDLE: case InternalState::IDLE:
internalState = InternalState::BOOT; sif::info << "STR: Booting to firmware mode" << std::endl;
internalState = InternalState::BOOT_FIRMWARE;
break; break;
case InternalState::BOOT_DELAY: case InternalState::BOOT_FIRMWARE:
if (bootCountdown.hasTimedOut()) {
internalState = InternalState::REQ_VERSION;
}
break; break;
case InternalState::FAILED_FIRMWARE_BOOT: case InternalState::FAILED_FIRMWARE_BOOT:
internalState = InternalState::IDLE; internalState = InternalState::IDLE;
break; break;
case InternalState::DONE: case InternalState::DONE:
setMode(toMode); if (toMode == MODE_NORMAL) {
setMode(toMode, 0);
} else {
setMode(toMode, SUBMODE_FIRMWARE);
}
sif::info << "STR: Firmware boot success" << std::endl;
internalState = InternalState::IDLE; internalState = InternalState::IDLE;
startupState = StartupState::IDLE;
break; break;
default: default:
return; return;
@ -776,10 +811,11 @@ void StarTrackerHandler::setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonF
void StarTrackerHandler::bootBootloader() { void StarTrackerHandler::bootBootloader() {
if (internalState == InternalState::IDLE) { if (internalState == InternalState::IDLE) {
internalState = InternalState::BOOT_BOOTLOADER; internalState = InternalState::BOOT_BOOTLOADER;
} else if (internalState == InternalState::BOOTING_BOOTLOADER_FAILED) { } else if (internalState == InternalState::FAILED_BOOTLOADER_BOOT) {
internalState = InternalState::IDLE; internalState = InternalState::IDLE;
} else if (internalState == InternalState::DONE) { } else if (internalState == InternalState::DONE) {
internalState = InternalState::IDLE; internalState = InternalState::IDLE;
startupState = StartupState::IDLE;
setMode(MODE_ON); setMode(MODE_ON);
} }
} }
@ -1934,7 +1970,7 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
if (startupState == StartupState::WAIT_CHECK_PROGRAM) { if (startupState == StartupState::WAIT_CHECK_PROGRAM) {
startupState = StartupState::DONE; startupState = StartupState::DONE;
} }
if (internalState == InternalState::VERIFY_BOOT) { if (bootState == FwBootState::VERIFY_BOOT) {
sif::warning << "StarTrackerHandler::checkProgram: Failed to boot firmware" << std::endl; sif::warning << "StarTrackerHandler::checkProgram: Failed to boot firmware" << std::endl;
// Device handler will run into timeout and fall back to transition source mode // Device handler will run into timeout and fall back to transition source mode
triggerEvent(BOOTING_FIRMWARE_FAILED_EVENT); triggerEvent(BOOTING_FIRMWARE_FAILED_EVENT);
@ -1947,11 +1983,11 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
if (startupState == StartupState::WAIT_CHECK_PROGRAM) { if (startupState == StartupState::WAIT_CHECK_PROGRAM) {
startupState = StartupState::BOOT_BOOTLOADER; startupState = StartupState::BOOT_BOOTLOADER;
} }
if (internalState == InternalState::VERIFY_BOOT) { if (bootState == FwBootState::VERIFY_BOOT) {
internalState = InternalState::LOGLEVEL; bootState = FwBootState::LOGLEVEL;
} else if (internalState == InternalState::BOOTLOADER_CHECK) { } else if (internalState == InternalState::BOOTLOADER_CHECK) {
triggerEvent(BOOTING_BOOTLOADER_FAILED_EVENT); triggerEvent(BOOTING_BOOTLOADER_FAILED_EVENT);
internalState = InternalState::BOOTING_BOOTLOADER_FAILED; internalState = InternalState::FAILED_BOOTLOADER_BOOT;
} }
break; break;
default: default:
@ -2025,54 +2061,55 @@ ReturnValue_t StarTrackerHandler::handleActionReplySet(LocalPoolDataSetBase& dat
void StarTrackerHandler::handleStartup(const uint8_t* parameterId) { void StarTrackerHandler::handleStartup(const uint8_t* parameterId) {
switch (*parameterId) { switch (*parameterId) {
case (startracker::ID::LOG_LEVEL): { case (startracker::ID::LOG_LEVEL): {
internalState = InternalState::LIMITS; bootState = FwBootState::LIMITS;
break; break;
} }
case (startracker::ID::LIMITS): { case (startracker::ID::LIMITS): {
internalState = InternalState::TRACKING; bootState = FwBootState::TRACKING;
break; break;
} }
case (startracker::ID::TRACKING): { case (startracker::ID::TRACKING): {
internalState = InternalState::MOUNTING; bootState = FwBootState::MOUNTING;
break; break;
} }
case (startracker::ID::MOUNTING): { case (startracker::ID::MOUNTING): {
internalState = InternalState::IMAGE_PROCESSOR; bootState = FwBootState::IMAGE_PROCESSOR;
break; break;
} }
case (startracker::ID::IMAGE_PROCESSOR): { case (startracker::ID::IMAGE_PROCESSOR): {
internalState = InternalState::CAMERA; bootState = FwBootState::CAMERA;
break; break;
} }
case (startracker::ID::CAMERA): { case (startracker::ID::CAMERA): {
internalState = InternalState::CENTROIDING; bootState = FwBootState::CENTROIDING;
break; break;
} }
case (startracker::ID::CENTROIDING): { case (startracker::ID::CENTROIDING): {
internalState = InternalState::LISA; bootState = FwBootState::LISA;
break; break;
} }
case (startracker::ID::LISA): { case (startracker::ID::LISA): {
internalState = InternalState::MATCHING; bootState = FwBootState::MATCHING;
break; break;
} }
case (startracker::ID::MATCHING): { case (startracker::ID::MATCHING): {
internalState = InternalState::VALIDATION; bootState = FwBootState::VALIDATION;
break; break;
} }
case (startracker::ID::VALIDATION): { case (startracker::ID::VALIDATION): {
internalState = InternalState::ALGO; bootState = FwBootState::ALGO;
break; break;
} }
case (startracker::ID::ALGO): { case (startracker::ID::ALGO): {
internalState = InternalState::LOG_SUBSCRIPTION; bootState = FwBootState::LOG_SUBSCRIPTION;
break; break;
} }
case (startracker::ID::LOG_SUBSCRIPTION): { case (startracker::ID::LOG_SUBSCRIPTION): {
internalState = InternalState::DEBUG_CAMERA; bootState = FwBootState::DEBUG_CAMERA;
break; break;
} }
case (startracker::ID::DEBUG_CAMERA): { case (startracker::ID::DEBUG_CAMERA): {
bootState = FwBootState::NONE;
internalState = InternalState::DONE; internalState = InternalState::DONE;
break; break;
} }

View File

@ -60,7 +60,6 @@ class StarTrackerHandler : public DeviceHandlerBase {
protected: protected:
void doStartUp() override; void doStartUp() override;
void doShutDown() override; void doShutDown() override;
void doOffActivity() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t* id) override; ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t* id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t* id) override; ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t* id) override;
void fillCommandAndReplyMap() override; void fillCommandAndReplyMap() override;
@ -247,14 +246,31 @@ class StarTrackerHandler : public DeviceHandlerBase {
NormalState normalState = NormalState::TEMPERATURE_REQUEST; NormalState normalState = NormalState::TEMPERATURE_REQUEST;
enum class StartupState {
IDLE,
CHECK_PROGRAM,
WAIT_CHECK_PROGRAM,
BOOT_BOOTLOADER,
WAIT_JCFG,
DONE
};
StartupState startupState = StartupState::IDLE;
enum class InternalState { enum class InternalState {
IDLE, IDLE,
BOOT, BOOT_FIRMWARE,
DONE,
FAILED_FIRMWARE_BOOT,
BOOT_BOOTLOADER,
BOOTLOADER_CHECK,
FAILED_BOOTLOADER_BOOT
};
enum class FwBootState {
NONE,
BOOT_DELAY,
REQ_VERSION, REQ_VERSION,
VERIFY_BOOT, VERIFY_BOOT,
STARTUP_CHECK,
BOOT_DELAY,
FIRMWARE_CHECK,
LOGLEVEL, LOGLEVEL,
LIMITS, LIMITS,
TRACKING, TRACKING,
@ -270,26 +286,11 @@ class StarTrackerHandler : public DeviceHandlerBase {
LOG_SUBSCRIPTION, LOG_SUBSCRIPTION,
DEBUG_CAMERA, DEBUG_CAMERA,
WAIT_FOR_EXECUTION, WAIT_FOR_EXECUTION,
DONE,
FAILED_FIRMWARE_BOOT,
BOOT_BOOTLOADER,
BOOTLOADER_CHECK,
BOOTING_BOOTLOADER_FAILED
}; };
FwBootState bootState = FwBootState::NONE;
InternalState internalState = InternalState::IDLE; InternalState internalState = InternalState::IDLE;
enum class StartupState {
IDLE,
CHECK_PROGRAM,
WAIT_CHECK_PROGRAM,
BOOT_BOOTLOADER,
WAIT_JCFG,
DONE
};
StartupState startupState = StartupState::IDLE;
bool strHelperExecuting = false; bool strHelperExecuting = false;
const power::Switch_t powerSwitch = power::NO_SWITCH; const power::Switch_t powerSwitch = power::NO_SWITCH;

View File

@ -768,10 +768,10 @@ class AcsParameters : public HasParametersIF {
double gyr2orientationMatrix[3][3] = {{0, 0, -1}, {0, -1, 0}, {-1, 0, 0}}; double gyr2orientationMatrix[3][3] = {{0, 0, -1}, {0, -1, 0}, {-1, 0, 0}};
double gyr3orientationMatrix[3][3] = {{0, 0, -1}, {0, 1, 0}, {1, 0, 0}}; double gyr3orientationMatrix[3][3] = {{0, 0, -1}, {0, 1, 0}, {1, 0, 0}};
double gyr0bias[3] = {0.06318149743589743, 0.4283235025641024, -0.16383500000000004}; double gyr0bias[3] = {0.0, 0.4, -0.1};
double gyr1bias[3] = {-0.12855128205128205, 1.6737307692307695, 1.031724358974359}; double gyr1bias[3] = {0.0956745283018868, 2.0854575471698116, 1.2505990566037737};
double gyr2bias[3] = {0.15039212820512823, 0.7094475589743591, -0.22298363589743594}; double gyr2bias[3] = {0.1, 0.7, -0.2};
double gyr3bias[3] = {0.0021730769230769217, -0.6655897435897435, 0.034096153846153845}; double gyr3bias[3] = {-0.10721698113207549, -0.6111650943396226, 0.1716462264150944};
/* var = sigma^2, sigma = RND*sqrt(freq), following values are RND^2 and not var as freq is /* var = sigma^2, sigma = RND*sqrt(freq), following values are RND^2 and not var as freq is
* assumed to be equal for the same class of sensors */ * assumed to be equal for the same class of sensors */

View File

@ -65,10 +65,7 @@ ReturnValue_t GyrAdis1650XHandler::buildTransitionDeviceCommand(DeviceCommandId_
} }
case (InternalState::SHUTDOWN): { case (InternalState::SHUTDOWN): {
*id = adis1650x::REQUEST; *id = adis1650x::REQUEST;
acs::Adis1650XRequest *request = reinterpret_cast<acs::Adis1650XRequest *>(cmdBuf.data()); return preparePeriodicRequest(acs::SimpleSensorMode::OFF);
request->mode = acs::SimpleSensorMode::OFF;
request->type = adisType;
return returnvalue::OK;
} }
default: { default: {
return NOTHING_TO_SEND; return NOTHING_TO_SEND;

View File

@ -34,10 +34,17 @@ void DualLaneAssemblyBase::performChildOperation() {
} }
void DualLaneAssemblyBase::startTransition(Mode_t mode, Submode_t submode) { void DualLaneAssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
// doStartTransition(mode, submode);
using namespace duallane; using namespace duallane;
pwrStateMachine.reset(); pwrStateMachine.reset();
if (mode != MODE_OFF) { if (mode != MODE_OFF) {
// Special exception: A transition from dual side to single mode must be handled like
// going OFF.
if ((this->mode == MODE_ON or this->mode == DeviceHandlerIF::MODE_NORMAL) and
this->submode == DUAL_MODE and submode != DUAL_MODE) {
dualToSingleSideTransition = true;
AssemblyBase::startTransition(mode, submode);
return;
}
// If anything other than MODE_OFF is commanded, perform power state machine first // If anything other than MODE_OFF is commanded, perform power state machine first
// Cache the target modes, required by power state machine // Cache the target modes, required by power state machine
pwrStateMachine.start(mode, submode); pwrStateMachine.start(mode, submode);
@ -75,9 +82,13 @@ ReturnValue_t DualLaneAssemblyBase::pwrStateMachineWrapper() {
// Will be called for transitions to MODE_OFF, where everything is done after power switching // Will be called for transitions to MODE_OFF, where everything is done after power switching
finishModeOp(); finishModeOp();
} else if (opCode == OpCodes::TO_NOT_OFF_DONE) { } else if (opCode == OpCodes::TO_NOT_OFF_DONE) {
// Will be called for transitions from MODE_OFF to anything else, where the mode still has if (dualToSingleSideTransition) {
// to be commanded after power switching finishModeOp();
AssemblyBase::startTransition(targetMode, targetSubmode); } else {
// Will be called for transitions from MODE_OFF to anything else, where the mode still has
// to be commanded after power switching
AssemblyBase::startTransition(targetMode, targetSubmode);
}
} else if (opCode == OpCodes::TIMEOUT_OCCURED) { } else if (opCode == OpCodes::TIMEOUT_OCCURED) {
if (powerRetryCounter == 0) { if (powerRetryCounter == 0) {
powerRetryCounter++; powerRetryCounter++;
@ -118,6 +129,13 @@ void DualLaneAssemblyBase::handleModeReached() {
// Ignore failures for now. // Ignore failures for now.
pwrStateMachineWrapper(); pwrStateMachineWrapper();
} else { } else {
// For dual to single side transition, devices should be logically off, but the switch
// handling still needs to be done.
if (dualToSingleSideTransition) {
pwrStateMachine.start(targetMode, targetSubmode);
pwrStateMachineWrapper();
return;
}
finishModeOp(); finishModeOp();
} }
} }
@ -229,6 +247,7 @@ void DualLaneAssemblyBase::finishModeOp() {
pwrStateMachine.reset(); pwrStateMachine.reset();
powerRetryCounter = 0; powerRetryCounter = 0;
tryingOtherSide = false; tryingOtherSide = false;
dualToSingleSideTransition = false;
dualModeErrorSwitch = true; dualModeErrorSwitch = true;
} }

View File

@ -31,6 +31,7 @@ class DualLaneAssemblyBase : public AssemblyBase, public ConfirmsFailuresIF {
uint8_t powerRetryCounter = 0; uint8_t powerRetryCounter = 0;
bool tryingOtherSide = false; bool tryingOtherSide = false;
bool dualModeErrorSwitch = true; bool dualModeErrorSwitch = true;
bool dualToSingleSideTransition = false;
duallane::Submodes defaultSubmode = duallane::Submodes::A_SIDE; duallane::Submodes defaultSubmode = duallane::Submodes::A_SIDE;
enum RecoveryCustomStates { enum RecoveryCustomStates {