PDEC IRQ Handling #310
@ -10,6 +10,8 @@ list yields a list of all related PRs for each release.
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
|
- Add IRQ mode for PDEC handler
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/310
|
||||||
- Extended TM funnels to allow multiple TM recipients.
|
- Extended TM funnels to allow multiple TM recipients.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/312
|
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/312
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ static constexpr char UIO_PDEC_REGISTERS[] = "/dev/uio_pdec_regs";
|
|||||||
static constexpr char UIO_PTME[] = "/dev/uio_ptme";
|
static constexpr char UIO_PTME[] = "/dev/uio_ptme";
|
||||||
static constexpr char UIO_PDEC_CONFIG_MEMORY[] = "/dev/uio_pdec_cfg_mem";
|
static constexpr char UIO_PDEC_CONFIG_MEMORY[] = "/dev/uio_pdec_cfg_mem";
|
||||||
static constexpr char UIO_PDEC_RAM[] = "/dev/uio_pdec_ram";
|
static constexpr char UIO_PDEC_RAM[] = "/dev/uio_pdec_ram";
|
||||||
|
static constexpr char UIO_PDEC_IRQ[] = "/dev/uio_pdec_irq";
|
||||||
static constexpr int MAP_ID_PTME_CONFIG = 3;
|
static constexpr int MAP_ID_PTME_CONFIG = 3;
|
||||||
|
|
||||||
namespace uiomapids {
|
namespace uiomapids {
|
||||||
|
@ -131,7 +131,7 @@ void initmission::initTasks() {
|
|||||||
// If a command has not been read before the next one arrives, the old command will be
|
// If a command has not been read before the next one arrives, the old command will be
|
||||||
// overwritten by the PDEC.
|
// overwritten by the PDEC.
|
||||||
PeriodicTaskIF* pdecHandlerTask = factory->createPeriodicTask(
|
PeriodicTaskIF* pdecHandlerTask = factory->createPeriodicTask(
|
||||||
"PDEC_HANDLER", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc);
|
"PDEC_HANDLER", 75, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc);
|
||||||
result = pdecHandlerTask->addComponent(objects::PDEC_HANDLER);
|
result = pdecHandlerTask->addComponent(objects::PDEC_HANDLER);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
initmission::printAddObjectError("PDEC Handler", objects::PDEC_HANDLER);
|
initmission::printAddObjectError("PDEC Handler", objects::PDEC_HANDLER);
|
||||||
|
@ -790,8 +790,13 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF,
|
|||||||
Levels::LOW);
|
Levels::LOW);
|
||||||
gpioCookiePdec->addGpio(gpioIds::PDEC_RESET, gpio);
|
gpioCookiePdec->addGpio(gpioIds::PDEC_RESET, gpio);
|
||||||
gpioChecker(gpioComIF->addGpios(gpioCookiePdec), "PDEC");
|
gpioChecker(gpioComIF->addGpios(gpioCookiePdec), "PDEC");
|
||||||
|
struct UioNames uioNames {};
|
||||||
|
uioNames.configMemory = q7s::UIO_PDEC_CONFIG_MEMORY;
|
||||||
|
uioNames.ramMemory = q7s::UIO_PDEC_RAM;
|
||||||
|
uioNames.registers = q7s::UIO_PDEC_REGISTERS;
|
||||||
|
uioNames.irq = q7s::UIO_PDEC_IRQ;
|
||||||
new PdecHandler(objects::PDEC_HANDLER, objects::CCSDS_HANDLER, gpioComIF, gpioIds::PDEC_RESET,
|
new PdecHandler(objects::PDEC_HANDLER, objects::CCSDS_HANDLER, gpioComIF, gpioIds::PDEC_RESET,
|
||||||
q7s::UIO_PDEC_CONFIG_MEMORY, q7s::UIO_PDEC_RAM, q7s::UIO_PDEC_REGISTERS);
|
uioNames);
|
||||||
GpioCookie* gpioRS485Chip = new GpioCookie;
|
GpioCookie* gpioRS485Chip = new GpioCookie;
|
||||||
gpio = new GpiodRegularByLineName(q7s::gpioNames::RS485_EN_TX_CLOCK, "RS485 Transceiver",
|
gpio = new GpiodRegularByLineName(q7s::gpioNames::RS485_EN_TX_CLOCK, "RS485 Transceiver",
|
||||||
Direction::OUT, Levels::LOW);
|
Direction::OUT, Levels::LOW);
|
||||||
|
@ -35,6 +35,9 @@ void ObjectFactory::produce(void* args) {
|
|||||||
// level components.
|
// level components.
|
||||||
dummy::DummyCfg dummyCfg;
|
dummy::DummyCfg dummyCfg;
|
||||||
dummyCfg.addCoreCtrlCfg = false;
|
dummyCfg.addCoreCtrlCfg = false;
|
||||||
|
#if OBSW_ADD_SYRLINKS == 1
|
||||||
|
dummyCfg.addSyrlinksDummies = false;
|
||||||
|
#endif
|
||||||
dummy::createDummies(dummyCfg);
|
dummy::createDummies(dummyCfg);
|
||||||
|
|
||||||
new CoreController(objects::CORE_CONTROLLER);
|
new CoreController(objects::CORE_CONTROLLER);
|
||||||
@ -65,6 +68,10 @@ void ObjectFactory::produce(void* args) {
|
|||||||
createImtqComponents(pwrSwitcher);
|
createImtqComponents(pwrSwitcher);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if OBSW_ADD_SYRLINKS == 1
|
||||||
|
createSyrlinksComponents(pwrSwitcher);
|
||||||
|
#endif /* OBSW_ADD_SYRLINKS == 1 */
|
||||||
|
|
||||||
#if OBSW_ADD_RW == 1
|
#if OBSW_ADD_RW == 1
|
||||||
createReactionWheelComponents(gpioComIF, pwrSwitcher);
|
createReactionWheelComponents(gpioComIF, pwrSwitcher);
|
||||||
#endif
|
#endif
|
||||||
@ -91,5 +98,5 @@ void ObjectFactory::produce(void* args) {
|
|||||||
createScexComponents(q7s::UART_SCEX_DEV, pwrSwitcher, *SdCardManager::instance(), true,
|
createScexComponents(q7s::UART_SCEX_DEV, pwrSwitcher, *SdCardManager::instance(), true,
|
||||||
std::nullopt);
|
std::nullopt);
|
||||||
#endif
|
#endif
|
||||||
createAcsController();
|
createAcsController(true);
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,7 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
CoreControllerDummy::CoreControllerDummy(object_id_t objectId)
|
CoreControllerDummy::CoreControllerDummy(object_id_t objectId) : ExtendedControllerBase(objectId) {}
|
||||||
: ExtendedControllerBase(objectId, objects::NO_OBJECT) {}
|
|
||||||
|
|
||||||
ReturnValue_t CoreControllerDummy::initialize() {
|
ReturnValue_t CoreControllerDummy::initialize() {
|
||||||
static bool done = false;
|
static bool done = false;
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
SusDummy::SusDummy()
|
SusDummy::SusDummy() : ExtendedControllerBase(objects::SUS_0_N_LOC_XFYFZM_PT_XF), susSet(this) {
|
||||||
: ExtendedControllerBase(objects::SUS_0_N_LOC_XFYFZM_PT_XF, objects::NO_OBJECT), susSet(this) {
|
|
||||||
ObjectManager::instance()->insert(objects::SUS_6_R_LOC_XFYBZM_PT_XF, this);
|
ObjectManager::instance()->insert(objects::SUS_6_R_LOC_XFYBZM_PT_XF, this);
|
||||||
ObjectManager::instance()->insert(objects::SUS_1_N_LOC_XBYFZM_PT_XB, this);
|
ObjectManager::instance()->insert(objects::SUS_1_N_LOC_XBYFZM_PT_XB, this);
|
||||||
ObjectManager::instance()->insert(objects::SUS_7_R_LOC_XBYBZM_PT_XB, this);
|
ObjectManager::instance()->insert(objects::SUS_7_R_LOC_XBYBZM_PT_XB, this);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
TemperatureSensorsDummy::TemperatureSensorsDummy()
|
TemperatureSensorsDummy::TemperatureSensorsDummy()
|
||||||
: ExtendedControllerBase(objects::RTD_0_IC3_PLOC_HEATSPREADER, objects::NO_OBJECT),
|
: ExtendedControllerBase(objects::RTD_0_IC3_PLOC_HEATSPREADER),
|
||||||
max31865Set(this, MAX31865::MAX31865_SET_ID) {
|
max31865Set(this, MAX31865::MAX31865_SET_ID) {
|
||||||
ObjectManager::instance()->insert(objects::RTD_1_IC4_PLOC_MISSIONBOARD, this);
|
ObjectManager::instance()->insert(objects::RTD_1_IC4_PLOC_MISSIONBOARD, this);
|
||||||
ObjectManager::instance()->insert(objects::RTD_2_IC5_4K_CAMERA, this);
|
ObjectManager::instance()->insert(objects::RTD_2_IC5_4K_CAMERA, this);
|
||||||
|
@ -38,7 +38,9 @@ void dummy::createDummies(DummyCfg cfg) {
|
|||||||
new RwDummy(objects::RW4, objects::DUMMY_COM_IF, comCookieDummy);
|
new RwDummy(objects::RW4, objects::DUMMY_COM_IF, comCookieDummy);
|
||||||
new SaDeplDummy(objects::SOLAR_ARRAY_DEPL_HANDLER);
|
new SaDeplDummy(objects::SOLAR_ARRAY_DEPL_HANDLER);
|
||||||
new StarTrackerDummy(objects::STAR_TRACKER, objects::DUMMY_COM_IF, comCookieDummy);
|
new StarTrackerDummy(objects::STAR_TRACKER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||||
new SyrlinksDummy(objects::SYRLINKS_HK_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
if (cfg.addSyrlinksDummies) {
|
||||||
|
new SyrlinksDummy(objects::SYRLINKS_HK_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||||
|
}
|
||||||
new ImtqDummy(objects::IMTQ_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
new ImtqDummy(objects::IMTQ_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||||
if (cfg.addPowerDummies) {
|
if (cfg.addPowerDummies) {
|
||||||
new AcuDummy(objects::ACU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
new AcuDummy(objects::ACU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||||
|
@ -5,6 +5,7 @@ namespace dummy {
|
|||||||
struct DummyCfg {
|
struct DummyCfg {
|
||||||
bool addCoreCtrlCfg = true;
|
bool addCoreCtrlCfg = true;
|
||||||
bool addPowerDummies = true;
|
bool addPowerDummies = true;
|
||||||
|
bool addSyrlinksDummies = true;
|
||||||
bool addAcsBoardDummies = true;
|
bool addAcsBoardDummies = true;
|
||||||
bool addSusDummies = true;
|
bool addSusDummies = true;
|
||||||
bool addTempSensorDummies = true;
|
bool addTempSensorDummies = true;
|
||||||
|
2
fsfw
2
fsfw
@ -1 +1 @@
|
|||||||
Subproject commit 7600ed1ea70ef2998739800f84722dd7cadb7552
|
Subproject commit e1d4209fbe06581c36dd0a1b8113dfb56e673613
|
@ -31,3 +31,8 @@ uint32_t PdecConfig::getConfigWord(uint8_t wordNo) {
|
|||||||
}
|
}
|
||||||
return configWords[wordNo];
|
return configWords[wordNo];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t PdecConfig::getImrReg() {
|
||||||
|
return static_cast<uint32_t>(enableNewFarIrq << 2) |
|
||||||
|
static_cast<uint32_t>(enableTcAbortIrq << 1) | static_cast<uint32_t>(enableTcNewIrq);
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@ class PdecConfig {
|
|||||||
* @brief Returns the configuration word by specifying the position.
|
* @brief Returns the configuration word by specifying the position.
|
||||||
*/
|
*/
|
||||||
uint32_t getConfigWord(uint8_t wordNo);
|
uint32_t getConfigWord(uint8_t wordNo);
|
||||||
|
uint32_t getImrReg();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TC transfer frame configuration parameters
|
// TC transfer frame configuration parameters
|
||||||
@ -45,6 +46,9 @@ class PdecConfig {
|
|||||||
static const uint8_t CONFIG_WORDS_NUM = 2;
|
static const uint8_t CONFIG_WORDS_NUM = 2;
|
||||||
|
|
||||||
uint32_t configWords[CONFIG_WORDS_NUM];
|
uint32_t configWords[CONFIG_WORDS_NUM];
|
||||||
|
bool enableTcNewIrq = true;
|
||||||
|
bool enableTcAbortIrq = true;
|
||||||
|
bool enableNewFarIrq = true;
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#include "PdecHandler.h"
|
#include "PdecHandler.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -12,18 +14,21 @@
|
|||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||||
#include "fsfw_hal/linux/uio/UioMapper.h"
|
#include "fsfw_hal/linux/uio/UioMapper.h"
|
||||||
|
#include "pdec.h"
|
||||||
|
|
||||||
|
using namespace pdec;
|
||||||
|
|
||||||
|
// If this is ever shared, protect it with a mutex!
|
||||||
|
uint32_t PdecHandler::CURRENT_FAR = 0;
|
||||||
|
|
||||||
PdecHandler::PdecHandler(object_id_t objectId, object_id_t tcDestinationId,
|
PdecHandler::PdecHandler(object_id_t objectId, object_id_t tcDestinationId,
|
||||||
LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, std::string uioConfigMemory,
|
LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, UioNames names)
|
||||||
std::string uioRamMemory, std::string uioRegisters)
|
|
||||||
: SystemObject(objectId),
|
: SystemObject(objectId),
|
||||||
tcDestinationId(tcDestinationId),
|
tcDestinationId(tcDestinationId),
|
||||||
gpioComIF(gpioComIF),
|
gpioComIF(gpioComIF),
|
||||||
pdecReset(pdecReset),
|
pdecReset(pdecReset),
|
||||||
uioConfigMemory(uioConfigMemory),
|
actionHelper(this, nullptr),
|
||||||
uioRamMemory(uioRamMemory),
|
uioNames(names) {
|
||||||
uioRegisters(uioRegisters),
|
|
||||||
actionHelper(this, nullptr) {
|
|
||||||
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);
|
||||||
@ -47,29 +52,39 @@ ReturnValue_t PdecHandler::initialize() {
|
|||||||
|
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
|
|
||||||
UioMapper regMapper(uioRegisters);
|
UioMapper regMapper(uioNames.registers);
|
||||||
result = regMapper.getMappedAdress(®isterBaseAddress, UioMapper::Permissions::READ_WRITE);
|
result = regMapper.getMappedAdress(®isterBaseAddress, UioMapper::Permissions::READ_WRITE);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
}
|
}
|
||||||
UioMapper configMemMapper(uioConfigMemory);
|
UioMapper configMemMapper(uioNames.configMemory);
|
||||||
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;
|
||||||
}
|
}
|
||||||
UioMapper ramMapper(uioRamMemory);
|
UioMapper ramMapper(uioNames.ramMemory);
|
||||||
result = ramMapper.getMappedAdress(&ramBaseAddress, UioMapper::Permissions::READ_WRITE);
|
result = ramMapper.getMappedAdress(&ramBaseAddress, UioMapper::Permissions::READ_WRITE);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
writePdecConfig();
|
if (OP_MODE == Modes::IRQ and uioNames.irq == nullptr) {
|
||||||
|
sif::error << "Can not use IRQ mode if IRQ UIO name is invalid" << std::endl;
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
PdecConfig pdecConfig;
|
||||||
|
writePdecConfigDuringReset(pdecConfig);
|
||||||
|
|
||||||
result = releasePdec();
|
result = releasePdec();
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This configuration must be done while the PDEC is not held in reset.
|
||||||
|
if (OP_MODE == Modes::IRQ) {
|
||||||
|
// Configure interrupt mask register to enable interrupts
|
||||||
|
*(registerBaseAddress + PDEC_IMR_OFFSET) = pdecConfig.getImrReg();
|
||||||
|
}
|
||||||
result = actionHelper.initialize(commandQueue);
|
result = actionHelper.initialize(commandQueue);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
@ -78,59 +93,16 @@ ReturnValue_t PdecHandler::initialize() {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t PdecHandler::getCommandQueue() const { return commandQueue->getId(); }
|
|
||||||
|
|
||||||
void PdecHandler::writePdecConfig() {
|
|
||||||
PdecConfig pdecConfig;
|
|
||||||
|
|
||||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET) = pdecConfig.getConfigWord(0);
|
|
||||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = pdecConfig.getConfigWord(1);
|
|
||||||
|
|
||||||
// Configure all MAP IDs as invalid
|
|
||||||
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
|
|
||||||
*(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PdecHandler::resetFarStatFlag() {
|
|
||||||
uint32_t pdecFar = *(registerBaseAddress + PDEC_FAR_OFFSET);
|
|
||||||
if (pdecFar != FAR_RESET) {
|
|
||||||
sif::warning << "PdecHandler::resetFarStatFlag: FAR register did not match expected value."
|
|
||||||
<< " Read value: 0x" << std::hex << static_cast<unsigned int>(pdecFar)
|
|
||||||
<< std::endl;
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
|
||||||
sif::debug << "PdecHandler::resetFarStatFlag: read FAR with value: 0x" << std::hex << pdecFar
|
|
||||||
<< std::endl;
|
|
||||||
#endif /* OBSW_DEBUG_PDEC_HANDLER == 1 */
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PdecHandler::releasePdec() {
|
|
||||||
ReturnValue_t result = returnvalue::OK;
|
|
||||||
result = gpioComIF->pullHigh(pdecReset);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
sif::error << "PdecHandler::releasePdec: Failed to release PDEC reset signal" << std::endl;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PdecHandler::performOperation(uint8_t operationCode) {
|
ReturnValue_t PdecHandler::performOperation(uint8_t operationCode) {
|
||||||
ReturnValue_t result = returnvalue::OK;
|
if (OP_MODE == Modes::POLLED) {
|
||||||
|
return polledOperation();
|
||||||
|
} else if (OP_MODE == Modes::IRQ) {
|
||||||
|
return irqOperation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PdecHandler::polledOperation() {
|
||||||
|
ReturnValue_t result = returnvalue::OK;
|
||||||
readCommandQueue();
|
readCommandQueue();
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -153,13 +125,95 @@ ReturnValue_t PdecHandler::performOperation(uint8_t operationCode) {
|
|||||||
case State::WAIT_FOR_RECOVERY:
|
case State::WAIT_FOR_RECOVERY:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sif::debug << "PdecHandler::performOperation: Invalid state" << std::endl;
|
sif::error << "PdecHandler::performOperation: Invalid state" << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PdecHandler::irqOperation() {
|
||||||
|
ReturnValue_t result = returnvalue::OK;
|
||||||
|
int fd = open(uioNames.irq, O_RDWR);
|
||||||
|
sif::info << uioNames.irq << std::endl;
|
||||||
|
if (fd < 0) {
|
||||||
|
sif::error << "PdecHandler::irqOperation: Opening UIO IRQ file" << uioNames.irq << " failed"
|
||||||
|
<< std::endl;
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pollfd fds = {.fd = fd, .events = POLLIN, .revents = 0};
|
||||||
|
// Used to unmask IRQ
|
||||||
|
uint32_t info = 1;
|
||||||
|
ssize_t nb = 0;
|
||||||
|
int ret = 0;
|
||||||
|
// Clear interrupts with dummy read before unmasking the interrupt
|
||||||
|
ret = *(registerBaseAddress + PDEC_PIR_OFFSET);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
readCommandQueue();
|
||||||
|
switch (state) {
|
||||||
|
case State::INIT:
|
||||||
|
resetFarStatFlag();
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
// Requires reconfiguration and reinitialization of PDEC
|
||||||
|
triggerEvent(INVALID_FAR);
|
||||||
|
state = State::WAIT_FOR_RECOVERY;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
state = State::RUNNING;
|
||||||
|
break;
|
||||||
|
case State::RUNNING: {
|
||||||
|
nb = write(fd, &info, sizeof(info));
|
||||||
|
if (nb != static_cast<ssize_t>(sizeof(info))) {
|
||||||
|
sif::error << "PdecHandler::irqOperation: Unmasking IRQ failed" << std::endl;
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = poll(&fds, 1, IRQ_TIMEOUT_MS);
|
||||||
|
if (ret == 0) {
|
||||||
|
// No TCs for timeout period
|
||||||
|
checkLocks();
|
||||||
|
lockCheckCd.resetTimer();
|
||||||
|
} else if (ret >= 1) {
|
||||||
|
nb = read(fd, &info, sizeof(info));
|
||||||
|
if (nb == static_cast<ssize_t>(sizeof(info))) {
|
||||||
|
uint32_t pisr = *(registerBaseAddress + PDEC_PISR_OFFSET);
|
||||||
|
if ((pisr & TC_NEW_MASK) == TC_NEW_MASK) {
|
||||||
|
// handle TC
|
||||||
|
handleNewTc();
|
||||||
|
}
|
||||||
|
if ((pisr & TC_ABORT_MASK) == TC_ABORT_MASK) {
|
||||||
|
tcAbortCounter += 1;
|
||||||
|
}
|
||||||
|
if ((pisr & NEW_FAR_MASK) == NEW_FAR_MASK) {
|
||||||
|
// Read FAR here
|
||||||
|
CURRENT_FAR = readFar();
|
||||||
|
}
|
||||||
|
if (lockCheckCd.hasTimedOut()) {
|
||||||
|
checkLocks();
|
||||||
|
lockCheckCd.resetTimer();
|
||||||
|
}
|
||||||
|
// Clear interrupts with dummy read
|
||||||
|
ret = *(registerBaseAddress + PDEC_PIR_OFFSET);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sif::error << "PdecHandler::irqOperation: Poll error with errno " << errno << ": "
|
||||||
|
<< strerror(errno) << std::endl;
|
||||||
|
triggerEvent(POLL_ERROR_PDEC, errno);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::WAIT_FOR_RECOVERY:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sif::error << "PdecHandler::performOperation: Invalid state" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
void PdecHandler::readCommandQueue(void) {
|
void PdecHandler::readCommandQueue(void) {
|
||||||
CommandMessage commandMessage;
|
CommandMessage commandMessage;
|
||||||
ReturnValue_t result = returnvalue::FAILED;
|
ReturnValue_t result = returnvalue::FAILED;
|
||||||
@ -177,13 +231,65 @@ void PdecHandler::readCommandQueue(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t PdecHandler::getCommandQueue() const { return commandQueue->getId(); }
|
||||||
|
|
||||||
|
void PdecHandler::writePdecConfigDuringReset(PdecConfig& pdecConfig) {
|
||||||
|
*(memoryBaseAddress + FRAME_HEADER_OFFSET) = pdecConfig.getConfigWord(0);
|
||||||
|
*(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = pdecConfig.getConfigWord(1);
|
||||||
|
|
||||||
|
// Configure all MAP IDs as invalid
|
||||||
|
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
|
||||||
|
*(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PdecHandler::resetFarStatFlag() {
|
||||||
|
uint32_t pdecFar = readFar();
|
||||||
|
if ((pdecFar & FAR_STAT_MASK) != FAR_STAT_MASK) {
|
||||||
|
sif::warning << "PdecHandler::resetFarStatFlag: FAR register stat bit is not set."
|
||||||
|
<< " Read value: 0x" << std::hex << static_cast<unsigned int>(pdecFar)
|
||||||
|
<< std::endl;
|
||||||
|
CURRENT_FAR = pdecFar;
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
||||||
|
sif::debug << "PdecHandler::resetFarStatFlag: read FAR with value: 0x" << std::hex << pdecFar
|
||||||
|
<< std::endl;
|
||||||
|
#endif /* OBSW_DEBUG_PDEC_HANDLER == 1 */
|
||||||
|
CURRENT_FAR = pdecFar;
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PdecHandler::releasePdec() {
|
||||||
|
ReturnValue_t result = returnvalue::OK;
|
||||||
|
result = gpioComIF->pullHigh(pdecReset);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
sif::error << "PdecHandler::releasePdec: Failed to release PDEC reset signal" << std::endl;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool PdecHandler::newTcReceived() {
|
bool PdecHandler::newTcReceived() {
|
||||||
uint32_t pdecFar = *(registerBaseAddress + PDEC_FAR_OFFSET);
|
uint32_t pdecFar = readFar();
|
||||||
|
|
||||||
if (pdecFar >> STAT_POSITION != NEW_FAR_RECEIVED) {
|
if (pdecFar >> STAT_POSITION != NEW_FAR_RECEIVED) {
|
||||||
|
CURRENT_FAR = pdecFar;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!checkFrameAna(pdecFar)) {
|
if (!checkFrameAna(pdecFar)) {
|
||||||
|
CURRENT_FAR = pdecFar;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -331,7 +437,6 @@ void PdecHandler::handleNewTc() {
|
|||||||
printTC(tcLength);
|
printTC(tcLength);
|
||||||
#endif /* OBSW_DEBUG_PDEC_HANDLER */
|
#endif /* OBSW_DEBUG_PDEC_HANDLER */
|
||||||
|
|
||||||
#if OBSW_TC_FROM_PDEC == 1
|
|
||||||
store_address_t storeId;
|
store_address_t storeId;
|
||||||
result = tcStore->addData(&storeId, tcSegment + 1, tcLength - 1);
|
result = tcStore->addData(&storeId, tcSegment + 1, tcLength - 1);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
@ -349,7 +454,6 @@ void PdecHandler::handleNewTc() {
|
|||||||
tcStore->deleteData(storeId);
|
tcStore->deleteData(storeId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif /* OBSW_TC_FROM_PDEC == 1 */
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -500,6 +604,8 @@ void PdecHandler::printPdecMon() {
|
|||||||
sif::info << std::setw(30) << std::left << "Start sequence lock: " << lock << std::endl;
|
sif::info << std::setw(30) << std::left << "Start sequence lock: " << lock << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t PdecHandler::readFar() { return *(registerBaseAddress + PDEC_FAR_OFFSET); }
|
||||||
|
|
||||||
std::string PdecHandler::getMonStatusString(uint32_t status) {
|
std::string PdecHandler::getMonStatusString(uint32_t status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case TC_CHANNEL_INACTIVE:
|
case TC_CHANNEL_INACTIVE:
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef LINUX_OBC_PDECHANDLER_H_
|
#ifndef LINUX_OBC_PDECHANDLER_H_
|
||||||
#define LINUX_OBC_PDECHANDLER_H_
|
#define LINUX_OBC_PDECHANDLER_H_
|
||||||
|
|
||||||
|
#include <fsfw/timemanager/Countdown.h>
|
||||||
|
|
||||||
#include "OBSWConfig.h"
|
#include "OBSWConfig.h"
|
||||||
#include "PdecConfig.h"
|
#include "PdecConfig.h"
|
||||||
#include "fsfw/action/ActionHelper.h"
|
#include "fsfw/action/ActionHelper.h"
|
||||||
@ -13,6 +15,13 @@
|
|||||||
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
|
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
|
||||||
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
|
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
|
||||||
|
|
||||||
|
struct UioNames {
|
||||||
|
const char* configMemory;
|
||||||
|
const char* ramMemory;
|
||||||
|
const char* registers;
|
||||||
|
const char* irq;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class controls the PDEC IP Core implemented in the programmable logic of the
|
* @brief This class controls the PDEC IP Core implemented in the programmable logic of the
|
||||||
* Zynq-7020. All registers and memories of the PDEC IP Core are accessed via UIO
|
* Zynq-7020. All registers and memories of the PDEC IP Core are accessed via UIO
|
||||||
@ -33,6 +42,10 @@
|
|||||||
*/
|
*/
|
||||||
class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasActionsIF {
|
class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasActionsIF {
|
||||||
public:
|
public:
|
||||||
|
static constexpr dur_millis_t IRQ_TIMEOUT_MS = 500;
|
||||||
|
|
||||||
|
enum class Modes { POLLED, IRQ };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructor
|
* @brief Constructor
|
||||||
* @param objectId Object ID of PDEC handler system object
|
* @param objectId Object ID of PDEC handler system object
|
||||||
@ -43,8 +56,7 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
|
|||||||
* @param uioregsiters String of uio device file same mapped to the PDEC register space
|
* @param uioregsiters String of uio device file same mapped to the PDEC register space
|
||||||
*/
|
*/
|
||||||
PdecHandler(object_id_t objectId, object_id_t tcDestinationId, LinuxLibgpioIF* gpioComIF,
|
PdecHandler(object_id_t objectId, object_id_t tcDestinationId, LinuxLibgpioIF* gpioComIF,
|
||||||
gpioId_t pdecReset, std::string uioConfigMemory, std::string uioRamMemory,
|
gpioId_t pdecReset, UioNames names);
|
||||||
std::string uioRegisters);
|
|
||||||
|
|
||||||
virtual ~PdecHandler();
|
virtual ~PdecHandler();
|
||||||
|
|
||||||
@ -74,10 +86,13 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
|
|||||||
static const Event LOST_CARRIER_LOCK_PDEC = MAKE_EVENT(5, severity::INFO);
|
static const Event LOST_CARRIER_LOCK_PDEC = MAKE_EVENT(5, severity::INFO);
|
||||||
//! [EXPORT] : [COMMENT] Lost bit lock
|
//! [EXPORT] : [COMMENT] Lost bit lock
|
||||||
static const Event LOST_BIT_LOCK_PDEC = MAKE_EVENT(6, severity::INFO);
|
static const Event LOST_BIT_LOCK_PDEC = MAKE_EVENT(6, severity::INFO);
|
||||||
|
static constexpr Event POLL_ERROR_PDEC = event::makeEvent(SUBSYSTEM_ID, 7, severity::MEDIUM);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::PDEC_HANDLER;
|
static const uint8_t INTERFACE_ID = CLASS_ID::PDEC_HANDLER;
|
||||||
|
|
||||||
|
static constexpr Modes OP_MODE = Modes::IRQ;
|
||||||
|
|
||||||
static const ReturnValue_t ABANDONED_CLTU = MAKE_RETURN_CODE(0xA0);
|
static const ReturnValue_t ABANDONED_CLTU = MAKE_RETURN_CODE(0xA0);
|
||||||
static const ReturnValue_t FRAME_DIRTY = MAKE_RETURN_CODE(0xA1);
|
static const ReturnValue_t FRAME_DIRTY = MAKE_RETURN_CODE(0xA1);
|
||||||
static const ReturnValue_t FRAME_ILLEGAL_ONE_REASON = MAKE_RETURN_CODE(0xA2);
|
static const ReturnValue_t FRAME_ILLEGAL_ONE_REASON = MAKE_RETURN_CODE(0xA2);
|
||||||
@ -112,48 +127,6 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
|
|||||||
// Print PDEC monitor register
|
// Print PDEC monitor register
|
||||||
static const ActionId_t PRINT_PDEC_MON = 1;
|
static const ActionId_t PRINT_PDEC_MON = 1;
|
||||||
|
|
||||||
static const uint8_t STAT_POSITION = 31;
|
|
||||||
static const uint8_t FRAME_ANA_POSITION = 28;
|
|
||||||
static const uint8_t IREASON_POSITION = 25;
|
|
||||||
|
|
||||||
static const uint8_t NEW_FAR_RECEIVED = 0;
|
|
||||||
|
|
||||||
static const uint32_t FRAME_ANA_MASK = 0x70000000;
|
|
||||||
static const uint32_t IREASON_MASK = 0x0E000000;
|
|
||||||
|
|
||||||
static const uint32_t TC_CHANNEL_INACTIVE = 0x0;
|
|
||||||
static const uint32_t TC_CHANNEL_ACTIVE = 0x1;
|
|
||||||
static const uint32_t TC_CHANNEL_TIMEDOUT = 0x2;
|
|
||||||
|
|
||||||
static const uint32_t TC0_STATUS_MASK = 0x3;
|
|
||||||
static const uint32_t TC1_STATUS_MASK = 0xC;
|
|
||||||
static const uint32_t TC2_STATUS_MASK = 0x300;
|
|
||||||
static const uint32_t TC3_STATUS_MASK = 0xC00;
|
|
||||||
static const uint32_t TC4_STATUS_MASK = 0x30000;
|
|
||||||
static const uint32_t TC5_STATUS_MASK = 0xc00000;
|
|
||||||
// Lock register set to 1 when start sequence has been found (CLTU is beeing processed)
|
|
||||||
static const uint32_t LOCK_MASK = 0xc00000;
|
|
||||||
|
|
||||||
static const uint32_t TC0_STATUS_POS = 0;
|
|
||||||
static const uint32_t TC1_STATUS_POS = 2;
|
|
||||||
static const uint32_t TC2_STATUS_POS = 4;
|
|
||||||
static const uint32_t TC3_STATUS_POS = 6;
|
|
||||||
static const uint32_t TC4_STATUS_POS = 8;
|
|
||||||
static const uint32_t TC5_STATUS_POS = 10;
|
|
||||||
// Lock register set to 1 when start sequence has been found (CLTU is beeing processed)
|
|
||||||
static const uint32_t LOCK_POS = 12;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UIO is 4 byte aligned. Thus offset is calculated with "true offset" / 4
|
|
||||||
* Example: PDEC_FAR = 0x2840 => Offset in virtual address space is 0xA10
|
|
||||||
*/
|
|
||||||
static const uint32_t PDEC_FAR_OFFSET = 0xA10;
|
|
||||||
static const uint32_t PDEC_CLCW_OFFSET = 0xA12;
|
|
||||||
static const uint32_t PDEC_BFREE_OFFSET = 0xA24;
|
|
||||||
static const uint32_t PDEC_BPTR_OFFSET = 0xA25;
|
|
||||||
static const uint32_t PDEC_SLEN_OFFSET = 0xA26;
|
|
||||||
static const uint32_t PDEC_MON_OFFSET = 0xA27;
|
|
||||||
|
|
||||||
#ifdef TE0720_1CFA
|
#ifdef TE0720_1CFA
|
||||||
static const int CONFIG_MEMORY_MAP_SIZE = 0x400;
|
static const int CONFIG_MEMORY_MAP_SIZE = 0x400;
|
||||||
static const int RAM_MAP_SIZE = 0x4000;
|
static const int RAM_MAP_SIZE = 0x4000;
|
||||||
@ -227,16 +200,69 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
|
|||||||
|
|
||||||
enum class State : uint8_t { INIT, RUNNING, WAIT_FOR_RECOVERY };
|
enum class State : uint8_t { INIT, RUNNING, WAIT_FOR_RECOVERY };
|
||||||
|
|
||||||
|
static uint32_t CURRENT_FAR;
|
||||||
|
|
||||||
|
Countdown lockCheckCd = Countdown(IRQ_TIMEOUT_MS);
|
||||||
|
object_id_t tcDestinationId;
|
||||||
|
|
||||||
|
AcceptsTelecommandsIF* tcDestination = nullptr;
|
||||||
|
|
||||||
|
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset signal is required to hold PDEC in reset state until the configuration has been
|
||||||
|
* written to the appropriate memory space.
|
||||||
|
* Can also be used to reboot PDEC in case of erros.
|
||||||
|
*/
|
||||||
|
gpioId_t pdecReset = gpio::NO_GPIO;
|
||||||
|
|
||||||
|
uint32_t tcAbortCounter = 0;
|
||||||
|
|
||||||
|
ActionHelper actionHelper;
|
||||||
|
|
||||||
|
StorageManagerIF* tcStore = nullptr;
|
||||||
|
|
||||||
|
MessageQueueIF* commandQueue = nullptr;
|
||||||
|
|
||||||
|
State state = State::INIT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer pointing to base address of the PDEC memory space.
|
||||||
|
* This address is equivalent with the base address of the section named configuration area in
|
||||||
|
* the PDEC datasheet.
|
||||||
|
*/
|
||||||
|
uint32_t* memoryBaseAddress = nullptr;
|
||||||
|
|
||||||
|
uint32_t* ramBaseAddress = nullptr;
|
||||||
|
|
||||||
|
// Pointer pointing to base address of register space
|
||||||
|
uint32_t* registerBaseAddress = nullptr;
|
||||||
|
|
||||||
|
uint8_t tcSegment[TC_SEGMENT_LEN];
|
||||||
|
|
||||||
|
// Used to check carrier and bit lock changes (default set to no rf and no bitlock)
|
||||||
|
uint32_t lastClcw = 0xC000;
|
||||||
|
|
||||||
|
bool carrierLock = false;
|
||||||
|
bool bitLock = false;
|
||||||
|
|
||||||
|
UioNames uioNames;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reads and handles messages stored in the commandQueue
|
* @brief Reads and handles messages stored in the commandQueue
|
||||||
*/
|
*/
|
||||||
void readCommandQueue(void);
|
void readCommandQueue(void);
|
||||||
|
|
||||||
|
ReturnValue_t polledOperation();
|
||||||
|
ReturnValue_t irqOperation();
|
||||||
|
|
||||||
|
uint32_t readFar();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This functions writes the configuration parameters to the configuration
|
* @brief This functions writes the configuration parameters to the configuration
|
||||||
* section of the PDEC.
|
* section of the PDEC.
|
||||||
*/
|
*/
|
||||||
void writePdecConfig();
|
void writePdecConfigDuringReset(PdecConfig& config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reading the FAR resets the set stat flag which signals a new TC. Without clearing
|
* @brief Reading the FAR resets the set stat flag which signals a new TC. Without clearing
|
||||||
@ -343,58 +369,6 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
|
|||||||
void printPdecMon();
|
void printPdecMon();
|
||||||
|
|
||||||
std::string getMonStatusString(uint32_t status);
|
std::string getMonStatusString(uint32_t status);
|
||||||
|
|
||||||
object_id_t tcDestinationId;
|
|
||||||
|
|
||||||
AcceptsTelecommandsIF* tcDestination = nullptr;
|
|
||||||
|
|
||||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset signal is required to hold PDEC in reset state until the configuration has been
|
|
||||||
* written to the appropriate memory space.
|
|
||||||
* Can also be used to reboot PDEC in case of erros.
|
|
||||||
*/
|
|
||||||
gpioId_t pdecReset = gpio::NO_GPIO;
|
|
||||||
|
|
||||||
// UIO device file giving access to the PDEC configuration memory section
|
|
||||||
std::string uioConfigMemory;
|
|
||||||
|
|
||||||
// UIO device file giving access to the PDEC RAM section
|
|
||||||
std::string uioRamMemory;
|
|
||||||
|
|
||||||
// UIO device file giving access to the PDEC register space
|
|
||||||
std::string uioRegisters;
|
|
||||||
|
|
||||||
ActionHelper actionHelper;
|
|
||||||
|
|
||||||
StorageManagerIF* tcStore = nullptr;
|
|
||||||
|
|
||||||
MessageQueueIF* commandQueue = nullptr;
|
|
||||||
|
|
||||||
State state = State::INIT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pointer pointing to base address of the PDEC memory space.
|
|
||||||
* This address is equivalent with the base address of the section named configuration area in
|
|
||||||
* the PDEC datasheet.
|
|
||||||
*/
|
|
||||||
uint32_t* memoryBaseAddress = nullptr;
|
|
||||||
|
|
||||||
uint32_t* ramBaseAddress = nullptr;
|
|
||||||
|
|
||||||
// Pointer pointing to base address of register space
|
|
||||||
uint32_t* registerBaseAddress = nullptr;
|
|
||||||
|
|
||||||
uint32_t pdecFar = 0;
|
|
||||||
|
|
||||||
uint8_t tcSegment[TC_SEGMENT_LEN];
|
|
||||||
|
|
||||||
// Used to check carrier and bit lock changes (default set to no rf and no bitlock)
|
|
||||||
uint32_t lastClcw = 0xC000;
|
|
||||||
|
|
||||||
bool carrierLock = false;
|
|
||||||
bool bitLock = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* LINUX_OBC_PDECHANDLER_H_ */
|
#endif /* LINUX_OBC_PDECHANDLER_H_ */
|
||||||
|
61
linux/ipcore/pdec.h
Normal file
61
linux/ipcore/pdec.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#ifndef LINUX_OBC_PDEC_H_
|
||||||
|
#define LINUX_OBC_PDEC_H_
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace pdec {
|
||||||
|
|
||||||
|
static const uint8_t STAT_POSITION = 31;
|
||||||
|
static const uint8_t FRAME_ANA_POSITION = 28;
|
||||||
|
static const uint8_t IREASON_POSITION = 25;
|
||||||
|
|
||||||
|
static const uint8_t NEW_FAR_RECEIVED = 0;
|
||||||
|
|
||||||
|
static constexpr uint32_t NEW_FAR_MASK = 1 << 2;
|
||||||
|
static constexpr uint32_t TC_ABORT_MASK = 1 << 1;
|
||||||
|
static constexpr uint32_t TC_NEW_MASK = 1 << 0;
|
||||||
|
|
||||||
|
static constexpr uint32_t FAR_STAT_MASK = 1 << 31;
|
||||||
|
|
||||||
|
static const uint32_t FRAME_ANA_MASK = 0x70000000;
|
||||||
|
static const uint32_t IREASON_MASK = 0x0E000000;
|
||||||
|
|
||||||
|
static const uint32_t TC_CHANNEL_INACTIVE = 0x0;
|
||||||
|
static const uint32_t TC_CHANNEL_ACTIVE = 0x1;
|
||||||
|
static const uint32_t TC_CHANNEL_TIMEDOUT = 0x2;
|
||||||
|
|
||||||
|
static const uint32_t TC0_STATUS_MASK = 0x3;
|
||||||
|
static const uint32_t TC1_STATUS_MASK = 0xC;
|
||||||
|
static const uint32_t TC2_STATUS_MASK = 0x300;
|
||||||
|
static const uint32_t TC3_STATUS_MASK = 0xC00;
|
||||||
|
static const uint32_t TC4_STATUS_MASK = 0x30000;
|
||||||
|
static const uint32_t TC5_STATUS_MASK = 0xc00000;
|
||||||
|
// Lock register set to 1 when start sequence has been found (CLTU is beeing processed)
|
||||||
|
static const uint32_t LOCK_MASK = 0xc00000;
|
||||||
|
|
||||||
|
static const uint32_t TC0_STATUS_POS = 0;
|
||||||
|
static const uint32_t TC1_STATUS_POS = 2;
|
||||||
|
static const uint32_t TC2_STATUS_POS = 4;
|
||||||
|
static const uint32_t TC3_STATUS_POS = 6;
|
||||||
|
static const uint32_t TC4_STATUS_POS = 8;
|
||||||
|
static const uint32_t TC5_STATUS_POS = 10;
|
||||||
|
// Lock register set to 1 when start sequence has been found (CLTU is beeing processed)
|
||||||
|
static const uint32_t LOCK_POS = 12;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UIO is 4 byte aligned. Thus offset is calculated with "true offset" / 4
|
||||||
|
* Example: PDEC_FAR = 0x2840 => Offset in virtual address space is 0xA10
|
||||||
|
*/
|
||||||
|
static constexpr uint32_t PDEC_PISR_OFFSET = 0xA02;
|
||||||
|
static constexpr uint32_t PDEC_PIR_OFFSET = 0xA03;
|
||||||
|
static constexpr uint32_t PDEC_IMR_OFFSET = 0xA04;
|
||||||
|
static const uint32_t PDEC_FAR_OFFSET = 0xA10;
|
||||||
|
static const uint32_t PDEC_CLCW_OFFSET = 0xA12;
|
||||||
|
static const uint32_t PDEC_BFREE_OFFSET = 0xA24;
|
||||||
|
static const uint32_t PDEC_BPTR_OFFSET = 0xA25;
|
||||||
|
static const uint32_t PDEC_SLEN_OFFSET = 0xA26;
|
||||||
|
static const uint32_t PDEC_MON_OFFSET = 0xA27;
|
||||||
|
|
||||||
|
} // namespace pdec
|
||||||
|
|
||||||
|
#endif /* LINUX_OBC_PDEC_H_ */
|
@ -80,14 +80,14 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
|||||||
StorageManagerIF* tcStore;
|
StorageManagerIF* tcStore;
|
||||||
StorageManagerIF* tmStore;
|
StorageManagerIF* tmStore;
|
||||||
{
|
{
|
||||||
PoolManager::LocalPoolConfig poolCfg = {{200, 16}, {200, 32}, {150, 64},
|
PoolManager::LocalPoolConfig poolCfg = {{250, 16}, {250, 32}, {250, 64},
|
||||||
{100, 128}, {100, 1024}, {100, 2048}};
|
{150, 128}, {120, 1024}, {120, 2048}};
|
||||||
tcStore = new PoolManager(objects::TC_STORE, poolCfg);
|
tcStore = new PoolManager(objects::TC_STORE, poolCfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PoolManager::LocalPoolConfig poolCfg = {{300, 16}, {300, 32}, {100, 64},
|
PoolManager::LocalPoolConfig poolCfg = {{300, 16}, {300, 32}, {250, 64},
|
||||||
{100, 128}, {100, 1024}, {100, 2048}};
|
{150, 128}, {120, 1024}, {120, 2048}};
|
||||||
tmStore = new PoolManager(objects::TM_STORE, poolCfg);
|
tmStore = new PoolManager(objects::TM_STORE, poolCfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
tmtc
2
tmtc
@ -1 +1 @@
|
|||||||
Subproject commit f3609b81799790578c095262f33c11add3c0b078
|
Subproject commit 074eb82e78d2d0f9e0ecfbc2020cd8d0532255ba
|
Loading…
Reference in New Issue
Block a user