From fe285888750659964bfcc47c993fe5daf654e536 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 29 Apr 2022 10:56:43 +0200 Subject: [PATCH 01/74] repoint tmtc submodule --- tmtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtc b/tmtc index 76da8042..168b6622 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 76da8042a4601087e99fa856af241afe9e43695d +Subproject commit 168b662288175f9db77a5796a02f38cb66911092 From 5888d90fbcd0a117f020abb9800ee6f6229eef2b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 29 Apr 2022 11:16:53 +0200 Subject: [PATCH 02/74] continued reboot command --- bsp_q7s/core/CoreController.cpp | 53 ++++++++++++++++++++++----------- bsp_q7s/core/CoreController.h | 10 +++++-- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 208999c2..da6a5807 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -211,8 +211,13 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ rewriteRebootFile(rebootFile); return HasActionsIF::EXECUTION_FINISHED; } + case (XSC_REBOOT_OBC): { + // Warning: This function will never return, because it reboots the system + return actionXscReboot(data, size); + } case (REBOOT_OBC): { - return actionPerformReboot(data, size); + // Warning: This function will never return, because it reboots the system + return actionReboot(data, size); } default: { return HasActionsIF::INVALID_ACTION_ID; @@ -844,25 +849,18 @@ void CoreController::initPrint() { #endif } -ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t size) { +ReturnValue_t CoreController::actionXscReboot(const uint8_t *data, size_t size) { if (size < 1) { return HasActionsIF::INVALID_PARAMETERS; } bool rebootSameBootCopy = data[0]; - bool protOpPerformed; + bool protOpPerformed = false; + SdCardManager::instance()->setBlocking(true); if (rebootSameBootCopy) { #if OBSW_VERBOSE_LEVEL >= 1 sif::info << "CoreController::actionPerformReboot: Rebooting on current image" << std::endl; #endif - // Attempt graceful shutdown by unmounting and switching off SD cards - SdCardManager::instance()->switchOffSdCard(sd::SdCard::SLOT_0); - SdCardManager::instance()->switchOffSdCard(sd::SdCard::SLOT_1); - // If any boot copies are unprotected - ReturnValue_t retval = setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true, - protOpPerformed, false); - if (retval == HasReturnvaluesIF::RETURN_OK and protOpPerformed) { - sif::info << "Running slot was writeprotected before reboot" << std::endl; - } + gracefulShutdownTasks(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, protOpPerformed); int result = std::system("xsc_boot_copy -r"); if (result != 0) { utility::handleSystemError(result, "CoreController::executeAction"); @@ -884,12 +882,8 @@ ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t si auto tgtChip = static_cast(data[1]); auto tgtCopy = static_cast(data[2]); - ReturnValue_t retval = - setBootCopyProtection(static_cast(data[1]), static_cast(data[2]), true, - protOpPerformed, false); - if (retval == HasReturnvaluesIF::RETURN_OK and protOpPerformed) { - sif::info << "Target slot was writeprotected before reboot" << std::endl; - } + // This function can not really fail + gracefulShutdownTasks(tgtChip, tgtCopy, protOpPerformed); switch (tgtChip) { case (xsc::Chip::CHIP_0): { @@ -930,6 +924,29 @@ ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t si return HasReturnvaluesIF::RETURN_FAILED; } +ReturnValue_t CoreController::actionReboot(const uint8_t *data, size_t size) { + bool protOpPerformed = false; + gracefulShutdownTasks(xsc::Chip::CHIP_0, xsc::Copy::COPY_0, protOpPerformed); + std::system("reboot"); + return RETURN_OK; +} + +ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy copy, + bool &protOpPerformed) { + // Attempt graceful shutdown by unmounting and switching off SD cards + SdCardManager::instance()->switchOffSdCard(sd::SdCard::SLOT_0); + SdCardManager::instance()->switchOffSdCard(sd::SdCard::SLOT_1); + // If any boot copies are unprotected + ReturnValue_t result = setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true, + protOpPerformed, false); + if (result == HasReturnvaluesIF::RETURN_OK and protOpPerformed) { + // TODO: Would be nice to notify operator. But we can't use the filesystem anymore + // and a reboot is imminent. Use scratch buffer? + sif::info << "Running slot was writeprotected before reboot" << std::endl; + } + return result; +} + CoreController::~CoreController() {} void CoreController::determinePreferredSdCard() { diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index dee06530..ede76890 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -67,8 +67,11 @@ class CoreController : public ExtendedControllerBase { static constexpr ActionId_t SWITCH_IMG_LOCK = 7; static constexpr ActionId_t SET_MAX_REBOOT_CNT = 8; - static constexpr ActionId_t REBOOT_OBC = 32; + //! Reboot using the xsc_boot_copy command + static constexpr ActionId_t XSC_REBOOT_OBC = 32; static constexpr ActionId_t MOUNT_OTHER_COPY = 33; + //! Reboot using the reboot command + static constexpr ActionId_t REBOOT_OBC = 34; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE; @@ -221,7 +224,10 @@ class CoreController : public ExtendedControllerBase { ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size); - ReturnValue_t actionPerformReboot(const uint8_t* data, size_t size); + ReturnValue_t actionXscReboot(const uint8_t* data, size_t size); + ReturnValue_t actionReboot(const uint8_t* data, size_t size); + + ReturnValue_t gracefulShutdownTasks(xsc::Chip chip, xsc::Copy copy, bool& protOpPerformed); void performWatchdogControlOperation(); From 50c363fb6f4ef490fca06e121ec04e995449e10e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 9 May 2022 21:29:54 +0200 Subject: [PATCH 03/74] new RTD reader module handling all RTD SPI Communication --- linux/ObjectFactory.cpp | 48 +-- linux/devices/CMakeLists.txt | 4 + linux/devices/Max31865RtdReader.cpp | 289 ++++++++++++++++++ linux/devices/Max31865RtdReader.h | 92 ++++++ mission/devices/Max31865PT1000Handler.cpp | 122 ++++---- mission/devices/Max31865PT1000Handler.h | 5 +- .../devicedefinitions/Max31865Definitions.h | 26 +- .../Max31865DeviceDefinitions.cpp | 1 + mission/system/TcsBoardAssembly.cpp | 12 +- mission/system/TcsBoardAssembly.h | 5 +- tmtc | 2 +- 11 files changed, 510 insertions(+), 96 deletions(-) create mode 100644 linux/devices/Max31865RtdReader.cpp create mode 100644 linux/devices/Max31865RtdReader.h create mode 100644 mission/devices/devicedefinitions/Max31865DeviceDefinitions.cpp diff --git a/linux/ObjectFactory.cpp b/linux/ObjectFactory.cpp index fcf1f81f..5a740c33 100644 --- a/linux/ObjectFactory.cpp +++ b/linux/ObjectFactory.cpp @@ -265,34 +265,36 @@ void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF, {addresses::RTD_IC_17, gpioIds::RTD_IC_17}, {addresses::RTD_IC_18, gpioIds::RTD_IC_18}, }}; - std::array rtdIds = {objects::RTD_0_IC3_PLOC_HEATSPREADER, - objects::RTD_1_IC4_PLOC_MISSIONBOARD, - objects::RTD_2_IC5_4K_CAMERA, - objects::RTD_3_IC6_DAC_HEATSPREADER, - objects::RTD_4_IC7_STARTRACKER, - objects::RTD_5_IC8_RW1_MX_MY, - objects::RTD_6_IC9_DRO, - objects::RTD_7_IC10_SCEX, - objects::RTD_8_IC11_X8, - objects::RTD_9_IC12_HPA, - objects::RTD_10_IC13_PL_TX, - objects::RTD_11_IC14_MPA, - objects::RTD_12_IC15_ACU, - objects::RTD_13_IC16_PLPCDU_HEATSPREADER, - objects::RTD_14_IC17_TCS_BOARD, - objects::RTD_15_IC18_IMTQ}; + std::array, NUMBER_RTDS> rtdInfos = {{ + {objects::RTD_0_IC3_PLOC_HEATSPREADER, "RTD_0_PLOC_HEATSPREADER"}, + {objects::RTD_1_IC4_PLOC_MISSIONBOARD, "RTD_1_PLOC_MISSIONBOARD"}, + {objects::RTD_2_IC5_4K_CAMERA, "RTD_2_4K_CAMERA"}, + {objects::RTD_3_IC6_DAC_HEATSPREADER, "RTD_3_DAC_HEATSPREADER"}, + {objects::RTD_4_IC7_STARTRACKER, "RTD_4_STARTRACKER"}, + {objects::RTD_5_IC8_RW1_MX_MY, "RTD_5_RW1_MX_MY"}, + {objects::RTD_6_IC9_DRO, "RTD_6_DRO"}, + {objects::RTD_7_IC10_SCEX, "RTD_7_SCEX"}, + {objects::RTD_8_IC11_X8, "RTD_8_X8"}, + {objects::RTD_9_IC12_HPA, "RTD_9_HPA"}, + {objects::RTD_10_IC13_PL_TX, "RTD_10_PL_TX,"}, + {objects::RTD_11_IC14_MPA, "RTD_11_MPA"}, + {objects::RTD_12_IC15_ACU, "RTD_12_ACU"}, + {objects::RTD_13_IC16_PLPCDU_HEATSPREADER, "RTD_13_PLPCDU_HEATSPREADER"}, + {objects::RTD_14_IC17_TCS_BOARD, "RTD_14_TCS_BOARD"}, + {objects::RTD_15_IC18_IMTQ, "RTD_15_IMTQ"}, + }}; std::array rtdCookies = {}; std::array rtds = {}; RtdFdir* rtdFdir = nullptr; for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) { - rtdCookies[idx] = - new SpiCookie(cookieArgs[idx].first, cookieArgs[idx].second, spiDev, - Max31865Definitions::MAX_REPLY_SIZE, spi::RTD_MODE, spi::RTD_SPEED); - rtds[idx] = new Max31865PT1000Handler(rtdIds[idx], objects::SPI_COM_IF, rtdCookies[idx]); + rtdCookies[idx] = new SpiCookie(cookieArgs[idx].first, cookieArgs[idx].second, spiDev, + MAX31865::MAX_REPLY_SIZE, spi::RTD_MODE, spi::RTD_SPEED); + rtds[idx] = + new Max31865PT1000Handler(rtdInfos[idx].first, objects::SPI_COM_IF, rtdCookies[idx]); rtds[idx]->setParent(objects::TCS_BOARD_ASS); - rtdFdir = new RtdFdir(rtdIds[idx]); + rtdFdir = new RtdFdir(rtdInfos[idx].first); rtds[idx]->setCustomFdir(rtdFdir); - rtds[idx]->setDeviceIdx(idx + 3); + rtds[idx]->setDeviceInfo(idx + 3, rtdInfos[idx].second); #if OBSW_DEBUG_RTD == 1 rtds[idx]->setDebugMode(true); #endif @@ -306,7 +308,7 @@ void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF, } } #endif // OBSW_TEST_RTD == 1 - TcsBoardHelper helper(rtdIds); + TcsBoardHelper helper(rtdInfos); TcsBoardAssembly* tcsBoardAss = new TcsBoardAssembly(objects::TCS_BOARD_ASS, objects::NO_OBJECT, pwrSwitcher, pcdu::Switches::PDU1_CH0_TCS_BOARD_3V3, helper); diff --git a/linux/devices/CMakeLists.txt b/linux/devices/CMakeLists.txt index 00d407e8..e65987c6 100644 --- a/linux/devices/CMakeLists.txt +++ b/linux/devices/CMakeLists.txt @@ -4,5 +4,9 @@ if(EIVE_BUILD_GPSD_GPS_HANDLER) ) endif() +target_sources(${OBSW_NAME} PRIVATE + Max31865RtdReader.cpp +) + add_subdirectory(ploc) add_subdirectory(startracker) diff --git a/linux/devices/Max31865RtdReader.cpp b/linux/devices/Max31865RtdReader.cpp new file mode 100644 index 00000000..0e2f9724 --- /dev/null +++ b/linux/devices/Max31865RtdReader.cpp @@ -0,0 +1,289 @@ +#include +#include + +Max31865RtdReader::Max31865RtdReader(object_id_t objectId, SpiComIF* comIF) + : SystemObject(objectId), rtds(NUM_RTDS), comIF(comIF) { + readerMutex = MutexFactory::instance()->createMutex(); +} + +ReturnValue_t Max31865RtdReader::performOperation(uint8_t operationCode) { + using namespace MAX31865; + while (true) { + rtdMainLoop(); + // Read all RTDs at once every 500 ms for now + TaskFactory::delayTask(500); + } +} + +void Max31865RtdReader::rtdMainLoop() { + using namespace MAX31865; + if (periodicInitHandling()) { + // 10 ms delay for VBIAS startup + TaskFactory::delayTask(10); + } else { + // No devices usable (e.g. TCS board off) + return; + } + + periodicReadReqHandling(); + // After requesting, 65 milliseconds delay required + TaskFactory::delayTask(65); + + periodicReadHandling(); +} + +bool Max31865RtdReader::rtdCanBeUsed(uint8_t idx) { + if (rtds[idx]->active and rtds[idx]->configured) { + return true; + } + return false; +} + +bool Max31865RtdReader::periodicInitHandling() { + using namespace MAX31865; + MutexGuard mg(readerMutex); + ReturnValue_t result = RETURN_OK; + if (mg.getLockResult() != RETURN_OK) { + // TODO: Emit warning, return + return false; + } + + bool someRtdActive = false; + for (auto& rtd : rtds) { + if (rtd == nullptr) { + continue; + } + if (rtd->active and not rtd->configured) { + someRtdActive = true; + uint8_t cfg = (Bias::OFF << CfgBitPos::BIAS_SEL) | (Wires::FOUR_WIRE << CfgBitPos::WIRE_SEL) | + (ConvMode::NORM_OFF << CfgBitPos::CONV_MODE) | + (1 << CfgBitPos::FAULTY_STATUS_CLEAR); + result = writeCfgReg(rtd->spiCookie, cfg); + if (result != HasReturnvaluesIF::RETURN_OK) { + // TODO: Check retval + } + rtd->configured = true; + } + } + if (not someRtdActive) { + return false; + } + bool someRtdUsable = false; + for (auto& rtd : rtds) { + if (rtd == nullptr) { + continue; + } + if (rtdCanBeUsed(rtd->idx)) { + someRtdUsable = true; + result = biasSel(Bias::ON, rtd->spiCookie); + } + } + return someRtdUsable; +} + +void Max31865RtdReader::periodicReadReqHandling() { + using namespace MAX31865; + MutexGuard mg(readerMutex); + if (mg.getLockResult() != RETURN_OK) { + // TODO: Emit warning, return + return; + } + // Now request one shot config for all active RTDs + for (auto& rtd : rtds) { + if (rtd == nullptr) { + continue; + } + if (rtd->active) { + uint8_t currentCfg = 0; + auto result = readCfgReg(rtd->spiCookie, currentCfg); + if (result != RETURN_OK) { + // TODO: Emit warning, FDIR? + continue; + } + currentCfg |= (1 << CfgBitPos::ONE_SHOT); + result = writeCfgReg(rtd->spiCookie, currentCfg); + } + } +} + +void Max31865RtdReader::periodicReadHandling() { + using namespace MAX31865; + auto result = RETURN_OK; + MutexGuard mg(readerMutex); + if (mg.getLockResult() != RETURN_OK) { + // TODO: Emit warning, return + return; + } + // Now read the RTD values + for (auto& rtd : rtds) { + if (rtd == nullptr) { + continue; + } + if (rtd->active) { + uint16_t rtdVal = 0; + bool faultBitSet = false; + result = readRtdVal(rtd->spiCookie, rtdVal, faultBitSet); + if (result != RETURN_OK) { + // TODO: Emit warning, FDIR? + continue; + } + if (faultBitSet) { + rtd->db.faultBitSet = faultBitSet; + } + rtd->db.rtdVal = rtdVal; + } + } + for (auto& rtd : rtds) { + if (rtd == nullptr) { + continue; + } + if (rtd->active) { + result = biasSel(Bias::OFF, rtd->spiCookie); + } + } +} + +ReturnValue_t Max31865RtdReader::initializeInterface(CookieIF* cookie) { + if (cookie == nullptr) { + throw std::invalid_argument("Invalid MAX31865 Reader Cookie"); + } + auto* rtdCookie = dynamic_cast(cookie); + ReturnValue_t result = comIF->initializeInterface(rtdCookie->spiCookie); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + if (rtdCookie->idx > NUM_RTDS) { + throw std::invalid_argument("Invalid RTD index"); + } + rtds[rtdCookie->idx] = rtdCookie; + return RETURN_OK; +} + +ReturnValue_t Max31865RtdReader::sendMessage(CookieIF* cookie, const uint8_t* sendData, + size_t sendLen) { + if (cookie == nullptr) { + return RETURN_FAILED; + } + if (sendLen < 1) { + return RETURN_OK; + } + MutexGuard mg(readerMutex); + if (mg.getLockResult() != RETURN_OK) { + // TODO: Emit warning, return + return RETURN_FAILED; + } + auto* rtdCookie = dynamic_cast(cookie); + uint8_t cmdRaw = sendData[0]; + if (cmdRaw > 2) { + // TODO: Emit warning, invalid command + return RETURN_OK; + } + auto cmd = static_cast(sendData[0]); + switch (cmd) { + case (RtdCommands::ON): { + if (not rtdCookie->active) { + rtdCookie->active = true; + rtdCookie->configured = false; + } + break; + } + case (RtdCommands::OFF): { + rtdCookie->active = false; + rtdCookie->configured = false; + break; + } + case (RtdCommands::CFG): { + // TODO: Only implement if needed + break; + } + } + return RETURN_OK; +} + +ReturnValue_t Max31865RtdReader::getSendSuccess(CookieIF* cookie) { return RETURN_OK; } + +ReturnValue_t Max31865RtdReader::requestReceiveMessage(CookieIF* cookie, size_t requestLen) { + return RETURN_OK; +} + +ReturnValue_t Max31865RtdReader::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, + size_t* size) { + MutexGuard mg(readerMutex); + if (mg.getLockResult() != RETURN_OK) { + // TODO: Emit warning + return RETURN_FAILED; + } + auto* rtdCookie = dynamic_cast(cookie); + uint8_t* exchangePtr = rtdCookie->exchangeBuf.data(); + size_t serLen = 0; + auto result = rtdCookie->db.serialize(&exchangePtr, &serLen, rtdCookie->exchangeBuf.size(), + SerializeIF::Endianness::MACHINE); + if (result != RETURN_OK) { + // TODO: Emit warning + return RETURN_FAILED; + } + *buffer = reinterpret_cast(rtdCookie->exchangeBuf.data()); + *size = rtdCookie->db.getSerializedSize(); + return RETURN_OK; +} + +ReturnValue_t Max31865RtdReader::writeCfgReg(SpiCookie* cookie, uint8_t cfg) { + using namespace MAX31865; + uint8_t cmd[2] = {REG_CONFIG | WRITE_BIT, cfg}; + return comIF->sendMessage(cookie, cmd, 2); +} + +ReturnValue_t Max31865RtdReader::biasSel(MAX31865::Bias bias, SpiCookie* cookie) { + using namespace MAX31865; + uint8_t currentCfg = 0; + auto result = readCfgReg(cookie, currentCfg); + if (result != RETURN_OK) { + return result; + } + if (bias == MAX31865::Bias::OFF) { + currentCfg &= ~(1 << CfgBitPos::BIAS_SEL); + } else { + currentCfg |= (1 << CfgBitPos::BIAS_SEL); + } + return writeCfgReg(cookie, currentCfg); +} + +ReturnValue_t Max31865RtdReader::readCfgReg(SpiCookie* cookie, uint8_t& cfg) { + using namespace MAX31865; + uint8_t cmd[2] = {REG_CONFIG, 0}; + ReturnValue_t result = comIF->sendMessage(cookie, cmd, 2); + if (result != RETURN_OK) { + return RETURN_FAILED; + } + uint8_t reply[2] = {}; + uint8_t* replyPtr = reply; + size_t dummyLen = 0; + result = comIF->readReceivedMessage(cookie, &replyPtr, &dummyLen); + if (result != RETURN_OK) { + return result; + } + cfg = reply[1]; + return RETURN_OK; +} + +ReturnValue_t Max31865RtdReader::readRtdVal(SpiCookie* cookie, uint16_t& val, bool& faultBitSet) { + using namespace MAX31865; + uint8_t cmd[3] = {REG_RTD, 0, 0}; + auto result = comIF->sendMessage(cookie, cmd, 3); + if (result != RETURN_OK) { + return RETURN_FAILED; + } + uint8_t reply[3] = {}; + uint8_t* replyPtr = reply; + size_t dummyLen = 0; + result = comIF->readReceivedMessage(cookie, &replyPtr, &dummyLen); + if (result != RETURN_OK) { + return result; + } + if (reply[2] & 0b0000'0001) { + faultBitSet = true; + } + // Shift 1 to the right to remove fault bit + val = ((reply[1] << 8) | reply[2]) >> 1; + return result; +} diff --git a/linux/devices/Max31865RtdReader.h b/linux/devices/Max31865RtdReader.h new file mode 100644 index 00000000..4a1bbb47 --- /dev/null +++ b/linux/devices/Max31865RtdReader.h @@ -0,0 +1,92 @@ +#ifndef LINUX_DEVICES_MAX31865RTDREADER_H_ +#define LINUX_DEVICES_MAX31865RTDREADER_H_ + +#include +#include +#include +#include + +#include "fsfw/devicehandlers/DeviceCommunicationIF.h" +#include "mission/devices/devicedefinitions/Max31865Definitions.h" + +static constexpr uint8_t NUM_RTDS = 16; + +enum RtdCommands : uint8_t { ON = 0, OFF = 1, CFG = 2 }; + +class ReadOutStruct : public SerialLinkedListAdapter { + public: + ReadOutStruct() { setLinks(); } + ReadOutStruct(uint32_t spiErrCnt, bool faultBitSet, uint8_t faultVal, uint16_t rtdVal) + : spiErrorCount(spiErrCnt), faultBitSet(faultBitSet), faultValue(faultVal), rtdVal(rtdVal) { + setLinks(); + } + + SerializeElement spiErrorCount = 0; + SerializeElement faultBitSet = false; + SerializeElement faultValue = 0; + SerializeElement rtdVal = 0; + + private: + void setLinks() { + setStart(&spiErrorCount); + spiErrorCount.setNext(&faultBitSet); + faultBitSet.setNext(&faultValue); + faultValue.setNext(&rtdVal); + }; +}; + +struct Max31865ReaderCookie { + Max31865ReaderCookie(){}; + Max31865ReaderCookie(object_id_t handlerId_, uint8_t idx_, const std::string& locString_, + SpiCookie* spiCookie_) + : idx(idx_), handlerId(handlerId_), locString(locString_), spiCookie(spiCookie_) {} + + uint8_t idx = 0; + object_id_t handlerId = objects::NO_OBJECT; + + std::string locString = ""; + std::array exchangeBuf{}; + bool active = false; + + bool configured = false; + + SpiCookie* spiCookie = nullptr; + + // Exchange data buffer struct + ReadOutStruct db; +}; + +class Max31865RtdReader : public SystemObject, + public ExecutableObjectIF, + public DeviceCommunicationIF { + public: + Max31865RtdReader(object_id_t objectId, SpiComIF* comIF); + void addRtd(Max31865ReaderCookie rtdCookie); + + [[noreturn]] ReturnValue_t performOperation(uint8_t operationCode) override; + + private: + std::vector rtds; + MutexIF* readerMutex; + + void rtdMainLoop(); + bool periodicInitHandling(); + void periodicReadReqHandling(); + void periodicReadHandling(); + + bool rtdCanBeUsed(uint8_t idx); + ReturnValue_t writeCfgReg(SpiCookie* cookie, uint8_t cfg); + ReturnValue_t biasSel(MAX31865::Bias bias, SpiCookie* cookie); + ReturnValue_t readCfgReg(SpiCookie* cookie, uint8_t& cfg); + ReturnValue_t readRtdVal(SpiCookie* cookie, uint16_t& val, bool& faultBitSet); + + ReturnValue_t initializeInterface(CookieIF* cookie) override; + ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override; + ReturnValue_t getSendSuccess(CookieIF* cookie) override; + ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override; + ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override; + + SpiComIF* comIF; +}; + +#endif /* LINUX_DEVICES_MAX31865RTDREADER_H_ */ diff --git a/mission/devices/Max31865PT1000Handler.cpp b/mission/devices/Max31865PT1000Handler.cpp index 580c8637..6ac888cd 100644 --- a/mission/devices/Max31865PT1000Handler.cpp +++ b/mission/devices/Max31865PT1000Handler.cpp @@ -93,13 +93,13 @@ void Max31865PT1000Handler::doShutDown() { ReturnValue_t Max31865PT1000Handler::buildNormalDeviceCommand(DeviceCommandId_t *id) { if (internalState == InternalState::RUNNING) { - *id = Max31865Definitions::REQUEST_RTD; + *id = MAX31865::REQUEST_RTD; return buildCommandFromCommand(*id, nullptr, 0); } else if (internalState == InternalState::REQUEST_FAULT_BYTE) { - *id = Max31865Definitions::REQUEST_FAULT_BYTE; + *id = MAX31865::REQUEST_FAULT_BYTE; return buildCommandFromCommand(*id, nullptr, 0); } else if (internalState == InternalState::CLEAR_FAULT_BYTE) { - *id = Max31865Definitions::CLEAR_FAULT_BYTE; + *id = MAX31865::CLEAR_FAULT_BYTE; return buildCommandFromCommand(*id, nullptr, 0); } else { return DeviceHandlerBase::NOTHING_TO_SEND; @@ -113,32 +113,32 @@ ReturnValue_t Max31865PT1000Handler::buildTransitionDeviceCommand(DeviceCommandI case (InternalState::RUNNING): return DeviceHandlerBase::NOTHING_TO_SEND; case (InternalState::CONFIGURE): { - *id = Max31865Definitions::CONFIG_CMD; + *id = MAX31865::CONFIG_CMD; uint8_t config[1] = {DEFAULT_CONFIG}; return buildCommandFromCommand(*id, config, 1); } case (InternalState::REQUEST_CONFIG): { - *id = Max31865Definitions::REQUEST_CONFIG; + *id = MAX31865::REQUEST_CONFIG; return buildCommandFromCommand(*id, nullptr, 0); } case (InternalState::CONFIG_HIGH_THRESHOLD): { - *id = Max31865Definitions::WRITE_HIGH_THRESHOLD; + *id = MAX31865::WRITE_HIGH_THRESHOLD; return buildCommandFromCommand(*id, nullptr, 0); } case (InternalState::REQUEST_HIGH_THRESHOLD): { - *id = Max31865Definitions::REQUEST_HIGH_THRESHOLD; + *id = MAX31865::REQUEST_HIGH_THRESHOLD; return buildCommandFromCommand(*id, nullptr, 0); } case (InternalState::CONFIG_LOW_THRESHOLD): { - *id = Max31865Definitions::WRITE_LOW_THRESHOLD; + *id = MAX31865::WRITE_LOW_THRESHOLD; return buildCommandFromCommand(*id, nullptr, 0); } case (InternalState::REQUEST_LOW_THRESHOLD): { - *id = Max31865Definitions::REQUEST_LOW_THRESHOLD; + *id = MAX31865::REQUEST_LOW_THRESHOLD; return buildCommandFromCommand(*id, nullptr, 0); } case (InternalState::CLEAR_FAULT_BYTE): { - *id = Max31865Definitions::CLEAR_FAULT_BYTE; + *id = MAX31865::CLEAR_FAULT_BYTE; return buildCommandFromCommand(*id, nullptr, 0); } @@ -156,8 +156,8 @@ ReturnValue_t Max31865PT1000Handler::buildCommandFromCommand(DeviceCommandId_t d const uint8_t *commandData, size_t commandDataLen) { switch (deviceCommand) { - case (Max31865Definitions::CONFIG_CMD): { - commandBuffer[0] = static_cast(Max31865Definitions::CONFIG_CMD); + case (MAX31865::CONFIG_CMD): { + commandBuffer[0] = static_cast(MAX31865::CONFIG_CMD); if (commandDataLen == 1) { commandBuffer[1] = commandData[0]; DeviceHandlerBase::rawPacketLen = 2; @@ -167,54 +167,54 @@ ReturnValue_t Max31865PT1000Handler::buildCommandFromCommand(DeviceCommandId_t d return DeviceHandlerIF::NO_COMMAND_DATA; } } - case (Max31865Definitions::CLEAR_FAULT_BYTE): { - commandBuffer[0] = static_cast(Max31865Definitions::CONFIG_CMD); - commandBuffer[1] = Max31865Definitions::CLEAR_FAULT_BIT_VAL; + case (MAX31865::CLEAR_FAULT_BYTE): { + commandBuffer[0] = static_cast(MAX31865::CONFIG_CMD); + commandBuffer[1] = MAX31865::CLEAR_FAULT_BIT_VAL; DeviceHandlerBase::rawPacketLen = 2; DeviceHandlerBase::rawPacket = commandBuffer.data(); return HasReturnvaluesIF::RETURN_OK; } - case (Max31865Definitions::REQUEST_CONFIG): { - commandBuffer[0] = static_cast(Max31865Definitions::REQUEST_CONFIG); + case (MAX31865::REQUEST_CONFIG): { + commandBuffer[0] = static_cast(MAX31865::REQUEST_CONFIG); commandBuffer[1] = 0x00; // dummy byte DeviceHandlerBase::rawPacketLen = 2; DeviceHandlerBase::rawPacket = commandBuffer.data(); return HasReturnvaluesIF::RETURN_OK; } - case (Max31865Definitions::WRITE_HIGH_THRESHOLD): { - commandBuffer[0] = static_cast(Max31865Definitions::WRITE_HIGH_THRESHOLD); + case (MAX31865::WRITE_HIGH_THRESHOLD): { + commandBuffer[0] = static_cast(MAX31865::WRITE_HIGH_THRESHOLD); commandBuffer[1] = static_cast(HIGH_THRESHOLD >> 8); commandBuffer[2] = static_cast(HIGH_THRESHOLD & 0xFF); DeviceHandlerBase::rawPacketLen = 3; DeviceHandlerBase::rawPacket = commandBuffer.data(); return HasReturnvaluesIF::RETURN_OK; } - case (Max31865Definitions::REQUEST_HIGH_THRESHOLD): { - commandBuffer[0] = static_cast(Max31865Definitions::REQUEST_HIGH_THRESHOLD); + case (MAX31865::REQUEST_HIGH_THRESHOLD): { + commandBuffer[0] = static_cast(MAX31865::REQUEST_HIGH_THRESHOLD); commandBuffer[1] = 0x00; // dummy byte commandBuffer[2] = 0x00; // dummy byte DeviceHandlerBase::rawPacketLen = 3; DeviceHandlerBase::rawPacket = commandBuffer.data(); return HasReturnvaluesIF::RETURN_OK; } - case (Max31865Definitions::WRITE_LOW_THRESHOLD): { - commandBuffer[0] = static_cast(Max31865Definitions::WRITE_LOW_THRESHOLD); + case (MAX31865::WRITE_LOW_THRESHOLD): { + commandBuffer[0] = static_cast(MAX31865::WRITE_LOW_THRESHOLD); commandBuffer[1] = static_cast(LOW_THRESHOLD >> 8); commandBuffer[2] = static_cast(LOW_THRESHOLD & 0xFF); DeviceHandlerBase::rawPacketLen = 3; DeviceHandlerBase::rawPacket = commandBuffer.data(); return HasReturnvaluesIF::RETURN_OK; } - case (Max31865Definitions::REQUEST_LOW_THRESHOLD): { - commandBuffer[0] = static_cast(Max31865Definitions::REQUEST_LOW_THRESHOLD); + case (MAX31865::REQUEST_LOW_THRESHOLD): { + commandBuffer[0] = static_cast(MAX31865::REQUEST_LOW_THRESHOLD); commandBuffer[1] = 0x00; // dummy byte commandBuffer[2] = 0x00; // dummy byte DeviceHandlerBase::rawPacketLen = 3; DeviceHandlerBase::rawPacket = commandBuffer.data(); return HasReturnvaluesIF::RETURN_OK; } - case (Max31865Definitions::REQUEST_RTD): { - commandBuffer[0] = static_cast(Max31865Definitions::REQUEST_RTD); + case (MAX31865::REQUEST_RTD): { + commandBuffer[0] = static_cast(MAX31865::REQUEST_RTD); // two dummy bytes commandBuffer[1] = 0x00; commandBuffer[2] = 0x00; @@ -222,8 +222,8 @@ ReturnValue_t Max31865PT1000Handler::buildCommandFromCommand(DeviceCommandId_t d DeviceHandlerBase::rawPacket = commandBuffer.data(); return HasReturnvaluesIF::RETURN_OK; } - case (Max31865Definitions::REQUEST_FAULT_BYTE): { - commandBuffer[0] = static_cast(Max31865Definitions::REQUEST_FAULT_BYTE); + case (MAX31865::REQUEST_FAULT_BYTE): { + commandBuffer[0] = static_cast(MAX31865::REQUEST_FAULT_BYTE); commandBuffer[1] = 0x00; DeviceHandlerBase::rawPacketLen = 2; DeviceHandlerBase::rawPacket = commandBuffer.data(); @@ -236,15 +236,15 @@ ReturnValue_t Max31865PT1000Handler::buildCommandFromCommand(DeviceCommandId_t d } void Max31865PT1000Handler::fillCommandAndReplyMap() { - insertInCommandAndReplyMap(Max31865Definitions::CONFIG_CMD, 3); - insertInCommandAndReplyMap(Max31865Definitions::REQUEST_CONFIG, 3); - insertInCommandAndReplyMap(Max31865Definitions::WRITE_LOW_THRESHOLD, 3); - insertInCommandAndReplyMap(Max31865Definitions::REQUEST_LOW_THRESHOLD, 3); - insertInCommandAndReplyMap(Max31865Definitions::WRITE_HIGH_THRESHOLD, 3); - insertInCommandAndReplyMap(Max31865Definitions::REQUEST_HIGH_THRESHOLD, 3); - insertInCommandAndReplyMap(Max31865Definitions::REQUEST_RTD, 3, &sensorDataset); - insertInCommandAndReplyMap(Max31865Definitions::REQUEST_FAULT_BYTE, 3); - insertInCommandAndReplyMap(Max31865Definitions::CLEAR_FAULT_BYTE, 3); + insertInCommandAndReplyMap(MAX31865::CONFIG_CMD, 3); + insertInCommandAndReplyMap(MAX31865::REQUEST_CONFIG, 3); + insertInCommandAndReplyMap(MAX31865::WRITE_LOW_THRESHOLD, 3); + insertInCommandAndReplyMap(MAX31865::REQUEST_LOW_THRESHOLD, 3); + insertInCommandAndReplyMap(MAX31865::WRITE_HIGH_THRESHOLD, 3); + insertInCommandAndReplyMap(MAX31865::REQUEST_HIGH_THRESHOLD, 3); + insertInCommandAndReplyMap(MAX31865::REQUEST_RTD, 3, &sensorDataset); + insertInCommandAndReplyMap(MAX31865::REQUEST_FAULT_BYTE, 3); + insertInCommandAndReplyMap(MAX31865::CLEAR_FAULT_BYTE, 3); } ReturnValue_t Max31865PT1000Handler::scanForReply(const uint8_t *start, size_t remainingSize, @@ -253,7 +253,7 @@ ReturnValue_t Max31865PT1000Handler::scanForReply(const uint8_t *start, size_t r size_t configReplySize = 2; if (remainingSize == rtdReplySize and internalState == InternalState::RUNNING) { - *foundId = Max31865Definitions::REQUEST_RTD; + *foundId = MAX31865::REQUEST_RTD; *foundLen = rtdReplySize; return RETURN_OK; } @@ -262,24 +262,24 @@ ReturnValue_t Max31865PT1000Handler::scanForReply(const uint8_t *start, size_t r switch (internalState) { case (InternalState::CONFIG_HIGH_THRESHOLD): { *foundLen = 3; - *foundId = Max31865Definitions::WRITE_HIGH_THRESHOLD; + *foundId = MAX31865::WRITE_HIGH_THRESHOLD; commandExecuted = true; return RETURN_OK; } case (InternalState::REQUEST_HIGH_THRESHOLD): { *foundLen = 3; - *foundId = Max31865Definitions::REQUEST_HIGH_THRESHOLD; + *foundId = MAX31865::REQUEST_HIGH_THRESHOLD; return RETURN_OK; } case (InternalState::CONFIG_LOW_THRESHOLD): { *foundLen = 3; - *foundId = Max31865Definitions::WRITE_LOW_THRESHOLD; + *foundId = MAX31865::WRITE_LOW_THRESHOLD; commandExecuted = true; return RETURN_OK; } case (InternalState::REQUEST_LOW_THRESHOLD): { *foundLen = 3; - *foundId = Max31865Definitions::REQUEST_LOW_THRESHOLD; + *foundId = MAX31865::REQUEST_LOW_THRESHOLD; return RETURN_OK; } default: { @@ -293,13 +293,13 @@ ReturnValue_t Max31865PT1000Handler::scanForReply(const uint8_t *start, size_t r if (internalState == InternalState::CONFIGURE) { commandExecuted = true; *foundLen = configReplySize; - *foundId = Max31865Definitions::CONFIG_CMD; + *foundId = MAX31865::CONFIG_CMD; } else if (internalState == InternalState::REQUEST_FAULT_BYTE) { - *foundId = Max31865Definitions::REQUEST_FAULT_BYTE; + *foundId = MAX31865::REQUEST_FAULT_BYTE; *foundLen = 2; internalState = InternalState::RUNNING; } else if (internalState == InternalState::CLEAR_FAULT_BYTE) { - *foundId = Max31865Definitions::CLEAR_FAULT_BYTE; + *foundId = MAX31865::CLEAR_FAULT_BYTE; *foundLen = 2; if (mode == _MODE_START_UP) { commandExecuted = true; @@ -307,7 +307,7 @@ ReturnValue_t Max31865PT1000Handler::scanForReply(const uint8_t *start, size_t r internalState = InternalState::RUNNING; } } else { - *foundId = Max31865Definitions::REQUEST_CONFIG; + *foundId = MAX31865::REQUEST_CONFIG; *foundLen = configReplySize; } } @@ -318,7 +318,7 @@ ReturnValue_t Max31865PT1000Handler::scanForReply(const uint8_t *start, size_t r ReturnValue_t Max31865PT1000Handler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { switch (id) { - case (Max31865Definitions::REQUEST_CONFIG): { + case (MAX31865::REQUEST_CONFIG): { if (packet[1] != DEFAULT_CONFIG) { if (warningSwitch) { #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -342,7 +342,7 @@ ReturnValue_t Max31865PT1000Handler::interpretDeviceReply(DeviceCommandId_t id, } break; } - case (Max31865Definitions::REQUEST_LOW_THRESHOLD): { + case (MAX31865::REQUEST_LOW_THRESHOLD): { uint16_t readLowThreshold = packet[1] << 8 | packet[2]; if (readLowThreshold != LOW_THRESHOLD) { #if FSFW_VERBOSE_LEVEL >= 1 @@ -360,7 +360,7 @@ ReturnValue_t Max31865PT1000Handler::interpretDeviceReply(DeviceCommandId_t id, commandExecuted = true; break; } - case (Max31865Definitions::REQUEST_HIGH_THRESHOLD): { + case (MAX31865::REQUEST_HIGH_THRESHOLD): { uint16_t readHighThreshold = packet[1] << 8 | packet[2]; if (readHighThreshold != HIGH_THRESHOLD) { #if FSFW_VERBOSE_LEVEL >= 1 @@ -378,7 +378,7 @@ ReturnValue_t Max31865PT1000Handler::interpretDeviceReply(DeviceCommandId_t id, commandExecuted = true; break; } - case (Max31865Definitions::REQUEST_RTD): { + case (MAX31865::REQUEST_RTD): { // first bit of LSB reply byte is the fault bit uint8_t faultBit = packet[2] & 0b0000'0001; if (resetFaultBit) { @@ -403,9 +403,9 @@ ReturnValue_t Max31865PT1000Handler::interpretDeviceReply(DeviceCommandId_t id, #if OBSW_VERBOSE_LEVEL >= 1 if (debugDivider->checkAndIncrement()) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::info << "Max31865: ObjID " << std::hex << this->getObjectId() << " | RTD " - << std::dec << static_cast(deviceIdx) << ": R[Ohm] " << rtdValue - << " Ohms | Approx T[C]: " << approxTemp << std::endl; + sif::info << "Max31865: " << std::setw(28) << std::left << locString << std::right + << " | R[Ohm] " << rtdValue << " Ohms | Approx T[C]: " << approxTemp + << std::endl; #else sif::printInfo("Max31685: Measured resistance is %f Ohms\n", rtdValue); sif::printInfo("Approximated temperature is %f C\n", approxTemp); @@ -438,7 +438,7 @@ ReturnValue_t Max31865PT1000Handler::interpretDeviceReply(DeviceCommandId_t id, sensorDataset.temperatureCelcius = approxTemp; break; } - case (Max31865Definitions::REQUEST_FAULT_BYTE): { + case (MAX31865::REQUEST_FAULT_BYTE): { faultByte = packet[1]; #if OBSW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -512,10 +512,9 @@ ReturnValue_t Max31865PT1000Handler::getSwitches(const uint8_t **switches, ReturnValue_t Max31865PT1000Handler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(Max31865Definitions::PoolIds::RTD_VALUE, new PoolEntry({0})); - localDataPoolMap.emplace(Max31865Definitions::PoolIds::TEMPERATURE_C, - new PoolEntry({0}, 1, true)); - localDataPoolMap.emplace(Max31865Definitions::PoolIds::FAULT_BYTE, new PoolEntry({0})); + localDataPoolMap.emplace(MAX31865::PoolIds::RTD_VALUE, new PoolEntry({0})); + localDataPoolMap.emplace(MAX31865::PoolIds::TEMPERATURE_C, new PoolEntry({0}, 1, true)); + localDataPoolMap.emplace(MAX31865::PoolIds::FAULT_BYTE, new PoolEntry({0})); poolManager.subscribeForPeriodicPacket(sensorDataset.getSid(), false, 30.0, false); return HasReturnvaluesIF::RETURN_OK; } @@ -530,6 +529,9 @@ void Max31865PT1000Handler::modeChanged() { } } -void Max31865PT1000Handler::setDeviceIdx(uint8_t idx) { deviceIdx = idx; } +void Max31865PT1000Handler::setDeviceInfo(uint8_t idx, const std::string &locString_) { + deviceIdx = idx; + locString = locString_; +} void Max31865PT1000Handler::setDebugMode(bool enable) { this->debugMode = enable; } diff --git a/mission/devices/Max31865PT1000Handler.h b/mission/devices/Max31865PT1000Handler.h index 4f617b9d..9a6b5add 100644 --- a/mission/devices/Max31865PT1000Handler.h +++ b/mission/devices/Max31865PT1000Handler.h @@ -48,7 +48,7 @@ class Max31865PT1000Handler : public DeviceHandlerBase { static constexpr uint8_t DEFAULT_CONFIG = 0b11000001; void setInstantNormal(bool instantNormal); - void setDeviceIdx(uint8_t idx); + void setDeviceInfo(uint8_t idx, const std::string &locString); /** * Expected temperature range is -100 C and 100 C. @@ -109,11 +109,12 @@ class Max31865PT1000Handler : public DeviceHandlerBase { bool resetFaultBit = false; dur_millis_t startTime = 0; + std::string locString; uint8_t faultByte = 0; uint8_t deviceIdx = 0; std::array commandBuffer{0}; - Max31865Definitions::Max31865Set sensorDataset; + MAX31865::Max31865Set sensorDataset; sid_t sensorDatasetSid; #if OBSW_VERBOSE_LEVEL >= 1 diff --git a/mission/devices/devicedefinitions/Max31865Definitions.h b/mission/devices/devicedefinitions/Max31865Definitions.h index 58faaf97..efd81681 100644 --- a/mission/devices/devicedefinitions/Max31865Definitions.h +++ b/mission/devices/devicedefinitions/Max31865Definitions.h @@ -7,9 +7,26 @@ #include "objects/systemObjectList.h" -namespace Max31865Definitions { +namespace MAX31865 { enum PoolIds : lp_id_t { RTD_VALUE, TEMPERATURE_C, FAULT_BYTE }; +enum Wires : unsigned int { TWO_WIRE = 0, THREE_WIRE = 1, FOUR_WIRE = 0 }; + +enum ConvMode : unsigned int { NORM_OFF = 0, AUTO = 1 }; + +enum Bias : unsigned int { ON = 0, OFF = 1 }; + +enum FilterSel : unsigned int { FIFTY_HERTZ = 1, SIXTY_HERTZ = 0 }; + +enum CfgBitPos { + FILTER_SEL = 0, + FAULTY_STATUS_CLEAR = 1, + FDCC = 2, + WIRE_SEL = 4, + ONE_SHOT = 5, + CONV_MODE = 6, + BIAS_SEL = 7 +}; static constexpr DeviceCommandId_t CONFIG_CMD = 0x80; static constexpr DeviceCommandId_t WRITE_HIGH_THRESHOLD = 0x83; @@ -26,6 +43,11 @@ static constexpr DeviceCommandId_t CLEAR_FAULT_BYTE = 0x08; static constexpr uint32_t MAX31865_SET_ID = REQUEST_RTD; static constexpr uint8_t CLEAR_FAULT_BIT_VAL = 0b0000'0010; +static constexpr uint8_t WRITE_BIT = 0b10000000; + +static constexpr uint8_t REG_CONFIG = 0x00; +static constexpr uint8_t REG_RTD = 0x01; + static constexpr size_t MAX_REPLY_SIZE = 5; class Max31865Set : public StaticLocalDataSet { @@ -48,6 +70,6 @@ class Max31865Set : public StaticLocalDataSet { lp_var_t errorByte = lp_var_t(sid.objectId, PoolIds::FAULT_BYTE, this); }; -} // namespace Max31865Definitions +} // namespace MAX31865 #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_MAX13865DEFINITIONS_H_ */ diff --git a/mission/devices/devicedefinitions/Max31865DeviceDefinitions.cpp b/mission/devices/devicedefinitions/Max31865DeviceDefinitions.cpp new file mode 100644 index 00000000..0f050093 --- /dev/null +++ b/mission/devices/devicedefinitions/Max31865DeviceDefinitions.cpp @@ -0,0 +1 @@ +#include "Max31865Definitions.h" diff --git a/mission/system/TcsBoardAssembly.cpp b/mission/system/TcsBoardAssembly.cpp index f011c931..ec4bce70 100644 --- a/mission/system/TcsBoardAssembly.cpp +++ b/mission/system/TcsBoardAssembly.cpp @@ -10,7 +10,7 @@ TcsBoardAssembly::TcsBoardAssembly(object_id_t objectId, object_id_t parentId, eventQueue = QueueFactory::instance()->createMessageQueue(24); ModeListEntry entry; for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) { - entry.setObject(helper.rtdIds[idx]); + entry.setObject(helper.rtdInfos[idx].first); entry.setMode(MODE_OFF); entry.setSubmode(SUBMODE_NONE); entry.setInheritSubmode(false); @@ -57,7 +57,7 @@ ReturnValue_t TcsBoardAssembly::checkChildrenStateOn(Mode_t wantedMode, Submode_ int devsInWrongMode = 0; try { for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) { - if (childrenMap.at(helper.rtdIds[idx]).mode != wantedMode) { + if (childrenMap.at(helper.rtdInfos[idx].first).mode != wantedMode) { devsInWrongMode++; } } @@ -93,8 +93,8 @@ ReturnValue_t TcsBoardAssembly::isModeCombinationValid(Mode_t mode, Submode_t su ReturnValue_t TcsBoardAssembly::initialize() { ReturnValue_t result = RETURN_OK; - for (const auto& obj : helper.rtdIds) { - result = registerChild(obj); + for (const auto& obj : helper.rtdInfos) { + result = registerChild(obj.first); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -126,8 +126,8 @@ ReturnValue_t TcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t s object_id_t objId = 0; try { for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) { - devMode = childrenMap.at(helper.rtdIds[idx]).mode; - objId = helper.rtdIds[idx]; + devMode = childrenMap.at(helper.rtdInfos[idx].first).mode; + objId = helper.rtdInfos[idx].first; if (mode == devMode) { modeTable[idx].setMode(mode); } else if (mode == DeviceHandlerIF::MODE_NORMAL) { diff --git a/mission/system/TcsBoardAssembly.h b/mission/system/TcsBoardAssembly.h index 832f335d..eb42abbf 100644 --- a/mission/system/TcsBoardAssembly.h +++ b/mission/system/TcsBoardAssembly.h @@ -6,9 +6,10 @@ #include struct TcsBoardHelper { - TcsBoardHelper(std::array rtdIds) : rtdIds(rtdIds) {} + TcsBoardHelper(std::array, 16> rtdInfos) + : rtdInfos(std::move(rtdInfos)) {} - std::array rtdIds = {}; + std::array, 16> rtdInfos = {}; }; class TcsBoardAssembly : public AssemblyBase, public ConfirmsFailuresIF { diff --git a/tmtc b/tmtc index 1e25b08e..6b7b07c3 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 1e25b08e40db28103b91814f7de5a47dae5b9e76 +Subproject commit 6b7b07c3409fc24a8585c39e308156b3657c655e From 5a82fe93d9524004e339d6d35f26c2d68d75d390 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 May 2022 17:02:57 +0200 Subject: [PATCH 04/74] core ctrl remount sd handling --- bsp_q7s/core/CoreController.cpp | 36 ++++++++++++++++---- bsp_q7s/core/CoreController.h | 3 +- bsp_q7s/memory/SdCardManager.cpp | 56 ++++++++++++++++++++++++++++++++ bsp_q7s/memory/SdCardManager.h | 6 ++++ fsfw | 2 +- 5 files changed, 95 insertions(+), 8 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 208999c2..00175067 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1235,18 +1235,42 @@ void CoreController::performWatchdogControlOperation() { void CoreController::performMountedSdCardOperations() { currMntPrefix = sdcMan->getCurrentMountPrefix(); - if (doPerformMountedSdCardOps) { + if (performMountedSdCardOpsSwitch) { bool sdCardMounted = false; + bool mountedReadOnly = false; + ReturnValue_t result = sdcMan->isSdCardMountedReadOnly(sdInfo.pref, mountedReadOnly); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "CoreController::performMountedSdCardOperations: Could not check " + "read-only mount state" << std::endl; + mountedReadOnly = true; + } + if (mountedReadOnly) { + int linuxErrno = 0; + result = sdcMan->performFsck(sdInfo.pref, true, linuxErrno); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "CoreController::performMountedSdCardOperations: fsck command on SD Card " + << sdInfo.prefChar << " failed with code " << linuxErrno << " | " << strerror(linuxErrno); + } + result = sdcMan->remountReadWrite(sdInfo.pref); + if(result == HasReturnvaluesIF::RETURN_OK) { + sif::warning << "CoreController::performMountedSdCardOperations: Remounted SD Card " << + sdInfo.prefChar << " read-write"; + } else { + sif::error << "CoreController::performMountedSdCardOperations: Remounting SD Card " << + sdInfo.prefChar << " read-write failed"; + } + } sdCardMounted = sdcMan->isSdCardMounted(sdInfo.pref); - if (sdCardMounted) { - std::string path = currMntPrefix + "/" + CONF_FOLDER; - if (not std::filesystem::exists(path)) { - std::filesystem::create_directory(path); + if (sdCardMounted and not performOneShotSdCardOpsSwitch) { + std::ostringstream path; + path << currMntPrefix << "/" << CONF_FOLDER; + if (not std::filesystem::exists(path.str())) { + std::filesystem::create_directory(path.str()); } initVersionFile(); initClockFromTimeFile(); performRebootFileHandling(false); - doPerformMountedSdCardOps = false; + performOneShotSdCardOpsSwitch = true; } } timeFileHandler(); diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index fb4f02b0..dd817bff 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -179,7 +179,8 @@ class CoreController : public ExtendedControllerBase { } sdInfo; RebootFile rebootFile = {}; std::string currMntPrefix; - bool doPerformMountedSdCardOps = true; + bool performOneShotSdCardOpsSwitch = true; + bool performMountedSdCardOpsSwitch = true; /** * Index 0: Chip 0 Copy 0 diff --git a/bsp_q7s/memory/SdCardManager.cpp b/bsp_q7s/memory/SdCardManager.cpp index 4ca11787..d5a91dac 100644 --- a/bsp_q7s/memory/SdCardManager.cpp +++ b/bsp_q7s/memory/SdCardManager.cpp @@ -466,3 +466,59 @@ bool SdCardManager::isSdCardMounted(sd::SdCard sdCard) { } return false; } + +ReturnValue_t SdCardManager::isSdCardMountedReadOnly(sd::SdCard sdcard, bool& readOnly) { + std::ostringstream command; + if(sdcard == sd::SdCard::SLOT_0) { + command << "grep -q \"" << SD_0_DEV_NAME << " vfat ro, \" /proc/mounts"; + } else { + command << "grep -q \"" << SD_1_DEV_NAME << " vfat ro, \" /proc/mounts"; + } + ReturnValue_t result = cmdExecutor.load(command.str(), true, false); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = cmdExecutor.execute(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + auto& readVec = cmdExecutor.getReadVector(); + size_t readLen = strnlen(readVec.data(), readVec.size()); + if(readLen == 0) { + readOnly = false; + } + readOnly = true; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t SdCardManager::remountReadWrite(sd::SdCard sdcard) { + std::ostringstream command; + if(sdcard == sd::SdCard::SLOT_0) { + command << "mount -o remount,rw " << SD_0_DEV_NAME << " " << SD_0_MOUNT_POINT; + } else { + command << "mount -o remount,rw " << SD_1_DEV_NAME << " " << SD_1_MOUNT_POINT; + } + ReturnValue_t result = cmdExecutor.load(command.str(), true, false); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return cmdExecutor.execute(); +} + +ReturnValue_t SdCardManager::performFsck(sd::SdCard sdcard, bool printOutput, int& linuxError) { + std::ostringstream command; + if(sdcard == sd::SdCard::SLOT_0) { + command << "fsck -y " << SD_0_DEV_NAME; + } else { + command << "fsck -y " << SD_1_DEV_NAME; + } + ReturnValue_t result = cmdExecutor.load(command.str(), true, printOutput); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = cmdExecutor.execute(); + if(result != HasReturnvaluesIF::RETURN_OK) { + linuxError = cmdExecutor.getLastError(); + } + return result; +} diff --git a/bsp_q7s/memory/SdCardManager.h b/bsp_q7s/memory/SdCardManager.h index 37660f75..01a50050 100644 --- a/bsp_q7s/memory/SdCardManager.h +++ b/bsp_q7s/memory/SdCardManager.h @@ -194,6 +194,12 @@ class SdCardManager : public SystemObject, public SdCardMountedIF { */ bool isSdCardMounted(sd::SdCard sdCard) override; + ReturnValue_t isSdCardMountedReadOnly(sd::SdCard sdcard, bool& readOnly); + + ReturnValue_t remountReadWrite(sd::SdCard sdcard); + + ReturnValue_t performFsck(sd::SdCard sdcard, bool printOutput, int& linuxError); + private: CommandExecutor cmdExecutor; Operations currentOp = Operations::IDLE; diff --git a/fsfw b/fsfw index dafcaa60..d1ff32bf 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit dafcaa60079ba8e57753d389e6a569ee3eb0b7cb +Subproject commit d1ff32bf968cbf769ca8daa37265af70e050d9c0 From 5f96d157a76a6a78aeb43259d6903bbbedafcbe6 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 May 2022 17:04:31 +0200 Subject: [PATCH 05/74] repoint fsfw --- fsfw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsfw b/fsfw index dafcaa60..c0ff84bb 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit dafcaa60079ba8e57753d389e6a569ee3eb0b7cb +Subproject commit c0ff84bb9d81bc3444992fef38b74d260d54d5a0 From 56f491befb64dcad4adc88bd140678def8ed39d1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 12 May 2022 00:48:49 +0200 Subject: [PATCH 06/74] compile fix --- linux/ObjectFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/ObjectFactory.cpp b/linux/ObjectFactory.cpp index 3a8f52d4..e28f41fa 100644 --- a/linux/ObjectFactory.cpp +++ b/linux/ObjectFactory.cpp @@ -288,8 +288,8 @@ void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF, for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) { rtdCookies[idx] = new SpiCookie(cookieArgs[idx].first, cookieArgs[idx].second, - Max31865Definitions::MAX_REPLY_SIZE, spi::RTD_MODE, spi::RTD_SPEED); - rtds[idx] = new Max31865PT1000Handler(rtdIds[idx], objects::SPI_MAIN_COM_IF, rtdCookies[idx]); + MAX31865::MAX_REPLY_SIZE, spi::RTD_MODE, spi::RTD_SPEED); + rtds[idx] = new Max31865PT1000Handler(rtdInfos[idx].first, objects::SPI_MAIN_COM_IF, rtdCookies[idx]); rtds[idx]->setParent(objects::TCS_BOARD_ASS); rtdFdir = new RtdFdir(rtdInfos[idx].first); rtds[idx]->setCustomFdir(rtdFdir); From 23f209fb077fb8b311a3cfc78eebcc96003536f3 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 12 May 2022 09:48:41 +0200 Subject: [PATCH 07/74] added eive specific max31865 handler --- linux/ObjectFactory.cpp | 8 +- linux/devices/Max31865RtdReader.cpp | 73 ++++++---- linux/devices/Max31865RtdReader.h | 36 +---- mission/devices/CMakeLists.txt | 1 + mission/devices/Max31865EiveHandler.cpp | 132 ++++++++++++++++++ mission/devices/Max31865EiveHandler.h | 37 +++++ mission/devices/Max31865PT1000Handler.cpp | 2 +- .../devicedefinitions/Max31865Definitions.h | 54 ++++++- .../Max31865DeviceDefinitions.cpp | 1 - 9 files changed, 279 insertions(+), 65 deletions(-) create mode 100644 mission/devices/Max31865EiveHandler.cpp create mode 100644 mission/devices/Max31865EiveHandler.h delete mode 100644 mission/devices/devicedefinitions/Max31865DeviceDefinitions.cpp diff --git a/linux/ObjectFactory.cpp b/linux/ObjectFactory.cpp index e28f41fa..35d1cff9 100644 --- a/linux/ObjectFactory.cpp +++ b/linux/ObjectFactory.cpp @@ -286,10 +286,10 @@ void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF, std::array rtds = {}; RtdFdir* rtdFdir = nullptr; for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) { - rtdCookies[idx] = - new SpiCookie(cookieArgs[idx].first, cookieArgs[idx].second, - MAX31865::MAX_REPLY_SIZE, spi::RTD_MODE, spi::RTD_SPEED); - rtds[idx] = new Max31865PT1000Handler(rtdInfos[idx].first, objects::SPI_MAIN_COM_IF, rtdCookies[idx]); + rtdCookies[idx] = new SpiCookie(cookieArgs[idx].first, cookieArgs[idx].second, + MAX31865::MAX_REPLY_SIZE, spi::RTD_MODE, spi::RTD_SPEED); + rtds[idx] = + new Max31865PT1000Handler(rtdInfos[idx].first, objects::SPI_MAIN_COM_IF, rtdCookies[idx]); rtds[idx]->setParent(objects::TCS_BOARD_ASS); rtdFdir = new RtdFdir(rtdInfos[idx].first); rtds[idx]->setCustomFdir(rtdFdir); diff --git a/linux/devices/Max31865RtdReader.cpp b/linux/devices/Max31865RtdReader.cpp index 0e2f9724..132467e9 100644 --- a/linux/devices/Max31865RtdReader.cpp +++ b/linux/devices/Max31865RtdReader.cpp @@ -2,7 +2,7 @@ #include Max31865RtdReader::Max31865RtdReader(object_id_t objectId, SpiComIF* comIF) - : SystemObject(objectId), rtds(NUM_RTDS), comIF(comIF) { + : SystemObject(objectId), rtds(EiveMax31855::NUM_RTDS), comIF(comIF) { readerMutex = MutexFactory::instance()->createMutex(); } @@ -32,8 +32,8 @@ void Max31865RtdReader::rtdMainLoop() { periodicReadHandling(); } -bool Max31865RtdReader::rtdCanBeUsed(uint8_t idx) { - if (rtds[idx]->active and rtds[idx]->configured) { +bool Max31865RtdReader::rtdIsActive(uint8_t idx) { + if (rtds[idx]->on and rtds[idx]->active and rtds[idx]->configured) { return true; } return false; @@ -48,24 +48,26 @@ bool Max31865RtdReader::periodicInitHandling() { return false; } - bool someRtdActive = false; + bool someRtdOn = false; for (auto& rtd : rtds) { if (rtd == nullptr) { continue; } - if (rtd->active and not rtd->configured) { - someRtdActive = true; - uint8_t cfg = (Bias::OFF << CfgBitPos::BIAS_SEL) | (Wires::FOUR_WIRE << CfgBitPos::WIRE_SEL) | - (ConvMode::NORM_OFF << CfgBitPos::CONV_MODE) | - (1 << CfgBitPos::FAULTY_STATUS_CLEAR); - result = writeCfgReg(rtd->spiCookie, cfg); - if (result != HasReturnvaluesIF::RETURN_OK) { - // TODO: Check retval + if (rtd->on and not rtd->configured) { + if (rtd->cd.hasTimedOut()) { + uint8_t cfg = + (Bias::OFF << CfgBitPos::BIAS_SEL) | (Wires::FOUR_WIRE << CfgBitPos::WIRE_SEL) | + (ConvMode::NORM_OFF << CfgBitPos::CONV_MODE) | (1 << CfgBitPos::FAULTY_STATUS_CLEAR); + result = writeCfgReg(rtd->spiCookie, cfg); + if (result != HasReturnvaluesIF::RETURN_OK) { + // TODO: Check retval + } + someRtdOn = true; + rtd->configured = true; } - rtd->configured = true; } } - if (not someRtdActive) { + if (not someRtdOn) { return false; } bool someRtdUsable = false; @@ -73,7 +75,7 @@ bool Max31865RtdReader::periodicInitHandling() { if (rtd == nullptr) { continue; } - if (rtdCanBeUsed(rtd->idx)) { + if (rtdIsActive(rtd->idx)) { someRtdUsable = true; result = biasSel(Bias::ON, rtd->spiCookie); } @@ -93,7 +95,7 @@ void Max31865RtdReader::periodicReadReqHandling() { if (rtd == nullptr) { continue; } - if (rtd->active) { + if (rtdIsActive(rtd->idx)) { uint8_t currentCfg = 0; auto result = readCfgReg(rtd->spiCookie, currentCfg); if (result != RETURN_OK) { @@ -119,7 +121,7 @@ void Max31865RtdReader::periodicReadHandling() { if (rtd == nullptr) { continue; } - if (rtd->active) { + if (rtdIsActive(rtd->idx)) { uint16_t rtdVal = 0; bool faultBitSet = false; result = readRtdVal(rtd->spiCookie, rtdVal, faultBitSet); @@ -137,7 +139,9 @@ void Max31865RtdReader::periodicReadHandling() { if (rtd == nullptr) { continue; } - if (rtd->active) { + // Even if a device was made inactive, turn off the bias here. If it was turned off, not + // necessary anymore.. + if (rtd->on) { result = biasSel(Bias::OFF, rtd->spiCookie); } } @@ -152,7 +156,7 @@ ReturnValue_t Max31865RtdReader::initializeInterface(CookieIF* cookie) { if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - if (rtdCookie->idx > NUM_RTDS) { + if (rtdCookie->idx > EiveMax31855::NUM_RTDS) { throw std::invalid_argument("Invalid RTD index"); } rtds[rtdCookie->idx] = rtdCookie; @@ -178,21 +182,40 @@ ReturnValue_t Max31865RtdReader::sendMessage(CookieIF* cookie, const uint8_t* se // TODO: Emit warning, invalid command return RETURN_OK; } - auto cmd = static_cast(sendData[0]); + auto cmd = static_cast(sendData[0]); switch (cmd) { - case (RtdCommands::ON): { - if (not rtdCookie->active) { - rtdCookie->active = true; + case (EiveMax31855::RtdCommands::ON): { + if (not rtdCookie->on) { + rtdCookie->cd.setTimeout(MAX31865::WARMUP_MS); + rtdCookie->cd.resetTimer(); + rtdCookie->on = true; + rtdCookie->active = false; rtdCookie->configured = false; } break; } - case (RtdCommands::OFF): { + case (EiveMax31855::RtdCommands::ACTIVE): { + if (not rtdCookie->on) { + rtdCookie->cd.setTimeout(MAX31865::WARMUP_MS); + rtdCookie->cd.resetTimer(); + rtdCookie->on = true; + rtdCookie->active = true; + rtdCookie->configured = false; + } else { + rtdCookie->active = true; + } + break; + } + case (EiveMax31855::RtdCommands::OFF): { + rtdCookie->on = false; rtdCookie->active = false; rtdCookie->configured = false; break; } - case (RtdCommands::CFG): { + case (EiveMax31855::RtdCommands::HIGH_TRESHOLD): + case (EiveMax31855::RtdCommands::LOW_THRESHOLD): + case (EiveMax31855::RtdCommands::CFG): + default: { // TODO: Only implement if needed break; } diff --git a/linux/devices/Max31865RtdReader.h b/linux/devices/Max31865RtdReader.h index 4a1bbb47..79ae1786 100644 --- a/linux/devices/Max31865RtdReader.h +++ b/linux/devices/Max31865RtdReader.h @@ -9,32 +9,6 @@ #include "fsfw/devicehandlers/DeviceCommunicationIF.h" #include "mission/devices/devicedefinitions/Max31865Definitions.h" -static constexpr uint8_t NUM_RTDS = 16; - -enum RtdCommands : uint8_t { ON = 0, OFF = 1, CFG = 2 }; - -class ReadOutStruct : public SerialLinkedListAdapter { - public: - ReadOutStruct() { setLinks(); } - ReadOutStruct(uint32_t spiErrCnt, bool faultBitSet, uint8_t faultVal, uint16_t rtdVal) - : spiErrorCount(spiErrCnt), faultBitSet(faultBitSet), faultValue(faultVal), rtdVal(rtdVal) { - setLinks(); - } - - SerializeElement spiErrorCount = 0; - SerializeElement faultBitSet = false; - SerializeElement faultValue = 0; - SerializeElement rtdVal = 0; - - private: - void setLinks() { - setStart(&spiErrorCount); - spiErrorCount.setNext(&faultBitSet); - faultBitSet.setNext(&faultValue); - faultValue.setNext(&rtdVal); - }; -}; - struct Max31865ReaderCookie { Max31865ReaderCookie(){}; Max31865ReaderCookie(object_id_t handlerId_, uint8_t idx_, const std::string& locString_, @@ -46,14 +20,14 @@ struct Max31865ReaderCookie { std::string locString = ""; std::array exchangeBuf{}; - bool active = false; - + Countdown cd = Countdown(MAX31865::WARMUP_MS); + bool on = false; bool configured = false; - + bool active = false; SpiCookie* spiCookie = nullptr; // Exchange data buffer struct - ReadOutStruct db; + EiveMax31855::ReadOutStruct db; }; class Max31865RtdReader : public SystemObject, @@ -74,7 +48,7 @@ class Max31865RtdReader : public SystemObject, void periodicReadReqHandling(); void periodicReadHandling(); - bool rtdCanBeUsed(uint8_t idx); + bool rtdIsActive(uint8_t idx); ReturnValue_t writeCfgReg(SpiCookie* cookie, uint8_t cfg); ReturnValue_t biasSel(MAX31865::Bias bias, SpiCookie* cookie); ReturnValue_t readCfgReg(SpiCookie* cookie, uint8_t& cfg); diff --git a/mission/devices/CMakeLists.txt b/mission/devices/CMakeLists.txt index 2919ff1f..d5f33e39 100644 --- a/mission/devices/CMakeLists.txt +++ b/mission/devices/CMakeLists.txt @@ -8,6 +8,7 @@ target_sources(${LIB_EIVE_MISSION} PRIVATE PDU2Handler.cpp ACUHandler.cpp SyrlinksHkHandler.cpp + Max31865EiveHandler.cpp Max31865PT1000Handler.cpp IMTQHandler.cpp HeaterHandler.cpp diff --git a/mission/devices/Max31865EiveHandler.cpp b/mission/devices/Max31865EiveHandler.cpp new file mode 100644 index 00000000..17afa718 --- /dev/null +++ b/mission/devices/Max31865EiveHandler.cpp @@ -0,0 +1,132 @@ +#include "Max31865EiveHandler.h" + +Max31865EiveHandler::Max31865EiveHandler(object_id_t objectId, object_id_t comIF, + CookieIF* comCookie) + : DeviceHandlerBase(objectId, comIF, comCookie, nullptr), + sensorDataset(this, EiveMax31855::RtdCommands::EXCHANGE_SET_ID) {} + +void Max31865EiveHandler::doStartUp() { + if (state == InternalState::NONE or state == InternalState::INACTIVE) { + if (instantNormal) { + state = InternalState::ACTIVE; + } else { + state = InternalState::ON; + } + transitionOk = false; + } + if ((state == InternalState::ON or state == InternalState::ACTIVE) and transitionOk) { + if (instantNormal) { + setMode(_MODE_TO_NORMAL); + } else { + setMode(MODE_ON); + } + } +} + +void Max31865EiveHandler::doShutDown() { + if (state == InternalState::NONE or state == InternalState::ACTIVE or + state == InternalState::ON) { + state = InternalState::INACTIVE; + transitionOk = false; + } else { + transitionOk = true; + } + if (state == InternalState::INACTIVE and transitionOk) { + setMode(_MODE_POWER_DOWN); + } +} + +ReturnValue_t Max31865EiveHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { + *id = EiveMax31855::RtdCommands::EXCHANGE_SET_ID; + return RETURN_OK; +} + +ReturnValue_t Max31865EiveHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { + if (state == InternalState::ON) { + *id = EiveMax31855::RtdCommands::ON; + buildCommandFromCommand(*id, nullptr, 0); + } + if (state == InternalState::ACTIVE) { + *id = EiveMax31855::RtdCommands::ACTIVE; + buildCommandFromCommand(*id, nullptr, 0); + } + if (state == InternalState::INACTIVE) { + *id = EiveMax31855::RtdCommands::OFF; + buildCommandFromCommand(*id, nullptr, 0); + } + return NOTHING_TO_SEND; +} + +ReturnValue_t Max31865EiveHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand, + const uint8_t* commandData, + size_t commandDataLen) { + auto cmdTyped = static_cast(deviceCommand); + switch (cmdTyped) { + case (EiveMax31855::RtdCommands::ON): + case (EiveMax31855::RtdCommands::ACTIVE): + case (EiveMax31855::RtdCommands::OFF): { + simpleCommand(cmdTyped); + break; + } + case (EiveMax31855::RtdCommands::LOW_THRESHOLD): + case (EiveMax31855::RtdCommands::HIGH_TRESHOLD): { + break; + } + case (EiveMax31855::RtdCommands::CFG): { + break; + } + default: + return NOTHING_TO_SEND; + } + return RETURN_OK; +} + +void Max31865EiveHandler::simpleCommand(EiveMax31855::RtdCommands cmd) { + cmdBuf[0] = cmd; + rawPacket = cmdBuf.data(); + rawPacketLen = 1; +} +void Max31865EiveHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) { + if (mode == _MODE_TO_NORMAL) { + state = InternalState::ACTIVE; + transitionOk = false; + if (transitionOk) { + setMode(MODE_NORMAL); + } + } else { + DeviceHandlerBase::doTransition(modeFrom, subModeFrom); + } +} + +void Max31865EiveHandler::fillCommandAndReplyMap() { + insertInReplyMap(EiveMax31855::RtdCommands::EXCHANGE_SET_ID, 2, &sensorDataset); +} + +ReturnValue_t Max31865EiveHandler::scanForReply(const uint8_t* start, size_t remainingSize, + DeviceCommandId_t* foundId, size_t* foundLen) { + if (remainingSize != exchangeStruct.getSerializedSize()) { + sif::error << "Invalid reply from RTD reader detected, reply size " << remainingSize + << "not equal to exchange struct size" << exchangeStruct.getSerializedSize() + << std::endl; + return RETURN_FAILED; + } + *foundId = EiveMax31855::RtdCommands::EXCHANGE_SET_ID; + *foundLen = remainingSize; + return RETURN_OK; +} + +ReturnValue_t Max31865EiveHandler::interpretDeviceReply(DeviceCommandId_t id, + const uint8_t* packet) { + return RETURN_OK; +} + +uint32_t Max31865EiveHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 2000; } + +ReturnValue_t Max31865EiveHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) { + localDataPoolMap.emplace(MAX31865::PoolIds::RTD_VALUE, new PoolEntry({0})); + localDataPoolMap.emplace(MAX31865::PoolIds::TEMPERATURE_C, new PoolEntry({0})); + localDataPoolMap.emplace(MAX31865::PoolIds::FAULT_BYTE, new PoolEntry({0})); + poolManager.subscribeForPeriodicPacket(sensorDataset.getSid(), false, 30.0, false); + return RETURN_OK; +} diff --git a/mission/devices/Max31865EiveHandler.h b/mission/devices/Max31865EiveHandler.h new file mode 100644 index 00000000..9214c680 --- /dev/null +++ b/mission/devices/Max31865EiveHandler.h @@ -0,0 +1,37 @@ +#ifndef MISSION_DEVICES_MAX31865EIVEHANDLER_H_ +#define MISSION_DEVICES_MAX31865EIVEHANDLER_H_ + +#include + +#include "devicedefinitions/Max31865Definitions.h" + +class Max31865EiveHandler : public DeviceHandlerBase { + public: + Max31865EiveHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie); + + private: + void doStartUp() override; + void doShutDown() override; + void doTransition(Mode_t modeFrom, Submode_t subModeFrom) override; + ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t* id) override; + ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t* id) override; + void fillCommandAndReplyMap() override; + ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData, + size_t commandDataLen) override; + ReturnValue_t scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId, + size_t* foundLen) override; + ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override; + uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; + + void simpleCommand(EiveMax31855::RtdCommands cmd); + std::array cmdBuf = {}; + EiveMax31855::ReadOutStruct exchangeStruct; + bool instantNormal = false; + MAX31865::Max31865Set sensorDataset; + enum class InternalState { NONE, ON, ACTIVE, INACTIVE } state = InternalState::NONE; + bool transitionOk = false; +}; + +#endif /* MISSION_DEVICES_MAX31865EIVEHANDLER_H_ */ diff --git a/mission/devices/Max31865PT1000Handler.cpp b/mission/devices/Max31865PT1000Handler.cpp index 6ac888cd..debe60e9 100644 --- a/mission/devices/Max31865PT1000Handler.cpp +++ b/mission/devices/Max31865PT1000Handler.cpp @@ -8,7 +8,7 @@ Max31865PT1000Handler::Max31865PT1000Handler(object_id_t objectId, object_id_t comIF, CookieIF *comCookie) : DeviceHandlerBase(objectId, comIF, comCookie), - sensorDataset(this), + sensorDataset(this, MAX31865::REQUEST_RTD), sensorDatasetSid(sensorDataset.getSid()) { #if OBSW_VERBOSE_LEVEL >= 1 debugDivider = new PeriodicOperationDivider(10); diff --git a/mission/devices/devicedefinitions/Max31865Definitions.h b/mission/devices/devicedefinitions/Max31865Definitions.h index efd81681..d1b67429 100644 --- a/mission/devices/devicedefinitions/Max31865Definitions.h +++ b/mission/devices/devicedefinitions/Max31865Definitions.h @@ -28,6 +28,8 @@ enum CfgBitPos { BIAS_SEL = 7 }; +static constexpr uint32_t WARMUP_MS = 100; + static constexpr DeviceCommandId_t CONFIG_CMD = 0x80; static constexpr DeviceCommandId_t WRITE_HIGH_THRESHOLD = 0x83; static constexpr DeviceCommandId_t WRITE_LOW_THRESHOLD = 0x85; @@ -50,20 +52,20 @@ static constexpr uint8_t REG_RTD = 0x01; static constexpr size_t MAX_REPLY_SIZE = 5; -class Max31865Set : public StaticLocalDataSet { +class Max31865Set : public StaticLocalDataSet<3> { public: /** * Constructor used by owner and data creators like device handlers. * @param owner * @param setId */ - Max31865Set(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, MAX31865_SET_ID) {} + Max31865Set(HasLocalDataPoolIF* owner, uint32_t setId) : StaticLocalDataSet(owner, setId) {} /** * Constructor used by data users like controllers. * @param sid */ - Max31865Set(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, MAX31865_SET_ID)) {} + Max31865Set(object_id_t objectId, uint32_t setId) : StaticLocalDataSet(sid_t(objectId, setId)) {} lp_var_t rtdValue = lp_var_t(sid.objectId, PoolIds::RTD_VALUE, this); lp_var_t temperatureCelcius = lp_var_t(sid.objectId, PoolIds::TEMPERATURE_C, this); @@ -72,4 +74,50 @@ class Max31865Set : public StaticLocalDataSet { } // namespace MAX31865 +namespace EiveMax31855 { + +static constexpr uint8_t NUM_RTDS = 16; + +enum RtdCommands : DeviceCommandId_t { + ON = 0, + EXCHANGE_SET_ID = MAX31865::REQUEST_RTD, + ACTIVE = 2, + LOW_THRESHOLD = 3, + HIGH_TRESHOLD = 4, + OFF = 5, + CFG = 6, + +}; + +class ReadOutStruct : public SerialLinkedListAdapter { + public: + ReadOutStruct() { setLinks(); } + ReadOutStruct(bool active, uint32_t spiErrCnt, bool faultBitSet, uint8_t faultVal, + uint16_t rtdVal) + : active(active), + rtdVal(rtdVal), + faultBitSet(faultBitSet), + faultValue(faultVal), + spiErrorCount(spiErrCnt) { + setLinks(); + } + + SerializeElement active = false; + SerializeElement rtdVal = 0; + SerializeElement faultBitSet = false; + SerializeElement faultValue = 0; + SerializeElement spiErrorCount = 0; + + private: + void setLinks() { + setStart(&active); + active.setNext(&rtdVal); + rtdVal.setNext(&faultBitSet); + faultBitSet.setNext(&faultValue); + faultValue.setNext(&spiErrorCount); + }; +}; + +}; // namespace EiveMax31855 + #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_MAX13865DEFINITIONS_H_ */ diff --git a/mission/devices/devicedefinitions/Max31865DeviceDefinitions.cpp b/mission/devices/devicedefinitions/Max31865DeviceDefinitions.cpp deleted file mode 100644 index 0f050093..00000000 --- a/mission/devices/devicedefinitions/Max31865DeviceDefinitions.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "Max31865Definitions.h" From 6b9e49e6326e35d973a294fcf7f68f79c371d104 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 12 May 2022 11:27:30 +0200 Subject: [PATCH 08/74] continued low level MAX31865 handler --- linux/devices/CMakeLists.txt | 2 +- ...der.cpp => Max31865RtdLowlevelHandler.cpp} | 205 ++++++++++++++---- ...dReader.h => Max31865RtdLowlevelHandler.h} | 20 +- mission/devices/Max31865EiveHandler.cpp | 7 +- mission/devices/Max31865PT1000Handler.cpp | 11 +- mission/devices/Max31865PT1000Handler.h | 1 + .../devicedefinitions/Max31865Definitions.h | 39 ++-- 7 files changed, 221 insertions(+), 64 deletions(-) rename linux/devices/{Max31865RtdReader.cpp => Max31865RtdLowlevelHandler.cpp} (56%) rename linux/devices/{Max31865RtdReader.h => Max31865RtdLowlevelHandler.h} (70%) diff --git a/linux/devices/CMakeLists.txt b/linux/devices/CMakeLists.txt index e65987c6..ec8127c9 100644 --- a/linux/devices/CMakeLists.txt +++ b/linux/devices/CMakeLists.txt @@ -5,7 +5,7 @@ if(EIVE_BUILD_GPSD_GPS_HANDLER) endif() target_sources(${OBSW_NAME} PRIVATE - Max31865RtdReader.cpp + Max31865RtdLowlevelHandler.cpp ) add_subdirectory(ploc) diff --git a/linux/devices/Max31865RtdReader.cpp b/linux/devices/Max31865RtdLowlevelHandler.cpp similarity index 56% rename from linux/devices/Max31865RtdReader.cpp rename to linux/devices/Max31865RtdLowlevelHandler.cpp index 132467e9..32a700b7 100644 --- a/linux/devices/Max31865RtdReader.cpp +++ b/linux/devices/Max31865RtdLowlevelHandler.cpp @@ -1,5 +1,6 @@ +#include "Max31865RtdLowlevelHandler.h" + #include -#include Max31865RtdReader::Max31865RtdReader(object_id_t objectId, SpiComIF* comIF) : SystemObject(objectId), rtds(EiveMax31855::NUM_RTDS), comIF(comIF) { @@ -44,7 +45,7 @@ bool Max31865RtdReader::periodicInitHandling() { MutexGuard mg(readerMutex); ReturnValue_t result = RETURN_OK; if (mg.getLockResult() != RETURN_OK) { - // TODO: Emit warning, return + sif::warning << "Max31865RtdReader::periodicInitHandling: Mutex lock failed" << std::endl; return false; } @@ -60,7 +61,28 @@ bool Max31865RtdReader::periodicInitHandling() { (ConvMode::NORM_OFF << CfgBitPos::CONV_MODE) | (1 << CfgBitPos::FAULTY_STATUS_CLEAR); result = writeCfgReg(rtd->spiCookie, cfg); if (result != HasReturnvaluesIF::RETURN_OK) { - // TODO: Check retval + handleSpiError(rtd, result, "writeCfgReg"); + } + bool additionalCfg = false; + if (rtd->writeLowThreshold) { + additionalCfg = true; + result = writeLowThreshold(rtd->spiCookie, rtd->lowThreshold); + if (result != HasReturnvaluesIF::RETURN_OK) { + handleSpiError(rtd, result, "writeLowThreshold"); + } + } + if (rtd->writeHighThreshold) { + additionalCfg = true; + result = writeHighThreshold(rtd->spiCookie, rtd->highThreshold); + if (result != HasReturnvaluesIF::RETURN_OK) { + handleSpiError(rtd, result, "writeHighThreshold"); + } + } + if (additionalCfg) { + result = clearFaultStatus(rtd->spiCookie); + if (result != HasReturnvaluesIF::RETURN_OK) { + handleSpiError(rtd, result, "clearFaultStatus"); + } } someRtdOn = true; rtd->configured = true; @@ -77,7 +99,7 @@ bool Max31865RtdReader::periodicInitHandling() { } if (rtdIsActive(rtd->idx)) { someRtdUsable = true; - result = biasSel(Bias::ON, rtd->spiCookie); + result = writeBiasSel(Bias::ON, rtd->spiCookie); } } return someRtdUsable; @@ -87,7 +109,7 @@ void Max31865RtdReader::periodicReadReqHandling() { using namespace MAX31865; MutexGuard mg(readerMutex); if (mg.getLockResult() != RETURN_OK) { - // TODO: Emit warning, return + sif::warning << "Max31865RtdReader::periodicReadReqHandling: Mutex lock failed" << std::endl; return; } // Now request one shot config for all active RTDs @@ -99,7 +121,7 @@ void Max31865RtdReader::periodicReadReqHandling() { uint8_t currentCfg = 0; auto result = readCfgReg(rtd->spiCookie, currentCfg); if (result != RETURN_OK) { - // TODO: Emit warning, FDIR? + handleSpiError(rtd, result, "readCfgReg"); continue; } currentCfg |= (1 << CfgBitPos::ONE_SHOT); @@ -113,7 +135,7 @@ void Max31865RtdReader::periodicReadHandling() { auto result = RETURN_OK; MutexGuard mg(readerMutex); if (mg.getLockResult() != RETURN_OK) { - // TODO: Emit warning, return + sif::warning << "Max31865RtdReader::periodicReadReqHandling: Mutex lock failed" << std::endl; return; } // Now read the RTD values @@ -126,7 +148,7 @@ void Max31865RtdReader::periodicReadHandling() { bool faultBitSet = false; result = readRtdVal(rtd->spiCookie, rtdVal, faultBitSet); if (result != RETURN_OK) { - // TODO: Emit warning, FDIR? + handleSpiError(rtd, result, "readRtdVal"); continue; } if (faultBitSet) { @@ -142,7 +164,7 @@ void Max31865RtdReader::periodicReadHandling() { // Even if a device was made inactive, turn off the bias here. If it was turned off, not // necessary anymore.. if (rtd->on) { - result = biasSel(Bias::OFF, rtd->spiCookie); + result = writeBiasSel(Bias::OFF, rtd->spiCookie); } } } @@ -168,20 +190,29 @@ ReturnValue_t Max31865RtdReader::sendMessage(CookieIF* cookie, const uint8_t* se if (cookie == nullptr) { return RETURN_FAILED; } + // Empty command.. don't fail for now if (sendLen < 1) { return RETURN_OK; } MutexGuard mg(readerMutex); if (mg.getLockResult() != RETURN_OK) { - // TODO: Emit warning, return + sif::warning << "Max31865RtdReader::sendMessage: Mutex lock failed" << std::endl; return RETURN_FAILED; } auto* rtdCookie = dynamic_cast(cookie); uint8_t cmdRaw = sendData[0]; - if (cmdRaw > 2) { - // TODO: Emit warning, invalid command - return RETURN_OK; + if (cmdRaw > EiveMax31855::RtdCommands::NUM_CMDS) { + sif::warning << "Max31865RtdReader::sendMessage: Invalid command" << std::endl; + return RETURN_FAILED; } + + auto thresholdHandler = [](Max31865ReaderCookie* rtdCookie, const uint8_t* sendData) { + rtdCookie->lowThreshold = (sendData[1] << 8) | sendData[2]; + rtdCookie->highThreshold = (sendData[3] << 8) | sendData[4]; + rtdCookie->writeLowThreshold = true; + rtdCookie->writeHighThreshold = true; + }; + auto cmd = static_cast(sendData[0]); switch (cmd) { case (EiveMax31855::RtdCommands::ON): { @@ -191,6 +222,9 @@ ReturnValue_t Max31865RtdReader::sendMessage(CookieIF* cookie, const uint8_t* se rtdCookie->on = true; rtdCookie->active = false; rtdCookie->configured = false; + if (sendLen == 5) { + thresholdHandler(rtdCookie, sendData); + } } break; } @@ -204,6 +238,9 @@ ReturnValue_t Max31865RtdReader::sendMessage(CookieIF* cookie, const uint8_t* se } else { rtdCookie->active = true; } + if (sendLen == 5) { + thresholdHandler(rtdCookie, sendData); + } break; } case (EiveMax31855::RtdCommands::OFF): { @@ -212,8 +249,24 @@ ReturnValue_t Max31865RtdReader::sendMessage(CookieIF* cookie, const uint8_t* se rtdCookie->configured = false; break; } - case (EiveMax31855::RtdCommands::HIGH_TRESHOLD): - case (EiveMax31855::RtdCommands::LOW_THRESHOLD): + case (EiveMax31855::RtdCommands::HIGH_TRESHOLD): { + if (sendLen == 3) { + rtdCookie->highThreshold = (sendData[1] << 8) | sendData[2]; + rtdCookie->writeHighThreshold = true; + } else { + return RETURN_FAILED; + } + break; + } + case (EiveMax31855::RtdCommands::LOW_THRESHOLD): { + if (sendLen == 3) { + rtdCookie->lowThreshold = (sendData[1] << 8) | sendData[2]; + rtdCookie->writeLowThreshold = true; + } else { + return RETURN_FAILED; + } + break; + } case (EiveMax31855::RtdCommands::CFG): default: { // TODO: Only implement if needed @@ -252,11 +305,11 @@ ReturnValue_t Max31865RtdReader::readReceivedMessage(CookieIF* cookie, uint8_t** ReturnValue_t Max31865RtdReader::writeCfgReg(SpiCookie* cookie, uint8_t cfg) { using namespace MAX31865; - uint8_t cmd[2] = {REG_CONFIG | WRITE_BIT, cfg}; - return comIF->sendMessage(cookie, cmd, 2); + uint8_t cmd = cfg; + return writeNToReg(cookie, CONFIG, 1, &cmd, nullptr); } -ReturnValue_t Max31865RtdReader::biasSel(MAX31865::Bias bias, SpiCookie* cookie) { +ReturnValue_t Max31865RtdReader::writeBiasSel(MAX31865::Bias bias, SpiCookie* cookie) { using namespace MAX31865; uint8_t currentCfg = 0; auto result = readCfgReg(cookie, currentCfg); @@ -271,42 +324,118 @@ ReturnValue_t Max31865RtdReader::biasSel(MAX31865::Bias bias, SpiCookie* cookie) return writeCfgReg(cookie, currentCfg); } -ReturnValue_t Max31865RtdReader::readCfgReg(SpiCookie* cookie, uint8_t& cfg) { +ReturnValue_t Max31865RtdReader::clearFaultStatus(SpiCookie* cookie) { using namespace MAX31865; - uint8_t cmd[2] = {REG_CONFIG, 0}; - ReturnValue_t result = comIF->sendMessage(cookie, cmd, 2); - if (result != RETURN_OK) { - return RETURN_FAILED; - } - uint8_t reply[2] = {}; - uint8_t* replyPtr = reply; - size_t dummyLen = 0; - result = comIF->readReceivedMessage(cookie, &replyPtr, &dummyLen); + // Read back the current configuration to avoid overwriting it when clearing te fault status + uint8_t currentCfg = 0; + auto result = readCfgReg(cookie, currentCfg); if (result != RETURN_OK) { return result; } - cfg = reply[1]; - return RETURN_OK; + currentCfg |= (1 << CfgBitPos::FAULTY_STATUS_CLEAR); + return writeCfgReg(cookie, currentCfg); +} + +ReturnValue_t Max31865RtdReader::readCfgReg(SpiCookie* cookie, uint8_t& cfg) { + using namespace MAX31865; + uint8_t* replyPtr = nullptr; + auto result = readNFromReg(cookie, CONFIG, 1, &replyPtr); + if (result == RETURN_OK) { + cfg = replyPtr[0]; + } + return result; +} + +ReturnValue_t Max31865RtdReader::writeLowThreshold(SpiCookie* cookie, uint16_t val) { + using namespace MAX31865; + uint8_t cmd[2] = {static_cast((val >> 8) & 0xff), static_cast(val & 0xff)}; + return writeNToReg(cookie, LOW_THRESHOLD, 2, cmd, nullptr); +} + +ReturnValue_t Max31865RtdReader::writeHighThreshold(SpiCookie* cookie, uint16_t val) { + using namespace MAX31865; + uint8_t cmd[2] = {static_cast((val >> 8) & 0xff), static_cast(val & 0xff)}; + return writeNToReg(cookie, HIGH_THRESHOLD, 2, cmd, nullptr); +} + +ReturnValue_t Max31865RtdReader::readLowThreshold(SpiCookie* cookie, uint16_t& lowThreshold) { + using namespace MAX31865; + uint8_t* replyPtr = nullptr; + auto result = readNFromReg(cookie, LOW_THRESHOLD, 2, &replyPtr); + if (result == RETURN_OK) { + lowThreshold = (replyPtr[0] << 8) | replyPtr[1]; + } + return result; +} + +ReturnValue_t Max31865RtdReader::readHighThreshold(SpiCookie* cookie, uint16_t& highThreshold) { + using namespace MAX31865; + uint8_t* replyPtr = nullptr; + auto result = readNFromReg(cookie, HIGH_THRESHOLD, 2, &replyPtr); + if (result == RETURN_OK) { + highThreshold = (replyPtr[0] << 8) | replyPtr[1]; + } + return result; +} + +ReturnValue_t Max31865RtdReader::writeNToReg(SpiCookie* cookie, uint8_t reg, size_t n, uint8_t* cmd, + uint8_t** reply) { + using namespace MAX31865; + if (n > cmdBuf.size() - 1) { + return HasReturnvaluesIF::RETURN_FAILED; + } + cmdBuf[0] = reg | WRITE_BIT; + for (size_t idx = 0; idx < n; idx++) { + cmdBuf[idx + 1] = cmd[idx]; + } + return comIF->sendMessage(cookie, cmd, 2); } ReturnValue_t Max31865RtdReader::readRtdVal(SpiCookie* cookie, uint16_t& val, bool& faultBitSet) { using namespace MAX31865; - uint8_t cmd[3] = {REG_RTD, 0, 0}; - auto result = comIF->sendMessage(cookie, cmd, 3); + uint8_t* replyPtr = nullptr; + auto result = readNFromReg(cookie, RTD, 2, &replyPtr); + if (result != RETURN_OK) { + return result; + } + if (replyPtr[1] & 0b0000'0001) { + faultBitSet = true; + } + // Shift 1 to the right to remove fault bit + val = ((replyPtr[0] << 8) | replyPtr[1]) >> 1; + return result; +} + +ReturnValue_t Max31865RtdReader::readNFromReg(SpiCookie* cookie, uint8_t reg, size_t n, + uint8_t** reply) { + using namespace MAX31865; + if (n > 4) { + return HasReturnvaluesIF::RETURN_FAILED; + } + // Clear write bit in any case + reg &= ~WRITE_BIT; + cmdBuf[0] = reg; + std::memset(cmdBuf.data() + 1, 0, n); + ReturnValue_t result = comIF->sendMessage(cookie, cmdBuf.data(), n); if (result != RETURN_OK) { return RETURN_FAILED; } - uint8_t reply[3] = {}; - uint8_t* replyPtr = reply; + uint8_t* replyPtr = replyBuf.data(); size_t dummyLen = 0; result = comIF->readReceivedMessage(cookie, &replyPtr, &dummyLen); if (result != RETURN_OK) { return result; } - if (reply[2] & 0b0000'0001) { - faultBitSet = true; + if (reply != nullptr) { + *reply = replyBuf.data() + 1; } - // Shift 1 to the right to remove fault bit - val = ((reply[1] << 8) | reply[2]) >> 1; + return RETURN_OK; +} + +ReturnValue_t Max31865RtdReader::handleSpiError(Max31865ReaderCookie* cookie, ReturnValue_t result, + const char* ctx) { + cookie->db.spiErrorCount.value += 1; + sif::warning << "Max31865RtdReader::handleSpiError: " << ctx << " | Failed with result " << result + << std::endl; return result; } diff --git a/linux/devices/Max31865RtdReader.h b/linux/devices/Max31865RtdLowlevelHandler.h similarity index 70% rename from linux/devices/Max31865RtdReader.h rename to linux/devices/Max31865RtdLowlevelHandler.h index 79ae1786..5e9a7c26 100644 --- a/linux/devices/Max31865RtdReader.h +++ b/linux/devices/Max31865RtdLowlevelHandler.h @@ -24,6 +24,10 @@ struct Max31865ReaderCookie { bool on = false; bool configured = false; bool active = false; + bool writeLowThreshold = false; + bool writeHighThreshold = false; + uint16_t lowThreshold = 0; + uint16_t highThreshold = 0; SpiCookie* spiCookie = nullptr; // Exchange data buffer struct @@ -35,12 +39,13 @@ class Max31865RtdReader : public SystemObject, public DeviceCommunicationIF { public: Max31865RtdReader(object_id_t objectId, SpiComIF* comIF); - void addRtd(Max31865ReaderCookie rtdCookie); [[noreturn]] ReturnValue_t performOperation(uint8_t operationCode) override; private: std::vector rtds; + std::array cmdBuf = {}; + std::array replyBuf = {}; MutexIF* readerMutex; void rtdMainLoop(); @@ -50,9 +55,18 @@ class Max31865RtdReader : public SystemObject, bool rtdIsActive(uint8_t idx); ReturnValue_t writeCfgReg(SpiCookie* cookie, uint8_t cfg); - ReturnValue_t biasSel(MAX31865::Bias bias, SpiCookie* cookie); + ReturnValue_t writeBiasSel(MAX31865::Bias bias, SpiCookie* cookie); ReturnValue_t readCfgReg(SpiCookie* cookie, uint8_t& cfg); ReturnValue_t readRtdVal(SpiCookie* cookie, uint16_t& val, bool& faultBitSet); + ReturnValue_t writeLowThreshold(SpiCookie* cookie, uint16_t val); + ReturnValue_t writeHighThreshold(SpiCookie* cookie, uint16_t val); + ReturnValue_t readLowThreshold(SpiCookie* cookie, uint16_t& val); + ReturnValue_t readHighThreshold(SpiCookie* cookie, uint16_t& val); + ReturnValue_t clearFaultStatus(SpiCookie* cookie); + + ReturnValue_t readNFromReg(SpiCookie* cookie, uint8_t reg, size_t n, uint8_t** reply); + ReturnValue_t writeNToReg(SpiCookie* cookie, uint8_t reg, size_t n, uint8_t* cmd, + uint8_t** reply); ReturnValue_t initializeInterface(CookieIF* cookie) override; ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override; @@ -60,6 +74,8 @@ class Max31865RtdReader : public SystemObject, ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override; ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override; + ReturnValue_t handleSpiError(Max31865ReaderCookie* cookie, ReturnValue_t result, const char* ctx); + SpiComIF* comIF; }; diff --git a/mission/devices/Max31865EiveHandler.cpp b/mission/devices/Max31865EiveHandler.cpp index 17afa718..98265600 100644 --- a/mission/devices/Max31865EiveHandler.cpp +++ b/mission/devices/Max31865EiveHandler.cpp @@ -124,9 +124,10 @@ uint32_t Max31865EiveHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeT ReturnValue_t Max31865EiveHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { - localDataPoolMap.emplace(MAX31865::PoolIds::RTD_VALUE, new PoolEntry({0})); - localDataPoolMap.emplace(MAX31865::PoolIds::TEMPERATURE_C, new PoolEntry({0})); - localDataPoolMap.emplace(MAX31865::PoolIds::FAULT_BYTE, new PoolEntry({0})); + using namespace MAX31865; + localDataPoolMap.emplace(static_cast(PoolIds::RTD_VALUE), new PoolEntry({0})); + localDataPoolMap.emplace(static_cast(PoolIds::TEMPERATURE_C), new PoolEntry({0})); + localDataPoolMap.emplace(static_cast(PoolIds::FAULT_BYTE), new PoolEntry({0})); poolManager.subscribeForPeriodicPacket(sensorDataset.getSid(), false, 30.0, false); return RETURN_OK; } diff --git a/mission/devices/Max31865PT1000Handler.cpp b/mission/devices/Max31865PT1000Handler.cpp index debe60e9..e82a0d9f 100644 --- a/mission/devices/Max31865PT1000Handler.cpp +++ b/mission/devices/Max31865PT1000Handler.cpp @@ -160,6 +160,7 @@ ReturnValue_t Max31865PT1000Handler::buildCommandFromCommand(DeviceCommandId_t d commandBuffer[0] = static_cast(MAX31865::CONFIG_CMD); if (commandDataLen == 1) { commandBuffer[1] = commandData[0]; + currentCfg = commandData[0]; DeviceHandlerBase::rawPacketLen = 2; DeviceHandlerBase::rawPacket = commandBuffer.data(); return HasReturnvaluesIF::RETURN_OK; @@ -169,7 +170,7 @@ ReturnValue_t Max31865PT1000Handler::buildCommandFromCommand(DeviceCommandId_t d } case (MAX31865::CLEAR_FAULT_BYTE): { commandBuffer[0] = static_cast(MAX31865::CONFIG_CMD); - commandBuffer[1] = MAX31865::CLEAR_FAULT_BIT_VAL; + commandBuffer[1] = currentCfg | MAX31865::CLEAR_FAULT_BIT_VAL; DeviceHandlerBase::rawPacketLen = 2; DeviceHandlerBase::rawPacket = commandBuffer.data(); return HasReturnvaluesIF::RETURN_OK; @@ -512,9 +513,11 @@ ReturnValue_t Max31865PT1000Handler::getSwitches(const uint8_t **switches, ReturnValue_t Max31865PT1000Handler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(MAX31865::PoolIds::RTD_VALUE, new PoolEntry({0})); - localDataPoolMap.emplace(MAX31865::PoolIds::TEMPERATURE_C, new PoolEntry({0}, 1, true)); - localDataPoolMap.emplace(MAX31865::PoolIds::FAULT_BYTE, new PoolEntry({0})); + using namespace MAX31865; + localDataPoolMap.emplace(static_cast(PoolIds::RTD_VALUE), new PoolEntry({0})); + localDataPoolMap.emplace(static_cast(PoolIds::TEMPERATURE_C), + new PoolEntry({0}, 1, true)); + localDataPoolMap.emplace(static_cast(PoolIds::FAULT_BYTE), new PoolEntry({0})); poolManager.subscribeForPeriodicPacket(sensorDataset.getSid(), false, 30.0, false); return HasReturnvaluesIF::RETURN_OK; } diff --git a/mission/devices/Max31865PT1000Handler.h b/mission/devices/Max31865PT1000Handler.h index 9a6b5add..0d3e4bb3 100644 --- a/mission/devices/Max31865PT1000Handler.h +++ b/mission/devices/Max31865PT1000Handler.h @@ -109,6 +109,7 @@ class Max31865PT1000Handler : public DeviceHandlerBase { bool resetFaultBit = false; dur_millis_t startTime = 0; + uint8_t currentCfg = 0; std::string locString; uint8_t faultByte = 0; uint8_t deviceIdx = 0; diff --git a/mission/devices/devicedefinitions/Max31865Definitions.h b/mission/devices/devicedefinitions/Max31865Definitions.h index d1b67429..1a3cca7a 100644 --- a/mission/devices/devicedefinitions/Max31865Definitions.h +++ b/mission/devices/devicedefinitions/Max31865Definitions.h @@ -9,7 +9,7 @@ namespace MAX31865 { -enum PoolIds : lp_id_t { RTD_VALUE, TEMPERATURE_C, FAULT_BYTE }; +enum class PoolIds : lp_id_t { RTD_VALUE, TEMPERATURE_C, FAULT_BYTE }; enum Wires : unsigned int { TWO_WIRE = 0, THREE_WIRE = 1, FOUR_WIRE = 0 }; enum ConvMode : unsigned int { NORM_OFF = 0, AUTO = 1 }; @@ -30,26 +30,30 @@ enum CfgBitPos { static constexpr uint32_t WARMUP_MS = 100; +static constexpr uint8_t WRITE_BIT = 0b10000000; + +enum Regs : uint8_t { + CONFIG = 0x00, + RTD = 0x01, + HIGH_THRESHOLD = 0x03, + LOW_THRESHOLD = 0x05, + FAULT_BYTE = 0x07 +}; + static constexpr DeviceCommandId_t CONFIG_CMD = 0x80; static constexpr DeviceCommandId_t WRITE_HIGH_THRESHOLD = 0x83; static constexpr DeviceCommandId_t WRITE_LOW_THRESHOLD = 0x85; -static constexpr DeviceCommandId_t REQUEST_CONFIG = 0x00; -static constexpr DeviceCommandId_t REQUEST_RTD = 0x01; -static constexpr DeviceCommandId_t REQUEST_HIGH_THRESHOLD = 0x03; -static constexpr DeviceCommandId_t REQUEST_LOW_THRESHOLD = 0x05; -static constexpr DeviceCommandId_t REQUEST_FAULT_BYTE = 0x07; - +static constexpr DeviceCommandId_t REQUEST_CONFIG = CONFIG; +static constexpr DeviceCommandId_t REQUEST_RTD = RTD; +static constexpr DeviceCommandId_t REQUEST_HIGH_THRESHOLD = HIGH_THRESHOLD; +static constexpr DeviceCommandId_t REQUEST_LOW_THRESHOLD = LOW_THRESHOLD; +static constexpr DeviceCommandId_t REQUEST_FAULT_BYTE = FAULT_BYTE; static constexpr DeviceCommandId_t CLEAR_FAULT_BYTE = 0x08; static constexpr uint32_t MAX31865_SET_ID = REQUEST_RTD; static constexpr uint8_t CLEAR_FAULT_BIT_VAL = 0b0000'0010; -static constexpr uint8_t WRITE_BIT = 0b10000000; - -static constexpr uint8_t REG_CONFIG = 0x00; -static constexpr uint8_t REG_RTD = 0x01; - static constexpr size_t MAX_REPLY_SIZE = 5; class Max31865Set : public StaticLocalDataSet<3> { @@ -67,9 +71,12 @@ class Max31865Set : public StaticLocalDataSet<3> { */ Max31865Set(object_id_t objectId, uint32_t setId) : StaticLocalDataSet(sid_t(objectId, setId)) {} - lp_var_t rtdValue = lp_var_t(sid.objectId, PoolIds::RTD_VALUE, this); - lp_var_t temperatureCelcius = lp_var_t(sid.objectId, PoolIds::TEMPERATURE_C, this); - lp_var_t errorByte = lp_var_t(sid.objectId, PoolIds::FAULT_BYTE, this); + lp_var_t rtdValue = + lp_var_t(sid.objectId, static_cast(PoolIds::RTD_VALUE), this); + lp_var_t temperatureCelcius = + lp_var_t(sid.objectId, static_cast(PoolIds::TEMPERATURE_C), this); + lp_var_t errorByte = + lp_var_t(sid.objectId, static_cast(PoolIds::FAULT_BYTE), this); }; } // namespace MAX31865 @@ -86,7 +93,7 @@ enum RtdCommands : DeviceCommandId_t { HIGH_TRESHOLD = 4, OFF = 5, CFG = 6, - + NUM_CMDS }; class ReadOutStruct : public SerialLinkedListAdapter { From a173ef43082b88de21a63cec982cf901ff7a0645 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 12 May 2022 12:12:47 +0200 Subject: [PATCH 09/74] create low level rtd handler in obj factory --- linux/ObjectFactory.cpp | 49 ++++++++++++++-------- linux/devices/Max31865RtdLowlevelHandler.h | 2 +- misc/eclipse/.cproject | 22 +++++----- mission/devices/Max31865EiveHandler.cpp | 9 ++++ mission/devices/Max31865EiveHandler.h | 4 ++ mission/devices/Max31865PT1000Handler.cpp | 4 +- mission/devices/Max31865PT1000Handler.h | 2 +- 7 files changed, 60 insertions(+), 32 deletions(-) diff --git a/linux/ObjectFactory.cpp b/linux/ObjectFactory.cpp index 35d1cff9..3e760c1f 100644 --- a/linux/ObjectFactory.cpp +++ b/linux/ObjectFactory.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include #include @@ -245,8 +247,8 @@ void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF, gpioChecker(gpioComIF->addGpios(rtdGpioCookie), "RTDs"); #if OBSW_ADD_RTD_DEVICES == 1 - static constexpr uint8_t NUMBER_RTDS = 16; - std::array, NUMBER_RTDS> cookieArgs = {{ + using namespace EiveMax31855; + std::array, NUM_RTDS> cookieArgs = {{ {addresses::RTD_IC_3, gpioIds::RTD_IC_3}, {addresses::RTD_IC_4, gpioIds::RTD_IC_4}, {addresses::RTD_IC_5, gpioIds::RTD_IC_5}, @@ -264,7 +266,7 @@ void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF, {addresses::RTD_IC_17, gpioIds::RTD_IC_17}, {addresses::RTD_IC_18, gpioIds::RTD_IC_18}, }}; - std::array, NUMBER_RTDS> rtdInfos = {{ + std::array, NUM_RTDS> rtdInfos = {{ {objects::RTD_0_IC3_PLOC_HEATSPREADER, "RTD_0_PLOC_HEATSPREADER"}, {objects::RTD_1_IC4_PLOC_MISSIONBOARD, "RTD_1_PLOC_MISSIONBOARD"}, {objects::RTD_2_IC5_4K_CAMERA, "RTD_2_4K_CAMERA"}, @@ -282,31 +284,44 @@ void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF, {objects::RTD_14_IC17_TCS_BOARD, "RTD_14_TCS_BOARD"}, {objects::RTD_15_IC18_IMTQ, "RTD_15_IMTQ"}, }}; - std::array rtdCookies = {}; - std::array rtds = {}; + std::array rtdCookies = {}; + std::array rtds = {}; RtdFdir* rtdFdir = nullptr; - for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) { + bool useDirectHandler = false; + auto directRtdsCreator = [&](uint8_t idx) { + auto typedHandler = + new Max31865PT1000Handler(rtdInfos[idx].first, objects::SPI_MAIN_COM_IF, rtdCookies[idx]); + rtds[idx] = typedHandler; + typedHandler->setDeviceInfo(idx + 3, rtdInfos[idx].second); + }; + auto lowLevelRtdsCreator = [&](uint8_t idx) { + Max31865ReaderCookie* rtdLowLevelCookie = + new Max31865ReaderCookie(rtdInfos[idx].first, idx, rtdInfos[idx].second, rtdCookies[idx]); + auto typedHandler = + new Max31865EiveHandler(rtdInfos[idx].first, objects::SPI_MAIN_COM_IF, rtdLowLevelCookie); + rtds[idx] = typedHandler; + typedHandler->setDeviceInfo(idx, rtdInfos[idx].second); + }; + for (uint8_t idx = 0; idx < NUM_RTDS; idx++) { rtdCookies[idx] = new SpiCookie(cookieArgs[idx].first, cookieArgs[idx].second, MAX31865::MAX_REPLY_SIZE, spi::RTD_MODE, spi::RTD_SPEED); - rtds[idx] = - new Max31865PT1000Handler(rtdInfos[idx].first, objects::SPI_MAIN_COM_IF, rtdCookies[idx]); + if (useDirectHandler) { + directRtdsCreator(idx); + } else { + lowLevelRtdsCreator(idx); + } rtds[idx]->setParent(objects::TCS_BOARD_ASS); rtdFdir = new RtdFdir(rtdInfos[idx].first); rtds[idx]->setCustomFdir(rtdFdir); - rtds[idx]->setDeviceInfo(idx + 3, rtdInfos[idx].second); #if OBSW_DEBUG_RTD == 1 rtds[idx]->setDebugMode(true); #endif +#if OBSW_TEST_RTD == 1 + rtds[idx]->setStartUpImmediately(); + rtds[idx]->setInstantNormal(true); +#endif // OBSW_TEST_RTD == 1 } -#if OBSW_TEST_RTD == 1 - for (auto& rtd : rtds) { - if (rtd != nullptr) { - rtd->setStartUpImmediately(); - rtd->setInstantNormal(true); - } - } -#endif // OBSW_TEST_RTD == 1 TcsBoardHelper helper(rtdInfos); TcsBoardAssembly* tcsBoardAss = new TcsBoardAssembly(objects::TCS_BOARD_ASS, objects::NO_OBJECT, pwrSwitcher, diff --git a/linux/devices/Max31865RtdLowlevelHandler.h b/linux/devices/Max31865RtdLowlevelHandler.h index 5e9a7c26..8194b1a8 100644 --- a/linux/devices/Max31865RtdLowlevelHandler.h +++ b/linux/devices/Max31865RtdLowlevelHandler.h @@ -9,7 +9,7 @@ #include "fsfw/devicehandlers/DeviceCommunicationIF.h" #include "mission/devices/devicedefinitions/Max31865Definitions.h" -struct Max31865ReaderCookie { +struct Max31865ReaderCookie : public CookieIF { Max31865ReaderCookie(){}; Max31865ReaderCookie(object_id_t handlerId_, uint8_t idx_, const std::string& locString_, SpiCookie* spiCookie_) diff --git a/misc/eclipse/.cproject b/misc/eclipse/.cproject index f40535b7..d30ef1ec 100644 --- a/misc/eclipse/.cproject +++ b/misc/eclipse/.cproject @@ -57,7 +57,7 @@ - + @@ -119,7 +119,7 @@ - + @@ -187,7 +187,7 @@ - + @@ -255,7 +255,7 @@ - + @@ -750,7 +750,7 @@ - + @@ -851,7 +851,7 @@