ploc memory dumper complete

This commit is contained in:
Jakob.Meier 2021-08-31 11:20:21 +02:00
parent 89b68940be
commit 0f79864446
19 changed files with 164 additions and 98 deletions

View File

@ -96,13 +96,6 @@ void initmission::initTasks() {
initmission::printAddObjectError("UDP_POLLING", objects::TMTC_POLLING_TASK);
}
PeriodicTaskIF* plocUpdaterTask = factory->createPeriodicTask(
"PLOC_UPDATER_TASK", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc);
result = plocUpdaterTask->addComponent(objects::PLOC_UPDATER);
if(result != HasReturnvaluesIF::RETURN_OK) {
initmission::printAddObjectError("PLOC_UPDATER_TASK", objects::PLOC_UPDATER);
}
# if BOARD_TE0720 == 0
// FS task, task interval does not matter because it runs in permanent loop, priority low
// because it is a non-essential background task
@ -151,7 +144,6 @@ void initmission::initTasks() {
#if BOARD_TE0720 == 0
coreController->startTask();
#endif
plocUpdaterTask->startTask();
taskStarter(pstTasks, "PST task vector");
taskStarter(pusTasks, "PUS task vector");

View File

@ -14,6 +14,7 @@
#include "bsp_q7s/memory/FileSystemHandler.h"
#include "bsp_q7s/devices/PlocSupervisorHandler.h"
#include "bsp_q7s/devices/PlocUpdater.h"
#include "bsp_q7s/devices/PlocMemoryDumper.h"
#include "linux/devices/HeaterHandler.h"
#include "linux/devices/SolarArrayDeploymentHandler.h"
@ -180,6 +181,7 @@ void ObjectFactory::produce(void* args){
#endif /* OBSW_ADD_TEST_CODE == 1 */
new PlocUpdater(objects::PLOC_UPDATER);
new PlocMemoryDumper(objects::PLOC_MEMORY_DUMPER);
}
void ObjectFactory::createTmpComponents() {

View File

@ -1,4 +1,5 @@
target_sources(${TARGET_NAME} PRIVATE
PlocSupervisorHandler.cpp
PlocUpdater.cpp
PlocMemoryDumper.cpp
)

View File

@ -1,3 +1,4 @@
#include <fsfw/src/fsfw/serialize/SerializeAdapter.h>
#include "fsfw/ipc/QueueFactory.h"
#include "PlocMemoryDumper.h"
@ -39,17 +40,17 @@ ReturnValue_t PlocMemoryDumper::performOperation(uint8_t operationCode) {
ReturnValue_t PlocMemoryDumper::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
ReturnValue_t result = RETURN_FAILED;
if (state != State::IDLE) {
return IS_BUSY;
}
switch (actionId) {
case DUMP_MRAM:
SerializeAdapter::deSerialize(&mram.startAddress, &data, sizeof(mramStartAdress),
case DUMP_MRAM: {
size_t deserializeSize = sizeof(mram.startAddress) + sizeof(mram.endAddress);
SerializeAdapter::deSerialize(&mram.startAddress, &data, &deserializeSize,
SerializeIF::Endianness::BIG);
SerializeAdapter::deSerialize(&mram.endAddress, &data, sizeof(mramStartAdress),
SerializeAdapter::deSerialize(&mram.endAddress, &data, &deserializeSize,
SerializeIF::Endianness::BIG);
if (mram.endAddress > MAX_MRAM_ADDRESS) {
return MRAM_ADDRESS_TOO_HIGH;
@ -59,13 +60,15 @@ ReturnValue_t PlocMemoryDumper::executeAction(ActionId_t actionId,
}
state = State::COMMAND_FIRST_MRAM_DUMP;
break;
default:
}
default: {
sif::warning << "PlocMemoryDumper::executeAction: Received command with invalid action id"
<< std::endl;
return INVALID_ACTION_ID;
}
}
return RETURN_OK;
return EXECUTION_FINISHED;
}
MessageQueueId_t PlocMemoryDumper::getCommandQueue() const {
@ -139,7 +142,7 @@ void PlocMemoryDumper::completionSuccessfulReceived(ActionId_t actionId) {
state = State::IDLE;
}
else {
state = State::COMMAND_MRAM_DUMP;
state = State::COMMAND_CONSECUTIVE_MRAM_DUMP;
}
break;
default:

View File

@ -51,6 +51,8 @@ public:
private:
static const uint32_t QUEUE_SIZE = 10;
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_MEMORY_DUMPER;
//! [EXPORT] : [COMMENT] The capacity of the MRAM amounts to 512 kB. Thus the maximum address must not be higher than 0x7d000.
@ -91,15 +93,15 @@ private:
ActionId_t pendingCommand = NONE;
typedef struct MemoryRange {
typedef struct MemoryInfo {
// Stores the start address of the next memory range to dump
uint32_t startAddress;
uint32_t endAddress;
// Stores the start address of the last sent dump command
uint32_t lastStartAddress;
} MemoryRange_t;
} MemoryInfo_t;
MemoryRange_t mram = {0, 0, 0};
MemoryInfo_t mram = {0, 0, 0};
void readCommandQueue();
void doStateMachine();
@ -107,7 +109,7 @@ private:
/**
* @brief Sends the next mram dump command to the PLOC supervisor handler.
*/
void commandNextMramDump();
void commandNextMramDump(ActionId_t dumpCommand);
};
#endif /* MISSION_DEVICES_PLOCMEMORYDUMPER_H_ */

View File

@ -199,10 +199,10 @@ ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand(
result = prepareWipeMramCmd(commandData);
break;
}
case(PLOC_SPV::DUMP_MRAM): {
case(PLOC_SPV::FIRST_MRAM_DUMP):
case(PLOC_SPV::CONSECUTIVE_MRAM_DUMP):
result = prepareDumpMramCmd(commandData);
break;
}
case(PLOC_SPV::PRINT_CPU_STATS): {
preparePrintCpuStatsCmd(commandData);
result = RETURN_OK;
@ -319,7 +319,8 @@ void PlocSupervisorHandler::fillCommandAndReplyMap() {
this->insertInCommandMap(PLOC_SPV::FACTORY_RESET_CLEAR_MIRROR);
this->insertInCommandMap(PLOC_SPV::FACTORY_RESET_CLEAR_CIRCULAR);
this->insertInCommandMap(PLOC_SPV::CAN_LOOPBACK_TEST);
this->insertInCommandAndReplyMap(PLOC_SPV::DUMP_MRAM, 3);
this->insertInCommandAndReplyMap(PLOC_SPV::FIRST_MRAM_DUMP, 3);
this->insertInCommandAndReplyMap(PLOC_SPV::CONSECUTIVE_MRAM_DUMP, 3);
this->insertInReplyMap(PLOC_SPV::ACK_REPORT, 3, nullptr, PLOC_SPV::SIZE_ACK_REPORT);
this->insertInReplyMap(PLOC_SPV::EXE_REPORT, 3, nullptr, PLOC_SPV::SIZE_EXE_REPORT);
this->insertInReplyMap(PLOC_SPV::HK_REPORT, 3, &hkset, PLOC_SPV::SIZE_HK_REPORT);
@ -332,8 +333,12 @@ void PlocSupervisorHandler::fillCommandAndReplyMap() {
ReturnValue_t PlocSupervisorHandler::scanForReply(const uint8_t *start,
size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) {
if (nextReplyId == PLOC_SPV::DUMP_MRAM) {
*foundId = PLOC_SPV::DUMP_MRAM;
if (nextReplyId == PLOC_SPV::FIRST_MRAM_DUMP) {
*foundId = PLOC_SPV::FIRST_MRAM_DUMP;
return parseMramPackets(start, remainingSize, foundLen);
}
else if (nextReplyId == PLOC_SPV::CONSECUTIVE_MRAM_DUMP) {
*foundId = PLOC_SPV::CONSECUTIVE_MRAM_DUMP;
return parseMramPackets(start, remainingSize, foundLen);
}
@ -402,10 +407,10 @@ ReturnValue_t PlocSupervisorHandler::interpretDeviceReply(DeviceCommandId_t id,
result = handleLatchupStatusReport(packet);
break;
}
case (PLOC_SPV::DUMP_MRAM): {
result = handleMramDumpPacket();
case (PLOC_SPV::FIRST_MRAM_DUMP):
case (PLOC_SPV::CONSECUTIVE_MRAM_DUMP):
result = handleMramDumpPacket(id);
break;
}
case (PLOC_SPV::EXE_REPORT): {
result = handleExecutionReport(packet);
break;
@ -511,13 +516,23 @@ ReturnValue_t PlocSupervisorHandler::enableReplyInReplyMap(DeviceCommandMap::ite
}
break;
}
case PLOC_SPV::DUMP_MRAM: {
case PLOC_SPV::FIRST_MRAM_DUMP: {
enabledReplies = 2; // expected replies will be increased in handleMramDumpPacket
result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true,
PLOC_SPV::DUMP_MRAM);
PLOC_SPV::FIRST_MRAM_DUMP);
if (result != RETURN_OK) {
sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id "
<< PLOC_SPV::LATCHUP_REPORT << " not in replyMap" << std::endl;
<< PLOC_SPV::FIRST_MRAM_DUMP << " not in replyMap" << std::endl;
}
break;
}
case PLOC_SPV::CONSECUTIVE_MRAM_DUMP: {
enabledReplies = 2; // expected replies will be increased in handleMramDumpPacket
result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true,
PLOC_SPV::CONSECUTIVE_MRAM_DUMP);
if (result != RETURN_OK) {
sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id "
<< PLOC_SPV::CONSECUTIVE_MRAM_DUMP << " not in replyMap" << std::endl;
}
break;
}
@ -924,8 +939,11 @@ void PlocSupervisorHandler::setNextReplyId() {
case PLOC_SPV::GET_LATCHUP_STATUS_REPORT:
nextReplyId = PLOC_SPV::LATCHUP_REPORT;
break;
case PLOC_SPV::DUMP_MRAM:
nextReplyId = PLOC_SPV::DUMP_MRAM;
case PLOC_SPV::FIRST_MRAM_DUMP:
nextReplyId = PLOC_SPV::FIRST_MRAM_DUMP;
break;
case PLOC_SPV::CONSECUTIVE_MRAM_DUMP:
nextReplyId = PLOC_SPV::CONSECUTIVE_MRAM_DUMP;
break;
default:
/* If no telemetry is expected the next reply is always the execution report */
@ -942,7 +960,8 @@ size_t PlocSupervisorHandler::getNextReplyLength(DeviceCommandId_t commandId){
return replyLen;
}
if (nextReplyId == PLOC_SPV::DUMP_MRAM) {
if (nextReplyId == PLOC_SPV::FIRST_MRAM_DUMP
|| nextReplyId == PLOC_SPV::CONSECUTIVE_MRAM_DUMP) {
/**
* Try to read 20 MRAM packets. If reply is larger, the packets will be read with the
* next doSendRead call. The command will be as long active as the packet with the sequence
@ -1347,7 +1366,7 @@ ReturnValue_t PlocSupervisorHandler::parseMramPackets(const uint8_t *packet, siz
return result;
}
ReturnValue_t PlocSupervisorHandler::handleMramDumpPacket() {
ReturnValue_t PlocSupervisorHandler::handleMramDumpPacket(DeviceCommandId_t id) {
ReturnValue_t result = RETURN_FAILED;
@ -1359,24 +1378,24 @@ ReturnValue_t PlocSupervisorHandler::handleMramDumpPacket() {
sif::warning << "PlocSupervisorHandler::handleMramDumpPacket: CRC failure" << std::endl;
return result;
}
handleMramDumpFile();
handleMramDumpFile(id);
if (downlinkMramDump == true) {
handleDeviceTM(spacePacketBuffer + PLOC_SPV::SPACE_PACKET_HEADER_LENGTH, packetLen - 1,
PLOC_SPV::DUMP_MRAM);
id);
}
packetInBuffer = false;
receivedMramDumpPackets++;
if (expectedMramDumpPackets == receivedMramDumpPackets) {
nextReplyId = PLOC_SPV::EXE_REPORT;
}
increaseExpectedMramReplies();
increaseExpectedMramReplies(id);
return RETURN_OK;
}
return result;
}
void PlocSupervisorHandler::increaseExpectedMramReplies() {
DeviceReplyMap::iterator mramDumpIter = deviceReplyMap.find(PLOC_SPV::DUMP_MRAM);
void PlocSupervisorHandler::increaseExpectedMramReplies(DeviceCommandId_t id) {
DeviceReplyMap::iterator mramDumpIter = deviceReplyMap.find(id);
DeviceReplyMap::iterator exeReportIter = deviceReplyMap.find(PLOC_SPV::EXE_REPORT);
if (mramDumpIter == deviceReplyMap.end()) {
sif::debug << "PlocSupervisorHandler::increaseExpectedMramReplies: Dump MRAM reply not "
@ -1432,10 +1451,11 @@ ReturnValue_t PlocSupervisorHandler::checkMramPacketApid() {
return APERIODIC_REPLY;
}
ReturnValue_t PlocSupervisorHandler::handleMramDumpFile() {
ReturnValue_t PlocSupervisorHandler::handleMramDumpFile(DeviceCommandId_t id) {
ReturnValue_t result = RETURN_OK;
uint16_t packetLen = readSpacePacketLength(spacePacketBuffer);
uint8_t sequenceFlags = readSequenceFlags(spacePacketBuffer);
if (id == PLOC_SPV::FIRST_MRAM_DUMP) {
if (sequenceFlags == static_cast<uint8_t>(PLOC_SPV::SequenceFlags::FIRST_PKT)
|| (sequenceFlags == static_cast<uint8_t>(PLOC_SPV::SequenceFlags::STANDALONE_PKT))) {
result = createMramDumpFile();
@ -1443,6 +1463,7 @@ ReturnValue_t PlocSupervisorHandler::handleMramDumpFile() {
return result;
}
}
}
if (not std::filesystem::exists(activeMramFile)) {
sif::warning << "PlocSupervisorHandler::handleMramDumpFile: MRAM file does not exist"
<< std::endl;

View File

@ -295,14 +295,14 @@ private:
/**
* @brief This function generates the Service 8 packets for the MRAM dump data.
*/
ReturnValue_t handleMramDumpPacket();
ReturnValue_t handleMramDumpPacket(DeviceCommandId_t id);
/**
* @brief With this function the number of expected replies following an MRAM dump command
* will be increased. This is necessary to release the command in case not all replies
* have been received.
*/
void increaseExpectedMramReplies();
void increaseExpectedMramReplies(DeviceCommandId_t id);
/**
* @brief Function checks if the packet written to the space packet buffer is really a
@ -314,7 +314,7 @@ private:
* @brief Writes the data of the MRAM dump to a file. The file will be created when receiving
* the first packet.
*/
ReturnValue_t handleMramDumpFile();
ReturnValue_t handleMramDumpFile(DeviceCommandId_t id);
/**
* @brief Extracts the length field of a spacePacket referenced by the spacePacket pointer.

View File

@ -1,6 +1,8 @@
#ifndef BSP_Q7S_DEVICES_DEVICEDEFINITIONS_PLOCMEMDUMPDEFINITIONS_H_
#define BSP_Q7S_DEVICES_DEVICEDEFINITIONS_PLOCMEMDUMPDEFINITIONS_H_
#include <fsfw/src/fsfw/serialize/SerialLinkedListAdapter.h>
class MemoryParams: public SerialLinkedListAdapter<SerializeIF> {
public:

View File

@ -55,7 +55,7 @@ static const DeviceCommandId_t UPDATE_IMAGE_DATA = 39;
static const DeviceCommandId_t FACTORY_RESET_CLEAR_MIRROR = 40;
static const DeviceCommandId_t FACTORY_RESET_CLEAR_CIRCULAR = 41;
static const DeviceCommandId_t UPDATE_VERIFY = 42;
static const DeviceCommandId_t CONSECUTIVE_MRAM_DUMP = 41;
static const DeviceCommandId_t CONSECUTIVE_MRAM_DUMP = 43;
/** Reply IDs */
static const DeviceCommandId_t ACK_REPORT = 50;

View File

@ -82,7 +82,8 @@ enum commonObjects: uint32_t {
START_TRACKER = 0x44130001,
PLOC_UPDATER = 0x44330000
PLOC_UPDATER = 0x44330000,
PLOC_MEMORY_DUMPER = 0x44330001
};
}

View File

@ -90,13 +90,17 @@
11207;SELF_TEST_COIL_CURRENT_FAILURE;LOW;Get self test result returns failure indicating that the coil current was outside of the expected range P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/IMTQHandler.h
11208;INVALID_ERROR_BYTE;LOW;Received invalid error byte. This indicates an error of the communication link between IMTQ and OBC.;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/IMTQHandler.h
11301;ERROR_STATE;HIGH;Reaction wheel signals an error state;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/RwHandler.h
11501;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocSupervisorHandler.h
11502;SUPV_ACK_FAILURE;LOW;PLOC supervisor received acknowledgment failure report;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocSupervisorHandler.h
11503;SUPV_EXE_FAILURE;LOW;PLOC received execution failure report;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocSupervisorHandler.h
11504;SUPV_CRC_FAILURE_EVENT;LOW;PLOC supervisor reply has invalid crc;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocSupervisorHandler.h
11700;UPDATE_FILE_NOT_EXISTS;LOW;;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocUpdater.h
11701;ACTION_COMMANDING_FAILED;LOW;;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocUpdater.h
11702;UPDATE_AVAILABLE_FAILED;LOW;Supervisor handler replied action message indicating a command execution failure of the update available command;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocUpdater.h
11703;UPDATE_TRANSFER_FAILED;LOW;Supervisor handler failed to transfer an update space packet. P1: Parameter holds the number of update packets already sent.;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocUpdater.h
11704;UPDATE_VERIFY_FAILED;LOW;Supervisor failed to execute the update verify command.;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocUpdater.h
11705;UPDATE_FINISHED;INFO;MPSoC update successful completed;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocUpdater.h
11501;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocSupervisorHandler.h
11502;SUPV_ACK_FAILURE;LOW;PLOC supervisor received acknowledgment failure report;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocSupervisorHandler.h
11503;SUPV_EXE_FAILURE;LOW;PLOC received execution failure report;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocSupervisorHandler.h
11504;SUPV_CRC_FAILURE_EVENT;LOW;PLOC supervisor reply has invalid crc;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocSupervisorHandler.h
11600;SANITIZATION_FAILED;LOW;;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/memory/SdCardManager.h
11700;UPDATE_FILE_NOT_EXISTS;LOW;;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h
11701;ACTION_COMMANDING_FAILED;LOW;;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h
11702;UPDATE_AVAILABLE_FAILED;LOW;Supervisor handler replied action message indicating a command execution failure of the update available command;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h
11703;UPDATE_TRANSFER_FAILED;LOW;Supervisor handler failed to transfer an update space packet. P1: Parameter holds the number of update packets already sent (inclusive the failed packet);C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h
11704;UPDATE_VERIFY_FAILED;LOW;Supervisor failed to execute the update verify command.;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h
11705;UPDATE_FINISHED;INFO;MPSoC update successful completed;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h
11800;SEND_MRAM_DUMP_FAILED;LOW;;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocMemoryDumper.h
11801;MRAM_DUMP_FAILED;LOW;Received completion failure report form PLOC supervisor handler P1: MRAM start address of failing dump command;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocMemoryDumper.h
11802;MRAM_DUMP_FINISHED;LOW;MRAM dump finished successfully;C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocMemoryDumper.h

1 2200 STORE_SEND_WRITE_FAILED LOW C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/fsfw/src/fsfw/tmstorage/TmStoreBackendIF.h
90 11207 SELF_TEST_COIL_CURRENT_FAILURE LOW Get self test result returns failure indicating that the coil current was outside of the expected range P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/IMTQHandler.h
91 11208 INVALID_ERROR_BYTE LOW Received invalid error byte. This indicates an error of the communication link between IMTQ and OBC. C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/IMTQHandler.h
92 11301 ERROR_STATE HIGH Reaction wheel signals an error state C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/RwHandler.h
93 11501 SUPV_MEMORY_READ_RPT_CRC_FAILURE LOW PLOC supervisor crc failure in telemetry packet C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocSupervisorHandler.h C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocSupervisorHandler.h
94 11502 SUPV_ACK_FAILURE LOW PLOC supervisor received acknowledgment failure report C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocSupervisorHandler.h C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocSupervisorHandler.h
95 11503 SUPV_EXE_FAILURE LOW PLOC received execution failure report C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocSupervisorHandler.h C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocSupervisorHandler.h
96 11504 SUPV_CRC_FAILURE_EVENT LOW PLOC supervisor reply has invalid crc C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocSupervisorHandler.h C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocSupervisorHandler.h
97 11700 11600 UPDATE_FILE_NOT_EXISTS SANITIZATION_FAILED LOW C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocUpdater.h C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/memory/SdCardManager.h
98 11701 11700 ACTION_COMMANDING_FAILED UPDATE_FILE_NOT_EXISTS LOW C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocUpdater.h C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h
99 11702 11701 UPDATE_AVAILABLE_FAILED ACTION_COMMANDING_FAILED LOW Supervisor handler replied action message indicating a command execution failure of the update available command C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocUpdater.h C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h
100 11703 11702 UPDATE_TRANSFER_FAILED UPDATE_AVAILABLE_FAILED LOW Supervisor handler failed to transfer an update space packet. P1: Parameter holds the number of update packets already sent. Supervisor handler replied action message indicating a command execution failure of the update available command C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocUpdater.h C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h
101 11704 11703 UPDATE_VERIFY_FAILED UPDATE_TRANSFER_FAILED LOW Supervisor failed to execute the update verify command. Supervisor handler failed to transfer an update space packet. P1: Parameter holds the number of update packets already sent (inclusive the failed packet) C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocUpdater.h C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h
102 11705 11704 UPDATE_FINISHED UPDATE_VERIFY_FAILED INFO LOW MPSoC update successful completed Supervisor failed to execute the update verify command. C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/mission/devices/PlocUpdater.h C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h
103 11705 UPDATE_FINISHED INFO MPSoC update successful completed C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocUpdater.h
104 11800 SEND_MRAM_DUMP_FAILED LOW C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocMemoryDumper.h
105 11801 MRAM_DUMP_FAILED LOW Received completion failure report form PLOC supervisor handler P1: MRAM start address of failing dump command C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocMemoryDumper.h
106 11802 MRAM_DUMP_FINISHED LOW MRAM dump finished successfully C:\Users\jakob\Work\EIVE\Q7S\Software\eive_obsw/bsp_q7s/devices/PlocMemoryDumper.h

View File

@ -2,10 +2,6 @@
0x43000003;CORE_CONTROLLER
0x43100002;ACS_CONTROLLER
0x43400001;THERMAL_CONTROLLER
0x44120001;RW1
0x44120002;RW2
0x44120003;RW3
0x44120004;RW4
0x44120006;MGM_0_LIS3_HANDLER
0x44120010;GYRO_0_ADIS_HANDLER
0x44120032;SUS_1
@ -21,12 +17,16 @@
0x44120042;SUS_11
0x44120043;SUS_12
0x44120044;SUS_13
0x44120047;RW1
0x44120107;MGM_1_RM3100_HANDLER
0x44120111;GYRO_1_L3G_HANDLER
0x44120148;RW2
0x44120208;MGM_2_LIS3_HANDLER
0x44120212;GYRO_2_ADIS_HANDLER
0x44120249;RW3
0x44120309;MGM_3_RM3100_HANDLER
0x44120313;GYRO_3_L3G_HANDLER
0x44120350;RW4
0x44130001;START_TRACKER
0x44130045;GPS0_HANDLER
0x44130146;GPS1_HANDLER
@ -38,6 +38,7 @@
0x44250003;ACU_HANDLER
0x443200A5;RAD_SENSOR
0x44330000;PLOC_UPDATER
0x44330001;PLOC_MEMORY_DUMPER
0x44330015;PLOC_MPSOC_HANDLER
0x44330016;PLOC_SUPERVISOR_HANDLER
0x444100A2;SOLAR_ARRAY_DEPL_HANDLER

1 0x00005060 P60DOCK_TEST_TASK
2 0x43000003 CORE_CONTROLLER
3 0x43100002 ACS_CONTROLLER
4 0x43400001 THERMAL_CONTROLLER
0x44120001 RW1
0x44120002 RW2
0x44120003 RW3
0x44120004 RW4
5 0x44120006 MGM_0_LIS3_HANDLER
6 0x44120010 GYRO_0_ADIS_HANDLER
7 0x44120032 SUS_1
17 0x44120042 SUS_11
18 0x44120043 SUS_12
19 0x44120044 SUS_13
20 0x44120047 RW1
21 0x44120107 MGM_1_RM3100_HANDLER
22 0x44120111 GYRO_1_L3G_HANDLER
23 0x44120148 RW2
24 0x44120208 MGM_2_LIS3_HANDLER
25 0x44120212 GYRO_2_ADIS_HANDLER
26 0x44120249 RW3
27 0x44120309 MGM_3_RM3100_HANDLER
28 0x44120313 GYRO_3_L3G_HANDLER
29 0x44120350 RW4
30 0x44130001 START_TRACKER
31 0x44130045 GPS0_HANDLER
32 0x44130146 GPS1_HANDLER
38 0x44250003 ACU_HANDLER
39 0x443200A5 RAD_SENSOR
40 0x44330000 PLOC_UPDATER
41 0x44330001 PLOC_MEMORY_DUMPER
42 0x44330015 PLOC_MPSOC_HANDLER
43 0x44330016 PLOC_SUPERVISOR_HANDLER
44 0x444100A2 SOLAR_ARRAY_DEPL_HANDLER

View File

@ -51,7 +51,7 @@ SUBSYSTEM_DEFINITION_DESTINATIONS = [
]
HEADER_DEFINITION_DESTINATIONS = [
f"{OBSW_ROOT_DIR}/mission/", f"{OBSW_ROOT_DIR}/fsfw/", f"{FSFW_CONFIG_ROOT}",
f"{OBSW_ROOT_DIR}/test/"
f"{OBSW_ROOT_DIR}/test/", f"{OBSW_ROOT_DIR}/bsp_q7s"
]

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 102 translations.
* @brief Auto-generated event translation file. Contains 106 translations.
* @details
* Generated on: 2021-08-07 18:11:16
* Generated on: 2021-08-31 10:50:10
*/
#include "translateEvents.h"
@ -101,12 +101,16 @@ const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_
const char *SUPV_ACK_FAILURE_STRING = "SUPV_ACK_FAILURE";
const char *SUPV_EXE_FAILURE_STRING = "SUPV_EXE_FAILURE";
const char *SUPV_CRC_FAILURE_EVENT_STRING = "SUPV_CRC_FAILURE_EVENT";
const char *SANITIZATION_FAILED_STRING = "SANITIZATION_FAILED";
const char *UPDATE_FILE_NOT_EXISTS_STRING = "UPDATE_FILE_NOT_EXISTS";
const char *ACTION_COMMANDING_FAILED_STRING = "ACTION_COMMANDING_FAILED";
const char *UPDATE_AVAILABLE_FAILED_STRING = "UPDATE_AVAILABLE_FAILED";
const char *UPDATE_TRANSFER_FAILED_STRING = "UPDATE_TRANSFER_FAILED";
const char *UPDATE_VERIFY_FAILED_STRING = "UPDATE_VERIFY_FAILED";
const char *UPDATE_FINISHED_STRING = "UPDATE_FINISHED";
const char *SEND_MRAM_DUMP_FAILED_STRING = "SEND_MRAM_DUMP_FAILED";
const char *MRAM_DUMP_FAILED_STRING = "MRAM_DUMP_FAILED";
const char *MRAM_DUMP_FINISHED_STRING = "MRAM_DUMP_FINISHED";
const char * translateEvents(Event event) {
switch( (event & 0xffff) ) {
@ -302,6 +306,8 @@ const char * translateEvents(Event event) {
return SUPV_EXE_FAILURE_STRING;
case(11504):
return SUPV_CRC_FAILURE_EVENT_STRING;
case(11600):
return SANITIZATION_FAILED_STRING;
case(11700):
return UPDATE_FILE_NOT_EXISTS_STRING;
case(11701):
@ -314,6 +320,12 @@ const char * translateEvents(Event event) {
return UPDATE_VERIFY_FAILED_STRING;
case(11705):
return UPDATE_FINISHED_STRING;
case(11800):
return SEND_MRAM_DUMP_FAILED_STRING;
case(11801):
return MRAM_DUMP_FAILED_STRING;
case(11802):
return MRAM_DUMP_FINISHED_STRING;
default:
return "UNKNOWN_EVENT";
}

View File

@ -1,8 +1,8 @@
/**
* @brief Auto-generated object translation file.
* @details
* Contains 104 translations.
* Generated on: 2021-08-07 18:08:35
* Contains 105 translations.
* Generated on: 2021-08-31 10:31:24
*/
#include "translateObjects.h"
@ -10,10 +10,6 @@ const char *P60DOCK_TEST_TASK_STRING = "P60DOCK_TEST_TASK";
const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER";
const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER";
const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER";
const char *RW1_STRING = "RW1";
const char *RW2_STRING = "RW2";
const char *RW3_STRING = "RW3";
const char *RW4_STRING = "RW4";
const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER";
const char *GYRO_0_ADIS_HANDLER_STRING = "GYRO_0_ADIS_HANDLER";
const char *SUS_1_STRING = "SUS_1";
@ -29,12 +25,16 @@ const char *SUS_10_STRING = "SUS_10";
const char *SUS_11_STRING = "SUS_11";
const char *SUS_12_STRING = "SUS_12";
const char *SUS_13_STRING = "SUS_13";
const char *RW1_STRING = "RW1";
const char *MGM_1_RM3100_HANDLER_STRING = "MGM_1_RM3100_HANDLER";
const char *GYRO_1_L3G_HANDLER_STRING = "GYRO_1_L3G_HANDLER";
const char *RW2_STRING = "RW2";
const char *MGM_2_LIS3_HANDLER_STRING = "MGM_2_LIS3_HANDLER";
const char *GYRO_2_ADIS_HANDLER_STRING = "GYRO_2_ADIS_HANDLER";
const char *RW3_STRING = "RW3";
const char *MGM_3_RM3100_HANDLER_STRING = "MGM_3_RM3100_HANDLER";
const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER";
const char *RW4_STRING = "RW4";
const char *START_TRACKER_STRING = "START_TRACKER";
const char *GPS0_HANDLER_STRING = "GPS0_HANDLER";
const char *GPS1_HANDLER_STRING = "GPS1_HANDLER";
@ -46,6 +46,7 @@ const char *PDU2_HANDLER_STRING = "PDU2_HANDLER";
const char *ACU_HANDLER_STRING = "ACU_HANDLER";
const char *RAD_SENSOR_STRING = "RAD_SENSOR";
const char *PLOC_UPDATER_STRING = "PLOC_UPDATER";
const char *PLOC_MEMORY_DUMPER_STRING = "PLOC_MEMORY_DUMPER";
const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER";
const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER";
const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER";
@ -121,14 +122,6 @@ const char* translateObject(object_id_t object) {
return ACS_CONTROLLER_STRING;
case 0x43400001:
return THERMAL_CONTROLLER_STRING;
case 0x44120001:
return RW1_STRING;
case 0x44120002:
return RW2_STRING;
case 0x44120003:
return RW3_STRING;
case 0x44120004:
return RW4_STRING;
case 0x44120006:
return MGM_0_LIS3_HANDLER_STRING;
case 0x44120010:
@ -159,18 +152,26 @@ const char* translateObject(object_id_t object) {
return SUS_12_STRING;
case 0x44120044:
return SUS_13_STRING;
case 0x44120047:
return RW1_STRING;
case 0x44120107:
return MGM_1_RM3100_HANDLER_STRING;
case 0x44120111:
return GYRO_1_L3G_HANDLER_STRING;
case 0x44120148:
return RW2_STRING;
case 0x44120208:
return MGM_2_LIS3_HANDLER_STRING;
case 0x44120212:
return GYRO_2_ADIS_HANDLER_STRING;
case 0x44120249:
return RW3_STRING;
case 0x44120309:
return MGM_3_RM3100_HANDLER_STRING;
case 0x44120313:
return GYRO_3_L3G_HANDLER_STRING;
case 0x44120350:
return RW4_STRING;
case 0x44130001:
return START_TRACKER_STRING;
case 0x44130045:
@ -193,6 +194,8 @@ const char* translateObject(object_id_t object) {
return RAD_SENSOR_STRING;
case 0x44330000:
return PLOC_UPDATER_STRING;
case 0x44330001:
return PLOC_MEMORY_DUMPER_STRING;
case 0x44330015:
return PLOC_MPSOC_HANDLER_STRING;
case 0x44330016:

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 102 translations.
* @brief Auto-generated event translation file. Contains 106 translations.
* @details
* Generated on: 2021-08-07 18:11:16
* Generated on: 2021-08-31 10:50:10
*/
#include "translateEvents.h"
@ -101,12 +101,16 @@ const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_
const char *SUPV_ACK_FAILURE_STRING = "SUPV_ACK_FAILURE";
const char *SUPV_EXE_FAILURE_STRING = "SUPV_EXE_FAILURE";
const char *SUPV_CRC_FAILURE_EVENT_STRING = "SUPV_CRC_FAILURE_EVENT";
const char *SANITIZATION_FAILED_STRING = "SANITIZATION_FAILED";
const char *UPDATE_FILE_NOT_EXISTS_STRING = "UPDATE_FILE_NOT_EXISTS";
const char *ACTION_COMMANDING_FAILED_STRING = "ACTION_COMMANDING_FAILED";
const char *UPDATE_AVAILABLE_FAILED_STRING = "UPDATE_AVAILABLE_FAILED";
const char *UPDATE_TRANSFER_FAILED_STRING = "UPDATE_TRANSFER_FAILED";
const char *UPDATE_VERIFY_FAILED_STRING = "UPDATE_VERIFY_FAILED";
const char *UPDATE_FINISHED_STRING = "UPDATE_FINISHED";
const char *SEND_MRAM_DUMP_FAILED_STRING = "SEND_MRAM_DUMP_FAILED";
const char *MRAM_DUMP_FAILED_STRING = "MRAM_DUMP_FAILED";
const char *MRAM_DUMP_FINISHED_STRING = "MRAM_DUMP_FINISHED";
const char * translateEvents(Event event) {
switch( (event & 0xffff) ) {
@ -302,6 +306,8 @@ const char * translateEvents(Event event) {
return SUPV_EXE_FAILURE_STRING;
case(11504):
return SUPV_CRC_FAILURE_EVENT_STRING;
case(11600):
return SANITIZATION_FAILED_STRING;
case(11700):
return UPDATE_FILE_NOT_EXISTS_STRING;
case(11701):
@ -314,6 +320,12 @@ const char * translateEvents(Event event) {
return UPDATE_VERIFY_FAILED_STRING;
case(11705):
return UPDATE_FINISHED_STRING;
case(11800):
return SEND_MRAM_DUMP_FAILED_STRING;
case(11801):
return MRAM_DUMP_FAILED_STRING;
case(11802):
return MRAM_DUMP_FINISHED_STRING;
default:
return "UNKNOWN_EVENT";
}

View File

@ -1,8 +1,8 @@
/**
* @brief Auto-generated object translation file.
* @details
* Contains 104 translations.
* Generated on: 2021-08-07 18:08:35
* Contains 105 translations.
* Generated on: 2021-08-31 10:31:24
*/
#include "translateObjects.h"
@ -10,10 +10,6 @@ const char *P60DOCK_TEST_TASK_STRING = "P60DOCK_TEST_TASK";
const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER";
const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER";
const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER";
const char *RW1_STRING = "RW1";
const char *RW2_STRING = "RW2";
const char *RW3_STRING = "RW3";
const char *RW4_STRING = "RW4";
const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER";
const char *GYRO_0_ADIS_HANDLER_STRING = "GYRO_0_ADIS_HANDLER";
const char *SUS_1_STRING = "SUS_1";
@ -29,12 +25,16 @@ const char *SUS_10_STRING = "SUS_10";
const char *SUS_11_STRING = "SUS_11";
const char *SUS_12_STRING = "SUS_12";
const char *SUS_13_STRING = "SUS_13";
const char *RW1_STRING = "RW1";
const char *MGM_1_RM3100_HANDLER_STRING = "MGM_1_RM3100_HANDLER";
const char *GYRO_1_L3G_HANDLER_STRING = "GYRO_1_L3G_HANDLER";
const char *RW2_STRING = "RW2";
const char *MGM_2_LIS3_HANDLER_STRING = "MGM_2_LIS3_HANDLER";
const char *GYRO_2_ADIS_HANDLER_STRING = "GYRO_2_ADIS_HANDLER";
const char *RW3_STRING = "RW3";
const char *MGM_3_RM3100_HANDLER_STRING = "MGM_3_RM3100_HANDLER";
const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER";
const char *RW4_STRING = "RW4";
const char *START_TRACKER_STRING = "START_TRACKER";
const char *GPS0_HANDLER_STRING = "GPS0_HANDLER";
const char *GPS1_HANDLER_STRING = "GPS1_HANDLER";
@ -46,6 +46,7 @@ const char *PDU2_HANDLER_STRING = "PDU2_HANDLER";
const char *ACU_HANDLER_STRING = "ACU_HANDLER";
const char *RAD_SENSOR_STRING = "RAD_SENSOR";
const char *PLOC_UPDATER_STRING = "PLOC_UPDATER";
const char *PLOC_MEMORY_DUMPER_STRING = "PLOC_MEMORY_DUMPER";
const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER";
const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER";
const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER";
@ -121,14 +122,6 @@ const char* translateObject(object_id_t object) {
return ACS_CONTROLLER_STRING;
case 0x43400001:
return THERMAL_CONTROLLER_STRING;
case 0x44120001:
return RW1_STRING;
case 0x44120002:
return RW2_STRING;
case 0x44120003:
return RW3_STRING;
case 0x44120004:
return RW4_STRING;
case 0x44120006:
return MGM_0_LIS3_HANDLER_STRING;
case 0x44120010:
@ -159,18 +152,26 @@ const char* translateObject(object_id_t object) {
return SUS_12_STRING;
case 0x44120044:
return SUS_13_STRING;
case 0x44120047:
return RW1_STRING;
case 0x44120107:
return MGM_1_RM3100_HANDLER_STRING;
case 0x44120111:
return GYRO_1_L3G_HANDLER_STRING;
case 0x44120148:
return RW2_STRING;
case 0x44120208:
return MGM_2_LIS3_HANDLER_STRING;
case 0x44120212:
return GYRO_2_ADIS_HANDLER_STRING;
case 0x44120249:
return RW3_STRING;
case 0x44120309:
return MGM_3_RM3100_HANDLER_STRING;
case 0x44120313:
return GYRO_3_L3G_HANDLER_STRING;
case 0x44120350:
return RW4_STRING;
case 0x44130001:
return START_TRACKER_STRING;
case 0x44130045:
@ -193,6 +194,8 @@ const char* translateObject(object_id_t object) {
return RAD_SENSOR_STRING;
case 0x44330000:
return PLOC_UPDATER_STRING;
case 0x44330001:
return PLOC_MEMORY_DUMPER_STRING;
case 0x44330015:
return PLOC_MPSOC_HANDLER_STRING;
case 0x44330016:

View File

@ -533,6 +533,9 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) {
DeviceHandlerIF::GET_READ);
#endif
thisSequence->addSlot(objects::PLOC_UPDATER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::PLOC_MEMORY_DUMPER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
#if OBSW_ADD_PLOC_SUPERVISOR == 1
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
@ -832,6 +835,10 @@ ReturnValue_t pst::pollingSequenceTE0720(FixedTimeslotTaskIF *thisSequence) {
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
#endif
thisSequence->addSlot(objects::PLOC_UPDATER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::PLOC_MEMORY_DUMPER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Initialization of TE0720 PST failed" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;

2
tmtc

@ -1 +1 @@
Subproject commit ce5596f5669b8df44df418da6adff123941a395d
Subproject commit 9b176aebfaba51f4d045881a125d42b123f4eeb3