diff --git a/.gitmodules b/.gitmodules index b555af94..b0016647 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,12 +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 5b1b94f8..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,11 +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) @@ -67,6 +67,7 @@ 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) @@ -77,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) @@ -142,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}) @@ -150,7 +155,6 @@ 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() @@ -159,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. @@ -167,7 +171,6 @@ if(NOT Q7S_SIMPLE_MODE) ${LIB_FSFW_NAME} ${LIB_OS_NAME} ${LIB_LWGPS_NAME} - ${LIB_FSFW_HAL_NAME} ${LIB_ARCSEC} ${LIB_CXX_FS} ) @@ -185,6 +188,12 @@ 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} @@ -248,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 68a5df30..b3875876 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,20 @@ 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 +``` + ## pa3tool Host Tool The `pa3tool` is a host tool to interface with the ProASIC3 on the Q7S board. It was @@ -612,6 +627,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 +744,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 +759,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..2f48fe2d 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1,6 +1,9 @@ #include "CoreController.h" #include "q7sConfig.h" +#include "fsfw/serviceinterface/ServiceInterface.h" + +#include "../memory/scratchApi.h" #include "../memory/SdCardManager.h" CoreController::CoreController(object_id_t objectId): @@ -24,7 +27,16 @@ LocalPoolDataSetBase* CoreController::getDataSetHandle(sid_t sid) { } ReturnValue_t CoreController::initialize() { - return sdCardInit(); + ReturnValue_t result = sdCardInit(); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "CoreController::initialize: SD card init failed" << 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 +50,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 +60,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 +81,161 @@ 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 { + sif::info << "SD card " << sdString << " already on and mounted at " << + mountString << std::endl; + return SdCardManager::ALREADY_MOUNTED; + } +} + +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 7389d5ff..8bb36ff6 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,65 +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 "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 -#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 +#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; @@ -87,24 +93,80 @@ 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); + + 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); + + 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, @@ -125,8 +187,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, @@ -159,10 +240,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); @@ -173,7 +253,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, @@ -258,21 +340,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"), @@ -330,20 +426,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; @@ -384,7 +483,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, @@ -398,14 +499,19 @@ 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(); new SyrlinksHkHandler(objects::SYRLINKS_HK_HANDLER, objects::UART_COM_IF, syrlinksUartCookie); + SyrlinksHkHandler* syrlinksHkHandler = 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, @@ -508,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; @@ -541,19 +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); - -#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 - +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); @@ -568,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, @@ -605,51 +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); +} -#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 - -#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); @@ -658,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); @@ -672,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); @@ -686,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); @@ -702,7 +790,7 @@ 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_MPSOC::MAX_REPLY_SIZE); /* Testing PlocMPSoCHandler on TE0720-03-1CFA */ @@ -711,7 +799,7 @@ void ObjectFactory::produce(void* args){ 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; 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 a6bdb61b..b6e90d4d 100644 --- a/bsp_q7s/core/obsw.cpp +++ b/bsp_q7s/core/obsw.cpp @@ -7,7 +7,7 @@ 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..d24f540d 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) { @@ -226,26 +232,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 +334,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/commonObjects.h b/common/config/commonObjects.h index 458b9a5f..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, diff --git a/common/config/commonSubsystemIds.h b/common/config/commonSubsystemIds.h index a86cb5a0..7c2cb605 100644 --- a/common/config/commonSubsystemIds.h +++ b/common/config/commonSubsystemIds.h @@ -16,6 +16,7 @@ enum: uint8_t { 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/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/OBSWConfig.h.in b/linux/fsfwconfig/OBSWConfig.h.in index 294f1d91..83af12b1 100644 --- a/linux/fsfwconfig/OBSWConfig.h.in +++ b/linux/fsfwconfig/OBSWConfig.h.in @@ -32,7 +32,7 @@ debugging. */ #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 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/pollingsequence/pollingSequenceFactory.cpp b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp index 3c5f570c..a24c5393 100644 --- a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp +++ b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp @@ -475,8 +475,10 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { 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); @@ -486,6 +488,7 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { 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); @@ -493,8 +496,10 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { DeviceHandlerIF::SEND_WRITE); #endif +#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); @@ -502,8 +507,10 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { DeviceHandlerIF::GET_WRITE); #endif +#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); @@ -511,8 +518,10 @@ ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { DeviceHandlerIF::SEND_READ); #endif +#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); @@ -694,7 +703,7 @@ ReturnValue_t pst::pstTest(FixedTimeslotTaskIF* thisSequence) { return HasReturnvaluesIF::RETURN_OK; } -#if TE0720 == 1 +#if BOARD_TE7020 == 1 ReturnValue_t pst::pollingSequenceTE0720(FixedTimeslotTaskIF *thisSequence) { uint32_t length = thisSequence->getPeriodMs(); @@ -751,4 +760,4 @@ ReturnValue_t pst::pollingSequenceTE0720(FixedTimeslotTaskIF *thisSequence) { } return HasReturnvaluesIF::RETURN_OK; } -#endif /* TE7020 == 1 */ +#endif /* BOARD_TE7020 == 1 */ 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/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/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/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/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_ */