eive-obsw/linux/devices/startracker/StrComHandler.cpp

712 lines
24 KiB
C++
Raw Normal View History

2023-03-21 20:35:28 +01:00
#include <fcntl.h>
2022-10-25 11:31:06 +02:00
#include <fsfw/filesystem/HasFileSystemIF.h>
2023-03-21 20:35:28 +01:00
#include <fsfw/tasks/TaskFactory.h>
#include <linux/devices/startracker/StrComHandler.h>
#include <unistd.h>
2022-10-25 11:31:06 +02:00
2021-11-30 16:01:02 +01:00
#include <filesystem>
2022-01-17 15:58:27 +01:00
#include <fstream>
2021-11-30 16:01:02 +01:00
2022-02-05 18:08:54 +01:00
#include "OBSWConfig.h"
2022-09-26 11:39:17 +02:00
#include "eive/definitions.h"
2022-02-23 18:15:34 +01:00
#include "fsfw/timemanager/Countdown.h"
2023-03-21 20:35:28 +01:00
#include "helpers.h"
2022-02-23 18:15:34 +01:00
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
2022-04-30 16:21:59 +02:00
#include "mission/utility/Filenaming.h"
2022-03-01 17:17:15 +01:00
#include "mission/utility/ProgressPrinter.h"
#include "mission/utility/Timestamp.h"
2021-11-30 16:01:02 +01:00
2023-03-21 20:35:28 +01:00
using namespace returnvalue;
StrComHandler::StrComHandler(object_id_t objectId) : SystemObject(objectId) {}
2021-11-30 16:01:02 +01:00
2023-03-21 20:35:28 +01:00
StrComHandler::~StrComHandler() {}
2021-11-30 16:01:02 +01:00
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::initialize() {
2022-02-05 13:19:20 +01:00
#ifdef XIPHOS_Q7S
2022-01-17 15:58:27 +01:00
sdcMan = SdCardManager::instance();
if (sdcMan == nullptr) {
sif::warning << "StrHelper::initialize: Invalid SD Card Manager" << std::endl;
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2022-01-17 15:58:27 +01:00
}
2022-02-05 13:19:20 +01:00
#endif
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-11-30 16:01:02 +01:00
}
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::performOperation(uint8_t operationCode) {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
2022-01-17 15:58:27 +01:00
semaphore.acquire();
while (true) {
switch (internalState) {
case InternalState::IDLE: {
semaphore.acquire();
break;
}
case InternalState::UPLOAD_IMAGE: {
result = performImageUpload();
2022-08-24 17:27:47 +02:00
if (result == returnvalue::OK) {
2022-01-17 15:58:27 +01:00
triggerEvent(IMAGE_UPLOAD_SUCCESSFUL);
} else {
triggerEvent(IMAGE_UPLOAD_FAILED);
2021-12-02 08:05:33 +01:00
}
2022-01-17 15:58:27 +01:00
internalState = InternalState::IDLE;
break;
}
case InternalState::DOWNLOAD_IMAGE: {
result = performImageDownload();
2022-08-24 17:27:47 +02:00
if (result == returnvalue::OK) {
2022-01-17 15:58:27 +01:00
triggerEvent(IMAGE_DOWNLOAD_SUCCESSFUL);
} else {
triggerEvent(IMAGE_DOWNLOAD_FAILED);
2021-12-21 15:46:09 +01:00
}
2022-01-17 15:58:27 +01:00
internalState = InternalState::IDLE;
break;
}
case InternalState::FLASH_READ: {
result = performFlashRead();
2022-08-24 17:27:47 +02:00
if (result == returnvalue::OK) {
2022-01-17 15:58:27 +01:00
triggerEvent(FLASH_READ_SUCCESSFUL);
} else {
triggerEvent(FLASH_READ_FAILED);
2021-12-29 20:33:20 +01:00
}
2022-01-17 15:58:27 +01:00
internalState = InternalState::IDLE;
break;
}
2022-02-01 11:45:22 +01:00
case InternalState::FIRMWARE_UPDATE: {
result = performFirmwareUpdate();
2022-08-24 17:27:47 +02:00
if (result == returnvalue::OK) {
2022-02-01 11:45:22 +01:00
triggerEvent(FIRMWARE_UPDATE_SUCCESSFUL);
} else {
triggerEvent(FIRMWARE_UPDATE_FAILED);
}
internalState = InternalState::IDLE;
break;
}
2022-01-17 15:58:27 +01:00
default:
sif::debug << "StrHelper::performOperation: Invalid state" << std::endl;
break;
2021-11-30 16:01:02 +01:00
}
2022-01-17 15:58:27 +01:00
}
2021-11-30 16:01:02 +01:00
}
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::startImageUpload(std::string fullname) {
2022-02-05 13:19:20 +01:00
#ifdef XIPHOS_Q7S
2022-01-17 15:58:27 +01:00
ReturnValue_t result = checkPath(fullname);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-01-17 15:58:27 +01:00
return result;
}
2022-02-05 13:19:20 +01:00
#endif
2022-01-17 15:58:27 +01:00
uploadImage.uploadFile = fullname;
if (not std::filesystem::exists(fullname)) {
return FILE_NOT_EXISTS;
}
internalState = InternalState::UPLOAD_IMAGE;
2022-01-17 15:58:27 +01:00
semaphore.release();
terminate = false;
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-12-06 19:36:21 +01:00
}
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::startImageDownload(std::string path) {
2022-02-05 13:19:20 +01:00
#ifdef XIPHOS_Q7S
2022-01-17 15:58:27 +01:00
ReturnValue_t result = checkPath(path);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-01-17 15:58:27 +01:00
return result;
}
2022-02-05 13:19:20 +01:00
#endif
2022-01-17 15:58:27 +01:00
if (not std::filesystem::exists(path)) {
return PATH_NOT_EXISTS;
}
downloadImage.path = path;
internalState = InternalState::DOWNLOAD_IMAGE;
terminate = false;
semaphore.release();
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-12-09 15:02:58 +01:00
}
2023-03-21 20:35:28 +01:00
void StrComHandler::stopProcess() { terminate = true; }
2021-12-10 10:07:23 +01:00
2023-03-21 20:35:28 +01:00
void StrComHandler::setDownloadImageName(std::string filename) {
downloadImage.filename = filename;
}
2021-12-11 11:56:47 +01:00
2023-03-21 20:35:28 +01:00
void StrComHandler::setFlashReadFilename(std::string filename) { flashRead.filename = filename; }
2021-12-22 16:06:30 +01:00
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::startFirmwareUpdate(std::string fullname) {
2022-02-05 13:19:20 +01:00
#ifdef XIPHOS_Q7S
2022-01-17 15:58:27 +01:00
ReturnValue_t result = checkPath(fullname);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-01-17 15:58:27 +01:00
return result;
}
2022-02-05 13:19:20 +01:00
#endif
2022-01-17 15:58:27 +01:00
flashWrite.fullname = fullname;
if (not std::filesystem::exists(flashWrite.fullname)) {
return FILE_NOT_EXISTS;
}
2022-02-14 11:28:15 +01:00
flashWrite.firstRegion = static_cast<uint8_t>(startracker::FirmwareRegions::FIRST);
flashWrite.lastRegion = static_cast<uint8_t>(startracker::FirmwareRegions::LAST);
2022-02-01 11:45:22 +01:00
internalState = InternalState::FIRMWARE_UPDATE;
2022-01-17 15:58:27 +01:00
semaphore.release();
terminate = false;
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-12-21 15:46:09 +01:00
}
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::startFlashRead(std::string path, uint8_t startRegion,
uint32_t length) {
2022-02-05 13:19:20 +01:00
#ifdef XIPHOS_Q7S
2022-01-17 15:58:27 +01:00
ReturnValue_t result = checkPath(path);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-01-17 15:58:27 +01:00
return result;
}
2022-02-05 13:19:20 +01:00
#endif
2022-01-17 15:58:27 +01:00
flashRead.path = path;
if (not std::filesystem::exists(flashRead.path)) {
return FILE_NOT_EXISTS;
}
2022-02-25 14:24:51 +01:00
flashRead.startRegion = startRegion;
2022-01-17 15:58:27 +01:00
flashRead.size = length;
internalState = InternalState::FLASH_READ;
semaphore.release();
terminate = false;
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-12-22 16:06:30 +01:00
}
2023-03-21 20:35:28 +01:00
void StrComHandler::disableTimestamping() { timestamping = false; }
2023-03-21 20:35:28 +01:00
void StrComHandler::enableTimestamping() { timestamping = true; }
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::performImageDownload() {
2022-10-25 11:31:06 +02:00
#ifdef XIPHOS_Q7S
if (not sdcMan->getActiveSdCard()) {
return HasFileSystemIF::FILESYSTEM_INACTIVE;
}
#endif
2022-01-17 15:58:27 +01:00
ReturnValue_t result;
2022-03-01 17:17:15 +01:00
#if OBSW_DEBUG_STARTRACKER == 1
ProgressPrinter progressPrinter("Image download", ImageDownload::LAST_POSITION);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
2022-01-17 15:58:27 +01:00
struct DownloadActionRequest downloadReq;
uint32_t size = 0;
uint32_t retries = 0;
2023-03-21 20:35:28 +01:00
const uint8_t* replyFrame;
2022-04-13 11:56:37 +02:00
std::string image = Filenaming::generateAbsoluteFilename(downloadImage.path,
downloadImage.filename, timestamping);
std::ofstream file(image, std::ios_base::out);
2022-01-17 15:58:27 +01:00
if (not std::filesystem::exists(image)) {
return FILE_CREATION_FAILED;
}
downloadReq.position = 0;
while (downloadReq.position < ImageDownload::LAST_POSITION) {
if (terminate) {
2022-02-23 18:15:34 +01:00
file.close();
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2022-01-17 15:58:27 +01:00
}
arc_pack_download_action_req(&downloadReq, commandBuffer, &size);
2023-03-21 20:35:28 +01:00
result = sendAndRead(&replyFrame, size, downloadReq.position);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-01-17 15:58:27 +01:00
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
2023-03-21 20:35:28 +01:00
uart::flushRxBuf(serialPort);
2022-01-17 15:58:27 +01:00
retries++;
continue;
}
file.close();
return result;
2021-12-09 15:02:58 +01:00
}
2023-03-21 20:35:28 +01:00
result = checkActionReply(replyFrame);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-01-17 15:58:27 +01:00
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
2023-03-21 20:35:28 +01:00
uart::flushRxBuf(serialPort);
2022-01-17 15:58:27 +01:00
retries++;
continue;
}
file.close();
return result;
}
2023-03-21 20:35:28 +01:00
result = checkReplyPosition(replyFrame, downloadReq.position);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-01-17 15:58:27 +01:00
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
2023-03-21 20:35:28 +01:00
uart::flushRxBuf(serialPort);
2022-01-17 15:58:27 +01:00
retries++;
continue;
}
file.close();
return result;
}
2023-03-21 20:35:28 +01:00
file.write(reinterpret_cast<const char*>(replyFrame + IMAGE_DATA_OFFSET), CHUNK_SIZE);
2022-02-01 10:45:07 +01:00
#if OBSW_DEBUG_STARTRACKER == 1
2022-03-01 17:17:15 +01:00
progressPrinter.print(downloadReq.position);
2022-02-01 10:45:07 +01:00
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
2022-03-01 17:17:15 +01:00
downloadReq.position++;
2022-01-17 15:58:27 +01:00
retries = 0;
}
file.close();
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-11-30 16:01:02 +01:00
}
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::performImageUpload() {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
2022-01-17 15:58:27 +01:00
uint32_t size = 0;
uint32_t imageSize = 0;
2023-03-21 20:35:28 +01:00
const uint8_t* replyFrame;
2022-01-17 15:58:27 +01:00
struct UploadActionRequest uploadReq;
uploadReq.position = 0;
2022-10-25 11:31:06 +02:00
#ifdef XIPHOS_Q7S
if (not sdcMan->getActiveSdCard()) {
return HasFileSystemIF::FILESYSTEM_INACTIVE;
}
#endif
2022-01-17 15:58:27 +01:00
std::memset(&uploadReq.data, 0, sizeof(uploadReq.data));
if (not std::filesystem::exists(uploadImage.uploadFile)) {
triggerEvent(STR_HELPER_FILE_NOT_EXISTS, static_cast<uint32_t>(internalState));
internalState = InternalState::IDLE;
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2022-01-17 15:58:27 +01:00
}
std::ifstream file(uploadImage.uploadFile, std::ifstream::binary);
2023-03-21 17:37:39 +01:00
if (file.bad()) {
return HasFileSystemIF::GENERIC_FILE_ERROR;
}
2022-01-17 15:58:27 +01:00
// Set position of next character to end of file input stream
file.seekg(0, file.end);
// tellg returns position of character in input stream
imageSize = file.tellg();
2022-03-01 17:17:15 +01:00
#if OBSW_DEBUG_STARTRACKER == 1
ProgressPrinter progressPrinter("Image upload", imageSize);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
2022-01-17 15:58:27 +01:00
while ((uploadReq.position + 1) * SIZE_IMAGE_PART < imageSize) {
if (terminate) {
2022-02-23 18:15:34 +01:00
file.close();
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-12-02 08:05:33 +01:00
}
2021-12-09 15:02:58 +01:00
file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg);
2022-01-17 15:58:27 +01:00
file.read(reinterpret_cast<char*>(uploadReq.data), SIZE_IMAGE_PART);
2021-12-09 15:02:58 +01:00
arc_pack_upload_action_req(&uploadReq, commandBuffer, &size);
2023-03-21 20:35:28 +01:00
result = sendAndRead(&replyFrame, size, uploadReq.position);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-02-23 18:15:34 +01:00
file.close();
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2021-12-06 19:36:21 +01:00
}
2023-03-21 20:35:28 +01:00
result = checkActionReply(replyFrame);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-02-23 18:15:34 +01:00
file.close();
2022-01-17 15:58:27 +01:00
return result;
2021-12-06 19:36:21 +01:00
}
2022-02-01 10:45:07 +01:00
#if OBSW_DEBUG_STARTRACKER == 1
2022-03-01 17:17:15 +01:00
progressPrinter.print((uploadReq.position + 1) * SIZE_IMAGE_PART);
2022-02-01 10:45:07 +01:00
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
2022-01-17 15:58:27 +01:00
uploadReq.position++;
}
std::memset(uploadReq.data, 0, sizeof(uploadReq.data));
uint32_t remainder = imageSize - uploadReq.position * SIZE_IMAGE_PART;
file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg);
file.read(reinterpret_cast<char*>(uploadReq.data), remainder);
file.close();
uploadReq.position++;
arc_pack_upload_action_req(&uploadReq, commandBuffer, &size);
2023-03-21 20:35:28 +01:00
result = sendAndRead(&replyFrame, size, uploadReq.position);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
return returnvalue::FAILED;
2022-01-17 15:58:27 +01:00
}
2023-03-21 20:35:28 +01:00
result = checkActionReply(replyFrame);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-01-17 15:58:27 +01:00
return result;
}
2022-02-01 10:45:07 +01:00
#if OBSW_DEBUG_STARTRACKER == 1
2022-03-01 17:17:15 +01:00
progressPrinter.print((uploadReq.position + 1) * SIZE_IMAGE_PART);
2022-02-01 10:45:07 +01:00
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-12-06 19:36:21 +01:00
}
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::performFirmwareUpdate() {
2022-02-23 18:15:34 +01:00
using namespace startracker;
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
2022-02-23 18:15:34 +01:00
result = unlockAndEraseRegions(static_cast<uint32_t>(startracker::FirmwareRegions::FIRST),
static_cast<uint32_t>(startracker::FirmwareRegions::LAST));
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-02-01 11:45:22 +01:00
return result;
2022-02-23 18:15:34 +01:00
}
result = performFlashWrite();
return result;
2022-02-01 11:45:22 +01:00
}
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::performFlashWrite() {
2022-10-25 11:31:06 +02:00
#ifdef XIPHOS_Q7S
if (not sdcMan->getActiveSdCard()) {
return HasFileSystemIF::FILESYSTEM_INACTIVE;
}
#endif
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
2022-01-17 15:58:27 +01:00
uint32_t size = 0;
2022-02-14 11:28:15 +01:00
uint32_t bytesWritten = 0;
2022-01-17 15:58:27 +01:00
uint32_t fileSize = 0;
2023-03-21 20:35:28 +01:00
const uint8_t* replyFrame;
2022-01-17 15:58:27 +01:00
struct WriteActionRequest req;
if (not std::filesystem::exists(flashWrite.fullname)) {
triggerEvent(STR_HELPER_FILE_NOT_EXISTS, static_cast<uint32_t>(internalState));
internalState = InternalState::IDLE;
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2022-01-17 15:58:27 +01:00
}
std::ifstream file(flashWrite.fullname, std::ifstream::binary);
file.seekg(0, file.end);
fileSize = file.tellg();
2022-02-14 11:28:15 +01:00
if (fileSize > FLASH_REGION_SIZE * (flashWrite.lastRegion - flashWrite.firstRegion)) {
2022-02-23 18:15:34 +01:00
sif::warning << "StrHelper::performFlashWrite: Invalid file" << std::endl;
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2022-02-14 11:28:15 +01:00
}
2022-03-01 17:17:15 +01:00
#if OBSW_DEBUG_STARTRACKER == 1
ProgressPrinter progressPrinter("Flash write", fileSize);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
2022-02-14 11:28:15 +01:00
uint32_t fileChunks = fileSize / CHUNK_SIZE;
bytesWritten = 0;
req.region = flashWrite.firstRegion;
req.length = CHUNK_SIZE;
for (uint32_t idx = 0; idx < fileChunks; idx++) {
2022-01-17 15:58:27 +01:00
if (terminate) {
2022-02-23 18:15:34 +01:00
file.close();
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-12-21 15:46:09 +01:00
}
2022-02-14 11:28:15 +01:00
file.seekg(idx * CHUNK_SIZE, file.beg);
file.read(reinterpret_cast<char*>(req.data), CHUNK_SIZE);
if (bytesWritten + CHUNK_SIZE > FLASH_REGION_SIZE) {
2022-02-23 18:15:34 +01:00
req.region++;
bytesWritten = 0;
2022-02-14 11:28:15 +01:00
}
req.address = bytesWritten;
2021-12-21 15:46:09 +01:00
arc_pack_write_action_req(&req, commandBuffer, &size);
2023-03-21 20:35:28 +01:00
result = sendAndRead(&replyFrame, size, req.address);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-02-23 18:15:34 +01:00
file.close();
2022-02-04 13:06:56 +01:00
return result;
2021-12-21 15:46:09 +01:00
}
2023-03-21 20:35:28 +01:00
result = checkActionReply(replyFrame);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-02-23 18:15:34 +01:00
file.close();
2022-01-17 15:58:27 +01:00
return result;
}
2022-02-14 11:28:15 +01:00
bytesWritten += CHUNK_SIZE;
2022-03-01 17:17:15 +01:00
#if OBSW_DEBUG_STARTRACKER == 1
progressPrinter.print(idx * CHUNK_SIZE);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
2022-01-17 15:58:27 +01:00
}
2022-02-14 11:28:15 +01:00
uint32_t remainingBytes = fileSize - fileChunks * CHUNK_SIZE;
2022-02-23 18:15:34 +01:00
file.seekg((fileChunks - 1) * CHUNK_SIZE, file.beg);
2022-01-17 15:58:27 +01:00
file.read(reinterpret_cast<char*>(req.data), remainingBytes);
file.close();
2022-02-14 11:28:15 +01:00
if (bytesWritten + CHUNK_SIZE > FLASH_REGION_SIZE) {
2022-02-23 18:15:34 +01:00
req.region++;
bytesWritten = 0;
2022-02-14 11:28:15 +01:00
}
req.address = bytesWritten;
req.length = remainingBytes;
2022-03-01 17:17:15 +01:00
bytesWritten += remainingBytes;
2022-01-17 15:58:27 +01:00
arc_pack_write_action_req(&req, commandBuffer, &size);
2023-03-21 20:35:28 +01:00
result = sendAndRead(&replyFrame, size, req.address);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-02-04 13:06:56 +01:00
return result;
2022-01-17 15:58:27 +01:00
}
2023-03-21 20:35:28 +01:00
result = checkActionReply(replyFrame);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-01-17 15:58:27 +01:00
return result;
}
2022-03-01 17:17:15 +01:00
#if OBSW_DEBUG_STARTRACKER == 1
progressPrinter.print(fileSize);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-12-21 15:46:09 +01:00
}
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::performFlashRead() {
2022-10-25 11:31:06 +02:00
#ifdef XIPHOS_Q7S
if (not sdcMan->getActiveSdCard()) {
return HasFileSystemIF::FILESYSTEM_INACTIVE;
}
#endif
2022-01-17 15:58:27 +01:00
ReturnValue_t result;
2022-03-01 17:17:15 +01:00
#if OBSW_DEBUG_STARTRACKER == 1
ProgressPrinter progressPrinter("Flash read", flashRead.size);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
2022-01-17 15:58:27 +01:00
struct ReadActionRequest req;
uint32_t bytesRead = 0;
uint32_t size = 0;
uint32_t retries = 0;
2023-03-21 20:35:28 +01:00
const uint8_t* replyFrame;
2022-01-17 15:58:27 +01:00
Timestamp timestamp;
2022-04-13 11:56:37 +02:00
std::string fullname =
Filenaming::generateAbsoluteFilename(flashRead.path, flashRead.filename, timestamping);
2022-01-17 15:58:27 +01:00
std::ofstream file(fullname, std::ios_base::app | std::ios_base::out);
if (not std::filesystem::exists(fullname)) {
return FILE_CREATION_FAILED;
}
2022-02-25 14:24:51 +01:00
req.region = flashRead.startRegion;
req.address = 0;
2022-01-17 15:58:27 +01:00
while (bytesRead < flashRead.size) {
if (terminate) {
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2022-01-17 15:58:27 +01:00
}
2022-02-14 11:28:15 +01:00
if ((flashRead.size - bytesRead) < CHUNK_SIZE) {
2022-01-17 15:58:27 +01:00
req.length = flashRead.size - bytesRead;
} else {
2022-02-14 11:28:15 +01:00
req.length = CHUNK_SIZE;
2022-01-17 15:58:27 +01:00
}
arc_pack_read_action_req(&req, commandBuffer, &size);
2023-03-21 20:35:28 +01:00
result = sendAndRead(&replyFrame, size, req.address);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-01-17 15:58:27 +01:00
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
2023-03-21 20:35:28 +01:00
uart::flushRxBuf(serialPort);
2022-01-17 15:58:27 +01:00
retries++;
continue;
}
file.close();
return result;
2021-12-22 11:14:27 +01:00
}
2023-03-21 20:35:28 +01:00
result = checkActionReply(replyFrame);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-01-17 15:58:27 +01:00
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
2023-03-21 20:35:28 +01:00
uart::flushRxBuf(serialPort);
2022-01-17 15:58:27 +01:00
retries++;
continue;
}
file.close();
return result;
2021-12-22 11:14:27 +01:00
}
2023-03-21 20:35:28 +01:00
file.write(reinterpret_cast<const char*>(replyFrame + FLASH_READ_DATA_OFFSET), req.length);
2022-01-17 15:58:27 +01:00
bytesRead += req.length;
2022-02-25 14:24:51 +01:00
req.address += req.length;
if (req.address >= FLASH_REGION_SIZE) {
2022-02-27 15:48:42 +01:00
req.address = 0;
req.region++;
2022-02-25 14:24:51 +01:00
}
2022-01-17 15:58:27 +01:00
retries = 0;
2022-02-27 15:46:06 +01:00
#if OBSW_DEBUG_STARTRACKER == 1
2022-03-01 17:17:15 +01:00
progressPrinter.print(bytesRead);
2022-02-27 15:46:06 +01:00
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
2022-01-17 15:58:27 +01:00
}
file.close();
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-12-22 11:14:27 +01:00
}
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::sendAndRead(const uint8_t** replyFrame, size_t size,
uint32_t failParameter, uint32_t delayMs) {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
ReturnValue_t decResult = returnvalue::OK;
2022-01-17 15:58:27 +01:00
size_t receivedDataLen = 0;
size_t bytesLeft = 0;
uint32_t missedReplies = 0;
2023-03-21 18:47:42 +01:00
2023-03-21 20:35:28 +01:00
const uint8_t* sendData;
2023-03-21 18:47:42 +01:00
size_t txFrameLen = 0;
datalinkLayer.encodeFrame(commandBuffer, size, &sendData, txFrameLen);
2023-03-21 20:35:28 +01:00
int writeResult = write(serialPort, sendData, txFrameLen);
if (writeResult < 0) {
2022-01-17 15:58:27 +01:00
sif::warning << "StrHelper::sendAndRead: Failed to send packet" << std::endl;
2023-03-21 20:35:28 +01:00
triggerEvent(STR_HELPER_SENDING_PACKET_FAILED, result, failParameter);
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2022-01-17 15:58:27 +01:00
}
2023-03-21 20:35:28 +01:00
Countdown delay(delayMs);
while (true) {
2022-02-23 18:15:34 +01:00
delay.resetTimer();
while (delay.isBusy()) {
2023-03-21 20:35:28 +01:00
TaskFactory::delayTask(10);
2022-02-23 18:15:34 +01:00
}
2023-03-21 20:35:28 +01:00
// TODO: Read periodically into ring buffer, analyse ring buffer for reply frames periodically.
// result = uartComIF->requestReceiveMessage(comCookie, startracker::MAX_FRAME_SIZE * 2 + 2);
// if (result != returnvalue::OK) {
// sif::warning << "StrHelper::sendAndRead: Failed to request reply" << std::endl;
// triggerEvent(STR_HELPER_REQUESTING_MSG_FAILED, result, parameter);
// return returnvalue::FAILED;
// }
// result = uartComIF->readReceivedMessage(comCookie, &receivedData, &receivedDataLen);
// if (result != returnvalue::OK) {
// sif::warning << "StrHelper::sendAndRead: Failed to read received message" << std::endl;
// triggerEvent(STR_HELPER_READING_REPLY_FAILED, result, parameter);
// return returnvalue::FAILED;
// }
2022-01-17 15:58:27 +01:00
if (receivedDataLen == 0 && missedReplies < MAX_POLLS) {
missedReplies++;
continue;
} else if ((receivedDataLen == 0) && (missedReplies >= MAX_POLLS)) {
2023-03-21 20:35:28 +01:00
triggerEvent(STR_HELPER_NO_REPLY, failParameter);
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2022-01-17 15:58:27 +01:00
} else {
missedReplies = 0;
}
2023-03-21 20:35:28 +01:00
// TODO: Use frame detector function here instead.
// decResult = datalinkLayer.decodeFrame(receivedData, receivedDataLen, &bytesLeft);
2022-01-17 15:58:27 +01:00
if (bytesLeft != 0) {
// This should never happen
sif::warning << "StrHelper::sendAndRead: Bytes left after decoding" << std::endl;
2023-03-21 20:35:28 +01:00
triggerEvent(STR_HELPER_COM_ERROR, result, failParameter);
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2022-01-17 15:58:27 +01:00
}
}
2022-08-24 17:27:47 +02:00
if (decResult != returnvalue::OK) {
2023-03-21 20:35:28 +01:00
triggerEvent(STR_HELPER_DEC_ERROR, decResult, failParameter);
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2022-01-17 15:58:27 +01:00
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-12-06 19:36:21 +01:00
}
2021-12-02 08:05:33 +01:00
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::checkActionReply(const uint8_t* rawFrame) {
uint8_t type = str::getReplyFrameType(rawFrame);
2022-01-17 15:58:27 +01:00
if (type != TMTC_ACTIONREPLY) {
sif::warning << "StrHelper::checkActionReply: Received reply with invalid type ID" << std::endl;
return INVALID_TYPE_ID;
}
2023-03-21 20:35:28 +01:00
uint8_t status = str::getStatusField(rawFrame);
2022-01-17 15:58:27 +01:00
if (status != ArcsecDatalinkLayer::STATUS_OK) {
sif::warning << "StrHelper::checkActionReply: Status failure: "
<< static_cast<unsigned int>(status) << std::endl;
return STATUS_ERROR;
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-11-30 16:01:02 +01:00
}
2021-12-09 15:02:58 +01:00
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::checkReplyPosition(const uint8_t* rawFrame,
uint32_t expectedPosition) {
2022-01-17 15:58:27 +01:00
uint32_t receivedPosition = 0;
2023-03-21 20:35:28 +01:00
std::memcpy(&receivedPosition, rawFrame + POS_OFFSET, sizeof(receivedPosition));
2022-01-17 15:58:27 +01:00
if (receivedPosition != expectedPosition) {
triggerEvent(POSITION_MISMATCH, receivedPosition);
2022-08-24 17:27:47 +02:00
return returnvalue::FAILED;
2022-01-17 15:58:27 +01:00
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-12-09 15:02:58 +01:00
}
2021-12-11 11:56:47 +01:00
2022-02-05 13:19:20 +01:00
#ifdef XIPHOS_Q7S
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::checkPath(std::string name) {
2022-09-26 11:39:17 +02:00
if (name.substr(0, sizeof(config::SD_0_MOUNT_POINT)) == std::string(config::SD_0_MOUNT_POINT)) {
2022-09-27 10:51:07 +02:00
if (!sdcMan->isSdCardUsable(sd::SLOT_0)) {
2022-01-17 15:58:27 +01:00
sif::warning << "StrHelper::checkPath: SD card 0 not mounted" << std::endl;
return SD_NOT_MOUNTED;
}
2022-09-26 11:39:17 +02:00
} else if (name.substr(0, sizeof(config::SD_1_MOUNT_POINT)) ==
std::string(config::SD_1_MOUNT_POINT)) {
2022-09-27 10:51:07 +02:00
if (!sdcMan->isSdCardUsable(sd::SLOT_0)) {
2022-01-17 15:58:27 +01:00
sif::warning << "StrHelper::checkPath: SD card 1 not mounted" << std::endl;
return SD_NOT_MOUNTED;
}
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-12-11 11:56:47 +01:00
}
2022-02-05 13:19:20 +01:00
#endif
2022-02-01 10:45:07 +01:00
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::initializeInterface(CookieIF* cookie) {
if (cookie == nullptr) {
return returnvalue::FAILED;
}
SerialCookie* serCookie = dynamic_cast<SerialCookie*>(cookie);
if (serCookie == nullptr) {
return DeviceCommunicationIF::INVALID_COOKIE_TYPE;
}
// comCookie = serCookie;
std::string devname = serCookie->getDeviceFile();
/* Get file descriptor */
serialPort = open(devname.c_str(), O_RDWR);
if (serialPort < 0) {
sif::warning << "StrComHandler: open call failed with error [" << errno << ", "
<< strerror(errno) << std::endl;
return returnvalue::FAILED;
}
// Setting up UART parameters
tty.c_cflag &= ~PARENB; // Clear parity bit
uart::setStopbits(tty, serCookie->getStopBits());
uart::setBitsPerWord(tty, BitsPerWord::BITS_8);
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control
uart::enableRead(tty);
uart::ignoreCtrlLines(tty);
// Use non-canonical mode and clear echo flag
tty.c_lflag &= ~(ICANON | ECHO);
// Non-blocking mode, use polling
tty.c_cc[VTIME] = 0;
tty.c_cc[VMIN] = 0;
uart::setBaudrate(tty, serCookie->getBaudrate());
if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
sif::warning << "ScexUartReader::initializeInterface: tcsetattr call failed with error ["
<< errno << ", " << strerror(errno) << std::endl;
}
// Flush received and unread data
tcflush(serialPort, TCIOFLUSH);
return returnvalue::OK;
}
ReturnValue_t StrComHandler::sendMessage(CookieIF* cookie, const uint8_t* sendData,
size_t sendLen) {
const uint8_t* txFrame;
size_t frameLen;
datalinkLayer.encodeFrame(sendData, sendLen, &txFrame, frameLen);
size_t bytesWritten = write(serialPort, txFrame, frameLen);
if (bytesWritten != frameLen) {
sif::warning << "ScexUartReader::sendMessage: Sending ping command to solar experiment failed"
<< std::endl;
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t StrComHandler::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
ReturnValue_t StrComHandler::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
return returnvalue::OK;
}
ReturnValue_t StrComHandler::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
return returnvalue::OK;
}
ReturnValue_t StrComHandler::unlockAndEraseRegions(uint32_t from, uint32_t to) {
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
2023-03-21 20:35:28 +01:00
const uint8_t* replyFrame;
2022-03-01 17:17:15 +01:00
#if OBSW_DEBUG_STARTRACKER == 1
ProgressPrinter progressPrinter("Unlock and erase", to - from);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
2022-02-23 18:15:34 +01:00
struct UnlockActionRequest unlockReq;
struct EraseActionRequest eraseReq;
uint32_t size = 0;
2022-03-01 17:17:15 +01:00
for (uint32_t idx = from; idx <= to; idx++) {
2022-02-23 18:15:34 +01:00
unlockReq.region = idx;
unlockReq.code = startracker::region_secrets::secret[idx];
arc_pack_unlock_action_req(&unlockReq, commandBuffer, &size);
2023-03-21 20:35:28 +01:00
sendAndRead(&replyFrame, size, unlockReq.region);
result = checkActionReply(replyFrame);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-02-23 18:15:34 +01:00
sif::warning << "StrHelper::unlockAndEraseRegions: Failed to unlock region with id "
<< static_cast<unsigned int>(unlockReq.region) << std::endl;
return result;
2022-02-04 13:06:56 +01:00
}
2022-02-23 18:15:34 +01:00
eraseReq.region = idx;
arc_pack_erase_action_req(&eraseReq, commandBuffer, &size);
2023-03-21 20:35:28 +01:00
result = sendAndRead(&replyFrame, size, eraseReq.region, FLASH_ERASE_DELAY);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-02-23 18:15:34 +01:00
sif::warning << "StrHelper::unlockAndEraseRegions: Failed to erase region with id "
<< static_cast<unsigned int>(eraseReq.region) << std::endl;
return result;
}
2022-03-01 17:17:15 +01:00
#if OBSW_DEBUG_STARTRACKER == 1
progressPrinter.print(idx - from);
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
2022-02-23 18:15:34 +01:00
}
return result;
2022-02-04 13:06:56 +01:00
}
2023-03-21 20:35:28 +01:00
ReturnValue_t StrComHandler::handleUartReception() {
ssize_t bytesRead = read(serialPort, reinterpret_cast<void*>(recBuf.data()),
static_cast<unsigned int>(recBuf.size()));
if (bytesRead == 0) {
return NO_SERIAL_DATA_READ;
} else if (bytesRead < 0) {
sif::warning << "PlocSupvHelper::performOperation: read call failed with error [" << errno
<< ", " << strerror(errno) << "]" << std::endl;
return FAILED;
} else if (bytesRead >= static_cast<int>(recBuf.size())) {
sif::error << "PlocSupvHelper::performOperation: Receive buffer too small for " << bytesRead
<< " bytes" << std::endl;
return FAILED;
} else if (bytesRead > 0) {
// sif::info << "Received " << bytesRead << " bytes from the PLOC Supervisor:" << std::endl;
// arrayprinter::print(recBuf.data(), bytesRead);
datalinkLayer.feedData(recBuf.data(), bytesRead);
}
return OK;
}