Variable STR CFG path #824

Merged
muellerr merged 7 commits from str-variable-cfg-path-q7s into main 2023-11-29 14:09:10 +01:00
14 changed files with 126 additions and 29 deletions

View File

@ -16,6 +16,18 @@ will consitute of a breaking change warranting a new major release:
# [unreleased]
## Fixed
- STR config path was previously hardcoded to `/mnt/sd0/startracker/flight-config.json`.
A new abstraction was introduces which now uses the active SD card to build the correct
config path when initializing the star tracker.
## Added
- Introduced a new `RELOAD_JSON_CFG_FILE` command for the STR to reload the JSON configuration
data based on the current output of the config file path getter function. A reboot of the
device is still necessary to load the configuration to the STR.
# [v7.3.0] 2023-11-07
## Changed
@ -696,7 +708,7 @@ This is the version which will fly on the satellite for the initial launch phase
This gives other tasks some time to register the SD cards being unusable, and therefore provides
a way for them to perform any re-initialization tasks necessary after SD card switches.
- TCS controller now only has an OFF mode and an ON mode
- The TCS controller pauses operations related to the TCS board assembly (reading sensors and
- The TCS controller pauses operations related to the TCS board assembly (reading sensors and
the primary control loop) while a TCS board recovery is on-going.
- Allow specifying custom OBSW update filename. This allowed keeping a cleaner file structure
where each update has a name including the version
@ -1761,8 +1773,8 @@ Syrlinks PR: PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/353
- Syrlinks Handler: Read RX frequency shift as 24 bit signed number now. Also include
validity handling for datasets.
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/350
- `GyroADIS1650XHandler`: Changed calculation of angular rate to be sensitivity based instead of
max. range based, as previous fix still left an margin of error between ADIS16505 sensors
- `GyroADIS1650XHandler`: Changed calculation of angular rate to be sensitivity based instead of
max. range based, as previous fix still left an margin of error between ADIS16505 sensors
and L3GD20 sensors.
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/346

View File

@ -25,3 +25,4 @@ add_subdirectory(memory)
add_subdirectory(callbacks)
add_subdirectory(xadc)
add_subdirectory(fs)
add_subdirectory(acs)

View File

@ -0,0 +1 @@
# target_sources(${OBSW_NAME} PUBLIC <Source File List>)

View File

@ -0,0 +1,23 @@
#include <optional>
#include "bsp_q7s/fs/SdCardManager.h"
#include "mission/acs/str/strHelpers.h"
class StrConfigPathGetter : public startracker::SdCardConfigPathGetter {
public:
StrConfigPathGetter(SdCardManager& sdcMan) : sdcMan(sdcMan) {}
std::optional<std::string> getCfgPath() override {
if (!sdcMan.isSdCardUsable(std::nullopt)) {
return std::nullopt;
}
if (sdcMan.getActiveSdCard() == sd::SdCard::SLOT_1) {
return std::string("/mnt/sd1/startracker/flight-config.json");
} else {
return std::string("/mnt/sd0/startracker/flight-config.json");
}
}
private:
SdCardManager& sdcMan;
};

View File

@ -152,7 +152,7 @@ void ObjectFactory::produce(void* args) {
#endif
#if OBSW_ADD_STAR_TRACKER == 1
createStrComponents(pwrSwitcher);
createStrComponents(pwrSwitcher, *SdCardManager::instance());
#endif /* OBSW_ADD_STAR_TRACKER == 1 */
#if OBSW_ADD_PL_PCDU == 1

View File

@ -109,7 +109,7 @@ void ObjectFactory::produce(void* args) {
createPayloadComponents(gpioComIF, *pwrSwitcher);
#if OBSW_ADD_STAR_TRACKER == 1
createStrComponents(pwrSwitcher);
createStrComponents(pwrSwitcher, *SdCardManager::instance());
#endif /* OBSW_ADD_STAR_TRACKER == 1 */
#if OBSW_ADD_CCSDS_IP_CORES == 1

View File

@ -37,6 +37,7 @@
#include <cstring>
#include "OBSWConfig.h"
#include "bsp_q7s/acs/StrConfigPathGetter.h"
#include "bsp_q7s/boardtest/Q7STestTask.h"
#include "bsp_q7s/callbacks/gnssCallback.h"
#include "bsp_q7s/callbacks/pcduSwitchCb.h"
@ -935,7 +936,7 @@ void ObjectFactory::createTestComponents(LinuxLibgpioIF* gpioComIF) {
#endif
}
void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher) {
void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher, SdCardManager& sdcMan) {
auto* strAssy = new StrAssembly(objects::STR_ASSY);
strAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
auto* starTrackerCookie =
@ -949,9 +950,10 @@ void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher) {
sif::error << "No valid Star Tracker parameter JSON file" << std::endl;
}
auto strFdir = new StrFdir(objects::STAR_TRACKER);
auto cfgGetter = new StrConfigPathGetter(sdcMan);
auto starTracker =
new StarTrackerHandler(objects::STAR_TRACKER, objects::STR_COM_IF, starTrackerCookie,
paramJsonFile, strComIF, power::PDU1_CH2_STAR_TRACKER_5V);
strComIF, power::PDU1_CH2_STAR_TRACKER_5V, *cfgGetter);
starTracker->setPowerSwitcher(pwrSwitcher);
starTracker->connectModeTreeParent(*strAssy);
starTracker->setCustomFdir(strFdir);

View File

@ -15,6 +15,8 @@
#include <atomic>
#include <string>
#include "bsp_q7s/fs/SdCardManager.h"
class LinuxLibgpioIF;
class SerialComIF;
class SpiComIF;
@ -75,7 +77,7 @@ void createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher, HealthTa
HeaterHandler*& heaterHandler);
void createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets, const char* i2cDev);
void createBpxBatteryComponent(bool enableHkSets, const char* i2cDev);
void createStrComponents(PowerSwitchIF* pwrSwitcher);
void createStrComponents(PowerSwitchIF* pwrSwitcher, SdCardManager& sdcMan);
void createSolarArrayDeploymentComponents(PowerSwitchIF& pwrSwitcher, GpioIF& gpioIF);
void createSyrlinksComponents(PowerSwitchIF* pwrSwitcher);
void createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF& pwrSwitcher);

