diff --git a/bsp_q7s/core/InitMission.cpp b/bsp_q7s/core/InitMission.cpp index 803339a2..7977deed 100644 --- a/bsp_q7s/core/InitMission.cpp +++ b/bsp_q7s/core/InitMission.cpp @@ -127,12 +127,15 @@ void initmission::initTasks() { initmission::printAddObjectError("FILE_SYSTEM_TASK", objects::FILE_SYSTEM_HANDLER); } +#if OBSW_ADD_STAR_TRACKER == 1 PeriodicTaskIF* strImgLoaderTask = factory->createPeriodicTask( "FILE_SYSTEM_TASK", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); result = strImgLoaderTask->addComponent(objects::STR_HELPER); if(result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("FILE_SYSTEM_TASK", objects::STR_HELPER); } +#endif /* OBSW_ADD_STAR_TRACKER == 1 */ + #endif /* BOARD_TE0720 */ #if OBSW_TEST_CCSDS_BRIDGE == 1 @@ -194,7 +197,9 @@ void initmission::initTasks() { #if BOARD_TE0720 == 0 fsTask->startTask(); +#if OBSW_ADD_STAR_TRACKER == 1 strImgLoaderTask->startTask(); +#endif /* OBSW_ADD_STAR_TRACKER == 1 */ #endif sif::info << "Tasks started.." << std::endl; diff --git a/bsp_q7s/devices/startracker/StarTrackerDefinitions.h b/bsp_q7s/devices/startracker/StarTrackerDefinitions.h index 22214cb0..a66b16e7 100644 --- a/bsp_q7s/devices/startracker/StarTrackerDefinitions.h +++ b/bsp_q7s/devices/startracker/StarTrackerDefinitions.h @@ -202,6 +202,7 @@ static const DeviceCommandId_t STOP_IMAGE_LOADER = 55; static const DeviceCommandId_t RESET_ERROR = 56; static const DeviceCommandId_t CHANGE_DOWNLOAD_FILE = 57; static const DeviceCommandId_t SET_JSON_FILE_NAME = 58; +static const DeviceCommandId_t SET_READ_FILENAME = 59; static const DeviceCommandId_t NONE = 0xFFFFFFFF; static const uint32_t VERSION_SET_ID = REQ_VERSION; diff --git a/bsp_q7s/devices/startracker/StarTrackerHandler.cpp b/bsp_q7s/devices/startracker/StarTrackerHandler.cpp index bb9018be..d55fb17a 100644 --- a/bsp_q7s/devices/startracker/StarTrackerHandler.cpp +++ b/bsp_q7s/devices/startracker/StarTrackerHandler.cpp @@ -145,6 +145,18 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu strHelperExecuting = true; return EXECUTION_FINISHED; } + case(StarTracker::READ): { + result = DeviceHandlerBase::acceptExternalDeviceCommands(); + if (result != RETURN_OK) { + return result; + } + result = executeReadCommand(data, size); + if (result != RETURN_OK) { + return result; + } + strHelperExecuting = true; + return EXECUTION_FINISHED; + } case(StarTracker::CHANGE_DOWNLOAD_FILE): { if (size > MAX_FILE_NAME) { return FILENAME_TOO_LONG; @@ -153,6 +165,14 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu std::string(reinterpret_cast(data), size)); return EXECUTION_FINISHED; } + case(StarTracker::SET_READ_FILENAME): { + if (size > MAX_FILE_NAME) { + return FILENAME_TOO_LONG; + } + strHelper->setDownloadImageName( + std::string(reinterpret_cast(data), size)); + return EXECUTION_FINISHED; + } default: break; } @@ -396,6 +416,10 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi result = prepareParamCommand(commandData, commandDataLen, tracking); return result; } + case (StarTracker::UNLOCK): { + result = prepareUnlockCommand(commandData, commandDataLen); + return result; + } default: return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; } @@ -454,6 +478,8 @@ void StarTrackerHandler::fillCommandAndReplyMap() { StarTracker::MAX_FRAME_SIZE * 2 + 2); this->insertInCommandAndReplyMap(StarTracker::RESET_ERROR, 3, nullptr, StarTracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(StarTracker::UNLOCK, 3, nullptr, + StarTracker::MAX_FRAME_SIZE * 2 + 2); } ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t *start, size_t remainingSize, @@ -522,15 +548,10 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id, con result = handlePingReply(); break; } - case (StarTracker::BOOT): { - result = handleActionReply(); - break; - } - case (StarTracker::RESET_ERROR): { - result = handleActionReply(); - break; - } - case (StarTracker::TAKE_IMAGE): { + case (StarTracker::BOOT): + case (StarTracker::TAKE_IMAGE): + case (StarTracker::RESET_ERROR): + case (StarTracker::UNLOCK): { result = handleActionReply(); break; } @@ -809,6 +830,10 @@ ReturnValue_t StarTrackerHandler::scanForActionReply(DeviceCommandId_t *foundId) *foundId = StarTracker::RESET_ERROR; break; } + case (StarTracker::ID::UNLOCK): { + *foundId = StarTracker::UNLOCK; + break; + } default: sif::warning << "StarTrackerHandler::scanForParameterReply: Unknown parameter reply id" << std::endl; @@ -966,6 +991,49 @@ ReturnValue_t StarTrackerHandler::executeWriteCommand(const uint8_t* commandData return result; } +ReturnValue_t StarTrackerHandler::executeReadCommand(const uint8_t* commandData, + size_t commandDataLen) { + ReturnValue_t result = RETURN_OK; + if (commandDataLen < ReadCmd::MIN_LENGTH) { + sif::warning << "StarTrackerHandler::executeReadCommand: Command too short" << std::endl; + return COMMAND_TOO_SHORT; + } + uint8_t region = *(commandData); + uint32_t address; + size_t size = sizeof(address); + const uint8_t* addressPtr = commandData + ReadCmd::ADDRESS_OFFSET; + result = SerializeAdapter::deSerialize(&address, addressPtr, &size, + SerializeIF::Endianness::LITTLE); + if (result != RETURN_OK) { + sif::debug << "StarTrackerHandler::executeReadCommand: Deserialization of address failed" + << std::endl; + return result; + } + uint16_t length; + size = sizeof(length); + const uint8_t* lengthPtr = commandData + ReadCmd::LENGTH_OFFSET; + result = SerializeAdapter::deSerialize(&address, lengthPtr, &size, + SerializeIF::Endianness::LITTLE); + if (result != RETURN_OK) { + sif::debug << "StarTrackerHandler::executeReadCommand: Deserialization of length failed" + << std::endl; + return result; + } + if (commandDataLen - sizeof(address) - sizeof(region) - sizeof(length) > MAX_PATH_SIZE) { + sif::warning << "StarTrackerHandler::executeReadCommand: Received command with invalid" + << " path and filename" << std::endl; + return FILE_PATH_TOO_LONG; + } + const uint8_t* filePtr = commandData + ReadCmd::FILE_OFFSET; + std::string fullname = std::string(reinterpret_cast(filePtr), + commandDataLen - sizeof(address) - sizeof(region) - sizeof(length)); + result = strHelper->startFlashRead(fullname, region, address, length); + if (result != RETURN_OK) { + return result; + } + return result; +} + void StarTrackerHandler::prepareBootCommand() { uint32_t length = 0; struct BootActionRequest bootRequest = {BOOT_REGION_ID}; @@ -975,6 +1043,25 @@ void StarTrackerHandler::prepareBootCommand() { rawPacketLen = dataLinkLayer.getEncodedLength(); } +ReturnValue_t StarTrackerHandler::prepareUnlockCommand(const uint8_t* commandData, size_t commandDataLen) { + ReturnValue_t result = RETURN_OK; + uint32_t length = 0; + struct UnlockActionRequest req; + req.region = *commandData; + size_t size = sizeof(req.code); + const uint8_t* codePtr = commandData + UnlockCmd::CODE_OFFSET; + result = SerializeAdapter::deSerialize(&req.code, &codePtr, &size, + SerializeIF::Endianness::BIG); + if (result != RETURN_OK) { + return result; + } + arc_pack_unlock_action_req(&req, commandBuffer, &length); + dataLinkLayer.encodeFrame(commandBuffer, length); + rawPacket = dataLinkLayer.getEncodedFrame(); + rawPacketLen = dataLinkLayer.getEncodedLength(); + return result; +} + void StarTrackerHandler::prepareTimeRequest() { uint32_t length = 0; arc_tm_pack_time_req(commandBuffer, &length); diff --git a/bsp_q7s/devices/startracker/StarTrackerHandler.h b/bsp_q7s/devices/startracker/StarTrackerHandler.h index 7d22592e..791ead0f 100644 --- a/bsp_q7s/devices/startracker/StarTrackerHandler.h +++ b/bsp_q7s/devices/startracker/StarTrackerHandler.h @@ -147,6 +147,20 @@ private: static const size_t MIN_LENGTH = 7; }; + class ReadCmd { + public: + static const uint8_t ADDRESS_OFFSET = 1; + static const uint8_t LENGTH_OFFSET = 5; + static const uint8_t FILE_OFFSET = 7; + // Minimum length of a read command (region, address, length and filename) + static const size_t MIN_LENGTH = 9; + }; + + class UnlockCmd { + public: + static const uint8_t CODE_OFFSET = 1; + }; + MessageQueueIF* eventQueue = nullptr; ArcsecDatalinkLayer dataLinkLayer; @@ -245,12 +259,28 @@ private: */ ReturnValue_t executeWriteCommand(const uint8_t* commandData, size_t commandDataLen); + /** + * @brief Extracts information for flash-read-command from TC data and starts execution of + * flash-read-procedure + * + * @param commandData Pointer to received command data + * @param commandDataLen Size of received command data + * + * @return RETURN_OK if start of execution was successful, otherwise error return value + */ + ReturnValue_t executeReadCommand(const uint8_t* commandData, size_t commandDataLen); + /** * @brief Fills command buffer with data to boot image (works only when star tracker is * in bootloader mode). */ void prepareBootCommand(); + /** + * @brief Fills command buffer with command to unlock flash region + */ + ReturnValue_t prepareUnlockCommand(const uint8_t* commandData, size_t commandDataLen); + /** * @brief Fills the command buffer with the command to take an image. */ diff --git a/bsp_q7s/devices/startracker/StrHelper.cpp b/bsp_q7s/devices/startracker/StrHelper.cpp index bc4e034f..4a6797f1 100644 --- a/bsp_q7s/devices/startracker/StrHelper.cpp +++ b/bsp_q7s/devices/startracker/StrHelper.cpp @@ -63,6 +63,17 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) { internalState = InternalState::IDLE; break; } + case InternalState::FLASH_READ: { + result = performFlashRead(); + if (result == RETURN_OK){ + triggerEvent(FLASH_READ_SUCCESSFUL); + } + else { + triggerEvent(FLASH_READ_FAILED); + } + internalState = InternalState::IDLE; + break; + } default: sif::debug << "StrHelper::performOperation: Invalid state" << std::endl; break; @@ -121,8 +132,12 @@ void StrHelper::setDownloadImageName(std::string image) { downloadImage = image; } +void StrHelper::setFlashReadFilename(std::string filename) { + flashReadFile = filename; +} + ReturnValue_t StrHelper::startFlashWrite(std::string flashWriteFile_, uint8_t region, - uint32_t flashWriteAddress) { + uint32_t address) { ReturnValue_t result = checkPath(flashWriteFile_); if (result != RETURN_OK) { return result; @@ -131,12 +146,33 @@ ReturnValue_t StrHelper::startFlashWrite(std::string flashWriteFile_, uint8_t re if(not std::filesystem::exists(flashWriteFile)) { return FILE_NOT_EXISTS; } + flashWriteAddress = address; + flashWriteRegion = region; internalState = InternalState::FLASH_WRITE; semaphore.release(); terminate = false; return RETURN_OK; } +ReturnValue_t StrHelper::startFlashRead(std::string flashReadFile_, uint8_t region, + uint32_t address, uint16_t length) { + ReturnValue_t result = checkPath(flashReadFile_); + if (result != RETURN_OK) { + return result; + } + flashReadFile = flashReadFile_; + if(not std::filesystem::exists(flashReadFile)) { + return FILE_NOT_EXISTS; + } + flashReadAddress = address; + flashReadRegion = region; + flashReadSize = length; + internalState = InternalState::FLASH_READ; + semaphore.release(); + terminate = false; + return RETURN_OK; +} + ReturnValue_t StrHelper::performImageDownload() { ReturnValue_t result; struct DownloadActionRequest downloadReq; @@ -184,7 +220,7 @@ ReturnValue_t StrHelper::performImageDownload() { file.close(); return result; } - file.write(reinterpret_cast(datalinkLayer.getReply() + DATA_OFFSET), + file.write(reinterpret_cast(datalinkLayer.getReply() + IMAGE_DATA_OFFSET), IMAGE_DATA_SIZE); downloadReq.position++; retries = 0; @@ -274,7 +310,7 @@ ReturnValue_t StrHelper::performFlashWrite() { if (result != RETURN_OK) { return RETURN_FAILED; } - result = checkFlashWriteReply(req); + result = checkFlashActionReply(req.region, req.address, req.length); if (result != RETURN_OK) { return result; } @@ -288,7 +324,7 @@ ReturnValue_t StrHelper::performFlashWrite() { if (result != RETURN_OK) { return RETURN_FAILED; } - result = checkFlashWriteReply(req); + result = checkFlashActionReply(req.region, req.address, req.length); if (result != RETURN_OK) { return result; } @@ -302,13 +338,12 @@ ReturnValue_t StrHelper::performFlashRead() { uint32_t size = 0; uint32_t retries = 0; Timestamp timestamp; - std::string file = flashReadPath + "/" + timestamp.str() + flashReadFile ; - std::ofstream file(file, std::ios_base::app | std::ios_base::out); - if(not std::filesystem::exists(file)) { + std::string fullname = flashReadPath + "/" + timestamp.str() + flashReadFile ; + std::ofstream file(fullname, std::ios_base::app | std::ios_base::out); + if (not std::filesystem::exists(fullname)) { return FILE_CREATION_FAILED; } req.region = flashReadRegion; - req.address = flashReadAddress; while(bytesRead < flashReadSize) { if (terminate) { return RETURN_OK; @@ -319,12 +354,9 @@ ReturnValue_t StrHelper::performFlashRead() { else { req.length = MAX_FLASH_DATA; } - arc_pack_read_action_req(&req, commandBuffer, static_cast(req.length)); - - - - - result = sendAndRead(size, downloadReq.position); + req.address = flashReadAddress + bytesRead; + arc_pack_read_action_req(&req, commandBuffer, &size); + result = sendAndRead(size, req.address); if (result != RETURN_OK) { if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) { uartComIF->flushUartRxBuffer(comCookie); @@ -344,7 +376,7 @@ ReturnValue_t StrHelper::performFlashRead() { file.close(); return result; } - result = checkReplyPosition(downloadReq.position); + result = checkFlashActionReply(req.region, req.address, req.length); if (result != RETURN_OK) { if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) { uartComIF->flushUartRxBuffer(comCookie); @@ -354,9 +386,9 @@ ReturnValue_t StrHelper::performFlashRead() { file.close(); return result; } - file.write(reinterpret_cast(datalinkLayer.getReply() + DATA_OFFSET), - IMAGE_DATA_SIZE); - downloadReq.position++; + file.write(reinterpret_cast(datalinkLayer.getReply() + FLASH_READ_DATA_OFFSET), + req.length); + bytesRead += req.length; retries = 0; } file.close(); @@ -446,8 +478,13 @@ ReturnValue_t StrHelper::checkReplyPosition(uint32_t expectedPosition) { return RETURN_OK; } -ReturnValue_t StrHelper::checkFlashWriteReply(struct WriteActionRequest& req) { +ReturnValue_t StrHelper::checkFlashActionReply(uint8_t region_, uint32_t address_, + uint16_t length_) { ReturnValue_t result = RETURN_OK; + result = checkReply(); + if (result != RETURN_OK) { + return result; + } const uint8_t* data = datalinkLayer.getReply(); uint8_t region = *(data + REGION_OFFSET); uint32_t address; @@ -456,7 +493,7 @@ ReturnValue_t StrHelper::checkFlashWriteReply(struct WriteActionRequest& req) { result = SerializeAdapter::deSerialize(&address, &addressData, &size, SerializeIF::Endianness::LITTLE); if (result != RETURN_OK) { - sif::warning << "StrHelper::checkFlashWriteReply: Deserialization of address failed" + sif::warning << "StrHelper::checkFlashActionReply: Deserialization of address failed" << std::endl; } uint16_t length; @@ -465,16 +502,16 @@ ReturnValue_t StrHelper::checkFlashWriteReply(struct WriteActionRequest& req) { result = SerializeAdapter::deSerialize(&length, lengthData, &size, SerializeIF::Endianness::LITTLE); if (result != RETURN_OK) { - sif::warning << "StrHelper::checkFlashWriteReply: Deserialization of length failed" + sif::warning << "StrHelper::checkFlashActionReply: Deserialization of length failed" << std::endl; } - if (region != req.region) { + if (region != region_) { return REGION_MISMATCH; } - if (address != req.address) { + if (address != address_) { return ADDRESS_MISMATCH; } - if (region != req.length) { + if (region != length_) { return LENGTH_MISMATCH; } return RETURN_OK; diff --git a/bsp_q7s/devices/startracker/StrHelper.h b/bsp_q7s/devices/startracker/StrHelper.h index 9fd74c7e..13742778 100644 --- a/bsp_q7s/devices/startracker/StrHelper.h +++ b/bsp_q7s/devices/startracker/StrHelper.h @@ -103,10 +103,21 @@ public: * * @param flashWriteFile_ Full name including absolute path of file to write to flash * @param region Region ID of flash region to write to - * @param flashWriteAddress Start address of flash write procedure + * @param address Start address of flash write procedure */ ReturnValue_t startFlashWrite(std::string flashWriteFile_, uint8_t region, - uint32_t flashWriteAddress); + uint32_t address); + + /** + * @brief Starts the flash read procedure + * + * @param flashWriteFile_ Full name including absolute path of file to write to flash + * @param region Region ID of flash region to read from + * @param flashWriteAddress Start address of flash section to read + * @param length Number of bytes to read from flash + */ + ReturnValue_t startFlashRead(std::string flashReadFile_, uint8_t region, + uint32_t address, uint16_t length); /** * @brief Can be used to interrupt a running data transfer. @@ -118,6 +129,11 @@ public: */ void setDownloadImageName(std::string image); + /** + * @brief Sets the name of the file which will be created to store the data read from flash + */ + void setFlashReadFilename(std::string filename); + private: static const uint8_t INTERFACE_ID = CLASS_ID::STR_HELPER; @@ -145,7 +161,8 @@ private: static const uint32_t MAX_POLLS = 10000; static const uint8_t POS_OFFSET = 2; - static const uint8_t DATA_OFFSET = 5; + static const uint8_t IMAGE_DATA_OFFSET = 5; + static const uint8_t FLASH_READ_DATA_OFFSET = 8; static const uint8_t REGION_OFFSET = 2; static const uint8_t ADDRESS_OFFSET = 3; static const uint8_t LENGTH_OFFSET = 7; @@ -232,6 +249,12 @@ private: */ ReturnValue_t performFlashWrite(); + /** + * @brief Sends a sequence of commands to the star tracker to read larger parts from the + * flash memory. + */ + ReturnValue_t performFlashRead(); + /** * @brief Sends packet to the star tracker and reads reply by using the communication * interface @@ -260,12 +283,12 @@ private: ReturnValue_t checkReplyPosition(uint32_t expectedPosition); /** - * @brief Checks the region, address and length value of a flash write reply. + * @brief Checks the region, address and length value of a flash write or read reply. * * @return RETURN_OK if values match expected values, otherwise appropriate error return * value. */ - ReturnValue_t checkFlashWriteReply(struct WriteActionRequest& req); + ReturnValue_t checkFlashActionReply(uint8_t region_, uint32_t address_, uint16_t length_); /** * @brief Checks if a path points to an sd card and whether the SD card is monuted.