Merge pull request 'PDEC Config Persistent' (#398) from meier/pdec-config-persistent into develop
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good

Reviewed-on: #398
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
This commit is contained in:
Robin Müller 2023-02-27 18:33:51 +01:00
commit 8e5adae8ef
22 changed files with 683 additions and 161 deletions

View File

@ -30,7 +30,6 @@
#include <dummies/CoreControllerDummy.h> #include <dummies/CoreControllerDummy.h>
#include "dummies/helpers.h" #include "dummies/helpers.h"
#include "mission/utility/GlobalConfigHandler.h"
#ifdef PLATFORM_UNIX #ifdef PLATFORM_UNIX
#include <fsfw_hal/linux/serial/SerialComIF.h> #include <fsfw_hal/linux/serial/SerialComIF.h>

View File

@ -394,7 +394,7 @@ ReturnValue_t CoreController::sdStateMachine() {
sdInfo.cycleCount = 0; sdInfo.cycleCount = 0;
return true; return true;
} else if (sdInfo.cycleCount > 4) { } else if (sdInfo.cycleCount > 4) {
sif::warning << "CoreController::sdInitStateMachine: " << opPrintout << " takes too long" sif::warning << "CoreController::sdStateMachine: " << opPrintout << " takes too long"
<< std::endl; << std::endl;
return false; return false;
} }
@ -406,7 +406,7 @@ ReturnValue_t CoreController::sdStateMachine() {
// Create updated status file // Create updated status file
result = sdcMan->updateSdCardStateFile(); result = sdcMan->updateSdCardStateFile();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
sif::warning << "CoreController::initialize: Updating SD card state file failed" sif::warning << "CoreController::sdStateMachine: Updating SD card state file failed"
<< std::endl; << std::endl;
} }
sdInfo.commandExecuted = true; sdInfo.commandExecuted = true;

View File

@ -40,6 +40,7 @@
#include "linux/ipcore/PdecHandler.h" #include "linux/ipcore/PdecHandler.h"
#include "linux/ipcore/Ptme.h" #include "linux/ipcore/Ptme.h"
#include "linux/ipcore/PtmeConfig.h" #include "linux/ipcore/PtmeConfig.h"
#include "mission/config/configfile.h"
#include "mission/csp/CspCookie.h" #include "mission/csp/CspCookie.h"
#include "mission/system/fdir/AcsBoardFdir.h" #include "mission/system/fdir/AcsBoardFdir.h"
#include "mission/system/fdir/GomspacePowerFdir.h" #include "mission/system/fdir/GomspacePowerFdir.h"
@ -53,6 +54,7 @@
#include "mission/system/tree/comModeTree.h" #include "mission/system/tree/comModeTree.h"
#include "mission/system/tree/payloadModeTree.h" #include "mission/system/tree/payloadModeTree.h"
#include "mission/system/tree/tcsModeTree.h" #include "mission/system/tree/tcsModeTree.h"
#include "mission/utility/GlobalConfigHandler.h"
#include "tmtc/pusIds.h" #include "tmtc/pusIds.h"
#if OBSW_TEST_LIBGPIOD == 1 #if OBSW_TEST_LIBGPIOD == 1
#include "linux/boardtest/LibgpiodTest.h" #include "linux/boardtest/LibgpiodTest.h"

View File

@ -22,7 +22,7 @@ ReturnValue_t FilesystemHelper::checkPath(std::string path) {
} }
} else if (path.substr(0, sizeof(config::SD_1_MOUNT_POINT)) == } else if (path.substr(0, sizeof(config::SD_1_MOUNT_POINT)) ==
std::string(config::SD_1_MOUNT_POINT)) { std::string(config::SD_1_MOUNT_POINT)) {
if (!sdcMan->isSdCardUsable(sd::SLOT_0)) { if (!sdcMan->isSdCardUsable(sd::SLOT_1)) {
sif::warning << "FilesystemHelper::checkPath: SD card 1 not mounted" << std::endl; sif::warning << "FilesystemHelper::checkPath: SD card 1 not mounted" << std::endl;
return SD_NOT_MOUNTED; return SD_NOT_MOUNTED;
} }

View File

@ -1 +1 @@
target_sources(${OBSW_NAME} PRIVATE scratchApi.cpp) target_sources(${OBSW_NAME} PRIVATE scratchApi.cpp LocalParameterHandler.cpp)

View File

@ -0,0 +1,41 @@
#include "LocalParameterHandler.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
LocalParameterHandler::LocalParameterHandler(std::string sdRelativeName, SdCardMountedIF* sdcMan)
: NVMParameterBase(), sdRelativeName(sdRelativeName), sdcMan(sdcMan) {}
LocalParameterHandler::~LocalParameterHandler() {}
ReturnValue_t LocalParameterHandler::initialize() {
ReturnValue_t result = updateFullName();
if (result != returnvalue::OK) {
return result;
}
result = readJsonFile();
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
ReturnValue_t LocalParameterHandler::writeJsonFile() {
ReturnValue_t result = updateFullName();
if (result != returnvalue::OK) {
return result;
}
return NVMParameterBase::writeJsonFile();
}
ReturnValue_t LocalParameterHandler::updateFullName() {
std::string mountPrefix;
auto activeSd = sdcMan->getActiveSdCard();
if (activeSd and sdcMan->isSdCardUsable(activeSd.value())) {
mountPrefix = sdcMan->getCurrentMountPrefix();
} else {
return SD_NOT_READY;
}
std::string fullname = mountPrefix + "/" + sdRelativeName;
NVMParameterBase::setFullName(fullname);
return returnvalue::OK;
}

View File

@ -0,0 +1,106 @@
#ifndef BSP_Q7S_MEMORY_LOCALPARAMETERHANDLER_H_
#define BSP_Q7S_MEMORY_LOCALPARAMETERHANDLER_H_
#include <mission/memory/NVMParameterBase.h>
#include <mission/memory/SdCardMountedIF.h>
#include <string>
/**
* @brief Class to handle persistent parameters
*
*/
class LocalParameterHandler : public NVMParameterBase {
public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_PARAM_HANDLER;
static constexpr ReturnValue_t SD_NOT_READY = returnvalue::makeCode(INTERFACE_ID, 0);
/**
* @brief Constructor
*
* @param sdRelativeName Absolute name of json file relative to mount
* directory of SD card.
* E.g. conf/example.json
* @param sdcMan Pointer to SD card manager
*/
LocalParameterHandler(std::string sdRelativeName, SdCardMountedIF* sdcMan);
virtual ~LocalParameterHandler();
/**
* @brief Will initialize the local parameter handler
*
* @return OK if successful, otherwise error return value
*/
ReturnValue_t initialize();
/**
* @brief Function to add parameter to json file. If the json file does
* not yet exist it will be created here.
*
* @param key The string to identify the parameter
* @param value The value to set for this parameter
*
* @return OK if successful, otherwise error return value
*
* @details The function will add the parameter only if it is not already
* present in the json file
*/
template <typename T>
ReturnValue_t addParameter(std::string key, T value);
/**
* @brief Function will update a parameter which already exists in the json
* file
*
* @param key The unique string to identify the parameter to update
* @param value The new new value to set
*
* @return OK if successful, otherwise error return value
*/
template <typename T>
ReturnValue_t updateParameter(std::string key, T value);
private:
// Name relative to mount point of SD card where parameters will be stored
std::string sdRelativeName;
SdCardMountedIF* sdcMan;
virtual ReturnValue_t writeJsonFile();
/**
* @brief This function sets the name of the json file dependent on the
* currently active SD card
*
* @return OK if successful, otherwise error return value
*/
ReturnValue_t updateFullName();
};
template <typename T>
inline ReturnValue_t LocalParameterHandler::addParameter(std::string key, T value) {
ReturnValue_t result = insertValue(key, value);
if (result != returnvalue::OK) {
return result;
}
result = writeJsonFile();
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
template <typename T>
inline ReturnValue_t LocalParameterHandler::updateParameter(std::string key, T value) {
ReturnValue_t result = setValue(key, value);
if (result != returnvalue::OK) {
return result;
}
result = writeJsonFile();
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
#endif /* BSP_Q7S_MEMORY_LOCALPARAMETERHANDLER_H_ */

View File

@ -36,8 +36,9 @@ enum : uint8_t {
SCEX_HANDLER = 138, SCEX_HANDLER = 138,
CONFIGHANDLER = 139, CONFIGHANDLER = 139,
CORE = 140, CORE = 140,
PERSISTENT_TM_STORE = 141, TCS_CONTROLLER = 141,
TCS_CONTROLLER = 142, COM_SUBSYSTEM = 142,
PERSISTENT_TM_STORE = 143,
COMMON_SUBSYSTEM_ID_END COMMON_SUBSYSTEM_ID_END
}; };

View File

@ -40,6 +40,8 @@ enum commonClassIds : uint8_t {
ACS_SAFE, // ACSSAF ACS_SAFE, // ACSSAF
ACS_PTG, // ACSPTG ACS_PTG, // ACSPTG
ACS_DETUMBLE, // ACSDTB ACS_DETUMBLE, // ACSDTB
SD_CARD_MANAGER, // SDMA
LOCAL_PARAM_HANDLER, // LPH
COMMON_CLASS_ID_END // [EXPORT] : [END] COMMON_CLASS_ID_END // [EXPORT] : [END]
}; };
} }

