diff --git a/.gitmodules b/.gitmodules index 6bde354a..b0016647 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,9 +13,12 @@ [submodule "thirdparty/lwgps"] path = thirdparty/lwgps url = https://github.com/rmspacefish/lwgps.git -[submodule "fsfw_hal"] - path = fsfw_hal - url = https://egit.irs.uni-stuttgart.de/fsfw/fsfw-hal.git [submodule "generators/fsfwgen"] path = generators/fsfwgen url = https://egit.irs.uni-stuttgart.de/fsfw/fsfw-generators.git +[submodule "thirdparty/arcsec_star_tracker"] + path = thirdparty/arcsec_star_tracker + url = https://egit.irs.uni-stuttgart.de/eive/arcsec_star_tracker.git +[submodule "thirdparty/json"] + path = thirdparty/json + url = https://github.com/nlohmann/json.git diff --git a/CMakeLists.txt b/CMakeLists.txt index cbf38410..b7dbea87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,6 @@ ################################################################################ # CMake support for the EIVE OBSW # -# Developed in an effort to replace Make with a modern build system. -# # Author: R. Mueller ################################################################################ @@ -20,8 +18,10 @@ if(TGT_BSP MATCHES "arm/q7s") endif() option(ADD_ETL_LIB "Add ETL library" ON) -if(NOT OS_FSFW) - set(OS_FSFW host CACHE STRING "OS for the FSFW.") +option(ADD_JSON_LIB "Add JSON librara" ON) + +if(NOT FSFW_OSAL) + set(FSFW_OSAL host CACHE STRING "OS for the FSFW.") endif() if(TGT_BSP MATCHES "arm/raspberrypi" OR TGT_BSP MATCHES "arm/beagleboneblack") @@ -48,10 +48,11 @@ set(TARGET_NAME ${CMAKE_PROJECT_NAME}) set(LIB_FSFW_NAME fsfw) set(LIB_ETL_NAME etl) set(LIB_CSP_NAME libcsp) -set(LIB_FSFW_HAL_NAME fsfw_hal) set(LIB_LWGPS_NAME lwgps) +set(LIB_ARCSEC wire) set(THIRD_PARTY_FOLDER thirdparty) set(LIB_CXX_FS -lstdc++fs) +set(LIB_JSON_NAME nlohmann_json::nlohmann_json) # Set path names set(FSFW_PATH fsfw) @@ -65,6 +66,8 @@ set(FSFW_HAL_LIB_PATH fsfw_hal) set(CSP_LIB_PATH ${THIRD_PARTY_FOLDER}/libcsp) set(ETL_LIB_PATH ${THIRD_PARTY_FOLDER}/etl) set(LWGPS_LIB_PATH ${THIRD_PARTY_FOLDER}/lwgps) +set(ARCSEC_LIB_PATH ${THIRD_PARTY_FOLDER}/arcsec_star_tracker) +set(LIB_JSON_PATH ${THIRD_PARTY_FOLDER}/json) set(FSFW_WARNING_SHADOW_LOCAL_GCC OFF) set(ADD_LINUX_FILES False) @@ -75,8 +78,8 @@ include (${CMAKE_SCRIPT_PATH}/HardwareOsPreConfig.cmake) pre_source_hw_os_config() if(TGT_BSP) - if(${TGT_BSP} MATCHES "arm/q7s" OR ${TGT_BSP} MATCHES "arm/raspberrypi" - OR ${TGT_BSP} MATCHES "arm/beagleboneblack" + if(TGT_BSP MATCHES "arm/q7s" OR TGT_BSP MATCHES "arm/raspberrypi" + OR TGT_BSP MATCHES "arm/beagleboneblack" ) set(FSFW_CONFIG_PATH "linux/fsfwconfig") if(NOT Q7S_SIMPLE_MODE) @@ -140,6 +143,10 @@ if(ADD_LINUX_FILES) add_subdirectory(${LINUX_PATH}) endif() +if(ADD_JSON_LIB) + add_subdirectory(${LIB_JSON_PATH}) +endif() + add_subdirectory(${BSP_PATH}) add_subdirectory(${COMMON_PATH}) @@ -148,7 +155,7 @@ if(NOT Q7S_SIMPLE_MODE) add_subdirectory(${FSFW_PATH}) add_subdirectory(${MISSION_PATH}) add_subdirectory(${TEST_PATH}) - add_subdirectory(${FSFW_HAL_LIB_PATH}) + add_subdirectory(${ARCSEC_LIB_PATH}) endif() @@ -156,7 +163,7 @@ endif() # Post-Sources preparation ################################################################################ -set_property(CACHE OS_FSFW PROPERTY STRINGS host linux) +set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux) if(NOT Q7S_SIMPLE_MODE) # Add libraries for all sources. @@ -164,7 +171,7 @@ if(NOT Q7S_SIMPLE_MODE) ${LIB_FSFW_NAME} ${LIB_OS_NAME} ${LIB_LWGPS_NAME} - ${LIB_FSFW_HAL_NAME} + ${LIB_ARCSEC} ${LIB_CXX_FS} ) endif() @@ -181,11 +188,18 @@ if(ADD_CSP_LIB) ) endif() +if(ADD_JSON_LIB) + target_link_libraries(${TARGET_NAME} PRIVATE + ${LIB_JSON_NAME} + ) +endif() + # Add include paths for all sources. target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${FSFW_CONFIG_PATH} ${CMAKE_CURRENT_BINARY_DIR} + ${ARCSEC_LIB_PATH} ) @@ -243,7 +257,7 @@ endif() string(CONCAT POST_BUILD_COMMENT "Build directory: ${CMAKE_BINARY_DIR}\n" - "Target OSAL: ${OS_FSFW}\n" + "Target OSAL: ${FSFW_OSAL}\n" "Target Build Type: ${CMAKE_BUILD_TYPE}\n" "${TARGET_STRING}" ) diff --git a/README.md b/README.md index 356ccf75..26adb303 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ Target systems: * Datasheet at https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Arbeitsdaten/08_Used%20Components/Q7S&fileid=340648 * Also a lot of information about the Q7S can be found on the [Xiphos Traq Platform](https://trac2.xiphos.ca/eive-q7). Press on index to find all - relevant pages. + relevant pages. The most recent datasheet can be found + [here](https://trac2.xiphos.ca/manual/wiki/Q7RevB/UserManual). * Linux OS built with Yocto 2.5 * Linux Kernel https://github.com/XiphosSystemsCorp/linux-xlnx.git . EIVE version can be found [here](https://github.com/spacefisch/linux-xlnx) . Pre-compiled files can be @@ -591,6 +592,39 @@ Eclipse indexer. # Q7S Utilities and Troubleshooting +## Core commands + +Display currently running image: + +```sh +xsc_boot_copy +``` + +Rebooting currently running image: + +```sh +xsc_boot_copy -r +``` + +### Setting time on Q7S +Setting date and time (only timezone UTC available) +```` +timedatectl set-time 'YYYY-MM-DD HH:MM:SS' +```` +Setting UNIX time +```` +date +%s -s @1626337522 +```` +This only sets the system time and does not updating the time of the real time clock. To harmonize +the system time with the real time clock run +```` +hwclock -w +```` +Reading the real time clock +```` +hwclock --show +```` + ## pa3tool Host Tool The `pa3tool` is a host tool to interface with the ProASIC3 on the Q7S board. It was @@ -612,6 +646,40 @@ cat /tmp/test.txt For more useful combinations, see this [link](https://www.freecodecamp.org/news/the-cat-command-in-linux-how-to-create-a-text-file-with-cat-or-touch/). +## Using the scratch buffer of the ProASIC3 + +The ProASIC3 has a 1024 byte scratch buffer. The values in this scratch buffer will survive +a reboot, so this buffer can be used as an alternative to the SD cards to exchange information +between images or to store mission critical information. + +You can use `xsc_scratch --help` for more information. + +Write to scratch buffer: + +```sh +xsc_scratch write TEST "1" +``` + +Read from scratch buffer: + +```sh +xsc_scratch read TEST +``` + +Read all keys: + +```sh +xsc_scratch read + +``` + +Get fill count: + +```sh +xsc_scratch read | wc -c +``` + + ## Using `system` when debugging Please note that when using a `system` call in C++/C code and debugging, a new thread will be @@ -695,20 +763,6 @@ Reading data from CAN: candump can0 ```` -## Useful Q7S Linux Commands - -Display currently running image: - -```sh -xsc_boot_copy -``` - -Rebooting currently running image: - -```sh -xsc_boot_copy -r -``` - ## Preparation of a fresh rootfs and SD card This section summarizes important changes between a fresh rootfs and the current @@ -724,7 +778,7 @@ EIVE implementation ### SD Cards - Folder `bin` for binaries, for example the OBSW -- Folder `misc` for miscellaneous files +- Folder `misc` for miscellaneous files. Contains `ls` for directory listings - Folder `tc` for telecommands - Folder `tm` for telemetry - Folder `xdi` for XDI components (e.g. for firmware or device tree updates) diff --git a/bsp_hosted/fsfwconfig/devices/powerSwitcherList.h b/bsp_hosted/fsfwconfig/devices/powerSwitcherList.h index 09bdf568..cacd23a1 100644 --- a/bsp_hosted/fsfwconfig/devices/powerSwitcherList.h +++ b/bsp_hosted/fsfwconfig/devices/powerSwitcherList.h @@ -33,7 +33,7 @@ namespace pcduSwitches { static const uint8_t INIT_STATE_Q7S = ON; static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH1 = OFF; static const uint8_t INIT_STATE_RW = OFF; -#if TE0720 == 1 +#if BOARD_TE0720 == 1 /* Because the TE0720 is not connected to the PCDU, this switch is always on */ static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = ON; #else diff --git a/bsp_linux_board/ObjectFactory.cpp b/bsp_linux_board/ObjectFactory.cpp index c5e12868..4f7dd59a 100644 --- a/bsp_linux_board/ObjectFactory.cpp +++ b/bsp_linux_board/ObjectFactory.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include #include #include "ObjectFactory.h" @@ -31,12 +31,12 @@ #include "fsfw/osal/common/UdpTmTcBridge.h" #include "fsfw/osal/common/UdpTcPollingTask.h" -#include "fsfw_hal/devicehandlers/GyroL3GD20Handler.h" -#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h" -#include "fsfw_hal/linux/rpi/GpioRPi.h" -#include "fsfw_hal/common/gpio/GpioCookie.h" -#include "fsfw_hal/linux/spi/SpiCookie.h" -#include "fsfw_hal/linux/spi/SpiComIF.h" +#include "fsfw/hal/devicehandlers/GyroL3GD20Handler.h" +#include "fsfw/hal/linux/gpio/LinuxLibgpioIF.h" +#include "fsfw/hal/linux/rpi/GpioRPi.h" +#include "fsfw/hal/common/gpio/GpioCookie.h" +#include "fsfw/hal/linux/spi/SpiCookie.h" +#include "fsfw/hal/linux/spi/SpiComIF.h" void Factory::setStaticFrameworkObjectIds() { PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR; diff --git a/bsp_q7s/boardconfig/q7sConfig.h.in b/bsp_q7s/boardconfig/q7sConfig.h.in index 11dec25c..2fd52eb7 100644 --- a/bsp_q7s/boardconfig/q7sConfig.h.in +++ b/bsp_q7s/boardconfig/q7sConfig.h.in @@ -24,6 +24,8 @@ #define Q7S_ADD_SPI_TEST 0 #endif +#define Q7S_ADD_SYRLINKS_HANDLER 1 + #define Q7S_SIMPLE_ADD_FILE_SYSTEM_TEST 0 namespace config { diff --git a/bsp_q7s/boardtest/Q7STestTask.cpp b/bsp_q7s/boardtest/Q7STestTask.cpp index a1470b79..4e763641 100644 --- a/bsp_q7s/boardtest/Q7STestTask.cpp +++ b/bsp_q7s/boardtest/Q7STestTask.cpp @@ -1,9 +1,16 @@ +#include +#include #include "Q7STestTask.h" +#include "bsp_q7s/memory/SdCardManager.h" +#include "bsp_q7s/memory/scratchApi.h" + #include "fsfw/timemanager/Stopwatch.h" #include "fsfw/tasks/TaskFactory.h" -#include "bsp_q7s/memory/scratchApi.h" +#include "test/DummyParameter.h" + +#include #include #include @@ -13,12 +20,16 @@ Q7STestTask::Q7STestTask(object_id_t objectId): TestTask(objectId) { } ReturnValue_t Q7STestTask::performOneShotAction() { - //sdCardTests(); - testScratchApi(); + //testSdCard(); + //testScratchApi(); + //testJsonLibDirect(); + //testDummyParams(); + FsOpCodes opCode = FsOpCodes::ATTEMPT_DIR_REMOVAL_NON_EMPTY; + testFileSystemHandlerDirect(opCode); return TestTask::performOneShotAction(); } -void Q7STestTask::sdCardTests() { +void Q7STestTask::testSdCard() { using namespace std; Stopwatch stopwatch; int result = std::system("q7hw sd info all > /tmp/sd_status.txt"); @@ -61,7 +72,183 @@ void Q7STestTask::testScratchApi() { } int number = 0; result = scratch::readNumber("TEST", number); + sif::info << "Q7STestTask::testScratchApi: Value for key \"TEST\": " << number << std::endl; if(result != HasReturnvaluesIF::RETURN_OK) { sif::debug << "Q7STestTask::scratchApiTest: Reading number failed" << std::endl; } + + result = scratch::writeString("TEST2", "halloWelt"); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::debug << "Q7STestTask::scratchApiTest: Writing string failed" << std::endl; + } + std::string string; + result = scratch::readString("TEST2", string); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::debug << "Q7STestTask::scratchApiTest: Reading number failed" << std::endl; + } + sif::info << "Q7STestTask::testScratchApi: Value for key \"TEST2\": " << string << std::endl; + + result = scratch::clearValue("TEST"); + result = scratch::clearValue("TEST2"); +} + +void Q7STestTask::testJsonLibDirect() { + Stopwatch stopwatch; + // for convenience + using json = nlohmann::json; + json helloTest; + // add a number that is stored as double (note the implicit conversion of j to an object) + helloTest["pi"] = 3.141; + std::string mntPrefix = SdCardManager::instance()->getCurrentMountPrefix(); + std::string fileName = mntPrefix + "/pretty.json"; + std::ofstream o(fileName); + o << std::setw(4) << helloTest << std::endl; +} + +void Q7STestTask::testDummyParams() { + std::string mntPrefix = SdCardManager::instance()->getCurrentMountPrefix(); + DummyParameter param(mntPrefix, "dummy_json.txt"); + param.printKeys(); + param.print(); + if(not param.getJsonFileExists()) { + param.writeJsonFile(); + } + + ReturnValue_t result = param.readJsonFile(); + if(result != HasReturnvaluesIF::RETURN_OK) { + + } + + param.setValue(DummyParameter::DUMMY_KEY_PARAM_1, 3); + param.setValue(DummyParameter::DUMMY_KEY_PARAM_2, "blirb"); + + param.writeJsonFile(); + param.print(); + + int test = param.getValue(DummyParameter::DUMMY_KEY_PARAM_1); + std::string test2 = param.getValue(DummyParameter::DUMMY_KEY_PARAM_2); + sif::info << "Test value (3 expected): " << test << std::endl; + sif::info << "Test value 2 (\"blirb\" expected): " << test2 << std::endl; +} + +void Q7STestTask::testFileSystemHandlerDirect(FsOpCodes opCode) { + auto fsHandler = ObjectManager::instance()-> + get(objects::FILE_SYSTEM_HANDLER); + if(fsHandler == nullptr) { + sif::warning << "Q7STestTask::testFileSystemHandlerDirect: No FS handler running.." + << std::endl; + } + FileSystemHandler::FsCommandCfg cfg = {}; + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + + // Lambda for common code + auto createNonEmptyTmpDir = [&]() { + if(not std::filesystem::exists("/tmp/test")) { + result = fsHandler->createDirectory("/tmp/test", &cfg); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + // Creating sample files + sif::info << "Creating sample files in directory" << std::endl; + result = fsHandler->createFile("/tmp/test", "test1.txt", nullptr, 0, &cfg); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = fsHandler->createFile("/tmp/test", "test2.txt", nullptr, 0, &cfg); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return result; + }; + + + switch(opCode) { + case(FsOpCodes::CREATE_EMPTY_FILE_IN_TMP): { + // No mount prefix, cause file is created in tmp + cfg.useMountPrefix = false; + sif::info << "Creating empty file in /tmp folder" << std::endl; + // Do not delete file, user can check existence in shell + fsHandler->createFile("/tmp", "test.txt", nullptr, 0, &cfg); + break; + } + case(FsOpCodes::REMOVE_TMP_FILE): { + sif::info << "Deleting /tmp/test.txt sample file" << std::endl; + // No mount prefix, cause file is created in tmp + cfg.useMountPrefix = false; + if(not std::filesystem::exists("/tmp/test.txt")) { + // Creating sample file + sif::info << "Creating sample file /tmp/test.txt to delete" << std::endl; + fsHandler->createFile("/tmp", "test.txt", nullptr, 0, &cfg); + } + result = fsHandler->removeFile("/tmp", "test.txt", &cfg); + if(result == HasReturnvaluesIF::RETURN_OK) { + sif::info << "File removed successfully" << std::endl; + } + else { + sif::warning << "File removal failed!" << std::endl; + } + break; + } + case(FsOpCodes::CREATE_DIR_IN_TMP): { + // No mount prefix, cause file is created in tmp + cfg.useMountPrefix = false; + sif::info << "Creating empty file in /tmp folder" << std::endl; + // Do not delete file, user can check existence in shell + ReturnValue_t result = fsHandler->createDirectory("/tmp/test", &cfg); + if(result == HasReturnvaluesIF::RETURN_OK) { + sif::info << "Directory created successfully" << std::endl; + } + else { + sif::warning << "Directory creation failed!" << std::endl; + } + break; + } + case(FsOpCodes::REMOVE_EMPTY_DIR_IN_TMP): { + // No mount prefix, cause file is created in tmp + cfg.useMountPrefix = false; + if(not std::filesystem::exists("/tmp/test")) { + result = fsHandler->createDirectory("/tmp/test", &cfg); + } + else { + // Delete any leftover files to regular dir removal works + std::remove("/tmp/test/*"); + } + result = fsHandler->removeDirectory("/tmp/test", false, &cfg); + if(result == HasReturnvaluesIF::RETURN_OK) { + sif::info << "Directory removed successfully" << std::endl; + } + else { + sif::warning << "Directory removal failed!" << std::endl; + } + break; + } + case(FsOpCodes::REMOVE_FILLED_DIR_IN_TMP): { + result = createNonEmptyTmpDir(); + if(result != HasReturnvaluesIF::RETURN_OK) { + return; + } + result = fsHandler->removeDirectory("/tmp/test", true, &cfg); + if(result == HasReturnvaluesIF::RETURN_OK) { + sif::info << "Directory removed recursively successfully" << std::endl; + } + else { + sif::warning << "Recursive directory removal failed!" << std::endl; + } + break; + } + case(FsOpCodes::ATTEMPT_DIR_REMOVAL_NON_EMPTY): { + result = createNonEmptyTmpDir(); + if(result != HasReturnvaluesIF::RETURN_OK) { + return; + } + result = fsHandler->removeDirectory("/tmp/test", false, &cfg); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::info << "Directory removal attempt failed as expected" << std::endl; + } + else { + sif::warning << "Directory removal worked when it should not have!" << std::endl; + } + } + } } diff --git a/bsp_q7s/boardtest/Q7STestTask.h b/bsp_q7s/boardtest/Q7STestTask.h index 664a8fa2..a14d8428 100644 --- a/bsp_q7s/boardtest/Q7STestTask.h +++ b/bsp_q7s/boardtest/Q7STestTask.h @@ -9,11 +9,22 @@ public: private: ReturnValue_t performOneShotAction() override; - void sdCardTests(); + void testSdCard(); void fileTests(); void testScratchApi(); + void testJsonLibDirect(); + void testDummyParams(); + enum FsOpCodes { + CREATE_EMPTY_FILE_IN_TMP, + REMOVE_TMP_FILE, + CREATE_DIR_IN_TMP, + REMOVE_EMPTY_DIR_IN_TMP, + ATTEMPT_DIR_REMOVAL_NON_EMPTY, + REMOVE_FILLED_DIR_IN_TMP, + }; + void testFileSystemHandlerDirect(FsOpCodes opCode); }; diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index c4863260..55cd0252 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1,8 +1,13 @@ #include "CoreController.h" #include "q7sConfig.h" +#include "fsfw/serviceinterface/ServiceInterface.h" + +#include "../memory/scratchApi.h" #include "../memory/SdCardManager.h" +#include + CoreController::CoreController(object_id_t objectId): ExtendedControllerBase(objectId, objects::NO_OBJECT, 5) { } @@ -24,7 +29,24 @@ LocalPoolDataSetBase* CoreController::getDataSetHandle(sid_t sid) { } ReturnValue_t CoreController::initialize() { - return sdCardInit(); + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + try { + result = sdCardInit(); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "CoreController::initialize: SD card init failed" << std::endl; + } + } + catch(const std::filesystem::filesystem_error& e) { + sif::error << "CoreController::initialize: sdCardInit failed with exception " << e.what() + << std::endl; + } + + result = scratch::writeNumber(scratch::ALLOC_FAILURE_COUNT, 0); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "CoreController::initialize: Setting up alloc failure " + "count failed" << std::endl; + } + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t CoreController::checkModeCommand(Mode_t mode, Submode_t submode, @@ -38,7 +60,9 @@ ReturnValue_t CoreController::sdCardInit() { return HasReturnvaluesIF::RETURN_OK; #else SdCardManager* sdcMan = SdCardManager::instance(); - + if(sdcMan == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } // Create update status file ReturnValue_t result = sdcMan->updateSdCardStateFile(); if(result != HasReturnvaluesIF::RETURN_OK) { @@ -46,93 +70,14 @@ ReturnValue_t CoreController::sdCardInit() { << std::endl; } - auto sdStatus = std::pair(sd::SdStatus::OFF, sd::SdStatus::OFF); - result = sdcMan->getSdCardActiveStatus(sdStatus); + auto statusPair = SdCardManager::SdStatusPair(sd::SdStatus::OFF, sd::SdStatus::OFF); + result = sdcMan->getSdCardActiveStatus(statusPair); if(result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "Getting SD card activity status failed" << std::endl; } - // Use a lambda to avoid duplicate code - auto setUpSdCard = [&](sd::SdCard sdCard, sd::SdStatus status, std::string sdString) { - std::string mountString; - if(sdCard == sd::SdCard::SLOT_0) { - mountString = SdCardManager::SD_0_MOUNT_POINT; - } - else { - mountString = SdCardManager::SD_1_MOUNT_POINT; - } - - if(status == sd::SdStatus::OFF) { - sif::info << "Switching on and mounting SD card " << sdString << " at " << - mountString << std::endl; - return sdcMan->switchOnSdCard(sdCard, true, &sdStatus); - } - else if(status == sd::SdStatus::ON) { - sif::info << "Mounting SD card " << sdString << " at " << mountString << std::endl; - return sdcMan->mountSdCard(sdCard); - } - else { - sif::info << "SD card " << sdString << " already on and mounted at " << - mountString << std::endl; - return SdCardManager::ALREADY_MOUNTED; - } - }; - #if Q7S_SD_CARD_CONFIG == Q7S_SD_COLD_REDUNDANT - sd::SdCard preferredSdCard = sd::SdCard::SLOT_0; - result = sdcMan->getPreferredSdCard(preferredSdCard); - if(result != HasReturnvaluesIF::RETURN_OK) { - sif::warning << "Could not get preferred SD card information from the scratch buffer" - << std::endl; - } - std::string preferredString; - sd::SdStatus preferredStatus = sd::SdStatus::OFF; - - sd::SdStatus otherStatus = sd::SdStatus::OFF; - std::string otherString; - sd::SdCard otherSdc = sd::SdCard::SLOT_0; - - if(preferredSdCard == sd::SdCard::SLOT_0) { - preferredStatus = sdStatus.first; - preferredString = "0"; - otherSdc = sd::SdCard::SLOT_1; - otherStatus = sdStatus.second; - otherString = "1"; - } - else { - preferredString = "1"; - preferredStatus = sdStatus.second; - otherStatus = sdStatus.first; - otherSdc = sd::SdCard::SLOT_0; - otherString = "0"; - } - - sif::info << "Cold redundant SD card configuration, preferred SD card " << - preferredString << std::endl; - - result = setUpSdCard(preferredSdCard, preferredStatus, preferredString); - if(result != SdCardManager::ALREADY_MOUNTED and result != HasReturnvaluesIF::RETURN_OK) { - sif::warning << "Setting up preferred card " << otherString << - " in cold redundant mode failed" << std::endl; - // Try other SD card and mark set up operation as failed - setUpSdCard(otherSdc, otherStatus, otherString); - result = HasReturnvaluesIF::RETURN_FAILED; - } - - if(result != HasReturnvaluesIF::RETURN_FAILED and otherStatus != sd::SdStatus::OFF) { - sif::info << "Switching off secondary SD card " << otherString << std::endl; - // Switch off other SD card in cold redundant mode if setting up preferred one walked - // without issues - result = sdcMan->switchOffSdCard(otherSdc, otherStatus, &sdStatus); - if(result != HasReturnvaluesIF::RETURN_OK and result != SdCardManager::ALREADY_OFF) { - sif::warning << "Switching off secondary SD card " << otherString << - " in cold redundant mode failed" << std::endl; - } - } - - // Update status file - sdcMan->updateSdCardStateFile(); - return HasReturnvaluesIF::RETURN_OK; + return sdCardColdRedundantInit(sdcMan, statusPair); #elif Q7S_SD_CARD_CONFIG == Q7S_SD_HOT_REDUNDANT sif::info << "Hot redundant SD card configuration" << std::endl; @@ -146,3 +91,166 @@ ReturnValue_t CoreController::sdCardInit() { #endif /* Q7S_SD_CARD_CONFIG != Q7S_SD_NONE */ } + +ReturnValue_t CoreController::sdCardSetup(SdCardManager& sdcMan, + SdCardManager::SdStatusPair& statusPair,sd::SdCard sdCard, sd::SdStatus status, + std::string sdString) { + std::string mountString; + if(sdCard == sd::SdCard::SLOT_0) { + mountString = SdCardManager::SD_0_MOUNT_POINT; + } + else { + mountString = SdCardManager::SD_1_MOUNT_POINT; + } + + if(status == sd::SdStatus::OFF) { + sif::info << "Switching on and mounting SD card " << sdString << " at " << + mountString << std::endl; + return sdcMan.switchOnSdCard(sdCard, true, &statusPair); + } + else if(status == sd::SdStatus::ON) { + sif::info << "Mounting SD card " << sdString << " at " << mountString << std::endl; + return sdcMan.mountSdCard(sdCard); + } + else { + if(std::filesystem::exists(mountString)) { + sif::info << "SD card " << sdString << " already on and mounted at " << + mountString << std::endl; + return SdCardManager::ALREADY_MOUNTED; + } + sif::error << "SD card mounted but expected mount point " << mountString << " not found!" + << std::endl; + return SdCardManager::MOUNT_ERROR; + } +} + +ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t *data, size_t size) { + switch(actionId) { + case(LIST_DIRECTORY_INTO_FILE): { + // TODO: Packet definition for clean deserialization + // 2 bytes for a and R flag, at least 5 bytes for minimum valid path /tmp with + // null termination, at least 7 bytes for minimum target file name /tmp/a with + // null termination. + if(size < 14) { + return HasActionsIF::INVALID_PARAMETERS; + } + // We could also make -l optional, but I can't think of a reason why to not use -l.. + + // This flag specifies to run ls with -a + bool aFlag = data[0]; + data += 1; + // This flag specifies to run ls with -R + bool RFlag = data[1]; + data += 1; + + size_t remainingSize = size - 2; + // One larger for null termination, which prevents undefined behaviour if the sent + // strings are not 0 terminated properly + std::vector repoAndTargetFileBuffer(remainingSize + 1, 0); + std::memcpy(repoAndTargetFileBuffer.data(), data, remainingSize); + const char* currentCharPtr = reinterpret_cast(repoAndTargetFileBuffer.data()); + // Full target file name + std::string repoName(currentCharPtr); + size_t repoLength = repoName.length(); + // The other string needs to be at least one letter plus NULL termination to be valid at all + // The first string also needs to be NULL terminated, but the termination is not included + // in the string length, so this is subtracted from the remaining size as well + if(repoLength > remainingSize - 3) { + return HasActionsIF::INVALID_PARAMETERS; + } + // The file length will not include the NULL termination, so we skip it + currentCharPtr += repoLength + 1; + std::string targetFileName(currentCharPtr); + std::ostringstream oss; + oss << "ls -l"; + if(aFlag) { + oss << "a"; + } + if(RFlag) { + oss << "R"; + } + oss << " " << repoName << " > " << targetFileName; + std::system(oss.str().c_str()); + return HasReturnvaluesIF::RETURN_OK; + } + default: { + return HasActionsIF::INVALID_ACTION_ID; + } + } +} + +ReturnValue_t CoreController::sdCardColdRedundantInit(SdCardManager* sdcMan, + SdCardManager::SdStatusPair& statusPair) { + sd::SdCard preferredSdCard = sd::SdCard::SLOT_0; + ReturnValue_t result = sdcMan->getPreferredSdCard(preferredSdCard); + if(result != HasReturnvaluesIF::RETURN_OK) { + if(result == scratch::KEY_NOT_FOUND) { + sif::warning << "CoreController::sdCardInit: " + "Preferred SD card not set. Setting to 0" << std::endl; + sdcMan->setPreferredSdCard(preferredSdCard); + } + else { + sif::warning << "CoreController::sdCardInit: Could not get preferred SD card" + "information from the scratch buffer" << std::endl; + } + } + std::string preferredString; + sd::SdStatus preferredStatus = sd::SdStatus::OFF; + + sd::SdStatus otherStatus = sd::SdStatus::OFF; + std::string otherString; + sd::SdCard otherSdc = sd::SdCard::SLOT_0; + + if(preferredSdCard == sd::SdCard::SLOT_0) { + preferredStatus = statusPair.first; + preferredString = "0"; + otherSdc = sd::SdCard::SLOT_1; + otherStatus = statusPair.second; + otherString = "1"; + } + else { + preferredString = "1"; + preferredStatus = statusPair.second; + otherStatus = statusPair.first; + otherSdc = sd::SdCard::SLOT_0; + otherString = "0"; + } + + sif::info << "Cold redundant SD card configuration, preferred SD card " << + preferredString << std::endl; + + result = sdCardSetup(*sdcMan, statusPair, preferredSdCard, preferredStatus, preferredString); + if(result != SdCardManager::ALREADY_MOUNTED and result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "Setting up preferred card " << otherString << + " in cold redundant mode failed" << std::endl; + // Try other SD card and mark set up operation as failed + sdCardSetup(*sdcMan, statusPair, preferredSdCard, preferredStatus, preferredString); + result = HasReturnvaluesIF::RETURN_FAILED; + } + + if(result != HasReturnvaluesIF::RETURN_FAILED and otherStatus != sd::SdStatus::OFF) { + sif::info << "Switching off secondary SD card " << otherString << std::endl; + // Switch off other SD card in cold redundant mode if setting up preferred one walked + // without issues + result = sdcMan->switchOffSdCard(otherSdc, otherStatus, &statusPair); + if(result != HasReturnvaluesIF::RETURN_OK and result != SdCardManager::ALREADY_OFF) { + sif::warning << "Switching off secondary SD card " << otherString << + " in cold redundant mode failed" << std::endl; + } + } + + // Update status file + sdcMan->updateSdCardStateFile(); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t CoreController::incrementAllocationFailureCount() { + uint32_t count = 0; + ReturnValue_t result = scratch::readNumber(scratch::ALLOC_FAILURE_COUNT, count); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + count++; + return scratch::writeNumber(scratch::ALLOC_FAILURE_COUNT, count); +} diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 940a9097..3e7e108a 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -2,15 +2,29 @@ #define BSP_Q7S_CORE_CORECONTROLLER_H_ #include "fsfw/controller/ExtendedControllerBase.h" +#include "bsp_q7s/memory/SdCardManager.h" + +#include "events/subsystemIdRanges.h" class CoreController: public ExtendedControllerBase { public: + static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0; + + static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE; + + static constexpr Event ALLOC_FAILURE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM); + CoreController(object_id_t objectId); ReturnValue_t initialize() override; + ReturnValue_t executeAction(ActionId_t actionId, + MessageQueueId_t commandedBy, const uint8_t *data, size_t size) override; + ReturnValue_t handleCommandMessage(CommandMessage *message) override; void performControlOperation() override; + + static ReturnValue_t incrementAllocationFailureCount(); private: ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) override; @@ -19,6 +33,10 @@ private: uint32_t *msToReachTheMode); ReturnValue_t sdCardInit(); + ReturnValue_t sdCardSetup(SdCardManager& sdcMan, SdCardManager::SdStatusPair& statusPair, + sd::SdCard sdCard, sd::SdStatus status, std::string sdString); + ReturnValue_t sdCardColdRedundantInit(SdCardManager* sdcMan, + SdCardManager::SdStatusPair& statusPair); }; diff --git a/bsp_q7s/core/InitMission.cpp b/bsp_q7s/core/InitMission.cpp index 2bc334b9..712cf9c8 100644 --- a/bsp_q7s/core/InitMission.cpp +++ b/bsp_q7s/core/InitMission.cpp @@ -3,20 +3,22 @@ #include "OBSWConfig.h" #include "pollingsequence/pollingSequenceFactory.h" -#include +#include "mission/utility/InitMission.h" -#include -#include -#include -#include -#include -#include -#include +#include "fsfw/platform.h" +#include "fsfw/objectmanager/ObjectManagerIF.h" +#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/serviceinterface/ServiceInterfaceStream.h" +#include "fsfw/objectmanager/ObjectManager.h" +#include "fsfw/tasks/FixedTimeslotTaskIF.h" +#include "fsfw/tasks/PeriodicTaskIF.h" +#include "fsfw/tasks/TaskFactory.h" #include +#include /* This is configured for linux without CR */ -#ifdef LINUX +#ifdef PLATFORM_UNIX ServiceInterfaceStream sif::debug("DEBUG"); ServiceInterfaceStream sif::info("INFO"); ServiceInterfaceStream sif::warning("WARNING"); @@ -93,6 +95,15 @@ void initmission::initTasks() { initmission::printAddObjectError("UDP_POLLING", objects::UDP_POLLING_TASK); } + // FS task, task interval does not matter because it runs in permanent loop, priority low + // because it is a non-essential background task + PeriodicTaskIF* fsTask = factory->createPeriodicTask( + "FILE_SYSTEM_TASK", 25, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc); + result = fsTask->addComponent(objects::FILE_SYSTEM_HANDLER); + if(result != HasReturnvaluesIF::RETURN_OK) { + initmission::printAddObjectError("FILE_SYSTEM_TASK", objects::FILE_SYSTEM_HANDLER); + } + #if TEST_CCSDS_BRIDGE == 1 PeriodicTaskIF* ptmeTestTask = factory->createPeriodicTask( "PTME_TEST", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc); @@ -102,15 +113,113 @@ void initmission::initTasks() { } #endif + std::vector pusTasks; + createPusTasks(*factory, missedDeadlineFunc, pusTasks); + std::vector pstTasks; + createPstTasks(*factory, missedDeadlineFunc, pstTasks); + std::vector testTasks; + createTestTasks(*factory, missedDeadlineFunc, testTasks); + + auto taskStarter = [](std::vector& taskVector, std::string name) { + for(const auto& task: taskVector) { + if(task != nullptr) { + task->startTask(); + } + else { + sif::error << "Task in vector " << name << " is invalid!" << std::endl; + } + } + }; + + sif::info << "Starting tasks.." << std::endl; + tmTcDistributor->startTask(); + udpBridgeTask->startTask(); + udpPollingTask->startTask(); + coreController->startTask(); + + taskStarter(pstTasks, "PST task vector"); + taskStarter(pusTasks, "PUS task vector"); +#if OBSW_ADD_TEST_CODE == 1 + taskStarter(testTasks, "Test task vector"); +#endif + +#if TEST_CCSDS_BRIDGE == 1 + ptmeTestTask->startTask(); +#endif + fsTask->startTask(); + + sif::info << "Tasks started.." << std::endl; +} + +void initmission::createPstTasks(TaskFactory& factory, + TaskDeadlineMissedFunction missedDeadlineFunc, std::vector &taskVec) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; +#if BOARD_TE0720 == 0 + /* Polling Sequence Table Default */ +#if Q7S_ADD_SPI_TEST == 0 + FixedTimeslotTaskIF* spiPst = factory.createFixedTimeslotTask( + "PST_TASK_DEFAULT", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, + missedDeadlineFunc); + result = pst::pstSpi(spiPst); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; + } + taskVec.push_back(spiPst); +#endif + + FixedTimeslotTaskIF* uartPst = factory.createFixedTimeslotTask( + "UART_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); + result = pst::pstUart(uartPst); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; + } + taskVec.push_back(uartPst); + FixedTimeslotTaskIF* gpioPst = factory.createFixedTimeslotTask( + "GPIO_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); + result = pst::pstGpio(gpioPst); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; + } + taskVec.push_back(gpioPst); + FixedTimeslotTaskIF* i2cPst = factory.createFixedTimeslotTask( + "I2C_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); + result = pst::pstI2c(i2cPst); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; + } + + FixedTimeslotTaskIF* gomSpacePstTask = factory.createFixedTimeslotTask( + "GS_PST_TASK", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 1.0, missedDeadlineFunc); + result = pst::pstGompaceCan(gomSpacePstTask); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "InitMission::initTasks: GomSpace PST initialization failed!" << std::endl; + } + taskVec.push_back(i2cPst); +#else /* BOARD_TE7020 == 0 */ + FixedTimeslotTaskIF * pollingSequenceTaskTE0720 = factory->createFixedTimeslotTask( + "PST_TASK_TE0720", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE * 8, 3.0, + missedDeadlineFunc); + result = pst::pollingSequenceTE0720(pollingSequenceTaskTE0720); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "InitMission::initTasks: Creating TE0720 PST failed!" << std::endl; + } + taskVec.push_back(pollingSequenceTaskTE0720); +#endif /* BOARD_TE7020 == 1 */ +} + +void initmission::createPusTasks(TaskFactory &factory, + TaskDeadlineMissedFunction missedDeadlineFunc, std::vector &taskVec) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; /* PUS Services */ - PeriodicTaskIF* pusVerification = factory->createPeriodicTask( + PeriodicTaskIF* pusVerification = factory.createPeriodicTask( "PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc); result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION); if(result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("PUS_VERIF", objects::PUS_SERVICE_1_VERIFICATION); } + taskVec.push_back(pusVerification); - PeriodicTaskIF* pusEvents = factory->createPeriodicTask( + PeriodicTaskIF* pusEvents = factory.createPeriodicTask( "PUS_EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc); result = pusEvents->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING); if(result != HasReturnvaluesIF::RETURN_OK) { @@ -120,8 +229,9 @@ void initmission::initTasks() { if(result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("PUS_MGMT", objects::EVENT_MANAGER); } + taskVec.push_back(pusEvents); - PeriodicTaskIF* pusHighPrio = factory->createPeriodicTask( + PeriodicTaskIF* pusHighPrio = factory.createPeriodicTask( "PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc); result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS); if(result != HasReturnvaluesIF::RETURN_OK) { @@ -131,8 +241,9 @@ void initmission::initTasks() { if(result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("PUS_9", objects::PUS_SERVICE_9_TIME_MGMT); } + taskVec.push_back(pusHighPrio); - PeriodicTaskIF* pusMedPrio = factory->createPeriodicTask( + PeriodicTaskIF* pusMedPrio = factory.createPeriodicTask( "PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc); result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT); if(result != HasReturnvaluesIF::RETURN_OK) { @@ -150,8 +261,9 @@ void initmission::initTasks() { if(result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("PUS_20", objects::PUS_SERVICE_20_PARAMETERS); } + taskVec.push_back(pusMedPrio); - PeriodicTaskIF* pusLowPrio = factory->createPeriodicTask( + PeriodicTaskIF* pusLowPrio = factory.createPeriodicTask( "PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc); result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST); if(result != HasReturnvaluesIF::RETURN_OK) { @@ -161,58 +273,13 @@ void initmission::initTasks() { if(result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("ERROR_REPORTER", objects::INTERNAL_ERROR_REPORTER); } + taskVec.push_back(pusLowPrio); +} -#if TE0720 == 0 - //TODO: Add handling of missed deadlines - /* Polling Sequence Table Default */ -#if Q7S_ADD_SPI_TEST == 0 - FixedTimeslotTaskIF* spiPst = factory->createFixedTimeslotTask( - "PST_TASK_DEFAULT", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, - missedDeadlineFunc); - result = pst::pstSpi(spiPst); - if (result != HasReturnvaluesIF::RETURN_OK) { - sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; - } -#endif - - FixedTimeslotTaskIF* uartPst = factory->createFixedTimeslotTask( - "UART_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); - result = pst::pstUart(uartPst); - if (result != HasReturnvaluesIF::RETURN_OK) { - sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; - } - FixedTimeslotTaskIF* gpioPst = factory->createFixedTimeslotTask( - "GPIO_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); - result = pst::pstGpio(gpioPst); - if (result != HasReturnvaluesIF::RETURN_OK) { - sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; - } - FixedTimeslotTaskIF* i2cPst = factory->createFixedTimeslotTask( - "I2C_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0, missedDeadlineFunc); - result = pst::pstI2c(i2cPst); - if (result != HasReturnvaluesIF::RETURN_OK) { - sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl; - } - - FixedTimeslotTaskIF* gomSpacePstTask = factory->createFixedTimeslotTask( - "GS_PST_TASK", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 1.0, missedDeadlineFunc); - result = pst::pstGompaceCan(gomSpacePstTask); - if(result != HasReturnvaluesIF::RETURN_OK) { - sif::error << "InitMission::initTasks: GomSpace PST initialization failed!" << std::endl; - } - -#else /* TE7020 == 0 */ - FixedTimeslotTaskIF * pollingSequenceTaskTE0720 = factory->createFixedTimeslotTask( - "PST_TASK_TE0720", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE * 8, 3.0, - missedDeadlineFunc); - result = pst::pollingSequenceTE0720(pollingSequenceTaskTE0720); - if (result != HasReturnvaluesIF::RETURN_OK) { - sif::error << "InitMission::initTasks: Creating TE0720 PST failed!" << std::endl; - } -#endif /* TE7020 == 1 */ - -#if OBSW_ADD_TEST_CODE == 1 - PeriodicTaskIF* testTask = factory->createPeriodicTask( +void initmission::createTestTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc, + std::vector& taskVec) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + PeriodicTaskIF* testTask = factory.createPeriodicTask( "TEST_TASK", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1, missedDeadlineFunc); result = testTask->addComponent(objects::TEST_TASK); if(result != HasReturnvaluesIF::RETURN_OK) { @@ -225,45 +292,11 @@ void initmission::initTasks() { initmission::printAddObjectError("SPI_TEST", objects::SPI_TEST); } #endif -#endif /* OBSW_ADD_TEST_CODE == 1 */ -#if TE0720 == 1 && TEST_LIBGPIOD == 1 +#if BOARD_TE0720 == 1 && TEST_LIBGPIOD == 1 result = testTask->addComponent(objects::LIBGPIOD_TEST); if(result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("GPIOD_TEST", objects::LIBGPIOD_TEST); } -#endif /* TE0720 == 1 && TEST_LIBGPIOD == 1 */ - - sif::info << "Starting tasks.." << std::endl; - tmTcDistributor->startTask(); - udpBridgeTask->startTask(); - udpPollingTask->startTask(); - coreController->startTask(); - -#if TE0720 == 0 - uartPst->startTask(); - gpioPst->startTask(); - i2cPst->startTask(); -#if Q7S_ADD_SPI_TEST == 0 - gomSpacePstTask->startTask(); - spiPst->startTask(); -#endif /* Q7S_ADD_SPI_TEST == 0 */ - -#elif TE0720 == 1 && Q7S_ADD_SPI_TEST == 0 - pollingSequenceTaskTE0720->startTask(); -#endif - - pusVerification->startTask(); - pusEvents->startTask(); - pusHighPrio->startTask(); - pusMedPrio->startTask(); - pusLowPrio->startTask(); - -#if OBSW_ADD_TEST_CODE == 1 - testTask->startTask(); -#endif - -#if TEST_CCSDS_BRIDGE == 1 - ptmeTestTask->startTask(); -#endif - sif::info << "Tasks started.." << std::endl; +#endif /* BOARD_TE0720 == 1 && TEST_LIBGPIOD == 1 */ + taskVec.push_back(testTask); } diff --git a/bsp_q7s/core/InitMission.h b/bsp_q7s/core/InitMission.h index 568b26b5..ffdfc11c 100644 --- a/bsp_q7s/core/InitMission.h +++ b/bsp_q7s/core/InitMission.h @@ -1,9 +1,22 @@ #ifndef BSP_Q7S_INITMISSION_H_ #define BSP_Q7S_INITMISSION_H_ +#include "fsfw/tasks/Typedef.h" +#include + +class PeriodicTaskIF; +class TaskFactory; + namespace initmission { void initMission(); void initTasks(); + +void createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc, + std::vector& taskVec); +void createPusTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc, + std::vector& taskVec); +void createTestTasks(TaskFactory& factory, TaskDeadlineMissedFunction missedDeadlineFunc, + std::vector& taskVec); }; #endif /* BSP_Q7S_INITMISSION_H_ */ diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 5f015ff1..3e36e63d 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -1,4 +1,3 @@ -#include #include "ObjectFactory.h" #include "OBSWConfig.h" #include "tmtc/apid.h" @@ -11,62 +10,72 @@ #include "bsp_q7s/gpio/gpioCallbacks.h" #include "bsp_q7s/core/CoreController.h" #include "bsp_q7s/spiCallbacks/rwSpiCallback.h" +#include "bsp_q7s/boardtest/Q7STestTask.h" +#include "bsp_q7s/memory/FileSystemHandler.h" -#include -#include -#include -#include -#include -#include +#include "linux/devices/HeaterHandler.h" +#include "linux/devices/SolarArrayDeploymentHandler.h" +#include "linux/devices/devicedefinitions/SusDefinitions.h" +#include "linux/devices/SusHandler.h" +#include "linux/csp/CspCookie.h" +#include "linux/csp/CspComIF.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "mission/core/GenericFactory.h" +#include "mission/devices/PDU1Handler.h" +#include "mission/devices/PDU2Handler.h" +#include "mission/devices/ACUHandler.h" +#include "mission/devices/PCDUHandler.h" +#include "mission/devices/P60DockHandler.h" +#include "mission/devices/Tmp1075Handler.h" +#include "mission/devices/Max31865PT1000Handler.h" +#include "mission/devices/IMTQHandler.h" +#include "mission/devices/SyrlinksHkHandler.h" +#include "mission/devices/MGMHandlerLIS3MDL.h" +#include "mission/devices/MGMHandlerRM3100.h" +#include "mission/devices/PlocMPSoCHandler.h" +#include "mission/devices/PlocSupervisorHandler.h" +#include "mission/devices/RadiationSensorHandler.h" +#include "mission/devices/RwHandler.h" +#include "mission/devices/StarTrackerHandler.h" +#include "mission/devices/devicedefinitions/GomspaceDefinitions.h" +#include "mission/devices/devicedefinitions/SyrlinksDefinitions.h" +#include "mission/devices/devicedefinitions/PlocMPSoCDefinitions.h" +#include "mission/devices/devicedefinitions/PlocSupervisorDefinitions.h" +#include "mission/devices/devicedefinitions/RadSensorDefinitions.h" +#include "mission/devices/devicedefinitions/Max31865Definitions.h" +#include "mission/devices/devicedefinitions/RwDefinitions.h" +#include +#include "mission/utility/TmFunnel.h" +#include "linux/obc/CCSDSIPCoreBridge.h" -#include "fsfw_hal/linux/uart/UartComIF.h" -#include "fsfw_hal/linux/uart/UartCookie.h" -#include "fsfw_hal/devicehandlers/GyroL3GD20Handler.h" -#include -#include -#include -#include -#include -#include +#include "fsfw/hal/linux/uart/UartComIF.h" +#include "fsfw/hal/linux/uart/UartCookie.h" +#include "fsfw/hal/devicehandlers/GyroL3GD20Handler.h" +#include "fsfw/hal/linux/i2c/I2cCookie.h" +#include "fsfw/hal/linux/i2c/I2cComIF.h" +#include "fsfw/hal/linux/spi/SpiCookie.h" +#include "fsfw/hal/linux/spi/SpiComIF.h" +#include "fsfw/hal/linux/gpio/LinuxLibgpioIF.h" +#include "fsfw/hal/common/gpio/GpioCookie.h" -#include -#include -#include -#include +#include "fsfw/datapoollocal/LocalDataPoolManager.h" +#include "fsfw/tmtcservices/CommandingServiceBase.h" +#include "fsfw/tmtcservices/PusServiceBase.h" +#include "fsfw/tmtcpacket/pus/tm.h" /* UDP server includes */ -#include -#include -#include +#include "fsfw/osal/common/UdpTmTcBridge.h" +#include "fsfw/osal/common/UdpTcPollingTask.h" +#include "linux/boardtest/SpiTestClass.h" #if TEST_LIBGPIOD == 1 -#include +#include "linux/boardtest/LibgpiodTest.h" #endif +void ObjectFactory::setStatics() { + Factory::setStaticFrameworkObjectIds(); +} + void Factory::setStaticFrameworkObjectIds() { PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR; PusServiceBase::packetDestination = objects::TM_FUNNEL; @@ -84,24 +93,82 @@ void Factory::setStaticFrameworkObjectIds() { TmPacketBase::timeStamperId = objects::TIME_STAMPER; } - - void ObjectFactory::produce(void* args){ - Factory::setStaticFrameworkObjectIds(); + ObjectFactory::setStatics(); ObjectFactory::produceGenericObjects(); - LinuxLibgpioIF* gpioComIF = new LinuxLibgpioIF(objects::GPIO_IF); - - /* Communication interfaces */ - new CspComIF(objects::CSP_COM_IF); - new I2cComIF(objects::I2C_COM_IF); - new UartComIF(objects::UART_COM_IF); -#if Q7S_ADD_SPI_TEST == 0 - new SpiComIF(objects::SPI_COM_IF, gpioComIF); -#endif /* Q7S_ADD_SPI_TEST == 0 */ - new CoreController(objects::CORE_CONTROLLER); + LinuxLibgpioIF* gpioComIF = nullptr; + createCommunicationInterfaces(&gpioComIF); + createTmpComponents(); +#if BOARD_TE0720 == 0 -#if TE0720 == 1 + createPcduComponents(); + createRadSensorComponent(gpioComIF); + createSunSensorComponents(gpioComIF); +#if OBSW_ADD_ACS_BOARD == 1 + createAcsBoardComponents(gpioComIF); +#endif /* OBSW_ADD_ACS_BOARD == 1 */ + createHeaterComponents(); + createSolarArrayDeploymentComponents(); +#if Q7S_ADD_SYRLINKS_HANDLER == 1 + createSyrlinksComponents(); +#endif /* Q7S_ADD_SYRLINKS_HANDLER == 1 */ + +#if Q7S_ADD_RTD_DEVICES == 1 + createRtdComponents(); +#endif /* Q7S_ADD_RTD_DEVICES == 1 */ + + I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, IMTQ::MAX_REPLY_SIZE, + std::string("/dev/i2c-0")); + new IMTQHandler(objects::IMTQ_HANDLER, objects::I2C_COM_IF, imtqI2cCookie); + +#if ADD_PLOC_MPSOC == 1 + UartCookie* mpsocUartCookie = new UartCookie(objects::RW1, std::string("/dev/ttyUL3"), + UartModes::NON_CANONICAL, 115200, PLOC_MPSOC::MAX_REPLY_SIZE); + new PlocMPSoCHandler(objects::PLOC_MPSOC_HANDLER, objects::UART_COM_IF, mpsocUartCookie); +#endif /* ADD_PLOC_MPSOC */ + + createReactionWheelComponents(gpioComIF); +#endif /* TE7020 != 0 */ + + new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); + new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE); + + /* Test Task */ +#if OBSW_ADD_TEST_CODE == 1 + createTestComponents(); +#endif /* OBSW_ADD_TEST_CODE == 1 */ + + new FileSystemHandler(objects::FILE_SYSTEM_HANDLER); + +#if ADD_PLOC_MPSOC == 1 + UartCookie* plocMpsocCookie = new UartCookie(objects::RW1, std::string("/dev/ttyUL3"), + UartModes::NON_CANONICAL, 115200, PLOC_MPSOC::MAX_REPLY_SIZE); + new PlocMPSoCHandler(objects::PLOC_MPSOC_HANDLER, objects::UART_COM_IF, plocMpsocCookie); +#endif + +#if OBSW_ADD_STAR_TRACKER == 1 + UartCookie* starTrackerCookie = new UartCookie(objects::START_TRACKER, std::string("/dev/ttyUL3"), + UartModes::NON_CANONICAL, 115200, StarTracker::MAX_FRAME_SIZE* 2 + 2); + starTrackerCookie->setNoFixedSizeReply(); + new StarTrackerHandler(objects::START_TRACKER, objects::UART_COM_IF, starTrackerCookie); +#endif + +#if ADD_PLOC_SUPERVISOR == 1 + /* Configuration for MIO0 on TE0720-03-1CFA */ + UartCookie* plocSupervisorCookie = new UartCookie(objects::PLOC_SUPERVISOR_HANDLER, + std::string("/dev/ttyUL3"), UartModes::NON_CANONICAL, 115200, + PLOC_SPV::MAX_REPLY_SIZE); + PlocSupervisorHandler* plocSupervisor = new PlocSupervisorHandler( + objects::PLOC_SUPERVISOR_HANDLER, objects::UART_COM_IF, plocSupervisorCookie); + plocSupervisor->setStartUpImmediately(); + +#endif + +} + +void ObjectFactory::createTmpComponents() { +#if BOARD_TE0720 == 1 I2cCookie* i2cCookieTmp1075tcs1 = new I2cCookie(addresses::TMP1075_TCS_1, TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-0")); I2cCookie* i2cCookieTmp1075tcs2 = new I2cCookie(addresses::TMP1075_TCS_2, @@ -122,8 +189,27 @@ void ObjectFactory::produce(void* args){ objects::TMP1075_HANDLER_2, objects::I2C_COM_IF, i2cCookieTmp1075tcs2); (void) tmp1075Handler_2; +} -#if TE0720 == 0 +void ObjectFactory::createCommunicationInterfaces(LinuxLibgpioIF **gpioComIF) { + if(gpioComIF == nullptr) { + sif::error << "ObjectFactory::createCommunicationInterfaces: Invalid GPIO ComIF" + << std::endl; + } + *gpioComIF = new LinuxLibgpioIF(objects::GPIO_IF); + + /* Communication interfaces */ + new CspComIF(objects::CSP_COM_IF); + new I2cComIF(objects::I2C_COM_IF); + new UartComIF(objects::UART_COM_IF); +#if Q7S_ADD_SPI_TEST == 0 + new SpiComIF(objects::SPI_COM_IF, *gpioComIF); +#endif /* Q7S_ADD_SPI_TEST == 0 */ + /* Adding gpios for chip select decoding to the gpioComIf */ + gpioCallbacks::initSpiCsDecoder(*gpioComIF); +} + +void ObjectFactory::createPcduComponents() { CspCookie* p60DockCspCookie = new CspCookie(P60Dock::MAX_REPLY_LENGTH, addresses::P60DOCK); CspCookie* pdu1CspCookie = new CspCookie(PDU::MAX_REPLY_LENGTH, @@ -156,10 +242,9 @@ void ObjectFactory::produce(void* args){ (void) pdu1handler; (void) pdu2handler; (void) acuhandler; +} - /* Adding gpios for chip select decoding to the gpioComIf */ - gpioCallbacks::initSpiCsDecoder(gpioComIF); - +void ObjectFactory::createRadSensorComponent(LinuxLibgpioIF* gpioComIF) { GpioCookie* gpioCookieRadSensor = new GpioCookie; GpiodRegular* chipSelectRadSensor = new GpiodRegular(std::string("gpiochip5"), 19, std::string("Chip Select Radiation Sensor"), gpio::OUT, 1); @@ -170,6 +255,9 @@ void ObjectFactory::produce(void* args){ std::string("/dev/spidev2.0"), RAD_SENSOR::READ_SIZE, spi::DEFAULT_MAX_1227_MODE, spi::DEFAULT_MAX_1227_SPEED); new RadiationSensorHandler(objects::RAD_SENSOR, objects::SPI_COM_IF, spiCookieRadSensor); +} + +void ObjectFactory::createSunSensorComponents(LinuxLibgpioIF *gpioComIF) { GpioCookie* gpioCookieSus = new GpioCookie(); GpioCallback* susgpio = new GpioCallback(std::string("Chip select SUS 1"), gpio::OUT, 1, @@ -254,21 +342,35 @@ void ObjectFactory::produce(void* args){ std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE, SUS::MAX1227_SPI_FREQ); - new SusHandler(objects::SUS_1, objects::SPI_COM_IF, spiCookieSus1, gpioComIF, gpioIds::CS_SUS_1); - new SusHandler(objects::SUS_2, objects::SPI_COM_IF, spiCookieSus2, gpioComIF, gpioIds::CS_SUS_2); - new SusHandler(objects::SUS_3, objects::SPI_COM_IF, spiCookieSus3, gpioComIF, gpioIds::CS_SUS_3); - new SusHandler(objects::SUS_4, objects::SPI_COM_IF, spiCookieSus4, gpioComIF, gpioIds::CS_SUS_4); - new SusHandler(objects::SUS_5, objects::SPI_COM_IF, spiCookieSus5, gpioComIF, gpioIds::CS_SUS_5); - new SusHandler(objects::SUS_6, objects::SPI_COM_IF, spiCookieSus6, gpioComIF, gpioIds::CS_SUS_6); - new SusHandler(objects::SUS_7, objects::SPI_COM_IF, spiCookieSus7, gpioComIF, gpioIds::CS_SUS_7); - new SusHandler(objects::SUS_8, objects::SPI_COM_IF, spiCookieSus8, gpioComIF, gpioIds::CS_SUS_8); - new SusHandler(objects::SUS_9, objects::SPI_COM_IF, spiCookieSus9, gpioComIF, gpioIds::CS_SUS_9); - new SusHandler(objects::SUS_10, objects::SPI_COM_IF, spiCookieSus10, gpioComIF, gpioIds::CS_SUS_10); - new SusHandler(objects::SUS_11, objects::SPI_COM_IF, spiCookieSus11, gpioComIF, gpioIds::CS_SUS_11); - new SusHandler(objects::SUS_12, objects::SPI_COM_IF, spiCookieSus12, gpioComIF, gpioIds::CS_SUS_12); - new SusHandler(objects::SUS_13, objects::SPI_COM_IF, spiCookieSus13, gpioComIF, gpioIds::CS_SUS_13); + new SusHandler(objects::SUS_1, objects::SPI_COM_IF, spiCookieSus1, gpioComIF, + gpioIds::CS_SUS_1); + new SusHandler(objects::SUS_2, objects::SPI_COM_IF, spiCookieSus2, gpioComIF, + gpioIds::CS_SUS_2); + new SusHandler(objects::SUS_3, objects::SPI_COM_IF, spiCookieSus3, gpioComIF, + gpioIds::CS_SUS_3); + new SusHandler(objects::SUS_4, objects::SPI_COM_IF, spiCookieSus4, gpioComIF, + gpioIds::CS_SUS_4); + new SusHandler(objects::SUS_5, objects::SPI_COM_IF, spiCookieSus5, gpioComIF, + gpioIds::CS_SUS_5); + new SusHandler(objects::SUS_6, objects::SPI_COM_IF, spiCookieSus6, gpioComIF, + gpioIds::CS_SUS_6); + new SusHandler(objects::SUS_7, objects::SPI_COM_IF, spiCookieSus7, gpioComIF, + gpioIds::CS_SUS_7); + new SusHandler(objects::SUS_8, objects::SPI_COM_IF, spiCookieSus8, gpioComIF, + gpioIds::CS_SUS_8); + new SusHandler(objects::SUS_9, objects::SPI_COM_IF, spiCookieSus9, gpioComIF, + gpioIds::CS_SUS_9); + new SusHandler(objects::SUS_10, objects::SPI_COM_IF, spiCookieSus10, gpioComIF, + gpioIds::CS_SUS_10); + new SusHandler(objects::SUS_11, objects::SPI_COM_IF, spiCookieSus11, gpioComIF, + gpioIds::CS_SUS_11); + new SusHandler(objects::SUS_12, objects::SPI_COM_IF, spiCookieSus12, gpioComIF, + gpioIds::CS_SUS_12); + new SusHandler(objects::SUS_13, objects::SPI_COM_IF, spiCookieSus13, gpioComIF, + gpioIds::CS_SUS_13); +} -#if OBSW_ADD_ACS_BOARD == 1 +void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF *gpioComIF) { GpioCookie* gpioCookieAcsBoard = new GpioCookie(); GpiodRegular* gpio = nullptr; gpio = new GpiodRegular(std::string("gpiochip5"), 1, std::string("CS_GYRO_0_ADIS"), @@ -326,20 +428,23 @@ void ObjectFactory::produce(void* args){ //TODO: Adis Gyro (Gyro 0 Side A) + // Commented until ACS board V2 in in clean room again /* Gyro 1 Side A */ - spiCookie = new SpiCookie(addresses::GYRO_1_L3G, gpioIds::GYRO_1_L3G_CS, spiDev, - L3GD20H::MAX_BUFFER_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED); - auto gyroL3gHandler = new GyroHandlerL3GD20H(objects::GYRO_1_L3G_HANDLER, objects::SPI_COM_IF, - spiCookie); - gyroL3gHandler->setStartUpImmediately(); +// spiCookie = new SpiCookie(addresses::GYRO_1_L3G, gpioIds::GYRO_1_L3G_CS, spiDev, +// L3GD20H::MAX_BUFFER_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED); +// auto gyroL3gHandler = new GyroHandlerL3GD20H(objects::GYRO_1_L3G_HANDLER, objects::SPI_COM_IF, +// spiCookie); +// gyroL3gHandler->setStartUpImmediately(); +// +// /* Gyro 2 Side B */ +// spiCookie = new SpiCookie(addresses::GYRO_2_L3G, gpioIds::GYRO_2_L3G_CS, spiDev, +// L3GD20H::MAX_BUFFER_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED); +// gyroL3gHandler = new GyroHandlerL3GD20H(objects::GYRO_2_L3G_HANDLER, objects::SPI_COM_IF, +// spiCookie); +// gyroL3gHandler->setStartUpImmediately(); +} - /* Gyro 2 Side B */ - spiCookie = new SpiCookie(addresses::GYRO_2_L3G, gpioIds::GYRO_2_L3G_CS, spiDev, - L3GD20H::MAX_BUFFER_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED); - gyroL3gHandler = new GyroHandlerL3GD20H(objects::GYRO_2_L3G_HANDLER, objects::SPI_COM_IF, - spiCookie); - gyroL3gHandler->setStartUpImmediately(); -#endif +void ObjectFactory::createHeaterComponents() { GpioCookie* heaterGpiosCookie = new GpioCookie; @@ -380,7 +485,9 @@ void ObjectFactory::produce(void* args){ new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, heaterGpiosCookie, objects::PCDU_HANDLER, pcduSwitches::TCS_BOARD_8V_HEATER_IN); +} +void ObjectFactory::createSolarArrayDeploymentComponents() { GpioCookie* solarArrayDeplCookie = new GpioCookie; GpiodRegular* gpioConfigDeplSA0 = new GpiodRegular(std::string("gpiochip7"), 4, @@ -394,16 +501,17 @@ void ObjectFactory::produce(void* args){ new SolarArrayDeploymentHandler(objects::SOLAR_ARRAY_DEPL_HANDLER, objects::GPIO_IF, solarArrayDeplCookie, objects::PCDU_HANDLER, pcduSwitches::DEPLOYMENT_MECHANISM, gpioIds::DEPLSA1, gpioIds::DEPLSA2, 1000); +} +void ObjectFactory::createSyrlinksComponents() { UartCookie* syrlinksUartCookie = new UartCookie(objects::SYRLINKS_HK_HANDLER, std::string("/dev/ttyUL0"), UartModes::NON_CANONICAL, 38400, SYRLINKS::MAX_REPLY_SIZE); syrlinksUartCookie->setParityEven(); - SyrlinksHkHandler* syrlinksHkHandler = new SyrlinksHkHandler(objects::SYRLINKS_HK_HANDLER, - objects::UART_COM_IF, syrlinksUartCookie); - syrlinksHkHandler->setModeNormal(); + new SyrlinksHkHandler(objects::SYRLINKS_HK_HANDLER, objects::UART_COM_IF, syrlinksUartCookie); +} -#if Q7S_ADD_RTD_DEVICES == 1 +void ObjectFactory::createRtdComponents(LinuxLibgpioIF *gpioComIF) { GpioCookie* rtdGpioCookie = new GpioCookie; GpioCallback* gpioRtdIc3 = new GpioCallback(std::string("Chip select RTD IC3"), gpio::OUT, 1, @@ -506,22 +614,38 @@ void ObjectFactory::produce(void* args){ std::string("/dev/spidev2.0"), Max31865Definitions::MAX_REPLY_SIZE, spi::SpiModes::MODE_1, 2000000); - Max31865PT1000Handler* rtdIc3 = new Max31865PT1000Handler(objects::RTD_IC3, objects::SPI_COM_IF, spiRtdIc3, 0); // 0 is switchId - Max31865PT1000Handler* rtdIc4 = new Max31865PT1000Handler(objects::RTD_IC4, objects::SPI_COM_IF, spiRtdIc4, 0); - Max31865PT1000Handler* rtdIc5 = new Max31865PT1000Handler(objects::RTD_IC5, objects::SPI_COM_IF, spiRtdIc5, 0); - Max31865PT1000Handler* rtdIc6 = new Max31865PT1000Handler(objects::RTD_IC6, objects::SPI_COM_IF, spiRtdIc6, 0); - Max31865PT1000Handler* rtdIc7 = new Max31865PT1000Handler(objects::RTD_IC7, objects::SPI_COM_IF, spiRtdIc7, 0); - Max31865PT1000Handler* rtdIc8 = new Max31865PT1000Handler(objects::RTD_IC8, objects::SPI_COM_IF, spiRtdIc8, 0); - Max31865PT1000Handler* rtdIc9 = new Max31865PT1000Handler(objects::RTD_IC9, objects::SPI_COM_IF, spiRtdIc9, 0); - Max31865PT1000Handler* rtdIc10 = new Max31865PT1000Handler(objects::RTD_IC10, objects::SPI_COM_IF, spiRtdIc10, 0); - Max31865PT1000Handler* rtdIc11 = new Max31865PT1000Handler(objects::RTD_IC11, objects::SPI_COM_IF, spiRtdIc11, 0); - Max31865PT1000Handler* rtdIc12 = new Max31865PT1000Handler(objects::RTD_IC12, objects::SPI_COM_IF, spiRtdIc12, 0); - Max31865PT1000Handler* rtdIc13 = new Max31865PT1000Handler(objects::RTD_IC13, objects::SPI_COM_IF, spiRtdIc13, 0); - Max31865PT1000Handler* rtdIc14 = new Max31865PT1000Handler(objects::RTD_IC14, objects::SPI_COM_IF, spiRtdIc14, 0); - Max31865PT1000Handler* rtdIc15 = new Max31865PT1000Handler(objects::RTD_IC15, objects::SPI_COM_IF, spiRtdIc15, 0); - Max31865PT1000Handler* rtdIc16 = new Max31865PT1000Handler(objects::RTD_IC16, objects::SPI_COM_IF, spiRtdIc16, 0); - Max31865PT1000Handler* rtdIc17 = new Max31865PT1000Handler(objects::RTD_IC17, objects::SPI_COM_IF, spiRtdIc17, 0); - Max31865PT1000Handler* rtdIc18 = new Max31865PT1000Handler(objects::RTD_IC18, objects::SPI_COM_IF, spiRtdIc18, 0); + Max31865PT1000Handler* rtdIc3 = new Max31865PT1000Handler(objects::RTD_IC3, + objects::SPI_COM_IF, spiRtdIc3, 0); // 0 is switchId + Max31865PT1000Handler* rtdIc4 = new Max31865PT1000Handler(objects::RTD_IC4, + objects::SPI_COM_IF, spiRtdIc4, 0); + Max31865PT1000Handler* rtdIc5 = new Max31865PT1000Handler(objects::RTD_IC5, + objects::SPI_COM_IF, spiRtdIc5, 0); + Max31865PT1000Handler* rtdIc6 = new Max31865PT1000Handler(objects::RTD_IC6, + objects::SPI_COM_IF, spiRtdIc6, 0); + Max31865PT1000Handler* rtdIc7 = new Max31865PT1000Handler(objects::RTD_IC7, + objects::SPI_COM_IF, spiRtdIc7, 0); + Max31865PT1000Handler* rtdIc8 = new Max31865PT1000Handler(objects::RTD_IC8, + objects::SPI_COM_IF, spiRtdIc8, 0); + Max31865PT1000Handler* rtdIc9 = new Max31865PT1000Handler(objects::RTD_IC9, + objects::SPI_COM_IF, spiRtdIc9, 0); + Max31865PT1000Handler* rtdIc10 = new Max31865PT1000Handler(objects::RTD_IC10, + objects::SPI_COM_IF, spiRtdIc10, 0); + Max31865PT1000Handler* rtdIc11 = new Max31865PT1000Handler(objects::RTD_IC11, + objects::SPI_COM_IF, spiRtdIc11, 0); + Max31865PT1000Handler* rtdIc12 = new Max31865PT1000Handler(objects::RTD_IC12, + objects::SPI_COM_IF, spiRtdIc12, 0); + Max31865PT1000Handler* rtdIc13 = new Max31865PT1000Handler(objects::RTD_IC13, + objects::SPI_COM_IF, spiRtdIc13, 0); + Max31865PT1000Handler* rtdIc14 = new Max31865PT1000Handler(objects::RTD_IC14, + objects::SPI_COM_IF, spiRtdIc14, 0); + Max31865PT1000Handler* rtdIc15 = new Max31865PT1000Handler(objects::RTD_IC15, + objects::SPI_COM_IF, spiRtdIc15, 0); + Max31865PT1000Handler* rtdIc16 = new Max31865PT1000Handler(objects::RTD_IC16, + objects::SPI_COM_IF, spiRtdIc16, 0); + Max31865PT1000Handler* rtdIc17 = new Max31865PT1000Handler(objects::RTD_IC17, + objects::SPI_COM_IF, spiRtdIc17, 0); + Max31865PT1000Handler* rtdIc18 = new Max31865PT1000Handler(objects::RTD_IC18, + objects::SPI_COM_IF, spiRtdIc18, 0); (void) rtdIc3; (void) rtdIc4; @@ -539,17 +663,9 @@ void ObjectFactory::produce(void* args){ (void) rtdIc16; (void) rtdIc17; (void) rtdIc18; +} -#endif /* Q7S_ADD_RTD_DEVICES == 1 */ - - I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, IMTQ::MAX_REPLY_SIZE, - std::string("/dev/i2c-0")); - new IMTQHandler(objects::IMTQ_HANDLER, objects::I2C_COM_IF, imtqI2cCookie); - - UartCookie* plocUartCookie = new UartCookie(objects::RW1, std::string("/dev/ttyUL3"), - UartModes::NON_CANONICAL, 115200, PLOC::MAX_REPLY_SIZE); - new PlocHandler(objects::PLOC_HANDLER, objects::UART_COM_IF, plocUartCookie); - +void ObjectFactory::createReactionWheelComponents(LinuxLibgpioIF* gpioComIF) { GpioCookie* gpioCookieRw = new GpioCookie; GpioCallback* csRw1 = new GpioCallback(std::string("Chip select reaction wheel 1"), gpio::OUT, 1, &gpioCallbacks::spiCsDecoderCallback, gpioComIF); @@ -564,29 +680,29 @@ void ObjectFactory::produce(void* args){ 1, &gpioCallbacks::spiCsDecoderCallback, gpioComIF); gpioCookieRw->addGpio(gpioIds::CS_RW4, csRw4); - GpiodRegular* enRw1 = new GpiodRegular(std::string("gpiochip5"), 7, - std::string("Enable reaction wheel 1"), gpio::OUT, 0); - gpioCookieRw->addGpio(gpioIds::EN_RW1, enRw1); - GpiodRegular* enRw2 = new GpiodRegular(std::string("gpiochip5"), 3, - std::string("Enable reaction wheel 2"), gpio::OUT, 0); - gpioCookieRw->addGpio(gpioIds::EN_RW2, enRw2); - GpiodRegular* enRw3 = new GpiodRegular(std::string("gpiochip5"), 11, - std::string("Enable reaction wheel 3"), gpio::OUT, 0); - gpioCookieRw->addGpio(gpioIds::EN_RW3, enRw3); - GpiodRegular* enRw4 = new GpiodRegular(std::string("gpiochip5"), 6, - std::string("Enable reaction wheel 4"), gpio::OUT, 0); - gpioCookieRw->addGpio(gpioIds::EN_RW4, enRw4); + GpiodRegular* enRw1 = new GpiodRegular(std::string("gpiochip5"), 7, + std::string("Enable reaction wheel 1"), gpio::OUT, 0); + gpioCookieRw->addGpio(gpioIds::EN_RW1, enRw1); + GpiodRegular* enRw2 = new GpiodRegular(std::string("gpiochip5"), 3, + std::string("Enable reaction wheel 2"), gpio::OUT, 0); + gpioCookieRw->addGpio(gpioIds::EN_RW2, enRw2); + GpiodRegular* enRw3 = new GpiodRegular(std::string("gpiochip5"), 11, + std::string("Enable reaction wheel 3"), gpio::OUT, 0); + gpioCookieRw->addGpio(gpioIds::EN_RW3, enRw3); + GpiodRegular* enRw4 = new GpiodRegular(std::string("gpiochip5"), 6, + std::string("Enable reaction wheel 4"), gpio::OUT, 0); + gpioCookieRw->addGpio(gpioIds::EN_RW4, enRw4); - /** - * This GPIO is only internally connected to the SPI MUX module and responsible to disconnect - * the PS SPI peripheral from the SPI interface and route out the SPI lines of the AXI SPI core. - * Per default the PS SPI is selected (EMIO = 0). - */ - GpiodRegular* spiMux = new GpiodRegular(std::string("gpiochip11"), 54, + /** + * This GPIO is only internally connected to the SPI MUX module and responsible to disconnect + * the PS SPI peripheral from the SPI interface and route out the SPI lines of the AXI SPI core. + * Per default the PS SPI is selected (EMIO = 0). + */ + GpiodRegular* spiMux = new GpiodRegular(std::string("gpiochip11"), 54, std::string("EMIO 0 SPI Mux"), gpio::OUT, 0); gpioCookieRw->addGpio(gpioIds::SPI_MUX, spiMux); - gpioComIF->addGpios(gpioCookieRw); + gpioComIF->addGpios(gpioCookieRw); auto rw1SpiCookie = new SpiCookie(addresses::RW1, gpioIds::CS_RW1, "/dev/spidev3.0", RwDefinitions::MAX_REPLY_SIZE, spi::RW_MODE, spi::RW_SPEED, &rwSpiCallback::spiCallback, @@ -601,33 +717,27 @@ void ObjectFactory::produce(void* args){ RwDefinitions::MAX_REPLY_SIZE, spi::RW_MODE, spi::RW_SPEED, &rwSpiCallback::spiCallback, nullptr); - auto rwHandler1 = new RwHandler(objects::RW1, objects::SPI_COM_IF, rw1SpiCookie, gpioComIF, - gpioIds::EN_RW1); + auto rwHandler1 = new RwHandler(objects::RW1, objects::SPI_COM_IF, rw1SpiCookie, gpioComIF, + gpioIds::EN_RW1); rw1SpiCookie->setCallbackArgs(rwHandler1); auto rwHandler2 = new RwHandler(objects::RW2, objects::SPI_COM_IF, rw2SpiCookie, gpioComIF, - gpioIds::EN_RW2); + gpioIds::EN_RW2); rw2SpiCookie->setCallbackArgs(rwHandler2); auto rwHandler3 = new RwHandler(objects::RW3, objects::SPI_COM_IF, rw3SpiCookie, gpioComIF, - gpioIds::EN_RW3); + gpioIds::EN_RW3); rw3SpiCookie->setCallbackArgs(rwHandler3); auto rwHandler4 = new RwHandler(objects::RW4, objects::SPI_COM_IF, rw4SpiCookie, gpioComIF, - gpioIds::EN_RW4); + gpioIds::EN_RW4); rw4SpiCookie->setCallbackArgs(rwHandler4); +} -#endif /* TE0720 == 0 */ - - new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); - new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE); - - /* Test Task */ -#if OBSW_ADD_TEST_CODE == 1 +void ObjectFactory::createTestComponents() { new Q7STestTask(objects::TEST_TASK); -#endif -#if TE0720 == 1 && TEST_LIBGPIOD == 1 +#if BOARD_TE0720 == 1 && TEST_LIBGPIOD == 1 /* Configure MIO0 as input */ GpiodRegular gpioConfigMio0(std::string("gpiochip0"), 0, std::string("MIO0"), gpio::IN, 0); @@ -636,7 +746,7 @@ void ObjectFactory::produce(void* args){ new LibgpiodTest(objects::LIBGPIOD_TEST, objects::GPIO_IF, gpioCookie); #endif -#if TE0720 == 1 && TEST_SUS_HANDLER == 1 +#if BOARD_TE0720 == 1 && TEST_SUS_HANDLER == 1 GpioCookie* gpioCookieSus = new GpioCookie; GpiodRegular* chipSelectSus = new GpiodRegular(std::string("gpiochip1"), 9, std::string("Chip Select Sus Sensor"), gpio::OUT, 1); @@ -650,7 +760,7 @@ void ObjectFactory::produce(void* args){ gpioIds::CS_SUS_1); #endif -#if TE0720 == 1 && TEST_CCSDS_BRIDGE == 1 +#if BOARD_TE0720 == 1 && TEST_CCSDS_BRIDGE == 1 GpioCookie* gpioCookieCcsdsIp = new GpioCookie; GpiodRegular* papbBusyN = new GpiodRegular(std::string("gpiochip0"), 0, std::string("PAPBBusy_N")); gpioCookieCcsdsIp->addGpio(gpioIds::PAPB_BUSY_N, papbBusyN); @@ -664,7 +774,7 @@ void ObjectFactory::produce(void* args){ gpioIds::PAPB_BUSY_N, gpioIds::PAPB_EMPTY); #endif -#if TE0720 == 1 && TEST_RADIATION_SENSOR_HANDLER == 1 +#if BOARD_TE0720 == 1 && TEST_RADIATION_SENSOR_HANDLER == 1 GpioCookie* gpioCookieRadSensor = new GpioCookie; GpiodRegular* chipSelectRadSensor = new GpiodRegular(std::string("gpiochip1"), 0, std::string("Chip select radiation sensor"), gpio::OUT, 1); @@ -680,16 +790,16 @@ void ObjectFactory::produce(void* args){ radSensor->setStartUpImmediately(); #endif -#if TE0720 == 1 && TEST_PLOC_HANDLER == 1 +#if BOARD_TE0720 == 1 && TEST_PLOC_HANDLER == 1 UartCookie* plocUartCookie = new UartCookie(std::string("/dev/ttyPS1"), 115200, - PLOC::MAX_REPLY_SIZE); - /* Testing PlocHandler on TE0720-03-1CFA */ - PlocHandler* plocHandler = new PlocHandler(objects::PLOC_HANDLER, objects::UART_COM_IF, + PLOC_MPSOC::MAX_REPLY_SIZE); + /* Testing PlocMPSoCHandler on TE0720-03-1CFA */ + PlocMPSoCHandler* mpsocPlocHandler = new PlocMPSoCHandler(objects::PLOC_MPSOC_HANDLER, objects::UART_COM_IF, plocUartCookie); - plocHandler->setStartUpImmediately(); + mpsocPlocHandler->setStartUpImmediately(); #endif -#if TE0720 == 1 && TE0720_HEATER_TEST == 1 +#if BOARD_TE0720 == 1 && TE0720_HEATER_TEST == 1 /* Configuration for MIO0 on TE0720-03-1CFA */ GpiodRegular* heaterGpio = new GpiodRegular(std::string("gpiochip0"), 0, std::string("MIO0"), gpio::IN, 0); GpioCookie* gpioCookie = new GpioCookie; @@ -698,6 +808,17 @@ void ObjectFactory::produce(void* args){ pcduSwitches::TCS_BOARD_8V_HEATER_IN); #endif +#if TE0720 == 1 && ADD_PLOC_SUPERVISOR == 1 + /* Configuration for MIO0 on TE0720-03-1CFA */ + UartCookie* plocSupervisorCookie = new UartCookie(objects::PLOC_SUPERVISOR_HANDLER, + std::string("/dev/ttyPS1"), UartModes::NON_CANONICAL, 115200, + PLOC_SPV::MAX_REPLY_SIZE); + PlocSupervisorHandler* plocSupervisor = new PlocSupervisorHandler( + objects::PLOC_SUPERVISOR_HANDLER, objects::UART_COM_IF, plocSupervisorCookie); + plocSupervisor->setStartUpImmediately(); + +#endif + #if Q7S_ADD_SPI_TEST == 1 new SpiTestClass(objects::SPI_TEST, gpioComIF); #endif diff --git a/bsp_q7s/core/ObjectFactory.h b/bsp_q7s/core/ObjectFactory.h index 536af52d..411fa230 100644 --- a/bsp_q7s/core/ObjectFactory.h +++ b/bsp_q7s/core/ObjectFactory.h @@ -1,9 +1,26 @@ #ifndef BSP_Q7S_OBJECTFACTORY_H_ #define BSP_Q7S_OBJECTFACTORY_H_ +class LinuxLibgpioIF; + namespace ObjectFactory { + void setStatics(); void produce(void* args); + +void createCommunicationInterfaces(LinuxLibgpioIF** gpioComIF); +void createTmpComponents(); +void createPcduComponents(); +void createRadSensorComponent(LinuxLibgpioIF* gpioComIF); +void createSunSensorComponents(LinuxLibgpioIF* gpioComIF); +void createAcsBoardComponents(LinuxLibgpioIF* gpioComIF); +void createHeaterComponents(); +void createSolarArrayDeploymentComponents(); +void createSyrlinksComponents(); +void createRtdComponents(LinuxLibgpioIF* gpioComIF); +void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF); +void createTestComponents(); + }; #endif /* BSP_Q7S_OBJECTFACTORY_H_ */ diff --git a/bsp_q7s/core/ParameterHandler.cpp b/bsp_q7s/core/ParameterHandler.cpp new file mode 100644 index 00000000..d6c8f34f --- /dev/null +++ b/bsp_q7s/core/ParameterHandler.cpp @@ -0,0 +1,8 @@ +#include "ParameterHandler.h" + +ParameterHandler::ParameterHandler(std::string mountPrefix): mountPrefix(mountPrefix) { +} + +void ParameterHandler::setMountPrefix(std::string prefix) { + mountPrefix = prefix; +} diff --git a/bsp_q7s/core/ParameterHandler.h b/bsp_q7s/core/ParameterHandler.h new file mode 100644 index 00000000..81cbc099 --- /dev/null +++ b/bsp_q7s/core/ParameterHandler.h @@ -0,0 +1,22 @@ +#ifndef BSP_Q7S_CORE_PARAMETERHANDLER_H_ +#define BSP_Q7S_CORE_PARAMETERHANDLER_H_ + +#include +#include + + + +class ParameterHandler { +public: + ParameterHandler(std::string mountPrefix); + + void setMountPrefix(std::string prefix); + + void setUpDummyParameter(); +private: + std::string mountPrefix; + DummyParameter dummyParam; +}; + + +#endif /* BSP_Q7S_CORE_PARAMETERHANDLER_H_ */ diff --git a/bsp_q7s/core/obsw.cpp b/bsp_q7s/core/obsw.cpp index f813bcae..b6e90d4d 100644 --- a/bsp_q7s/core/obsw.cpp +++ b/bsp_q7s/core/obsw.cpp @@ -2,11 +2,12 @@ #include "OBSWVersion.h" #include "InitMission.h" #include "fsfw/tasks/TaskFactory.h" +#include "OBSWConfig.h" #include int obsw::obsw() { std::cout << "-- EIVE OBSW --" << std::endl; -#if TE0720 == 0 +#if BOARD_TE0720 == 0 std::cout << "-- Compiled for Linux (Xiphos Q7S) --" << std::endl; #else std::cout << "-- Compiled for Linux (TE0720) --" << std::endl; diff --git a/bsp_q7s/gpio/gpioCallbacks.cpp b/bsp_q7s/gpio/gpioCallbacks.cpp index 5499517b..29e7f86d 100644 --- a/bsp_q7s/gpio/gpioCallbacks.cpp +++ b/bsp_q7s/gpio/gpioCallbacks.cpp @@ -1,8 +1,8 @@ #include "gpioCallbacks.h" #include -#include -#include +#include +#include #include diff --git a/bsp_q7s/gpio/gpioCallbacks.h b/bsp_q7s/gpio/gpioCallbacks.h index eaf9a701..55e67895 100644 --- a/bsp_q7s/gpio/gpioCallbacks.h +++ b/bsp_q7s/gpio/gpioCallbacks.h @@ -1,8 +1,8 @@ #ifndef LINUX_GPIO_GPIOCALLBACKS_H_ #define LINUX_GPIO_GPIOCALLBACKS_H_ -#include -#include +#include +#include namespace gpioCallbacks { diff --git a/bsp_q7s/memory/FileSystemHandler.cpp b/bsp_q7s/memory/FileSystemHandler.cpp index 1519b92b..159512a0 100644 --- a/bsp_q7s/memory/FileSystemHandler.cpp +++ b/bsp_q7s/memory/FileSystemHandler.cpp @@ -1,9 +1,13 @@ #include "FileSystemHandler.h" +#include "bsp_q7s/core/CoreController.h" + #include "fsfw/tasks/TaskFactory.h" #include "fsfw/memory/GenericFileSystemMessage.h" #include "fsfw/ipc/QueueFactory.h" +#include +#include #include FileSystemHandler::FileSystemHandler(object_id_t fileSystemHandler): @@ -24,9 +28,9 @@ ReturnValue_t FileSystemHandler::performOperation(uint8_t unsignedChar) { // Restart OBSW, hints at a memory leak sif::error << "Allocation error in FileSystemHandler::performOperation" << e.what() << std::endl; - // TODO: If we trigger an event, it might not get sent because were restarting - // Set up an error file or a special flag in the scratch buffer. - // TODO: CoreController: Implement function to restart OBC + // Set up an error file or a special flag in the scratch buffer for these cases + triggerEvent(CoreController::ALLOC_FAILURE, 0 , 0); + CoreController::incrementAllocationFailureCount(); } } } @@ -63,6 +67,7 @@ void FileSystemHandler::fileSystemHandlerLoop() { // This task will have a low priority and will run permanently in the background // so we will just run in a permanent loop here and check file system // messages permanently + opCounter++; TaskFactory::instance()->delayTask(1000); } @@ -75,7 +80,7 @@ void FileSystemHandler::fileSystemCheckup() { (statusPair.first == sd::SdStatus::MOUNTED)) { currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT; } - if((preferredSdCard == sd::SdCard::SLOT_1) and + else if((preferredSdCard == sd::SdCard::SLOT_1) and (statusPair.second == sd::SdStatus::MOUNTED)) { currentMountPrefix = SdCardManager::SD_1_MOUNT_POINT; } @@ -87,15 +92,16 @@ void FileSystemHandler::fileSystemCheckup() { else { sdString = "1"; } - sif::warning << "FileSystemHandler::performOperation: Inconsistent" << - " state detected. Preferred SD card is " << sdString << + sif::warning << "FileSystemHandler::performOperation: " + "Inconsistent state detected" << std::endl; + sif::warning << "Preferred SD card is " << sdString << " but does not appear to be mounted. Attempting fix.." << std::endl; // This function will appear to fix the inconsistent state - ReturnValue_t result = sdcMan->sanitizeState(&preferredSdCard, &statusPair); + ReturnValue_t result = sdcMan->sanitizeState(&statusPair, preferredSdCard); if(result != HasReturnvaluesIF::RETURN_OK) { // Oh no. - // TODO: Trigger medium severity event - sif::error << "Fix failed" << std::endl; + triggerEvent(SdCardManager::SANITIZATION_FAILED, 0, 0); + sif::error << "FileSystemHandler::fileSystemCheckup: Sanitization failed" << std::endl; } } } @@ -125,27 +131,70 @@ ReturnValue_t FileSystemHandler::appendToFile(const char *repositoryPath, const // A double slash between repo and filename should not be an issue, so add it in any case std::string fullPath = currentMountPrefix + std::string(repositoryPath) + "/" + std::string(filename); + if(not std::filesystem::exists(fullPath)) { + return FILE_DOES_NOT_EXIST; + } + std::ofstream file(fullPath, std::ios_base::app|std::ios_base::out); + file.write(reinterpret_cast(data), size); + if(not file.good()) { + return GENERIC_FILE_ERROR; + } return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t FileSystemHandler::createFile(const char *repositoryPath, const char *filename, const uint8_t *data, size_t size, void *args) { + std::string fullPath; + bool useMountPrefix = true; + parseCfg(reinterpret_cast(args), useMountPrefix); + if(useMountPrefix) { + fullPath += currentMountPrefix; + } + // A double slash between repo and filename should not be an issue, so add it in any case - std::string fullPath = currentMountPrefix + std::string(repositoryPath) + "/" + - std::string(filename); + fullPath += std::string(repositoryPath) + "/" + std::string(filename); + if(std::filesystem::exists(fullPath)) { + return FILE_ALREADY_EXISTS; + } + std::ofstream file(fullPath); + file.write(reinterpret_cast(data), size); + if(not file.good()) { + return GENERIC_FILE_ERROR; + } return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t FileSystemHandler::deleteFile(const char *repositoryPath, const char *filename, +ReturnValue_t FileSystemHandler::removeFile(const char *repositoryPath, const char *filename, void *args) { + std::string fullPath; + bool useMountPrefix = true; + parseCfg(reinterpret_cast(args), useMountPrefix); + if(useMountPrefix) { + fullPath += currentMountPrefix; + } + // A double slash between repo and filename should not be an issue, so add it in any case - std::string fullPath = currentMountPrefix + std::string(repositoryPath) + "/" + - std::string(filename); + fullPath += std::string(repositoryPath) + "/" + std::string(filename); + if(not std::filesystem::exists(fullPath)) { + return FILE_DOES_NOT_EXIST; + } + int result = std::remove(fullPath.c_str()); + if(result != 0) { + sif::warning << "FileSystemHandler::deleteFile: Failed with code " << result << std::endl; + return GENERIC_FILE_ERROR; + } return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t FileSystemHandler::createDirectory(const char *repositoryPath, void *args) { - std::string fullPath = currentMountPrefix + std::string(repositoryPath); + std::string fullPath; + bool useMountPrefix = true; + parseCfg(reinterpret_cast(args), useMountPrefix); + if(useMountPrefix) { + fullPath += currentMountPrefix; + } + + fullPath += std::string(repositoryPath); if(std::filesystem::exists(fullPath)) { return DIRECTORY_ALREADY_EXISTS; } @@ -158,7 +207,14 @@ ReturnValue_t FileSystemHandler::createDirectory(const char *repositoryPath, voi ReturnValue_t FileSystemHandler::removeDirectory(const char *repositoryPath, bool deleteRecurively, void *args) { - std::string fullPath = currentMountPrefix + std::string(repositoryPath); + std::string fullPath; + bool useMountPrefix = true; + parseCfg(reinterpret_cast(args), useMountPrefix); + if(useMountPrefix) { + fullPath += currentMountPrefix; + } + + fullPath += std::string(repositoryPath); if(not std::filesystem::exists(fullPath)) { return DIRECTORY_DOES_NOT_EXIST; } @@ -169,6 +225,15 @@ ReturnValue_t FileSystemHandler::removeDirectory(const char *repositoryPath, } else { // Check error code. Most probably denied permissions because folder is not empty + sif::warning << "FileSystemHandler::removeDirectory: Deleting directory failed with " + "code" << err.value() << ": " << strerror(err.value()) << std::endl; + if(err.value() == ENOTEMPTY) { + return DIRECTORY_NOT_EMPTY; + } + else { + return GENERIC_FILE_ERROR; + } + } } else { @@ -176,9 +241,23 @@ ReturnValue_t FileSystemHandler::removeDirectory(const char *repositoryPath, return HasReturnvaluesIF::RETURN_OK; } else { + sif::warning << "FileSystemHandler::removeDirectory: Deleting directory failed with " + "code" << err.value() << ": " << strerror(err.value()) << std::endl; // Check error code + if(err.value() == ENOTEMPTY) { + return DIRECTORY_NOT_EMPTY; + } + else { + return GENERIC_FILE_ERROR; + } } } return HasReturnvaluesIF::RETURN_OK; } + +void FileSystemHandler::parseCfg(FsCommandCfg *cfg, bool& useMountPrefix) { + if(cfg != nullptr) { + useMountPrefix = cfg->useMountPrefix; + } +} diff --git a/bsp_q7s/memory/FileSystemHandler.h b/bsp_q7s/memory/FileSystemHandler.h index 886fa574..22a7e7ae 100644 --- a/bsp_q7s/memory/FileSystemHandler.h +++ b/bsp_q7s/memory/FileSystemHandler.h @@ -15,6 +15,12 @@ class FileSystemHandler: public SystemObject, public ExecutableObjectIF, public HasFileSystemIF { public: + struct FsCommandCfg { + // Can be used to automatically use mount prefix of active SD card. + // Otherwise, the operator has to specify the full path to the mounted SD card as well. + bool useMountPrefix = false; + }; + FileSystemHandler(object_id_t fileSystemHandler); virtual~ FileSystemHandler(); @@ -28,27 +34,29 @@ public: */ MessageQueueId_t getCommandQueue() const override; -private: - MessageQueueIF* mq = nullptr; - std::string currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT; - static constexpr uint32_t FS_MAX_QUEUE_SIZE = config::OBSW_FILESYSTEM_HANDLER_QUEUE_SIZE; - SdCardManager* sdcMan = nullptr; - uint8_t opCounter = 0; - - void fileSystemHandlerLoop(); - void fileSystemCheckup(); - ReturnValue_t appendToFile(const char* repositoryPath, const char* filename, const uint8_t* data, size_t size, uint16_t packetNumber, void* args = nullptr) override; ReturnValue_t createFile(const char* repositoryPath, const char* filename, const uint8_t* data = nullptr, size_t size = 0, void* args = nullptr) override; - ReturnValue_t deleteFile(const char* repositoryPath, + ReturnValue_t removeFile(const char* repositoryPath, const char* filename, void* args = nullptr) override; ReturnValue_t createDirectory(const char* repositoryPath, void* args = nullptr) override; ReturnValue_t removeDirectory(const char* repositoryPath, bool deleteRecurively = false, void* args = nullptr) override; + +private: + MessageQueueIF* mq = nullptr; + std::string currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT; + static constexpr uint32_t FS_MAX_QUEUE_SIZE = config::OBSW_FILESYSTEM_HANDLER_QUEUE_SIZE; + + SdCardManager* sdcMan = nullptr; + uint8_t opCounter = 0; + + void fileSystemHandlerLoop(); + void fileSystemCheckup(); + void parseCfg(FsCommandCfg* cfg, bool& useMountPrefix); }; diff --git a/bsp_q7s/memory/SdCardManager.cpp b/bsp_q7s/memory/SdCardManager.cpp index 5a50665b..3dfa0b10 100644 --- a/bsp_q7s/memory/SdCardManager.cpp +++ b/bsp_q7s/memory/SdCardManager.cpp @@ -32,8 +32,10 @@ SdCardManager* SdCardManager::instance() { ReturnValue_t SdCardManager::switchOnSdCard(sd::SdCard sdCard, bool doMountSdCard, SdStatusPair* statusPair) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + std::unique_ptr sdStatusPtr; if(statusPair == nullptr) { - statusPair = std::make_unique().get(); + sdStatusPtr = std::make_unique(); + statusPair = sdStatusPtr.get(); result = getSdCardActiveStatus(*statusPair); if(result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -54,6 +56,10 @@ ReturnValue_t SdCardManager::switchOnSdCard(sd::SdCard sdCard, bool doMountSdCar else if(sdCard == sd::SdCard::SLOT_1) { targetStatus = statusPair->second; } + else { + // Should not happen + targetStatus = sd::SdStatus::OFF; + } auto switchCall = [&]() { if(targetStatus == sd::SdStatus::ON) { @@ -212,6 +218,11 @@ ReturnValue_t SdCardManager::unmountSdCard(sd::SdCard sdCard) { else if(sdCard == sd::SdCard::SLOT_1) { mountPoint = SD_1_MOUNT_POINT; } + if(not filesystem::exists(mountPoint)) { + sif::error << "SdCardManager::unmountSdCard: Default mount point " << mountPoint << + "does not exist" << std::endl; + return UNMOUNT_ERROR; + } if(filesystem::is_empty(mountPoint)) { // The mount point will always exist, but if it is empty, that is strong hint that // the SD card was not mounted properly. Still proceed with operation. @@ -226,26 +237,23 @@ ReturnValue_t SdCardManager::unmountSdCard(sd::SdCard sdCard) { return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t SdCardManager::sanitizeState(sd::SdCard* prefSdCard, SdStatusPair* statusPair) { - if(prefSdCard == nullptr) { - prefSdCard = std::make_unique(sd::SdCard::SLOT_0).get(); - getPreferredSdCard(*prefSdCard); +ReturnValue_t SdCardManager::sanitizeState(SdStatusPair* statusPair, sd::SdCard prefSdCard) { + std::unique_ptr sdStatusPtr; + if(prefSdCard == sd::SdCard::NONE) { + ReturnValue_t result = getPreferredSdCard(prefSdCard); + if(result != HasReturnvaluesIF::RETURN_OK) {} } if(statusPair == nullptr) { - statusPair = std::make_unique().get(); + sdStatusPtr = std::make_unique(); + statusPair = sdStatusPtr.get(); getSdCardActiveStatus(*statusPair); } - auto sanitizerFunc = [&](sd::SdCard prefSdCard) { - if(statusPair->first == sd::SdStatus::ON) { - return mountSdCard(prefSdCard); - } - else { - return switchOnSdCard(prefSdCard, true, statusPair); - } - }; + if(statusPair->first == sd::SdStatus::ON) { + return mountSdCard(prefSdCard); + } - return sanitizerFunc(*prefSdCard); + return switchOnSdCard(prefSdCard, true, statusPair); } void SdCardManager::processSdStatusLine(std::pair &active, @@ -331,3 +339,18 @@ ReturnValue_t SdCardManager::updateSdCardStateFile() { result << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } + +std::string SdCardManager::getCurrentMountPrefix(sd::SdCard prefSdCard) { + if(prefSdCard == sd::SdCard::NONE) { + ReturnValue_t result = getPreferredSdCard(prefSdCard); + if(result != HasReturnvaluesIF::RETURN_OK) { + return SD_0_MOUNT_POINT; + } + } + if(prefSdCard == sd::SdCard::SLOT_0) { + return SD_0_MOUNT_POINT; + } + else { + return SD_1_MOUNT_POINT; + } +} diff --git a/bsp_q7s/memory/SdCardManager.h b/bsp_q7s/memory/SdCardManager.h index 966e6e2a..7af57a67 100644 --- a/bsp_q7s/memory/SdCardManager.h +++ b/bsp_q7s/memory/SdCardManager.h @@ -3,12 +3,15 @@ #include "definitions.h" #include "returnvalues/classIds.h" +#include "events/subsystemIdRanges.h" +#include "fsfw/events/Event.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h" #include #include #include +#include class MutexIF; @@ -40,6 +43,10 @@ public: static constexpr ReturnValue_t SYSTEM_CALL_ERROR = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 14); + static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FILE_SYSTEM; + + static constexpr Event SANITIZATION_FAILED = event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW); + // C++17 does not support constexpr std::string yet static constexpr char SD_0_DEV_NAME[] = "/dev/mmcblk0p1"; static constexpr char SD_1_DEV_NAME[] = "/dev/mmcblk1p1"; @@ -137,14 +144,21 @@ public: * mounted one, this function will sanitize the state by attempting to mount the * currently preferred SD card. If the caller already has state information, it can be * passed into the function. - * @param prefSdCard Preferred SD card captured with #getPreferredSdCard * @param statusPair Current SD card status capture with #getSdCardActiveStatus + * @param prefSdCard Preferred SD card captured with #getPreferredSdCard * @throws std::bad_alloc if one of the two arguments was a nullptr and an allocation failed * @return */ - ReturnValue_t sanitizeState(sd::SdCard* prefSdCard = nullptr, - SdStatusPair* statusPair = nullptr); + ReturnValue_t sanitizeState(SdStatusPair* statusPair = nullptr, + sd::SdCard prefSdCard = sd::SdCard::NONE); + /** + * If sd::SdCard::NONE is passed as an argument, this funtion will get the currently + * preferred SD card from the scratch buffer. + * @param prefSdCardPtr + * @return + */ + std::string getCurrentMountPrefix(sd::SdCard prefSdCardPtr = sd::SdCard::NONE); private: SdCardManager(); @@ -153,6 +167,8 @@ private: void processSdStatusLine(SdStatusPair& active, std::string& line, uint8_t& idx, sd::SdCard& currentSd); + std::string currentPrefix; + static SdCardManager* factoryInstance; }; diff --git a/bsp_q7s/memory/definitions.h b/bsp_q7s/memory/definitions.h index 546a6585..9fcbee08 100644 --- a/bsp_q7s/memory/definitions.h +++ b/bsp_q7s/memory/definitions.h @@ -13,9 +13,10 @@ enum SdStatus: uint8_t { }; enum SdCard: uint8_t { - SLOT_0, - SLOT_1, - BOTH + SLOT_0 = 0, + SLOT_1 = 1, + BOTH, + NONE }; } diff --git a/bsp_q7s/memory/scratchApi.cpp b/bsp_q7s/memory/scratchApi.cpp index 0b159775..08d59df1 100644 --- a/bsp_q7s/memory/scratchApi.cpp +++ b/bsp_q7s/memory/scratchApi.cpp @@ -5,7 +5,44 @@ ReturnValue_t scratch::writeString(std::string name, std::string string) { oss << "xsc_scratch write " << name << " \"" << string << "\""; int result = std::system(oss.str().c_str()); if(result != 0) { - utility::handleSystemError(result, "scratch::String"); + utility::handleSystemError(result, "scratch::writeString"); + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t scratch::readString(std::string key, std::string &string) { + std::ifstream file; + std::string filename; + ReturnValue_t result = readToFile(key, file, filename); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + std::string line; + if (not std::getline(file, line)) { + std::remove(filename.c_str()); + return HasReturnvaluesIF::RETURN_FAILED; + } + + size_t pos = line.find("="); + if(pos == std::string::npos) { + sif::warning << "scratch::readNumber: Output file format invalid, " + "no \"=\" found" << std::endl; + // Could not find value + std::remove(filename.c_str()); + return KEY_NOT_FOUND; + } + string = line.substr(pos + 1); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t scratch::clearValue(std::string key) { + std::ostringstream oss; + oss << "xsc_scratch clear " << key; + int result = std::system(oss.str().c_str()); + if(result != 0) { + utility::handleSystemError(result, "scratch::clearValue"); return HasReturnvaluesIF::RETURN_FAILED; } return HasReturnvaluesIF::RETURN_OK; diff --git a/bsp_q7s/memory/scratchApi.h b/bsp_q7s/memory/scratchApi.h index eceda11a..ee19e084 100644 --- a/bsp_q7s/memory/scratchApi.h +++ b/bsp_q7s/memory/scratchApi.h @@ -4,6 +4,7 @@ #include "fsfw/returnvalues/HasReturnvaluesIF.h" #include "fsfw/serviceinterface/ServiceInterface.h" #include "linux/utility/utility.h" +#include "returnvalues/classIds.h" #include #include @@ -17,15 +18,86 @@ namespace scratch { static constexpr char PREFERED_SDC_KEY[] = "PREFSD"; +static constexpr char ALLOC_FAILURE_COUNT[] = "ALLOCERR"; +static constexpr uint8_t INTERFACE_ID = CLASS_ID::SCRATCH_BUFFER; +static constexpr ReturnValue_t KEY_NOT_FOUND = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 0); + +ReturnValue_t clearValue(std::string key); + +/** + * Write a string to the scratch buffer + * @param key + * @param string String to write + * @return + */ +ReturnValue_t writeString(std::string key, std::string string); +/** + * Read a string from the scratch buffer + * @param key + * @param string Will be set to read string + * @return + */ +ReturnValue_t readString(std::string key, std::string& string); + +/** + * Write a number to the scratch buffer + * @tparam T + * @tparam + * @param key + * @param num Number. Template allows to set signed, unsigned and floating point numbers + * @return + */ +template::value>::type> +inline ReturnValue_t writeNumber(std::string key, T num) noexcept; + +/** + * Read a number from the scratch buffer. + * @tparam T + * @tparam + * @param name + * @param num + * @return + */ +template::value>::type> +inline ReturnValue_t readNumber(std::string key, T& num) noexcept; + + +// Anonymous namespace namespace { + static uint8_t counter = 0; + +ReturnValue_t readToFile(std::string name, std::ifstream& file, std::string& filename) { + using namespace std; + filename = "/tmp/sro" + std::to_string(counter++); + ostringstream oss; + oss << "xsc_scratch read " << name << " > " << filename; + + int result = std::system(oss.str().c_str()); + if(result != 0) { + if(result == 256) { + sif::warning << "scratch::readNumber: Key " << name << " does not exist" << std::endl; + // Could not find value + std::remove(filename.c_str()); + return KEY_NOT_FOUND; + } + else { + utility::handleSystemError(result, "scratch::readNumber"); + std::remove(filename.c_str()); + return HasReturnvaluesIF::RETURN_FAILED; + } + } + file.open(filename); + return HasReturnvaluesIF::RETURN_OK; } +} // End of anonymous namespace + template::value>::type> -inline ReturnValue_t writeNumber(std::string name, T num) noexcept { +inline ReturnValue_t writeNumber(std::string key, T num) noexcept { std::ostringstream oss; - oss << "xsc_scratch write " << name << " " << num; + oss << "xsc_scratch write " << key << " " << std::to_string(num); int result = std::system(oss.str().c_str()); if(result != 0) { utility::handleSystemError(result, "scratch::writeNumber"); @@ -35,24 +107,30 @@ inline ReturnValue_t writeNumber(std::string name, T num) noexcept { } template::value>::type> -inline ReturnValue_t readNumber(std::string name, T& num) noexcept { +inline ReturnValue_t readNumber(std::string key, T& num) noexcept { using namespace std; - string filename = "/tmp/sro" + std::to_string(counter++); - ostringstream oss; - oss << "xsc_scratch read " << name << " > " << filename; - - int result = std::system(oss.str().c_str()); - if(result != 0) { - utility::handleSystemError(result, "scratch::writeNumber"); - return HasReturnvaluesIF::RETURN_FAILED; + ifstream file; + std::string filename; + ReturnValue_t result = readToFile(key, file, filename); + if(result != HasReturnvaluesIF::RETURN_OK) { + std::remove(filename.c_str()); + return result; } - ifstream file(filename); + string line; if (not std::getline(file, line)) { + std::remove(filename.c_str()); return HasReturnvaluesIF::RETURN_FAILED; } size_t pos = line.find("="); + if(pos == string::npos) { + sif::warning << "scratch::readNumber: Output file format invalid, " + "no \"=\" found" << std::endl; + // Could not find value + std::remove(filename.c_str()); + return KEY_NOT_FOUND; + } std::string valueAsString = line.substr(pos + 1); try { num = std::stoi(valueAsString); @@ -65,8 +143,6 @@ inline ReturnValue_t readNumber(std::string name, T& num) noexcept { return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t writeString(std::string name, std::string string); - } #endif /* BSP_Q7S_MEMORY_SCRATCHAPI_H_ */ diff --git a/bsp_q7s/spi/Q7sSpiComIF.h b/bsp_q7s/spi/Q7sSpiComIF.h index a10d63dd..4326bf8c 100644 --- a/bsp_q7s/spi/Q7sSpiComIF.h +++ b/bsp_q7s/spi/Q7sSpiComIF.h @@ -1,7 +1,7 @@ #ifndef BSP_Q7S_SPI_Q7SSPICOMIF_H_ #define BSP_Q7S_SPI_Q7SSPICOMIF_H_ -#include +#include /** diff --git a/bsp_q7s/spiCallbacks/rwSpiCallback.cpp b/bsp_q7s/spiCallbacks/rwSpiCallback.cpp index f05fbbdf..0f60288f 100644 --- a/bsp_q7s/spiCallbacks/rwSpiCallback.cpp +++ b/bsp_q7s/spiCallbacks/rwSpiCallback.cpp @@ -1,8 +1,8 @@ #include #include #include -#include -#include +#include +#include #include "devices/gpioIds.h" namespace rwSpiCallback { diff --git a/bsp_q7s/spiCallbacks/rwSpiCallback.h b/bsp_q7s/spiCallbacks/rwSpiCallback.h index e5a79e64..fd7f1592 100644 --- a/bsp_q7s/spiCallbacks/rwSpiCallback.h +++ b/bsp_q7s/spiCallbacks/rwSpiCallback.h @@ -2,8 +2,8 @@ #define BSP_Q7S_RW_SPI_CALLBACK_H_ #include -#include -#include +#include +#include namespace rwSpiCallback { diff --git a/cmake/BBBCrossCompileConfig.cmake b/cmake/BBBCrossCompileConfig.cmake index e1a669db..fcbab882 100644 --- a/cmake/BBBCrossCompileConfig.cmake +++ b/cmake/BBBCrossCompileConfig.cmake @@ -1,20 +1,22 @@ -# BBB_ROOTFS should point to the local directory which contains all the +# LINUX_ROOTFS should point to the local directory which contains all the # libraries and includes from the target raspi. # The following command can be used to do this, replace and the # local accordingly: # rsync -vR --progress -rl --delete-after --safe-links pi@:/{lib,usr,opt/vc/lib} -# RASPBIAN_ROOTFS needs to be passed to the CMake command or defined in the +# LINUX_ROOTFS needs to be passed to the CMake command or defined in the # application CMakeLists.txt before loading the toolchain file. # CROSS_COMPILE also needs to be set accordingly or passed to the CMake command - -if(NOT DEFINED ENV{BBB_ROOTFS}) - message(FATAL_ERROR - "Define the BBB_ROOTFS variable to point to the Beagle Bone Black rootfs." - ) +if(NOT DEFINED ENV{LINUX_ROOTFS}) + # Sysroot has not been cached yet and was not set in environment either + if(NOT SYSROOT_PATH) + message(FATAL_ERROR + "Define the LINUX_ROOTFS variable to point to the Raspberry Pi rootfs." + ) + endif() else() - set(SYSROOT_PATH "$ENV{BBB_ROOTFS}" CACHE FILEPATH "BBB root filesystem path") - message(STATUS "Beagle Bone Black sysroot: ${SYSROOT_PATH}") + set(SYSROOT_PATH "$ENV{LINUX_ROOTFS}" CACHE PATH "Local linux root filesystem path") + message(STATUS "Raspberry Pi sysroot: ${SYSROOT_PATH}") endif() if(NOT DEFINED ENV{CROSS_COMPILE}) @@ -31,6 +33,15 @@ else() ) endif() +# Generally, the debian roots will be a multiarch rootfs where some libraries are put +# into a folder named "arm-linux-gnueabihf". The user can override the folder name if this is +# not the case +if(NOT ENV{MULTIARCH_FOLDER_NAME}) + set(MULTIARCH_FOLDER_NAME "arm-linux-gnueabihf") +else() + set(MUTLIARCH_FOLDER_NAME $ENV{MULTIARCH_FOLDER_NAME}) +endif() + message(STATUS "Using sysroot path: ${SYSROOT_PATH}") set(CROSS_COMPILE_CC "${CROSS_COMPILE}-gcc") @@ -44,8 +55,11 @@ set(CROSS_COMPILE_OBJCOPY "${CROSS_COMPILE}-objcopy") set(CROSS_COMPILE_SIZE "${CROSS_COMPILE}-size") # At the very least, cross compile gcc and g++ have to be set! -find_program (CROSS_COMPILE_CC_FOUND ${CROSS_COMPILE_CC} REQUIRED) -find_program (CROSS_COMPILE_CXX_FOUND ${CROSS_COMPILE_CXX} REQUIRED) +find_program (CMAKE_C_COMPILER ${CROSS_COMPILE_CC} REQUIRED) +find_program (CMAKE_CXX_COMPILER ${CROSS_COMPILE_CXX} REQUIRED) +# Useful utilities, not strictly necessary +find_program(CMAKE_SIZE ${CROSS_COMPILE_SIZE}) +find_program(CMAKE_OBJCOPY ${CROSS_COMPILE_OBJCOPY}) set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_SYSROOT "${SYSROOT_PATH}") @@ -54,16 +68,12 @@ set(CMAKE_SYSROOT "${SYSROOT_PATH}") set(CMAKE_SYSTEM_NAME "Linux") set(CMAKE_SYSTEM_PROCESSOR "arm") -# Define the compiler -set(CMAKE_C_COMPILER ${CROSS_COMPILE_CC}) -set(CMAKE_CXX_COMPILER ${CROSS_COMPILE_CXX}) - # List of library dirs where LD has to look. Pass them directly through gcc. # LD_LIBRARY_PATH is not evaluated by arm-*-ld set(LIB_DIRS - "${SYSROOT_PATH}/lib/${CROSS_COMPILE}" + "${SYSROOT_PATH}/lib/${MUTLIARCH_FOLDER_NAME}" "${SYSROOT_PATH}/usr/local/lib" - "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}" + "${SYSROOT_PATH}/usr/lib/${MUTLIARCH_FOLDER_NAME}" "${SYSROOT_PATH}/usr/lib" ) # You can additionally check the linker paths if you add the @@ -73,11 +83,6 @@ foreach(LIB ${LIB_DIRS}) set(COMMON_FLAGS "${COMMON_FLAGS} -L${LIB} -Wl,-rpath-link,${LIB}") endforeach() -set(CMAKE_PREFIX_PATH - "${CMAKE_PREFIX_PATH}" - "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}" -) - set(CMAKE_C_FLAGS "-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard ${COMMON_FLAGS}" CACHE STRING "Flags for Beagle Bone Black" diff --git a/cmake/HardwareOsPreConfig.cmake b/cmake/HardwareOsPreConfig.cmake index 38248fce..535f9b9e 100644 --- a/cmake/HardwareOsPreConfig.cmake +++ b/cmake/HardwareOsPreConfig.cmake @@ -1,13 +1,13 @@ function(pre_source_hw_os_config) # FreeRTOS -if(${OS_FSFW} MATCHES freertos) +if(FSFW_OSAL MATCHES freertos) message(FATAL_ERROR "No FreeRTOS support implemented yet.") # RTEMS -elseif(${OS_FSFW} STREQUAL rtems) +elseif(FSFW_OSAL STREQUAL rtems) add_definitions(-DRTEMS) message(FATAL_ERROR "No RTEMS support implemented yet.") -elseif(${OS_FSFW} STREQUAL linux) +elseif(FSFW_OSAL STREQUAL linux) add_definitions(-DUNIX -DLINUX) find_package(Threads REQUIRED) # Hosted diff --git a/cmake/PreProjectConfig.cmake b/cmake/PreProjectConfig.cmake index 8a013d83..9f1790bb 100644 --- a/cmake/PreProjectConfig.cmake +++ b/cmake/PreProjectConfig.cmake @@ -2,31 +2,31 @@ function(pre_project_config) # Basic input sanitization if(DEFINED TGT_BSP) - if(${TGT_BSP} MATCHES "arm/raspberrypi" AND NOT ${OS_FSFW} MATCHES linux) + if(${TGT_BSP} MATCHES "arm/raspberrypi" AND NOT FSFW_OSAL MATCHES linux) message(STATUS "FSFW OSAL invalid for specified target BSP ${TGT_BSP}!") - message(STATUS "Setting valid OS_FSFW: linux") - set(OS_FSFW "linux") + message(STATUS "Setting valid FSFW_OSAL: linux") + set(FSFW_OSAL "linux") endif() endif() # Disable compiler checks for cross-compiling. -if(${OS_FSFW} STREQUAL linux AND TGT_BSP) - if(${TGT_BSP} MATCHES "arm/q7s") +if(FSFW_OSAL MATCHES linux AND TGT_BSP) + if(TGT_BSP MATCHES "arm/q7s") set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SCRIPT_PATH}/Q7SCrossCompileConfig.cmake" PARENT_SCOPE ) - elseif (${TGT_BSP} MATCHES "arm/raspberrypi") - if(NOT DEFINED ENV{RASPBIAN_ROOTFS}) - if(NOT DEFINED RASPBIAN_ROOTFS) - message(WARNING "No RASPBIAN_ROOTFS environmental or CMake variable set!") - set(ENV{RASPBIAN_ROOTFS} "$ENV{HOME}/raspberrypi/rootfs") + elseif(TGT_BSP MATCHES "arm/raspberrypi") + if(NOT DEFINED ENV{LINUX_ROOTFS}) + if(NOT DEFINED LINUX_ROOTFS) + message(WARNING "No LINUX_ROOTFS environmental or CMake variable set!") + set(ENV{LINUX_ROOTFS} "$ENV{HOME}/raspberrypi/rootfs") else() - set(ENV{RASPBIAN_ROOTFS} "${RASPBIAN_ROOTFS}") + set(ENV{LINUX_ROOTFS} "${LINUX_ROOTFS}") endif() else() message(STATUS - "RASPBIAN_ROOTFS from environmental variables used: $ENV{RASPBIAN_ROOTFS}" + "LINUX_ROOTFS from environmental variables used: $ENV{LINUX_ROOTFS}" ) endif() diff --git a/cmake/Q7SCrossCompileConfig.cmake b/cmake/Q7SCrossCompileConfig.cmake index bc95a909..746df453 100644 --- a/cmake/Q7SCrossCompileConfig.cmake +++ b/cmake/Q7SCrossCompileConfig.cmake @@ -1,10 +1,11 @@ # CROSS_COMPILE also needs to be set accordingly or passed to the CMake command - if(NOT DEFINED ENV{Q7S_SYSROOT}) -# message(FATAL_ERROR -# "Define the Q7S_ROOTFS variable to " -# "point to the raspbian rootfs." -# ) + # Sysroot has not been cached yet and was not set in environment either + if(NOT DEFINED SYSROOT_PATH) + message(FATAL_ERROR + "Define the Q7S_ROOTFS variable to point to the Q7S rootfs." + ) + endif() else() set(SYSROOT_PATH "$ENV{Q7S_SYSROOT}" CACHE PATH "Q7S root filesystem path") endif() @@ -36,8 +37,11 @@ set(CROSS_COMPILE_OBJCOPY "${CROSS_COMPILE}-objcopy") set(CROSS_COMPILE_SIZE "${CROSS_COMPILE}-size") # At the very least, cross compile gcc and g++ have to be set! -find_program (CROSS_COMPILE_CC_FOUND ${CROSS_COMPILE_CC} REQUIRED) -find_program (CROSS_COMPILE_CXX_FOUND ${CROSS_COMPILE_CXX} REQUIRED) +find_program (CMAKE_C_COMPILER ${CROSS_COMPILE_CC} REQUIRED) +find_program (CMAKE_CXX_COMPILER ${CROSS_COMPILE_CXX} REQUIRED) +# Useful utilities, not strictly necessary +find_program(CMAKE_SIZE ${CROSS_COMPILE_SIZE}) +find_program(CMAKE_OBJCOPY ${CROSS_COMPILE_OBJCOPY}) set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_SYSROOT "${SYSROOT_PATH}") diff --git a/cmake/RPiCrossCompileConfig.cmake b/cmake/RPiCrossCompileConfig.cmake index 1f246443..5806af59 100644 --- a/cmake/RPiCrossCompileConfig.cmake +++ b/cmake/RPiCrossCompileConfig.cmake @@ -1,7 +1,7 @@ # Based on https://github.com/Pro/raspi-toolchain but rewritten completely. # Adapted for the FSFW Example -if(NOT $ENV{RASPBERRY_VERSION}) +if(NOT DEFINED ENV{RASPBERRY_VERSION}) message(STATUS "Raspberry Pi version not specified, setting version 4!") set(RASPBERRY_VERSION 4) else() @@ -9,23 +9,25 @@ else() endif() -# RASPBIAN_ROOTFS should point to the local directory which contains all the +# LINUX_ROOTFS should point to the local directory which contains all the # libraries and includes from the target raspi. # The following command can be used to do this, replace and the # local accordingly: # rsync -vR --progress -rl --delete-after --safe-links pi@:/{lib,usr,opt/vc/lib} -# RASPBIAN_ROOTFS needs to be passed to the CMake command or defined in the +# LINUX_ROOTFS needs to be passed to the CMake command or defined in the # application CMakeLists.txt before loading the toolchain file. # CROSS_COMPILE also needs to be set accordingly or passed to the CMake command - -if(NOT DEFINED ENV{RASPBIAN_ROOTFS}) - message(FATAL_ERROR - "Define the RASPBIAN_ROOTFS variable to " - "point to the raspbian rootfs." - ) +if(NOT DEFINED ENV{LINUX_ROOTFS}) + # Sysroot has not been cached yet and was not set in environment either + if(NOT SYSROOT_PATH) + message(FATAL_ERROR + "Define the LINUX_ROOTFS variable to point to the Raspberry Pi rootfs." + ) + endif() else() - set(SYSROOT_PATH "$ENV{RASPBIAN_ROOTFS}" CACHE FILEPATH "RPi root filesystem path") + set(SYSROOT_PATH "$ENV{LINUX_ROOTFS}" CACHE PATH "Local linux root filesystem path") + message(STATUS "Raspberry Pi sysroot: ${SYSROOT_PATH}") endif() if(NOT DEFINED ENV{CROSS_COMPILE}) @@ -42,6 +44,15 @@ else() ) endif() +# Generally, the debian roots will be a multiarch rootfs where some libraries are put +# into a folder named "arm-linux-gnueabihf". The user can override the folder name if this is +# not the case +if(NOT ENV{MULTIARCH_FOLDER_NAME}) + set(MULTIARCH_FOLDER_NAME "arm-linux-gnueabihf") +else() + set(MUTLIARCH_FOLDER_NAME $ENV{MULTIARCH_FOLDER_NAME}) +endif() + message(STATUS "Using sysroot path: ${SYSROOT_PATH}") set(CROSS_COMPILE_CC "${CROSS_COMPILE}-gcc") @@ -55,8 +66,11 @@ set(CROSS_COMPILE_OBJCOPY "${CROSS_COMPILE}-objcopy") set(CROSS_COMPILE_SIZE "${CROSS_COMPILE}-size") # At the very least, cross compile gcc and g++ have to be set! -find_program (CROSS_COMPILE_CC_FOUND ${CROSS_COMPILE_CC} REQUIRED) -find_program (CROSS_COMPILE_CXX_FOUND ${CROSS_COMPILE_CXX} REQUIRED) +find_program (CMAKE_C_COMPILER ${CROSS_COMPILE_CC} REQUIRED) +find_program (CMAKE_CXX_COMPILER ${CROSS_COMPILE_CXX} REQUIRED) +# Useful utilities, not strictly necessary +find_program(CMAKE_SIZE ${CROSS_COMPILE_SIZE}) +find_program(CMAKE_OBJCOPY ${CROSS_COMPILE_OBJCOPY}) set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_SYSROOT "${SYSROOT_PATH}") @@ -69,22 +83,16 @@ else() set(CMAKE_SYSTEM_PROCESSOR "arm") endif() -# Define the compiler -set(CMAKE_C_COMPILER ${CROSS_COMPILE_CC}) -set(CMAKE_CXX_COMPILER ${CROSS_COMPILE_CXX}) - # List of library dirs where LD has to look. Pass them directly through gcc. # LD_LIBRARY_PATH is not evaluated by arm-*-ld set(LIB_DIRS - "/opt/cross-pi-gcc/arm-linux-gnueabihf/lib" - "/opt/cross-pi-gcc/lib" "${SYSROOT_PATH}/opt/vc/lib" - "${SYSROOT_PATH}/lib/${CROSS_COMPILE}" + "${SYSROOT_PATH}/lib/${MULTIARCH_FOLDER_NAME}" "${SYSROOT_PATH}/usr/local/lib" - "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}" + "${SYSROOT_PATH}/usr/lib/${MULTIARCH_FOLDER_NAME}" "${SYSROOT_PATH}/usr/lib" - "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}/blas" - "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}/lapack" + "${SYSROOT_PATH}/usr/lib/${MULTIARCH_FOLDER_NAME}/blas" + "${SYSROOT_PATH}/usr/lib/${MULTIARCH_FOLDER_NAME}/lapack" ) # You can additionally check the linker paths if you add the # flags ' -Xlinker --verbose' @@ -93,43 +101,38 @@ foreach(LIB ${LIB_DIRS}) set(COMMON_FLAGS "${COMMON_FLAGS} -L${LIB} -Wl,-rpath-link,${LIB}") endforeach() -set(CMAKE_PREFIX_PATH - "${CMAKE_PREFIX_PATH}" - "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}" -) - if(RASPBERRY_VERSION VERSION_GREATER 3) set(CMAKE_C_FLAGS "-mcpu=cortex-a72 -mfpu=neon-vfpv4 -mfloat-abi=hard ${COMMON_FLAGS}" - CACHE STRING "CPP flags for Raspberry PI 4" + CACHE STRING "Flags for Raspberry Pi 4" ) set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}" - CACHE STRING "C flags for Raspberry PI 4" + CACHE STRING "Flags for Raspberry Pi 4" ) elseif(RASPBERRY_VERSION VERSION_GREATER 2) set(CMAKE_C_FLAGS "-mcpu=cortex-a53 -mfpu=neon-vfpv4 -mfloat-abi=hard ${COMMON_FLAGS}" - CACHE STRING "C flags for Raspberry PI 3" + CACHE STRING "Flags for Raspberry Pi 3" ) set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}" - CACHE STRING "CPP flags for Raspberry PI 3" + CACHE STRING "Flags for Raspberry Pi 3" ) elseif(RASPBERRY_VERSION VERSION_GREATER 1) set(CMAKE_C_FLAGS "-mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard ${COMMON_FLAGS}" - CACHE STRING "C flags for Raspberry PI 2" + CACHE STRING "Flags for Raspberry Pi 2" ) set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}" - CACHE STRING "CPP flags for Raspberry PI 2" + CACHE STRING "Flags for Raspberry Pi 2" ) else() set(CMAKE_C_FLAGS "-mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard ${COMMON_FLAGS}" - CACHE STRING "C flags for Raspberry PI 1 B+ Zero" + CACHE STRING "Flags for Raspberry Pi 1 B+ Zero" ) set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}" - CACHE STRING "CPP flags for Raspberry PI 1 B+ Zero" + CACHE STRING "Flags for Raspberry PI 1 B+ Zero" ) endif() @@ -137,7 +140,6 @@ set(CMAKE_FIND_ROOT_PATH "${CMAKE_INSTALL_PREFIX};${CMAKE_PREFIX_PATH};${CMAKE_SYSROOT}" ) - # search for programs in the build host directories set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # for libraries and headers in the target directories diff --git a/cmake/scripts/Q7S/ninja_debug_cfg.sh b/cmake/scripts/Q7S/ninja_debug_cfg.sh index 2d3b333f..abb68de2 100755 --- a/cmake/scripts/Q7S/ninja_debug_cfg.sh +++ b/cmake/scripts/Q7S/ninja_debug_cfg.sh @@ -28,6 +28,6 @@ fi echo "Running command (without the leading +):" set -x # Print command ${python} cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -t "${tgt_bsp}" \ - -l"${build_dir}" + -l "${build_dir}" # set +x diff --git a/cmake/scripts/Q7S/ninja_release_cfg.sh b/cmake/scripts/Q7S/ninja_release_cfg.sh new file mode 100755 index 00000000..f5431d9a --- /dev/null +++ b/cmake/scripts/Q7S/ninja_release_cfg.sh @@ -0,0 +1,33 @@ +#!/bin/sh +counter=0 +while [ ${counter} -lt 5 ] +do + cd .. + if [ -f "cmake_build_config.py" ];then + break + fi + counter=$((counter=counter + 1)) +done + +if [ "${counter}" -ge 5 ];then + echo "cmake_build_config.py not found in upper directories!" + exit 1 +fi + +os_fsfw="linux" +tgt_bsp="arm/q7s" +build_dir="build-Release-Q7S" +build_generator="Ninja" +if [ "${OS}" = "Windows_NT" ]; then + python="py" +# Could be other OS but this works for now. +else + python="python3" +fi + +echo "Running command (without the leading +):" +set -x # Print command +${python} cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "release" -t "${tgt_bsp}" \ + -l"${build_dir}" +# set +x + diff --git a/cmake/scripts/cmake_build_config.py b/cmake/scripts/cmake_build_config.py index 67f175d9..e3259fd4 100755 --- a/cmake/scripts/cmake_build_config.py +++ b/cmake/scripts/cmake_build_config.py @@ -98,7 +98,7 @@ def main(): print(f"Navigating into build directory: {build_path}") os.chdir(build_folder) - cmake_command = f"cmake {generator_cmake_arg} -DOS_FSFW=\"{osal}\" " \ + cmake_command = f"cmake {generator_cmake_arg} -DFSFW_OSAL=\"{osal}\" " \ f"-DCMAKE_BUILD_TYPE=\"{cmake_build_type}\" {cmake_target_cfg_cmd} " \ f"{define_string} {source_location}" # Remove redundant spaces diff --git a/common/config/OBSWVersion.h b/common/config/OBSWVersion.h index b796f146..8f5b9574 100644 --- a/common/config/OBSWVersion.h +++ b/common/config/OBSWVersion.h @@ -4,7 +4,7 @@ const char* const SW_NAME = "eive"; #define SW_VERSION 1 -#define SW_SUBVERSION 3 +#define SW_SUBVERSION 4 #define SW_SUBSUBVERSION 0 #endif /* COMMON_CONFIG_OBSWVERSION_H_ */ diff --git a/common/config/commonClassIds.h b/common/config/commonClassIds.h index 8a4a8121..977cbdb2 100644 --- a/common/config/commonClassIds.h +++ b/common/config/commonClassIds.h @@ -14,7 +14,9 @@ enum commonClassIds: uint8_t { SYRLINKS_HANDLER, //SYRLINKS IMTQ_HANDLER, //IMTQ RW_HANDLER, //Reaction Wheels - PLOC_HANDLER, //PLOC + STR_HANDLER, //Star tracker + PLOC_MPSOC_HANDLER, //PLOC MPSoC + PLOC_SUPERVISOR_HANDLER, //PLOC Supervisor SUS_HANDLER, //SUSS CCSDS_IP_CORE_BRIDGE, // IP Core interface COMMON_CLASS_ID_END // [EXPORT] : [END] diff --git a/common/config/commonObjects.h b/common/config/commonObjects.h index 1fb755e3..0505e570 100644 --- a/common/config/commonObjects.h +++ b/common/config/commonObjects.h @@ -10,6 +10,7 @@ enum commonObjects: uint32_t { PUS_PACKET_DISTRIBUTOR = 0x50000200, UDP_BRIDGE = 0x50000300, UDP_POLLING_TASK = 0x50000400, + FILE_SYSTEM_HANDLER = 0x50000500, /* 0x43 ('C') for Controllers */ THERMAL_CONTROLLER = 0x43400001, @@ -33,7 +34,8 @@ enum commonObjects: uint32_t { GYRO_3_L3G_HANDLER = 0x44120313, IMTQ_HANDLER = 0x44140014, - PLOC_HANDLER = 0x44330015, + PLOC_MPSOC_HANDLER = 0x44330015, + PLOC_SUPERVISOR_HANDLER = 0x44330016, /** * Not yet specified which pt1000 will measure which device/location in the satellite. @@ -73,10 +75,12 @@ enum commonObjects: uint32_t { GPS0_HANDLER = 0x44130045, GPS1_HANDLER = 0x44130146, - RW1 = 0x44210001, - RW2 = 0x44210002, - RW3 = 0x44210003, - RW4 = 0x44210004 + RW1 = 0x44120001, + RW2 = 0x44120002, + RW3 = 0x44120003, + RW4 = 0x44120004, + + START_TRACKER = 0x44130001 }; } diff --git a/common/config/commonSubsystemIds.h b/common/config/commonSubsystemIds.h index bc2fe400..7c2cb605 100644 --- a/common/config/commonSubsystemIds.h +++ b/common/config/commonSubsystemIds.h @@ -11,9 +11,12 @@ enum: uint8_t { PCDU_HANDLER = 108, HEATER_HANDLER = 109, SA_DEPL_HANDLER = 110, - PLOC_HANDLER = 111, + PLOC_MPSOC_HANDLER = 111, IMTQ_HANDLER = 112, RW_HANDLER = 113, + STR_HANDLER = 114, + PLOC_SUPERVISOR_HANDLER = 115, + FILE_SYSTEM = 116, COMMON_SUBSYSTEM_ID_END }; } diff --git a/common/config/spiConf.h b/common/config/spiConf.h index 47600eb3..05866555 100644 --- a/common/config/spiConf.h +++ b/common/config/spiConf.h @@ -2,7 +2,7 @@ #define COMMON_CONFIG_SPICONF_H_ #include -#include +#include /** * SPI configuration will be contained here to let the device handlers remain independent diff --git a/doc/XSC-1542-6025-i_Q7RevB_User_Manual.pdf b/doc/XSC-1542-6025-i_Q7RevB_User_Manual.pdf new file mode 100644 index 00000000..0ab87985 Binary files /dev/null and b/doc/XSC-1542-6025-i_Q7RevB_User_Manual.pdf differ diff --git a/doc/Q7S-user-manual.pdf b/doc/deprecated-Q7S-user-manual14042020.pdf similarity index 100% rename from doc/Q7S-user-manual.pdf rename to doc/deprecated-Q7S-user-manual14042020.pdf diff --git a/fsfw b/fsfw index da8a4470..b8325959 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit da8a4470734808bed4d872e47c192af694382c41 +Subproject commit b83259592a1f0ae5af20b00d1aef813fa26cd350 diff --git a/fsfw_hal b/fsfw_hal deleted file mode 160000 index 8ff09c95..00000000 --- a/fsfw_hal +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8ff09c95a69f1f43fec6104d6cce1e788b2b870d diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index c895aebb..d19a79a3 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -77,10 +77,10 @@ 8901;CLOCK_SET_FAILURE;LOW; ;../../fsfw/pus/Service9TimeManagement.h 9700;TEST;INFO; ;../../fsfw/pus/Service17Test.h 10600;CHANGE_OF_SETUP_PARAMETER;LOW; ;../../mission/devices/MGMHandlerLIS3MDL.h -11101;MEMORY_READ_RPT_CRC_FAILURE;LOW; ;../../mission/devices/PlocHandler.h -11102;ACK_FAILURE;LOW; ;../../mission/devices/PlocHandler.h -11103;EXE_FAILURE;LOW; ;../../mission/devices/PlocHandler.h -11104;CRC_FAILURE_EVENT;LOW; ;../../mission/devices/PlocHandler.h +11101;MEMORY_READ_RPT_CRC_FAILURE;LOW; ;../../mission/devices/PlocMPSoCHandler.h +11102;ACK_FAILURE;LOW; ;../../mission/devices/PlocMPSoCHandler.h +11103;EXE_FAILURE;LOW; ;../../mission/devices/PlocMPSoCHandler.h +11104;CRC_FAILURE_EVENT;LOW; ;../../mission/devices/PlocMPSoCHandler.h 11201;SELF_TEST_I2C_FAILURE;LOW; ;../../mission/devices/IMTQHandler.h 11202;SELF_TEST_SPI_FAILURE;LOW; ;../../mission/devices/IMTQHandler.h 11203;SELF_TEST_ADC_FAILURE;LOW; ;../../mission/devices/IMTQHandler.h @@ -90,3 +90,7 @@ 11207;SELF_TEST_COIL_CURRENT_FAILURE;LOW; ;../../mission/devices/IMTQHandler.h 11208;INVALID_ERROR_BYTE;LOW; ;../../mission/devices/IMTQHandler.h 11301;ERROR_STATE;HIGH; ;../../mission/devices/RwHandler.h +11501;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW; ;../../mission/devices/PlocSupervisorHandler.h +11502;SUPV_ACK_FAILURE;LOW; ;../../mission/devices/PlocSupervisorHandler.h +11503;SUPV_EXE_FAILURE;LOW; ;../../mission/devices/PlocSupervisorHandler.h +11504;SUPV_CRC_FAILURE_EVENT;LOW; ;../../mission/devices/PlocSupervisorHandler.h diff --git a/generators/bsp_q7s_objects.csv b/generators/bsp_q7s_objects.csv index e0180089..cf3e082a 100644 --- a/generators/bsp_q7s_objects.csv +++ b/generators/bsp_q7s_objects.csv @@ -2,6 +2,10 @@ 0x43000003;CORE_CONTROLLER 0x43100002;ACS_CONTROLLER 0x43400001;THERMAL_CONTROLLER +0x44120001;RW1 +0x44120002;RW2 +0x44120003;RW3 +0x44120004;RW4 0x44120006;MGM_0_LIS3_HANDLER 0x44120010;GYRO_0_ADIS_HANDLER 0x44120032;SUS_1 @@ -23,20 +27,18 @@ 0x44120212;GYRO_2_ADIS_HANDLER 0x44120309;MGM_3_RM3100_HANDLER 0x44120313;GYRO_3_L3G_HANDLER +0x44130001;START_TRACKER 0x44130045;GPS0_HANDLER 0x44130146;GPS1_HANDLER 0x44140014;IMTQ_HANDLER 0x442000A1;PCDU_HANDLER -0x44210001;RW1 -0x44210002;RW2 -0x44210003;RW3 -0x44210004;RW4 0x44250000;P60DOCK_HANDLER 0x44250001;PDU1_HANDLER 0x44250002;PDU2_HANDLER 0x44250003;ACU_HANDLER 0x443200A5;RAD_SENSOR -0x44330015;PLOC_HANDLER +0x44330015;PLOC_MPSOC_HANDLER +0x44330016;PLOC_SUPERVISOR_HANDLER 0x444100A2;SOLAR_ARRAY_DEPL_HANDLER 0x444100A4;HEATER_HANDLER 0x44420004;TMP1075_HANDLER_1 diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 9ae81646..20521618 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 92 translations. + * @brief Auto-generated event translation file. Contains 96 translations. * @details - * Generated on: 2021-06-29 16:20:09 + * Generated on: 2021-07-12 15:20:38 */ #include "translateEvents.h" @@ -97,6 +97,10 @@ const char *SELF_TEST_MTM_RANGE_FAILURE_STRING = "SELF_TEST_MTM_RANGE_FAILURE"; const char *SELF_TEST_COIL_CURRENT_FAILURE_STRING = "SELF_TEST_COIL_CURRENT_FAILURE"; const char *INVALID_ERROR_BYTE_STRING = "INVALID_ERROR_BYTE"; const char *ERROR_STATE_STRING = "ERROR_STATE"; +const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE"; +const char *SUPV_ACK_FAILURE_STRING = "SUPV_ACK_FAILURE"; +const char *SUPV_EXE_FAILURE_STRING = "SUPV_EXE_FAILURE"; +const char *SUPV_CRC_FAILURE_EVENT_STRING = "SUPV_CRC_FAILURE_EVENT"; const char * translateEvents(Event event) { switch( (event & 0xffff) ) { @@ -284,6 +288,14 @@ const char * translateEvents(Event event) { return INVALID_ERROR_BYTE_STRING; case(11301): return ERROR_STATE_STRING; + case(11501): + return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING; + case(11502): + return SUPV_ACK_FAILURE_STRING; + case(11503): + return SUPV_EXE_FAILURE_STRING; + case(11504): + return SUPV_CRC_FAILURE_EVENT_STRING; default: return "UNKNOWN_EVENT"; } diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index 2068158b..cf9db4ca 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -1,8 +1,8 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 100 translations. - * Generated on: 2021-06-29 16:19:57 + * Contains 102 translations. + * Generated on: 2021-07-10 16:22:55 */ #include "translateObjects.h" @@ -10,6 +10,10 @@ const char *P60DOCK_TEST_TASK_STRING = "P60DOCK_TEST_TASK"; const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER"; const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER"; const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER"; +const char *RW1_STRING = "RW1"; +const char *RW2_STRING = "RW2"; +const char *RW3_STRING = "RW3"; +const char *RW4_STRING = "RW4"; const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER"; const char *GYRO_0_ADIS_HANDLER_STRING = "GYRO_0_ADIS_HANDLER"; const char *SUS_1_STRING = "SUS_1"; @@ -31,20 +35,18 @@ const char *MGM_2_LIS3_HANDLER_STRING = "MGM_2_LIS3_HANDLER"; const char *GYRO_2_ADIS_HANDLER_STRING = "GYRO_2_ADIS_HANDLER"; const char *MGM_3_RM3100_HANDLER_STRING = "MGM_3_RM3100_HANDLER"; const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER"; +const char *START_TRACKER_STRING = "START_TRACKER"; const char *GPS0_HANDLER_STRING = "GPS0_HANDLER"; const char *GPS1_HANDLER_STRING = "GPS1_HANDLER"; const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER"; const char *PCDU_HANDLER_STRING = "PCDU_HANDLER"; -const char *RW1_STRING = "RW1"; -const char *RW2_STRING = "RW2"; -const char *RW3_STRING = "RW3"; -const char *RW4_STRING = "RW4"; const char *P60DOCK_HANDLER_STRING = "P60DOCK_HANDLER"; const char *PDU1_HANDLER_STRING = "PDU1_HANDLER"; const char *PDU2_HANDLER_STRING = "PDU2_HANDLER"; const char *ACU_HANDLER_STRING = "ACU_HANDLER"; const char *RAD_SENSOR_STRING = "RAD_SENSOR"; -const char *PLOC_HANDLER_STRING = "PLOC_HANDLER"; +const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER"; +const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER"; const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER"; const char *HEATER_HANDLER_STRING = "HEATER_HANDLER"; const char *TMP1075_HANDLER_1_STRING = "TMP1075_HANDLER_1"; @@ -117,6 +119,14 @@ const char* translateObject(object_id_t object) { return ACS_CONTROLLER_STRING; case 0x43400001: return THERMAL_CONTROLLER_STRING; + case 0x44120001: + return RW1_STRING; + case 0x44120002: + return RW2_STRING; + case 0x44120003: + return RW3_STRING; + case 0x44120004: + return RW4_STRING; case 0x44120006: return MGM_0_LIS3_HANDLER_STRING; case 0x44120010: @@ -159,6 +169,8 @@ const char* translateObject(object_id_t object) { return MGM_3_RM3100_HANDLER_STRING; case 0x44120313: return GYRO_3_L3G_HANDLER_STRING; + case 0x44130001: + return START_TRACKER_STRING; case 0x44130045: return GPS0_HANDLER_STRING; case 0x44130146: @@ -167,14 +179,6 @@ const char* translateObject(object_id_t object) { return IMTQ_HANDLER_STRING; case 0x442000A1: return PCDU_HANDLER_STRING; - case 0x44210001: - return RW1_STRING; - case 0x44210002: - return RW2_STRING; - case 0x44210003: - return RW3_STRING; - case 0x44210004: - return RW4_STRING; case 0x44250000: return P60DOCK_HANDLER_STRING; case 0x44250001: @@ -186,7 +190,9 @@ const char* translateObject(object_id_t object) { case 0x443200A5: return RAD_SENSOR_STRING; case 0x44330015: - return PLOC_HANDLER_STRING; + return PLOC_MPSOC_HANDLER_STRING; + case 0x44330016: + return PLOC_SUPERVISOR_HANDLER_STRING; case 0x444100A2: return SOLAR_ARRAY_DEPL_HANDLER_STRING; case 0x444100A4: diff --git a/linux/boardtest/LibgpiodTest.h b/linux/boardtest/LibgpiodTest.h index a18c618e..38325622 100644 --- a/linux/boardtest/LibgpiodTest.h +++ b/linux/boardtest/LibgpiodTest.h @@ -2,8 +2,8 @@ #define TEST_TESTTASKS_LIBGPIODTEST_H_ #include "TestTask.h" -#include -#include +#include +#include #include /** diff --git a/linux/boardtest/SpiTestClass.cpp b/linux/boardtest/SpiTestClass.cpp index 4fc52f29..71313f25 100644 --- a/linux/boardtest/SpiTestClass.cpp +++ b/linux/boardtest/SpiTestClass.cpp @@ -7,10 +7,10 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include diff --git a/linux/boardtest/SpiTestClass.h b/linux/boardtest/SpiTestClass.h index dd112a0e..7982c601 100644 --- a/linux/boardtest/SpiTestClass.h +++ b/linux/boardtest/SpiTestClass.h @@ -1,8 +1,8 @@ #ifndef LINUX_BOARDTEST_SPITESTCLASS_H_ #define LINUX_BOARDTEST_SPITESTCLASS_H_ -#include -#include +#include +#include #include #include diff --git a/linux/devices/HeaterHandler.cpp b/linux/devices/HeaterHandler.cpp index 60a60328..c821aa6c 100644 --- a/linux/devices/HeaterHandler.cpp +++ b/linux/devices/HeaterHandler.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include HeaterHandler::HeaterHandler(object_id_t setObjectId_, object_id_t gpioDriverId_, CookieIF * gpioCookie_, object_id_t mainLineSwitcherObjectId_, uint8_t mainLineSwitch_) : diff --git a/linux/devices/HeaterHandler.h b/linux/devices/HeaterHandler.h index 678710df..5734a2b6 100644 --- a/linux/devices/HeaterHandler.h +++ b/linux/devices/HeaterHandler.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include /** diff --git a/linux/devices/SolarArrayDeploymentHandler.cpp b/linux/devices/SolarArrayDeploymentHandler.cpp index eea546f6..05052c61 100644 --- a/linux/devices/SolarArrayDeploymentHandler.cpp +++ b/linux/devices/SolarArrayDeploymentHandler.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include diff --git a/linux/devices/SolarArrayDeploymentHandler.h b/linux/devices/SolarArrayDeploymentHandler.h index 5e573128..97cb48c7 100644 --- a/linux/devices/SolarArrayDeploymentHandler.h +++ b/linux/devices/SolarArrayDeploymentHandler.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include /** diff --git a/linux/devices/SusHandler.cpp b/linux/devices/SusHandler.cpp index c31160c4..bf06e031 100644 --- a/linux/devices/SusHandler.cpp +++ b/linux/devices/SusHandler.cpp @@ -2,7 +2,7 @@ #include "OBSWConfig.h" #include -#include +#include SusHandler::SusHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie, LinuxLibgpioIF* gpioComIF, gpioId_t chipSelectId) : diff --git a/linux/devices/SusHandler.h b/linux/devices/SusHandler.h index ca9a5c45..d40d9371 100644 --- a/linux/devices/SusHandler.h +++ b/linux/devices/SusHandler.h @@ -3,7 +3,7 @@ #include "devicedefinitions/SusDefinitions.h" #include -#include +#include /** * @brief This is the device handler class for the SUS sensor. The sensor is diff --git a/linux/fsfwconfig/FSFWConfig.h.in b/linux/fsfwconfig/FSFWConfig.h.in index a8519cff..d70bb7b6 100644 --- a/linux/fsfwconfig/FSFWConfig.h.in +++ b/linux/fsfwconfig/FSFWConfig.h.in @@ -72,6 +72,6 @@ static constexpr size_t FSFW_MAX_TM_PACKET_SIZE = 2048; } -#define FSFW_HAL_LINUX_SPI_WIRETAPPING 0 +#define FSFW_HAL_LINUX_SPI_WIRETAPPING 1 #endif /* CONFIG_FSFWCONFIG_H_ */ diff --git a/linux/fsfwconfig/OBSWConfig.h.in b/linux/fsfwconfig/OBSWConfig.h.in index 30b01491..ab55537d 100644 --- a/linux/fsfwconfig/OBSWConfig.h.in +++ b/linux/fsfwconfig/OBSWConfig.h.in @@ -21,15 +21,18 @@ debugging. */ #define OBSW_ADD_TEST_CODE 1 #define OBSW_ADD_TEST_PST 1 #define OBSW_ADD_GPS 0 +#define OBSW_ADD_STAR_TRACKER 0 #define TEST_LIBGPIOD 0 #define TEST_RADIATION_SENSOR_HANDLER 0 -#define TEST_SUS_HANDLER 1 +#define TEST_SUS_HANDLER 0 #define TEST_PLOC_HANDLER 0 #define TEST_CCSDS_BRIDGE 0 #define PERFORM_PTME_TEST 0 +#define ADD_PLOC_SUPERVISOR 1 +#define ADD_PLOC_MPSOC 0 -#define TE0720 0 +#define BOARD_TE0720 0 #define TE0720_HEATER_TEST 0 #define P60DOCK_DEBUG 0 @@ -40,11 +43,14 @@ debugging. */ #define IMQT_DEBUG 0 #define ADIS16507_DEBUG 1 #define L3GD20_GYRO_DEBUG 0 -#define DEBUG_RAD_SENSOR 1 +#define DEBUG_RAD_SENSOR 0 #define DEBUG_SUS 1 #define DEBUG_RTD 1 #define IMTQ_DEBUG 1 -#define RW_DEBUG 1 +#define RW_DEBUG 0 +#define START_TRACKER_DEBUG 0 +#define PLOC_MPSOC_DEBUG 0 +#define PLOC_SUPERVISOR_DEBUG 1 // Leave at one as the BSP is linux. Used by the ADIS16507 device handler #define OBSW_ADIS16507_LINUX_COM_IF 1 @@ -52,7 +58,7 @@ debugging. */ #include "OBSWVersion.h" /* Can be used to switch device to NORMAL mode immediately */ -#define OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP 0 +#define OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP 1 #ifdef __cplusplus diff --git a/linux/fsfwconfig/devices/gpioIds.h b/linux/fsfwconfig/devices/gpioIds.h index aad06629..4b222b97 100644 --- a/linux/fsfwconfig/devices/gpioIds.h +++ b/linux/fsfwconfig/devices/gpioIds.h @@ -1,7 +1,7 @@ #ifndef FSFWCONFIG_DEVICES_GPIOIDS_H_ #define FSFWCONFIG_DEVICES_GPIOIDS_H_ -#include +#include namespace gpioIds { enum gpioId_t { diff --git a/linux/fsfwconfig/devices/powerSwitcherList.h b/linux/fsfwconfig/devices/powerSwitcherList.h index 48821db2..9facfd80 100644 --- a/linux/fsfwconfig/devices/powerSwitcherList.h +++ b/linux/fsfwconfig/devices/powerSwitcherList.h @@ -33,7 +33,7 @@ namespace pcduSwitches { static const uint8_t INIT_STATE_Q7S = ON; static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH1 = OFF; static const uint8_t INIT_STATE_RW = OFF; -#if TE0720 == 1 +#if BOARD_TE0720 == 1 /* Because the TE0720 is not connected to the PCDU, this switch is always on */ static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = ON; #else diff --git a/linux/fsfwconfig/events/subsystemIdRanges.h b/linux/fsfwconfig/events/subsystemIdRanges.h index be84c1a9..4894be16 100644 --- a/linux/fsfwconfig/events/subsystemIdRanges.h +++ b/linux/fsfwconfig/events/subsystemIdRanges.h @@ -12,7 +12,8 @@ */ namespace SUBSYSTEM_ID { enum: uint8_t { - SUBSYSTEM_ID_START = COMMON_SUBSYSTEM_ID_END + SUBSYSTEM_ID_START = COMMON_SUBSYSTEM_ID_END, + CORE = 116, }; } diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 9ae81646..20521618 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 92 translations. + * @brief Auto-generated event translation file. Contains 96 translations. * @details - * Generated on: 2021-06-29 16:20:09 + * Generated on: 2021-07-12 15:20:38 */ #include "translateEvents.h" @@ -97,6 +97,10 @@ const char *SELF_TEST_MTM_RANGE_FAILURE_STRING = "SELF_TEST_MTM_RANGE_FAILURE"; const char *SELF_TEST_COIL_CURRENT_FAILURE_STRING = "SELF_TEST_COIL_CURRENT_FAILURE"; const char *INVALID_ERROR_BYTE_STRING = "INVALID_ERROR_BYTE"; const char *ERROR_STATE_STRING = "ERROR_STATE"; +const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE"; +const char *SUPV_ACK_FAILURE_STRING = "SUPV_ACK_FAILURE"; +const char *SUPV_EXE_FAILURE_STRING = "SUPV_EXE_FAILURE"; +const char *SUPV_CRC_FAILURE_EVENT_STRING = "SUPV_CRC_FAILURE_EVENT"; const char * translateEvents(Event event) { switch( (event & 0xffff) ) { @@ -284,6 +288,14 @@ const char * translateEvents(Event event) { return INVALID_ERROR_BYTE_STRING; case(11301): return ERROR_STATE_STRING; + case(11501): + return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING; + case(11502): + return SUPV_ACK_FAILURE_STRING; + case(11503): + return SUPV_EXE_FAILURE_STRING; + case(11504): + return SUPV_CRC_FAILURE_EVENT_STRING; default: return "UNKNOWN_EVENT"; } diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index 2068158b..cf9db4ca 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -1,8 +1,8 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 100 translations. - * Generated on: 2021-06-29 16:19:57 + * Contains 102 translations. + * Generated on: 2021-07-10 16:22:55 */ #include "translateObjects.h" @@ -10,6 +10,10 @@ const char *P60DOCK_TEST_TASK_STRING = "P60DOCK_TEST_TASK"; const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER"; const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER"; const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER"; +const char *RW1_STRING = "RW1"; +const char *RW2_STRING = "RW2"; +const char *RW3_STRING = "RW3"; +const char *RW4_STRING = "RW4"; const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER"; const char *GYRO_0_ADIS_HANDLER_STRING = "GYRO_0_ADIS_HANDLER"; const char *SUS_1_STRING = "SUS_1"; @@ -31,20 +35,18 @@ const char *MGM_2_LIS3_HANDLER_STRING = "MGM_2_LIS3_HANDLER"; const char *GYRO_2_ADIS_HANDLER_STRING = "GYRO_2_ADIS_HANDLER"; const char *MGM_3_RM3100_HANDLER_STRING = "MGM_3_RM3100_HANDLER"; const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER"; +const char *START_TRACKER_STRING = "START_TRACKER"; const char *GPS0_HANDLER_STRING = "GPS0_HANDLER"; const char *GPS1_HANDLER_STRING = "GPS1_HANDLER"; const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER"; const char *PCDU_HANDLER_STRING = "PCDU_HANDLER"; -const char *RW1_STRING = "RW1"; -const char *RW2_STRING = "RW2"; -const char *RW3_STRING = "RW3"; -const char *RW4_STRING = "RW4"; const char *P60DOCK_HANDLER_STRING = "P60DOCK_HANDLER"; const char *PDU1_HANDLER_STRING = "PDU1_HANDLER"; const char *PDU2_HANDLER_STRING = "PDU2_HANDLER"; const char *ACU_HANDLER_STRING = "ACU_HANDLER"; const char *RAD_SENSOR_STRING = "RAD_SENSOR"; -const char *PLOC_HANDLER_STRING = "PLOC_HANDLER"; +const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER"; +const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER"; const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER"; const char *HEATER_HANDLER_STRING = "HEATER_HANDLER"; const char *TMP1075_HANDLER_1_STRING = "TMP1075_HANDLER_1"; @@ -117,6 +119,14 @@ const char* translateObject(object_id_t object) { return ACS_CONTROLLER_STRING; case 0x43400001: return THERMAL_CONTROLLER_STRING; + case 0x44120001: + return RW1_STRING; + case 0x44120002: + return RW2_STRING; + case 0x44120003: + return RW3_STRING; + case 0x44120004: + return RW4_STRING; case 0x44120006: return MGM_0_LIS3_HANDLER_STRING; case 0x44120010: @@ -159,6 +169,8 @@ const char* translateObject(object_id_t object) { return MGM_3_RM3100_HANDLER_STRING; case 0x44120313: return GYRO_3_L3G_HANDLER_STRING; + case 0x44130001: + return START_TRACKER_STRING; case 0x44130045: return GPS0_HANDLER_STRING; case 0x44130146: @@ -167,14 +179,6 @@ const char* translateObject(object_id_t object) { return IMTQ_HANDLER_STRING; case 0x442000A1: return PCDU_HANDLER_STRING; - case 0x44210001: - return RW1_STRING; - case 0x44210002: - return RW2_STRING; - case 0x44210003: - return RW3_STRING; - case 0x44210004: - return RW4_STRING; case 0x44250000: return P60DOCK_HANDLER_STRING; case 0x44250001: @@ -186,7 +190,9 @@ const char* translateObject(object_id_t object) { case 0x443200A5: return RAD_SENSOR_STRING; case 0x44330015: - return PLOC_HANDLER_STRING; + return PLOC_MPSOC_HANDLER_STRING; + case 0x44330016: + return PLOC_SUPERVISOR_HANDLER_STRING; case 0x444100A2: return SOLAR_ARRAY_DEPL_HANDLER_STRING; case 0x444100A4: diff --git a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp index a213ca06..a24c5393 100644 --- a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp +++ b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp @@ -449,10 +449,36 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { // Length of a communication cycle uint32_t length = thisSequence->getPeriodMs(); - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0, +#if ADD_PLOC_MPSOC == 1 + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.2, + DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.4, + DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.6, + DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.8, + DeviceHandlerIF::GET_READ); +#endif + +#if ADD_PLOC_SUPERVISOR == 1 + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0, + DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.2, + DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.4, + DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.6, + DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.8, + DeviceHandlerIF::GET_READ); +#endif + +#if Q7S_ADD_SYRLINKS_HANDLER == 1 thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); +#endif #if OBSW_ADD_ACS_BOARD == 1 thisSequence->addSlot(objects::GPS0_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); @@ -460,10 +486,9 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { DeviceHandlerIF::PERFORM_OPERATION); #endif - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.2, - DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); + #if OBSW_ADD_ACS_BOARD == 1 thisSequence->addSlot(objects::GPS0_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); @@ -471,10 +496,10 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { DeviceHandlerIF::SEND_WRITE); #endif - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.4, - DeviceHandlerIF::GET_WRITE); +#if Q7S_ADD_SYRLINKS_HANDLER == 1 thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); +#endif #if OBSW_ADD_ACS_BOARD == 1 thisSequence->addSlot(objects::GPS0_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); @@ -482,10 +507,10 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { DeviceHandlerIF::GET_WRITE); #endif - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.6, - DeviceHandlerIF::SEND_READ); +#if Q7S_ADD_SYRLINKS_HANDLER == 1 thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); +#endif #if OBSW_ADD_ACS_BOARD == 1 thisSequence->addSlot(objects::GPS0_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); @@ -493,10 +518,10 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { DeviceHandlerIF::SEND_READ); #endif - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.8, - DeviceHandlerIF::GET_READ); +#if Q7S_ADD_SYRLINKS_HANDLER == 1 thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); +#endif #if OBSW_ADD_ACS_BOARD == 1 thisSequence->addSlot(objects::GPS0_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); @@ -504,6 +529,14 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { DeviceHandlerIF::GET_READ); #endif +#if OBSW_ADD_STAR_TRACKER == 1 + thisSequence->addSlot(objects::START_TRACKER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::START_TRACKER, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::START_TRACKER, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::START_TRACKER, length * 0.6, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::START_TRACKER, length * 0.8, DeviceHandlerIF::GET_READ); +#endif + if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) { sif::error << "UART PST initialization failed" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; @@ -670,16 +703,16 @@ ReturnValue_t pst::pstTest(FixedTimeslotTaskIF* thisSequence) { return HasReturnvaluesIF::RETURN_OK; } -#if TE7020 == 1 +#if BOARD_TE7020 == 1 ReturnValue_t pst::pollingSequenceTE0720(FixedTimeslotTaskIF *thisSequence) { uint32_t length = thisSequence->getPeriodMs(); -#if TEST_PLOC_HANDLER == 1 - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); +#if TEST_PLOC_MPSOC_HANDLER == 1 + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); #endif #if TEST_RADIATION_SENSOR_HANDLER == 1 @@ -713,10 +746,18 @@ ReturnValue_t pst::pollingSequenceTE0720(FixedTimeslotTaskIF *thisSequence) { thisSequence->addSlot(objects::SUS_1, length * 0.915, DeviceHandlerIF::GET_READ); #endif +#if ADD_PLOC_SUPERVISOR == 1 + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.7, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); +#endif + if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) { sif::error << "Initialization of TE0720 PST failed" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } return HasReturnvaluesIF::RETURN_OK; } -#endif /* TE7020 == 1 */ +#endif /* BOARD_TE7020 == 1 */ diff --git a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.h b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.h index a2b5edfb..4ce1619c 100644 --- a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.h +++ b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.h @@ -55,7 +55,7 @@ ReturnValue_t pstI2c(FixedTimeslotTaskIF* thisSequence); */ ReturnValue_t pstTest(FixedTimeslotTaskIF* thisSequence); -#if TE7020 == 1 +#if TE0720 == 1 /** * @brief This polling sequence will be created when the software is compiled for the TE0720. */ diff --git a/linux/fsfwconfig/returnvalues/classIds.h b/linux/fsfwconfig/returnvalues/classIds.h index 79f1a175..b98801e2 100644 --- a/linux/fsfwconfig/returnvalues/classIds.h +++ b/linux/fsfwconfig/returnvalues/classIds.h @@ -14,6 +14,7 @@ enum { CLASS_ID_START = COMMON_CLASS_ID_END, SA_DEPL_HANDLER, //SADPL SD_CARD_MANAGER, //SDMA + SCRATCH_BUFFER, //SCBU CLASS_ID_END // [EXPORT] : [END] }; } diff --git a/linux/obc/CCSDSIPCoreBridge.h b/linux/obc/CCSDSIPCoreBridge.h index 5b7674e9..f5127828 100644 --- a/linux/obc/CCSDSIPCoreBridge.h +++ b/linux/obc/CCSDSIPCoreBridge.h @@ -1,11 +1,12 @@ #ifndef MISSION_OBC_CCSDSIPCOREBRIDGE_H_ #define MISSION_OBC_CCSDSIPCOREBRIDGE_H_ -#include -#include -#include -#include #include "OBSWConfig.h" +#include +#include +#include + +#include /** * @brief This class handles the interfacing to the telemetry (PTME) and telecommand (PDEC) IP diff --git a/linux/utility/utility.cpp b/linux/utility/utility.cpp index 69a3d08f..1d6ec5c0 100644 --- a/linux/utility/utility.cpp +++ b/linux/utility/utility.cpp @@ -3,9 +3,11 @@ #include "utility.h" #include "fsfw/serviceinterface/ServiceInterface.h" +#include void utility::handleSystemError(int retcode, std::string function) { #if OBSW_VERBOSE_LEVEL >= 1 - sif::warning << function << ": System call failed with code " << retcode; + sif::warning << function << ": System call failed with code " << retcode << ": " << + strerror(retcode) << std::endl; #endif } diff --git a/misc/eclipse/.cproject b/misc/eclipse/.cproject index 16bd992b..155e08b2 100644 --- a/misc/eclipse/.cproject +++ b/misc/eclipse/.cproject @@ -254,7 +254,7 @@ - + - + @@ -657,6 +658,7 @@ + diff --git a/mission/CMakeLists.txt b/mission/CMakeLists.txt index 9cb18749..46f562a5 100644 --- a/mission/CMakeLists.txt +++ b/mission/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(core) add_subdirectory(devices) add_subdirectory(utility) +add_subdirectory(memory) diff --git a/mission/core/GenericFactory.cpp b/mission/core/GenericFactory.cpp index fae8b7d8..a6708f98 100644 --- a/mission/core/GenericFactory.cpp +++ b/mission/core/GenericFactory.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include diff --git a/mission/devices/CMakeLists.txt b/mission/devices/CMakeLists.txt index 78d54185..63b417e9 100644 --- a/mission/devices/CMakeLists.txt +++ b/mission/devices/CMakeLists.txt @@ -12,10 +12,12 @@ target_sources(${TARGET_NAME} PUBLIC SyrlinksHkHandler.cpp Max31865PT1000Handler.cpp IMTQHandler.cpp - PlocHandler.cpp + PlocMPSoCHandler.cpp + PlocSupervisorHandler.cpp RadiationSensorHandler.cpp GyroADIS16507Handler.cpp RwHandler.cpp + StarTrackerHandler.cpp ) diff --git a/mission/devices/GyroADIS16507Handler.cpp b/mission/devices/GyroADIS16507Handler.cpp index ac49a89d..7b45b8c5 100644 --- a/mission/devices/GyroADIS16507Handler.cpp +++ b/mission/devices/GyroADIS16507Handler.cpp @@ -4,10 +4,10 @@ #include "GyroADIS16507Handler.h" #if OBSW_ADIS16507_LINUX_COM_IF == 1 -#include "fsfw_hal/linux/utility.h" -#include "fsfw_hal/linux/spi/SpiCookie.h" -#include "fsfw_hal/linux/spi/SpiComIF.h" -#include "fsfw_hal/linux/UnixFileGuard.h" +#include "fsfw/hal/linux/utility.h" +#include "fsfw/hal/linux/spi/SpiCookie.h" +#include "fsfw/hal/linux/spi/SpiComIF.h" +#include "fsfw/hal/linux/UnixFileGuard.h" #include #include #endif diff --git a/mission/devices/PCDUHandler.cpp b/mission/devices/PCDUHandler.cpp index 3ba734fb..ba0e8667 100644 --- a/mission/devices/PCDUHandler.cpp +++ b/mission/devices/PCDUHandler.cpp @@ -329,7 +329,7 @@ ReturnValue_t PCDUHandler::initializeLocalDataPool(localpool::DataPool &localDat pcduSwitches::INIT_STATE_PAYLOAD_PCDU_CH1 })); localDataPoolMap.emplace(P60System::PDU2_OUT_EN_RW, new PoolEntry( { pcduSwitches::INIT_STATE_RW })); -#if TE0720 == 1 +#if BOARD_TE0720 == 1 localDataPoolMap.emplace(P60System::PDU2_OUT_EN_TCS_BOARD_HEATER_IN, new PoolEntry( { 1 })); #else localDataPoolMap.emplace(P60System::PDU2_OUT_EN_TCS_BOARD_HEATER_IN, new PoolEntry( {pcduSwitches::INIT_STATE_TCS_BOARD_8V_HEATER_IN})); diff --git a/mission/devices/PDU2Handler.cpp b/mission/devices/PDU2Handler.cpp index eaeb00bb..798a6d67 100644 --- a/mission/devices/PDU2Handler.cpp +++ b/mission/devices/PDU2Handler.cpp @@ -265,7 +265,7 @@ ReturnValue_t PDU2Handler::initializeLocalDataPool( localDataPoolMap.emplace(P60System::PDU2_OUT_EN_Q7S, new PoolEntry( { 0 })); localDataPoolMap.emplace(P60System::PDU2_OUT_EN_PAYLOAD_PCDU_CH1, new PoolEntry( { 0 })); localDataPoolMap.emplace(P60System::PDU2_OUT_EN_RW, new PoolEntry( { 0 })); -#if TE0720 == 1 +#if BOARD_TE0720 == 1 localDataPoolMap.emplace(P60System::PDU2_OUT_EN_TCS_BOARD_HEATER_IN, new PoolEntry( { 1 })); #else localDataPoolMap.emplace(P60System::PDU2_OUT_EN_TCS_BOARD_HEATER_IN, new PoolEntry( { 0 })); diff --git a/mission/devices/PlocHandler.cpp b/mission/devices/PlocMPSoCHandler.cpp similarity index 53% rename from mission/devices/PlocHandler.cpp rename to mission/devices/PlocMPSoCHandler.cpp index 2101915a..0b1fac73 100644 --- a/mission/devices/PlocHandler.cpp +++ b/mission/devices/PlocMPSoCHandler.cpp @@ -1,66 +1,66 @@ -#include "PlocHandler.h" +#include "PlocMPSoCHandler.h" #include "OBSWConfig.h" #include #include -PlocHandler::PlocHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) : +PlocMPSoCHandler::PlocMPSoCHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) : DeviceHandlerBase(objectId, comIF, comCookie) { if (comCookie == NULL) { - sif::error << "PlocHandler: Invalid com cookie" << std::endl; + sif::error << "PlocMPSoCHandler: Invalid com cookie" << std::endl; } } -PlocHandler::~PlocHandler() { +PlocMPSoCHandler::~PlocMPSoCHandler() { } -void PlocHandler::doStartUp(){ +void PlocMPSoCHandler::doStartUp(){ if(mode == _MODE_START_UP){ setMode(MODE_ON); } } -void PlocHandler::doShutDown(){ +void PlocMPSoCHandler::doShutDown(){ } -ReturnValue_t PlocHandler::buildNormalDeviceCommand( +ReturnValue_t PlocMPSoCHandler::buildNormalDeviceCommand( DeviceCommandId_t * id) { return RETURN_OK; } -ReturnValue_t PlocHandler::buildTransitionDeviceCommand( +ReturnValue_t PlocMPSoCHandler::buildTransitionDeviceCommand( DeviceCommandId_t * id){ return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t PlocHandler::buildCommandFromCommand( +ReturnValue_t PlocMPSoCHandler::buildCommandFromCommand( DeviceCommandId_t deviceCommand, const uint8_t * commandData, size_t commandDataLen) { switch(deviceCommand) { - case(PLOC::TC_MEM_WRITE): { + case(PLOC_MPSOC::TC_MEM_WRITE): { return prepareTcMemWriteCommand(commandData, commandDataLen); } - case(PLOC::TC_MEM_READ): { + case(PLOC_MPSOC::TC_MEM_READ): { return prepareTcMemReadCommand(commandData, commandDataLen); } default: - sif::debug << "PlocHandler::buildCommandFromCommand: Command not implemented" << std::endl; + sif::debug << "PlocMPSoCHandler::buildCommandFromCommand: Command not implemented" << std::endl; return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; } return HasReturnvaluesIF::RETURN_FAILED; } -void PlocHandler::fillCommandAndReplyMap() { - this->insertInCommandMap(PLOC::TC_MEM_WRITE); - this->insertInCommandMap(PLOC::TC_MEM_READ); - this->insertInReplyMap(PLOC::ACK_REPORT, 1, nullptr, PLOC::SIZE_ACK_REPORT); - this->insertInReplyMap(PLOC::EXE_REPORT, 3, nullptr, PLOC::SIZE_EXE_REPORT); - this->insertInReplyMap(PLOC::TM_MEMORY_READ_REPORT, 2, nullptr, PLOC::SIZE_TM_MEM_READ_REPORT); +void PlocMPSoCHandler::fillCommandAndReplyMap() { + this->insertInCommandMap(PLOC_MPSOC::TC_MEM_WRITE); + this->insertInCommandMap(PLOC_MPSOC::TC_MEM_READ); + this->insertInReplyMap(PLOC_MPSOC::ACK_REPORT, 1, nullptr, PLOC_MPSOC::SIZE_ACK_REPORT); + this->insertInReplyMap(PLOC_MPSOC::EXE_REPORT, 3, nullptr, PLOC_MPSOC::SIZE_EXE_REPORT); + this->insertInReplyMap(PLOC_MPSOC::TM_MEMORY_READ_REPORT, 2, nullptr, PLOC_MPSOC::SIZE_TM_MEM_READ_REPORT); } -ReturnValue_t PlocHandler::scanForReply(const uint8_t *start, +ReturnValue_t PlocMPSoCHandler::scanForReply(const uint8_t *start, size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) { ReturnValue_t result = RETURN_OK; @@ -68,28 +68,28 @@ ReturnValue_t PlocHandler::scanForReply(const uint8_t *start, uint16_t apid = (*(start) << 8 | *(start + 1)) & APID_MASK; switch(apid) { - case(PLOC::APID_ACK_SUCCESS): - *foundLen = PLOC::SIZE_ACK_REPORT; - *foundId = PLOC::ACK_REPORT; + case(PLOC_MPSOC::APID_ACK_SUCCESS): + *foundLen = PLOC_MPSOC::SIZE_ACK_REPORT; + *foundId = PLOC_MPSOC::ACK_REPORT; break; - case(PLOC::APID_ACK_FAILURE): - *foundLen = PLOC::SIZE_ACK_REPORT; - *foundId = PLOC::ACK_REPORT; + case(PLOC_MPSOC::APID_ACK_FAILURE): + *foundLen = PLOC_MPSOC::SIZE_ACK_REPORT; + *foundId = PLOC_MPSOC::ACK_REPORT; break; - case(PLOC::APID_TM_MEMORY_READ_REPORT): - *foundLen = PLOC::SIZE_TM_MEM_READ_REPORT; - *foundId = PLOC::TM_MEMORY_READ_REPORT; + case(PLOC_MPSOC::APID_TM_MEMORY_READ_REPORT): + *foundLen = PLOC_MPSOC::SIZE_TM_MEM_READ_REPORT; + *foundId = PLOC_MPSOC::TM_MEMORY_READ_REPORT; break; - case(PLOC::APID_EXE_SUCCESS): - *foundLen = PLOC::SIZE_EXE_REPORT; - *foundId = PLOC::EXE_REPORT; + case(PLOC_MPSOC::APID_EXE_SUCCESS): + *foundLen = PLOC_MPSOC::SIZE_EXE_REPORT; + *foundId = PLOC_MPSOC::EXE_REPORT; break; - case(PLOC::APID_EXE_FAILURE): - *foundLen = PLOC::SIZE_EXE_REPORT; - *foundId = PLOC::EXE_REPORT; + case(PLOC_MPSOC::APID_EXE_FAILURE): + *foundLen = PLOC_MPSOC::SIZE_EXE_REPORT; + *foundId = PLOC_MPSOC::EXE_REPORT; break; default: { - sif::debug << "PlocHandler::scanForReply: Reply has invalid apid" << std::endl; + sif::debug << "PlocMPSoCHandler::scanForReply: Reply has invalid apid" << std::endl; *foundLen = remainingSize; return INVALID_APID; } @@ -104,26 +104,26 @@ ReturnValue_t PlocHandler::scanForReply(const uint8_t *start, return result; } -ReturnValue_t PlocHandler::interpretDeviceReply(DeviceCommandId_t id, +ReturnValue_t PlocMPSoCHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { ReturnValue_t result = RETURN_OK; switch (id) { - case PLOC::ACK_REPORT: { + case PLOC_MPSOC::ACK_REPORT: { result = handleAckReport(packet); break; } - case (PLOC::TM_MEMORY_READ_REPORT): { + case (PLOC_MPSOC::TM_MEMORY_READ_REPORT): { result = handleMemoryReadReport(packet); break; } - case (PLOC::EXE_REPORT): { + case (PLOC_MPSOC::EXE_REPORT): { result = handleExecutionReport(packet); break; } default: { - sif::debug << "PlocHandler::interpretDeviceReply: Unknown device reply id" << std::endl; + sif::debug << "PlocMPSoCHandler::interpretDeviceReply: Unknown device reply id" << std::endl; return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; } } @@ -131,62 +131,62 @@ ReturnValue_t PlocHandler::interpretDeviceReply(DeviceCommandId_t id, return result; } -void PlocHandler::setNormalDatapoolEntriesInvalid(){ +void PlocMPSoCHandler::setNormalDatapoolEntriesInvalid(){ } -uint32_t PlocHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){ +uint32_t PlocMPSoCHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){ return 500; } -ReturnValue_t PlocHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, +ReturnValue_t PlocMPSoCHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { return HasReturnvaluesIF::RETURN_OK; } -void PlocHandler::setModeNormal() { +void PlocMPSoCHandler::setModeNormal() { mode = MODE_NORMAL; } -ReturnValue_t PlocHandler::prepareTcMemWriteCommand(const uint8_t * commandData, +ReturnValue_t PlocMPSoCHandler::prepareTcMemWriteCommand(const uint8_t * commandData, size_t commandDataLen) { const uint32_t memoryAddress = *(commandData) << 24 | *(commandData + 1) << 16 | *(commandData + 2) << 8 | *(commandData + 3); const uint32_t memoryData = *(commandData + 4) << 24 | *(commandData + 5) << 16 | *(commandData + 6) << 8 | *(commandData + 7); packetSequenceCount = (packetSequenceCount + 1) & PACKET_SEQUENCE_COUNT_MASK; - PLOC::TcMemWrite tcMemWrite(memoryAddress, memoryData, packetSequenceCount); - if (tcMemWrite.getFullSize() > PLOC::MAX_COMMAND_SIZE) { - sif::debug << "PlocHandler::prepareTcMemWriteCommand: Command too big" << std::endl; + PLOC_MPSOC::TcMemWrite tcMemWrite(memoryAddress, memoryData, packetSequenceCount); + if (tcMemWrite.getFullSize() > PLOC_MPSOC::MAX_COMMAND_SIZE) { + sif::debug << "PlocMPSoCHandler::prepareTcMemWriteCommand: Command too big" << std::endl; return RETURN_FAILED; } memcpy(commandBuffer, tcMemWrite.getWholeData(), tcMemWrite.getFullSize()); rawPacket = commandBuffer; rawPacketLen = tcMemWrite.getFullSize(); - nextReplyId = PLOC::ACK_REPORT; + nextReplyId = PLOC_MPSOC::ACK_REPORT; return RETURN_OK; } -ReturnValue_t PlocHandler::prepareTcMemReadCommand(const uint8_t * commandData, +ReturnValue_t PlocMPSoCHandler::prepareTcMemReadCommand(const uint8_t * commandData, size_t commandDataLen) { const uint32_t memoryAddress = *(commandData) << 24 | *(commandData + 1) << 16 | *(commandData + 2) << 8 | *(commandData + 3); packetSequenceCount = (packetSequenceCount + 1) & PACKET_SEQUENCE_COUNT_MASK; - PLOC::TcMemRead tcMemRead(memoryAddress, packetSequenceCount); - if (tcMemRead.getFullSize() > PLOC::MAX_COMMAND_SIZE) { - sif::debug << "PlocHandler::prepareTcMemReadCommand: Command too big" << std::endl; + PLOC_MPSOC::TcMemRead tcMemRead(memoryAddress, packetSequenceCount); + if (tcMemRead.getFullSize() > PLOC_MPSOC::MAX_COMMAND_SIZE) { + sif::debug << "PlocMPSoCHandler::prepareTcMemReadCommand: Command too big" << std::endl; return RETURN_FAILED; } memcpy(commandBuffer, tcMemRead.getWholeData(), tcMemRead.getFullSize()); rawPacket = commandBuffer; rawPacketLen = tcMemRead.getFullSize(); - nextReplyId = PLOC::ACK_REPORT; + nextReplyId = PLOC_MPSOC::ACK_REPORT; return RETURN_OK; } -ReturnValue_t PlocHandler::verifyPacket(const uint8_t* start, size_t foundLen) { +ReturnValue_t PlocMPSoCHandler::verifyPacket(const uint8_t* start, size_t foundLen) { uint16_t receivedCrc = *(start + foundLen - 2) << 8 | *(start + foundLen - 1); @@ -199,17 +199,17 @@ ReturnValue_t PlocHandler::verifyPacket(const uint8_t* start, size_t foundLen) { return RETURN_OK; } -ReturnValue_t PlocHandler::handleAckReport(const uint8_t* data) { +ReturnValue_t PlocMPSoCHandler::handleAckReport(const uint8_t* data) { ReturnValue_t result = RETURN_OK; - result = verifyPacket(data, PLOC::SIZE_ACK_REPORT); + result = verifyPacket(data, PLOC_MPSOC::SIZE_ACK_REPORT); if(result == CRC_FAILURE) { - sif::error << "PlocHandler::handleAckReport: CRC failure" << std::endl; - nextReplyId = PLOC::NONE; - replyRawReplyIfnotWiretapped(data, PLOC::SIZE_ACK_REPORT); + sif::error << "PlocMPSoCHandler::handleAckReport: CRC failure" << std::endl; + nextReplyId = PLOC_MPSOC::NONE; + replyRawReplyIfnotWiretapped(data, PLOC_MPSOC::SIZE_ACK_REPORT); triggerEvent(CRC_FAILURE_EVENT); - sendFailureReport(PLOC::ACK_REPORT, CRC_FAILURE); + sendFailureReport(PLOC_MPSOC::ACK_REPORT, CRC_FAILURE); disableAllReplies(); return IGNORE_REPLY_DATA; } @@ -217,25 +217,25 @@ ReturnValue_t PlocHandler::handleAckReport(const uint8_t* data) { uint16_t apid = (*(data) << 8 | *(data + 1)) & APID_MASK; switch(apid) { - case PLOC::APID_ACK_FAILURE: { + case PLOC_MPSOC::APID_ACK_FAILURE: { //TODO: Interpretation of status field in acknowledgment report - sif::debug << "PlocHandler::handleAckReport: Received Ack failure report" << std::endl; + sif::debug << "PlocMPSoCHandler::handleAckReport: Received Ack failure report" << std::endl; DeviceCommandId_t commandId = getPendingCommand(); if (commandId != DeviceHandlerIF::NO_COMMAND_ID) { triggerEvent(ACK_FAILURE, commandId); } - sendFailureReport(PLOC::ACK_REPORT, RECEIVED_ACK_FAILURE); + sendFailureReport(PLOC_MPSOC::ACK_REPORT, RECEIVED_ACK_FAILURE); disableAllReplies(); - nextReplyId = PLOC::NONE; + nextReplyId = PLOC_MPSOC::NONE; result = IGNORE_REPLY_DATA; break; } - case PLOC::APID_ACK_SUCCESS: { + case PLOC_MPSOC::APID_ACK_SUCCESS: { setNextReplyId(); break; } default: { - sif::debug << "PlocHandler::handleAckReport: Invalid APID in Ack report" << std::endl; + sif::debug << "PlocMPSoCHandler::handleAckReport: Invalid APID in Ack report" << std::endl; result = RETURN_FAILED; break; } @@ -244,71 +244,71 @@ ReturnValue_t PlocHandler::handleAckReport(const uint8_t* data) { return result; } -ReturnValue_t PlocHandler::handleExecutionReport(const uint8_t* data) { +ReturnValue_t PlocMPSoCHandler::handleExecutionReport(const uint8_t* data) { ReturnValue_t result = RETURN_OK; - result = verifyPacket(data, PLOC::SIZE_EXE_REPORT); + result = verifyPacket(data, PLOC_MPSOC::SIZE_EXE_REPORT); if(result == CRC_FAILURE) { - sif::error << "PlocHandler::handleExecutionReport: CRC failure" << std::endl; - nextReplyId = PLOC::NONE; + sif::error << "PlocMPSoCHandler::handleExecutionReport: CRC failure" << std::endl; + nextReplyId = PLOC_MPSOC::NONE; return result; } uint16_t apid = (*(data) << 8 | *(data + 1)) & APID_MASK; switch (apid) { - case (PLOC::APID_EXE_SUCCESS): { + case (PLOC_MPSOC::APID_EXE_SUCCESS): { break; } - case (PLOC::APID_EXE_FAILURE): { + case (PLOC_MPSOC::APID_EXE_FAILURE): { //TODO: Interpretation of status field in execution report - sif::error << "PlocHandler::handleExecutionReport: Received execution failure report" + sif::error << "PlocMPSoCHandler::handleExecutionReport: Received execution failure report" << std::endl; DeviceCommandId_t commandId = getPendingCommand(); if (commandId != DeviceHandlerIF::NO_COMMAND_ID) { triggerEvent(EXE_FAILURE, commandId); } else { - sif::debug << "PlocHandler::handleExecutionReport: Unknown command id" << std::endl; + sif::debug << "PlocMPSoCHandler::handleExecutionReport: Unknown command id" << std::endl; } - sendFailureReport(PLOC::EXE_REPORT, RECEIVED_EXE_FAILURE); + sendFailureReport(PLOC_MPSOC::EXE_REPORT, RECEIVED_EXE_FAILURE); disableExeReportReply(); result = IGNORE_REPLY_DATA; break; } default: { - sif::error << "PlocHandler::handleExecutionReport: Unknown APID" << std::endl; + sif::error << "PlocMPSoCHandler::handleExecutionReport: Unknown APID" << std::endl; result = RETURN_FAILED; break; } } - nextReplyId = PLOC::NONE; + nextReplyId = PLOC_MPSOC::NONE; return result; } -ReturnValue_t PlocHandler::handleMemoryReadReport(const uint8_t* data) { +ReturnValue_t PlocMPSoCHandler::handleMemoryReadReport(const uint8_t* data) { ReturnValue_t result = RETURN_OK; - result = verifyPacket(data, PLOC::SIZE_TM_MEM_READ_REPORT); + result = verifyPacket(data, PLOC_MPSOC::SIZE_TM_MEM_READ_REPORT); if(result == CRC_FAILURE) { - sif::error << "PlocHandler::handleMemoryReadReport: Memory read report has invalid crc" + sif::error << "PlocMPSoCHandler::handleMemoryReadReport: Memory read report has invalid crc" << std::endl; } /** Send data to commanding queue */ - handleDeviceTM(data + PLOC::DATA_FIELD_OFFSET, PLOC::SIZE_MEM_READ_REPORT_DATA, - PLOC::TM_MEMORY_READ_REPORT); + handleDeviceTM(data + PLOC_MPSOC::DATA_FIELD_OFFSET, PLOC_MPSOC::SIZE_MEM_READ_REPORT_DATA, + PLOC_MPSOC::TM_MEMORY_READ_REPORT); - nextReplyId = PLOC::EXE_REPORT; + nextReplyId = PLOC_MPSOC::EXE_REPORT; return result; } -ReturnValue_t PlocHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command, +ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command, uint8_t expectedReplies, bool useAlternateId, DeviceCommandId_t alternateReplyID) { @@ -317,21 +317,21 @@ ReturnValue_t PlocHandler::enableReplyInReplyMap(DeviceCommandMap::iterator comm uint8_t enabledReplies = 0; switch (command->first) { - case PLOC::TC_MEM_WRITE: + case PLOC_MPSOC::TC_MEM_WRITE: enabledReplies = 2; break; - case PLOC::TC_MEM_READ: { + case PLOC_MPSOC::TC_MEM_READ: { enabledReplies = 3; result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, - PLOC::TM_MEMORY_READ_REPORT); + PLOC_MPSOC::TM_MEMORY_READ_REPORT); if (result != RETURN_OK) { - sif::debug << "PlocHandler::enableReplyInReplyMap: Reply with id " - << PLOC::TM_MEMORY_READ_REPORT << " not in replyMap" << std::endl; + sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Reply with id " + << PLOC_MPSOC::TM_MEMORY_READ_REPORT << " not in replyMap" << std::endl; } break; } default: - sif::debug << "PlocHandler::enableReplyInReplyMap: Unknown command id" << std::endl; + sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Unknown command id" << std::endl; break; } @@ -340,38 +340,38 @@ ReturnValue_t PlocHandler::enableReplyInReplyMap(DeviceCommandMap::iterator comm * replies will be enabled here. */ result = DeviceHandlerBase::enableReplyInReplyMap(command, - enabledReplies, true, PLOC::ACK_REPORT); + enabledReplies, true, PLOC_MPSOC::ACK_REPORT); if (result != RETURN_OK) { - sif::debug << "PlocHandler::enableReplyInReplyMap: Reply with id " << PLOC::ACK_REPORT + sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Reply with id " << PLOC_MPSOC::ACK_REPORT << " not in replyMap" << std::endl; } result = DeviceHandlerBase::enableReplyInReplyMap(command, - enabledReplies, true, PLOC::EXE_REPORT); + enabledReplies, true, PLOC_MPSOC::EXE_REPORT); if (result != RETURN_OK) { - sif::debug << "PlocHandler::enableReplyInReplyMap: Reply with id " << PLOC::EXE_REPORT + sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Reply with id " << PLOC_MPSOC::EXE_REPORT << " not in replyMap" << std::endl; } return RETURN_OK; } -void PlocHandler::setNextReplyId() { +void PlocMPSoCHandler::setNextReplyId() { switch(getPendingCommand()) { - case PLOC::TC_MEM_READ: - nextReplyId = PLOC::TM_MEMORY_READ_REPORT; + case PLOC_MPSOC::TC_MEM_READ: + nextReplyId = PLOC_MPSOC::TM_MEMORY_READ_REPORT; break; default: /* If no telemetry is expected the next reply is always the execution report */ - nextReplyId = PLOC::EXE_REPORT; + nextReplyId = PLOC_MPSOC::EXE_REPORT; break; } } -size_t PlocHandler::getNextReplyLength(DeviceCommandId_t commandId){ +size_t PlocMPSoCHandler::getNextReplyLength(DeviceCommandId_t commandId){ size_t replyLen = 0; - if (nextReplyId == PLOC::NONE) { + if (nextReplyId == PLOC_MPSOC::NONE) { return replyLen; } @@ -384,14 +384,14 @@ size_t PlocHandler::getNextReplyLength(DeviceCommandId_t commandId){ replyLen = iter->second.replyLen; } else { - sif::debug << "PlocHandler::getNextReplyLength: No entry for reply with reply id " + sif::debug << "PlocMPSoCHandler::getNextReplyLength: No entry for reply with reply id " << std::hex << nextReplyId << " in deviceReplyMap" << std::endl; } return replyLen; } -void PlocHandler::handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId) { +void PlocMPSoCHandler::handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId) { ReturnValue_t result = RETURN_OK; @@ -402,7 +402,7 @@ void PlocHandler::handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCom DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId); if (iter == deviceReplyMap.end()) { - sif::debug << "PlocHandler::handleDeviceTM: Unknown reply id" << std::endl; + sif::debug << "PlocMPSoCHandler::handleDeviceTM: Unknown reply id" << std::endl; return; } MessageQueueId_t queueId = iter->second.command->second.sendReplyTo; @@ -413,16 +413,16 @@ void PlocHandler::handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCom result = actionHelper.reportData(queueId, replyId, data, dataSize); if (result != RETURN_OK) { - sif::debug << "PlocHandler::handleDeviceTM: Failed to report data" << std::endl; + sif::debug << "PlocMPSoCHandler::handleDeviceTM: Failed to report data" << std::endl; } } -void PlocHandler::disableAllReplies() { +void PlocMPSoCHandler::disableAllReplies() { DeviceReplyMap::iterator iter; /* Disable ack reply */ - iter = deviceReplyMap.find(PLOC::ACK_REPORT); + iter = deviceReplyMap.find(PLOC_MPSOC::ACK_REPORT); DeviceReplyInfo *info = &(iter->second); info->delayCycles = 0; info->command = deviceCommandMap.end(); @@ -431,17 +431,17 @@ void PlocHandler::disableAllReplies() { /* If the command expects a telemetry packet the appropriate tm reply will be disabled here */ switch (commandId) { - case PLOC::TC_MEM_WRITE: + case PLOC_MPSOC::TC_MEM_WRITE: break; - case PLOC::TC_MEM_READ: { - iter = deviceReplyMap.find(PLOC::TM_MEMORY_READ_REPORT); + case PLOC_MPSOC::TC_MEM_READ: { + iter = deviceReplyMap.find(PLOC_MPSOC::TM_MEMORY_READ_REPORT); info = &(iter->second); info->delayCycles = 0; info->command = deviceCommandMap.end(); break; } default: { - sif::debug << "PlocHandler::disableAllReplies: Unknown command id" << commandId + sif::debug << "PlocMPSoCHandler::disableAllReplies: Unknown command id" << commandId << std::endl; break; } @@ -451,19 +451,19 @@ void PlocHandler::disableAllReplies() { disableExeReportReply(); } -void PlocHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status) { +void PlocMPSoCHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status) { DeviceReplyIter iter = deviceReplyMap.find(replyId); if (iter == deviceReplyMap.end()) { - sif::debug << "PlocHandler::sendFailureReport: Reply not in reply map" << std::endl; + sif::debug << "PlocMPSoCHandler::sendFailureReport: Reply not in reply map" << std::endl; return; } DeviceCommandInfo* info = &(iter->second.command->second); if (info == nullptr) { - sif::debug << "PlocHandler::sendFailureReport: Reply has no active command" << std::endl; + sif::debug << "PlocMPSoCHandler::sendFailureReport: Reply has no active command" << std::endl; return; } @@ -473,8 +473,8 @@ void PlocHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t sta info->isExecuting = false; } -void PlocHandler::disableExeReportReply() { - DeviceReplyIter iter = deviceReplyMap.find(PLOC::EXE_REPORT); +void PlocMPSoCHandler::disableExeReportReply() { + DeviceReplyIter iter = deviceReplyMap.find(PLOC_MPSOC::EXE_REPORT); DeviceReplyInfo *info = &(iter->second); info->delayCycles = 0; info->command = deviceCommandMap.end(); @@ -482,12 +482,12 @@ void PlocHandler::disableExeReportReply() { info->command->second.expectedReplies = 0; } -ReturnValue_t PlocHandler::checkPacketSequenceCount(const uint8_t* data) { +ReturnValue_t PlocMPSoCHandler::checkPacketSequenceCount(const uint8_t* data) { uint16_t receivedSequenceCount = (*(data + 2) << 8 | *(data + 3)) & PACKET_SEQUENCE_COUNT_MASK; uint16_t expectedPacketSequenceCount = ((packetSequenceCount + 1) & PACKET_SEQUENCE_COUNT_MASK); if (receivedSequenceCount != expectedPacketSequenceCount) { sif::debug - << "PlocHandler::checkPacketSequenceCount: Packet sequence count mismatch. " + << "PlocMPSoCHandler::checkPacketSequenceCount: Packet sequence count mismatch. " << std::endl; sif::debug << "Received sequence count: " << receivedSequenceCount << ". OBSW sequence " << "count: " << expectedPacketSequenceCount << std::endl; diff --git a/mission/devices/PlocHandler.h b/mission/devices/PlocMPSoCHandler.h similarity index 89% rename from mission/devices/PlocHandler.h rename to mission/devices/PlocMPSoCHandler.h index d400318e..2b3f6a57 100644 --- a/mission/devices/PlocHandler.h +++ b/mission/devices/PlocMPSoCHandler.h @@ -1,25 +1,28 @@ -#ifndef MISSION_DEVICES_PLOCHANDLER_H_ -#define MISSION_DEVICES_PLOCHANDLER_H_ +#ifndef MISSION_DEVICES_PLOCMPSOCHANDLER_H_ +#define MISSION_DEVICES_PLOCMPSOCHANDLER_H_ #include -#include +#include #include /** - * @brief This is the device handler for the PLOC. + * @brief This is the device handler for the MPSoC which is programmed by the ILH of the + * university of stuttgart. * * @details * The PLOC uses the space packet protocol for communication. To each command the PLOC * answers with at least one acknowledgment and one execution report. * Flight manual: * https://egit.irs.uni-stuttgart.de/redmine/projects/eive-flight-manual/wiki/PLOC_Commands + * ILH ICD: https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/ + * Arbeitsdaten/08_Used%20Components/PLOC&fileid=940960 * @author J. Meier */ -class PlocHandler: public DeviceHandlerBase { +class PlocMPSoCHandler: public DeviceHandlerBase { public: - PlocHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie); - virtual ~PlocHandler(); + PlocMPSoCHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie); + virtual ~PlocMPSoCHandler(); /** * @brief Sets mode to MODE_NORMAL. Can be used for debugging. @@ -49,14 +52,14 @@ protected: private: - static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_HANDLER; + static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_MPSOC_HANDLER; static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0); //!> Space Packet received from PLOC has invalid CRC static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1); //!> Received ACK failure reply from PLOC static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2); //!> Received execution failure reply from PLOC static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3); //!> Received space packet with invalid APID from PLOC - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_HANDLER; + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MPSOC_HANDLER; static const Event MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW); //!> PLOC crc failure in telemetry packet static const Event ACK_FAILURE = MAKE_EVENT(2, severity::LOW); //!> PLOC receive acknowledgment failure report @@ -66,7 +69,7 @@ private: static const uint16_t APID_MASK = 0x7FF; static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF; - uint8_t commandBuffer[PLOC::MAX_COMMAND_SIZE]; + uint8_t commandBuffer[PLOC_MPSOC::MAX_COMMAND_SIZE]; /** * @brief This object is incremented each time a packet is sent or received. By checking the @@ -85,7 +88,7 @@ private: * because the PLOC sends as reply to each command at least one acknowledgment and execution * report. */ - DeviceCommandId_t nextReplyId = PLOC::NONE; + DeviceCommandId_t nextReplyId = PLOC_MPSOC::NONE; /** * @brief This function fills the commandBuffer to initiate the write memory command. @@ -200,4 +203,4 @@ private: ReturnValue_t checkPacketSequenceCount(const uint8_t* data); }; -#endif /* MISSION_DEVICES_PLOCHANDLER_H_ */ +#endif /* MISSION_DEVICES_PLOCMPSOCHANDLER_H_ */ diff --git a/mission/devices/PlocSupervisorHandler.cpp b/mission/devices/PlocSupervisorHandler.cpp new file mode 100644 index 00000000..21310248 --- /dev/null +++ b/mission/devices/PlocSupervisorHandler.cpp @@ -0,0 +1,646 @@ +#include "PlocSupervisorHandler.h" +#include "OBSWConfig.h" + +#include +#include +#include + +PlocSupervisorHandler::PlocSupervisorHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF * comCookie) : + DeviceHandlerBase(objectId, uartComIFid, comCookie), hkset(this) { + if (comCookie == NULL) { + sif::error << "PlocSupervisorHandler: Invalid com cookie" << std::endl; + } +} + +PlocSupervisorHandler::~PlocSupervisorHandler() { +} + +ReturnValue_t PlocSupervisorHandler::initialize() { + ReturnValue_t result = RETURN_OK; + result = DeviceHandlerBase::initialize(); + if (result != RETURN_OK) { + return result; + } + uartComIf = dynamic_cast(communicationInterface); + if (uartComIf == nullptr) { + sif::warning << "PlocSupervisorHandler::initialize: Invalid uart com if" << std::endl; + return INVALID_UART_COM_IF; + } + return result; +} + + +void PlocSupervisorHandler::doStartUp(){ +#if OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP == 1 + setMode(MODE_NORMAL); +#else + setMode(_MODE_TO_ON); +#endif +} + +void PlocSupervisorHandler::doShutDown(){ + +} + +ReturnValue_t PlocSupervisorHandler::buildNormalDeviceCommand( + DeviceCommandId_t * id) { + return NOTHING_TO_SEND; +} + +ReturnValue_t PlocSupervisorHandler::buildTransitionDeviceCommand( + DeviceCommandId_t * id){ + return NOTHING_TO_SEND; +} + +ReturnValue_t PlocSupervisorHandler::buildCommandFromCommand( + DeviceCommandId_t deviceCommand, const uint8_t * commandData, + size_t commandDataLen) { + ReturnValue_t result = RETURN_FAILED; + switch(deviceCommand) { + case(PLOC_SPV::GET_HK_REPORT): { + prepareEmptyCmd(PLOC_SPV::APID_GET_HK_REPORT); + result = RETURN_OK; + break; + } + case(PLOC_SPV::RESTART_MPSOC): { + prepareEmptyCmd(PLOC_SPV::APID_RESTART_MPSOC); + result = RETURN_OK; + break; + } + case(PLOC_SPV::START_MPSOC): { + prepareEmptyCmd(PLOC_SPV::APID_START_MPSOC); + result = RETURN_OK; + break; + } + case(PLOC_SPV::SHUTDOWN_MPSOC): { + prepareEmptyCmd(PLOC_SPV::APID_SHUTWOWN_MPSOC); + result = RETURN_OK; + break; + } + case(PLOC_SPV::SEL_MPSOC_BOOT_IMAGE): { + prepareSelBootImageCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::RESET_MPSOC): { + prepareEmptyCmd(PLOC_SPV::APID_RESET_MPSOC); + result = RETURN_OK; + break; + } + case(PLOC_SPV::SET_TIME_REF): { + result = prepareSetTimeRefCmd(); + break; + } + case(PLOC_SPV::SET_BOOT_TIMEOUT): { + prepareSetBootTimeoutCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::SET_MAX_RESTART_TRIES): { + prepareRestartTriesCmd(commandData); + result = RETURN_OK; + break; + } + case(PLOC_SPV::DISABLE_PERIOIC_HK_TRANSMISSION): { + prepareDisableHk(); + result = RETURN_OK; + break; + } + default: + sif::debug << "PlocSupervisorHandler::buildCommandFromCommand: Command not implemented" + << std::endl; + result = DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; + break; + } + + if (result == RETURN_OK) { + /** + * Flushing the receive buffer to make sure there are no data left from a faulty reply. + */ + uartComIf->flushUartRxBuffer(comCookie); + } + + return result; +} + +void PlocSupervisorHandler::fillCommandAndReplyMap() { + this->insertInCommandMap(PLOC_SPV::GET_HK_REPORT); + this->insertInCommandMap(PLOC_SPV::RESTART_MPSOC); + this->insertInCommandMap(PLOC_SPV::START_MPSOC); + this->insertInCommandMap(PLOC_SPV::SHUTDOWN_MPSOC); + this->insertInCommandMap(PLOC_SPV::SEL_MPSOC_BOOT_IMAGE); + this->insertInCommandMap(PLOC_SPV::SET_BOOT_TIMEOUT); + this->insertInCommandMap(PLOC_SPV::SET_MAX_RESTART_TRIES); + this->insertInCommandMap(PLOC_SPV::RESET_MPSOC); + this->insertInCommandMap(PLOC_SPV::SET_TIME_REF); + this->insertInCommandMap(PLOC_SPV::DISABLE_PERIOIC_HK_TRANSMISSION); + this->insertInReplyMap(PLOC_SPV::ACK_REPORT, 3, nullptr, PLOC_SPV::SIZE_ACK_REPORT); + this->insertInReplyMap(PLOC_SPV::EXE_REPORT, 3, nullptr, PLOC_SPV::SIZE_EXE_REPORT); + this->insertInReplyMap(PLOC_SPV::HK_REPORT, 3, nullptr, PLOC_SPV::SIZE_HK_REPORT); +} + +ReturnValue_t PlocSupervisorHandler::scanForReply(const uint8_t *start, + size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) { + + ReturnValue_t result = RETURN_OK; + + uint16_t apid = (*(start) << 8 | *(start + 1)) & APID_MASK; + + switch(apid) { + case(PLOC_SPV::APID_ACK_SUCCESS): + *foundLen = PLOC_SPV::SIZE_ACK_REPORT; + *foundId = PLOC_SPV::ACK_REPORT; + break; + case(PLOC_SPV::APID_ACK_FAILURE): + *foundLen = PLOC_SPV::SIZE_ACK_REPORT; + *foundId = PLOC_SPV::ACK_REPORT; + break; + case(PLOC_SPV::APID_HK_REPORT): + *foundLen = PLOC_SPV::SIZE_HK_REPORT; + *foundId = PLOC_SPV::HK_REPORT; + break; + case(PLOC_SPV::APID_EXE_SUCCESS): + *foundLen = PLOC_SPV::SIZE_EXE_REPORT; + *foundId = PLOC_SPV::EXE_REPORT; + break; + case(PLOC_SPV::APID_EXE_FAILURE): + *foundLen = PLOC_SPV::SIZE_EXE_REPORT; + *foundId = PLOC_SPV::EXE_REPORT; + break; + default: { + sif::debug << "PlocSupervisorHandler::scanForReply: Reply has invalid apid" << std::endl; + *foundLen = remainingSize; + return INVALID_APID; + } + } + + return result; +} + +ReturnValue_t PlocSupervisorHandler::interpretDeviceReply(DeviceCommandId_t id, + const uint8_t *packet) { + + ReturnValue_t result = RETURN_OK; + + switch (id) { + case PLOC_SPV::ACK_REPORT: { + result = handleAckReport(packet); + break; + } + case (PLOC_SPV::HK_REPORT): { + result = handleHkReport(packet); + break; + } + case (PLOC_SPV::EXE_REPORT): { + result = handleExecutionReport(packet); + break; + } + default: { + sif::debug << "PlocSupervisorHandler::interpretDeviceReply: Unknown device reply id" << std::endl; + return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; + } + } + + return result; +} + +void PlocSupervisorHandler::setNormalDatapoolEntriesInvalid(){ + +} + +uint32_t PlocSupervisorHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){ + return 500; +} + +ReturnValue_t PlocSupervisorHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) { + + localDataPoolMap.emplace(PLOC_SPV::NUM_TMS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::TEMP_PS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::TEMP_PL, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::SOC_STATE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::NVM0_1_STATE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::NVM3_STATE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::MISSION_IO_STATE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::FMC_STATE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::NUM_TCS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::UPTIME, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::CPULOAD, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PLOC_SPV::AVAILABLEHEAP, new PoolEntry( { 0 })); + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PlocSupervisorHandler::verifyPacket(const uint8_t* start, size_t foundLen) { + + uint16_t receivedCrc = *(start + foundLen - 2) << 8 | *(start + foundLen - 1); + + uint16_t recalculatedCrc = CRC::crc16ccitt(start, foundLen - 2); + + if (receivedCrc != recalculatedCrc) { + return CRC_FAILURE; + } + + return RETURN_OK; +} + +ReturnValue_t PlocSupervisorHandler::handleAckReport(const uint8_t* data) { + + ReturnValue_t result = RETURN_OK; + + result = verifyPacket(data, PLOC_SPV::SIZE_ACK_REPORT); + if(result == CRC_FAILURE) { + sif::error << "PlocSupervisorHandler::handleAckReport: CRC failure" << std::endl; + nextReplyId = PLOC_SPV::NONE; + replyRawReplyIfnotWiretapped(data, PLOC_SPV::SIZE_ACK_REPORT); + triggerEvent(SUPV_CRC_FAILURE_EVENT); + sendFailureReport(PLOC_SPV::ACK_REPORT, CRC_FAILURE); + disableAllReplies(); + return RETURN_OK; + } + + uint16_t apid = (*(data) << 8 | *(data + 1)) & APID_MASK; + + switch(apid) { + case PLOC_SPV::APID_ACK_FAILURE: { + //TODO: Interpretation of status field in acknowledgment report + sif::debug << "PlocSupervisorHandler::handleAckReport: Received Ack failure report" << std::endl; + DeviceCommandId_t commandId = getPendingCommand(); + if (commandId != DeviceHandlerIF::NO_COMMAND_ID) { + triggerEvent(SUPV_ACK_FAILURE, commandId); + } + sendFailureReport(PLOC_SPV::ACK_REPORT, RECEIVED_ACK_FAILURE); + disableAllReplies(); + nextReplyId = PLOC_SPV::NONE; + result = IGNORE_REPLY_DATA; + break; + } + case PLOC_SPV::APID_ACK_SUCCESS: { + setNextReplyId(); + break; + } + default: { + sif::debug << "PlocSupervisorHandler::handleAckReport: Invalid APID in Ack report" << std::endl; + result = RETURN_FAILED; + break; + } + } + + return result; +} + +ReturnValue_t PlocSupervisorHandler::handleExecutionReport(const uint8_t* data) { + + ReturnValue_t result = RETURN_OK; + + result = verifyPacket(data, PLOC_SPV::SIZE_EXE_REPORT); + if(result == CRC_FAILURE) { + sif::error << "PlocSupervisorHandler::handleExecutionReport: CRC failure" << std::endl; + nextReplyId = PLOC_SPV::NONE; + return result; + } + + uint16_t apid = (*(data) << 8 | *(data + 1)) & APID_MASK; + + switch (apid) { + case (PLOC_SPV::APID_EXE_SUCCESS): { + break; + } + case (PLOC_SPV::APID_EXE_FAILURE): { + //TODO: Interpretation of status field in execution report + sif::error << "PlocSupervisorHandler::handleExecutionReport: Received execution failure report" + << std::endl; + DeviceCommandId_t commandId = getPendingCommand(); + if (commandId != DeviceHandlerIF::NO_COMMAND_ID) { + triggerEvent(SUPV_EXE_FAILURE, commandId); + } + else { + sif::debug << "PlocSupervisorHandler::handleExecutionReport: Unknown command id" << std::endl; + } + sendFailureReport(PLOC_SPV::EXE_REPORT, RECEIVED_EXE_FAILURE); + disableExeReportReply(); + result = IGNORE_REPLY_DATA; + break; + } + default: { + sif::error << "PlocSupervisorHandler::handleExecutionReport: Unknown APID" << std::endl; + result = RETURN_FAILED; + break; + } + } + + nextReplyId = PLOC_SPV::NONE; + + return result; +} + +ReturnValue_t PlocSupervisorHandler::handleHkReport(const uint8_t* data) { + + ReturnValue_t result = RETURN_OK; + + result = verifyPacket(data, PLOC_SPV::SIZE_HK_REPORT); + + if(result == CRC_FAILURE) { + sif::error << "PlocSupervisorHandler::handleHkReport: Hk report has invalid crc" + << std::endl; + } + + uint16_t offset = PLOC_SPV::DATA_FIELD_OFFSET; + hkset.tempPs = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 + | *(data + offset + 3); + offset += 4; + hkset.tempPl = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 + | *(data + offset + 3); + offset += 4; + hkset.tempSup = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 + | *(data + offset + 3); + offset += 4; + hkset.uptime = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 + | *(data + offset + 3); + offset += 4; + hkset.cpuLoad = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 + | *(data + offset + 3); + offset += 4; + hkset.availableHeap = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 + | *(data + offset + 3); + offset += 4; + hkset.numTcs = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 + | *(data + offset + 3); + offset += 4; + hkset.numTms = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 + | *(data + offset + 3); + offset += 4; + hkset.socState = *(data + offset) << 24 | *(data + offset + 1) << 16 | *(data + offset + 2) << 8 + | *(data + offset + 3); + offset += 4; + hkset.nvm0_1_state = *(data + offset); + offset += 1; + hkset.nvm3_state = *(data + offset); + offset += 1; + hkset.missionIoState = *(data + offset); + offset += 1; + hkset.fmcState = *(data + offset); + offset += 1; + + nextReplyId = PLOC_SPV::EXE_REPORT; + +#if OBSW_VERBOSE_LEVEL >= 1 && PLOC_SUPERVISOR_DEBUG == 1 + sif::info << "PlocSupervisorHandler::handleHkReport: temp_ps: " << hkset.tempPs << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: temp_pl: " << hkset.tempPl << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: temp_sup: " << hkset.tempSup << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: uptime: " << hkset.uptime << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: cpu_load: " << hkset.cpuLoad << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: available_heap: " << hkset.availableHeap << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: num_tcs: " << hkset.numTcs << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: num_tms: " << hkset.numTms << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: soc_state: " << hkset.socState << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: nvm0_1_state: " + << static_cast(hkset.nvm0_1_state.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: nvm3_state: " + << static_cast(hkset.nvm3_state.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: missoin_io_state: " + << static_cast(hkset.missionIoState.value) << std::endl; + sif::info << "PlocSupervisorHandler::handleHkReport: fmc_state: " + << static_cast(hkset.fmcState.value) << std::endl; + +#endif + + return result; +} + +ReturnValue_t PlocSupervisorHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command, + uint8_t expectedReplies, bool useAlternateId, + DeviceCommandId_t alternateReplyID) { + + ReturnValue_t result = RETURN_OK; + + uint8_t enabledReplies = 0; + + switch (command->first) { + case PLOC_SPV::GET_HK_REPORT: { + enabledReplies = 3; + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, + PLOC_SPV::HK_REPORT); + if (result != RETURN_OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << PLOC_SPV::HK_REPORT << " not in replyMap" << std::endl; + } + break; + } + case PLOC_SPV::RESTART_MPSOC: + case PLOC_SPV::START_MPSOC: + case PLOC_SPV::SHUTDOWN_MPSOC: + case PLOC_SPV::SEL_MPSOC_BOOT_IMAGE: + case PLOC_SPV::SET_BOOT_TIMEOUT: + case PLOC_SPV::SET_MAX_RESTART_TRIES: + case PLOC_SPV::RESET_MPSOC: + case PLOC_SPV::SET_TIME_REF: + enabledReplies = 2; + break; + default: + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Unknown command id" << std::endl; + break; + } + + /** + * Every command causes at least one acknowledgment and one execution report. Therefore both + * replies will be enabled here. + */ + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, + PLOC_SPV::ACK_REPORT); + if (result != RETURN_OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << PLOC_SPV::ACK_REPORT << " not in replyMap" << std::endl; + } + + result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, + PLOC_SPV::EXE_REPORT); + if (result != RETURN_OK) { + sif::debug << "PlocSupervisorHandler::enableReplyInReplyMap: Reply with id " + << PLOC_SPV::EXE_REPORT << " not in replyMap" << std::endl; + } + + return RETURN_OK; +} + +void PlocSupervisorHandler::setNextReplyId() { + switch(getPendingCommand()) { + case PLOC_SPV::GET_HK_REPORT: + nextReplyId = PLOC_SPV::HK_REPORT; + break; + default: + /* If no telemetry is expected the next reply is always the execution report */ + nextReplyId = PLOC_SPV::EXE_REPORT; + break; + } +} +size_t PlocSupervisorHandler::getNextReplyLength(DeviceCommandId_t commandId){ + + size_t replyLen = 0; + + if (nextReplyId == PLOC_SPV::NONE) { + return replyLen; + } + + DeviceReplyIter iter = deviceReplyMap.find(nextReplyId); + if (iter != deviceReplyMap.end()) { + if (iter->second.delayCycles == 0) { + /* Reply inactive */ + return replyLen; + } + replyLen = iter->second.replyLen; + } + else { + sif::debug << "PlocSupervisorHandler::getNextReplyLength: No entry for reply with reply id " + << std::hex << nextReplyId << " in deviceReplyMap" << std::endl; + } + + return replyLen; +} + +void PlocSupervisorHandler::handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId) { + + ReturnValue_t result = RETURN_OK; + + if (wiretappingMode == RAW) { + /* Data already sent in doGetRead() */ + return; + } + + DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId); + if (iter == deviceReplyMap.end()) { + sif::debug << "PlocSupervisorHandler::handleDeviceTM: Unknown reply id" << std::endl; + return; + } + MessageQueueId_t queueId = iter->second.command->second.sendReplyTo; + + if (queueId == NO_COMMANDER) { + return; + } + + result = actionHelper.reportData(queueId, replyId, data, dataSize); + if (result != RETURN_OK) { + sif::debug << "PlocSupervisorHandler::handleDeviceTM: Failed to report data" << std::endl; + } +} + +void PlocSupervisorHandler::prepareEmptyCmd(uint16_t apid) { + PLOC_SPV::EmptyPacket packet(apid); + memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); + rawPacket = commandBuffer; + rawPacketLen = packet.getFullSize(); + nextReplyId = PLOC_SPV::ACK_REPORT; +} + +void PlocSupervisorHandler::prepareSelBootImageCmd(const uint8_t * commandData) { + PLOC_SPV::MPSoCBootSelect packet(*commandData, *(commandData + 1), *(commandData + 2), + *(commandData + 3)); + memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); + rawPacket = commandBuffer; + rawPacketLen = packet.getFullSize(); + nextReplyId = PLOC_SPV::ACK_REPORT; +} + +ReturnValue_t PlocSupervisorHandler::prepareSetTimeRefCmd() { + Clock::TimeOfDay_t time; + ReturnValue_t result = Clock::getDateAndTime(&time); + if (result != RETURN_OK) { + sif::warning << "PlocSupervisorHandler::prepareSetTimeRefCmd: Failed to get current time" + << std::endl; + return GET_TIME_FAILURE; + } + PLOC_SPV::SetTimeRef packet(&time); + memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); + rawPacket = commandBuffer; + rawPacketLen = packet.getFullSize(); + nextReplyId = PLOC_SPV::ACK_REPORT; + return RETURN_OK; +} + +void PlocSupervisorHandler::prepareDisableHk() { + PLOC_SPV::DisablePeriodicHkTransmission packet; + memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); + rawPacket = commandBuffer; + rawPacketLen = packet.getFullSize(); + nextReplyId = PLOC_SPV::ACK_REPORT; +} + +void PlocSupervisorHandler::prepareSetBootTimeoutCmd(const uint8_t * commandData) { + uint32_t timeout = *(commandData) << 24 | *(commandData + 1) << 16 | *(commandData + 2) << 8 + | *(commandData + 3); + PLOC_SPV::SetBootTimeout packet(timeout); + memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); + rawPacket = commandBuffer; + rawPacketLen = packet.getFullSize(); + nextReplyId = PLOC_SPV::ACK_REPORT; +} + +void PlocSupervisorHandler::prepareRestartTriesCmd(const uint8_t * commandData) { + uint8_t restartTries = *(commandData); + PLOC_SPV::SetRestartTries packet(restartTries); + memcpy(commandBuffer, packet.getWholeData(), packet.getFullSize()); + rawPacket = commandBuffer; + rawPacketLen = packet.getFullSize(); + nextReplyId = PLOC_SPV::ACK_REPORT; +} + +void PlocSupervisorHandler::disableAllReplies() { + + DeviceReplyMap::iterator iter; + + /* Disable ack reply */ + iter = deviceReplyMap.find(PLOC_SPV::ACK_REPORT); + DeviceReplyInfo *info = &(iter->second); + info->delayCycles = 0; + info->command = deviceCommandMap.end(); + + DeviceCommandId_t commandId = getPendingCommand(); + + /* If the command expects a telemetry packet the appropriate tm reply will be disabled here */ + switch (commandId) { + case PLOC_SPV::GET_HK_REPORT: { + iter = deviceReplyMap.find(PLOC_SPV::GET_HK_REPORT); + info = &(iter->second); + info->delayCycles = 0; + info->command = deviceCommandMap.end(); + break; + } + default: { + break; + } + } + + /* We must always disable the execution report reply here */ + disableExeReportReply(); +} + +void PlocSupervisorHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status) { + + DeviceReplyIter iter = deviceReplyMap.find(replyId); + + if (iter == deviceReplyMap.end()) { + sif::debug << "PlocSupervisorHandler::sendFailureReport: Reply not in reply map" << std::endl; + return; + } + + DeviceCommandInfo* info = &(iter->second.command->second); + + if (info == nullptr) { + sif::debug << "PlocSupervisorHandler::sendFailureReport: Reply has no active command" << std::endl; + return; + } + + if (info->sendReplyTo != NO_COMMANDER) { + actionHelper.finish(false, info->sendReplyTo, iter->first, status); + } + info->isExecuting = false; +} + +void PlocSupervisorHandler::disableExeReportReply() { + DeviceReplyIter iter = deviceReplyMap.find(PLOC_SPV::EXE_REPORT); + DeviceReplyInfo *info = &(iter->second); + info->delayCycles = 0; + info->command = deviceCommandMap.end(); + /* Expected replies is set to one here. The value will set to 0 in replyToReply() */ + info->command->second.expectedReplies = 1; +} diff --git a/mission/devices/PlocSupervisorHandler.h b/mission/devices/PlocSupervisorHandler.h new file mode 100644 index 00000000..e91fb1e4 --- /dev/null +++ b/mission/devices/PlocSupervisorHandler.h @@ -0,0 +1,213 @@ +#ifndef MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ +#define MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ + +#include +#include +#include +#include + +/** + * @brief This is the device handler for the supervisor of the PLOC which is programmed by + * Thales. + * + * @details The PLOC uses the space packet protocol for communication. To each command the PLOC + * answers with at least one acknowledgment and one execution report. + * Flight manual: + * https://egit.irs.uni-stuttgart.de/redmine/projects/eive-flight-manual/wiki/PLOC_Commands + * ILH ICD: https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/ + * Arbeitsdaten/08_Used%20Components/PLOC&fileid=940960 + * @author J. Meier + */ +class PlocSupervisorHandler: public DeviceHandlerBase { +public: + + PlocSupervisorHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF * comCookie); + virtual ~PlocSupervisorHandler(); + + virtual ReturnValue_t initialize() override; + +protected: + void doStartUp() override; + void doShutDown() override; + ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override; + ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) override; + void fillCommandAndReplyMap() override; + ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, + const uint8_t * commandData,size_t commandDataLen) override; + ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize, + DeviceCommandId_t *foundId, size_t *foundLen) override; + ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, + const uint8_t *packet) override; + void setNormalDatapoolEntriesInvalid() override; + uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; + ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command, + uint8_t expectedReplies = 1, bool useAlternateId = false, + DeviceCommandId_t alternateReplyID = 0) override; + size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override; + +private: + + static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_SUPERVISOR_HANDLER; + + //! [EXPORT] : [COMMENT] Space Packet received from PLOC supervisor has invalid CRC + static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0); + //! [EXPORT] : [COMMENT] Received ACK failure reply from PLOC supervisor + static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1); + //! [EXPORT] : [COMMENT] Received execution failure reply from PLOC supervisor + static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2); + //! [EXPORT] : [COMMENT] Received space packet with invalid APID from PLOC supervisor + static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3); + //! [EXPORT] : [COMMENT] Failed to read current system time + static const ReturnValue_t GET_TIME_FAILURE = MAKE_RETURN_CODE(0xA4); + //! [EXPORT] : [COMMENT] Invalid communication interface specified + static const ReturnValue_t INVALID_UART_COM_IF = MAKE_RETURN_CODE(0xA5); + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_SUPERVISOR_HANDLER; + + //! [EXPORT] : [COMMENT] PLOC supervrisor crc failure in telemetry packet + static const Event SUPV_MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW); + //! [EXPORT] : [COMMENT] PLOC supervisor received acknowledgment failure report + static const Event SUPV_ACK_FAILURE = MAKE_EVENT(2, severity::LOW); + //! [EXPORT] : [COMMENT] PLOC received execution failure report + static const Event SUPV_EXE_FAILURE = MAKE_EVENT(3, severity::LOW); + //! [EXPORT] : [COMMENT] PLOC supervisor reply has invalid crc + static const Event SUPV_CRC_FAILURE_EVENT = MAKE_EVENT(4, severity::LOW); + + static const uint16_t APID_MASK = 0x7FF; + static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF; + + uint8_t commandBuffer[PLOC_SPV::MAX_COMMAND_SIZE]; + + /** + * @brief This object is incremented each time a packet is sent or received. By checking the + * packet sequence count of a received packet, no packets can be lost without noticing + * it. Only the least significant 14 bits represent the packet sequence count in a + * space packet. Thus the maximum value amounts to 16383 (0x3FFF). + * @note Normally this should never happen because the PLOC replies are always sent in a + * fixed order. However, the PLOC software checks this value and will return an ACK + * failure report in case the sequence count is not incremented with each transferred + * space packet. + */ + uint16_t packetSequenceCount = 0x3FFF; + + /** + * This variable is used to store the id of the next reply to receive. This is necessary + * because the PLOC sends as reply to each command at least one acknowledgment and execution + * report. + */ + DeviceCommandId_t nextReplyId = PLOC_SPV::NONE; + + PLOC_SPV::HkSet hkset; + + UartComIF* uartComIf = nullptr; + + /** + * @brief This function checks the crc of the received PLOC reply. + * + * @param start Pointer to the first byte of the reply. + * @param foundLen Pointer to the length of the whole packet. + * + * @return RETURN_OK if CRC is ok, otherwise CRC_FAILURE. + */ + ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen); + + /** + * @brief This function handles the acknowledgment report. + * + * @param data Pointer to the data holding the acknowledgment report. + * + * @return RETURN_OK if successful, otherwise an error code. + */ + ReturnValue_t handleAckReport(const uint8_t* data); + + /** + * @brief This function handles the data of a execution report. + * + * @param data Pointer to the received data packet. + * + * @return RETURN_OK if successful, otherwise an error code. + */ + ReturnValue_t handleExecutionReport(const uint8_t* data); + + /** + * @brief This function handles the housekeeping report. This means verifying the CRC of the + * reply and filling the appropriate dataset. + * + * @param data Pointer to the data buffer holding the housekeeping read report. + * + * @return RETURN_OK if successful, otherwise an error code. + */ + ReturnValue_t handleHkReport(const uint8_t* data); + + /** + * @brief Depending on the current active command, this function sets the reply id of the + * next reply after a successful acknowledgment report has been received. This is + * required by the function getNextReplyLength() to identify the length of the next + * reply to read. + */ + void setNextReplyId(); + + /** + * @brief This function handles action message replies in case the telemetry has been + * requested by another object. + * + * @param data Pointer to the telemetry data. + * @param dataSize Size of telemetry in bytes. + * @param replyId Id of the reply. This will be added to the ActionMessage. + */ + void handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId); + + /** + * @brief This function prepares a space packet which does not transport any data in the + * packet data field apart from the crc. + */ + void prepareEmptyCmd(uint16_t apid); + + + /** + * @brief This function initializes the space packet to select the boot image of the MPSoC. + */ + void prepareSelBootImageCmd(const uint8_t * commandData); + + void prepareDisableHk(); + + /** + * @brief This function fills the commandBuffer with the data to update the time of the + * PLOC supervisor. + */ + ReturnValue_t prepareSetTimeRefCmd(); + + /** + * @brief This function fills the commandBuffer with the data to change the boot timeout + * value in the PLOC supervisor. + */ + void prepareSetBootTimeoutCmd(const uint8_t * commandData); + + void prepareRestartTriesCmd(const uint8_t * commandData); + + /** + * @brief In case an acknowledgment failure reply has been received this function disables + * all previously enabled commands and resets the exepected replies variable of an + * active command. + */ + void disableAllReplies(); + + /** + * @brief This function sends a failure report if the active action was commanded by an other + * object. + * + * @param replyId The id of the reply which signals a failure. + * @param status A status byte which gives information about the failure type. + */ + void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status); + + /** + * @brief This function disables the execution report reply. Within this function also the + * the variable expectedReplies of an active command will be set to 0. + */ + void disableExeReportReply(); +}; + +#endif /* MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ */ diff --git a/mission/devices/RadiationSensorHandler.cpp b/mission/devices/RadiationSensorHandler.cpp index 65a877b6..bb5176ee 100644 --- a/mission/devices/RadiationSensorHandler.cpp +++ b/mission/devices/RadiationSensorHandler.cpp @@ -58,7 +58,7 @@ ReturnValue_t RadiationSensorHandler::buildTransitionDeviceCommand( *id = RAD_SENSOR::WRITE_SETUP; } else { - return HasReturnvaluesIF::RETURN_OK; + return NOTHING_TO_SEND; } return buildCommandFromCommand(*id, nullptr, 0); } @@ -84,15 +84,19 @@ ReturnValue_t RadiationSensorHandler::buildCommandFromCommand( } case(RAD_SENSOR::READ_CONVERSIONS): { cmdBuffer[0] = RAD_SENSOR::DUMMY_BYTE; - cmdBuffer[1] = RAD_SENSOR::DUMMY_BYTE; - cmdBuffer[2] = RAD_SENSOR::DUMMY_BYTE; - cmdBuffer[3] = RAD_SENSOR::DUMMY_BYTE; - cmdBuffer[4] = RAD_SENSOR::DUMMY_BYTE; - cmdBuffer[5] = RAD_SENSOR::DUMMY_BYTE; + std::memset(cmdBuffer, RAD_SENSOR::DUMMY_BYTE, RAD_SENSOR::READ_SIZE); rawPacket = cmdBuffer; rawPacketLen = RAD_SENSOR::READ_SIZE; return RETURN_OK; } +// case(RAD_SENSOR::AIN0_AND_TMP_CONVERSION): { +// /* First the fifo will be reset here */ +// cmdBuffer[0] = RAD_SENSOR::RESET_DEFINITION; +// cmdBuffer[1] = RAD_SENSOR::CONVERSION_DEFINITION; +// rawPacket = cmdBuffer; +// rawPacketLen = 2; +// return RETURN_OK; +// } default: return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; } @@ -109,7 +113,17 @@ void RadiationSensorHandler::fillCommandAndReplyMap() { ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) { *foundId = this->getPendingCommand(); + + switch (*foundId) { + case RAD_SENSOR::START_CONVERSION: + case RAD_SENSOR::WRITE_SETUP: + return IGNORE_REPLY_DATA; + default: + break; + } + *foundLen = remainingSize; + return HasReturnvaluesIF::RETURN_OK; } @@ -117,16 +131,36 @@ ReturnValue_t RadiationSensorHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { switch (id) { case RAD_SENSOR::READ_CONVERSIONS: { + uint8_t offset = 0; PoolReadGuard readSet(&dataset); - dataset.temperatureCelcius = (*(packet) << 8 | *(packet + 1)) * 0.125; - dataset.channel0 = (*(packet + 2) << 8 | *(packet + 3)); - dataset.channel1 = (*(packet + 4) << 8 | *(packet + 5)); + dataset.temperatureCelcius = (*(packet + offset) << 8 | *(packet + offset + 1)) * 0.125; + offset += 2; + dataset.ain0 = (*(packet + offset) << 8 | *(packet + offset +1)); + offset += 2; + dataset.ain1 = (*(packet + offset) << 8 | *(packet + offset + 1)); + offset += 6; + dataset.ain4 = (*(packet + offset) << 8 | *(packet + offset + 1)); + offset += 2; + dataset.ain5 = (*(packet + offset) << 8 | *(packet + offset + 1)); + offset += 2; + dataset.ain6 = (*(packet + offset) << 8 | *(packet + offset + 1)); + offset += 2; + dataset.ain7 = (*(packet + offset) << 8 | *(packet + offset + 1)); + #if OBSW_VERBOSE_LEVEL >= 1 && DEBUG_RAD_SENSOR sif::info << "Radiation sensor temperature: " << dataset.temperatureCelcius << " °C" << std::endl; - sif::info << "Radiation sensor temperature ADC value channel 0: " << dataset.channel0 + sif::info << "Radiation sensor ADC value channel 0: " << dataset.ain0 << std::endl; - sif::info << "Radiation sensor temperature ADC value channel 1: " << dataset.channel1 + sif::info << "Radiation sensor ADC value channel 1: " << dataset.ain1 + << std::endl; + sif::info << "Radiation sensor ADC value channel 4: " << dataset.ain4 + << std::endl; + sif::info << "Radiation sensor ADC value channel 5: " << dataset.ain5 + << std::endl; + sif::info << "Radiation sensor ADC value channel 6: " << dataset.ain6 + << std::endl; + sif::info << "Radiation sensor ADC value channel 7: " << dataset.ain7 << std::endl; #endif break; @@ -151,8 +185,12 @@ uint32_t RadiationSensorHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t mo ReturnValue_t RadiationSensorHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { localDataPoolMap.emplace(RAD_SENSOR::TEMPERATURE_C, new PoolEntry( { 0.0 })); - localDataPoolMap.emplace(RAD_SENSOR::CHANNEL_0, new PoolEntry( { 0 })); - localDataPoolMap.emplace(RAD_SENSOR::CHANNEL_1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(RAD_SENSOR::AIN0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(RAD_SENSOR::AIN1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(RAD_SENSOR::AIN4, new PoolEntry( { 0 })); + localDataPoolMap.emplace(RAD_SENSOR::AIN5, new PoolEntry( { 0 })); + localDataPoolMap.emplace(RAD_SENSOR::AIN6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(RAD_SENSOR::AIN7, new PoolEntry( { 0 })); return HasReturnvaluesIF::RETURN_OK; } diff --git a/mission/devices/RwHandler.cpp b/mission/devices/RwHandler.cpp index beb17602..86e09b9e 100644 --- a/mission/devices/RwHandler.cpp +++ b/mission/devices/RwHandler.cpp @@ -60,7 +60,7 @@ ReturnValue_t RwHandler::buildNormalDeviceCommand(DeviceCommandId_t * id) { internalState = InternalState::GET_RESET_STATUS; break; default: - sif::debug << "RwHandler::buildNormalDeviceCommand: Invalid communication step" + sif::debug << "RwHandler::buildNormalDeviceCommand: Invalid internal step" << std::endl; break; } @@ -176,8 +176,7 @@ ReturnValue_t RwHandler::scanForReply(const uint8_t *start, size_t remainingSize break; } case (static_cast(RwDefinitions::GET_TM)): { -// *foundLen = RwDefinitions::SIZE_GET_TELEMETRY_REPLY; - *foundLen = 91; + *foundLen = RwDefinitions::SIZE_GET_TELEMETRY_REPLY; *foundId = RwDefinitions::GET_TM; break; } @@ -264,6 +263,8 @@ ReturnValue_t RwHandler::initializeLocalDataPool(localpool::DataPool& localDataP localDataPoolMap.emplace(RwDefinitions::TM_LAST_RESET_STATUS, new PoolEntry( { 0 })); localDataPoolMap.emplace(RwDefinitions::TM_MCU_TEMPERATURE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(RwDefinitions::PRESSURE_SENSOR_TEMPERATURE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(RwDefinitions::PRESSURE, new PoolEntry( { 0 })); localDataPoolMap.emplace(RwDefinitions::TM_RW_STATE, new PoolEntry( { 0 })); localDataPoolMap.emplace(RwDefinitions::TM_CLC_MODE, new PoolEntry( { 0 })); localDataPoolMap.emplace(RwDefinitions::TM_RW_CURR_SPEED, new PoolEntry( { 0 })); @@ -407,7 +408,12 @@ void RwHandler::handleGetTelemetryReply(const uint8_t* packet) { tmDataset.mcuTemperature = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16 | *(packet + offset + 1) << 8 | *(packet + offset); offset += 4; - offset += 8; + tmDataset.pressureSensorTemperature = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16 + | *(packet + offset + 1) << 8 | *(packet + offset); + offset += 4; + tmDataset.pressure = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16 + | *(packet + offset + 1) << 8 | *(packet + offset); + offset += 4; tmDataset.rwState = *(packet + offset); offset += 1; tmDataset.rwClcMode = *(packet + offset); @@ -470,6 +476,10 @@ void RwHandler::handleGetTelemetryReply(const uint8_t* packet) { << static_cast(tmDataset.lastResetStatus.value) << std::endl; sif::info << "RwHandler::handleTemperatureReply: MCU temperature: " << tmDataset.mcuTemperature << std::endl; + sif::info << "RwHandler::handleTemperatureReply: Pressure sensor temperature: " + << tmDataset.pressureSensorTemperature << std::endl; + sif::info << "RwHandler::handleTemperatureReply: Pressure " + << tmDataset.pressure << std::endl; sif::info << "RwHandler::handleTemperatureReply: State: " << static_cast(tmDataset.rwState.value) << std::endl; sif::info << "RwHandler::handleTemperatureReply: CLC mode: " diff --git a/mission/devices/RwHandler.h b/mission/devices/RwHandler.h index cd753be0..a0577043 100644 --- a/mission/devices/RwHandler.h +++ b/mission/devices/RwHandler.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include /** diff --git a/mission/devices/StarTrackerHandler.cpp b/mission/devices/StarTrackerHandler.cpp new file mode 100644 index 00000000..59eab3de --- /dev/null +++ b/mission/devices/StarTrackerHandler.cpp @@ -0,0 +1,216 @@ +#include "StarTrackerHandler.h" +#include "OBSWConfig.h" + +#include +#include + +extern "C" { + #include + #include "common/misc.h" +} + +StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF, + CookieIF * comCookie) : + DeviceHandlerBase(objectId, comIF, comCookie), temperatureSet(this) { + if (comCookie == NULL) { + sif::error << "StarTrackerHandler: Invalid com cookie" << std::endl; + } + slipInit(); +} + +StarTrackerHandler::~StarTrackerHandler() { +} + +void StarTrackerHandler::doStartUp() { + +#if OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP == 1 + setMode(MODE_NORMAL); +#else + setMode(_MODE_TO_ON); +#endif + +} + +void StarTrackerHandler::doShutDown() { +} + +ReturnValue_t StarTrackerHandler::buildNormalDeviceCommand(DeviceCommandId_t * id) { + switch (internalState) { + case InternalState::TEMPERATURE_REQUEST: + *id = StarTracker::REQ_TEMPERATURE; + break; + default: + sif::debug << "StarTrackerHandler::buildNormalDeviceCommand: Invalid internal step" + << std::endl; + break; + } + return buildCommandFromCommand(*id, NULL, 0); +} + +ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t * id) { + return NOTHING_TO_SEND; +} + +ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand, + const uint8_t * commandData, size_t commandDataLen) { + + switch (deviceCommand) { + case (StarTracker::REQ_TEMPERATURE): { + prepareTemperatureRequest(); + return RETURN_OK; + } + default: + return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; + } + return HasReturnvaluesIF::RETURN_FAILED; +} + +void StarTrackerHandler::fillCommandAndReplyMap() { + /** Reply lengths are unknown because of the slip encoding. Thus always maximum reply size + * is specified */ + this->insertInCommandAndReplyMap(StarTracker::REQ_TEMPERATURE, 1, &temperatureSet, + StarTracker::MAX_FRAME_SIZE * 2 + 2); +} + +ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t *start, size_t remainingSize, + DeviceCommandId_t *foundId, size_t *foundLen) { + + uint32_t decodedLength = 0; + + for (size_t idx = 0; idx < remainingSize; idx++) { + enum arc_dec_result decResult = arc_transport_decode_body(*(start + idx), &slipInfo, + decodedFrame, &decodedLength); + + switch (decResult) { + case ARC_DEC_INPROGRESS: { + continue; + } + case ARC_DEC_ASYNC: { + sif::debug << "StarTrackerHandler::scanForReply: Received asychronous tm" << std::endl; + /** No asynchronous replies are expected as of now */ + return RETURN_FAILED; + } + case ARC_DEC_ERROR_FRAME_SHORT: + return REPLY_TOO_SHORT; + case ARC_DEC_ERROR_CHECKSUM: + return CRC_FAILURE; + case ARC_DEC_SYNC: { + /** Reset length of SLIP struct for next frame */ + slipInfo.length = 0; + break; + } + default: + sif::debug << "StarTrackerHandler::scanForReply: Unknown result code" << std::endl; + break; + } + } + + switch (decodedFrame[1]) { + case (static_cast(StarTracker::REQ_TEMPERATURE)): { + *foundLen = decodedLength; + *foundId = StarTracker::REQ_TEMPERATURE; + break; + } + default: { + sif::debug << "StarTrackerHandler::scanForReply: Reply contains invalid reply id" + << std::endl; + return RETURN_FAILED; + break; + } + } + + return RETURN_OK; +} + +ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { + + switch (id) { + case (StarTracker::REQ_TEMPERATURE): { + handleTemperatureTm(); + break; + } + default: { + sif::debug << "StarTrackerHandler::interpretDeviceReply: Unknown device reply id" << std::endl; + return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; + } + } + + return RETURN_OK; +} + +void StarTrackerHandler::setNormalDatapoolEntriesInvalid() { + +} + +uint32_t StarTrackerHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { + return 5000; +} + +ReturnValue_t StarTrackerHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) { + + localDataPoolMap.emplace(StarTracker::STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TICKS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::TIME, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::MCU_TEMPERATURE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(StarTracker::CMOS_TEMPERATURE, new PoolEntry( { 0 })); + + return RETURN_OK; +} + +size_t StarTrackerHandler::getNextReplyLength(DeviceCommandId_t commandId){ + return StarTracker::MAX_FRAME_SIZE; +} + +void StarTrackerHandler::slipInit() { + slipInfo.buffer = rxBuffer; + slipInfo.maxlength = StarTracker::MAX_FRAME_SIZE; + slipInfo.length = 0; + slipInfo.unescape_next = 0; + slipInfo.prev_state = SLIP_COMPLETE; +} + +void StarTrackerHandler::prepareTemperatureRequest() { + uint32_t length = 0; + arc_tm_pack_temperature_req(commandBuffer, &length); + uint32_t encLength = 0; + arc_transport_encode_body(commandBuffer, length, encBuffer, &encLength); + rawPacket = encBuffer; + rawPacketLen = encLength; +} + +void StarTrackerHandler::handleTemperatureTm() { + PoolReadGuard rg(&temperatureSet); + uint32_t offset = 1; + temperatureSet.status = *(decodedFrame + offset); + offset += 1; + if(temperatureSet.status.value != 0) { + sif::warning << "StarTrackerHandler::handleTemperatureTm: Reply error: " + << static_cast(temperatureSet.status.value) << std::endl; + triggerEvent(TM_REPLY_ERROR, temperatureSet.status.value); + } + temperatureSet.ticks = *(decodedFrame + offset) << 24 + | *(decodedFrame + offset + 1) << 16 | *(decodedFrame + offset + 2) << 8 + | *(decodedFrame + offset + 3); + offset += 4; + temperatureSet.time = static_cast(*(decodedFrame + offset)) << 56 + | static_cast(*(decodedFrame + offset + 1)) << 48 + | static_cast(*(decodedFrame + offset + 2)) << 40 + | static_cast(*(decodedFrame + offset + 3)) << 32 + | *(decodedFrame + offset + 4) << 24 | *(decodedFrame + offset + 5) << 16 + | *(decodedFrame + offset + 6) << 8 | *(decodedFrame + offset + 7); + offset += 8; + temperatureSet.mcuTemperature = *(decodedFrame + offset) << 24 + | *(decodedFrame + offset + 1) << 16 | *(decodedFrame + offset + 2) << 8 + | *(decodedFrame + offset + 3); + offset += 4; + temperatureSet.cmosTemperature = *(decodedFrame + offset) << 24 + | *(decodedFrame + offset + 1) << 16 | *(decodedFrame + offset + 2) << 8 + | *(decodedFrame + offset + 3); +#if OBSW_VERBOSE_LEVEL >= 1 && START_TRACKER_DEBUG == 1 + sif::info << "StarTrackerHandler::handleTemperatureTm: MCU Temperature: " + << temperatureSet.mcuTemperature << " °C" << std::endl; + sif::info << "StarTrackerHandler::handleTemperatureTm: CMOS Temperature: " + << temperatureSet.mcuTemperature << " °C" << std::endl; +#endif +} diff --git a/mission/devices/StarTrackerHandler.h b/mission/devices/StarTrackerHandler.h new file mode 100644 index 00000000..ee96e544 --- /dev/null +++ b/mission/devices/StarTrackerHandler.h @@ -0,0 +1,100 @@ +#ifndef MISSION_DEVICES_STARTRACKERHANDLER_H_ +#define MISSION_DEVICES_STARTRACKERHANDLER_H_ + +#include +#include +#include + +/** + * @brief This is the device handler for the star tracker from arcsec. + * + * @details Datasheet: https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/ + * Arbeitsdaten/08_Used%20Components/ArcSec_KULeuven_Startracker/ + * Sagitta%201.0%20Datapack&fileid=659181 + * + * @author J. Meier + */ +class StarTrackerHandler: public DeviceHandlerBase { +public: + + /** + * @brief Constructor + * + * @param objectId + * @param comIF + * @param comCookie + * @param gpioComIF Pointer to gpio communication interface + * @param enablePin GPIO connected to the enable pin of the reaction wheels. Must be pulled + * to high to enable the device. + */ + StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie); + virtual ~StarTrackerHandler(); + +protected: + void doStartUp() override; + void doShutDown() override; + ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override; + ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) override; + void fillCommandAndReplyMap() override; + ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, + const uint8_t * commandData,size_t commandDataLen) override; + ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize, + DeviceCommandId_t *foundId, size_t *foundLen) override; + ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, + const uint8_t *packet) override; + void setNormalDatapoolEntriesInvalid() override; + uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; + + /** + * @brief Overwritten here to always read all available data from the UartComIF. + */ + virtual size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override; + +private: + + static const uint8_t INTERFACE_ID = CLASS_ID::STR_HANDLER; + + //! [EXPORT] : [COMMENT] Received reply is too short + static const ReturnValue_t REPLY_TOO_SHORT = MAKE_RETURN_CODE(0xB0); + //! [EXPORT] : [COMMENT] Received reply with invalid CRC + static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xB0); + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::STR_HANDLER; + + //! [EXPORT] : [COMMENT] Result code of tm reply indicates an error + static const ReturnValue_t TM_REPLY_ERROR = MAKE_RETURN_CODE(0xA0); + //! P1: TM id + + StarTracker::TemperatureSet temperatureSet; + + uint8_t commandBuffer[StarTracker::MAX_FRAME_SIZE]; + uint8_t rxBuffer[StarTracker::MAX_FRAME_SIZE]; + uint8_t decodedFrame[StarTracker::MAX_FRAME_SIZE]; + + /** Size of buffer derived from the egse source code */ + uint8_t encBuffer[StarTracker::MAX_FRAME_SIZE * 2 + 2]; + + slip_decode_state slipInfo; + + enum class InternalState { + TEMPERATURE_REQUEST + }; + + InternalState internalState = InternalState::TEMPERATURE_REQUEST; + + /** + * @brief This function initializes the serial link ip protocol struct slipInfo. + */ + void slipInit(); + + void prepareTemperatureRequest(); + + /** + * @brief This function handles the telemetry reply of a temperature request. + */ + void handleTemperatureTm(); +}; + +#endif /* MISSION_DEVICES_STARTRACKERHANDLER_H_ */ diff --git a/mission/devices/devicedefinitions/PlocDefinitions.h b/mission/devices/devicedefinitions/PlocMPSoCDefinitions.h similarity index 96% rename from mission/devices/devicedefinitions/PlocDefinitions.h rename to mission/devices/devicedefinitions/PlocMPSoCDefinitions.h index 5cc38d5a..2b9466ab 100644 --- a/mission/devices/devicedefinitions/PlocDefinitions.h +++ b/mission/devices/devicedefinitions/PlocMPSoCDefinitions.h @@ -1,11 +1,11 @@ -#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_PLOCDEFINITIONS_H_ -#define MISSION_DEVICES_DEVICEDEFINITIONS_PLOCDEFINITIONS_H_ +#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_PLOCMPSOCDEFINITIONS_H_ +#define MISSION_DEVICES_DEVICEDEFINITIONS_PLOCMPSOCDEFINITIONS_H_ #include #include #include -namespace PLOC { +namespace PLOC_MPSOC { static const DeviceCommandId_t NONE = 0x0; static const DeviceCommandId_t TC_MEM_WRITE = 0x1; @@ -169,4 +169,4 @@ namespace PLOC { } -#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_PLOCDEFINITIONS_H_ */ +#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_PLOCMPSOCDEFINITIONS_H_ */ diff --git a/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h b/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h new file mode 100644 index 00000000..dd4f875b --- /dev/null +++ b/mission/devices/devicedefinitions/PlocSupervisorDefinitions.h @@ -0,0 +1,397 @@ +#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_PLOCSVPDEFINITIONS_H_ +#define MISSION_DEVICES_DEVICEDEFINITIONS_PLOCSVPDEFINITIONS_H_ + +#include +#include +#include +#include + +namespace PLOC_SPV { + +/** Command IDs */ +static const DeviceCommandId_t NONE = 0; +static const DeviceCommandId_t GET_HK_REPORT = 1; +static const DeviceCommandId_t RESTART_MPSOC = 2; +static const DeviceCommandId_t START_MPSOC = 3; +static const DeviceCommandId_t SHUTDOWN_MPSOC = 4; +static const DeviceCommandId_t SEL_MPSOC_BOOT_IMAGE = 5; +static const DeviceCommandId_t SET_BOOT_TIMEOUT = 6; +static const DeviceCommandId_t SET_MAX_RESTART_TRIES = 7; +static const DeviceCommandId_t RESET_MPSOC = 8; +static const DeviceCommandId_t SET_TIME_REF = 9; +static const DeviceCommandId_t DISABLE_PERIOIC_HK_TRANSMISSION = 10; + +/** Reply IDs */ +static const DeviceCommandId_t ACK_REPORT = 50; +static const DeviceCommandId_t EXE_REPORT = 51; +static const DeviceCommandId_t HK_REPORT = 52; + +static const uint16_t SIZE_ACK_REPORT = 14; +static const uint16_t SIZE_EXE_REPORT = 14; +static const uint16_t SIZE_HK_REPORT = 48; + +/** + * SpacePacket apids of telemetry packets + */ +static const uint16_t APID_ACK_SUCCESS = 0x200; +static const uint16_t APID_ACK_FAILURE = 0x201; +static const uint16_t APID_EXE_SUCCESS = 0x202; +static const uint16_t APID_EXE_FAILURE = 0x203; +static const uint16_t APID_HK_REPORT = 0x204; +static const uint16_t APID_BOOT_STATUS_REPORT = 0x205; +static const uint16_t APID_UPDATE_STATUS_REPORT = 0x206; +static const uint16_t APID_WDG_STATUS_REPORT = 0x207; +static const uint16_t APID_LATCHUP_STATUS_REPORT = 0x208; +static const uint16_t APID_SOC_SYSMON = 0x209; +static const uint16_t APID_MRAM = 0x20A; +static const uint16_t APID_SRAM = 0x20B; +static const uint16_t APID_NOR_DATA = 0x20C; +static const uint16_t APID_DATA_LOGGER_DATA = 0x20D; + +/** + * APIDs of telecommand packets + */ +static const uint16_t APID_RESTART_MPSOC = 0xA0; +static const uint16_t APID_START_MPSOC = 0xA1; +static const uint16_t APID_SHUTWOWN_MPSOC = 0xA2; +static const uint16_t APID_SEL_MPSOC_BOOT_IMAGE = 0xA3; +static const uint16_t APID_SET_BOOT_TIMEOUT = 0xA4; +static const uint16_t APID_SET_MAX_RESTART_TRIES = 0xA5; +static const uint16_t APID_RESET_MPSOC = 0xA6; +static const uint16_t APID_GET_BOOT_STATUS_RPT = 0xA8; +static const uint16_t APID_UPDATE_AVAILABLE = 0xB0; +static const uint16_t APID_UPDATE_IMAGE_DATA = 0xB1; +static const uint16_t APID_UPDATE_VERIFY = 0xB2; +static const uint16_t APID_WTD_ENABLE = 0xC0; +static const uint16_t APID_WTD_CONFIG_TIMEOUT = 0xC1; +static const uint16_t APID_SET_TIME_REF = 0xC2; +static const uint16_t APID_DISABLE_HK = 0xC3; + +static const uint16_t APID_GET_HK_REPORT = 0xC6; + +/** Offset from first byte in Space packet to first byte of data field */ +static const uint8_t DATA_FIELD_OFFSET = 6; + +/** + * Space packet length for fixed size packets. This is the size of the whole packet data + * field. For the length field in the space packet this size will be substracted by one. + */ +static const uint16_t LENGTH_EMPTY_TC = 2; // Only CRC will be transported with the data field + +/** This is the maximum length of a space packet as defined by the TAS ICD */ +static const size_t MAX_REPLY_SIZE = 1024; +static const size_t MAX_COMMAND_SIZE = 1024; + +enum SequenceFlags { + CONTINUED_PKT = 0b00, FIRST_PKT = 0b01, LAST_PKT = 0b10, STANDALONE_PKT = 0b11 +}; + +enum PoolIds + : lp_id_t { + NUM_TMS, + TEMP_PS, + TEMP_PL, + SOC_STATE, + NVM0_1_STATE, + NVM3_STATE, + MISSION_IO_STATE, + FMC_STATE, + NUM_TCS, + TEMP_SUP, + UPTIME, + CPULOAD, + AVAILABLEHEAP +}; + +static const uint8_t HK_SET_ENTRIES = 13; + +static const uint32_t HK_SET_ID = HK_REPORT; + +/** + * @brief With this class a space packet can be created which does not contain any data. + */ +class EmptyPacket: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param apid The APID to set in the space packet. + * + * @note Sequence count of empty packet is always 1. + */ + EmptyPacket(uint16_t apid) : + SpacePacket(LENGTH_EMPTY_TC - 1, true, apid, 1) { + calcCrc(); + } + +private: + + /** + * @brief CRC calculation which involves only the header in an empty packet + */ + void calcCrc() { + + /* Calculate crc */ + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, sizeof(CCSDSPrimaryHeader)); + + /* Add crc to packet data field of space packet */ + size_t serializedSize = 0; + uint8_t* crcPos = this->localData.fields.buffer; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class can be used to generate the space packet selecting the boot image of + * of the MPSoC. + */ +class MPSoCBootSelect: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param mem The memory to boot from: NVM0 (0), NVM1 (1) + * @param bp0 Partition pin 0 + * @param bp1 Partition pin 1 + * @param bp2 Partition pin 2 + */ + MPSoCBootSelect(uint8_t mem, uint8_t bp0, uint8_t bp1, uint8_t bp2) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SEL_MPSOC_BOOT_IMAGE, + DEFAULT_SEQUENCE_COUNT), mem(mem), bp0(bp0), bp1(bp1), bp2(bp2) { + initPacket(); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 6; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + + static const uint8_t MEM_OFFSET = 0; + static const uint8_t BP0_OFFSET = 1; + static const uint8_t BP1_OFFSET = 2; + static const uint8_t BP2_OFFSET = 3; + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + uint8_t mem = 0; + uint8_t bp0 = 0; + uint8_t bp1 = 0; + uint8_t bp2 = 0; + + void initPacket() { + uint8_t* data_field_start = this->localData.fields.buffer; + std::memcpy(data_field_start + MEM_OFFSET, &mem, sizeof(mem)); + std::memcpy(data_field_start + BP0_OFFSET, &bp0, sizeof(bp0)); + std::memcpy(data_field_start + BP1_OFFSET, &bp1, sizeof(bp1)); + std::memcpy(data_field_start + BP2_OFFSET, &bp2, sizeof(bp2)); + /* Calculate crc */ + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + + /* Add crc to packet data field of space packet */ + size_t serializedSize = 0; + uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET; + SerializeAdapter::serialize(&crc, &crcPos, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class generates the space packet to update the time of the PLOC supervisor. + */ +class SetTimeRef: public SpacePacket { +public: + + SetTimeRef(Clock::TimeOfDay_t* time) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_TIME_REF, DEFAULT_SEQUENCE_COUNT) { + initPacket(time); + } + +private: + + static const uint16_t DATA_FIELD_LENGTH = 34; + static const uint16_t DEFAULT_SEQUENCE_COUNT = 1; + static const uint16_t CRC_OFFSET = DATA_FIELD_LENGTH - 2; + + void initPacket(Clock::TimeOfDay_t* time) { + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&time->second, &data_field_ptr, &serializedSize, + sizeof(time->second), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&time->minute, &data_field_ptr, &serializedSize, + sizeof(time->minute), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&time->hour, &data_field_ptr, &serializedSize, + sizeof(time->hour), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&time->day, &data_field_ptr, &serializedSize, + sizeof(time->day), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&time->month, &data_field_ptr, &serializedSize, + sizeof(time->month), SerializeIF::Endianness::BIG); + serializedSize = 0; + SerializeAdapter::serialize(&time->year, &data_field_ptr, &serializedSize, + sizeof(time->year), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint32_t milliseconds = time->usecond / 1000; + SerializeAdapter::serialize(&milliseconds, &data_field_ptr, &serializedSize, + sizeof(milliseconds), SerializeIF::Endianness::BIG); + serializedSize = 0; + uint32_t isSet = 0xFFFFFFFF; + SerializeAdapter::serialize(&isSet, &data_field_ptr, &serializedSize, + sizeof(isSet), SerializeIF::Endianness::BIG); + serializedSize = 0; + /* Calculate crc */ + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + SerializeAdapter::serialize(&crc, &data_field_ptr, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class can be used to generate the set boot timout command. + */ +class SetBootTimeout: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param timeout The boot timeout in milliseconds. + */ + SetBootTimeout(uint32_t timeout) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_BOOT_TIMEOUT, 1), timeout(timeout) { + initPacket(); + } + +private: + + uint32_t timeout = 0; + + /** boot timeout value (uint32_t) and crc (uint16_t) */ + static const uint16_t DATA_FIELD_LENGTH = 6; + + void initPacket() { + + size_t serializedSize = 0; + uint8_t* data_field_ptr = this->localData.fields.buffer; + SerializeAdapter::serialize(&timeout, &data_field_ptr, &serializedSize, + sizeof(timeout), SerializeIF::Endianness::BIG); + /* Calculate crc */ + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + /* Add crc to packet data field of space packet */ + serializedSize = 0; + SerializeAdapter::serialize(&crc, &data_field_ptr, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This class can be used to generate the space packet to set the maximum boot tries. + */ +class SetRestartTries: public SpacePacket { +public: + + /** + * @brief Constructor + * + * @param restartTries Maximum restart tries to set. + */ + SetRestartTries(uint8_t restartTries) : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_SET_MAX_RESTART_TRIES, 1), restartTries( + restartTries) { + initPacket(); + } + +private: + + uint8_t restartTries = 0; + + /** Restart tries value (uint8_t) and crc (uint16_t) */ + static const uint16_t DATA_FIELD_LENGTH = 3; + + void initPacket() { + uint8_t* data_field_ptr = this->localData.fields.buffer; + *data_field_ptr = restartTries; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + size_t serializedSize = 0; + uint8_t* crcPtr = data_field_ptr + 1; + SerializeAdapter::serialize(&crc, &crcPtr, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief With this class the space packet can be generated to disable to periodic transmission + * of housekeeping data. Normally, this will be disabled by default. However, adding this + * command can be useful for debugging. + */ +class DisablePeriodicHkTransmission: public SpacePacket { +public: + + /** + * @brief Constructor + */ + DisablePeriodicHkTransmission() : + SpacePacket(DATA_FIELD_LENGTH - 1, true, APID_DISABLE_HK, 1) { + initPacket(); + } + +private: + + uint8_t disableHk = 0; + + /** Restart tries value (uint8_t) and crc (uint16_t) */ + static const uint16_t DATA_FIELD_LENGTH = 3; + + void initPacket() { + uint8_t* data_field_ptr = this->localData.fields.buffer; + *data_field_ptr = disableHk; + uint16_t crc = CRC::crc16ccitt(this->localData.byteStream, + sizeof(CCSDSPrimaryHeader) + DATA_FIELD_LENGTH - 2); + size_t serializedSize = 0; + uint8_t* crcPtr = data_field_ptr + 1; + SerializeAdapter::serialize(&crc, &crcPtr, &serializedSize, sizeof(crc), + SerializeIF::Endianness::BIG); + } +}; + +/** + * @brief This dataset to store the housekeeping data of the supervisor. + */ +class HkSet: public StaticLocalDataSet { +public: + + HkSet(HasLocalDataPoolIF* owner) : + StaticLocalDataSet(owner, HK_SET_ID) { + } + + HkSet(object_id_t objectId) : + StaticLocalDataSet(sid_t(objectId, HK_SET_ID)) { + } + + lp_var_t numTms = lp_var_t(sid.objectId, PoolIds::NUM_TMS, this); + lp_var_t tempPs = lp_var_t(sid.objectId, PoolIds::TEMP_PS, this); + lp_var_t tempPl = lp_var_t(sid.objectId, PoolIds::TEMP_PS, this); + lp_var_t socState = lp_var_t(sid.objectId, PoolIds::SOC_STATE, this); + lp_var_t nvm0_1_state = lp_var_t(sid.objectId, PoolIds::NVM0_1_STATE, this); + lp_var_t nvm3_state = lp_var_t(sid.objectId, PoolIds::NVM3_STATE, this); + lp_var_t missionIoState = lp_var_t(sid.objectId, PoolIds::MISSION_IO_STATE, + this); + lp_var_t fmcState = lp_var_t(sid.objectId, PoolIds::FMC_STATE, this); + lp_var_t numTcs = lp_var_t(sid.objectId, PoolIds::NUM_TCS, this); + lp_var_t tempSup = lp_var_t(sid.objectId, PoolIds::TEMP_SUP, this); + lp_var_t uptime = lp_var_t(sid.objectId, PoolIds::UPTIME, this); + lp_var_t cpuLoad = lp_var_t(sid.objectId, PoolIds::CPULOAD, this); + lp_var_t availableHeap = lp_var_t(sid.objectId, PoolIds::AVAILABLEHEAP, + this); +}; +} + +#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_PLOCSVPDEFINITIONS_H_ */ diff --git a/mission/devices/devicedefinitions/RadSensorDefinitions.h b/mission/devices/devicedefinitions/RadSensorDefinitions.h index 7d434d04..d3c8e876 100644 --- a/mission/devices/devicedefinitions/RadSensorDefinitions.h +++ b/mission/devices/devicedefinitions/RadSensorDefinitions.h @@ -30,10 +30,11 @@ namespace RAD_SENSOR { * conversions to perform. * @details Bit0: 1 - Enables temperature conversion * Bit2 (SCAN1) and Bit1 (SCAN0): 0b00 (channel conversion from 0 to N) - * Bit6 - Bit3 defines N: 0b0001 (N = 1) + * Bit6 - Bit3 defines N: 0b0111 (N = 7) * Bit7: Always 1. Tells the ADC that this is the conversion register. */ - static const uint8_t CONVERSION_DEFINITION = 0b10001001; + static const uint8_t CONVERSION_DEFINITION = 0b10111001; +// static const uint8_t CONVERSION_DEFINITION = 0b10111111; /** * @brief Writing this value resets the fifo of the MAX1227. @@ -44,18 +45,23 @@ namespace RAD_SENSOR { static const uint8_t RAD_SENSOR_DATA_SET_ID = READ_CONVERSIONS; + static const uint8_t DATASET_ENTRIES = 7; /** - * One temperature value, conversion of channel 0 and conversion of channel 1 + * One temperature value and conversions for AIN0 - AIN7 */ - static const uint8_t READ_SIZE = 6; + static const uint8_t READ_SIZE = 18; enum Max1227PoolIds: lp_id_t { TEMPERATURE_C, - CHANNEL_0, - CHANNEL_1, + AIN0, + AIN1, + AIN4, + AIN5, + AIN6, + AIN7, }; -class RadSensorDataset: public StaticLocalDataSet { +class RadSensorDataset: public StaticLocalDataSet { public: RadSensorDataset(HasLocalDataPoolIF* owner) : @@ -67,8 +73,12 @@ public: } lp_var_t temperatureCelcius = lp_var_t(sid.objectId, TEMPERATURE_C, this); - lp_var_t channel0 = lp_var_t(sid.objectId, CHANNEL_0, this); - lp_var_t channel1 = lp_var_t(sid.objectId, CHANNEL_1, this); + lp_var_t ain0 = lp_var_t(sid.objectId, AIN0, this); + lp_var_t ain1 = lp_var_t(sid.objectId, AIN1, this); + lp_var_t ain4 = lp_var_t(sid.objectId, AIN4, this); + lp_var_t ain5 = lp_var_t(sid.objectId, AIN5, this); + lp_var_t ain6 = lp_var_t(sid.objectId, AIN6, this); + lp_var_t ain7 = lp_var_t(sid.objectId, AIN7, this); }; } diff --git a/mission/devices/devicedefinitions/RwDefinitions.h b/mission/devices/devicedefinitions/RwDefinitions.h index d87c09fd..4b3eeee7 100644 --- a/mission/devices/devicedefinitions/RwDefinitions.h +++ b/mission/devices/devicedefinitions/RwDefinitions.h @@ -20,6 +20,8 @@ enum PoolIds: lp_id_t { CURRRENT_RESET_STATUS, TM_LAST_RESET_STATUS, TM_MCU_TEMPERATURE, + PRESSURE_SENSOR_TEMPERATURE, + PRESSURE, TM_RW_STATE, TM_CLC_MODE, TM_RW_CURR_SPEED, @@ -83,7 +85,7 @@ static const size_t SIZE_GET_RW_STATUS = 14; static const size_t SIZE_SET_SPEED_REPLY = 4; static const size_t SIZE_GET_TEMPERATURE_REPLY = 8; /** Max size when requesting telemetry */ -static const size_t SIZE_GET_TELEMETRY_REPLY = 83; +static const size_t SIZE_GET_TELEMETRY_REPLY = 91; /** Set speed command has maximum size */ static const size_t MAX_CMD_SIZE = 9; @@ -96,7 +98,7 @@ static const size_t MAX_REPLY_SIZE = 2 * SIZE_GET_TELEMETRY_REPLY; static const uint8_t LAST_RESET_ENTRIES = 2; static const uint8_t TEMPERATURE_SET_ENTRIES = 1; static const uint8_t STATUS_SET_ENTRIES = 4; -static const uint8_t TM_SET_ENTRIES = 22; +static const uint8_t TM_SET_ENTRIES = 24; /** * @brief This dataset can be used to store the temperature of a reaction wheel. @@ -184,6 +186,10 @@ public: PoolIds::TM_LAST_RESET_STATUS, this); lp_var_t mcuTemperature = lp_var_t(sid.objectId, PoolIds::TM_MCU_TEMPERATURE, this); + lp_var_t pressureSensorTemperature = lp_var_t(sid.objectId, + PoolIds::PRESSURE_SENSOR_TEMPERATURE, this); + lp_var_t pressure = lp_var_t(sid.objectId, + PoolIds::PRESSURE, this); lp_var_t rwState = lp_var_t(sid.objectId, PoolIds::TM_RW_STATE, this); lp_var_t rwClcMode = lp_var_t(sid.objectId, diff --git a/mission/devices/devicedefinitions/StarTrackerDefinitions.h b/mission/devices/devicedefinitions/StarTrackerDefinitions.h new file mode 100644 index 00000000..6c28219b --- /dev/null +++ b/mission/devices/devicedefinitions/StarTrackerDefinitions.h @@ -0,0 +1,64 @@ +#ifndef MISSION_STARTRACKER_DEFINITIONS_H_ +#define MISSION_STARTRACKER_DEFINITIONS_H_ + +#include +#include +#include +#include "objects/systemObjectList.h" + +namespace StarTracker { + +/** This is the address of the star tracker */ +static const uint8_t ADDRESS = 33; + +enum PoolIds: lp_id_t { + STATUS, + TICKS, + TIME, + MCU_TEMPERATURE, + CMOS_TEMPERATURE +}; + + + +static const DeviceCommandId_t REQ_TEMPERATURE = 25; + +static const uint32_t TEMPERATURE_SET_ID = REQ_TEMPERATURE; + +/** Max size of unencoded frame */ +static const size_t MAX_FRAME_SIZE = 1200; + +static const uint8_t TEMPERATURE_SET_ENTRIES = 5; + +/** + * @brief This dataset can be used to store the temperature of a reaction wheel. + */ +class TemperatureSet: + public StaticLocalDataSet { +public: + + TemperatureSet(HasLocalDataPoolIF* owner): + StaticLocalDataSet(owner, TEMPERATURE_SET_ID) { + } + + TemperatureSet(object_id_t objectId): + StaticLocalDataSet(sid_t(objectId, TEMPERATURE_SET_ID)) { + } + + lp_var_t status = lp_var_t(sid.objectId, + PoolIds::STATUS, this); + lp_var_t ticks = lp_var_t(sid.objectId, + PoolIds::TICKS, this); + /** Unix time in microseconds */ + lp_var_t time = lp_var_t(sid.objectId, + PoolIds::TIME, this); + lp_var_t mcuTemperature = lp_var_t(sid.objectId, + PoolIds::MCU_TEMPERATURE, this); + lp_var_t cmosTemperature = lp_var_t(sid.objectId, + PoolIds::CMOS_TEMPERATURE, this); +}; + +} + +#endif /* MISSION_STARTRACKER_DEFINITIONS_H_ */ + diff --git a/mission/memory/CMakeLists.txt b/mission/memory/CMakeLists.txt new file mode 100644 index 00000000..ccaef754 --- /dev/null +++ b/mission/memory/CMakeLists.txt @@ -0,0 +1,5 @@ +target_sources(${TARGET_NAME} PUBLIC + NVMParameterBase.cpp +) + + diff --git a/mission/memory/NVMParameterBase.cpp b/mission/memory/NVMParameterBase.cpp new file mode 100644 index 00000000..e7b8e8a6 --- /dev/null +++ b/mission/memory/NVMParameterBase.cpp @@ -0,0 +1,50 @@ +#include "NVMParameterBase.h" +#include "fsfw/memory/HasFileSystemIF.h" +#include "fsfw/serviceinterface/ServiceInterface.h" + +#include + +NVMParameterBase::NVMParameterBase(std::string fullName): fullName(fullName) { +} + +ReturnValue_t NVMParameterBase::readJsonFile() { + if(std::filesystem::exists(fullName)) { + // Read JSON file content into object + std::ifstream i(fullName); + i >> json; + return HasReturnvaluesIF::RETURN_OK; + } + return HasFileSystemIF::FILE_DOES_NOT_EXIST; +} + +ReturnValue_t NVMParameterBase::writeJsonFile() { + std::ofstream o(fullName); + o << std::setw(4) << json; + return HasReturnvaluesIF::RETURN_OK; +} + +void NVMParameterBase::setFullName(std::string fullName) { + this->fullName = fullName; +} + +std::string NVMParameterBase::getFullName() const { + return fullName; +} + +bool NVMParameterBase::getJsonFileExists() { + return std::filesystem::exists(fullName); +} + +void NVMParameterBase::printKeys() const { + sif::info << "Printing keys for JSON file " << fullName << std::endl; + for(const auto& key: keys) { + sif::info << key << std::endl; + } +} + +void NVMParameterBase::print() const { + sif::info << "Printing JSON file " << fullName << std::endl; + for(const auto& key: keys) { + sif::info << key << ": " << json[key] << std::endl; + } +} diff --git a/mission/memory/NVMParameterBase.h b/mission/memory/NVMParameterBase.h new file mode 100644 index 00000000..4814acf4 --- /dev/null +++ b/mission/memory/NVMParameterBase.h @@ -0,0 +1,69 @@ +#ifndef BSP_Q7S_CORE_NVMPARAMS_NVMPARAMIF_H_ +#define BSP_Q7S_CORE_NVMPARAMS_NVMPARAMIF_H_ + +#include "fsfw/returnvalues/HasReturnvaluesIF.h" + +#include +#include +#include + +class NVMParameterBase { +public: + virtual~ NVMParameterBase() {} + + NVMParameterBase(std::string fullName); + + bool getJsonFileExists(); + + /** + * Returns RETURN_OK on successfull read and HasFileSystemIF::FILE_DOES_NOT_EXIST if + * file does not exist yet. + * @return + */ + virtual ReturnValue_t readJsonFile(); + + virtual ReturnValue_t writeJsonFile(); + + void setFullName(std::string fullName); + std::string getFullName() const; + + template + ReturnValue_t insertValue(std::string key, T value); + + template + ReturnValue_t setValue(std::string key, T value); + + template + T getValue(std::string key) const; + + void printKeys() const; + void print() const; + +private: + nlohmann::json json; + std::vector keys; + std::string fullName; +}; + +template +inline ReturnValue_t NVMParameterBase::insertValue(std::string key, T value) { + // Check whether key already exists. If it does not, insert it + if (std::find(keys.begin(), keys.end(), key) == keys.end()) { + keys.push_back(key); + } + json[key] = value; + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline ReturnValue_t NVMParameterBase::setValue(std::string key, T value) { + json[key] = value; + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline T NVMParameterBase::getValue(std::string key) const { + return json[key]; +} + +#endif /* BSP_Q7S_CORE_NVMPARAMS_NVMPARAMIF_H_ */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000..06c053c8 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(testtasks) diff --git a/test/DummyParameter.h b/test/DummyParameter.h new file mode 100644 index 00000000..b8da7275 --- /dev/null +++ b/test/DummyParameter.h @@ -0,0 +1,26 @@ +#ifndef BSP_Q7S_CORE_NVMPARAMS_PARAMETERDEFINITIONS_H_ +#define BSP_Q7S_CORE_NVMPARAMS_PARAMETERDEFINITIONS_H_ + +#include "mission/memory/NVMParameterBase.h" +#include + +#include + +class DummyParameter: public NVMParameterBase { +public: + static constexpr char DUMMY_KEY_PARAM_1[] = "dummy1"; + static constexpr char DUMMY_KEY_PARAM_2[] = "dummy2"; + + DummyParameter(std::string mountPrefix, std::string jsonFileName): + NVMParameterBase(mountPrefix + "/conf/" + jsonFileName), + mountPrefix(mountPrefix) { + insertValue(DUMMY_KEY_PARAM_1, 1); + insertValue(DUMMY_KEY_PARAM_2, "blablub"); + } + +private: + std::string mountPrefix; +}; + + +#endif /* BSP_Q7S_CORE_NVMPARAMS_PARAMETERDEFINITIONS_H_ */ diff --git a/thirdparty/arcsec_star_tracker b/thirdparty/arcsec_star_tracker new file mode 160000 index 00000000..f596c533 --- /dev/null +++ b/thirdparty/arcsec_star_tracker @@ -0,0 +1 @@ +Subproject commit f596c53315f1f81facb28faec3150612a5ad2ca0 diff --git a/thirdparty/json b/thirdparty/json new file mode 160000 index 00000000..fb1ee4f9 --- /dev/null +++ b/thirdparty/json @@ -0,0 +1 @@ +Subproject commit fb1ee4f94b426a398969b2c96df9784be8e007e6