diff --git a/CMakeLists.txt b/CMakeLists.txt index 677182d7b352aa380b577f5740411d036b469a61..986ff8435fefffb9251e461b81048a9a5f54be4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,8 +31,7 @@ add_library(common OBJECT add_executable(ecss_services src/main.cpp $<TARGET_OBJECTS:common> - src/Platform/x86/Service.cpp - ) + src/Platform/x86/Service.cpp) IF (EXISTS "${PROJECT_SOURCE_DIR}/lib/Catch2/CMakeLists.txt") # Gather all the .cpp files corresponding to tests diff --git a/inc/ErrorHandler.hpp b/inc/ErrorHandler.hpp index 56223cacaecfa11b03c0a12b0e3626d0d3d0b7c0..b18ae74466fa8750ca1c4a7b9e4e68eeec3a6062 100644 --- a/inc/ErrorHandler.hpp +++ b/inc/ErrorHandler.hpp @@ -81,7 +81,15 @@ public: * changes. */ enum ExecutionErrorType { - UnknownExecutionError = 0 + UnknownExecutionError = 0, + /** + * Checksum comparison failed + */ + ChecksumFailed = 1, + /** + * Address of a memory is out of the defined range for the type of memory + */ + AddressOutOfRange = 2, }; /** diff --git a/inc/Platform/STM32F7/MemoryAddressLimits.hpp b/inc/Platform/STM32F7/MemoryAddressLimits.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e30651f9373d45912404ca7f33ceceed060b2002 --- /dev/null +++ b/inc/Platform/STM32F7/MemoryAddressLimits.hpp @@ -0,0 +1,18 @@ +#ifndef ECSS_SERVICES_MEMORYADDRESSLIMITS_STM32F7_HPP +#define ECSS_SERVICES_MEMORYADDRESSLIMITS_STM32F7_HPP + +// Memory limits definitions +#define DTCMRAM_LOWER_LIM 0x20000000UL +#define DTCMRAM_UPPER_LIM 0x20020000UL +#define ITCMRAM_LOWER_LIM 0x00000000UL +#define ITCMRAM_UPPER_LIM 0x00010000UL +#define RAM_D1_LOWER_LIM 0x24000000UL +#define RAM_D1_UPPER_LIM 0x24080000UL +#define RAM_D2_LOWER_LIM 0x30000000UL +#define RAM_D2_UPPER_LIM 0x30048000UL +#define RAM_D3_LOWER_LIM 0x38000000UL +#define RAM_D3_UPPER_LIM 0x38010000UL +#define FLASH_LOWER_LIM 0x08000000UL +#define FLASH_UPPER_LIM 0x08200000UL + +#endif //ECSS_SERVICES_MEMORYADDRESSLIMITS_STM32F7_HPP diff --git a/inc/Services/EventReportService.hpp b/inc/Services/EventReportService.hpp index 4f516648a2a681a17eb14879d2c676dd7fb56164..026262b182d5783c0f2cad9a0e0fa5328b6ed105 100644 --- a/inc/Services/EventReportService.hpp +++ b/inc/Services/EventReportService.hpp @@ -2,11 +2,12 @@ #define ECSS_SERVICES_EVENTREPORTSERVICE_HPP #include "Service.hpp" +#include <bitset> /** * Implementation of ST[05] event reporting service * @todo add enum event definition id (and maybe some appending?) * - * @todo changes enums event IDs + * @todo add more enums event IDs * * Note: enum IDs are these just for test purposes * @@ -15,15 +16,48 @@ #define ECSS_EVENTS_BITS 16 class EventReportService : public Service { +private: + static const uint16_t numberOfEvents = 7; + std::bitset<numberOfEvents> stateOfEvents; public: + // Variables that count the event reports per severity level + uint16_t lowSeverityReportCount; + uint16_t mediumSeverityReportCount; + uint16_t highSeverityReportCount; + + // Variables that count the event occurences per severity level + uint16_t lowSeverityEventCount; + uint16_t mediumSeverityEventCount; + uint16_t highSeverityEventCount; + + uint16_t disabledEventsCount; + + uint16_t lastLowSeverityReportID; + uint16_t lastMediumSeverityReportID; + uint16_t lastHighSeverityReportID; + EventReportService() { + stateOfEvents.set(); serviceType = 5; + lowSeverityReportCount = 0; + mediumSeverityReportCount = 0; + highSeverityReportCount = 0; + disabledEventsCount = 0; + lowSeverityEventCount = 0; + mediumSeverityEventCount = 0; + highSeverityEventCount = 0; + lastLowSeverityReportID = 65535; + lastMediumSeverityReportID = 65535; + lastHighSeverityReportID = 65535; } /** * Type of the information event + * + * Note: Numbers are kept in code explicitly, so that there is no uncertainty when something + * changes. */ - enum InformationEvent { + enum Event { /** * An unknown event occured */ @@ -33,96 +67,116 @@ public: */ WWDGReset = 1, /** - * An assertion has failed + * Assertion has failed */ AssertionFail = 2, /** * Microcontroller has started */ MCUStart = 3, - }; - - /** - * Type of the low severity anomaly event - */ - enum LowSeverityAnomalyEvent { /** * An unknown anomaly of low severity anomalyhas occurred */ - LowSeverityUnknownEvent = 1, - }; - - /** - * Type of the medium severity anomaly event - */ - enum MediumSeverityAnomalyEvent { + LowSeverityUnknownEvent = 4, /** * An unknown anomaly of medium severity has occurred */ - MediumSeverityUnknownEvent = 2, - }; - - /** - * Type of the high severity anomaly event - */ - enum HighSeverityAnomalyEvent { + MediumSeverityUnknownEvent = 5, /** * An unknown anomaly of high severity has occurred */ - HighSeverityUnknownEvent = 3, + HighSeverityUnknownEvent = 6, + /** + * When an execution of a notification/event fails to start + */ + FailedStartOfExecution = 7 }; /** * TM[5,1] informative event report * Send report to inform the respective recipients about an event * - * Note: The parameters are defined by the standard, but the event definition id is missing! + * Note: The parameters are defined by the standard * * @param eventID event definition ID * @param data the data of the report * @param length the length of the data */ - void informativeEventReport(InformationEvent eventID, const uint8_t *data, uint8_t length); + void informativeEventReport(Event eventID, const uint8_t *data, uint8_t length); /** * TM[5,2] low severiity anomaly report * Send report when there is an anomaly event of low severity to the respective recipients * - * Note: The parameters are defined by the standard, but the event definition id is missing! + * Note: The parameters are defined by the standard * * @param eventID event definition ID * @param data the data of the report * @param length the length of the data */ void - lowSeverityAnomalyReport(LowSeverityAnomalyEvent eventID, const uint8_t *data, uint8_t length); + lowSeverityAnomalyReport(Event eventID, const uint8_t *data, uint8_t length); /** * TM[5,3] medium severity anomaly report * Send report when there is an anomaly event of medium severity to the respective recipients * - * Note: The parameters are defined by the standard, but the event definition id is missing! + * Note: The parameters are defined by the standard * * @param eventID event definition ID * @param data the data of the report * @param length the length of the data */ - void mediumSeverityAnomalyReport(MediumSeverityAnomalyEvent eventID, const uint8_t *data, + void mediumSeverityAnomalyReport(Event eventID, const uint8_t *data, uint8_t length); /** * TM[5,4] high severity anomaly report - * Send report when there is an anomaly event of hgih severity to the respective recipients + * Send report when there is an anomaly event of high severity to the respective recipients * - * Note: The parameters are defined by the standard, but the event definition id is missing! + * Note: The parameters are defined by the standard * * @param eventID event definition ID * @param data the data of the report * @param length the length of the data */ - void highSeverityAnomalyReport(HighSeverityAnomalyEvent eventID, const uint8_t *data, + void highSeverityAnomalyReport(Event eventID, const uint8_t *data, uint8_t length); + /** + * TC[5,5] request to enable report generation + * Telecommand to enable the report generation of event definitions + */ + void enableReportGeneration(Message message); + + /** + * TC[5,6] request to disable report generation + * Telecommand to disable the report generation of event definitions + * @param message + */ + void disableReportGeneration(Message message); + + /** + * TC[5,7] request to report the disabled event definitions + * Note: No arguments, according to the standard. + * @param message + */ + void requestListOfDisabledEvents(Message message); + + /** + * TM[5,8] disabled event definitions report + * Telemetry package of a report of the disabled event definitions + * @param message + */ + void listOfDisabledEventsReport(); + + /** + * Getter for stateOfEvents bitset + * @return stateOfEvents, just in case the whole bitset is needed + */ + std::bitset<numberOfEvents> getStateOfEvents() { + return stateOfEvents; + } }; #endif //ECSS_SERVICES_EVENTREPORTSERVICE_HPP diff --git a/inc/Services/MemoryManagementService.hpp b/inc/Services/MemoryManagementService.hpp index 1d2de9be32b3589b84e84b07007f05380e81a062..5cd3c16da1f43a2f62d741553052dbae2eeb319c 100644 --- a/inc/Services/MemoryManagementService.hpp +++ b/inc/Services/MemoryManagementService.hpp @@ -1,17 +1,25 @@ #ifndef ECSS_SERVICES_MEMMANGSERVICE_HPP #define ECSS_SERVICES_MEMMANGSERVICE_HPP -#include "Service.hpp" #include <memory> #include <iostream> +#include "Service.hpp" +#include "Helpers/CRCHelper.hpp" +#include "ErrorHandler.hpp" +#include "Platform/STM32F7/MemoryAddressLimits.hpp" + class MemoryManagementService : public Service { public: // Memory type ID's enum MemoryID { - RAM = 0, - FLASH = 1, - EXTERNAL = 2 + DTCMRAM = 0, + RAM_D1, + RAM_D2, + RAM_D3, + ITCMRAM, + FLASH, + EXTERNAL }; MemoryManagementService(); @@ -35,7 +43,8 @@ public: * * @details This function loads new values to memory data areas * specified in the request - * @param request: Provide the received message as a parameter + * @param request Provide the received message as a parameter + * @todo Only allow aligned memory address to be start addresses */ void loadRawData(Message &request); @@ -44,12 +53,47 @@ public: * * @details This function reads the raw data from the RAM memory and * triggers a TM[6,6] report - * @param request: Provide the received message as a parameter + * @param request Provide the received message as a parameter * @todo In later embedded version, implement error checking for address validity for * different memory types + * @todo Only allow aligned memory address to be start addresses */ void dumpRawData(Message &request); + + /** + * TC[6,9] check raw memory data + * + * @details This function reads the raw data from the specified memory and + * triggers a TM[6,10] report + * @param request Provide the received message as a parameter + * @todo In later embedded version, implement error checking for address validity for + * different memory types + * @todo Only allow aligned memory address to be start addresses + */ + void checkRawData(Message &request); } rawDataMemorySubservice; + +private: + /** + * Check whether the provided address is valid or not, based on the defined limit values + * + * @param memId The ID of the memory to check is passed + * @param address Takes the address to be checked for validity + */ + bool addressValidator(MemoryManagementService::MemoryID memId, uint64_t address); + + /** + * Check if the provided memory ID is valid + * + * @param memId The memory ID for validation + */ + bool memoryIdValidator(MemoryManagementService::MemoryID memId); + + /** + * Validate the data according to checksum calculation + * + */ + bool dataValidator(const uint8_t *data, uint16_t checksum, uint16_t length); }; #endif //ECSS_SERVICES_MEMMANGSERVICE_HPP diff --git a/src/Platform/x86/Service.cpp b/src/Platform/x86/Service.cpp index 07403e438e1ff884b430c5eafff7d92a7d63c63c..ff9d9d95de57f749996cb8a2fcd7853cebda7813 100644 --- a/src/Platform/x86/Service.cpp +++ b/src/Platform/x86/Service.cpp @@ -4,7 +4,9 @@ void Service::storeMessage(const Message &message) { // Just print it to the screen - std::cout << "New " << ((message.packetType == Message::TM) ? "TM" : "TC") << "[" << std::dec + std::cout << "New " << ((message.packetType == Message::TM) ? "TM" : "TC") << "[" + << std::hex + // << std::dec << static_cast<int>(message.serviceType) << "," << static_cast<int>(message.messageType) << "] message!\n"; //std::cout << std::hex << std::setfill('0') << std::setw(2); diff --git a/src/Services/EventReportService.cpp b/src/Services/EventReportService.cpp index 0a89f5c9765aa49e8932c0df9c1a4f1ed732a4ac..d49cef3c7ca31b184bfae618c6007e2245fb1865 100644 --- a/src/Services/EventReportService.cpp +++ b/src/Services/EventReportService.cpp @@ -1,46 +1,130 @@ +#include <Services/EventReportService.hpp> #include "Services/EventReportService.hpp" #include "Message.hpp" - -void EventReportService::informativeEventReport(InformationEvent eventID, const uint8_t *data, +/** + * @todo: Add message type in TCs + * @todo: this code is error prone, depending on parameters given, add fail safes (probably?) + */ +void EventReportService::informativeEventReport(Event eventID, const uint8_t *data, uint8_t length) { // TM[5,1] - Message report = createTM(1); - report.appendEnum16(eventID); - report.appendString(length, data); + if (stateOfEvents[static_cast<uint16_t> (eventID)] == 1) { + Message report = createTM(1); + report.appendEnum16(eventID); + report.appendString(length, data); - storeMessage(report); + storeMessage(report); + } } void -EventReportService::lowSeverityAnomalyReport(LowSeverityAnomalyEvent eventID, const uint8_t *data, +EventReportService::lowSeverityAnomalyReport(Event eventID, const uint8_t *data, uint8_t length) { + lowSeverityEventCount++; // TM[5,2] - Message report = createTM(2); - report.appendEnum16(eventID); - report.appendString(length, data); + if (stateOfEvents[static_cast<uint16_t> (eventID)] == 1) { + lowSeverityReportCount++; + Message report = createTM(2); + report.appendEnum16(eventID); + report.appendString(length, data); + lastLowSeverityReportID = static_cast<uint16_t >(eventID); - storeMessage(report); + storeMessage(report); + } } -void EventReportService::mediumSeverityAnomalyReport(MediumSeverityAnomalyEvent eventID, - const uint8_t *data, - uint8_t length) { +void EventReportService::mediumSeverityAnomalyReport(Event eventID, + const uint8_t *data, uint8_t length) { + mediumSeverityEventCount++; // TM[5,3] - Message report = createTM(3); - report.appendEnum16(eventID); - report.appendString(length, data); + if (stateOfEvents[static_cast<uint16_t> (eventID)] == 1) { + mediumSeverityReportCount++; + Message report = createTM(3); + report.appendEnum16(eventID); + report.appendString(length, data); + lastMediumSeverityReportID = static_cast<uint16_t >(eventID); - storeMessage(report); + storeMessage(report); + } } void -EventReportService::highSeverityAnomalyReport(HighSeverityAnomalyEvent eventID, const uint8_t *data, +EventReportService::highSeverityAnomalyReport(Event eventID, const uint8_t *data, uint8_t length) { + highSeverityEventCount++; // TM[5,4] - Message report = createTM(4); - report.appendEnum16(eventID); - report.appendString(length, data); + if (stateOfEvents[static_cast<uint16_t> (eventID)] == 1) { + highSeverityReportCount++; + Message report = createTM(4); + report.appendEnum16(eventID); + report.appendString(length, data); + lastHighSeverityReportID = static_cast<uint16_t >(eventID); + + storeMessage(report); + } +} + +void EventReportService::enableReportGeneration(Message message) { + // TC[5,5] + if (message.serviceType == 5 && message.packetType == Message::TC && message.messageType == 5) { + /** + * @todo: Report an error if length > numberOfEvents + */ + uint16_t length = message.readUint16(); + Event eventID[length]; + for (uint16_t i = 0; i < length; i++) { + eventID[i] = static_cast<Event >(message.readEnum16()); + } + if (length <= numberOfEvents) { + for (uint16_t i = 0; i < length; i++) { + stateOfEvents[static_cast<uint16_t> (eventID[i])] = 1; + } + } + disabledEventsCount = stateOfEvents.size() - stateOfEvents.count(); + } +} + +void EventReportService::disableReportGeneration(Message message) { + // TC[5,6] + if (message.serviceType == 5 && message.packetType == Message::TC && message.messageType + == 6) { + /** + * @todo: Report an error if length > numberOfEvents + */ + uint16_t length = message.readUint16(); + Event eventID[length]; + for (uint16_t i = 0; i < length; i++) { + eventID[i] = static_cast<Event >(message.readEnum16()); + } + if (length <= numberOfEvents) { + for (uint16_t i = 0; i < length; i++) { + stateOfEvents[static_cast<uint16_t> (eventID[i])] = 0; + } + } + disabledEventsCount = stateOfEvents.size() - stateOfEvents.count(); + } +} + +void EventReportService::requestListOfDisabledEvents(Message message) { + // TC[5,7] + // I think this is all that is needed here. + if (message.serviceType == 5 && message.packetType == Message::TC && message.messageType == 7) { + listOfDisabledEventsReport(); + } +} + +void EventReportService::listOfDisabledEventsReport() { + // TM[5,8] + Message report = createTM(8); + + uint16_t numberOfDisabledEvents = stateOfEvents.size() - stateOfEvents.count(); + report.appendHalfword(numberOfDisabledEvents); + for (uint16_t i = 0; i < stateOfEvents.size(); i++) { + if (stateOfEvents[i] == 0) { + report.appendEnum16(i); + } + } storeMessage(report); } diff --git a/src/Services/MemoryManagementService.cpp b/src/Services/MemoryManagementService.cpp index cd84b3dd01df44dac75852009ec90c587c500889..05bd9bdfea50fb1de15ef10b3f8daf919d701c50 100644 --- a/src/Services/MemoryManagementService.cpp +++ b/src/Services/MemoryManagementService.cpp @@ -25,25 +25,49 @@ void MemoryManagementService::RawDataMemoryManagement::loadRawData(Message &requ assert(request.serviceType == 6); assert(request.messageType == 2); - // Variable declaration - uint8_t readData[ECSS_MAX_STRING_SIZE]; // Preallocate the array - - uint8_t memoryID = request.readEnum8(); // Read the memory ID from the request - uint16_t iterationCount = request.readUint16(); // Get the iteration count - - if (memoryID == MemoryManagementService::MemoryID::RAM) { - for (std::size_t j = 0; j < iterationCount; j++) { - uint64_t startAddress = request.readUint64(); // Start address of the memory - uint16_t dataLength = request.readOctetString(readData); // Data length to load - // todo: Error logging has to be included, if memory allocation above fails - // todo: Continue only if the checksum passes (when the checksum will be implemented) - - for (std::size_t i = 0; i < dataLength; i++) { - *(reinterpret_cast<uint8_t *>(startAddress) + i) = readData[i]; + // Read the memory ID from the request + auto memoryID = MemoryManagementService::MemoryID(request.readEnum8()); + + // Check for a valid memory ID first + if (mainService.memoryIdValidator(MemoryManagementService::MemoryID(memoryID))) { + // Variable declaration + uint8_t readData[ECSS_MAX_STRING_SIZE]; // Preallocate the array + uint16_t iterationCount = request.readUint16(); // Get the iteration count + + if (memoryID == MemoryManagementService::MemoryID::FLASH) { + // todo: Define FLASH specific access code when we transfer to embedded + } else { + for (std::size_t j = 0; j < iterationCount; j++) { + uint64_t startAddress = request.readUint64(); // Start address of the memory + uint16_t dataLength = request.readOctetString(readData); // Data length to load + uint16_t checksum = request.readBits(16); // Get the CRC checksum from the message + + // Continue only if the checksum passes + if (mainService.dataValidator(readData, checksum, dataLength)) { + if (mainService.addressValidator(memoryID, startAddress) && + mainService.addressValidator(memoryID, startAddress + dataLength)) { + for (std::size_t i = 0; i < dataLength; i++) { + *(reinterpret_cast<uint8_t *>(startAddress) + i) = readData[i]; + } + + // Read the loaded data for checksum validation and perform a check + for (std::size_t i = 0; i < dataLength; i++) { + readData[i] = *(reinterpret_cast<uint8_t *>(startAddress) + i); + } + if (checksum != CRCHelper::calculateCRC(readData, dataLength)) { + ErrorHandler::reportError(request, ErrorHandler::ChecksumFailed); + } + } else { + ErrorHandler::reportError(request, ErrorHandler::ChecksumFailed); + } + } else { + ErrorHandler::reportError(request, ErrorHandler::ChecksumFailed); + continue; // Continue to the next command + } } } - } else if (memoryID == MemoryManagementService::MemoryID::FLASH) { - // todo: Define FLASH specific access code when we transfer to embedded + } else { + // todo: Send a failed start of execution } } @@ -54,35 +78,156 @@ void MemoryManagementService::RawDataMemoryManagement::dumpRawData(Message &requ // Create the report message object of telemetry message subtype 6 Message report = mainService.createTM(6); + uint8_t memoryID = request.readEnum8(); // Read the memory ID from the request - // Variable declaration - uint8_t readData[ECSS_MAX_STRING_SIZE]; // Preallocate the array + // Check for a valid memory ID first + if (mainService.memoryIdValidator(MemoryManagementService::MemoryID(memoryID))) { + // Variable declaration + uint8_t readData[ECSS_MAX_STRING_SIZE]; // Preallocate the array + uint16_t iterationCount = request.readUint16(); // Get the iteration count - uint8_t memoryID = request.readEnum8(); // Read the memory ID from the request - // todo: Add checks depending on the memory type + // Append the data to report message + report.appendEnum8(memoryID); // Memory ID + report.appendUint16(iterationCount); // Iteration count - uint16_t iterationCount = request.readUint16(); // Get the iteration count + // Iterate N times, as specified in the command message + for (std::size_t j = 0; j < iterationCount; j++) { + uint64_t startAddress = request.readUint64(); // Data length to read + uint16_t readLength = request.readUint16(); // Start address for the memory read + + // Read memory data, an octet at a time, checking for a valid address first + if (mainService.addressValidator(MemoryManagementService::MemoryID(memoryID), + startAddress) && + mainService.addressValidator(MemoryManagementService::MemoryID(memoryID), + startAddress + readLength)) { + for (std::size_t i = 0; i < readLength; i++) { + readData[i] = *(reinterpret_cast<uint8_t *>(startAddress) + i); + } + + // This part is repeated N-times (N = iteration count) + report.appendUint64(startAddress); // Start address + report.appendOctetString(readLength, readData); // Save the read data + report.appendBits(16, CRCHelper::calculateCRC(readData, readLength)); + } else { + ErrorHandler::reportError(request, ErrorHandler::AddressOutOfRange); + } + } - // Append the data to report message - report.appendEnum8(memoryID); // Memory ID - report.appendUint16(iterationCount); // Iteration count + mainService.storeMessage(report); // Save the report message + request.resetRead(); // Reset the reading count + } else { + // todo: Send a failed start of execution + } +} - // Iterate N times, as specified in the command message - for (std::size_t j = 0; j < iterationCount; j++) { - uint64_t startAddress = request.readUint64(); // Data length to read - uint16_t readLength = request.readUint16(); // Start address for the memory read +void MemoryManagementService::RawDataMemoryManagement::checkRawData(Message &request) { + // Check if we have the correct packet + assert(request.serviceType == 6); + assert(request.messageType == 9); - // Read memory data, an octet at a time - for (std::size_t i = 0; i < readLength; i++) { - readData[i] = *(reinterpret_cast<uint8_t *>(startAddress) + i); + // Create the report message object of telemetry message subtype 10 + Message report = mainService.createTM(10); + uint8_t memoryID = request.readEnum8(); // Read the memory ID from the request + + if (mainService.memoryIdValidator(MemoryManagementService::MemoryID(memoryID))) { + // Variable declaration + uint8_t readData[ECSS_MAX_STRING_SIZE]; // Preallocate the array + uint16_t iterationCount = request.readUint16(); // Get the iteration count + + // Append the data to report message + report.appendEnum8(memoryID); // Memory ID + report.appendUint16(iterationCount); // Iteration count + + // Iterate N times, as specified in the command message + for (std::size_t j = 0; j < iterationCount; j++) { + uint64_t startAddress = request.readUint64(); // Data length to read + uint16_t readLength = request.readUint16(); // Start address for the memory read + + // Check whether the first and the last addresses are within the limits + if (mainService.addressValidator(MemoryManagementService::MemoryID(memoryID), + startAddress) && + mainService.addressValidator(MemoryManagementService::MemoryID(memoryID), + startAddress + readLength)) { + // Read memory data and save them for checksum calculation + for (std::size_t i = 0; i < readLength; i++) { + readData[i] = *(reinterpret_cast<uint8_t *>(startAddress) + i); + } + + // This part is repeated N-times (N = iteration count) + report.appendUint64(startAddress); // Start address + report.appendUint16(readLength); // Save the read data + report.appendBits(16, CRCHelper::calculateCRC(readData, readLength)); // Append CRC + } else { + ErrorHandler::reportError(request, ErrorHandler::AddressOutOfRange); + } } - // This part is repeated N-times (N = iteration count) - report.appendUint64(startAddress); // Start address - report.appendOctetString(readLength, readData); // Save the read data + + mainService.storeMessage(report); // Save the report message + request.resetRead(); // Reset the reading count + } else { + // todo: Send a failed start of execution report + } +} + + +// Private function declaration section +bool MemoryManagementService::addressValidator( + MemoryManagementService::MemoryID memId, uint64_t address) { + bool validIndicator = false; + + switch (memId) { + case MemoryManagementService::MemoryID::DTCMRAM: + if (address >= DTCMRAM_LOWER_LIM && address <= DTCMRAM_UPPER_LIM) { + validIndicator = true; + } + break; + case MemoryManagementService::MemoryID::ITCMRAM: + if (address >= ITCMRAM_LOWER_LIM && address <= ITCMRAM_UPPER_LIM) { + validIndicator = true; + } + break; + case MemoryManagementService::MemoryID::RAM_D1: + if (address >= RAM_D1_LOWER_LIM && address <= RAM_D1_UPPER_LIM) { + validIndicator = true; + } + break; + case MemoryManagementService::MemoryID::RAM_D2: + if (address >= RAM_D2_LOWER_LIM && address <= RAM_D2_UPPER_LIM) { + validIndicator = true; + } + break; + case MemoryManagementService::MemoryID::RAM_D3: + if (address >= RAM_D3_LOWER_LIM && address <= RAM_D3_UPPER_LIM) { + validIndicator = true; + } + break; + case MemoryManagementService::MemoryID::FLASH: + if (address >= FLASH_LOWER_LIM && address <= FLASH_UPPER_LIM) { + validIndicator = true; + } + break; + + default: + validIndicator = true; // todo: Implemented so addresses from PC can be read. Remove. + break; } - // todo: implement and append the checksum part of the reporting packet - mainService.storeMessage(report); // Save the report message - request.resetRead(); // Reset the reading count + return validIndicator; +} + +inline bool MemoryManagementService::memoryIdValidator( + MemoryManagementService::MemoryID memId) { + return (memId == MemoryManagementService::MemoryID::RAM_D1) || + (memId == MemoryManagementService::MemoryID::RAM_D2) || + (memId == MemoryManagementService::MemoryID::RAM_D3) || + (memId == MemoryManagementService::MemoryID::DTCMRAM) || + (memId == MemoryManagementService::MemoryID::ITCMRAM) || + (memId == MemoryManagementService::MemoryID::FLASH) || + (memId == MemoryManagementService::MemoryID::EXTERNAL); +} + +inline bool MemoryManagementService::dataValidator(const uint8_t *data, uint16_t checksum, + uint16_t length) { + return (checksum == CRCHelper::calculateCRC(data, length)); } diff --git a/src/main.cpp b/src/main.cpp index d8c0c8dfa037a9df240ffdef44f027003f78f521..3219196bc212f42548f6049597b28e51651bcbb3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,8 +9,10 @@ #include "Message.hpp" #include "MessageParser.hpp" #include "Services/MemoryManagementService.hpp" +#include "Helpers/CRCHelper.hpp" #include "ErrorHandler.hpp" + int main() { Message packet = Message(0, 0, Message::TC, 1); @@ -69,7 +71,7 @@ int main() { MemoryManagementService memMangService; Message rcvPack = Message(6, 5, Message::TC, 1); - rcvPack.appendEnum8(MemoryManagementService::MemoryID::RAM); // Memory ID + rcvPack.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL); // Memory ID rcvPack.appendUint16(3); // Iteration count rcvPack.appendUint64(reinterpret_cast<uint64_t >(string)); // Start address rcvPack.appendUint16(sizeof(string) / sizeof(string[0])); // Data read length @@ -84,14 +86,26 @@ int main() { rcvPack = Message(6, 2, Message::TC, 1); uint8_t data[2] = {'h', 'R'}; - rcvPack.appendEnum8(MemoryManagementService::MemoryID::RAM); // Memory ID + rcvPack.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL); // Memory ID rcvPack.appendUint16(2); // Iteration count rcvPack.appendUint64(reinterpret_cast<uint64_t >(pStr)); // Start address rcvPack.appendOctetString(2, data); + rcvPack.appendBits(16, CRCHelper::calculateCRC(data, 2)); // Append the CRC value rcvPack.appendUint64(reinterpret_cast<uint64_t >(pStr + 1)); // Start address rcvPack.appendOctetString(1, data); + rcvPack.appendBits(16, CRCHelper::calculateCRC(data, 1)); // Append the CRC value memMangService.rawDataMemorySubservice.loadRawData(rcvPack); + rcvPack = Message(6, 9, Message::TC, 1); + + rcvPack.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL); // Memory ID + rcvPack.appendUint16(2); // Iteration count + rcvPack.appendUint64(reinterpret_cast<uint64_t >(data)); // Start address + rcvPack.appendUint16(2); + rcvPack.appendUint64(reinterpret_cast<uint64_t >(data + 1)); // Start address + rcvPack.appendUint16(1); + memMangService.rawDataMemorySubservice.checkRawData(rcvPack); + // ST[01] test @@ -112,7 +126,7 @@ int main() { receivedMessage = Message(1, 10, Message::TC, 3); reqVerifService.failRoutingVerification(receivedMessage); - // ST[05] test [works] + // ST[05] (5,1 to 5,4) test [works] const unsigned char eventReportData[12] = "Hello World"; EventReportService eventReportService; eventReportService.informativeEventReport(EventReportService::InformativeUnknownEvent, @@ -156,9 +170,29 @@ int main() { errorMessage.appendBits(2, 7); errorMessage.appendByte(15); + // TimeHelper test uint64_t test = TimeHelper::implementCUCTimeFormat(1200); std::cout << "\n" << test; + // ST[05] (5,5 to 5,8) test [works] + EventReportService::Event eventIDs[] = {EventReportService::HighSeverityUnknownEvent, + EventReportService::MediumSeverityUnknownEvent}; + EventReportService::Event eventIDs2[] = {EventReportService::HighSeverityUnknownEvent}; + Message eventMessage(5, 6, Message::TC, 1); + eventMessage.appendUint16(2); + eventMessage.appendEnum16(eventIDs[0]); + eventMessage.appendEnum16(eventIDs[1]); + + Message eventMessage2(5, 5, Message::TC, 1); + eventMessage2.appendUint16(1); + eventMessage2.appendEnum16(eventIDs2[0]); + + Message eventMessage3(5, 7, Message::TC, 1); + eventReportService.disableReportGeneration(eventMessage); + eventReportService.listOfDisabledEventsReport(); + eventReportService.enableReportGeneration(eventMessage2); + eventReportService.requestListOfDisabledEvents(eventMessage3); + return 0; } diff --git a/test/Services/EventReportService.cpp b/test/Services/EventReportService.cpp index 32f4f30b18ee8d9e38c9c5a059fcfd07ad27c9f1..f326e76841d6ea0638db8d648db98ff94db73a08 100644 --- a/test/Services/EventReportService.cpp +++ b/test/Services/EventReportService.cpp @@ -42,7 +42,7 @@ TEST_CASE("Low Severity Anomaly Report TM[5,2]", "[service][st05]") { CHECK(report.packetType == Message::TM); // packet type(TM = 0, TC = 1) REQUIRE(report.dataSize == 12); // Check for the value that is stored in <<data>> array(data-member of object response) - CHECK(report.readEnum16() == 1); + CHECK(report.readEnum16() == 4); report.readString(checkString, 10); CHECK(strcmp(checkString, reinterpret_cast<const char *>(eventReportData)) == 0); } @@ -62,7 +62,7 @@ TEST_CASE("Medium Severity Anomaly Report TM[5,3]", "[service][st05]") { CHECK(report.packetType == Message::TM); // packet type(TM = 0, TC = 1) REQUIRE(report.dataSize == 12); // Check for the value that is stored in <<data>> array(data-member of object response) - CHECK(report.readEnum16() == 2); + CHECK(report.readEnum16() == 5); report.readString(checkString, 10); CHECK(strcmp(checkString, reinterpret_cast<const char *>(eventReportData)) == 0); } @@ -82,7 +82,106 @@ TEST_CASE("High Severity Anomaly Report TM[5,4]", "[service][st05]") { CHECK(report.packetType == Message::TM); // packet type(TM = 0, TC = 1) REQUIRE(report.dataSize == 12); // Check for the value that is stored in <<data>> array(data-member of object response) - CHECK(report.readEnum16() == 3); + CHECK(report.readEnum16() == 6); report.readString(checkString, 10); CHECK(strcmp(checkString, reinterpret_cast<const char *>(eventReportData)) == 0); } + +TEST_CASE("Enable Report Generation TC[5,5]", "[service][st05]") { + EventReportService eventReportService; + eventReportService.getStateOfEvents().reset(); + EventReportService::Event eventID[] = {EventReportService::AssertionFail, + EventReportService::LowSeverityUnknownEvent}; + Message message(5, 5, Message::TC, 1); + message.appendUint16(2); + message.appendEnum16(eventID[0]); + message.appendEnum16(eventID[1]); + eventReportService.enableReportGeneration(message); + CHECK(eventReportService.getStateOfEvents()[2] == 1); + CHECK(eventReportService.getStateOfEvents()[4] == 1); +} + +TEST_CASE("Disable Report Generation TC[5,6]", "[service][st05]") { + EventReportService eventReportService; + EventReportService::Event eventID[] = {EventReportService::InformativeUnknownEvent, + EventReportService::MediumSeverityUnknownEvent}; + Message message(5, 6, Message::TC, 1); + message.appendUint16(2); + message.appendEnum16(eventID[0]); + message.appendEnum16(eventID[1]); + eventReportService.disableReportGeneration(message); + CHECK(eventReportService.getStateOfEvents()[0] == 0); + CHECK(eventReportService.getStateOfEvents()[5] == 0); + + const unsigned char eventReportData[] = "HelloWorld"; + eventReportService.highSeverityAnomalyReport(EventReportService::InformativeUnknownEvent, + eventReportData, 10); + CHECK(ServiceTests::hasOneMessage() == false); +} + +TEST_CASE("Request list of disabled events TC[5,7]", "[service][st05]") { + EventReportService eventReportService; + Message message(5, 7, Message::TC, 1); + eventReportService.requestListOfDisabledEvents(message); + REQUIRE(ServiceTests::hasOneMessage()); + + Message report = ServiceTests::get(0); + // Check if there is message of type 8 created + CHECK(report.messageType == 8); +} + +TEST_CASE("List of Disabled Events Report TM[5,8]", "[service][st05]") { + EventReportService eventReportService; + EventReportService::Event eventID[] = {EventReportService::MCUStart, + EventReportService::HighSeverityUnknownEvent}; + Message message(5, 6, Message::TC, 1); + message.appendUint16(2); + message.appendEnum16(eventID[0]); + message.appendEnum16(eventID[1]); + // Disable 3rd and 6th + eventReportService.disableReportGeneration(message); + eventReportService.listOfDisabledEventsReport(); + REQUIRE(ServiceTests::hasOneMessage()); + + Message report = ServiceTests::get(0); + // Check for the data-members of the report Message created + CHECK(report.serviceType == 5); + CHECK(report.messageType == 8); + CHECK(report.packetType == Message::TM); // packet type(TM = 0, TC = 1) + REQUIRE(report.dataSize == 6); + // Check for the information stored in report + CHECK(report.readHalfword() == 2); + CHECK(report.readEnum16() == 3); + CHECK(report.readEnum16() == 6); +} + +TEST_CASE("List of observables 6.5.6", "[service][st05]") { + EventReportService eventReportService; + EventReportService::Event eventID[] = {EventReportService::HighSeverityUnknownEvent}; + Message message(5, 6, Message::TC, 1); + message.appendUint16(1); + message.appendEnum16(eventID[0]); + eventReportService.disableReportGeneration(message); + + const unsigned char eventReportData[] = "HelloWorld"; + + eventReportService.highSeverityAnomalyReport(EventReportService::HighSeverityUnknownEvent, + eventReportData, + 10); + eventReportService.mediumSeverityAnomalyReport(EventReportService::MediumSeverityUnknownEvent, + eventReportData, + 10); + CHECK(eventReportService.lowSeverityReportCount == 0); + CHECK(eventReportService.mediumSeverityReportCount == 1); + CHECK(eventReportService.highSeverityReportCount == 0); + + CHECK(eventReportService.lowSeverityEventCount == 0); + CHECK(eventReportService.mediumSeverityEventCount == 1); + CHECK(eventReportService.highSeverityEventCount == 1); + + CHECK(eventReportService.disabledEventsCount == 1); + + CHECK(eventReportService.lastLowSeverityReportID == 65535); + CHECK(eventReportService.lastMediumSeverityReportID == 5); + CHECK(eventReportService.lastHighSeverityReportID == 65535); +} diff --git a/test/Services/MemoryManagementService.cpp b/test/Services/MemoryManagementService.cpp index d59c8de2c6490d99b9113904a08ce313dc25ef26..06bbe264f0ce68c5585dcc158e5f8e8fcec12cf4 100644 --- a/test/Services/MemoryManagementService.cpp +++ b/test/Services/MemoryManagementService.cpp @@ -2,6 +2,7 @@ #include <Services/MemoryManagementService.hpp> #include <Message.hpp> #include "ServiceTests.hpp" +#include "Helpers/CRCHelper.hpp" TEST_CASE("TM[6,2]", "[service][st06]") { // Required test variables @@ -14,12 +15,14 @@ TEST_CASE("TM[6,2]", "[service][st06]") { MemoryManagementService memMangService; Message receivedPacket = Message(6, 2, Message::TC, 1); - receivedPacket.appendEnum8(MemoryManagementService::MemoryID::RAM); // Memory ID + receivedPacket.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL); // Memory ID receivedPacket.appendUint16(2); // Iteration count receivedPacket.appendUint64(reinterpret_cast<uint64_t >(pStr)); // Start address receivedPacket.appendOctetString(2, data); + receivedPacket.appendBits(16, CRCHelper::calculateCRC(data, 2)); // Append CRC receivedPacket.appendUint64(reinterpret_cast<uint64_t >(pStr + 2)); // Start address - receivedPacket.appendOctetString(1, data); + receivedPacket.appendOctetString(1, data); // Append CRC + receivedPacket.appendBits(16, CRCHelper::calculateCRC(data, 1)); memMangService.rawDataMemorySubservice.loadRawData(receivedPacket); CHECK(pStr[0] == 'h'); @@ -33,43 +36,46 @@ TEST_CASE("TM[6,5]", "[service][st06]") { uint8_t testString_3[2] = {5, 8}; uint8_t checkString[ECSS_MAX_STRING_SIZE]; - uint16_t readSize = 0; + uint16_t readSize = 0, checksum = 0; MemoryManagementService memMangService; Message receivedPacket = Message(6, 5, Message::TC, 1); - receivedPacket.appendEnum8(MemoryManagementService::MemoryID::RAM); // Memory ID + receivedPacket.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL); // Memory ID receivedPacket.appendUint16(3); // Iteration count (Equal to 3 test strings) receivedPacket.appendUint64(reinterpret_cast<uint64_t >(testString_1)); // Start address - receivedPacket.appendUint16(sizeof(testString_1)/ sizeof(testString_1[0])); // Data read length + receivedPacket.appendUint16(sizeof(testString_1) / sizeof(testString_1[0])); // Data read length receivedPacket.appendUint64(reinterpret_cast<uint64_t >(testString_2)); - receivedPacket.appendUint16(sizeof(testString_2)/ sizeof(testString_2[0])); + receivedPacket.appendUint16(sizeof(testString_2) / sizeof(testString_2[0])); receivedPacket.appendUint64(reinterpret_cast<uint64_t >(testString_3)); - receivedPacket.appendUint16(sizeof(testString_3)/ sizeof(testString_3[0])); + receivedPacket.appendUint16(sizeof(testString_3) / sizeof(testString_3[0])); memMangService.rawDataMemorySubservice.dumpRawData(receivedPacket); REQUIRE(ServiceTests::hasOneMessage()); Message response = ServiceTests::get(0); CHECK(response.serviceType == 6); CHECK(response.messageType == 6); - REQUIRE(response.dataSize == 49); + REQUIRE(response.dataSize == 55); - CHECK(response.readEnum8() == MemoryManagementService::MemoryID::RAM); + CHECK(response.readEnum8() == MemoryManagementService::MemoryID::EXTERNAL); CHECK(response.readUint16() == 3); CHECK(response.readUint64() == reinterpret_cast<uint64_t >(testString_1)); readSize = response.readOctetString(checkString); - CHECK(readSize == sizeof(testString_1)/ sizeof(testString_1[0])); + checksum = response.readBits(16); + CHECK(readSize == sizeof(testString_1) / sizeof(testString_1[0])); CHECK(checkString[0] == 'F'); CHECK(checkString[1] == 'S'); CHECK(checkString[2] == 't'); CHECK(checkString[3] == 'r'); CHECK(checkString[4] == 'T'); CHECK(checkString[5] == '\0'); + CHECK(checksum == CRCHelper::calculateCRC(checkString, readSize)); CHECK(response.readUint64() == reinterpret_cast<uint64_t >(testString_2)); readSize = response.readOctetString(checkString); - CHECK(readSize == sizeof(testString_2)/ sizeof(testString_2[0])); + checksum = response.readBits(16); + CHECK(readSize == sizeof(testString_2) / sizeof(testString_2[0])); CHECK(checkString[0] == 'S'); CHECK(checkString[1] == 'e'); CHECK(checkString[2] == 'c'); @@ -78,10 +84,50 @@ TEST_CASE("TM[6,5]", "[service][st06]") { CHECK(checkString[5] == 'r'); CHECK(checkString[6] == 'T'); CHECK(checkString[7] == '\0'); + CHECK(checksum == CRCHelper::calculateCRC(checkString, readSize)); CHECK(response.readUint64() == reinterpret_cast<uint64_t >(testString_3)); readSize = response.readOctetString(checkString); - CHECK(readSize == sizeof(testString_3)/ sizeof(testString_3[0])); + checksum = response.readBits(16); + CHECK(readSize == sizeof(testString_3) / sizeof(testString_3[0])); CHECK(checkString[0] == 5); CHECK(checkString[1] == 8); + CHECK(checksum == CRCHelper::calculateCRC(checkString, readSize)); +} + +TEST_CASE("TM[6,9]", "[service][st06]") { + uint8_t testString_1[6] = "FStrT"; + uint8_t testString_2[8] = "SecStrT"; + uint16_t readSize = 0, checksum = 0; + + MemoryManagementService memMangService; + Message receivedPacket = Message(6, 9, Message::TC, 1); + receivedPacket.appendEnum8(MemoryManagementService::MemoryID::EXTERNAL); // Memory ID + receivedPacket.appendUint16(2); // Iteration count + receivedPacket.appendUint64(reinterpret_cast<uint64_t >(testString_1)); // Start address + receivedPacket.appendUint16(sizeof(testString_1) / sizeof(testString_1[0])); // Data read length + + receivedPacket.appendUint64(reinterpret_cast<uint64_t >(testString_2)); + receivedPacket.appendUint16(sizeof(testString_2) / sizeof(testString_2[0])); + memMangService.rawDataMemorySubservice.checkRawData(receivedPacket); + REQUIRE(ServiceTests::hasOneMessage()); + + Message response = ServiceTests::get(0); + CHECK(response.serviceType == 6); + CHECK(response.messageType == 10); + REQUIRE(response.dataSize == 27); + + CHECK(response.readEnum8() == MemoryManagementService::MemoryID::EXTERNAL); + CHECK(response.readUint16() == 2); + CHECK(response.readUint64() == reinterpret_cast<uint64_t >(testString_1)); + readSize = response.readUint16(); + checksum = response.readBits(16); + CHECK(readSize == sizeof(testString_1) / sizeof(testString_1[0])); + CHECK(checksum == CRCHelper::calculateCRC(testString_1, readSize)); + + CHECK(response.readUint64() == reinterpret_cast<uint64_t >(testString_2)); + readSize = response.readUint16(); + checksum = response.readBits(16); + CHECK(readSize == sizeof(testString_2) / sizeof(testString_2[0])); + CHECK(checksum == CRCHelper::calculateCRC(testString_2, readSize)); }