Merge branch 'develop' into meier/pdec-config-persistent

This commit is contained in:
Jakob Meier
2023-02-21 15:34:16 +01:00
221 changed files with 11565 additions and 5368 deletions

View File

@ -22,15 +22,14 @@ using namespace pdec;
uint32_t PdecHandler::CURRENT_FAR = 0;
PdecHandler::PdecHandler(object_id_t objectId, object_id_t tcDestinationId,
LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, UioNames names,
object_id_t globalConfigHandlerId)
LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, UioNames names)
: SystemObject(objectId),
tcDestinationId(tcDestinationId),
gpioComIF(gpioComIF),
pdecReset(pdecReset),
actionHelper(this, nullptr),
uioNames(names),
globalConfigHandlerId(globalConfigHandlerId) {
paramHelper(this) {
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
QUEUE_SIZE, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
@ -77,12 +76,6 @@ ReturnValue_t PdecHandler::initialize() {
return returnvalue::FAILED;
}
globalConfigHandler = ObjectManager::instance()->get<StorageManagerIF>(objects::GLOBAL_JSON_CFG);
if (globalConfigHandler == nullptr) {
sif::error << "PdecHandler::initialize: Invalid global config handler" << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
result = pdecConfig.write();
if (result != returnvalue::OK) {
sif::error << "PdecHandler::initialize: Failed to write PDEC config" << std::endl;
@ -113,6 +106,7 @@ ReturnValue_t PdecHandler::performOperation(uint8_t operationCode) {
} else if (OP_MODE == Modes::IRQ) {
return irqOperation();
}
return returnvalue::FAILED;
}
ReturnValue_t PdecHandler::polledOperation() {
@ -146,6 +140,7 @@ ReturnValue_t PdecHandler::polledOperation() {
return returnvalue::OK;
}
// See https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt.html for more information.
ReturnValue_t PdecHandler::irqOperation() {
ReturnValue_t result = returnvalue::OK;
int fd = open(uioNames.irq, O_RDWR);
@ -155,15 +150,17 @@ ReturnValue_t PdecHandler::irqOperation() {
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);
// Clear interrupts with dummy read before unmasking the interrupt. Use a volatile to prevent
// read being optimized away.
volatile uint32_t dummy = *(registerBaseAddress + PDEC_PIR_OFFSET);
while (true) {
// Default value to unmask IRQ on the write call.
info = 1;
readCommandQueue();
switch (state) {
case State::INIT:
@ -180,9 +177,12 @@ ReturnValue_t PdecHandler::irqOperation() {
nb = write(fd, &info, sizeof(info));
if (nb != static_cast<ssize_t>(sizeof(info))) {
sif::error << "PdecHandler::irqOperation: Unmasking IRQ failed" << std::endl;
triggerEvent(WRITE_SYSCALL_ERROR_PDEC, errno);
close(fd);
state = State::INIT;
return returnvalue::FAILED;
}
struct pollfd fds = {.fd = fd, .events = POLLIN, .revents = 0};
ret = poll(&fds, 1, IRQ_TIMEOUT_MS);
if (ret == 0) {
// No TCs for timeout period
@ -209,12 +209,15 @@ ReturnValue_t PdecHandler::irqOperation() {
lockCheckCd.resetTimer();
}
// Clear interrupts with dummy read
ret = *(registerBaseAddress + PDEC_PIR_OFFSET);
dummy = *(registerBaseAddress + PDEC_PIR_OFFSET);
}
} else {
sif::error << "PdecHandler::irqOperation: Poll error with errno " << errno << ": "
<< strerror(errno) << std::endl;
triggerEvent(POLL_ERROR_PDEC, errno);
triggerEvent(POLL_SYSCALL_ERROR_PDEC, errno);
close(fd);
state = State::INIT;
return returnvalue::FAILED;
}
break;
}
@ -225,21 +228,27 @@ ReturnValue_t PdecHandler::irqOperation() {
break;
}
}
// To avoid compiler warning
static_cast<void>(dummy);
return returnvalue::OK;
}
void PdecHandler::readCommandQueue(void) {
CommandMessage commandMessage;
CommandMessage message;
ReturnValue_t result = returnvalue::FAILED;
result = commandQueue->receiveMessage(&commandMessage);
result = commandQueue->receiveMessage(&message);
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) {
return;
}
CommandMessage reply;
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, commandMessage.getCommand());
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, message.getCommand());
commandQueue->reply(&reply);
return;
}
@ -371,12 +380,12 @@ bool PdecHandler::checkFrameAna(uint32_t pdecFar) {
FrameAna_t frameAna = static_cast<FrameAna_t>((pdecFar & FRAME_ANA_MASK) >> FRAME_ANA_POSITION);
switch (frameAna) {
case (FrameAna_t::ABANDONED_CLTU): {
triggerEvent(INVALID_TC_FRAME, ABANDONED_CLTU);
triggerEvent(INVALID_TC_FRAME, ABANDONED_CLTU_RETVAL);
sif::warning << "PdecHandler::checkFrameAna: Abondoned CLTU" << std::endl;
break;
}
case (FrameAna_t::FRAME_DIRTY): {
triggerEvent(INVALID_TC_FRAME, FRAME_DIRTY);
triggerEvent(INVALID_TC_FRAME, FRAME_DIRTY_RETVAL);
sif::warning << "PdecHandler::checkFrameAna: Frame dirty" << std::endl;
break;
}
@ -391,13 +400,13 @@ bool PdecHandler::checkFrameAna(uint32_t pdecFar) {
break;
}
case (FrameAna_t::AD_DISCARDED_LOCKOUT): {
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_LOCKOUT);
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_LOCKOUT_RETVAL);
sif::warning << "PdecHandler::checkFrameAna: AD frame discarded because of lockout"
<< std::endl;
break;
}
case (FrameAna_t::AD_DISCARDED_WAIT): {
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_LOCKOUT);
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_LOCKOUT_RETVAL);
sif::warning << "PdecHandler::checkFrameAna: AD frame discarded because of wait" << std::endl;
break;
}
@ -426,40 +435,40 @@ void PdecHandler::handleIReason(uint32_t pdecFar, ReturnValue_t parameter1) {
IReason_t ireason = static_cast<IReason_t>((pdecFar & IREASON_MASK) >> IREASON_POSITION);
switch (ireason) {
case (IReason_t::NO_REPORT): {
triggerEvent(INVALID_TC_FRAME, parameter1, NO_REPORT);
triggerEvent(INVALID_TC_FRAME, parameter1, NO_REPORT_RETVAL);
sif::info << "PdecHandler::handleIReason: No illegal report" << std::endl;
break;
}
case (IReason_t::ERROR_VERSION_NUMBER): {
triggerEvent(INVALID_TC_FRAME, parameter1, ERROR_VERSION_NUMBER);
triggerEvent(INVALID_TC_FRAME, parameter1, ERROR_VERSION_NUMBER_RETVAL);
sif::info << "PdecHandler::handleIReason: Error in version number and reserved A and B "
<< "fields" << std::endl;
break;
}
case (IReason_t::ILLEGAL_COMBINATION): {
triggerEvent(INVALID_TC_FRAME, parameter1, ILLEGAL_COMBINATION);
triggerEvent(INVALID_TC_FRAME, parameter1, ILLEGAL_COMBINATION_RETVAL);
sif::info << "PdecHandler::handleIReason: Illegal combination (AC) of bypass and control "
<< "command flags" << std::endl;
break;
}
case (IReason_t::INVALID_SC_ID): {
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_SC_ID);
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_SC_ID_RETVAL);
sif::info << "PdecHandler::handleIReason: Invalid spacecraft identifier " << std::endl;
break;
}
case (IReason_t::INVALID_VC_ID_MSB): {
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_MSB);
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_MSB_RETVAL);
sif::info << "PdecHandler::handleIReason: VC identifier bit 0 to 4 did not match "
<< std::endl;
break;
}
case (IReason_t::INVALID_VC_ID_LSB): {
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_LSB);
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_LSB_RETVAL);
sif::info << "PdecHandler::handleIReason: VC identifier bit 5 did not match " << std::endl;
break;
}
case (IReason_t::NS_NOT_ZERO): {
triggerEvent(INVALID_TC_FRAME, parameter1, NS_NOT_ZERO);
triggerEvent(INVALID_TC_FRAME, parameter1, NS_NOT_ZERO_RETVAL);
sif::info << "PdecHandler::handleIReason: N(S) of BC or BD frame not set to all zeros"
<< std::endl;
break;