I2C fatal error counter #496

Merged
meggert merged 6 commits from feature_i2c_fatal_error_counter into develop 2023-03-21 13:38:29 +01:00
8 changed files with 34 additions and 8 deletions

View File

@ -22,7 +22,7 @@ will consitute of a breaking change warranting a new major release:
the `MEKF` on its own once. This way, there will not be an event spam and operators will have the `MEKF` on its own once. This way, there will not be an event spam and operators will have
to look into the reason of wrong outputs. To restore the reset ability, an action command has to look into the reason of wrong outputs. To restore the reset ability, an action command has
been added. been added.
- Contingency handling for non-working I2C bus bug. Reboot the system if the I2C is not working.
## Fixed ## Fixed

View File

@ -31,14 +31,15 @@
xsc::Chip CoreController::CURRENT_CHIP = xsc::Chip::NO_CHIP; xsc::Chip CoreController::CURRENT_CHIP = xsc::Chip::NO_CHIP;
xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY; xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY;
CoreController::CoreController(object_id_t objectId) CoreController::CoreController(object_id_t objectId, const std::atomic_uint16_t& i2cErrors)
: ExtendedControllerBase(objectId, 5), : ExtendedControllerBase(objectId, 5),
cmdExecutor(4096), cmdExecutor(4096),
cmdReplyBuf(4096, true), cmdReplyBuf(4096, true),
cmdRepliesSizes(128), cmdRepliesSizes(128),
opDivider5(5), opDivider5(5),
opDivider10(10), opDivider10(10),
hkSet(this) { hkSet(this),
i2cErrors(i2cErrors) {
cmdExecutor.setRingBuffer(&cmdReplyBuf, &cmdRepliesSizes); cmdExecutor.setRingBuffer(&cmdReplyBuf, &cmdRepliesSizes);
try { try {
sdcMan = SdCardManager::instance(); sdcMan = SdCardManager::instance();
@ -107,6 +108,12 @@ void CoreController::performControlOperation() {
sdStateMachine(); sdStateMachine();
performMountedSdCardOperations(); performMountedSdCardOperations();
readHkData(); readHkData();
if(i2cErrors >= 5) {
bool protOpPerformed = false;
triggerEvent(I2C_UNAVAILABLE_REBOOT);
gracefulShutdownTasks(CURRENT_CHIP, CURRENT_COPY, protOpPerformed);
std::system("xsc_boot_copy -r");
}
if (shellCmdIsExecuting) { if (shellCmdIsExecuting) {
bool replyReceived = false; bool replyReceived = false;
// TODO: We could read the data in the ring buffer and send it as an action data reply. // TODO: We could read the data in the ring buffer and send it as an action data reply.

View File

@ -15,6 +15,7 @@
#include "fsfw/controller/ExtendedControllerBase.h" #include "fsfw/controller/ExtendedControllerBase.h"
#include "mission/devices/devicedefinitions/GPSDefinitions.h" #include "mission/devices/devicedefinitions/GPSDefinitions.h"
#include "mission/trace.h" #include "mission/trace.h"
#include <atomic>
class Timer; class Timer;
class SdCardManager; class SdCardManager;
@ -131,8 +132,9 @@ class CoreController : public ExtendedControllerBase {
//! P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. //! P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1.
//! P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1. //! P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1.
static constexpr Event INDIVIDUAL_BOOT_COUNTS = event::makeEvent(SUBSYSTEM_ID, 8, severity::INFO); static constexpr Event INDIVIDUAL_BOOT_COUNTS = event::makeEvent(SUBSYSTEM_ID, 8, severity::INFO);
static constexpr Event I2C_UNAVAILABLE_REBOOT = event::makeEvent(SUBSYSTEM_ID, 10, severity::MEDIUM);
CoreController(object_id_t objectId); CoreController(object_id_t objectId, const std::atomic_uint16_t& i2cErrors);
virtual ~CoreController(); virtual ~CoreController();
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
@ -262,6 +264,7 @@ class CoreController : public ExtendedControllerBase {
PoolEntry<float> plVoltageEntry = PoolEntry<float>(0.0); PoolEntry<float> plVoltageEntry = PoolEntry<float>(0.0);
core::HkSet hkSet; core::HkSet hkSet;
const std::atomic_uint16_t& i2cErrors;
#if OBSW_SD_CARD_MUST_BE_ON == 1 #if OBSW_SD_CARD_MUST_BE_ON == 1
bool remountAttemptFlag = true; bool remountAttemptFlag = true;

View File

@ -123,6 +123,7 @@ using gpio::Levels;
ResetArgs RESET_ARGS_GNSS; ResetArgs RESET_ARGS_GNSS;
std::atomic_bool LINK_STATE = CcsdsIpCoreHandler::LINK_DOWN; std::atomic_bool LINK_STATE = CcsdsIpCoreHandler::LINK_DOWN;
std::atomic_uint16_t I2C_FATAL_ERRORS = 0;
void Factory::setStaticFrameworkObjectIds() { void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_PACKET_DISTRIBUTOR; PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_PACKET_DISTRIBUTOR;
@ -953,7 +954,7 @@ void ObjectFactory::createImtqComponents(PowerSwitchIF* pwrSwitcher) {
auto* imtqAssy = new ImtqAssembly(objects::IMTQ_ASSY); auto* imtqAssy = new ImtqAssembly(objects::IMTQ_ASSY);
imtqAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM); imtqAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
new ImtqPollingTask(objects::IMTQ_POLLING); new ImtqPollingTask(objects::IMTQ_POLLING, I2C_FATAL_ERRORS);
I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, imtq::MAX_REPLY_SIZE, q7s::I2C_PL_EIVE); I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, imtq::MAX_REPLY_SIZE, q7s::I2C_PL_EIVE);
auto imtqHandler = new ImtqHandler(objects::IMTQ_HANDLER, objects::IMTQ_POLLING, imtqI2cCookie, auto imtqHandler = new ImtqHandler(objects::IMTQ_HANDLER, objects::IMTQ_POLLING, imtqI2cCookie,
pcdu::Switches::PDU1_CH3_MGT_5V); pcdu::Switches::PDU1_CH3_MGT_5V);

View File

@ -12,6 +12,7 @@
#include <mission/tmtc/PusTmFunnel.h> #include <mission/tmtc/PusTmFunnel.h>
#include <string> #include <string>
#include <atomic>
class LinuxLibgpioIF; class LinuxLibgpioIF;
class SerialComIF; class SerialComIF;
@ -22,6 +23,8 @@ class HealthTableIF;
class AcsBoardAssembly; class AcsBoardAssembly;
class GpioIF; class GpioIF;
extern std::atomic_uint16_t I2C_FATAL_ERRORS;
namespace ObjectFactory { namespace ObjectFactory {
struct CcsdsComponentArgs { struct CcsdsComponentArgs {

View File

@ -38,7 +38,7 @@ void ObjectFactory::produce(void* args) {
q7s::gpioCallbacks::initSpiCsDecoder(gpioComIF); q7s::gpioCallbacks::initSpiCsDecoder(gpioComIF);
gpioCallbacks::disableAllDecoder(gpioComIF); gpioCallbacks::disableAllDecoder(gpioComIF);
new CoreController(objects::CORE_CONTROLLER); new CoreController(objects::CORE_CONTROLLER, I2C_FATAL_ERRORS);
createPcduComponents(gpioComIF, &pwrSwitcher); createPcduComponents(gpioComIF, &pwrSwitcher);
auto* stackHandler = new Stack5VHandler(*pwrSwitcher); auto* stackHandler = new Stack5VHandler(*pwrSwitcher);

View File

@ -10,7 +10,9 @@
#include "fsfw/FSFW.h" #include "fsfw/FSFW.h"
ImtqPollingTask::ImtqPollingTask(object_id_t imtqPollingTask) : SystemObject(imtqPollingTask) { ImtqPollingTask::ImtqPollingTask(object_id_t imtqPollingTask,
std::atomic_uint16_t& i2cFatalErrors): SystemObject(imtqPollingTask),
i2cFatalErrors(i2cFatalErrors) {
semaphore = SemaphoreFactory::instance()->createBinarySemaphore(); semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
semaphore->acquire(); semaphore->acquire();
ipcLock = MutexFactory::instance()->createMutex(); ipcLock = MutexFactory::instance()->createMutex();
@ -427,12 +429,20 @@ ReturnValue_t ImtqPollingTask::performI2cFullRequest(uint8_t* reply, size_t repl
if (ioctl(fd, I2C_SLAVE, i2cAddr) < 0) { if (ioctl(fd, I2C_SLAVE, i2cAddr) < 0) {
sif::warning << "Opening IMTQ slave device failed with code " << errno << ": " sif::warning << "Opening IMTQ slave device failed with code " << errno << ": "
<< strerror(errno) << std::endl; << strerror(errno) << std::endl;
if(errno == EBUSY) {
i2cFatalErrors++;
}
} }
int written = write(fd, cmdBuf.data(), cmdLen); int written = write(fd, cmdBuf.data(), cmdLen);
if (written < 0) { if (written < 0) {
sif::error << "IMTQ: Failed to send with error code " << errno sif::error << "IMTQ: Failed to send with error code " << errno
<< ". Error description: " << strerror(errno) << std::endl; << ". Error description: " << strerror(errno) << std::endl;
// This is a weird issue which sometimes occurs on debug builds. All I2C buses are busy
// for all writes,
if(errno == EBUSY) {
i2cFatalErrors++;
}
return returnvalue::FAILED; return returnvalue::FAILED;
} else if (static_cast<size_t>(written) != cmdLen) { } else if (static_cast<size_t>(written) != cmdLen) {
sif::error << "IMTQ: Could not write all bytes" << std::endl; sif::error << "IMTQ: Could not write all bytes" << std::endl;

View File

@ -8,12 +8,13 @@
#include "fsfw/objectmanager/SystemObject.h" #include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/tasks/ExecutableObjectIF.h" #include "fsfw/tasks/ExecutableObjectIF.h"
#include "mission/devices/devicedefinitions/imtqHelpers.h" #include "mission/devices/devicedefinitions/imtqHelpers.h"
#include <atomic>
class ImtqPollingTask : public SystemObject, class ImtqPollingTask : public SystemObject,
public ExecutableObjectIF, public ExecutableObjectIF,
public DeviceCommunicationIF { public DeviceCommunicationIF {
public: public:
ImtqPollingTask(object_id_t imtqPollingTask); ImtqPollingTask(object_id_t imtqPollingTask, std::atomic_uint16_t& i2cFatalErrors);
ReturnValue_t performOperation(uint8_t operationCode) override; ReturnValue_t performOperation(uint8_t operationCode) override;
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
@ -28,6 +29,7 @@ class ImtqPollingTask : public SystemObject,
ReturnValue_t comStatus = returnvalue::OK; ReturnValue_t comStatus = returnvalue::OK;
MutexIF* ipcLock; MutexIF* ipcLock;
MutexIF* bufLock; MutexIF* bufLock;
std::atomic_uint16_t& i2cFatalErrors;
I2cCookie* i2cCookie = nullptr; I2cCookie* i2cCookie = nullptr;
const char* i2cDev = nullptr; const char* i2cDev = nullptr;
address_t i2cAddr = 0; address_t i2cAddr = 0;