eive-obsw/linux/payload/PlocSupvUartMan.cpp

1168 lines
37 KiB
C++
Raw Permalink Normal View History

2022-08-22 10:35:23 +02:00
#include <etl/crc16_ccitt.h>
2022-11-04 11:08:47 +01:00
#include <fcntl.h> // Contains file controls like O_RDWR
2022-10-25 11:31:06 +02:00
#include <fsfw/filesystem/HasFileSystemIF.h>
2022-11-16 13:26:49 +01:00
#include <fsfw/globalfunctions/arrayprinter.h>
2022-11-04 11:16:22 +01:00
#include <fsfw/tasks/SemaphoreFactory.h>
2023-03-26 16:42:00 +02:00
#include <linux/payload/PlocSupvUartMan.h>
2022-11-04 11:08:47 +01:00
#include <unistd.h>
2022-08-22 10:35:23 +02:00
#include <cmath>
2022-04-06 08:36:34 +02:00
#include <filesystem>
#include <fstream>
#include "OBSWConfig.h"
2022-11-04 12:04:47 +01:00
#include "tas/hdlc.h"
2022-04-06 08:36:34 +02:00
#ifdef XIPHOS_Q7S
2022-09-16 11:53:33 +02:00
#include "bsp_q7s/fs/FilesystemHelper.h"
#include "bsp_q7s/fs/SdCardManager.h"
2022-04-06 08:36:34 +02:00
#endif
#include <fsfw_hal/linux/serial/helper.h>
#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"
2023-11-14 13:25:53 +01:00
#include "tas/crc.h"
2022-04-06 08:36:34 +02:00
2022-11-04 11:08:47 +01:00
using namespace returnvalue;
2022-11-07 11:19:10 +01:00
using namespace supv;
2022-11-04 11:08:47 +01:00
2022-11-15 17:24:38 +01:00
PlocSupvUartManager::PlocSupvUartManager(object_id_t objectId)
2022-11-04 12:45:20 +01:00
: SystemObject(objectId),
recRingBuf(4096, true),
2022-11-08 16:26:30 +01:00
decodedRingBuf(1200 * MAX_STORED_DECODED_PACKETS, true),
2022-11-04 12:45:20 +01:00
ipcRingBuf(1200 * MAX_STORED_DECODED_PACKETS, true) {
2022-08-15 18:53:25 +02:00
resetSpParams();
2022-11-17 17:28:41 +01:00
spParams.maxSize = cmdBuf.size();
2022-11-04 11:16:22 +01:00
semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
semaphore->acquire();
lock = MutexFactory::instance()->createMutex();
2022-11-08 16:26:30 +01:00
ipcLock = MutexFactory::instance()->createMutex();
}
2022-04-06 08:36:34 +02:00
2022-11-15 17:24:38 +01:00
PlocSupvUartManager::~PlocSupvUartManager() = default;
2022-04-06 08:36:34 +02:00
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::initializeInterface(CookieIF* cookie) {
2022-11-15 17:21:12 +01:00
auto* uartCookie = dynamic_cast<SerialCookie*>(cookie);
2022-11-04 11:53:07 +01:00
if (uartCookie == nullptr) {
return FAILED;
}
std::string devname = uartCookie->getDeviceFile();
/* Get file descriptor */
serialPort = open(devname.c_str(), O_RDWR);
if (serialPort < 0) {
2022-11-16 15:25:29 +01:00
sif::warning << "PlocSupvUartManager::initializeInterface: open call failed with error ["
<< errno << ", " << strerror(errno) << std::endl;
2022-11-04 11:53:07 +01:00
return FAILED;
}
// Setting up UART parameters
tty.c_cflag &= ~PARENB; // Clear parity bit
2023-03-22 02:20:14 +01:00
serial::setParity(tty, uartCookie->getParity());
serial::setStopbits(tty, uartCookie->getStopBits());
serial::setBitsPerWord(tty, BitsPerWord::BITS_8);
2022-11-04 11:53:07 +01:00
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control
2023-03-22 02:20:14 +01:00
serial::enableRead(tty);
serial::ignoreCtrlLines(tty);
2022-11-04 11:53:07 +01:00
// Use non-canonical mode and clear echo flag
tty.c_lflag &= ~(ICANON | ECHO);
2022-11-24 11:58:41 +01:00
// Blocking mode, 0.2 seconds timeout
2023-11-14 18:20:52 +01:00
tty.c_cc[VTIME] = 2;
2022-11-04 11:53:07 +01:00
tty.c_cc[VMIN] = 0;
2023-03-22 02:20:14 +01:00
serial::setBaudrate(tty, uartCookie->getBaudrate());
2022-11-04 11:53:07 +01:00
if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
2022-11-16 15:25:29 +01:00
sif::warning << "PlocSupvUartManager::initializeInterface: tcsetattr call failed with error ["
2022-11-04 11:53:07 +01:00
<< errno << ", " << strerror(errno) << std::endl;
}
// Flush received and unread data
tcflush(serialPort, TCIOFLUSH);
return OK;
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::initialize() {
2022-04-06 08:36:34 +02:00
#ifdef XIPHOS_Q7S
sdcMan = SdCardManager::instance();
if (sdcMan == nullptr) {
sif::warning << "PlocSupvHelper::initialize: Invalid SD Card Manager" << std::endl;
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2022-04-06 08:36:34 +02:00
}
#endif
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2022-04-06 08:36:34 +02:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::performOperation(uint8_t operationCode) {
2022-11-04 13:40:42 +01:00
bool putTaskToSleep = false;
2022-04-06 08:36:34 +02:00
while (true) {
2023-11-15 11:31:57 +01:00
{
MutexGuard mg(lock);
state = InternalState::SLEEPING;
}
2022-11-04 11:34:33 +01:00
semaphore->acquire();
2022-12-23 12:14:01 +01:00
putTaskToSleep = false;
2023-02-14 11:10:18 +01:00
#if OBSW_THREAD_TRACING == 1
trace::threadTrace(opCounter, "PLOC SUPV Helper PST");
#endif
2022-11-04 11:34:33 +01:00
while (true) {
2022-11-04 13:40:42 +01:00
if (putTaskToSleep) {
performUartShutdown();
2022-08-22 12:08:39 +02:00
break;
2022-05-23 12:05:42 +02:00
}
2022-11-18 17:25:52 +01:00
handleUartReception();
2023-11-15 11:31:57 +01:00
InternalState currentState;
{
MutexGuard mg(lock);
currentState = state;
}
2022-11-04 11:34:33 +01:00
switch (currentState) {
case InternalState::SLEEPING:
case InternalState::GO_TO_SLEEP: {
2022-11-04 13:40:42 +01:00
putTaskToSleep = true;
2022-04-13 11:56:37 +02:00
break;
2022-04-06 08:36:34 +02:00
}
2022-11-10 11:20:27 +01:00
case InternalState::DEDICATED_REQUEST: {
2022-11-28 16:24:18 +01:00
updateVtime(1);
2022-11-17 17:46:06 +01:00
handleRunningLongerRequest();
2022-11-28 16:24:18 +01:00
updateVtime(2);
2022-11-17 17:46:06 +01:00
MutexGuard mg(lock);
state = InternalState::DEFAULT;
2022-11-04 11:34:33 +01:00
break;
}
case InternalState::DEFAULT: {
2022-11-04 11:34:33 +01:00
break;
}
2022-11-04 13:40:42 +01:00
}
2022-04-06 08:36:34 +02:00
}
}
}
2022-11-18 17:25:52 +01:00
ReturnValue_t PlocSupvUartManager::handleUartReception() {
2022-11-04 13:40:42 +01:00
ReturnValue_t result = OK;
2022-11-18 17:25:52 +01:00
ReturnValue_t status = OK;
2023-11-15 11:31:57 +01:00
ssize_t bytesRead = read(serialPort, reinterpret_cast<void*>(recBuf.data()),
2022-11-04 13:40:42 +01:00
static_cast<unsigned int>(recBuf.size()));
if (bytesRead == 0) {
while (result != NO_PACKET_FOUND) {
result = tryHdlcParsing();
2022-11-18 17:25:52 +01:00
if (result != NO_PACKET_FOUND and result != OK) {
status = result;
}
2022-11-04 13:40:42 +01:00
}
} else if (bytesRead < 0) {
sif::warning << "PlocSupvHelper::performOperation: read call failed with error [" << errno
<< ", " << strerror(errno) << "]" << std::endl;
2022-11-18 17:25:52 +01:00
return FAILED;
2022-11-04 13:40:42 +01:00
} else if (bytesRead >= static_cast<int>(recBuf.size())) {
sif::error << "PlocSupvHelper::performOperation: Receive buffer too small for " << bytesRead
<< " bytes" << std::endl;
2022-11-18 17:25:52 +01:00
return FAILED;
2022-11-04 13:40:42 +01:00
} else if (bytesRead > 0) {
2023-11-15 11:31:57 +01:00
if (DEBUG_MODE) {
2022-11-04 13:40:42 +01:00
sif::info << "Received " << bytesRead << " bytes from the PLOC Supervisor:" << std::endl;
2022-11-16 11:57:29 +01:00
arrayprinter::print(recBuf.data(), bytesRead);
2022-11-04 13:40:42 +01:00
}
recRingBuf.writeData(recBuf.data(), bytesRead);
2022-11-18 17:25:52 +01:00
status = tryHdlcParsing();
2022-11-04 13:40:42 +01:00
}
2022-11-18 17:25:52 +01:00
return status;
2022-11-04 13:40:42 +01:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::startUpdate(std::string file, uint8_t memoryId,
uint32_t startAddress) {
2022-08-24 12:02:16 +02:00
supv::UpdateParams params;
params.file = file;
params.memId = memoryId;
params.startAddr = startAddress;
params.bytesWritten = 0;
params.seqCount = 1;
params.deleteMemory = true;
return performUpdate(params);
2022-08-20 22:52:48 +02:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::performUpdate(const supv::UpdateParams& params) {
2022-11-08 14:52:07 +01:00
lock->lockMutex();
InternalState current = state;
lock->unlockMutex();
if (current != InternalState::DEFAULT) {
return HasActionsIF::IS_BUSY;
}
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
2022-04-06 08:36:34 +02:00
#ifdef XIPHOS_Q7S
2022-08-24 12:02:16 +02:00
result = FilesystemHelper::checkPath(params.file);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-08-24 12:02:16 +02:00
sif::warning << "PlocSupvHelper::startUpdate: File " << params.file << " does not exist"
<< std::endl;
2022-04-06 08:36:34 +02:00
return result;
}
2022-08-24 12:02:16 +02:00
result = FilesystemHelper::fileExists(params.file);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-08-24 12:02:16 +02:00
sif::warning << "PlocSupvHelper::startUpdate: The file " << params.file << " does not exist"
2022-04-10 18:46:39 +02:00
<< 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;
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2022-04-10 18:46:39 +02:00
}
2022-04-06 08:36:34 +02:00
#endif
2022-11-08 14:52:07 +01:00
{
MutexGuard mg(lock);
update.file = params.file;
update.fullFileSize = getFileSize(update.file);
if (params.bytesWritten > update.fullFileSize) {
sif::warning << "Invalid start bytes counter " << params.bytesWritten
<< ", smaller than full file length" << update.fullFileSize << std::endl;
return returnvalue::FAILED;
}
update.length = update.fullFileSize - params.bytesWritten;
update.memoryId = params.memId;
update.startAddress = params.startAddr;
update.progressPercent = 0;
update.bytesWritten = params.bytesWritten;
update.crcShouldBeChecked = true;
update.packetNum = 1;
update.deleteMemory = params.deleteMemory;
update.sequenceCount = params.seqCount;
2022-11-10 11:20:27 +01:00
state = InternalState::DEDICATED_REQUEST;
2022-11-08 14:52:07 +01:00
request = Request::UPDATE;
}
2022-04-06 08:36:34 +02:00
return result;
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::performMemCheck(std::string file, uint8_t memoryId,
uint32_t startAddress) {
2022-11-08 14:52:07 +01:00
lock->lockMutex();
InternalState current = state;
lock->unlockMutex();
if (current != InternalState::DEFAULT) {
return HasActionsIF::IS_BUSY;
}
return performMemCheck(file, memoryId, startAddress, getFileSize(update.file), true);
2022-08-22 13:50:24 +02:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::performMemCheck(std::string file, uint8_t memoryId,
uint32_t startAddress, size_t sizeToCheck,
bool checkCrc) {
2022-11-08 14:52:07 +01:00
{
MutexGuard mg(lock);
update.file = file;
update.fullFileSize = getFileSize(file);
2022-11-10 11:20:27 +01:00
state = InternalState::DEDICATED_REQUEST;
2022-11-08 14:52:07 +01:00
request = Request::CHECK_MEMORY;
update.memoryId = memoryId;
update.startAddress = startAddress;
update.length = sizeToCheck;
update.crcShouldBeChecked = checkCrc;
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2022-08-22 12:08:39 +02:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::initiateUpdateContinuation() {
2022-11-08 14:52:07 +01:00
lock->lockMutex();
InternalState current = state;
lock->unlockMutex();
if (current != InternalState::DEFAULT) {
return HasActionsIF::IS_BUSY;
2022-04-13 11:56:37 +02:00
}
2022-11-08 14:52:07 +01:00
MutexGuard mg(lock);
2022-11-10 11:20:27 +01:00
state = InternalState::DEDICATED_REQUEST;
2022-11-08 14:52:07 +01:00
request = Request::CONTINUE_UPDATE;
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2022-04-13 11:56:37 +02:00
}
2022-11-08 14:52:07 +01:00
// ReturnValue_t PlocSupvHelper::startEventBufferRequest(std::string path) {
2023-08-21 16:01:56 +02:00
// #ifdef XIPHOS_Q7S
2022-11-08 14:52:07 +01:00
// ReturnValue_t result = FilesystemHelper::checkPath(path);
// if (result != returnvalue::OK) {
// return result;
// }
2023-08-21 16:01:56 +02:00
// #endif
2022-11-08 14:52:07 +01:00
// if (not std::filesystem::exists(path)) {
// return PATH_NOT_EXISTS;
// }
// eventBufferReq.path = path;
// request = Request::REQUEST_EVENT_BUFFER;
// //uartComIF->flushUartTxAndRxBuf(comCookie);
// semaphore->release();
// return returnvalue::OK;
// }
2022-11-15 17:24:38 +01:00
void PlocSupvUartManager::stop() {
2022-11-08 14:52:07 +01:00
MutexGuard mg(lock);
2022-11-16 13:26:49 +01:00
if (state == InternalState::SLEEPING or state == InternalState::GO_TO_SLEEP) {
return;
2022-11-15 17:51:22 +01:00
}
2022-11-08 14:52:07 +01:00
state = InternalState::GO_TO_SLEEP;
}
2022-04-06 08:36:34 +02:00
2022-11-15 17:40:19 +01:00
void PlocSupvUartManager::start() {
2022-12-23 12:14:01 +01:00
{
MutexGuard mg(lock);
if (state != InternalState::SLEEPING and state != InternalState::GO_TO_SLEEP) {
return;
}
state = InternalState::DEFAULT;
2022-11-15 17:40:19 +01:00
}
2022-12-23 12:14:01 +01:00
2022-11-15 17:40:19 +01:00
semaphore->release();
}
2022-11-15 17:24:38 +01:00
void PlocSupvUartManager::executeFullCheckMemoryCommand() {
2022-08-22 13:50:24 +02:00
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();
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-08-22 13:50:24 +02:00
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();
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
triggerEvent(SUPV_MEM_CHECK_FAIL, result, 1);
2022-08-22 13:50:24 +02:00
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();
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
triggerEvent(SUPV_MEM_CHECK_FAIL, result, 2);
2022-08-22 13:50:24 +02:00
return;
}
2022-08-22 22:25:22 +02:00
sif::info << "PLOC SUPV Mem Check: Memory Check" << std::endl;
handleCheckMemoryCommand(3);
2022-08-22 13:50:24 +02:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::executeUpdate() {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::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();
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-04-19 13:33:37 +02:00
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();
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-05-23 12:05:42 +02:00
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();
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-04-10 18:46:39 +02:00
return result;
}
2022-08-24 15:16:46 +02:00
if (update.deleteMemory) {
2022-08-24 12:02:16 +02:00
sif::info << "PLOC SUPV Update MPSoC: Erasing Memory" << std::endl;
result = eraseMemory();
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-08-24 12:02:16 +02:00
return result;
}
2022-04-06 08:36:34 +02:00
}
return updateOperation();
2022-05-23 12:05:42 +02:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::continueUpdate() {
2022-05-23 12:05:42 +02:00
ReturnValue_t result = prepareUpdate();
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-05-23 12:05:42 +02:00
return result;
}
return updateOperation();
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::updateOperation() {
sif::info << "PlocSupvHelper::performUpdate: Writing Update Packets" << std::endl;
auto result = writeUpdatePackets();
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-05-23 12:05:42 +02:00
return result;
}
sif::info << "PlocSupvHelper::performUpdate: Memory Check" << std::endl;
return handleCheckMemoryCommand(0);
2022-05-23 12:05:42 +02:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::writeUpdatePackets() {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::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-11-28 11:21:12 +01:00
if (not std::filesystem::exists(update.file)) {
2022-11-28 16:24:18 +01:00
sif::error << "PlocSupvUartManager::writeUpdatePackets: File " << update.file
<< " does not exist" << std::endl;
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
2022-11-28 11:21:12 +01:00
}
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) {
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);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::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 = handlePacketTransmissionNoReply(packet, 5000);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::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;
}
2022-11-10 13:08:17 +01:00
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 */
// TaskFactory::delayTask(1);
2022-04-17 14:52:43 +02:00
}
2022-04-06 08:36:34 +02:00
return result;
}
2022-11-15 17:24:38 +01:00
uint32_t PlocSupvUartManager::buildProgParams1(uint8_t percent, uint16_t seqCount) {
2022-08-22 12:08:39 +02:00
return (static_cast<uint32_t>(percent) << 24) | static_cast<uint32_t>(seqCount);
}
// ReturnValue_t PlocSupvHelper::performEventBufferRequest() {
// using namespace supv;
// ReturnValue_t result = returnvalue::OK;
// resetSpParams();
// RequestLoggingData packet(spParams);
// result = packet.buildPacket(RequestLoggingData::Sa::REQUEST_EVENT_BUFFERS);
// if (result != returnvalue::OK) {
// return result;
// }
// result = sendCommand(packet);
// if (result != returnvalue::OK) {
// return result;
// }
// result = handleAck();
// if (result != returnvalue::OK) {
// return result;
// }
// result =
// handleTmReception(ccsds::HEADER_LEN, tmBuf.data(),
// supv::recv_timeout::UPDATE_STATUS_REPORT);
// if (result != returnvalue::OK) {
// return result;
// }
// ploc::SpTmReader spReader(tmBuf.data(), tmBuf.size());
// bool exeAlreadyReceived = false;
// if (spReader.getApid() == supv::APID_EXE_FAILURE) {
// exeAlreadyReceived = true;
// result = handleRemainingExeReport(spReader);
// } else if (spReader.getApid() == supv::APID_MRAM_DUMP_TM) {
// result = handleEventBufferReception(spReader);
// }
//
// if (not exeAlreadyReceived) {
// result = handleExe();
// if (result != returnvalue::OK) {
// return result;
// }
// }
// return result;
// }
2022-08-24 12:02:16 +02:00
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::selectMemory() {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
2022-08-15 18:53:25 +02:00
resetSpParams();
supv::MPSoCBootSelect packet(spParams);
result = packet.buildPacket(update.memoryId);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
return result;
}
2022-11-24 11:58:41 +01:00
result = handlePacketTransmissionNoReply(packet, 2000);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-05-23 12:05:42 +02:00
return result;
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2022-05-23 12:05:42 +02:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::prepareUpdate() {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
2022-08-15 18:53:25 +02:00
resetSpParams();
2022-11-08 14:26:52 +01:00
supv::NoPayloadPacket packet(spParams, Apid::BOOT_MAN,
2022-11-08 11:08:21 +01:00
static_cast<uint8_t>(tc::BootManId::PREPARE_UPDATE));
result = packet.buildPacket();
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-08-20 12:11:08 +02:00
return result;
}
2022-11-08 16:26:30 +01:00
result = handlePacketTransmissionNoReply(packet, PREPARE_UPDATE_EXECUTION_REPORT);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-04-06 08:36:34 +02:00
return result;
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2022-04-06 08:36:34 +02:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::eraseMemory() {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::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);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
return result;
}
2022-11-08 16:26:30 +01:00
result = handlePacketTransmissionNoReply(eraseMemory, supv::timeout::ERASE_MEMORY);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-04-06 08:36:34 +02:00
return result;
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2022-04-06 08:36:34 +02:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::handlePacketTransmissionNoReply(
supv::TcBase& packet, uint32_t timeoutExecutionReport) {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
2022-11-08 16:26:30 +01:00
result = encodeAndSendPacket(packet.getFullPacket(), packet.getFullPacketLen());
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-04-06 08:36:34 +02:00
return result;
}
2022-11-08 16:26:30 +01:00
Countdown countdown(timeoutExecutionReport);
2022-11-28 16:24:18 +01:00
dur_millis_t currentDelay = 5;
2022-11-08 16:26:30 +01:00
bool ackReceived = false;
2022-11-09 19:47:42 +01:00
bool packetWasHandled = false;
2022-11-08 16:26:30 +01:00
while (true) {
2022-11-18 17:25:52 +01:00
handleUartReception();
2022-11-08 16:26:30 +01:00
if (not decodedQueue.empty()) {
size_t packetLen = 0;
decodedQueue.retrieve(&packetLen);
2022-11-18 17:25:52 +01:00
decodedRingBuf.readData(decodedBuf.data(), packetLen, true);
2023-11-15 11:31:57 +01:00
tmReader.setReadOnlyData(decodedBuf.data(), packetLen);
2022-11-08 16:26:30 +01:00
result = checkReceivedTm();
if (result != returnvalue::OK) {
continue;
}
2022-11-17 13:24:39 +01:00
if (tmReader.getModuleApid() == Apid::TMTC_MAN) {
2022-11-08 16:26:30 +01:00
int retval = 0;
if (not ackReceived) {
2022-11-18 17:25:52 +01:00
retval = handleAckReception(packet, packetLen);
2022-11-08 16:26:30 +01:00
if (retval == 1) {
ackReceived = true;
2022-11-09 19:47:42 +01:00
packetWasHandled = true;
2022-11-08 16:26:30 +01:00
} else if (retval == -1) {
return returnvalue::FAILED;
}
} else {
2022-11-18 17:25:52 +01:00
retval = handleExeAckReception(packet, packetLen);
2022-11-08 16:26:30 +01:00
if (retval == 1) {
break;
} else if (retval == -1) {
return returnvalue::FAILED;
}
}
2022-11-09 19:47:42 +01:00
}
if (not packetWasHandled) {
2022-11-08 16:26:30 +01:00
pushIpcData(decodedBuf.data(), packetLen);
decodedRingBuf.deleteData(packetLen);
}
} else {
2022-11-28 16:24:18 +01:00
TaskFactory::delayTask(currentDelay);
2022-11-28 16:27:33 +01:00
if (currentDelay < 80) {
2022-11-28 16:24:18 +01:00
currentDelay *= 2;
}
2022-11-08 16:26:30 +01:00
}
if (countdown.hasTimedOut()) {
return result::NO_REPLY_TIMEOUT;
}
2022-04-06 08:36:34 +02:00
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2022-04-06 08:36:34 +02:00
}
2022-11-18 17:25:52 +01:00
int PlocSupvUartManager::handleAckReception(supv::TcBase& tc, size_t packetLen) {
uint8_t serviceId = tmReader.getServiceId();
2022-11-08 16:26:30 +01:00
if (serviceId == static_cast<uint8_t>(supv::tm::TmtcId::ACK) or
serviceId == static_cast<uint8_t>(supv::tm::TmtcId::NAK)) {
AcknowledgmentReport ackReport(tmReader);
2023-11-15 11:31:57 +01:00
ReturnValue_t result = ackReport.parse(false);
2022-11-08 16:26:30 +01:00
if (result != returnvalue::OK) {
triggerEvent(ACK_RECEPTION_FAILURE);
2022-11-09 19:47:42 +01:00
return -1;
2022-11-08 16:26:30 +01:00
}
2022-11-17 13:26:03 +01:00
if (ackReport.getRefModuleApid() == tc.getModuleApid() and
2022-11-08 16:26:30 +01:00
ackReport.getRefServiceId() == tc.getServiceId()) {
if (serviceId == static_cast<uint8_t>(supv::tm::TmtcId::ACK)) {
return 1;
} else if (serviceId == static_cast<uint8_t>(supv::tm::TmtcId::NAK)) {
2023-11-15 11:31:57 +01:00
ackReport.printStatusInformationAck();
2022-11-17 13:39:59 +01:00
triggerEvent(
SUPV_ACK_FAILURE_REPORT,
buildApidServiceParam1(ackReport.getRefModuleApid(), ackReport.getRefServiceId()),
ackReport.getStatusCode());
2022-11-08 16:26:30 +01:00
return -1;
}
// Should never happen
return -1;
} else {
pushIpcData(decodedBuf.data(), packetLen);
decodedRingBuf.deleteData(packetLen);
}
2022-04-06 08:36:34 +02:00
}
2022-11-08 16:26:30 +01:00
return 0;
2022-08-22 12:41:08 +02:00
}
2022-11-18 17:25:52 +01:00
int PlocSupvUartManager::handleExeAckReception(supv::TcBase& tc, size_t packetLen) {
uint8_t serviceId = tmReader.getServiceId();
2022-11-08 16:26:30 +01:00
if (serviceId == static_cast<uint8_t>(supv::tm::TmtcId::EXEC_ACK) or
serviceId == static_cast<uint8_t>(supv::tm::TmtcId::EXEC_NAK)) {
ExecutionReport exeReport(tmReader);
2023-11-15 11:31:57 +01:00
ReturnValue_t result = exeReport.parse(false);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-11-08 16:26:30 +01:00
triggerEvent(EXE_RECEPTION_FAILURE);
2022-11-09 19:47:42 +01:00
return -1;
2022-04-06 08:36:34 +02:00
}
2022-11-18 17:25:52 +01:00
if (exeReport.getRefModuleApid() == tc.getModuleApid() and
2022-11-08 16:26:30 +01:00
exeReport.getRefServiceId() == tc.getServiceId()) {
if (serviceId == static_cast<uint8_t>(supv::tm::TmtcId::EXEC_ACK)) {
return 1;
} else if (serviceId == static_cast<uint8_t>(supv::tm::TmtcId::EXEC_NAK)) {
2023-11-15 11:31:57 +01:00
exeReport.printStatusInformationExe();
2022-11-17 13:39:59 +01:00
triggerEvent(
SUPV_EXE_FAILURE_REPORT,
buildApidServiceParam1(exeReport.getRefModuleApid(), exeReport.getRefServiceId()),
exeReport.getStatusCode());
2022-11-08 16:26:30 +01:00
return -1;
}
// Should never happen
return -1;
} else {
pushIpcData(decodedBuf.data(), packetLen);
decodedRingBuf.deleteData(packetLen);
2022-04-06 08:36:34 +02:00
}
}
2022-11-08 16:26:30 +01:00
return 0;
2022-04-06 08:36:34 +02:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::checkReceivedTm() {
2022-11-08 16:26:30 +01:00
ReturnValue_t result = tmReader.checkSize();
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-08-15 18:43:28 +02:00
triggerEvent(SUPV_REPLY_SIZE_MISSMATCH, rememberApid);
return result;
}
2023-11-15 11:31:57 +01:00
if (tmReader.checkCrc() != returnvalue::OK) {
2022-08-15 18:43:28 +02:00
triggerEvent(SUPV_REPLY_CRC_MISSMATCH, rememberApid);
return result;
}
return result;
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::calcImageCrc() {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
if (update.fullFileSize == 0) {
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2022-08-22 13:50:24 +02:00
}
2022-04-10 18:46:39 +02:00
#ifdef XIPHOS_Q7S
result = FilesystemHelper::checkPath(update.file);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-04-10 18:46:39 +02:00
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 PlocSupvUartManager::handleCheckMemoryCommand(uint8_t failStep) {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
2022-11-08 16:26:30 +01:00
resetSpParams();
2022-11-18 17:25:52 +01:00
supv::CheckMemory tcPacket(spParams);
result = tcPacket.buildPacket(update.memoryId, update.startAddress, update.fullFileSize);
2022-11-08 16:26:30 +01:00
if (result != returnvalue::OK) {
return result;
}
2022-11-18 17:25:52 +01:00
result = encodeAndSendPacket(tcPacket.getFullPacket(), tcPacket.getFullPacketLen());
2022-11-08 16:26:30 +01:00
if (result != returnvalue::OK) {
return result;
}
Countdown countdown(timeout::CRC_EXECUTION_TIMEOUT);
bool ackReceived = false;
bool checkReplyReceived = false;
2022-11-09 19:47:42 +01:00
bool packetWasHandled = false;
bool exeReceived = false;
2022-11-08 16:26:30 +01:00
while (true) {
2022-11-18 17:25:52 +01:00
handleUartReception();
2022-11-08 16:26:30 +01:00
if (not decodedQueue.empty()) {
size_t packetLen = 0;
decodedQueue.retrieve(&packetLen);
2022-11-18 17:25:52 +01:00
decodedRingBuf.readData(decodedBuf.data(), packetLen, true);
2023-11-15 11:31:57 +01:00
tmReader.setReadOnlyData(decodedBuf.data(), packetLen);
2022-11-08 16:26:30 +01:00
result = checkReceivedTm();
if (result != returnvalue::OK) {
continue;
}
2022-11-09 19:47:42 +01:00
packetWasHandled = false;
2022-11-17 13:24:39 +01:00
if (tmReader.getModuleApid() == Apid::TMTC_MAN) {
2022-11-08 16:26:30 +01:00
int retval = 0;
if (not ackReceived) {
2022-11-18 17:25:52 +01:00
retval = handleAckReception(tcPacket, packetLen);
2022-11-08 16:26:30 +01:00
if (retval == 1) {
2022-11-09 19:47:42 +01:00
packetWasHandled = true;
2022-11-08 16:26:30 +01:00
ackReceived = true;
} else if (retval == -1) {
return returnvalue::FAILED;
}
2022-11-09 19:47:42 +01:00
} else {
2022-11-18 17:25:52 +01:00
retval = handleExeAckReception(tcPacket, packetLen);
2022-11-08 16:26:30 +01:00
if (retval == 1) {
2022-11-09 19:47:42 +01:00
packetWasHandled = true;
exeReceived = true;
2022-11-08 16:26:30 +01:00
} else if (retval == -1) {
return returnvalue::FAILED;
}
}
2022-11-17 13:24:39 +01:00
} else if (tmReader.getModuleApid() == Apid::MEM_MAN) {
2022-11-08 16:56:42 +01:00
if (ackReceived) {
supv::UpdateStatusReport report(tmReader);
2023-11-15 11:31:57 +01:00
result = report.parse(false);
2022-11-08 16:56:42 +01:00
if (result != returnvalue::OK) {
return result;
}
2022-11-09 19:47:42 +01:00
packetWasHandled = true;
checkReplyReceived = true;
2022-11-08 16:56:42 +01:00
if (update.crcShouldBeChecked) {
result = report.verifyCrc(update.crc);
2022-11-09 19:47:42 +01:00
if (result == returnvalue::OK) {
triggerEvent(SUPV_MEM_CHECK_OK, result);
} else {
2022-11-08 16:56:42 +01:00
sif::warning
2022-11-09 19:47:42 +01:00
2022-11-08 16:56:42 +01:00
<< "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)
<< report.getCrc() << std::dec << std::endl;
triggerEvent(SUPV_MEM_CHECK_FAIL, result, failStep);
2022-11-08 16:56:42 +01:00
}
}
}
2022-11-09 19:47:42 +01:00
}
if (not packetWasHandled) {
2022-11-08 16:26:30 +01:00
pushIpcData(decodedBuf.data(), packetLen);
decodedRingBuf.deleteData(packetLen);
}
} else {
2022-11-24 11:58:41 +01:00
TaskFactory::delayTask(20);
2022-11-08 16:26:30 +01:00
}
2022-11-09 19:47:42 +01:00
if (ackReceived and exeReceived and checkReplyReceived) {
break;
}
2022-11-08 16:26:30 +01:00
if (countdown.hasTimedOut()) {
return result::NO_REPLY_TIMEOUT;
}
}
return returnvalue::OK;
2022-04-10 18:46:39 +02:00
}
2022-11-15 17:24:38 +01:00
uint32_t PlocSupvUartManager::getFileSize(std::string filename) {
2022-04-10 18:46:39 +02:00
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
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::handleEventBufferReception(ploc::SpTmReader& reader) {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
2022-11-08 14:26:52 +01:00
// TODO: Fix
2023-08-21 16:01:56 +02:00
// #ifdef XIPHOS_Q7S
2022-11-08 14:26:52 +01:00
// if (not sdcMan->getActiveSdCard()) {
// return HasFileSystemIF::FILESYSTEM_INACTIVE;
// }
2023-08-21 16:01:56 +02:00
// #endif
2022-11-08 14:26:52 +01:00
// std::string filename = Filenaming::generateAbsoluteFilename(
// eventBufferReq.path, eventBufferReq.filename, timestamping);
// std::ofstream file(filename, std::ios_base::app | std::ios_base::out);
// uint32_t packetsRead = 0;
// size_t requestLen = 0;
// bool firstPacket = true;
// for (packetsRead = 0; packetsRead < NUM_EVENT_BUFFER_PACKETS; packetsRead++) {
// if (terminate) {
// triggerEvent(SUPV_EVENT_BUFFER_REQUEST_TERMINATED, packetsRead - 1);
// file.close();
// return PROCESS_TERMINATED;
// }
// if (packetsRead == NUM_EVENT_BUFFER_PACKETS - 1) {
// requestLen = SIZE_EVENT_BUFFER_LAST_PACKET;
// } else {
// requestLen = SIZE_EVENT_BUFFER_FULL_PACKET;
// }
// if (firstPacket) {
// firstPacket = false;
// requestLen -= 6;
// }
// result = handleTmReception(requestLen);
// if (result != returnvalue::OK) {
// sif::debug << "PlocSupvHelper::handleEventBufferReception: Failed while trying to read
// packet"
// << " " << packetsRead + 1 << std::endl;
// file.close();
// return result;
// }
// ReturnValue_t result = reader.checkCrc();
// if (result != returnvalue::OK) {
// triggerEvent(SUPV_REPLY_CRC_MISSMATCH, rememberApid);
// return result;
// }
// uint16_t apid = reader.getApid();
// if (apid != supv::APID_MRAM_DUMP_TM) {
// sif::warning << "PlocSupvHelper::handleEventBufferReception: Did not expect space packet "
// << "with APID 0x" << std::hex << apid << std::endl;
// file.close();
// return EVENT_BUFFER_REPLY_INVALID_APID;
// }
// // TODO: Fix
// // file.write(reinterpret_cast<const char*>(reader.getPacketData()),
// // reader.getPayloadDataLength());
// }
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
2022-11-15 17:24:38 +01:00
void PlocSupvUartManager::resetSpParams() { spParams.buf = cmdBuf.data(); }
2022-11-04 11:08:47 +01:00
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::sendMessage(CookieIF* cookie, const uint8_t* sendData,
size_t sendLen) {
2022-11-04 12:51:01 +01:00
if (sendData == nullptr or sendLen == 0) {
return FAILED;
}
2022-11-17 15:59:31 +01:00
{
MutexGuard mg(lock);
if (state == InternalState::SLEEPING or state == InternalState::DEDICATED_REQUEST) {
return FAILED;
}
2022-11-04 12:51:01 +01:00
}
2022-11-04 13:40:42 +01:00
return encodeAndSendPacket(sendData, sendLen);
2022-11-04 11:08:47 +01:00
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
2022-11-04 11:08:47 +01:00
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
2022-11-04 11:08:47 +01:00
return returnvalue::OK;
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::handleRunningLongerRequest() {
2022-11-04 13:40:42 +01:00
ReturnValue_t result = OK;
switch (request) {
case Request::UPDATE: {
result = executeUpdate();
if (result == returnvalue::OK) {
triggerEvent(SUPV_UPDATE_SUCCESSFUL, result);
} else if (result == PROCESS_TERMINATED) {
// Event already triggered
} else {
triggerEvent(SUPV_UPDATE_FAILED, result);
}
break;
2022-11-04 13:40:42 +01:00
}
case Request::CHECK_MEMORY: {
executeFullCheckMemoryCommand();
break;
2022-11-04 13:40:42 +01:00
}
case Request::CONTINUE_UPDATE: {
result = continueUpdate();
if (result == returnvalue::OK) {
triggerEvent(SUPV_CONTINUE_UPDATE_SUCCESSFUL, result);
} else if (result == PROCESS_TERMINATED) {
// Event already triggered
} else {
triggerEvent(SUPV_CONTINUE_UPDATE_FAILED, result);
}
break;
2022-11-04 13:40:42 +01:00
}
case Request::REQUEST_EVENT_BUFFER: {
2023-12-12 17:55:09 +01:00
sif::error << "Requesting event buffer is not implemented" << std::endl;
break;
2022-11-04 13:40:42 +01:00
}
case Request::DEFAULT: {
2022-11-04 13:40:42 +01:00
break;
}
}
return false;
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::encodeAndSendPacket(const uint8_t* sendData, size_t sendLen) {
2022-11-04 13:40:42 +01:00
size_t encodedLen = 0;
2022-11-17 11:33:47 +01:00
addHdlcFraming(sendData, sendLen, encodedSendBuf.data(), &encodedLen, encodedSendBuf.size());
2023-11-15 11:31:57 +01:00
if (PRINT_TC) {
2022-11-24 11:58:41 +01:00
sif::debug << "Sending TC" << std::endl;
arrayprinter::print(encodedSendBuf.data(), encodedLen);
}
2022-11-08 16:26:30 +01:00
size_t bytesWritten = write(serialPort, encodedSendBuf.data(), encodedLen);
2022-11-04 13:40:42 +01:00
if (bytesWritten != encodedLen) {
2022-11-17 15:59:31 +01:00
sif::warning
<< "PlocSupvUartManager::sendMessage: Sending ping command to solar experiment failed"
<< std::endl;
2022-11-04 13:40:42 +01:00
return FAILED;
}
return returnvalue::OK;
}
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
size_t* size) {
2022-11-08 16:26:30 +01:00
MutexGuard mg(ipcLock);
2022-11-04 12:51:01 +01:00
if (ipcQueue.empty()) {
*size = 0;
return OK;
}
ipcQueue.retrieve(size);
2023-11-15 11:31:57 +01:00
if (*size > ipcBuffer.size()) {
return FAILED;
}
2022-11-04 12:51:01 +01:00
*buffer = ipcBuffer.data();
ReturnValue_t result = ipcRingBuf.readData(ipcBuffer.data(), *size, true);
if (result != OK) {
2022-11-04 13:40:42 +01:00
sif::warning << "PlocSupvHelper::readReceivedMessage: Reading RingBuffer failed" << std::endl;
2022-11-04 12:51:01 +01:00
}
return OK;
2022-11-04 11:08:47 +01:00
}
2022-11-04 11:53:07 +01:00
2022-11-15 17:24:38 +01:00
ReturnValue_t PlocSupvUartManager::tryHdlcParsing() {
2022-11-04 13:40:42 +01:00
size_t bytesRead = 0;
2022-11-16 13:26:49 +01:00
size_t decodedLen = 0;
ReturnValue_t result = parseRecRingBufForHdlc(bytesRead, decodedLen);
2022-11-04 13:40:42 +01:00
if (result == returnvalue::OK) {
// Packet found, advance read pointer.
2022-11-10 11:20:27 +01:00
if (state == InternalState::DEDICATED_REQUEST) {
2022-11-16 13:26:49 +01:00
decodedRingBuf.writeData(decodedBuf.data(), decodedLen);
decodedQueue.insert(decodedLen);
2022-11-08 16:26:30 +01:00
} else {
MutexGuard mg(ipcLock);
2022-11-16 13:26:49 +01:00
ipcRingBuf.writeData(decodedBuf.data(), decodedLen);
ipcQueue.insert(decodedLen);
2022-11-08 16:26:30 +01:00
}
2022-11-04 13:40:42 +01:00
recRingBuf.deleteData(bytesRead);
} else if (result != NO_PACKET_FOUND) {
2022-11-16 11:57:29 +01:00
sif::warning << "PlocSupvUartMan::performOperation: Possible packet loss" << std::endl;
2022-11-04 13:40:42 +01:00
// Markers found at wrong place
// which might be a hint for a possibly lost packet.
// Maybe trigger event?
recRingBuf.deleteData(bytesRead);
}
return result;
}
2022-11-16 13:26:49 +01:00
ReturnValue_t PlocSupvUartManager::parseRecRingBufForHdlc(size_t& readSize, size_t& decodedLen) {
2022-11-04 11:53:07 +01:00
size_t availableData = recRingBuf.getAvailableReadData();
if (availableData == 0) {
2022-11-04 12:04:47 +01:00
return NO_PACKET_FOUND;
2022-11-04 11:53:07 +01:00
}
2022-11-04 12:04:47 +01:00
if (availableData > encodedBuf.size()) {
return DECODE_BUF_TOO_SMALL;
2022-11-04 11:53:07 +01:00
}
ReturnValue_t result = recRingBuf.readData(encodedBuf.data(), availableData);
2022-11-04 12:04:47 +01:00
if (result != returnvalue::OK) {
return result;
2022-11-04 11:53:07 +01:00
}
bool startMarkerFound = false;
size_t startIdx = 0;
2022-11-04 12:04:47 +01:00
for (size_t idx = 0; idx < availableData; idx++) {
// handle start marker
if (encodedBuf[idx] == HDLC_START_MARKER) {
if (not startMarkerFound) {
startMarkerFound = true;
startIdx = idx;
} else {
readSize = idx;
return POSSIBLE_PACKET_LOSS_CONSECUTIVE_START;
}
}
if (encodedBuf[idx] == HDLC_END_MARKER) {
if (startMarkerFound) {
// Probably a packet, so decode it
2022-11-17 11:33:47 +01:00
int retval = removeHdlcFramingWithCrcCheck(encodedBuf.data() + startIdx, idx + 1 - startIdx,
decodedBuf.data(), &decodedLen);
2022-11-16 13:26:49 +01:00
readSize = idx + 1;
2022-11-16 14:42:18 +01:00
if (retval == -1 or retval == -2) {
triggerEvent(HDLC_FRAME_REMOVAL_ERROR, retval);
} else if (retval == 1) {
triggerEvent(HDLC_CRC_ERROR);
}
2022-11-16 14:43:22 +01:00
if (retval != 0) {
2023-11-15 14:38:09 +01:00
readSize = ++idx;
2022-11-16 14:43:22 +01:00
return HDLC_ERROR;
}
2022-11-04 12:38:30 +01:00
return returnvalue::OK;
} else {
readSize = ++idx;
return POSSIBLE_PACKET_LOSS_CONSECUTIVE_END;
2022-11-04 12:04:47 +01:00
}
}
}
2022-11-04 12:38:30 +01:00
return NO_PACKET_FOUND;
2022-11-04 11:53:07 +01:00
}
2022-11-15 17:24:38 +01:00
void PlocSupvUartManager::pushIpcData(const uint8_t* data, size_t len) {
2022-11-08 16:26:30 +01:00
MutexGuard mg(ipcLock);
ipcRingBuf.writeData(data, len);
ipcQueue.insert(len);
}
2022-11-15 17:24:38 +01:00
uint32_t PlocSupvUartManager::buildApidServiceParam1(uint8_t apid, uint8_t serviceId) {
2022-11-08 16:26:30 +01:00
return (apid << 8) | serviceId;
}
2022-11-15 17:24:38 +01:00
void PlocSupvUartManager::performUartShutdown() {
tcflush(serialPort, TCIOFLUSH);
2022-11-08 14:52:07 +01:00
// Clear ring buffers
recRingBuf.clear();
2022-11-08 16:26:30 +01:00
decodedRingBuf.clear();
while (not decodedQueue.empty()) {
decodedQueue.pop();
}
2023-11-15 11:31:57 +01:00
{
MutexGuard mg0(ipcLock);
ipcRingBuf.clear();
while (not ipcQueue.empty()) {
ipcQueue.pop();
}
2022-11-08 16:26:30 +01:00
}
2023-11-15 11:31:57 +01:00
MutexGuard mg1(lock);
state = InternalState::GO_TO_SLEEP;
}
2022-11-17 11:33:47 +01:00
void PlocSupvUartManager::addHdlcFraming(const uint8_t* src, size_t slen, uint8_t* dst,
size_t* dlen, size_t maxDest) {
size_t tlen = 0;
uint16_t ii;
uint8_t bt;
// calc crc16
uint16_t crc16 = calc_crc16_buff_reflected(src, slen);
dst[tlen++] = 0x7E;
for (ii = 0; ii < slen; ii++) {
bt = *src++;
hdlc_add_byte(bt, dst, &tlen);
}
size_t dummy = 0;
2022-11-28 16:24:18 +01:00
uint8_t crcRaw[2];
2022-11-17 11:33:47 +01:00
// hdlc crc16 is in little endian format
2022-11-28 16:24:18 +01:00
SerializeAdapter::serialize(&crc16, crcRaw, &dummy, maxDest, SerializeIF::Endianness::LITTLE);
hdlc_add_byte(crcRaw[0], dst, &tlen);
hdlc_add_byte(crcRaw[1], dst, &tlen);
2022-11-17 11:33:47 +01:00
dst[tlen++] = 0x7C;
*dlen = tlen;
}
int PlocSupvUartManager::removeHdlcFramingWithCrcCheck(const uint8_t* src, size_t slen,
uint8_t* dst, size_t* dlen) {
uint16_t tlen = 0;
uint16_t ii;
uint8_t bt;
*dlen = 0;
if (slen < 4) return -1;
if ((src[tlen] != 0x7E) && (src[slen - 1] != 0x7C)) return -2;
src++;
for (ii = 1; ii < slen - 1; ii++) {
bt = *src++;
if (bt == 0x7D) {
bt = *src++ ^ 0x20;
ii++;
}
dst[tlen++] = bt;
}
// calc crc16
uint16_t calcCrc = calc_crc16_buff_reflected(dst, tlen - 2);
2022-11-29 23:09:55 +01:00
uint16_t crc = 0;
2022-11-17 11:33:47 +01:00
size_t dummy;
SerializeAdapter::deSerialize(&crc, dst + tlen - 2, &dummy, SerializeIF::Endianness::LITTLE);
if (calcCrc != crc) {
return 1;
}
2022-11-17 11:38:45 +01:00
// if(calc_crc16_buff_reflected(dst, tlen) != 0) {
// return 1;
// }
2022-11-17 11:33:47 +01:00
*dlen = tlen - 2;
return 0;
}
2022-11-21 18:32:23 +01:00
bool PlocSupvUartManager::longerRequestActive() const {
MutexGuard mg(lock);
return state == InternalState::DEDICATED_REQUEST;
}
2022-11-28 16:24:18 +01:00
void PlocSupvUartManager::updateVtime(uint8_t vtime) {
tcgetattr(serialPort, &tty);
tty.c_cc[VTIME] = vtime;
tcsetattr(serialPort, TCSANOW, &tty);
}