2
fsfw

@ -1 +1 @@
Subproject commit cc3e64e70d90f6a2b5c59215b2569c1771e890f0
Subproject commit 41d67bff639192afa2e18a23db6801c75b4fea88

View File

@ -65,7 +65,7 @@ void ArcsecJsonParamBase::addSetParamHeader(uint8_t* buffer, uint8_t setId) {
*(buffer + 1) = setId;
}
ReturnValue_t ArcsecJsonParamBase::init(const std::string filename) {
ReturnValue_t ArcsecJsonParamBase::init(const std::string& filename) {
ReturnValue_t result = returnvalue::OK;
if (not std::filesystem::exists(filename)) {
sif::warning << "ArcsecJsonParamBase::init: JSON file " << filename << " does not exist"

View File

@ -46,7 +46,7 @@ class ArcsecJsonParamBase {
* @param return JSON_FILE_NOT_EXISTS if specified file does not exist, otherwise
* returnvalue::OK
*/
ReturnValue_t init(const std::string filename);
ReturnValue_t init(const std::string& filename);
/**
* @brief Fills a buffer with a parameter set

View File

@ -5,6 +5,8 @@
#include <mission/acs/str/strHelpers.h>
#include <mission/acs/str/strJsonCommands.h>
#include "fsfw/ipc/MessageQueueIF.h"
extern "C" {
#include <sagitta/client/actionreq.h>
#include <sagitta/client/client_tm_structs.h>
@ -24,8 +26,8 @@ extern "C" {
std::atomic_bool JCFG_DONE(false);
StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
const char* jsonFileStr, StrComHandler* strHelper,
power::Switch_t powerSwitch)
StrComHandler* strHelper, power::Switch_t powerSwitch,
startracker::SdCardConfigPathGetter& cfgPathGetter)
: DeviceHandlerBase(objectId, comIF, comCookie),
temperatureSet(this),
versionSet(this),
@ -57,8 +59,8 @@ StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF,
centroidsSet(this),
contrastSet(this),
strHelper(strHelper),
paramJsonFile(jsonFileStr),
powerSwitch(powerSwitch) {
powerSwitch(powerSwitch),
cfgPathGetter(cfgPathGetter) {
if (comCookie == nullptr) {
sif::error << "StarTrackerHandler: Invalid com cookie" << std::endl;
}
@ -82,17 +84,12 @@ void StarTrackerHandler::doStartUp() {
// the device handler's submode to the star tracker's mode
return;
case StartupState::DONE:
if (jcfgCountdown.isBusy()) {
if (!JCFG_DONE) {
startupState = StartupState::WAIT_JCFG;
return;
}
startupState = StartupState::IDLE;
break;
case StartupState::WAIT_JCFG: {
if (jcfgCountdown.hasTimedOut()) {
startupState = StartupState::IDLE;
break;
}
return;
}
default:
@ -139,8 +136,7 @@ ReturnValue_t StarTrackerHandler::initialize() {
// 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()};
reloadJsonCfgFile();
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
if (manager == nullptr) {
@ -169,6 +165,20 @@ ReturnValue_t StarTrackerHandler::initialize() {
return returnvalue::OK;
}
bool StarTrackerHandler::reloadJsonCfgFile() {
jcfgCountdown.resetTimer();
auto strCfgPath = cfgPathGetter.getCfgPath();
if (strCfgPath.has_value()) {
jcfgPending = true;
JCFG_DONE = false;
jsonCfgTask = std::thread{setUpJsonCfgs, std::ref(jcfgs), strCfgPath.value()};
return true;
}
// Simplified FDIR: Just continue as usual..
JCFG_DONE = true;
return false;
}
ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
ReturnValue_t result = returnvalue::OK;
@ -335,6 +345,24 @@ void StarTrackerHandler::performOperationHook() {
break;
}
}
if (jcfgPending) {
if (JCFG_DONE) {
if(startupState == StartupState::WAIT_JCFG) {
startupState = StartupState::DONE;
}
jsonCfgTask.join();
jcfgPending = false;
auto iter = deviceCommandMap.find(startracker::RELOAD_JSON_CFG_FILE);
if (iter != deviceCommandMap.end() and iter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) {
actionHelper.finish(true, iter->second.sendReplyTo, startracker::RELOAD_JSON_CFG_FILE);
}
} else if (jcfgCountdown.hasTimedOut()) {
auto iter = deviceCommandMap.find(startracker::RELOAD_JSON_CFG_FILE);
if (iter != deviceCommandMap.end() and iter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) {
actionHelper.finish(false, iter->second.sendReplyTo, startracker::RELOAD_JSON_CFG_FILE);
}
}
}
}
Submode_t StarTrackerHandler::getInitialSubmode() { return startracker::SUBMODE_BOOTLOADER; }
@ -499,6 +527,16 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
preparePingRequest();
return returnvalue::OK;
}
case (startracker::RELOAD_JSON_CFG_FILE): {
if (jcfgPending) {
return HasActionsIF::IS_BUSY;
}
// It should be noted that this just reloads the JSON config structure in memory from the
// JSON file. The configuration still needs to be sent to the STR. The easiest way to achieve
// this is to simply reboot the device after a reload.
reloadJsonCfgFile();
return returnvalue::OK;
}
case (startracker::SET_TIME_FROM_SYS_TIME): {
SetTimeActionRequest setTimeRequest{};
timeval tv;
@ -513,6 +551,7 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
rawPacket = commandBuffer;
return returnvalue::OK;
}
case (startracker::REQ_TIME): {
prepareTimeRequest();
return returnvalue::OK;
@ -726,6 +765,7 @@ void StarTrackerHandler::fillCommandAndReplyMap() {
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandMap(startracker::UPLOAD_IMAGE);
this->insertInCommandMap(startracker::DOWNLOAD_IMAGE);
this->insertInCommandMap(startracker::RELOAD_JSON_CFG_FILE);
this->insertInCommandAndReplyMap(startracker::REQ_POWER, 3, &powerSet,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::REQ_INTERFACE, 3, &interfaceSet,
@ -928,7 +968,7 @@ void StarTrackerHandler::bootFirmware(Mode_t toMode) {
}
}
void StarTrackerHandler::setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonFile) {
void StarTrackerHandler::setUpJsonCfgs(JsonConfigs& cfgs, std::string paramJsonFile) {
cfgs.tracking.init(paramJsonFile);
cfgs.logLevel.init(paramJsonFile);
cfgs.logSubscription.init(paramJsonFile);
@ -2811,3 +2851,5 @@ ReturnValue_t StarTrackerHandler::checkCommand(ActionId_t actionId) {
}
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::acceptExternalDeviceCommands() { return returnvalue::OK; }

View File

@ -27,7 +27,9 @@ extern "C" {
* @details Datasheet: https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/
* Arbeitsdaten/08_Used%20Components/ArcSec_KULeuven_Startracker/
* Sagitta%201.0%20Datapack&fileid=659181
* @author J. Meier
* @note The STR code is a chaotic inconsistent mess and should be re-written with a simpler base
* class. DO NOT USE THIS AS REFERENCE. Stay away from it.
* @author J. Meier, R. Mueller
*/
class StarTrackerHandler : public DeviceHandlerBase {
public:
@ -42,8 +44,8 @@ class StarTrackerHandler : public DeviceHandlerBase {
* to high to enable the device.
*/
StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
const char* jsonFileStr, StrComHandler* strHelper,
power::Switch_t powerSwitch);
StrComHandler* strHelper, power::Switch_t powerSwitch,
startracker::SdCardConfigPathGetter& cfgPathGetter);
virtual ~StarTrackerHandler();
ReturnValue_t initialize() override;
@ -240,11 +242,12 @@ class StarTrackerHandler : public DeviceHandlerBase {
Subscription subscription;
AutoThreshold autoThreshold;
};
bool jcfgPending = false;
JsonConfigs jcfgs;
Countdown jcfgCountdown = Countdown(250);
Countdown jcfgCountdown = Countdown(1000);
bool commandExecuted = false;
std::thread jsonCfgTask;
static void setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonFile);
static void setUpJsonCfgs(JsonConfigs& cfgs, std::string paramJsonFile);
std::string paramJsonFile;
@ -311,6 +314,8 @@ class StarTrackerHandler : public DeviceHandlerBase {
std::set<DeviceCommandId_t> additionalRequestedTm{};
std::set<DeviceCommandId_t>::iterator currentSecondaryTmIter;
startracker::SdCardConfigPathGetter& cfgPathGetter;
/**
* @brief Handles internal state
*/
@ -542,6 +547,8 @@ class StarTrackerHandler : public DeviceHandlerBase {
void doNormalTransition(Mode_t modeFrom, Submode_t subModeFrom);
void bootFirmware(Mode_t toMode);
void bootBootloader();
bool reloadJsonCfgFile();
ReturnValue_t acceptExternalDeviceCommands() override;
};
#endif /* MISSION_DEVICES_STARTRACKERHANDLER_H_ */

View File

@ -14,6 +14,12 @@ namespace startracker {
static const Submode_t SUBMODE_BOOTLOADER = 1;
static const Submode_t SUBMODE_FIRMWARE = 2;
class SdCardConfigPathGetter {
public:
virtual ~SdCardConfigPathGetter() = default;
virtual std::optional<std::string> getCfgPath() = 0;
};
/**
* @brief Returns the frame type field of a decoded frame.
*/
@ -381,6 +387,7 @@ static constexpr DeviceCommandId_t REQ_CENTROIDS = 94;
static constexpr DeviceCommandId_t ADD_SECONDARY_TM_TO_NORMAL_MODE = 95;
static constexpr DeviceCommandId_t RESET_SECONDARY_TM_SET = 96;
static constexpr DeviceCommandId_t READ_SECONDARY_TM_SET = 97;
static constexpr DeviceCommandId_t RELOAD_JSON_CFG_FILE = 100;
static const DeviceCommandId_t NONE = 0xFFFFFFFF;
static const uint32_t VERSION_SET_ID = REQ_VERSION;