View File

@ -13,9 +13,8 @@
namespace CLASS_ID { namespace CLASS_ID {
enum { enum {
CLASS_ID_START = COMMON_CLASS_ID_END, CLASS_ID_START = COMMON_CLASS_ID_END,
SD_CARD_MANAGER, // SDMA SCRATCH_BUFFER, // SCBU
SCRATCH_BUFFER, // SCBU CLASS_ID_END // [EXPORT] : [END]
CLASS_ID_END // [EXPORT] : [END]
}; };
} }

View File

@ -1,12 +1,120 @@
#include "PdecConfig.h" #include "PdecConfig.h"
#include "fsfw/filesystem/HasFileSystemIF.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
#include "pdecconfigdefs.h"
PdecConfig::PdecConfig() { initialize(); } PdecConfig::PdecConfig()
: localParameterHandler("conf/pdecconfig.json", SdCardManager::instance()) {}
PdecConfig::~PdecConfig() {} PdecConfig::~PdecConfig() {}
void PdecConfig::initialize() { void PdecConfig::setMemoryBaseAddress(uint32_t* memoryBaseAddress_) {
memoryBaseAddress = memoryBaseAddress_;
}
ReturnValue_t PdecConfig::write() {
if (memoryBaseAddress == nullptr) {
sif::error << "PdecConfig::write: Memory base address not set" << std::endl;
return returnvalue::FAILED;
}
ReturnValue_t result = initializePersistentParameters();
if (result != returnvalue::OK) {
return result;
}
result = writeFrameHeaderFirstOctet();
if (result != returnvalue::OK) {
return result;
}
result = writeFrameHeaderSecondOctet();
if (result != returnvalue::OK) {
return result;
}
writeMapConfig();
return returnvalue::OK;
}
ReturnValue_t PdecConfig::initializePersistentParameters() {
ReturnValue_t result = localParameterHandler.initialize();
if (result == HasFileSystemIF::FILE_DOES_NOT_EXIST) {
result = createPersistentConfig();
if (result != returnvalue::OK) {
return result;
}
}
return result;
}
ReturnValue_t PdecConfig::createPersistentConfig() {
ReturnValue_t result = localParameterHandler.addParameter(
pdecconfigdefs::paramkeys::POSITIVE_WINDOW, pdecconfigdefs::defaultvalue::positiveWindow);
if (result != returnvalue::OK) {
sif::error << "PdecConfig::createPersistentConfig: Failed to set positive window" << std::endl;
return result;
}
result = localParameterHandler.addParameter(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW,
pdecconfigdefs::defaultvalue::negativeWindow);
if (result != returnvalue::OK) {
sif::error << "PdecConfig::createPersistentConfig: Failed to set negative window" << std::endl;
return result;
}
return returnvalue::OK;
}
uint32_t PdecConfig::getImrReg() {
return static_cast<uint32_t>(enableNewFarIrq << 2) |
static_cast<uint32_t>(enableTcAbortIrq << 1) | static_cast<uint32_t>(enableTcNewIrq);
}
ReturnValue_t PdecConfig::setPositiveWindow(uint8_t pw) {
if (memoryBaseAddress == nullptr) {
sif::error << "PdecConfig::setPositiveWindow: Memory base address not set" << std::endl;
return returnvalue::FAILED;
}
ReturnValue_t result =
localParameterHandler.updateParameter(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, pw);
if (result != returnvalue::OK) {
return result;
}
// Rewrite second config word which contains the positive window parameter
writeFrameHeaderSecondOctet();
return returnvalue::OK;
}
ReturnValue_t PdecConfig::setNegativeWindow(uint8_t nw) {
if (memoryBaseAddress == nullptr) {
sif::error << "PdecConfig::setPositiveWindow: Memory base address not set" << std::endl;
return returnvalue::FAILED;
}
ReturnValue_t result =
localParameterHandler.updateParameter(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, nw);
if (result != returnvalue::OK) {
return result;
}
// Rewrite second config word which contains the negative window parameter
writeFrameHeaderSecondOctet();
return returnvalue::OK;
}
ReturnValue_t PdecConfig::getPositiveWindow(uint8_t& positiveWindow) {
ReturnValue_t result =
localParameterHandler.getValue(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, positiveWindow);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
ReturnValue_t PdecConfig::getNegativeWindow(uint8_t& negativeWindow) {
ReturnValue_t result =
localParameterHandler.getValue(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, negativeWindow);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
ReturnValue_t PdecConfig::writeFrameHeaderFirstOctet() {
uint32_t word = 0; uint32_t word = 0;
word |= (VERSION_ID << 30); word |= (VERSION_ID << 30);
@ -19,24 +127,65 @@ void PdecConfig::initialize() {
word |= (SPACECRAFT_ID << 16); word |= (SPACECRAFT_ID << 16);
word |= (VIRTUAL_CHANNEL << 10); word |= (VIRTUAL_CHANNEL << 10);
word |= (DUMMY_BITS << 8); word |= (DUMMY_BITS << 8);
word |= POSITIVE_WINDOW; uint8_t positiveWindow = 0;
configWords[0] = word; ReturnValue_t result =
localParameterHandler.getValue(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, positiveWindow);
if (result != returnvalue::OK) {
return result;
}
word |= static_cast<uint32_t>(positiveWindow);
*(memoryBaseAddress + FRAME_HEADER_OFFSET) = word;
return returnvalue::OK;
}
ReturnValue_t PdecConfig::writeFrameHeaderSecondOctet() {
uint8_t negativeWindow = 0;
ReturnValue_t result =
localParameterHandler.getValue(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, negativeWindow);
if (result != returnvalue::OK) {
return result;
}
uint32_t word = 0;
word = 0; word = 0;
word |= (static_cast<uint32_t>(NEGATIVE_WINDOW) << 24); word |= (static_cast<uint32_t>(negativeWindow) << 24);
word |= (HIGH_AU_MAP_ID << 16); word |= (HIGH_AU_MAP_ID << 16);
word |= (ENABLE_DERANDOMIZER << 8); word |= (ENABLE_DERANDOMIZER << 8);
configWords[1] = word; *(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = word;
return returnvalue::OK;
} }
uint32_t PdecConfig::getConfigWord(uint8_t wordNo) { void PdecConfig::writeMapConfig() {
if (wordNo >= CONFIG_WORDS_NUM) { // Configure all MAP IDs as invalid
sif::error << "PdecConfig::getConfigWord: Invalid word number" << std::endl; for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
return 0; *(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + idx / 4) =
NO_DESTINATION << 24 | NO_DESTINATION << 16 | NO_DESTINATION << 8 | NO_DESTINATION;
}
// All TCs with MAP ID 7 will be routed to the PM module (can then be read from memory)
uint8_t routeToPm = calcMapAddrEntry(PM_BUFFER);
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + 1) =
(NO_DESTINATION << 24) | (NO_DESTINATION << 16) | (NO_DESTINATION << 8) | routeToPm;
// Write map id clock frequencies
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
*(memoryBaseAddress + MAP_CLK_FREQ_OFFSET + idx / 4) =
MAP_CLK_FREQ << 24 | MAP_CLK_FREQ << 16 | MAP_CLK_FREQ << 8 | MAP_CLK_FREQ;
} }
return configWords[wordNo];
} }
uint32_t PdecConfig::getImrReg() { uint8_t PdecConfig::calcMapAddrEntry(uint8_t moduleId) {
return static_cast<uint32_t>(enableNewFarIrq << 2) | uint8_t lutEntry = 0;
static_cast<uint32_t>(enableTcAbortIrq << 1) | static_cast<uint32_t>(enableTcNewIrq); uint8_t parity = getOddParity(moduleId | (1 << VALID_POSITION));
lutEntry = (parity << PARITY_POSITION) | (1 << VALID_POSITION) | moduleId;
return lutEntry;
}
uint8_t PdecConfig::getOddParity(uint8_t number) {
uint8_t parityBit = 0;
uint8_t countBits = 0;
for (unsigned int idx = 0; idx < sizeof(number) * 8; idx++) {
countBits += (number >> idx) & 0x1;
}
parityBit = ~(countBits & 0x1) & 0x1;
return parityBit;
} }

View File

@ -1,30 +1,53 @@
#ifndef LINUX_OBC_PDECCONFIG_H_ #ifndef LINUX_OBC_PDECCONFIG_H_
#define LINUX_OBC_PDECCONFIG_H_ #define LINUX_OBC_PDECCONFIG_H_
#include <cstring> #include <string>
#include "bsp_q7s/fs/SdCardManager.h"
#include "bsp_q7s/memory/LocalParameterHandler.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
#include "pdec.h"
/** /**
* @brief This class generates the configuration words for the configuration memory of the PDEC * @brief This class generates the configuration words for the configuration memory of the PDEC
* IP Cores. * IP Cores.
* *
* @details Fields are initialized according to pecification in PDEC datasheet section 6.11.3.1 * @details Fields are initialized according to specification in PDEC datasheet section 6.11.3.1
* PROM usage. * PROM usage.
* *
* @author J. Meier * @author J. Meier
*/ */
class PdecConfig { class PdecConfig {
public: public:
/**
* @brief Constructor
*/
PdecConfig(); PdecConfig();
virtual ~PdecConfig(); virtual ~PdecConfig();
/** /**
* @brief Returns the configuration word by specifying the position. * @brief Sets the memory base address pointer
*/
void setMemoryBaseAddress(uint32_t* memoryBaseAddress_);
/**
* @brief Will write the config to the PDEC configuration memory. New config
* becomes active after resetting PDEC.
*/
ReturnValue_t write();
/**
* @brief Returns the value to write to the interrupt mask register. This
* value defines which interrupts should be enabled/disabled.
*/ */
uint32_t getConfigWord(uint8_t wordNo);
uint32_t getImrReg(); uint32_t getImrReg();
ReturnValue_t setPositiveWindow(uint8_t pw);
ReturnValue_t setNegativeWindow(uint8_t nw);
ReturnValue_t getPositiveWindow(uint8_t& positiveWindow);
ReturnValue_t getNegativeWindow(uint8_t& negativeWindow);
private: private:
// TC transfer frame configuration parameters // TC transfer frame configuration parameters
static const uint8_t VERSION_ID = 0; static const uint8_t VERSION_ID = 0;
@ -36,21 +59,73 @@ class PdecConfig {
static const uint8_t RESERVED_FIELD_A = 0; static const uint8_t RESERVED_FIELD_A = 0;
static const uint16_t SPACECRAFT_ID = 0x3DC; static const uint16_t SPACECRAFT_ID = 0x3DC;
static const uint16_t DUMMY_BITS = 0; static const uint16_t DUMMY_BITS = 0;
// Parameters to control the FARM for AD frames
// Set here for future use
static const uint8_t POSITIVE_WINDOW = 10;
static const uint8_t NEGATIVE_WINDOW = 151;
static const uint8_t HIGH_AU_MAP_ID = 0xF; static const uint8_t HIGH_AU_MAP_ID = 0xF;
static const uint8_t ENABLE_DERANDOMIZER = 1; static const uint8_t ENABLE_DERANDOMIZER = 1;
static const uint8_t CONFIG_WORDS_NUM = 2; static const uint8_t CONFIG_WORDS_NUM = 2;
// 0x200 / 4 = 0x80
static const uint32_t FRAME_HEADER_OFFSET = 0x80;
static const uint32_t MAP_ADDR_LUT_OFFSET = 0xA0;
static const uint32_t MAP_CLK_FREQ_OFFSET = 0x90;
// MAP clock frequency. Must be a value between 1 and 13 otherwise the TC segment will be
// discarded
static const uint8_t MAP_CLK_FREQ = 2;
static const uint8_t MAX_MAP_ADDR = 63;
// Writing this to the map address in the look up table will invalidate a MAP ID.
static const uint8_t NO_DESTINATION = 0;
static const uint8_t VALID_POSITION = 6;
static const uint8_t PARITY_POSITION = 7;
/**
* TCs with map addresses (also know as Map IDs) assigned to this channel will be stored in
* the PDEC memory.
*/
static const uint8_t PM_BUFFER = 7;
uint32_t* memoryBaseAddress = nullptr;
// Pointer to object providing access to persistent configuration parameters
LocalParameterHandler localParameterHandler;
uint32_t configWords[CONFIG_WORDS_NUM]; uint32_t configWords[CONFIG_WORDS_NUM];
bool enableTcNewIrq = true; bool enableTcNewIrq = true;
bool enableTcAbortIrq = true; bool enableTcAbortIrq = true;
bool enableNewFarIrq = true; bool enableNewFarIrq = true;
void initialize(); ReturnValue_t initializePersistentParameters();
/**
* @brief If the json file containing the persistent config parameters does
* not exist it will be created here.
*/
ReturnValue_t createPersistentConfig();
ReturnValue_t writeFrameHeaderFirstOctet();
ReturnValue_t writeFrameHeaderSecondOctet();
void writeMapConfig();
/**
* @brief This function calculates the entry for the configuration of the MAP ID routing.
*
* @param mapAddr The MAP ID to configure
* @param moduleId The destination module where all TCs with the map id mapAddr will be routed
* to.
*
* @details The PDEC has different modules where the TCs can be routed to. A lookup table is
* used which links the MAP ID field to the destination module. The entry for this
* lookup table is created by this function and must be stored in the configuration
* memory region of the PDEC. The entry has a specific format
*/
uint8_t calcMapAddrEntry(uint8_t moduleId);
/**
* @brief This functions calculates the odd parity of the bits in number.
*
* @param number The number from which to calculate the odd parity.
*/
uint8_t getOddParity(uint8_t number);
}; };
#endif /* LINUX_OBC_PDECCONFIG_H_ */ #endif /* LINUX_OBC_PDECCONFIG_H_ */

View File

@ -29,7 +29,8 @@ PdecHandler::PdecHandler(object_id_t objectId, object_id_t tcDestinationId,
gpioComIF(gpioComIF), gpioComIF(gpioComIF),
pdecReset(pdecReset), pdecReset(pdecReset),
actionHelper(this, nullptr), actionHelper(this, nullptr),
uioNames(names) { uioNames(names),
paramHelper(this) {
auto mqArgs = MqArgs(objectId, static_cast<void*>(this)); auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue( commandQueue = QueueFactory::instance()->createMessageQueue(
QUEUE_SIZE, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs); QUEUE_SIZE, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
@ -62,6 +63,8 @@ ReturnValue_t PdecHandler::initialize() {
result = configMemMapper.getMappedAdress(&memoryBaseAddress, UioMapper::Permissions::READ_WRITE); result = configMemMapper.getMappedAdress(&memoryBaseAddress, UioMapper::Permissions::READ_WRITE);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} else {
pdecConfig.setMemoryBaseAddress(memoryBaseAddress);
} }
UioMapper ramMapper(uioNames.ramMemory); UioMapper ramMapper(uioNames.ramMemory);
result = ramMapper.getMappedAdress(&ramBaseAddress, UioMapper::Permissions::READ_WRITE); result = ramMapper.getMappedAdress(&ramBaseAddress, UioMapper::Permissions::READ_WRITE);
@ -73,12 +76,34 @@ ReturnValue_t PdecHandler::initialize() {
sif::error << "Can not use IRQ mode if IRQ UIO name is invalid" << std::endl; sif::error << "Can not use IRQ mode if IRQ UIO name is invalid" << std::endl;
return returnvalue::FAILED; return returnvalue::FAILED;
} }
PdecConfig pdecConfig;
writePdecConfigDuringReset(pdecConfig); result = actionHelper.initialize(commandQueue);
if (result != returnvalue::OK) {
return result;
}
result = paramHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
ReturnValue_t PdecHandler::firstLoop() {
ReturnValue_t result = pdecConfig.write();
if (result != returnvalue::OK) {
if (result == LocalParameterHandler::SD_NOT_READY) {
return result;
} else {
sif::error << "PdecHandler::firstLoop: Failed to write PDEC config" << std::endl;
}
return returnvalue::FAILED;
}
result = releasePdec(); result = releasePdec();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return ObjectManagerIF::CHILD_INIT_FAILED; return returnvalue::FAILED;
} }
// This configuration must be done while the PDEC is not held in reset. // This configuration must be done while the PDEC is not held in reset.
@ -86,11 +111,12 @@ ReturnValue_t PdecHandler::initialize() {
// Configure interrupt mask register to enable interrupts // Configure interrupt mask register to enable interrupts
*(registerBaseAddress + PDEC_IMR_OFFSET) = pdecConfig.getImrReg(); *(registerBaseAddress + PDEC_IMR_OFFSET) = pdecConfig.getImrReg();
} }
result = actionHelper.initialize(commandQueue); result = resetFarStatFlag();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
// Requires reconfiguration and reinitialization of PDEC
triggerEvent(INVALID_FAR);
return result; return result;
} }
return returnvalue::OK; return returnvalue::OK;
} }
@ -104,26 +130,28 @@ ReturnValue_t PdecHandler::performOperation(uint8_t operationCode) {
} }
ReturnValue_t PdecHandler::polledOperation() { ReturnValue_t PdecHandler::polledOperation() {
ReturnValue_t result = returnvalue::OK;
readCommandQueue(); readCommandQueue();
switch (state) { switch (state) {
case State::INIT: case State::INIT: {
resetFarStatFlag(); handleInitState();
if (result != returnvalue::OK) {
// Requires reconfiguration and reinitialization of PDEC
triggerEvent(INVALID_FAR);
state = State::WAIT_FOR_RECOVERY;
break;
}
state = State::RUNNING;
break; break;
case State::RUNNING: }
case State::RUNNING: {
if (newTcReceived()) { if (newTcReceived()) {
handleNewTc(); handleNewTc();
} }
checkLocks(); checkLocks();
break; break;
}
case State::PDEC_RESET: {
ReturnValue_t result = pdecToReset();
if (result != returnvalue::OK) {
triggerEvent(PDEC_RESET_FAILED);
}
state = State::INIT;
break;
}
case State::WAIT_FOR_RECOVERY: case State::WAIT_FOR_RECOVERY:
break; break;
default: default:
@ -136,14 +164,8 @@ ReturnValue_t PdecHandler::polledOperation() {
// See https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt.html for more information. // See https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt.html for more information.
ReturnValue_t PdecHandler::irqOperation() { ReturnValue_t PdecHandler::irqOperation() {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
int fd = open(uioNames.irq, O_RDWR); int fd = -1;
if (fd < 0) {
sif::error << "PdecHandler::irqOperation: Opening UIO IRQ file" << uioNames.irq << " failed"
<< std::endl;
return returnvalue::FAILED;
}
// Used to unmask IRQ // Used to unmask IRQ
uint32_t info = 1; uint32_t info = 1;
@ -158,18 +180,23 @@ ReturnValue_t PdecHandler::irqOperation() {
info = 1; info = 1;
readCommandQueue(); readCommandQueue();
switch (state) { switch (state) {
case State::INIT: case State::INIT: {
result = resetFarStatFlag(); result = handleInitState();
if (result != returnvalue::OK) { if (result == returnvalue::OK) {
// Requires reconfiguration and reinitialization of PDEC openIrqFile(&fd);
triggerEvent(INVALID_FAR);
state = State::WAIT_FOR_RECOVERY;
return result;
} }
state = State::RUNNING;
checkLocks();
break; break;
}
case State::PDEC_RESET: {
result = pdecToReset();
if (result != returnvalue::OK) {
triggerEvent(PDEC_RESET_FAILED);
}
state = State::INIT;
break;
}
case State::RUNNING: { case State::RUNNING: {
checkLocks();
checkAndHandleIrqs(fd, info); checkAndHandleIrqs(fd, info);
break; break;
} }
@ -188,6 +215,38 @@ ReturnValue_t PdecHandler::irqOperation() {
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t PdecHandler::handleInitState() {
ReturnValue_t result = firstLoop();
if (result != returnvalue::OK) {
if (result == LocalParameterHandler::SD_NOT_READY) {
TaskFactory::delayTask(400);
if (initTries == MAX_INIT_TRIES) {
sif::error << "PdecHandler::handleInitState: SD card never "
"becomes ready"
<< std::endl;
state = State::WAIT_FOR_RECOVERY;
} else {
state = State::INIT;
}
return result;
}
state = State::WAIT_FOR_RECOVERY;
return result;
}
state = State::RUNNING;
return returnvalue::OK;
}
void PdecHandler::openIrqFile(int* fd) {
*fd = open(uioNames.irq, O_RDWR);
if (*fd < 0) {
sif::error << "PdecHandler::irqOperation: Opening UIO IRQ file" << uioNames.irq << " failed"
<< std::endl;
triggerEvent(OPEN_IRQ_FILE_FAILED);
state = State::WAIT_FOR_RECOVERY;
}
}
ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) { ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) {
ssize_t nb = write(fd, &info, sizeof(info)); ssize_t nb = write(fd, &info, sizeof(info));
if (nb != static_cast<ssize_t>(sizeof(info))) { if (nb != static_cast<ssize_t>(sizeof(info))) {
@ -201,7 +260,6 @@ ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) {
int ret = poll(&fds, 1, IRQ_TIMEOUT_MS); int ret = poll(&fds, 1, IRQ_TIMEOUT_MS);
if (ret == 0) { if (ret == 0) {
// No TCs for timeout period // No TCs for timeout period
checkLocks();
genericCheckCd.resetTimer(); genericCheckCd.resetTimer();
resetIrqLimiters(); resetIrqLimiters();
} else if (ret >= 1) { } else if (ret >= 1) {
@ -228,7 +286,6 @@ ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) {
static_cast<void>(dummy); static_cast<void>(dummy);
if (genericCheckCd.hasTimedOut()) { if (genericCheckCd.hasTimedOut()) {
checkLocks();
genericCheckCd.resetTimer(); genericCheckCd.resetTimer();
if (interruptWindowCd.hasTimedOut()) { if (interruptWindowCd.hasTimedOut()) {
if (interruptCounter >= MAX_ALLOWED_IRQS_PER_WINDOW) { if (interruptCounter >= MAX_ALLOWED_IRQS_PER_WINDOW) {
@ -254,17 +311,21 @@ ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) {
} }
void PdecHandler::readCommandQueue(void) { void PdecHandler::readCommandQueue(void) {
CommandMessage commandMessage; CommandMessage message;
ReturnValue_t result = returnvalue::FAILED; ReturnValue_t result = returnvalue::FAILED;
result = commandQueue->receiveMessage(&commandMessage); result = commandQueue->receiveMessage(&message);
if (result == returnvalue::OK) { if (result == returnvalue::OK) {
result = actionHelper.handleActionMessage(&commandMessage); result = actionHelper.handleActionMessage(&message);
if (result == returnvalue::OK) {
return;
}
result = paramHelper.handleParameterMessage(&message);
if (result == returnvalue::OK) { if (result == returnvalue::OK) {
return; return;
} }
CommandMessage reply; CommandMessage reply;
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, commandMessage.getCommand()); reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, message.getCommand());
commandQueue->reply(&reply); commandQueue->reply(&reply);
return; return;
} }
@ -272,26 +333,69 @@ void PdecHandler::readCommandQueue(void) {
MessageQueueId_t PdecHandler::getCommandQueue() const { return commandQueue->getId(); } MessageQueueId_t PdecHandler::getCommandQueue() const { return commandQueue->getId(); }
void PdecHandler::writePdecConfigDuringReset(PdecConfig& pdecConfig) { ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
*(memoryBaseAddress + FRAME_HEADER_OFFSET) = pdecConfig.getConfigWord(0); const uint8_t* data, size_t size) {
*(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = pdecConfig.getConfigWord(1); switch (actionId) {
case PRINT_CLCW:
// Configure all MAP IDs as invalid printClcw();
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) { return EXECUTION_FINISHED;
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + idx / 4) = case PRINT_PDEC_MON:
NO_DESTINATION << 24 | NO_DESTINATION << 16 | NO_DESTINATION << 8 | NO_DESTINATION; printPdecMon();
return EXECUTION_FINISHED;
default:
return COMMAND_NOT_IMPLEMENTED;
} }
}
// All TCs with MAP ID 7 will be routed to the PM module (can then be read from memory) ReturnValue_t PdecHandler::getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
uint8_t routeToPm = calcMapAddrEntry(PM_BUFFER); ParameterWrapper* parameterWrapper,
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + 1) = const ParameterWrapper* newValues, uint16_t startAtIndex) {
(NO_DESTINATION << 24) | (NO_DESTINATION << 16) | (NO_DESTINATION << 8) | routeToPm; if ((domainId == 0) and (uniqueIdentifier == ParameterId::POSITIVE_WINDOW)) {
uint8_t newVal = 0;
// Write map id clock frequencies ReturnValue_t result = newValues->getElement(&newVal);
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) { if (result != returnvalue::OK) {
*(memoryBaseAddress + MAP_CLK_FREQ_OFFSET + idx / 4) = return result;
MAP_CLK_FREQ << 24 | MAP_CLK_FREQ << 16 | MAP_CLK_FREQ << 8 | MAP_CLK_FREQ; }
uint8_t positiveWindow = 0;
result = pdecConfig.getPositiveWindow(positiveWindow);
if (result != returnvalue::OK) {
sif::warning << "PdecHandler::getParameter: Failed to get positive window from pdec config"
<< std::endl;
return returnvalue::FAILED;
}
parameterWrapper->set(positiveWindow);
result = pdecConfig.setPositiveWindow(newVal);
if (result != returnvalue::OK) {
sif::warning << "PdecHandler::getParameter: Failed to set positive window" << std::endl;
return returnvalue::FAILED;
}
// PDEC needs reset to apply this parameter change
state = State::PDEC_RESET;
return returnvalue::OK;
} else if ((domainId == 0) and (uniqueIdentifier == ParameterId::NEGATIVE_WINDOW)) {
uint8_t newVal = 0;
ReturnValue_t result = newValues->getElement(&newVal);
if (result != returnvalue::OK) {
return result;
}
uint8_t negativeWindow = 0;
result = pdecConfig.getNegativeWindow(negativeWindow);
if (result != returnvalue::OK) {
sif::warning << "PdecHandler::getParameter: Failed to get negative window from pdec config"
<< std::endl;
return returnvalue::FAILED;
}
parameterWrapper->set(negativeWindow);
result = pdecConfig.setNegativeWindow(newVal);
if (result != returnvalue::OK) {
sif::warning << "PdecHandler::getParameter: Failed to set negative window" << std::endl;
return returnvalue::FAILED;
}
// PDEC needs reset to apply this parameter change
state = State::PDEC_RESET;
return returnvalue::OK;
} }
return returnvalue::OK;
} }
ReturnValue_t PdecHandler::resetFarStatFlag() { ReturnValue_t PdecHandler::resetFarStatFlag() {
@ -320,6 +424,17 @@ ReturnValue_t PdecHandler::releasePdec() {
return result; return result;
} }
ReturnValue_t PdecHandler::pdecToReset() {
ReturnValue_t result = returnvalue::OK;
result = gpioComIF->pullLow(pdecReset);
if (result != returnvalue::OK) {
sif::error << "PdecHandler::pdecToReset: Failed to pull PDEC reset line"
" to low"
<< std::endl;
}
return result;
}
bool PdecHandler::newTcReceived() { bool PdecHandler::newTcReceived() {
uint32_t pdecFar = readFar(); uint32_t pdecFar = readFar();
@ -557,23 +672,6 @@ void PdecHandler::printTC(uint32_t tcLength) {
sif::info << tcSegmentStream.str() << std::endl; sif::info << tcSegmentStream.str() << std::endl;
} }
uint8_t PdecHandler::calcMapAddrEntry(uint8_t moduleId) {
uint8_t lutEntry = 0;
uint8_t parity = getOddParity(moduleId | (1 << VALID_POSITION));
lutEntry = (parity << PARITY_POSITION) | (1 << VALID_POSITION) | moduleId;
return lutEntry;
}
uint8_t PdecHandler::getOddParity(uint8_t number) {
uint8_t parityBit = 0;
uint8_t countBits = 0;
for (unsigned int idx = 0; idx < sizeof(number) * 8; idx++) {
countBits += (number >> idx) & 0x1;
}
parityBit = ~(countBits & 0x1) & 0x1;
return parityBit;
}
uint32_t PdecHandler::getClcw() { return *(registerBaseAddress + PDEC_CLCW_OFFSET); } uint32_t PdecHandler::getClcw() { return *(registerBaseAddress + PDEC_CLCW_OFFSET); }
uint32_t PdecHandler::getPdecMon() { return *(registerBaseAddress + PDEC_MON_OFFSET); } uint32_t PdecHandler::getPdecMon() { return *(registerBaseAddress + PDEC_MON_OFFSET); }
@ -664,17 +762,3 @@ std::string PdecHandler::getMonStatusString(uint32_t status) {
break; break;
} }
} }
ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
switch (actionId) {
case PRINT_CLCW:
printClcw();
return EXECUTION_FINISHED;
case PRINT_PDEC_MON:
printPdecMon();
return EXECUTION_FINISHED;
default:
return COMMAND_NOT_IMPLEMENTED;
}
}

View File

@ -9,6 +9,8 @@
#include "fsfw/action/ActionHelper.h" #include "fsfw/action/ActionHelper.h"
#include "fsfw/action/HasActionsIF.h" #include "fsfw/action/HasActionsIF.h"
#include "fsfw/objectmanager/SystemObject.h" #include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/parameters/ParameterHelper.h"
#include "fsfw/parameters/ReceivesParameterMessagesIF.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/storagemanager/StorageManagerIF.h" #include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h" #include "fsfw/tasks/ExecutableObjectIF.h"
@ -41,7 +43,10 @@ struct UioNames {
* *
* @author J. Meier * @author J. Meier
*/ */
class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasActionsIF { class PdecHandler : public SystemObject,
public ExecutableObjectIF,
public HasActionsIF,
public ReceivesParameterMessagesIF {
public: public:
static constexpr dur_millis_t IRQ_TIMEOUT_MS = 500; static constexpr dur_millis_t IRQ_TIMEOUT_MS = 500;
@ -70,6 +75,10 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override; const uint8_t* data, size_t size) override;
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) override;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PDEC_HANDLER; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PDEC_HANDLER;
//! [EXPORT] : [COMMENT] Frame acceptance report signals an invalid frame //! [EXPORT] : [COMMENT] Frame acceptance report signals an invalid frame
@ -92,7 +101,12 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
static constexpr Event POLL_SYSCALL_ERROR_PDEC = static constexpr Event POLL_SYSCALL_ERROR_PDEC =
event::makeEvent(SUBSYSTEM_ID, 8, severity::MEDIUM); event::makeEvent(SUBSYSTEM_ID, 8, severity::MEDIUM);
static constexpr Event WRITE_SYSCALL_ERROR_PDEC = static constexpr Event WRITE_SYSCALL_ERROR_PDEC =
event::makeEvent(SUBSYSTEM_ID, 9, severity::MEDIUM); event::makeEvent(SUBSYSTEM_ID, 9, severity::HIGH);
//! [EXPORT] : [COMMENT] Failed to pull PDEC reset to low
static constexpr Event PDEC_RESET_FAILED = event::makeEvent(SUBSYSTEM_ID, 10, severity::HIGH);
//! [EXPORT] : [COMMENT] Failed to open the IRQ uio file
static constexpr Event OPEN_IRQ_FILE_FAILED =
event::makeEvent(SUBSYSTEM_ID, 11, severity::HIGH);
private: private:
static const uint8_t INTERFACE_ID = CLASS_ID::PDEC_HANDLER; static const uint8_t INTERFACE_ID = CLASS_ID::PDEC_HANDLER;
@ -143,9 +157,6 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
static const int REGISTER_MAP_SIZE = 0x4000; static const int REGISTER_MAP_SIZE = 0x4000;
#endif /* BOARD_TE0720 == 1 */ #endif /* BOARD_TE0720 == 1 */
// 0x200 / 4 = 0x80
static const uint32_t FRAME_HEADER_OFFSET = 0x80;
static const size_t MAX_TC_SEGMENT_SIZE = 1017; static const size_t MAX_TC_SEGMENT_SIZE = 1017;
static const uint8_t MAP_ID_MASK = 0x3F; static const uint8_t MAP_ID_MASK = 0x3F;
@ -155,15 +166,6 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
static const uint32_t PHYSICAL_RAM_BASE_ADDRESS = 0x26000000; static const uint32_t PHYSICAL_RAM_BASE_ADDRESS = 0x26000000;
#endif #endif
static const uint32_t MAP_ADDR_LUT_OFFSET = 0xA0;
static const uint32_t MAP_CLK_FREQ_OFFSET = 0x90;
static const uint8_t MAX_MAP_ADDR = 63;
// Writing this to the map address in the look up table will invalidate a MAP ID.
static const uint8_t NO_DESTINATION = 0;
static const uint8_t VALID_POSITION = 6;
static const uint8_t PARITY_POSITION = 7;
// Expected value stored in FAR register after reset // Expected value stored in FAR register after reset
static const uint32_t FAR_RESET = 0x7FE0; static const uint32_t FAR_RESET = 0x7FE0;
@ -172,15 +174,15 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
static const uint32_t NO_RF_MASK = 0x8000; static const uint32_t NO_RF_MASK = 0x8000;
static const uint32_t NO_BITLOCK_MASK = 0x4000; static const uint32_t NO_BITLOCK_MASK = 0x4000;
/** static const uint32_t MAX_INIT_TRIES = 20;
* TCs with map addresses (also know as Map IDs) assigned to this channel will be stored in
* the PDEC memory.
*/
static const uint8_t PM_BUFFER = 7;
// MAP clock frequency. Must be a value between 1 and 13 otherwise the TC segment will be class ParameterId {
// discarded public:
static const uint8_t MAP_CLK_FREQ = 2; // ID of the parameter to update the positive window of AD frames
static const uint8_t POSITIVE_WINDOW = 0;
// ID of the parameter to update the negative window of AD frames
static const uint8_t NEGATIVE_WINDOW = 1;
};
static constexpr uint32_t MAX_ALLOWED_IRQS_PER_WINDOW = 800; static constexpr uint32_t MAX_ALLOWED_IRQS_PER_WINDOW = 800;
@ -206,7 +208,7 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
INCORRECT_BC_CC INCORRECT_BC_CC
}; };
enum class State : uint8_t { INIT, RUNNING, WAIT_FOR_RECOVERY }; enum class State : uint8_t { INIT, PDEC_RESET, RUNNING, WAIT_FOR_RECOVERY };
static uint32_t CURRENT_FAR; static uint32_t CURRENT_FAR;
@ -259,6 +261,20 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
UioNames uioNames; UioNames uioNames;
ParameterHelper paramHelper;
PdecConfig pdecConfig;
uint32_t initTries = 0;
/**
* @brief Performs initialization stuff which must be performed in first
* loop of running task
*
* @return OK if successful, otherwise FAILED
*/
ReturnValue_t firstLoop();
/** /**
* @brief Reads and handles messages stored in the commandQueue * @brief Reads and handles messages stored in the commandQueue
*/ */
@ -266,6 +282,8 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
ReturnValue_t polledOperation(); ReturnValue_t polledOperation();
ReturnValue_t irqOperation(); ReturnValue_t irqOperation();
ReturnValue_t handleInitState();
void openIrqFile(int* fd);
ReturnValue_t checkAndHandleIrqs(int fd, uint32_t& info); ReturnValue_t checkAndHandleIrqs(int fd, uint32_t& info);
uint32_t readFar(); uint32_t readFar();
@ -291,6 +309,14 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
*/ */
ReturnValue_t releasePdec(); ReturnValue_t releasePdec();
/**
* @brief Will set PDEC in reset state. Use releasePdec() to release PDEC
* from reset state
*
* @return OK if successful, otherwise error return value
*/
ReturnValue_t pdecToReset();
/** /**
* @brief Reads the FAR register and checks if a new TC has been received. * @brief Reads the FAR register and checks if a new TC has been received.
*/ */
@ -354,13 +380,6 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
*/ */
uint8_t calcMapAddrEntry(uint8_t moduleId); uint8_t calcMapAddrEntry(uint8_t moduleId);
/**
* @brief This functions calculates the odd parity of the bits in number.
*
* @param number The number from which to calculate the odd parity.
*/
uint8_t getOddParity(uint8_t number);
/** /**
* brief Returns the 32-bit wide communication link control word (CLCW) * brief Returns the 32-bit wide communication link control word (CLCW)
*/ */

View File

@ -0,0 +1,20 @@
#ifndef LINUX_IPCORE_PDECCONFIGDEFS_H_
#define LINUX_IPCORE_PDECCONFIGDEFS_H_
#include <string>
namespace pdecconfigdefs {
namespace paramkeys {
static const std::string POSITIVE_WINDOW = "positive_window";
static const std::string NEGATIVE_WINDOW = "negattive_window";
} // namespace paramkeys
namespace defaultvalue {
static const uint8_t positiveWindow = 10;
static const uint8_t negativeWindow = 151;
} // namespace defaultvalue
} // namespace pdecconfigdefs
#endif /* LINUX_IPCORE_PDECCONFIGDEFS_H_ */

View File

@ -0,0 +1,9 @@
#ifndef MISSION_CONFIG_CONFIGFILE_H_
#define MISSION_CONFIG_CONFIGFILE_H_
namespace configfile {
// Name of global config file relative to currently mounted SD card
static const char sdrelative[] = "config/global_config.json";
} // namespace configfile
#endif /* MISSION_CONFIG_CONFIGFILE_H_ */

View File

@ -667,7 +667,7 @@ ReturnValue_t PayloadPcduHandler::getParameter(uint8_t domainId, uint8_t uniqueI
} }
void PayloadPcduHandler::handleFailureInjection(std::string output, Event event) { void PayloadPcduHandler::handleFailureInjection(std::string output, Event event) {
sif::info << "PayloadPcduHandler::checkAdcValues: " << output sif::info << "PayloadPcduHandler::handleFailureInjection: " << output
<< " failure injection. " << " failure injection. "
"Transitioning back to off" "Transitioning back to off"
<< std::endl; << std::endl;

View File

@ -7,6 +7,8 @@
NVMParameterBase::NVMParameterBase(std::string fullName) : fullName(fullName) {} NVMParameterBase::NVMParameterBase(std::string fullName) : fullName(fullName) {}
NVMParameterBase::NVMParameterBase() {}
ReturnValue_t NVMParameterBase::readJsonFile() { ReturnValue_t NVMParameterBase::readJsonFile() {
if (std::filesystem::exists(fullName)) { if (std::filesystem::exists(fullName)) {
// Read JSON file content into object // Read JSON file content into object

View File

@ -14,6 +14,12 @@ class NVMParameterBase {
NVMParameterBase(std::string fullName); NVMParameterBase(std::string fullName);
/**
* @brief Use this constructor when name of json file shall be set on an later
* point
*/
NVMParameterBase();
bool getJsonFileExists(); bool getJsonFileExists();
/** /**
@ -25,7 +31,7 @@ class NVMParameterBase {
virtual ReturnValue_t writeJsonFile(); virtual ReturnValue_t writeJsonFile();
void setFullName(std::string fullName); virtual void setFullName(std::string fullName);
std::string getFullName() const; std::string getFullName() const;
template <typename T> template <typename T>
@ -48,7 +54,7 @@ class NVMParameterBase {
nlohmann::json json; nlohmann::json json;
std::vector<std::string> keys; std::vector<std::string> keys;
std::string fullName; std::string fullName = "";
}; };
template <typename T> template <typename T>

View File

@ -166,6 +166,7 @@ void ComSubsystem::handleBitLockEvent() {
rememberBitLock = true; rememberBitLock = true;
return; return;
} }
triggerEvent(BIT_LOCK_TX_ON);
startRxAndTxLowRateSeq(); startRxAndTxLowRateSeq();
} }
@ -183,6 +184,7 @@ void ComSubsystem::startRxAndTxLowRateSeq() {
void ComSubsystem::checkTransmitterCountdown() { void ComSubsystem::checkTransmitterCountdown() {
if (transmitterCountdown.hasTimedOut()) { if (transmitterCountdown.hasTimedOut()) {
triggerEvent(TX_TIMER_EXPIRED, transmitterTimeout);
startTransition(com::Submode::RX_ONLY, SUBMODE_NONE); startTransition(com::Submode::RX_ONLY, SUBMODE_NONE);
countdownActive = false; countdownActive = false;
} }

View File

@ -5,11 +5,21 @@
#include <fsfw/parameters/HasParametersIF.h> #include <fsfw/parameters/HasParametersIF.h>
#include <fsfw/parameters/ParameterHelper.h> #include <fsfw/parameters/ParameterHelper.h>
#include <fsfw/subsystem/Subsystem.h> #include <fsfw/subsystem/Subsystem.h>
#include <common/config/eive/eventSubsystemIds.h>
#include "mission/comDefs.h" #include "mission/comDefs.h"
class ComSubsystem : public Subsystem, public ReceivesParameterMessagesIF { class ComSubsystem : public Subsystem, public ReceivesParameterMessagesIF {
public: public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::COM_SUBSYSTEM;
//! [EXPORT] : [COMMENT] The transmit timer to protect the Syrlinks expired
//! P1: The current timer value
static const Event TX_TIMER_EXPIRED = MAKE_EVENT(1, severity::INFO);
//! [EXPORT] : [COMMENT] Transmitter will be turned on due to detection of bitlock
static const Event BIT_LOCK_TX_ON = MAKE_EVENT(2, severity::INFO);
/** /**
* @brief Constructor * @brief Constructor
* *
@ -17,8 +27,7 @@ class ComSubsystem : public Subsystem, public ReceivesParameterMessagesIF {
* @param maxNumberOfSequences * @param maxNumberOfSequences
* @param maxNumberOfTables * @param maxNumberOfTables
* @param transmitterTimeout Maximum time the transmitter of the syrlinks * @param transmitterTimeout Maximum time the transmitter of the syrlinks
* will * will be enabled
* be enabled
*/ */
ComSubsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables, ComSubsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables,
uint32_t transmitterTimeout); uint32_t transmitterTimeout);
@ -55,6 +64,7 @@ class ComSubsystem : public Subsystem, public ReceivesParameterMessagesIF {
bool isTxMode(Mode_t mode); bool isTxMode(Mode_t mode);
uint8_t datarateCfg = static_cast<uint8_t>(com::Datarate::LOW_RATE_MODULATION_BPSK); uint8_t datarateCfg = static_cast<uint8_t>(com::Datarate::LOW_RATE_MODULATION_BPSK);
// Maximum time after which the transmitter will be turned of. This is a // Maximum time after which the transmitter will be turned of. This is a
// protection mechanism due prevent the syrlinks from overheating // protection mechanism due prevent the syrlinks from overheating
uint32_t transmitterTimeout = 0; uint32_t transmitterTimeout = 0;

View File

@ -11,10 +11,6 @@
static constexpr double PARAM0_DEFAULT = 5.0; static constexpr double PARAM0_DEFAULT = 5.0;
static constexpr int PARAM1_DEFAULT = 905; static constexpr int PARAM1_DEFAULT = 905;
enum ParamIds : uint8_t { enum ParamIds : uint8_t { PARAM0 = 0, PARAM1 = 1, PARAM2 = 2, PDEC_PW = 3, PDEC_NW = 4 };
PARAM0 = 0,
PARAM1 = 1,
PARAM2 = 2,
};
#endif /* MISSION_UTILITY_GLOBALCONFIGFILEDEFINITIONS_H_ */ #endif /* MISSION_UTILITY_GLOBALCONFIGFILEDEFINITIONS_H_ */