eive-obsw/linux/devices/ploc/PlocSupvHelper.cpp

763 lines
25 KiB
C++
Raw Normal View History

2022-04-06 08:36:34 +02:00
#include "PlocSupvHelper.h"
2022-08-22 10:35:23 +02:00
#include <etl/crc16_ccitt.h>
#include <cmath>
2022-04-06 08:36:34 +02:00
#include <filesystem>
#include <fstream>
#include "OBSWConfig.h"
#ifdef XIPHOS_Q7S
#include "bsp_q7s/memory/FilesystemHelper.h"
2022-04-22 14:16:40 +02:00
#include "bsp_q7s/memory/SdCardManager.h"
2022-04-06 08:36:34 +02:00
#endif
#include "fsfw/tasks/TaskFactory.h"
2022-05-13 18:37:16 +02:00
#include "fsfw/timemanager/Countdown.h"
2022-04-14 07:52:21 +02:00
#include "mission/utility/Filenaming.h"
#include "mission/utility/ProgressPrinter.h"
#include "mission/utility/Timestamp.h"
2022-04-06 08:36:34 +02:00
PlocSupvHelper::PlocSupvHelper(object_id_t objectId) : SystemObject(objectId) {
spParams.maxSize = sizeof(commandBuffer);
2022-08-15 18:53:25 +02:00
resetSpParams();
}
2022-04-06 08:36:34 +02:00
PlocSupvHelper::~PlocSupvHelper() {}
ReturnValue_t PlocSupvHelper::initialize() {
#ifdef XIPHOS_Q7S
sdcMan = SdCardManager::instance();
if (sdcMan == nullptr) {
sif::warning << "PlocSupvHelper::initialize: Invalid SD Card Manager" << std::endl;
return RETURN_FAILED;
}
#endif
return RETURN_OK;
}
ReturnValue_t PlocSupvHelper::performOperation(uint8_t operationCode) {
ReturnValue_t result = RETURN_OK;
semaphore.acquire();
while (true) {
switch (internalState) {
case InternalState::IDLE: {
semaphore.acquire();
break;
}
2022-04-07 11:00:07 +02:00
case InternalState::UPDATE: {
2022-04-06 08:36:34 +02:00
result = performUpdate();
if (result == RETURN_OK) {
2022-04-13 11:56:37 +02:00
triggerEvent(SUPV_UPDATE_SUCCESSFUL, result);
} else if (result == PROCESS_TERMINATED) {
// Event already triggered
2022-04-06 08:36:34 +02:00
} else {
2022-04-13 11:56:37 +02:00
triggerEvent(SUPV_UPDATE_FAILED, result);
}
internalState = InternalState::IDLE;
break;
}
2022-08-22 12:08:39 +02:00
case InternalState::CHECK_MEMORY: {
2022-08-22 13:50:24 +02:00
executeFullCheckMemoryCommand();
2022-08-22 12:08:39 +02:00
internalState = InternalState::IDLE;
break;
}
2022-05-23 12:05:42 +02:00
case InternalState::CONTINUE_UPDATE: {
result = continueUpdate();
if (result == RETURN_OK) {
triggerEvent(SUPV_CONTINUE_UPDATE_SUCCESSFUL, result);
} else if (result == PROCESS_TERMINATED) {
// Event already triggered
} else {
triggerEvent(SUPV_CONTINUE_UPDATE_FAILED, result);
}
internalState = InternalState::IDLE;
break;
}
2022-04-13 11:56:37 +02:00
case InternalState::REQUEST_EVENT_BUFFER: {
result = performEventBufferRequest();
if (result == RETURN_OK) {
triggerEvent(SUPV_EVENT_BUFFER_REQUEST_SUCCESSFUL, result);
} else if (result == PROCESS_TERMINATED) {
// Event already triggered
break;
} else {
2022-04-13 11:56:37 +02:00
triggerEvent(SUPV_EVENT_BUFFER_REQUEST_FAILED, result);
2022-04-06 08:36:34 +02:00
}
internalState = InternalState::IDLE;
break;
}
default:
sif::debug << "PlocSupvHelper::performOperation: Invalid state" << std::endl;
break;
}
}
}
2022-04-10 18:46:39 +02:00
ReturnValue_t PlocSupvHelper::setComIF(UartComIF* uartComIF_) {
if (uartComIF_ == nullptr) {
sif::warning << "PlocSupvHelper::initialize: Provided invalid uart com if" << std::endl;
2022-04-06 08:36:34 +02:00
return RETURN_FAILED;
}
2022-04-10 18:46:39 +02:00
uartComIF = uartComIF_;
2022-04-06 08:36:34 +02:00
return RETURN_OK;
}
void PlocSupvHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
2022-08-20 22:52:48 +02:00
ReturnValue_t PlocSupvHelper::startUpdate(std::string file, uint8_t memoryId,
uint32_t startAddress) {
return performUpdate(file, memoryId, startAddress, 0, 1);
}
ReturnValue_t PlocSupvHelper::performUpdate(std::string file, uint8_t memoryId,
uint32_t startAddress, size_t startBytesWritten,
uint16_t initSeqCount) {
2022-04-06 08:36:34 +02:00
ReturnValue_t result = RETURN_OK;
#ifdef XIPHOS_Q7S
2022-04-07 11:00:07 +02:00
result = FilesystemHelper::checkPath(file);
2022-04-06 08:36:34 +02:00
if (result != RETURN_OK) {
2022-04-10 18:46:39 +02:00
sif::warning << "PlocSupvHelper::startUpdate: File " << file << " does not exist" << std::endl;
2022-04-06 08:36:34 +02:00
return result;
}
result = FilesystemHelper::fileExists(file);
2022-04-10 18:46:39 +02:00
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::startUpdate: The file " << file << " does not exist"
<< std::endl;
return result;
2022-04-10 18:46:39 +02:00
}
#endif
#ifdef TE0720_1CFA
if (not std::filesystem::exists(file)) {
sif::warning << "PlocSupvHelper::startUpdate: The file " << file << " does not exist"
<< std::endl;
return RETURN_FAILED;
}
2022-04-06 08:36:34 +02:00
#endif
2022-04-07 11:00:07 +02:00
update.file = file;
update.fullFileSize = getFileSize(update.file);
if (startBytesWritten > update.fullFileSize) {
sif::warning << "Invalid start bytes counter " << startBytesWritten
<< ", smaller than full file length" << update.fullFileSize << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
update.length = update.fullFileSize - startBytesWritten;
2022-04-07 11:00:07 +02:00
update.memoryId = memoryId;
update.startAddress = startAddress;
update.progressPercent = 0;
update.bytesWritten = startBytesWritten;
2022-08-22 13:52:39 +02:00
update.crcShouldBeChecked = true;
2022-05-23 12:05:42 +02:00
update.packetNum = 1;
update.sequenceCount = initSeqCount;
2022-04-07 11:00:07 +02:00
internalState = InternalState::UPDATE;
2022-04-10 18:46:39 +02:00
uartComIF->flushUartTxAndRxBuf(comCookie);
semaphore.release();
2022-04-06 08:36:34 +02:00
return result;
}
2022-08-22 13:50:24 +02:00
ReturnValue_t PlocSupvHelper::performMemCheck(std::string file, uint8_t memoryId,
uint32_t startAddress) {
update.file = file;
update.fullFileSize = getFileSize(file);
2022-08-22 13:50:24 +02:00
return performMemCheck(memoryId, startAddress, getFileSize(update.file), true);
}
2022-08-22 12:08:39 +02:00
ReturnValue_t PlocSupvHelper::performMemCheck(uint8_t memoryId, uint32_t startAddress,
2022-08-22 13:50:24 +02:00
size_t sizeToCheck, bool checkCrc) {
2022-08-22 12:08:39 +02:00
update.memoryId = memoryId;
update.startAddress = startAddress;
update.length = sizeToCheck;
2022-08-22 13:50:24 +02:00
update.crcShouldBeChecked = checkCrc;
2022-08-22 12:08:39 +02:00
internalState = InternalState::CHECK_MEMORY;
uartComIF->flushUartTxAndRxBuf(comCookie);
semaphore.release();
return HasReturnvaluesIF::RETURN_OK;
}
2022-05-23 12:05:42 +02:00
void PlocSupvHelper::initiateUpdateContinuation() {
internalState = InternalState::CONTINUE_UPDATE;
semaphore.release();
}
2022-04-13 11:56:37 +02:00
ReturnValue_t PlocSupvHelper::startEventbBufferRequest(std::string path) {
#ifdef XIPHOS_Q7S
ReturnValue_t result = FilesystemHelper::checkPath(path);
if (result != RETURN_OK) {
return result;
}
#endif
if (not std::filesystem::exists(path)) {
return PATH_NOT_EXISTS;
}
eventBufferReq.path = path;
internalState = InternalState::REQUEST_EVENT_BUFFER;
uartComIF->flushUartTxAndRxBuf(comCookie);
semaphore.release();
return RETURN_OK;
}
2022-04-06 08:36:34 +02:00
void PlocSupvHelper::stopProcess() { terminate = true; }
2022-08-22 13:50:24 +02:00
void PlocSupvHelper::executeFullCheckMemoryCommand() {
ReturnValue_t result;
if (update.crcShouldBeChecked) {
2022-08-22 22:25:22 +02:00
sif::info << "PLOC SUPV Mem Check: Calculating Image CRC" << std::endl;
2022-08-22 13:50:24 +02:00
result = calcImageCrc();
if (result != RETURN_OK) {
triggerEvent(SUPV_MEM_CHECK_FAIL, result);
return;
}
}
2022-08-22 22:25:22 +02:00
sif::info << "PLOC SUPV Mem Check: Selecting Memory" << std::endl;
2022-08-22 13:50:24 +02:00
result = selectMemory();
if (result != RETURN_OK) {
triggerEvent(SUPV_MEM_CHECK_FAIL, result);
return;
}
2022-08-22 22:25:22 +02:00
sif::info << "PLOC SUPV Mem Check: Preparing Update" << std::endl;
2022-08-22 13:50:24 +02:00
result = prepareUpdate();
if (result != RETURN_OK) {
triggerEvent(SUPV_MEM_CHECK_FAIL, result);
return;
}
2022-08-22 22:25:22 +02:00
sif::info << "PLOC SUPV Mem Check: Memory Check" << std::endl;
2022-08-22 13:50:24 +02:00
result = handleCheckMemoryCommand();
if (result == HasReturnvaluesIF::RETURN_OK) {
triggerEvent(SUPV_MEM_CHECK_OK, result);
} else {
triggerEvent(SUPV_MEM_CHECK_FAIL, result);
}
}
2022-04-06 08:36:34 +02:00
ReturnValue_t PlocSupvHelper::performUpdate() {
ReturnValue_t result = RETURN_OK;
2022-08-22 22:25:22 +02:00
sif::info << "PLOC SUPV Update MPSoC: Calculating Image CRC" << std::endl;
2022-04-19 13:33:37 +02:00
result = calcImageCrc();
if (result != RETURN_OK) {
return result;
}
2022-08-22 22:25:22 +02:00
sif::info << "PLOC SUPV Update MPSoC: Selecting Memory" << std::endl;
2022-05-23 12:05:42 +02:00
result = selectMemory();
if (result != RETURN_OK) {
return result;
}
2022-08-22 22:25:22 +02:00
sif::info << "PLOC SUPV Update MPSoC: Preparing Update" << std::endl;
2022-04-10 18:46:39 +02:00
result = prepareUpdate();
if (result != RETURN_OK) {
return result;
}
2022-08-22 22:25:22 +02:00
sif::info << "PLOC SUPV Update MPSoC: Erasing Memory" << std::endl;
2022-04-06 08:36:34 +02:00
result = eraseMemory();
if (result != RETURN_OK) {
return result;
}
return updateOperation();
2022-05-23 12:05:42 +02:00
}
ReturnValue_t PlocSupvHelper::continueUpdate() {
ReturnValue_t result = prepareUpdate();
if (result != RETURN_OK) {
return result;
}
return updateOperation();
}
ReturnValue_t PlocSupvHelper::updateOperation() {
sif::info << "PlocSupvHelper::performUpdate: Writing Update Packets" << std::endl;
auto result = writeUpdatePackets();
2022-05-23 12:05:42 +02:00
if (result != RETURN_OK) {
return result;
}
sif::info << "PlocSupvHelper::performUpdate: Memory Check" << std::endl;
return handleCheckMemoryCommand();
2022-05-23 12:05:42 +02:00
}
ReturnValue_t PlocSupvHelper::writeUpdatePackets() {
ReturnValue_t result = RETURN_OK;
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
ProgressPrinter progressPrinter("Supervisor update", update.fullFileSize,
ProgressPrinter::HALF_PERCENT);
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
uint8_t tempData[supv::WriteMemory::CHUNK_MAX + 1]{};
2022-04-06 08:36:34 +02:00
std::ifstream file(update.file, std::ifstream::binary);
2022-04-10 18:46:39 +02:00
uint16_t dataLength = 0;
ccsds::SequenceFlags seqFlags;
while (update.bytesWritten < update.fullFileSize) {
2022-04-06 08:36:34 +02:00
if (terminate) {
terminate = false;
2022-05-13 18:37:16 +02:00
triggerEvent(TERMINATED_UPDATE_PROCEDURE);
2022-04-10 18:46:39 +02:00
return PROCESS_TERMINATED;
2022-04-06 08:36:34 +02:00
}
size_t remainingSize = update.fullFileSize - update.bytesWritten;
2022-08-20 22:52:48 +02:00
bool lastSegment = false;
if (remainingSize > supv::WriteMemory::CHUNK_MAX) {
2022-04-10 18:46:39 +02:00
dataLength = supv::WriteMemory::CHUNK_MAX;
2022-04-06 08:36:34 +02:00
} else {
2022-08-20 22:52:48 +02:00
lastSegment = true;
dataLength = static_cast<uint16_t>(remainingSize);
2022-04-06 08:36:34 +02:00
}
if (file.is_open()) {
file.seekg(update.bytesWritten, std::ios::beg);
2022-04-06 08:36:34 +02:00
file.read(reinterpret_cast<char*>(tempData), dataLength);
2022-04-19 13:33:37 +02:00
if (!file) {
sif::warning << "PlocSupvHelper::performUpdate: Read only " << file.gcount() << " of "
<< dataLength << " bytes" << std::endl;
2022-04-19 13:33:37 +02:00
sif::info << "PlocSupvHelper::performUpdate: Failed when trying to read byte "
2022-05-23 12:05:42 +02:00
<< update.bytesWritten << std::endl;
2022-04-19 13:33:37 +02:00
}
2022-04-06 08:36:34 +02:00
} else {
return FILE_CLOSED_ACCIDENTALLY;
}
2022-05-23 12:05:42 +02:00
if (update.bytesWritten == 0) {
seqFlags = ccsds::SequenceFlags::FIRST_SEGMENT;
2022-08-20 22:52:48 +02:00
} else if (lastSegment) {
seqFlags = ccsds::SequenceFlags::LAST_SEGMENT;
2022-04-10 18:46:39 +02:00
} else {
seqFlags = ccsds::SequenceFlags::CONTINUATION;
}
2022-08-15 18:53:25 +02:00
resetSpParams();
float progress = static_cast<float>(update.bytesWritten) / update.fullFileSize;
2022-08-20 22:52:48 +02:00
uint8_t progPercent = std::floor(progress * 100);
if (progPercent > update.progressPercent) {
update.progressPercent = progPercent;
if (progPercent % 5 == 0) {
// Useful to allow restarting the update
2022-08-22 12:08:39 +02:00
triggerEvent(SUPV_UPDATE_PROGRESS, buildProgParams1(progPercent, update.sequenceCount),
update.bytesWritten);
2022-08-20 22:52:48 +02:00
}
}
supv::WriteMemory packet(spParams);
result = packet.buildPacket(seqFlags, update.sequenceCount, update.memoryId,
update.startAddress + update.bytesWritten, dataLength, tempData);
if (result != RETURN_OK) {
2022-08-22 12:08:39 +02:00
triggerEvent(WRITE_MEMORY_FAILED, buildProgParams1(progPercent, update.sequenceCount),
update.bytesWritten);
return result;
2022-04-10 18:46:39 +02:00
}
result = handlePacketTransmission(packet);
2022-04-06 08:36:34 +02:00
if (result != RETURN_OK) {
2022-08-22 12:08:39 +02:00
triggerEvent(WRITE_MEMORY_FAILED, buildProgParams1(progPercent, update.sequenceCount),
update.bytesWritten);
2022-04-06 08:36:34 +02:00
return result;
}
update.sequenceCount++;
2022-05-23 12:05:42 +02:00
update.packetNum += 1;
update.bytesWritten += dataLength;
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
2022-05-23 12:05:42 +02:00
progressPrinter.print(update.bytesWritten);
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
2022-04-17 14:52:43 +02:00
}
2022-04-06 08:36:34 +02:00
return result;
}
2022-08-22 12:08:39 +02:00
uint32_t PlocSupvHelper::buildProgParams1(uint8_t percent, uint16_t seqCount) {
return (static_cast<uint32_t>(percent) << 24) | static_cast<uint32_t>(seqCount);
}
2022-04-13 11:56:37 +02:00
ReturnValue_t PlocSupvHelper::performEventBufferRequest() {
using namespace supv;
2022-04-14 07:52:21 +02:00
ReturnValue_t result = RETURN_OK;
2022-08-15 18:53:25 +02:00
resetSpParams();
RequestLoggingData packet(spParams);
result = packet.buildPacket(RequestLoggingData::Sa::REQUEST_EVENT_BUFFERS);
if (result != RETURN_OK) {
return result;
}
2022-04-13 11:56:37 +02:00
result = sendCommand(packet);
if (result != RETURN_OK) {
return result;
}
result = handleAck();
if (result != RETURN_OK) {
return result;
}
result = handleEventBufferReception();
if (result != RETURN_OK) {
return result;
}
result = handleExe();
if (result != RETURN_OK) {
return result;
}
2022-04-14 07:52:21 +02:00
return result;
2022-04-13 11:56:37 +02:00
}
2022-05-23 12:05:42 +02:00
ReturnValue_t PlocSupvHelper::selectMemory() {
ReturnValue_t result = RETURN_OK;
2022-08-15 18:53:25 +02:00
resetSpParams();
supv::MPSoCBootSelect packet(spParams);
result = packet.buildPacket(update.memoryId);
if (result != RETURN_OK) {
return result;
}
2022-05-23 12:05:42 +02:00
result = handlePacketTransmission(packet);
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
2022-04-10 18:46:39 +02:00
ReturnValue_t PlocSupvHelper::prepareUpdate() {
2022-04-06 08:36:34 +02:00
ReturnValue_t result = RETURN_OK;
2022-08-15 18:53:25 +02:00
resetSpParams();
supv::ApidOnlyPacket packet(spParams, supv::APID_PREPARE_UPDATE);
result = packet.buildPacket();
2022-08-20 12:11:08 +02:00
if (result != RETURN_OK) {
return result;
}
result = handlePacketTransmission(packet, PREPARE_UPDATE_EXECUTION_REPORT);
2022-04-06 08:36:34 +02:00
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
2022-04-10 18:46:39 +02:00
ReturnValue_t PlocSupvHelper::eraseMemory() {
2022-04-06 08:36:34 +02:00
ReturnValue_t result = RETURN_OK;
2022-08-15 18:53:25 +02:00
resetSpParams();
supv::EraseMemory eraseMemory(spParams);
result = eraseMemory.buildPacket(update.memoryId, update.startAddress + update.bytesWritten,
update.length);
if (result != RETURN_OK) {
return result;
}
2022-08-22 12:41:08 +02:00
result = handlePacketTransmission(eraseMemory, supv::recv_timeout::ERASE_MEMORY);
2022-04-06 08:36:34 +02:00
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
2022-08-15 18:34:26 +02:00
ReturnValue_t PlocSupvHelper::handlePacketTransmission(ploc::SpTcBase& packet,
2022-04-19 13:33:37 +02:00
uint32_t timeoutExecutionReport) {
2022-04-06 08:36:34 +02:00
ReturnValue_t result = RETURN_OK;
2022-04-10 18:46:39 +02:00
result = sendCommand(packet);
2022-04-06 08:36:34 +02:00
if (result != RETURN_OK) {
return result;
}
result = handleAck();
if (result != RETURN_OK) {
return result;
}
2022-04-19 13:33:37 +02:00
result = handleExe(timeoutExecutionReport);
2022-04-06 08:36:34 +02:00
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
2022-08-15 18:34:26 +02:00
ReturnValue_t PlocSupvHelper::sendCommand(ploc::SpTcBase& packet) {
2022-04-06 08:36:34 +02:00
ReturnValue_t result = RETURN_OK;
rememberApid = packet.getApid();
result = uartComIF->sendMessage(comCookie, packet.getFullPacket(), packet.getFullPacketLen());
2022-04-06 08:36:34 +02:00
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::sendCommand: Failed to send command" << std::endl;
2022-04-10 18:46:39 +02:00
triggerEvent(SUPV_SENDING_COMMAND_FAILED, result, static_cast<uint32_t>(internalState));
2022-04-06 08:36:34 +02:00
return result;
}
return result;
}
ReturnValue_t PlocSupvHelper::handleAck() {
ReturnValue_t result = RETURN_OK;
2022-08-15 18:34:26 +02:00
result = handleTmReception(supv::SIZE_ACK_REPORT);
2022-04-06 08:36:34 +02:00
if (result != RETURN_OK) {
2022-04-17 14:52:43 +02:00
triggerEvent(ACK_RECEPTION_FAILURE, result, static_cast<uint32_t>(rememberApid));
2022-04-10 18:46:39 +02:00
sif::warning << "PlocSupvHelper::handleAck: Error in reception of acknowledgment report"
<< std::endl;
2022-04-06 08:36:34 +02:00
return result;
}
2022-08-15 18:34:26 +02:00
supv::AcknowledgmentReport ackReport(tmBuf.data(), tmBuf.size());
2022-08-15 18:43:28 +02:00
result = checkReceivedTm(ackReport);
2022-08-15 18:53:25 +02:00
if (result != RETURN_OK) {
2022-08-15 18:34:26 +02:00
return result;
}
result = ackReport.checkApid();
if (result != RETURN_OK) {
if (result == SupvReturnValuesIF::RECEIVED_ACK_FAILURE) {
triggerEvent(SUPV_ACK_FAILURE_REPORT, static_cast<uint32_t>(ackReport.getRefApid()));
} else if (result == SupvReturnValuesIF::INVALID_APID) {
triggerEvent(SUPV_ACK_INVALID_APID, static_cast<uint32_t>(rememberApid));
}
return result;
2022-04-06 08:36:34 +02:00
}
return RETURN_OK;
}
2022-04-19 13:33:37 +02:00
ReturnValue_t PlocSupvHelper::handleExe(uint32_t timeout) {
2022-04-06 08:36:34 +02:00
ReturnValue_t result = RETURN_OK;
2022-08-15 18:34:26 +02:00
2022-08-22 12:08:39 +02:00
result = handleTmReception(supv::SIZE_EXE_REPORT, tmBuf.data(), timeout);
2022-04-06 08:36:34 +02:00
if (result != RETURN_OK) {
2022-04-17 14:52:43 +02:00
triggerEvent(EXE_RECEPTION_FAILURE, result, static_cast<uint32_t>(rememberApid));
2022-04-10 18:46:39 +02:00
sif::warning << "PlocSupvHelper::handleExe: Error in reception of execution report"
<< std::endl;
2022-04-06 08:36:34 +02:00
return result;
}
2022-08-22 12:41:08 +02:00
return exeReportHandling();
}
ReturnValue_t PlocSupvHelper::exeReportHandling() {
2022-08-15 18:34:26 +02:00
supv::ExecutionReport exeReport(tmBuf.data(), tmBuf.size());
2022-08-22 12:41:08 +02:00
ReturnValue_t result = checkReceivedTm(exeReport);
2022-08-15 18:53:25 +02:00
if (result != RETURN_OK) {
2022-08-15 18:34:26 +02:00
return result;
}
result = exeReport.checkApid();
if (result != RETURN_OK) {
if (result == SupvReturnValuesIF::RECEIVED_EXE_FAILURE) {
triggerEvent(SUPV_EXE_FAILURE_REPORT, static_cast<uint32_t>(exeReport.getRefApid()));
} else if (result == SupvReturnValuesIF::INVALID_APID) {
triggerEvent(SUPV_EXE_INVALID_APID, static_cast<uint32_t>(rememberApid));
}
return result;
2022-04-06 08:36:34 +02:00
}
2022-08-22 13:50:24 +02:00
return result;
2022-04-06 08:36:34 +02:00
}
2022-08-22 12:08:39 +02:00
ReturnValue_t PlocSupvHelper::handleTmReception(size_t remainingBytes, uint8_t* readBuf,
uint32_t timeout) {
2022-04-06 08:36:34 +02:00
ReturnValue_t result = RETURN_OK;
size_t readBytes = 0;
size_t currentBytes = 0;
2022-04-19 13:33:37 +02:00
Countdown countdown(timeout);
2022-08-22 12:08:39 +02:00
if (readBuf == nullptr) {
readBuf = tmBuf.data();
}
2022-04-19 13:33:37 +02:00
while (!countdown.hasTimedOut()) {
2022-08-22 12:08:39 +02:00
result = receive(readBuf + readBytes, &currentBytes, remainingBytes);
2022-04-06 08:36:34 +02:00
if (result != RETURN_OK) {
return result;
}
readBytes += currentBytes;
remainingBytes = remainingBytes - currentBytes;
if (remainingBytes == 0) {
break;
}
}
if (remainingBytes != 0) {
sif::warning << "PlocSupvHelper::handleTmReception: Failed to read " << std::dec
2022-08-22 12:08:39 +02:00
<< remainingBytes << " remaining bytes" << std::endl;
2022-04-06 08:36:34 +02:00
return RETURN_FAILED;
}
return result;
}
2022-08-15 18:43:28 +02:00
ReturnValue_t PlocSupvHelper::checkReceivedTm(ploc::SpTmReader& reader) {
ReturnValue_t result = reader.checkSize();
if (result != RETURN_OK) {
triggerEvent(SUPV_REPLY_SIZE_MISSMATCH, rememberApid);
return result;
}
result = reader.checkCrc();
if (result != RETURN_OK) {
triggerEvent(SUPV_REPLY_CRC_MISSMATCH, rememberApid);
return result;
}
return result;
}
2022-04-06 08:36:34 +02:00
ReturnValue_t PlocSupvHelper::receive(uint8_t* data, size_t* readBytes, size_t requestBytes) {
ReturnValue_t result = RETURN_OK;
uint8_t* buffer = nullptr;
result = uartComIF->requestReceiveMessage(comCookie, requestBytes);
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::receive: Failed to request reply" << std::endl;
2022-04-10 18:46:39 +02:00
triggerEvent(SUPV_HELPER_REQUESTING_REPLY_FAILED, result,
2022-04-06 08:36:34 +02:00
static_cast<uint32_t>(static_cast<uint32_t>(internalState)));
return RETURN_FAILED;
}
result = uartComIF->readReceivedMessage(comCookie, &buffer, readBytes);
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::receive: Failed to read received message" << std::endl;
2022-04-10 18:46:39 +02:00
triggerEvent(SUPV_HELPER_READING_REPLY_FAILED, result, static_cast<uint32_t>(internalState));
2022-04-06 08:36:34 +02:00
return RETURN_FAILED;
}
if (*readBytes > 0) {
std::memcpy(data, buffer, *readBytes);
2022-05-13 18:37:16 +02:00
} else {
TaskFactory::delayTask(40);
}
2022-04-06 08:36:34 +02:00
return result;
}
2022-04-10 18:46:39 +02:00
ReturnValue_t PlocSupvHelper::calcImageCrc() {
ReturnValue_t result = RETURN_OK;
if (update.fullFileSize == 0) {
2022-08-22 13:50:24 +02:00
return HasReturnvaluesIF::RETURN_FAILED;
}
2022-04-10 18:46:39 +02:00
#ifdef XIPHOS_Q7S
result = FilesystemHelper::checkPath(update.file);
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::calcImageCrc: File " << update.file << " does not exist"
<< std::endl;
return result;
}
2022-08-22 13:50:24 +02:00
#endif
auto crc16Calcer = etl::crc16_ccitt();
2022-04-10 18:46:39 +02:00
std::ifstream file(update.file, std::ifstream::binary);
std::array<uint8_t, 1025> crcBuf{};
2022-04-19 13:33:37 +02:00
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
ProgressPrinter progress("Supervisor update crc calculation", update.fullFileSize,
ProgressPrinter::ONE_PERCENT);
2022-04-19 13:33:37 +02:00
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
uint32_t byteCount = 0;
size_t bytesToRead = 1024;
while (byteCount < update.fullFileSize) {
size_t remLen = update.fullFileSize - byteCount;
2022-08-22 10:35:23 +02:00
if (remLen < 1024) {
bytesToRead = remLen;
} else {
bytesToRead = 1024;
2022-08-22 10:35:23 +02:00
}
2022-04-10 18:46:39 +02:00
file.seekg(byteCount, file.beg);
2022-08-22 10:35:23 +02:00
file.read(reinterpret_cast<char*>(crcBuf.data()), bytesToRead);
crc16Calcer.add(crcBuf.begin(), crcBuf.begin() + bytesToRead);
2022-04-19 13:33:37 +02:00
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
progress.print(byteCount);
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
2022-08-22 10:35:23 +02:00
byteCount += bytesToRead;
2022-04-10 18:46:39 +02:00
}
2022-04-19 13:33:37 +02:00
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
progress.print(byteCount);
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
2022-08-22 10:35:23 +02:00
update.crc = crc16Calcer.value();
2022-04-10 18:46:39 +02:00
return result;
}
ReturnValue_t PlocSupvHelper::handleCheckMemoryCommand() {
ReturnValue_t result = RETURN_OK;
2022-08-15 18:53:25 +02:00
resetSpParams();
2022-08-22 12:08:39 +02:00
// Will hold status report for later processing
std::array<uint8_t, 32> statusReportBuf{};
2022-08-22 13:50:24 +02:00
supv::UpdateStatusReport updateStatusReport(tmBuf.data(), tmBuf.size());
2022-04-10 18:46:39 +02:00
// Verification of update write procedure
supv::CheckMemory packet(spParams);
result = packet.buildPacket(update.memoryId, update.startAddress, update.fullFileSize);
if (result != RETURN_OK) {
return result;
}
2022-04-10 18:46:39 +02:00
result = sendCommand(packet);
if (result != RETURN_OK) {
return result;
}
result = handleAck();
if (result != RETURN_OK) {
return result;
}
2022-08-21 01:38:45 +02:00
2022-08-22 12:08:39 +02:00
result =
2022-08-22 12:41:08 +02:00
handleTmReception(ccsds::HEADER_LEN, tmBuf.data(), supv::recv_timeout::UPDATE_STATUS_REPORT);
SpacePacketReader spReader(tmBuf.data(), tmBuf.size());
if (spReader.getApid() == supv::APID_EXE_FAILURE) {
size_t remBytes = spReader.getPacketDataLen() + 1;
result = handleTmReception(remBytes, tmBuf.data() + ccsds::HEADER_LEN);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Reading exe failure report failed" << std::endl;
}
2022-08-22 13:50:24 +02:00
result = exeReportHandling();
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Handling exe report failed" << std::endl;
}
2022-08-22 12:41:08 +02:00
} else if (spReader.getApid() == supv::APID_UPDATE_STATUS_REPORT) {
size_t remBytes = spReader.getPacketDataLen() + 1;
result = handleTmReception(remBytes, tmBuf.data() + ccsds::HEADER_LEN);
if (result != RETURN_OK) {
sif::warning
<< "PlocSupvHelper::handleCheckMemoryCommand: Failed to receive update status report"
<< std::endl;
return result;
}
result = updateStatusReport.checkCrc();
if (result != RETURN_OK) {
2022-08-22 13:50:24 +02:00
sif::warning << "PlocSupvHelper::handleCheckMemoryCommand: CRC check failed" << std::endl;
2022-08-22 12:41:08 +02:00
return result;
}
2022-08-22 13:50:24 +02:00
// Copy into other buffer because data will be overwritten when reading execution report
std::memcpy(statusReportBuf.data(), tmBuf.data(), updateStatusReport.getNominalSize());
2022-04-10 18:46:39 +02:00
}
2022-08-21 01:38:45 +02:00
result = handleExe(CRC_EXECUTION_TIMEOUT);
2022-04-10 18:46:39 +02:00
if (result != RETURN_OK) {
return result;
}
2022-08-22 12:08:39 +02:00
2022-08-21 01:38:45 +02:00
// Now process the status report
2022-08-22 13:50:24 +02:00
updateStatusReport.setData(statusReportBuf.data(), statusReportBuf.size());
2022-08-22 12:08:39 +02:00
result = updateStatusReport.parseDataField();
2022-04-10 18:46:39 +02:00
if (result != RETURN_OK) {
return result;
}
2022-08-22 13:50:24 +02:00
if (update.crcShouldBeChecked) {
result = updateStatusReport.verifycrc(update.crc);
if (result != RETURN_OK) {
sif::warning << "PlocSupvHelper::handleCheckMemoryCommand: CRC failure. Expected CRC 0x"
<< std::setfill('0') << std::hex << std::setw(4)
<< static_cast<uint16_t>(update.crc) << " but received CRC 0x" << std::setw(4)
<< updateStatusReport.getCrc() << std::dec << std::endl;
return result;
}
2022-04-10 18:46:39 +02:00
}
return result;
}
uint32_t PlocSupvHelper::getFileSize(std::string filename) {
std::ifstream file(filename, std::ifstream::binary);
file.seekg(0, file.end);
uint32_t size = file.tellg();
file.close();
return size;
2022-04-10 18:46:39 +02:00
}
2022-04-13 11:56:37 +02:00
ReturnValue_t PlocSupvHelper::handleEventBufferReception() {
2022-04-14 07:52:21 +02:00
ReturnValue_t result = RETURN_OK;
std::string filename = Filenaming::generateAbsoluteFilename(
eventBufferReq.path, eventBufferReq.filename, timestamping);
2022-04-13 11:56:37 +02:00
std::ofstream file(filename, std::ios_base::app | std::ios_base::out);
uint32_t packetsRead = 0;
2022-04-14 07:52:21 +02:00
size_t requestLen = 0;
2022-08-15 18:34:26 +02:00
ploc::SpTmReader tmReader(tmBuf.data(), tmBuf.size());
2022-04-14 07:52:21 +02:00
for (packetsRead = 0; packetsRead < NUM_EVENT_BUFFER_PACKETS; packetsRead++) {
2022-04-13 11:56:37 +02:00
if (terminate) {
triggerEvent(SUPV_EVENT_BUFFER_REQUEST_TERMINATED, packetsRead - 1);
file.close();
return PROCESS_TERMINATED;
}
2022-04-14 07:52:21 +02:00
if (packetsRead == NUM_EVENT_BUFFER_PACKETS - 1) {
requestLen = SIZE_EVENT_BUFFER_LAST_PACKET;
} else {
requestLen = SIZE_EVENT_BUFFER_FULL_PACKET;
}
2022-08-15 18:34:26 +02:00
result = handleTmReception(requestLen);
2022-04-13 11:56:37 +02:00
if (result != RETURN_OK) {
2022-04-14 07:52:21 +02:00
sif::debug << "PlocSupvHelper::handleEventBufferReception: Failed while trying to read packet"
<< " " << packetsRead + 1 << std::endl;
2022-04-14 07:52:21 +02:00
file.close();
2022-04-13 11:56:37 +02:00
return result;
}
2022-08-15 18:34:26 +02:00
ReturnValue_t result = tmReader.checkCrc();
2022-08-15 18:53:25 +02:00
if (result != RETURN_OK) {
2022-08-15 18:34:26 +02:00
triggerEvent(SUPV_REPLY_CRC_MISSMATCH, rememberApid);
return result;
}
uint16_t apid = tmReader.getApid();
2022-04-13 11:56:37 +02:00
if (apid != supv::APID_MRAM_DUMP_TM) {
sif::warning << "PlocSupvHelper::handleEventBufferReception: Did not expect space packet "
2022-04-14 07:52:21 +02:00
<< "with APID 0x" << std::hex << apid << std::endl;
file.close();
return EVENT_BUFFER_REPLY_INVALID_APID;
2022-04-13 11:56:37 +02:00
}
2022-08-15 18:34:26 +02:00
file.write(reinterpret_cast<const char*>(tmReader.getPacketData()),
tmReader.getPayloadDataLength());
2022-04-13 11:56:37 +02:00
}
2022-04-14 07:52:21 +02:00
return result;
2022-04-13 11:56:37 +02:00
}
2022-08-15 18:53:25 +02:00
void PlocSupvHelper::resetSpParams() { spParams.buf = commandBuffer; }