scex code #303
@ -27,6 +27,8 @@ list yields a list of all related PRs for each release.
|
|||||||
- Increase number of allowed consescutive action commands from 3 to 16
|
- Increase number of allowed consescutive action commands from 3 to 16
|
||||||
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/294
|
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/294
|
||||||
- Fix for EM SW: Always create ACS Task
|
- Fix for EM SW: Always create ACS Task
|
||||||
|
- Added Scex device handler and Scex uart reader
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/303
|
||||||
|
|
||||||
# [v1.13.0] 24.08.2022
|
# [v1.13.0] 24.08.2022
|
||||||
|
|
||||||
|
@ -125,6 +125,9 @@ set(OBSW_ADD_GOMSPACE_PCDU
|
|||||||
set(OBSW_ADD_RW
|
set(OBSW_ADD_RW
|
||||||
${INIT_VAL}
|
${INIT_VAL}
|
||||||
CACHE STRING "Add RW modules")
|
CACHE STRING "Add RW modules")
|
||||||
|
set(OBSW_ADD_SCEX_DEVICE
|
||||||
|
${INIT_VAL}
|
||||||
|
CACHE STRING "Add Solar Cell Experiment module")
|
||||||
|
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
# Pre-Sources preparation
|
# Pre-Sources preparation
|
||||||
@ -389,10 +392,8 @@ add_subdirectory(${TEST_PATH})
|
|||||||
add_subdirectory(${UNITTEST_PATH})
|
add_subdirectory(${UNITTEST_PATH})
|
||||||
|
|
||||||
# This should have already been downloaded by the FSFW Still include it to be
|
# This should have already been downloaded by the FSFW Still include it to be
|
||||||
# safe
|
# safe find_package(etl ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET) Not
|
||||||
find_package(etl ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET)
|
# installed, so use FetchContent to download and provide etl if(NOT etl_FOUND)
|
||||||
# Not installed, so use FetchContent to download and provide etl
|
|
||||||
if(NOT etl_FOUND)
|
|
||||||
message(
|
message(
|
||||||
STATUS
|
STATUS
|
||||||
"No ETL installation was found with find_package. Installing and providing "
|
"No ETL installation was found with find_package. Installing and providing "
|
||||||
@ -403,7 +404,7 @@ if(NOT etl_FOUND)
|
|||||||
GIT_REPOSITORY https://github.com/ETLCPP/etl
|
GIT_REPOSITORY https://github.com/ETLCPP/etl
|
||||||
GIT_TAG ${FSFW_ETL_LIB_VERSION})
|
GIT_TAG ${FSFW_ETL_LIB_VERSION})
|
||||||
list(APPEND FSFW_FETCH_CONTENT_TARGETS etl)
|
list(APPEND FSFW_FETCH_CONTENT_TARGETS etl)
|
||||||
endif()
|
# endif()
|
||||||
|
|
||||||
# Use same Catch2 version as framework
|
# Use same Catch2 version as framework
|
||||||
if(NOT (TGT_BSP MATCHES "arm/te0720-1cfa")
|
if(NOT (TGT_BSP MATCHES "arm/te0720-1cfa")
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
target_sources(${OBSW_NAME} PUBLIC InitMission.cpp main.cpp gpioInit.cpp
|
target_sources(${OBSW_NAME} PUBLIC InitMission.cpp main.cpp gpioInit.cpp
|
||||||
ObjectFactory.cpp)
|
ObjectFactory.cpp RPiSdCardManager.cpp)
|
||||||
|
|
||||||
add_subdirectory(boardconfig)
|
add_subdirectory(boardconfig)
|
||||||
add_subdirectory(boardtest)
|
add_subdirectory(boardtest)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "InitMission.h"
|
#include "InitMission.h"
|
||||||
|
|
||||||
|
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||||
#include <fsfw/objectmanager/ObjectManager.h>
|
#include <fsfw/objectmanager/ObjectManager.h>
|
||||||
#include <fsfw/objectmanager/ObjectManagerIF.h>
|
#include <fsfw/objectmanager/ObjectManagerIF.h>
|
||||||
#include <fsfw/returnvalues/returnvalue.h>
|
#include <fsfw/returnvalues/returnvalue.h>
|
||||||
@ -7,6 +8,7 @@
|
|||||||
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
|
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
|
||||||
#include <fsfw/tasks/PeriodicTaskIF.h>
|
#include <fsfw/tasks/PeriodicTaskIF.h>
|
||||||
#include <fsfw/tasks/TaskFactory.h>
|
#include <fsfw/tasks/TaskFactory.h>
|
||||||
|
#include <linux/InitMission.h>
|
||||||
#include <mission/utility/InitMission.h>
|
#include <mission/utility/InitMission.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -77,6 +79,12 @@ void initmission::initTasks() {
|
|||||||
sif::error << "Add component TMTC Polling failed" << std::endl;
|
sif::error << "Add component TMTC Polling failed" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OBSW_ADD_SCEX_DEVICE == 1
|
||||||
|
PeriodicTaskIF* scexDevHandler;
|
||||||
|
PeriodicTaskIF* scexReaderTask;
|
||||||
|
scheduling::schedulingScex(*factory, scexDevHandler, scexReaderTask);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* PUS Services */
|
/* PUS Services */
|
||||||
std::vector<PeriodicTaskIF*> pusTasks;
|
std::vector<PeriodicTaskIF*> pusTasks;
|
||||||
createPusTasks(*factory, missedDeadlineFunc, pusTasks);
|
createPusTasks(*factory, missedDeadlineFunc, pusTasks);
|
||||||
@ -109,6 +117,10 @@ void initmission::initTasks() {
|
|||||||
#endif /* OBSW_ADD_TEST_CODE == 1 */
|
#endif /* OBSW_ADD_TEST_CODE == 1 */
|
||||||
taskStarter(pstTasks, "PST Tasks");
|
taskStarter(pstTasks, "PST Tasks");
|
||||||
|
|
||||||
|
#if OBSW_ADD_SCEX_DEVICE == 1
|
||||||
|
scexDevHandler->startTask();
|
||||||
|
scexReaderTask->startTask();
|
||||||
|
#endif
|
||||||
#if OBSW_ADD_TEST_PST == 1
|
#if OBSW_ADD_TEST_PST == 1
|
||||||
if (startTestPst) {
|
if (startTestPst) {
|
||||||
pstTestTask->startTask();
|
pstTestTask->startTask();
|
||||||
@ -195,9 +207,12 @@ void initmission::createPstTasks(TaskFactory& factory,
|
|||||||
"SPI_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 1.0, missedDeadlineFunc);
|
"SPI_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 1.0, missedDeadlineFunc);
|
||||||
result = pst::pstSpi(spiPst);
|
result = pst::pstSpi(spiPst);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
sif::error << "InitMission::initTasks: Creating PST failed!" << std::endl;
|
if (result != FixedTimeslotTaskIF::SLOT_LIST_EMPTY) {
|
||||||
|
sif::error << "InitMission::createPstTasks: Creating PST failed!" << std::endl;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
taskVec.push_back(spiPst);
|
taskVec.push_back(spiPst);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,6 +243,13 @@ void initmission::createTestTasks(TaskFactory& factory,
|
|||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
initmission::printAddObjectError("UART_TEST", objects::UART_TEST);
|
initmission::printAddObjectError("UART_TEST", objects::UART_TEST);
|
||||||
}
|
}
|
||||||
|
PeriodicTaskIF* scexReaderTask = factory.createPeriodicTask(
|
||||||
|
"SCEX_UART_READER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
|
||||||
|
result = scexReaderTask->addComponent(objects::SCEX_UART_READER);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
initmission::printAddObjectError("SCEX_UART_READER", objects::SCEX_UART_READER);
|
||||||
|
}
|
||||||
|
taskVec.push_back(scexReaderTask);
|
||||||
#endif /* RPI_ADD_GPIO_TEST == 1 */
|
#endif /* RPI_ADD_GPIO_TEST == 1 */
|
||||||
taskVec.push_back(testTask);
|
taskVec.push_back(testTask);
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#define OBSW_ADD_RTD_DEVICES 0
|
#define OBSW_ADD_RTD_DEVICES 0
|
||||||
#define OBSW_ADD_PL_PCDU 0
|
#define OBSW_ADD_PL_PCDU 0
|
||||||
#define OBSW_ADD_TMP_DEVICES 0
|
#define OBSW_ADD_TMP_DEVICES 0
|
||||||
|
#define OBSW_ADD_SCEX_DEVICE 1
|
||||||
#define OBSW_ADD_RAD_SENSORS 0
|
#define OBSW_ADD_RAD_SENSORS 0
|
||||||
#define OBSW_ADD_SYRLINKS 0
|
#define OBSW_ADD_SYRLINKS 0
|
||||||
#define OBSW_STAR_TRACKER_GROUND_CONFIG 1
|
#define OBSW_STAR_TRACKER_GROUND_CONFIG 1
|
||||||
@ -102,6 +103,12 @@
|
|||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
#cmakedefine EIVE_BUILD_GPSD_GPS_HANDLER
|
#cmakedefine EIVE_BUILD_GPSD_GPS_HANDLER
|
||||||
|
|
||||||
|
#define OBSW_USE_CCSDS_IP_CORE 0
|
||||||
|
// Set to 1 if all telemetry should be sent to the PTME IP Core
|
||||||
|
#define OBSW_TM_TO_PTME 0
|
||||||
|
// Set to 1 if telecommands are received via the PDEC IP Core
|
||||||
|
#define OBSW_TC_FROM_PDEC 0
|
||||||
|
|
||||||
#cmakedefine LIBGPS_VERSION_MAJOR @LIBGPS_VERSION_MAJOR@
|
#cmakedefine LIBGPS_VERSION_MAJOR @LIBGPS_VERSION_MAJOR@
|
||||||
#cmakedefine LIBGPS_VERSION_MINOR @LIBGPS_VERSION_MINOR@
|
#cmakedefine LIBGPS_VERSION_MINOR @LIBGPS_VERSION_MINOR@
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#include "ObjectFactory.h"
|
#include "ObjectFactory.h"
|
||||||
|
|
||||||
|
#include <bsp_linux_board/RPiSdCardManager.h>
|
||||||
|
#include <linux/devices/ScexUartReader.h>
|
||||||
|
|
||||||
#include "OBSWConfig.h"
|
#include "OBSWConfig.h"
|
||||||
#include "devConf.h"
|
#include "devConf.h"
|
||||||
#include "devices/addresses.h"
|
#include "devices/addresses.h"
|
||||||
@ -18,9 +21,8 @@
|
|||||||
#include "mission/core/GenericFactory.h"
|
#include "mission/core/GenericFactory.h"
|
||||||
#include "mission/devices/GPSHyperionHandler.h"
|
#include "mission/devices/GPSHyperionHandler.h"
|
||||||
#include "mission/devices/GyroADIS1650XHandler.h"
|
#include "mission/devices/GyroADIS1650XHandler.h"
|
||||||
#include "mission/utility/TmFunnel.h"
|
#include "mission/tmtc/TmFunnel.h"
|
||||||
#include "objects/systemObjectList.h"
|
#include "objects/systemObjectList.h"
|
||||||
#include "tmtc/apid.h"
|
|
||||||
#include "tmtc/pusIds.h"
|
#include "tmtc/pusIds.h"
|
||||||
|
|
||||||
/* UDP server includes */
|
/* UDP server includes */
|
||||||
@ -45,8 +47,8 @@
|
|||||||
#include "fsfw_hal/linux/spi/SpiCookie.h"
|
#include "fsfw_hal/linux/spi/SpiCookie.h"
|
||||||
|
|
||||||
void Factory::setStaticFrameworkObjectIds() {
|
void Factory::setStaticFrameworkObjectIds() {
|
||||||
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
|
PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_PACKET_DISTRIBUTOR;
|
||||||
PusServiceBase::packetDestination = objects::TM_FUNNEL;
|
PusServiceBase::PACKET_DESTINATION = objects::TM_FUNNEL;
|
||||||
|
|
||||||
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
|
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
|
||||||
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
|
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
|
||||||
@ -54,9 +56,6 @@ void Factory::setStaticFrameworkObjectIds() {
|
|||||||
TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
|
TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
|
||||||
// No storage object for now.
|
// No storage object for now.
|
||||||
TmFunnel::storageDestination = objects::NO_OBJECT;
|
TmFunnel::storageDestination = objects::NO_OBJECT;
|
||||||
|
|
||||||
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
|
|
||||||
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectFactory::produce(void* args) {
|
void ObjectFactory::produce(void* args) {
|
||||||
@ -76,12 +75,17 @@ void ObjectFactory::produce(void* args) {
|
|||||||
createRpiAcsBoard(gpioIF, spiDev);
|
createRpiAcsBoard(gpioIF, spiDev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OBSW_ADD_SUN_SENSORS == 1 || defined(OBSW_ADD_RTD_DEVICES)
|
#if OBSW_ADD_SUN_SENSORS == 1 || OBSW_ADD_RTD_DEVICES == 1
|
||||||
#ifdef RASPBERRY_PI
|
#ifdef RASPBERRY_PI
|
||||||
rpi::gpio::initSpiCsDecoder(gpioIF);
|
rpi::gpio::initSpiCsDecoder(gpioIF);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if OBSW_ADD_SCEX_DEVICE == 1
|
||||||
|
auto* sdcMan = new RPiSdCardManager("/tmp");
|
||||||
|
createScexComponents(uart::DEV, pwrSwitcher, *sdcMan, true, std::nullopt);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if OBSW_ADD_SUN_SENSORS == 1
|
#if OBSW_ADD_SUN_SENSORS == 1
|
||||||
createSunSensorComponents(gpioIF, spiComIF, pwrSwitcher, spi::DEV);
|
createSunSensorComponents(gpioIF, spiComIF, pwrSwitcher, spi::DEV);
|
||||||
#endif
|
#endif
|
||||||
|
13
bsp_linux_board/RPiSdCardManager.cpp
Normal file
13
bsp_linux_board/RPiSdCardManager.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "RPiSdCardManager.h"
|
||||||
|
|
||||||
|
RPiSdCardManager::RPiSdCardManager(std::string prefix) : prefix(std::move(prefix)) {}
|
||||||
|
|
||||||
|
const std::string& RPiSdCardManager::getCurrentMountPrefix() const { return prefix; }
|
||||||
|
|
||||||
|
bool RPiSdCardManager::isSdCardUsable(sd::SdCard sdCard) { return true; }
|
||||||
|
|
||||||
|
std::optional<sd::SdCard> RPiSdCardManager::getPreferredSdCard() const { return std::nullopt; }
|
||||||
|
|
||||||
|
void RPiSdCardManager::setActiveSdCard(sd::SdCard sdCard) {}
|
||||||
|
|
||||||
|
std::optional<sd::SdCard> RPiSdCardManager::getActiveSdCard() const { return std::nullopt; }
|
18
bsp_linux_board/RPiSdCardManager.h
Normal file
18
bsp_linux_board/RPiSdCardManager.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef BSP_LINUX_BOARD_RPISDCARDMANAGER_H_
|
||||||
|
#define BSP_LINUX_BOARD_RPISDCARDMANAGER_H_
|
||||||
|
#include <mission/memory/SdCardMountedIF.h>
|
||||||
|
|
||||||
|
class RPiSdCardManager : public SdCardMountedIF {
|
||||||
|
public:
|
||||||
|
RPiSdCardManager(std::string prefix);
|
||||||
|
const std::string& getCurrentMountPrefix() const override;
|
||||||
|
bool isSdCardUsable(sd::SdCard sdCard) override;
|
||||||
|
std::optional<sd::SdCard> getPreferredSdCard() const override;
|
||||||
|
void setActiveSdCard(sd::SdCard sdCard) override;
|
||||||
|
std::optional<sd::SdCard> getActiveSdCard() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string prefix;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* BSP_LINUX_BOARD_RPISDCARDMANAGER_H_ */
|
@ -13,6 +13,12 @@ static constexpr char DEV[] = "/dev/spidev0.1";
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace uart {
|
||||||
|
|
||||||
|
static constexpr char DEV[] = "/dev/serial0";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Adapt these values accordingly */
|
/* Adapt these values accordingly */
|
||||||
namespace gpio {
|
namespace gpio {
|
||||||
static constexpr uint8_t MGM_0_BCM_PIN = 17;
|
static constexpr uint8_t MGM_0_BCM_PIN = 17;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#define OBSW_ADD_TCS_CTRL @OBSW_ADD_TCS_CTRL@
|
#define OBSW_ADD_TCS_CTRL @OBSW_ADD_TCS_CTRL@
|
||||||
#define OBSW_ADD_RW @OBSW_ADD_RW@
|
#define OBSW_ADD_RW @OBSW_ADD_RW@
|
||||||
#define OBSW_ADD_RTD_DEVICES @OBSW_ADD_RTD_DEVICES@
|
#define OBSW_ADD_RTD_DEVICES @OBSW_ADD_RTD_DEVICES@
|
||||||
|
#define OBSW_ADD_SCEX_DEVICE @OBSW_ADD_SCEX_DEVICE@
|
||||||
#define OBSW_ADD_TMP_DEVICES @OBSW_ADD_TMP_DEVICES@
|
#define OBSW_ADD_TMP_DEVICES @OBSW_ADD_TMP_DEVICES@
|
||||||
#define OBSW_ADD_RAD_SENSORS @OBSW_ADD_RAD_SENSORS@
|
#define OBSW_ADD_RAD_SENSORS @OBSW_ADD_RAD_SENSORS@
|
||||||
#define OBSW_ADD_PL_PCDU @OBSW_ADD_PL_PCDU@
|
#define OBSW_ADD_PL_PCDU @OBSW_ADD_PL_PCDU@
|
||||||
|
@ -15,6 +15,7 @@ static constexpr char UART_PLOC_MPSOC_DEV[] = "/dev/ul-plmpsoc";
|
|||||||
static constexpr char UART_PLOC_SUPERVSIOR_DEV[] = "/dev/ul-plsv";
|
static constexpr char UART_PLOC_SUPERVSIOR_DEV[] = "/dev/ul-plsv";
|
||||||
static constexpr char UART_SYRLINKS_DEV[] = "/dev/ul-syrlinks";
|
static constexpr char UART_SYRLINKS_DEV[] = "/dev/ul-syrlinks";
|
||||||
static constexpr char UART_STAR_TRACKER_DEV[] = "/dev/ul-str";
|
static constexpr char UART_STAR_TRACKER_DEV[] = "/dev/ul-str";
|
||||||
|
static constexpr char UART_SCEX_DEV[] = "/dev/ttyS-SCEX";
|
||||||
|
|
||||||
static constexpr char UIO_PDEC_REGISTERS[] = "/dev/uio0";
|
static constexpr char UIO_PDEC_REGISTERS[] = "/dev/uio0";
|
||||||
static constexpr char UIO_PTME[] = "/dev/uio1";
|
static constexpr char UIO_PTME[] = "/dev/uio1";
|
||||||
|
@ -142,7 +142,11 @@ ReturnValue_t CoreController::initialize() {
|
|||||||
|
|
||||||
ReturnValue_t CoreController::initializeAfterTaskCreation() {
|
ReturnValue_t CoreController::initializeAfterTaskCreation() {
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
sdInfo.active = sdcMan->getPreferredSdCard();
|
auto sdCard = sdcMan->getPreferredSdCard();
|
||||||
|
if (not sdCard) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
sdInfo.active = sdCard.value();
|
||||||
if (sdInfo.active == sd::SdCard::NONE) {
|
if (sdInfo.active == sd::SdCard::NONE) {
|
||||||
sif::error << "CoreController::initializeAfterTaskCreation: "
|
sif::error << "CoreController::initializeAfterTaskCreation: "
|
||||||
"Issues getting preferred SD card, setting to 0"
|
"Issues getting preferred SD card, setting to 0"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "bsp_q7s/core/InitMission.h"
|
#include "bsp_q7s/core/InitMission.h"
|
||||||
|
|
||||||
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
||||||
|
#include <linux/InitMission.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -252,6 +253,11 @@ void initmission::initTasks() {
|
|||||||
initmission::printAddObjectError("PTME_TEST", objects::CCSDS_IP_CORE_BRIDGE);
|
initmission::printAddObjectError("PTME_TEST", objects::CCSDS_IP_CORE_BRIDGE);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if OBSW_ADD_SCEX_DEVICE == 1
|
||||||
|
PeriodicTaskIF* scexDevHandler;
|
||||||
|
PeriodicTaskIF* scexReaderTask;
|
||||||
|
scheduling::schedulingScex(*factory, scexDevHandler, scexReaderTask);
|
||||||
|
#endif
|
||||||
|
|
||||||
std::vector<PeriodicTaskIF*> pusTasks;
|
std::vector<PeriodicTaskIF*> pusTasks;
|
||||||
createPusTasks(*factory, missedDeadlineFunc, pusTasks);
|
createPusTasks(*factory, missedDeadlineFunc, pusTasks);
|
||||||
@ -290,8 +296,9 @@ void initmission::initTasks() {
|
|||||||
|
|
||||||
taskStarter(pstTasks, "PST task vector");
|
taskStarter(pstTasks, "PST task vector");
|
||||||
taskStarter(pusTasks, "PUS task vector");
|
taskStarter(pusTasks, "PUS task vector");
|
||||||
#if OBSW_ADD_TEST_CODE == 1
|
#if OBSW_ADD_SCEX_DEVICE == 1
|
||||||
taskStarter(testTasks, "Test task vector");
|
scexDevHandler->startTask();
|
||||||
|
scexReaderTask->startTask();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OBSW_TEST_CCSDS_BRIDGE == 1
|
#if OBSW_TEST_CCSDS_BRIDGE == 1
|
||||||
@ -315,6 +322,11 @@ void initmission::initTasks() {
|
|||||||
#if OBSW_ADD_PLOC_SUPERVISOR == 1
|
#if OBSW_ADD_PLOC_SUPERVISOR == 1
|
||||||
supvHelperTask->startTask();
|
supvHelperTask->startTask();
|
||||||
#endif /* OBSW_ADD_PLOC_SUPERVISOR == 1 */
|
#endif /* OBSW_ADD_PLOC_SUPERVISOR == 1 */
|
||||||
|
|
||||||
|
#if OBSW_ADD_TEST_CODE == 1
|
||||||
|
taskStarter(testTasks, "Test task vector");
|
||||||
|
#endif
|
||||||
|
|
||||||
sif::info << "Tasks started.." << std::endl;
|
sif::info << "Tasks started.." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "ObjectFactory.h"
|
#include "ObjectFactory.h"
|
||||||
|
|
||||||
|
#include <linux/devices/ScexUartReader.h>
|
||||||
|
|
||||||
#include "OBSWConfig.h"
|
#include "OBSWConfig.h"
|
||||||
#include "bsp_q7s/boardtest/Q7STestTask.h"
|
#include "bsp_q7s/boardtest/Q7STestTask.h"
|
||||||
#include "bsp_q7s/callbacks/gnssCallback.h"
|
#include "bsp_q7s/callbacks/gnssCallback.h"
|
||||||
@ -864,6 +866,7 @@ void ObjectFactory::createTestComponents(LinuxLibgpioIF* gpioComIF) {
|
|||||||
new I2cTestClass(objects::I2C_TEST, q7s::I2C_DEFAULT_DEV);
|
new I2cTestClass(objects::I2C_TEST, q7s::I2C_DEFAULT_DEV);
|
||||||
#endif
|
#endif
|
||||||
#if OBSW_ADD_UART_TEST_CODE == 1
|
#if OBSW_ADD_UART_TEST_CODE == 1
|
||||||
|
// auto* reader= new ScexUartReader(objects::SCEX_UART_READER);
|
||||||
new UartTestClass(objects::UART_TEST);
|
new UartTestClass(objects::UART_TEST);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
|
||||||
|
|
||||||
#include "OBSWConfig.h"
|
#include "OBSWConfig.h"
|
||||||
#include "bsp_q7s/core/CoreController.h"
|
#include "bsp_q7s/core/CoreController.h"
|
||||||
#include "bsp_q7s/core/ObjectFactory.h"
|
#include "bsp_q7s/core/ObjectFactory.h"
|
||||||
@ -56,6 +58,11 @@ void ObjectFactory::produce(void* args) {
|
|||||||
#if OBSW_USE_CCSDS_IP_CORE == 1
|
#if OBSW_USE_CCSDS_IP_CORE == 1
|
||||||
createCcsdsComponents(gpioComIF);
|
createCcsdsComponents(gpioComIF);
|
||||||
#endif /* OBSW_USE_CCSDS_IP_CORE == 1 */
|
#endif /* OBSW_USE_CCSDS_IP_CORE == 1 */
|
||||||
|
|
||||||
|
#if OBSW_ADD_SCEX_DEVICE == 1
|
||||||
|
createScexComponents(q7s::UART_SCEX_DEV, pwrSwitcher, *SdCardManager::instance(), false,
|
||||||
|
pcdu::Switches::PDU1_CH5_SOLAR_CELL_EXP_5V);
|
||||||
|
#endif
|
||||||
/* Test Task */
|
/* Test Task */
|
||||||
#if OBSW_ADD_TEST_CODE == 1
|
#if OBSW_ADD_TEST_CODE == 1
|
||||||
createTestComponents(gpioComIF);
|
createTestComponents(gpioComIF);
|
||||||
|
@ -304,11 +304,6 @@ ReturnValue_t SdCardManager::sanitizeState(SdStatePair* statusPair, sd::SdCard p
|
|||||||
blocking = true;
|
blocking = true;
|
||||||
resetNonBlockingState = true;
|
resetNonBlockingState = true;
|
||||||
}
|
}
|
||||||
if (prefSdCard == sd::SdCard::NONE) {
|
|
||||||
result = getPreferredSdCard();
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (statusPair == nullptr) {
|
if (statusPair == nullptr) {
|
||||||
sdStatusPtr = std::make_unique<SdStatePair>();
|
sdStatusPtr = std::make_unique<SdStatePair>();
|
||||||
statusPair = sdStatusPtr.get();
|
statusPair = sdStatusPtr.get();
|
||||||
@ -383,7 +378,7 @@ void SdCardManager::processSdStatusLine(std::pair<sd::SdState, sd::SdState>& act
|
|||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
sd::SdCard SdCardManager::getPreferredSdCard() const {
|
std::optional<sd::SdCard> SdCardManager::getPreferredSdCard() const {
|
||||||
MutexGuard mg(mutex);
|
MutexGuard mg(mutex);
|
||||||
auto res = mg.getLockResult();
|
auto res = mg.getLockResult();
|
||||||
if (res != returnvalue::OK) {
|
if (res != returnvalue::OK) {
|
||||||
@ -416,13 +411,9 @@ ReturnValue_t SdCardManager::updateSdCardStateFile() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SdCardManager::getCurrentMountPrefix() const {
|
const std::string& SdCardManager::getCurrentMountPrefix() const {
|
||||||
MutexGuard mg(mutex);
|
MutexGuard mg(mutex);
|
||||||
if (sdInfo.active == sd::SdCard::SLOT_0) {
|
return currentPrefix;
|
||||||
return config::SD_0_MOUNT_POINT;
|
|
||||||
} else {
|
|
||||||
return config::SD_1_MOUNT_POINT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SdCardManager::OpStatus SdCardManager::checkCurrentOp(Operations& currentOp) {
|
SdCardManager::OpStatus SdCardManager::checkCurrentOp(Operations& currentOp) {
|
||||||
@ -558,6 +549,17 @@ ReturnValue_t SdCardManager::performFsck(sd::SdCard sdcard, bool printOutput, in
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdCardManager::setActiveSdCard(sd::SdCard sdCard) { sdInfo.active = sdCard; }
|
void SdCardManager::setActiveSdCard(sd::SdCard sdCard) {
|
||||||
|
MutexGuard mg(mutex);
|
||||||
|
sdInfo.active = sdCard;
|
||||||
|
if (sdInfo.active == sd::SdCard::SLOT_0) {
|
||||||
|
currentPrefix = config::SD_0_MOUNT_POINT;
|
||||||
|
} else {
|
||||||
|
currentPrefix = config::SD_1_MOUNT_POINT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sd::SdCard SdCardManager::getActiveSdCard() const { return sdInfo.active; }
|
std::optional<sd::SdCard> SdCardManager::getActiveSdCard() const {
|
||||||
|
MutexGuard mg(mutex);
|
||||||
|
return sdInfo.active;
|
||||||
|
}
|
||||||
|
@ -91,7 +91,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
|
|||||||
* @param sdCard
|
* @param sdCard
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
sd::SdCard getPreferredSdCard() const override;
|
std::optional<sd::SdCard> getPreferredSdCard() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch on the specified SD card.
|
* Switch on the specified SD card.
|
||||||
@ -158,7 +158,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
|
|||||||
* mounted
|
* mounted
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
sd::SdCard getActiveSdCard() const override;
|
std::optional<sd::SdCard> getActiveSdCard() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unmount the specified SD card. This is recommended before switching it off. The SD card
|
* Unmount the specified SD card. This is recommended before switching it off. The SD card
|
||||||
@ -187,7 +187,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
|
|||||||
* @param prefSdCardPtr
|
* @param prefSdCardPtr
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
std::string getCurrentMountPrefix() const override;
|
const std::string& getCurrentMountPrefix() const override;
|
||||||
|
|
||||||
OpStatus checkCurrentOp(Operations& currentOp);
|
OpStatus checkCurrentOp(Operations& currentOp);
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "scratchApi.h"
|
#include "scratchApi.h"
|
||||||
|
|
||||||
ReturnValue_t scratch::writeString(std::string name, std::string string) {
|
ReturnValue_t scratch::writeString(std::string name, std::string string) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss("xsc_scratch write ", std::ostringstream::ate);
|
||||||
oss << "xsc_scratch write " << name << " \"" << string << "\"";
|
oss << name << " \"" << string << "\"";
|
||||||
int result = std::system(oss.str().c_str());
|
int result = std::system(oss.str().c_str());
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
utility::handleSystemError(result, "scratch::writeString");
|
utility::handleSystemError(result, "scratch::writeString");
|
||||||
@ -39,8 +39,8 @@ ReturnValue_t scratch::readString(std::string key, std::string &string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t scratch::clearValue(std::string key) {
|
ReturnValue_t scratch::clearValue(std::string key) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss("xsc_scratch clear ", std::ostringstream::ate);
|
||||||
oss << "xsc_scratch clear " << key;
|
oss << key;
|
||||||
int result = std::system(oss.str().c_str());
|
int result = std::system(oss.str().c_str());
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
utility::handleSystemError(result, "scratch::clearValue");
|
utility::handleSystemError(result, "scratch::clearValue");
|
||||||
|
@ -94,8 +94,8 @@ ReturnValue_t readToFile(std::string name, std::ifstream& file, std::string& fil
|
|||||||
|
|
||||||
template <typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
|
template <typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
|
||||||
inline ReturnValue_t writeNumber(std::string key, T num) noexcept {
|
inline ReturnValue_t writeNumber(std::string key, T num) noexcept {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss("xsc_scratch write ", std::ostringstream::ate);
|
||||||
oss << "xsc_scratch write " << key << " " << std::to_string(num);
|
oss << key << " " << std::to_string(num);
|
||||||
int result = std::system(oss.str().c_str());
|
int result = std::system(oss.str().c_str());
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
utility::handleSystemError(result, "scratch::writeNumber");
|
utility::handleSystemError(result, "scratch::writeNumber");
|
||||||
|
@ -55,6 +55,7 @@ namespace uart {
|
|||||||
|
|
||||||
static constexpr size_t HYPERION_GPS_REPLY_MAX_BUFFER = 1024;
|
static constexpr size_t HYPERION_GPS_REPLY_MAX_BUFFER = 1024;
|
||||||
static constexpr UartBaudRate SYRLINKS_BAUD = UartBaudRate::RATE_38400;
|
static constexpr UartBaudRate SYRLINKS_BAUD = UartBaudRate::RATE_38400;
|
||||||
|
static constexpr UartBaudRate SCEX_BAUD = UartBaudRate::RATE_57600;
|
||||||
static constexpr UartBaudRate GNSS_BAUD = UartBaudRate::RATE_9600;
|
static constexpr UartBaudRate GNSS_BAUD = UartBaudRate::RATE_9600;
|
||||||
static constexpr UartBaudRate PLOC_MPSOC_BAUD = UartBaudRate::RATE_115200;
|
static constexpr UartBaudRate PLOC_MPSOC_BAUD = UartBaudRate::RATE_115200;
|
||||||
static constexpr UartBaudRate PLOC_SUPV_BAUD = UartBaudRate::RATE_115200;
|
static constexpr UartBaudRate PLOC_SUPV_BAUD = UartBaudRate::RATE_115200;
|
||||||
|
@ -33,7 +33,8 @@ enum : uint8_t {
|
|||||||
ACU_HANDLER = 135,
|
ACU_HANDLER = 135,
|
||||||
PLOC_SUPV_HELPER = 136,
|
PLOC_SUPV_HELPER = 136,
|
||||||
SYRLINKS = 137,
|
SYRLINKS = 137,
|
||||||
CONFIGHANDLER = 138,
|
SCEX_HANDLER = 138,
|
||||||
|
CONFIGHANDLER = 139,
|
||||||
COMMON_SUBSYSTEM_ID_END
|
COMMON_SUBSYSTEM_ID_END
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -58,6 +58,7 @@ enum commonObjects : uint32_t {
|
|||||||
PLOC_MPSOC_HANDLER = 0x44330015,
|
PLOC_MPSOC_HANDLER = 0x44330015,
|
||||||
PLOC_SUPERVISOR_HANDLER = 0x44330016,
|
PLOC_SUPERVISOR_HANDLER = 0x44330016,
|
||||||
PLOC_SUPERVISOR_HELPER = 0x44330017,
|
PLOC_SUPERVISOR_HELPER = 0x44330017,
|
||||||
|
SCEX = 0x44330032,
|
||||||
SOLAR_ARRAY_DEPL_HANDLER = 0x444100A2,
|
SOLAR_ARRAY_DEPL_HANDLER = 0x444100A2,
|
||||||
HEATER_HANDLER = 0x444100A4,
|
HEATER_HANDLER = 0x444100A4,
|
||||||
|
|
||||||
|
2
fsfw
2
fsfw
@ -1 +1 @@
|
|||||||
Subproject commit 692be9df8d06beb3bfc83aad77cefd727d8f7c35
|
Subproject commit a8fb83dfcedb5391ac942d6bcffa64f0cbca38c5
|
@ -216,8 +216,11 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
|||||||
13701;0x3585;REBOOT_SW;MEDIUM; Software reboot occurred. Can also be a systemd reboot. P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h
|
13701;0x3585;REBOOT_SW;MEDIUM; Software reboot occurred. Can also be a systemd reboot. P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h
|
||||||
13702;0x3586;REBOOT_MECHANISM_TRIGGERED;MEDIUM;The reboot mechanism was triggered. P1: First 16 bits: Last Chip, Last 16 bits: Last Copy, P2: Each byte is the respective reboot count for the slots;bsp_q7s/core/CoreController.h
|
13702;0x3586;REBOOT_MECHANISM_TRIGGERED;MEDIUM;The reboot mechanism was triggered. P1: First 16 bits: Last Chip, Last 16 bits: Last Copy, P2: Each byte is the respective reboot count for the slots;bsp_q7s/core/CoreController.h
|
||||||
13703;0x3587;REBOOT_HW;MEDIUM;;bsp_q7s/core/CoreController.h
|
13703;0x3587;REBOOT_HW;MEDIUM;;bsp_q7s/core/CoreController.h
|
||||||
13801;0x35e9;SET_CONFIGFILEVALUE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
|
13800;0x35e8;MISSING_PACKET;LOW;;mission/devices/devicedefinitions/ScexDefinitions.h
|
||||||
13802;0x35ea;GET_CONFIGFILEVALUE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
|
13801;0x35e9;EXPERIMENT_TIMEDOUT;LOW;;mission/devices/devicedefinitions/ScexDefinitions.h
|
||||||
13803;0x35eb;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
|
13802;0x35ea;MULTI_PACKET_COMMAND_DONE;INFO;;mission/devices/devicedefinitions/ScexDefinitions.h
|
||||||
13804;0x35ec;WRITE_CONFIGFILE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
|
13901;0x364d;SET_CONFIGFILEVALUE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
|
||||||
13805;0x35ed;READ_CONFIGFILE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
|
13902;0x364e;GET_CONFIGFILEVALUE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
|
||||||
|
13903;0x364f;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
|
||||||
|
13904;0x3650;WRITE_CONFIGFILE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
|
||||||
|
13905;0x3651;READ_CONFIGFILE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
|
||||||
|
|
@ -47,6 +47,7 @@
|
|||||||
0x44330015;PLOC_MPSOC_HANDLER
|
0x44330015;PLOC_MPSOC_HANDLER
|
||||||
0x44330016;PLOC_SUPERVISOR_HANDLER
|
0x44330016;PLOC_SUPERVISOR_HANDLER
|
||||||
0x44330017;PLOC_SUPERVISOR_HELPER
|
0x44330017;PLOC_SUPERVISOR_HELPER
|
||||||
|
0x44330032;SCEX
|
||||||
0x444100A2;SOLAR_ARRAY_DEPL_HANDLER
|
0x444100A2;SOLAR_ARRAY_DEPL_HANDLER
|
||||||
0x444100A4;HEATER_HANDLER
|
0x444100A4;HEATER_HANDLER
|
||||||
0x44420004;TMP1075_HANDLER_1
|
0x44420004;TMP1075_HANDLER_1
|
||||||
@ -70,6 +71,7 @@
|
|||||||
0x445300A3;SYRLINKS_HK_HANDLER
|
0x445300A3;SYRLINKS_HK_HANDLER
|
||||||
0x49000000;ARDUINO_COM_IF
|
0x49000000;ARDUINO_COM_IF
|
||||||
0x49010005;GPIO_IF
|
0x49010005;GPIO_IF
|
||||||
|
0x49010006;SCEX_UART_READER
|
||||||
0x49020004;SPI_MAIN_COM_IF
|
0x49020004;SPI_MAIN_COM_IF
|
||||||
0x49020005;SPI_RW_COM_IF
|
0x49020005;SPI_RW_COM_IF
|
||||||
0x49020006;SPI_RTD_COM_IF
|
0x49020006;SPI_RTD_COM_IF
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 222 translations.
|
* @brief Auto-generated event translation file. Contains 225 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2022-10-10 10:15:22
|
* Generated on: 2022-10-10 11:15:49
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
@ -218,6 +218,9 @@ const char *ALLOC_FAILURE_STRING = "ALLOC_FAILURE";
|
|||||||
const char *REBOOT_SW_STRING = "REBOOT_SW";
|
const char *REBOOT_SW_STRING = "REBOOT_SW";
|
||||||
const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED";
|
const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED";
|
||||||
const char *REBOOT_HW_STRING = "REBOOT_HW";
|
const char *REBOOT_HW_STRING = "REBOOT_HW";
|
||||||
|
const char *MISSING_PACKET_STRING = "MISSING_PACKET";
|
||||||
|
const char *EXPERIMENT_TIMEDOUT_STRING = "EXPERIMENT_TIMEDOUT";
|
||||||
|
const char *MULTI_PACKET_COMMAND_DONE_STRING = "MULTI_PACKET_COMMAND_DONE";
|
||||||
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
|
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
|
||||||
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
|
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
|
||||||
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
|
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
|
||||||
@ -652,15 +655,21 @@ const char *translateEvents(Event event) {
|
|||||||
return REBOOT_MECHANISM_TRIGGERED_STRING;
|
return REBOOT_MECHANISM_TRIGGERED_STRING;
|
||||||
case (13703):
|
case (13703):
|
||||||
return REBOOT_HW_STRING;
|
return REBOOT_HW_STRING;
|
||||||
|
case (13800):
|
||||||
|
return MISSING_PACKET_STRING;
|
||||||
case (13801):
|
case (13801):
|
||||||
return SET_CONFIGFILEVALUE_FAILED_STRING;
|
return EXPERIMENT_TIMEDOUT_STRING;
|
||||||
case (13802):
|
case (13802):
|
||||||
|
return MULTI_PACKET_COMMAND_DONE_STRING;
|
||||||
|
case (13901):
|
||||||
|
return SET_CONFIGFILEVALUE_FAILED_STRING;
|
||||||
|
case (13902):
|
||||||
return GET_CONFIGFILEVALUE_FAILED_STRING;
|
return GET_CONFIGFILEVALUE_FAILED_STRING;
|
||||||
case (13803):
|
case (13903):
|
||||||
return INSERT_CONFIGFILEVALUE_FAILED_STRING;
|
return INSERT_CONFIGFILEVALUE_FAILED_STRING;
|
||||||
case (13804):
|
case (13904):
|
||||||
return WRITE_CONFIGFILE_FAILED_STRING;
|
return WRITE_CONFIGFILE_FAILED_STRING;
|
||||||
case (13805):
|
case (13905):
|
||||||
return READ_CONFIGFILE_FAILED_STRING;
|
return READ_CONFIGFILE_FAILED_STRING;
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN_EVENT";
|
return "UNKNOWN_EVENT";
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 136 translations.
|
* Contains 138 translations.
|
||||||
* Generated on: 2022-10-10 10:15:22
|
* Generated on: 2022-10-10 11:15:49
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
@ -55,6 +55,7 @@ const char *PTME_CONFIG_STRING = "PTME_CONFIG";
|
|||||||
const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER";
|
const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER";
|
||||||
const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER";
|
const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER";
|
||||||
const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER";
|
const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER";
|
||||||
|
const char *SCEX_STRING = "SCEX";
|
||||||
const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER";
|
const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER";
|
||||||
const char *HEATER_HANDLER_STRING = "HEATER_HANDLER";
|
const char *HEATER_HANDLER_STRING = "HEATER_HANDLER";
|
||||||
const char *TMP1075_HANDLER_1_STRING = "TMP1075_HANDLER_1";
|
const char *TMP1075_HANDLER_1_STRING = "TMP1075_HANDLER_1";
|
||||||
@ -78,6 +79,7 @@ const char *RTD_15_IC18_IMTQ_STRING = "RTD_15_IC18_IMTQ";
|
|||||||
const char *SYRLINKS_HK_HANDLER_STRING = "SYRLINKS_HK_HANDLER";
|
const char *SYRLINKS_HK_HANDLER_STRING = "SYRLINKS_HK_HANDLER";
|
||||||
const char *ARDUINO_COM_IF_STRING = "ARDUINO_COM_IF";
|
const char *ARDUINO_COM_IF_STRING = "ARDUINO_COM_IF";
|
||||||
const char *GPIO_IF_STRING = "GPIO_IF";
|
const char *GPIO_IF_STRING = "GPIO_IF";
|
||||||
|
const char *SCEX_UART_READER_STRING = "SCEX_UART_READER";
|
||||||
const char *SPI_MAIN_COM_IF_STRING = "SPI_MAIN_COM_IF";
|
const char *SPI_MAIN_COM_IF_STRING = "SPI_MAIN_COM_IF";
|
||||||
const char *SPI_RW_COM_IF_STRING = "SPI_RW_COM_IF";
|
const char *SPI_RW_COM_IF_STRING = "SPI_RW_COM_IF";
|
||||||
const char *SPI_RTD_COM_IF_STRING = "SPI_RTD_COM_IF";
|
const char *SPI_RTD_COM_IF_STRING = "SPI_RTD_COM_IF";
|
||||||
@ -243,6 +245,8 @@ const char *translateObject(object_id_t object) {
|
|||||||
return PLOC_SUPERVISOR_HANDLER_STRING;
|
return PLOC_SUPERVISOR_HANDLER_STRING;
|
||||||
case 0x44330017:
|
case 0x44330017:
|
||||||
return PLOC_SUPERVISOR_HELPER_STRING;
|
return PLOC_SUPERVISOR_HELPER_STRING;
|
||||||
|
case 0x44330032:
|
||||||
|
return SCEX_STRING;
|
||||||
case 0x444100A2:
|
case 0x444100A2:
|
||||||
return SOLAR_ARRAY_DEPL_HANDLER_STRING;
|
return SOLAR_ARRAY_DEPL_HANDLER_STRING;
|
||||||
case 0x444100A4:
|
case 0x444100A4:
|
||||||
@ -289,6 +293,8 @@ const char *translateObject(object_id_t object) {
|
|||||||
return ARDUINO_COM_IF_STRING;
|
return ARDUINO_COM_IF_STRING;
|
||||||
case 0x49010005:
|
case 0x49010005:
|
||||||
return GPIO_IF_STRING;
|
return GPIO_IF_STRING;
|
||||||
|
case 0x49010006:
|
||||||
|
return SCEX_UART_READER_STRING;
|
||||||
case 0x49020004:
|
case 0x49020004:
|
||||||
return SPI_MAIN_COM_IF_STRING;
|
return SPI_MAIN_COM_IF_STRING;
|
||||||
case 0x49020005:
|
case 0x49020005:
|
||||||
|
@ -6,4 +6,4 @@ add_subdirectory(devices)
|
|||||||
add_subdirectory(fsfwconfig)
|
add_subdirectory(fsfwconfig)
|
||||||
add_subdirectory(obc)
|
add_subdirectory(obc)
|
||||||
|
|
||||||
target_sources(${OBSW_NAME} PUBLIC ObjectFactory.cpp)
|
target_sources(${OBSW_NAME} PUBLIC ObjectFactory.cpp InitMission.cpp)
|
||||||
|
47
linux/InitMission.cpp
Normal file
47
linux/InitMission.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "InitMission.h"
|
||||||
|
|
||||||
|
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||||
|
#include <fsfw/tasks/PeriodicTaskIF.h>
|
||||||
|
#include <mission/utility/InitMission.h>
|
||||||
|
|
||||||
|
#include "OBSWConfig.h"
|
||||||
|
#include "ObjectFactory.h"
|
||||||
|
|
||||||
|
void scheduling::schedulingScex(TaskFactory& factory, PeriodicTaskIF*& scexDevHandler,
|
||||||
|
PeriodicTaskIF*& scexReaderTask) {
|
||||||
|
using namespace initmission;
|
||||||
|
ReturnValue_t result = returnvalue::OK;
|
||||||
|
#if OBSW_PRINT_MISSED_DEADLINES == 1
|
||||||
|
void (*missedDeadlineFunc)(void) = TaskFactory::printMissedDeadline;
|
||||||
|
#else
|
||||||
|
void (*missedDeadlineFunc)(void) = nullptr;
|
||||||
|
#endif
|
||||||
|
scexDevHandler = factory.createPeriodicTask(
|
||||||
|
"SCEX_DEV", 35, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.5, missedDeadlineFunc);
|
||||||
|
|
||||||
|
result = scexDevHandler->addComponent(objects::SCEX, DeviceHandlerIF::PERFORM_OPERATION);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
printAddObjectError("SCEX_DEV", objects::SCEX);
|
||||||
|
}
|
||||||
|
result = scexDevHandler->addComponent(objects::SCEX, DeviceHandlerIF::SEND_WRITE);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
printAddObjectError("SCEX_DEV", objects::SCEX);
|
||||||
|
}
|
||||||
|
result = scexDevHandler->addComponent(objects::SCEX, DeviceHandlerIF::GET_WRITE);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
printAddObjectError("SCEX_DEV", objects::SCEX);
|
||||||
|
}
|
||||||
|
result = scexDevHandler->addComponent(objects::SCEX, DeviceHandlerIF::SEND_READ);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
printAddObjectError("SCEX_DEV", objects::SCEX);
|
||||||
|
}
|
||||||
|
result = scexDevHandler->addComponent(objects::SCEX, DeviceHandlerIF::GET_READ);
|
||||||
|
|
||||||
|
result = returnvalue::OK;
|
||||||
|
scexReaderTask = factory.createPeriodicTask(
|
||||||
|
"SCEX_UART_READER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc);
|
||||||
|
result = scexReaderTask->addComponent(objects::SCEX_UART_READER);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
printAddObjectError("SCEX_UART_READER", objects::SCEX_UART_READER);
|
||||||
|
}
|
||||||
|
}
|
7
linux/InitMission.h
Normal file
7
linux/InitMission.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <fsfw/tasks/TaskFactory.h>
|
||||||
|
|
||||||
|
namespace scheduling {
|
||||||
|
void schedulingScex(TaskFactory& factory, PeriodicTaskIF*& scexDevHandler,
|
||||||
|
PeriodicTaskIF*& scexReaderTask);
|
||||||
|
}
|
@ -6,12 +6,14 @@
|
|||||||
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
|
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
|
||||||
#include <fsfw_hal/linux/spi/SpiComIF.h>
|
#include <fsfw_hal/linux/spi/SpiComIF.h>
|
||||||
#include <fsfw_hal/linux/spi/SpiCookie.h>
|
#include <fsfw_hal/linux/spi/SpiCookie.h>
|
||||||
|
#include <fsfw_hal/linux/uart/UartCookie.h>
|
||||||
#include <linux/callbacks/gpioCallbacks.h>
|
#include <linux/callbacks/gpioCallbacks.h>
|
||||||
#include <linux/devices/Max31865RtdLowlevelHandler.h>
|
#include <linux/devices/Max31865RtdLowlevelHandler.h>
|
||||||
#include <mission/controller/AcsController.h>
|
#include <mission/controller/AcsController.h>
|
||||||
#include <mission/controller/ThermalController.h>
|
#include <mission/controller/ThermalController.h>
|
||||||
#include <mission/devices/Max31865EiveHandler.h>
|
#include <mission/devices/Max31865EiveHandler.h>
|
||||||
#include <mission/devices/Max31865PT1000Handler.h>
|
#include <mission/devices/Max31865PT1000Handler.h>
|
||||||
|
#include <mission/devices/ScexDeviceHandler.h>
|
||||||
#include <mission/devices/SusHandler.h>
|
#include <mission/devices/SusHandler.h>
|
||||||
#include <mission/system/SusAssembly.h>
|
#include <mission/system/SusAssembly.h>
|
||||||
#include <mission/system/TcsBoardAssembly.h>
|
#include <mission/system/TcsBoardAssembly.h>
|
||||||
@ -321,6 +323,22 @@ void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF,
|
|||||||
#endif // OBSW_ADD_RTD_DEVICES == 1
|
#endif // OBSW_ADD_RTD_DEVICES == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjectFactory::createScexComponents(std::string uartDev, PowerSwitchIF* pwrSwitcher,
|
||||||
|
SdCardMountedIF& mountedIF, bool onImmediately,
|
||||||
|
std::optional<power::Switch_t> switchId) {
|
||||||
|
auto* cookie = new UartCookie(objects::SCEX, uartDev, uart::SCEX_BAUD, 4096);
|
||||||
|
cookie->setTwoStopBits();
|
||||||
|
//cookie->setParityEven();
|
||||||
|
auto scexUartReader = new ScexUartReader(objects::SCEX_UART_READER);
|
||||||
|
auto scexHandler = new ScexDeviceHandler(objects::SCEX, *scexUartReader, cookie, mountedIF);
|
||||||
|
if (onImmediately) {
|
||||||
|
scexHandler->setStartUpImmediately();
|
||||||
|
}
|
||||||
|
if (switchId) {
|
||||||
|
scexHandler->setPowerSwitcher(*pwrSwitcher, switchId.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectFactory::createThermalController() {
|
void ObjectFactory::createThermalController() {
|
||||||
new ThermalController(objects::THERMAL_CONTROLLER, objects::NO_OBJECT);
|
new ThermalController(objects::THERMAL_CONTROLLER, objects::NO_OBJECT);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <fsfw/power/definitions.h>
|
||||||
#include <fsfw/returnvalues/returnvalue.h>
|
#include <fsfw/returnvalues/returnvalue.h>
|
||||||
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
|
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
|
||||||
|
#include <mission/memory/SdCardMountedIF.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class GpioIF;
|
class GpioIF;
|
||||||
@ -16,6 +19,10 @@ void createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiComIF, PowerSwitc
|
|||||||
void createRtdComponents(std::string spiDev, GpioIF* gpioComIF, PowerSwitchIF* pwrSwitcher,
|
void createRtdComponents(std::string spiDev, GpioIF* gpioComIF, PowerSwitchIF* pwrSwitcher,
|
||||||
SpiComIF* comIF);
|
SpiComIF* comIF);
|
||||||
|
|
||||||
|
void createScexComponents(std::string uartDev, PowerSwitchIF* pwrSwitcher,
|
||||||
|
SdCardMountedIF& mountedIF, bool onImmediately,
|
||||||
|
std::optional<power::Switch_t> switchId);
|
||||||
|
|
||||||
void gpioChecker(ReturnValue_t result, std::string output);
|
void gpioChecker(ReturnValue_t result, std::string output);
|
||||||
|
|
||||||
void createThermalController();
|
void createThermalController();
|
||||||
|
@ -3,14 +3,21 @@
|
|||||||
#include <errno.h> // Error integer and strerror() function
|
#include <errno.h> // Error integer and strerror() function
|
||||||
#include <fcntl.h> // Contains file controls like O_RDWR
|
#include <fcntl.h> // Contains file controls like O_RDWR
|
||||||
#include <fsfw/tasks/TaskFactory.h>
|
#include <fsfw/tasks/TaskFactory.h>
|
||||||
|
#include <fsfw_hal/linux/uart/UartCookie.h>
|
||||||
|
#include <linux/devices/ScexDleParser.h>
|
||||||
|
#include <linux/devices/ScexHelper.h>
|
||||||
|
#include <linux/devices/ScexUartReader.h>
|
||||||
#include <unistd.h> // write(), read(), close()
|
#include <unistd.h> // write(), read(), close()
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "OBSWConfig.h"
|
#include "OBSWConfig.h"
|
||||||
#include "fsfw/globalfunctions/CRC.h"
|
#include "fsfw/globalfunctions/CRC.h"
|
||||||
#include "fsfw/globalfunctions/DleEncoder.h"
|
#include "fsfw/globalfunctions/DleEncoder.h"
|
||||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||||
#include "fsfw/serviceinterface.h"
|
#include "fsfw/serviceinterface.h"
|
||||||
#include "mission/devices/devicedefinitions/SCEXDefinitions.h"
|
#include "mission/devices/devicedefinitions/ScexDefinitions.h"
|
||||||
|
|
||||||
#define GPS_REPLY_WIRETAPPING 0
|
#define GPS_REPLY_WIRETAPPING 0
|
||||||
|
|
||||||
@ -18,7 +25,25 @@
|
|||||||
#define RPI_TEST_GPS_HANDLER 0
|
#define RPI_TEST_GPS_HANDLER 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UartTestClass::UartTestClass(object_id_t objectId) : TestTask(objectId) { mode = TestModes::SCEX; }
|
using namespace returnvalue;
|
||||||
|
|
||||||
|
UartTestClass::UartTestClass(object_id_t objectId) : TestTask(objectId) {
|
||||||
|
mode = TestModes::SCEX;
|
||||||
|
scexMode = ScexModes::SIMPLE;
|
||||||
|
// No one-cell and all-cell support implemented yet
|
||||||
|
currCmd = scex::Cmds::PING;
|
||||||
|
if (scexMode == ScexModes::SIMPLE) {
|
||||||
|
auto encodingBuf = new std::array<uint8_t, 4096>;
|
||||||
|
DleParser::BufPair encodingBufPair{encodingBuf->data(), encodingBuf->size()};
|
||||||
|
auto decodedBuf = new std::array<uint8_t, 4096>;
|
||||||
|
DleParser::BufPair decodingBufPair{decodedBuf->data(), decodedBuf->size()};
|
||||||
|
// TODO: Code changes but this test class has not, might not work like this anymore
|
||||||
|
dleParser = new ScexDleParser(*(new SimpleRingBuffer(4096, true)), dleEncoder, encodingBufPair,
|
||||||
|
decodingBufPair);
|
||||||
|
} else {
|
||||||
|
reader = new ScexUartReader(objects::SCEX_UART_READER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t UartTestClass::initialize() {
|
ReturnValue_t UartTestClass::initialize() {
|
||||||
if (mode == TestModes::GPS) {
|
if (mode == TestModes::GPS) {
|
||||||
@ -44,14 +69,14 @@ void UartTestClass::gpsInit() {
|
|||||||
#if RPI_TEST_GPS_HANDLER == 1
|
#if RPI_TEST_GPS_HANDLER == 1
|
||||||
int result = lwgps_init(&gpsData);
|
int result = lwgps_init(&gpsData);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
sif::warning << "lwgps_init error: " << result << std::endl;
|
sif::warning << "UartTestClass::gpsInit: lwgps_init error: " << result << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get file descriptor */
|
/* Get file descriptor */
|
||||||
serialPort = open("/dev/serial0", O_RDWR);
|
serialPort = open("/dev/serial0", O_RDWR);
|
||||||
if (serialPort < 0) {
|
if (serialPort < 0) {
|
||||||
sif::warning << "open call failed with error [" << errno << ", " << strerror(errno)
|
sif::warning << "UartTestClass::gpsInit: open call failed with error [" << errno << ", "
|
||||||
<< std::endl;
|
<< strerror(errno) << std::endl;
|
||||||
}
|
}
|
||||||
/* Setting up UART parameters */
|
/* Setting up UART parameters */
|
||||||
tty.c_cflag &= ~PARENB; // Clear parity bit
|
tty.c_cflag &= ~PARENB; // Clear parity bit
|
||||||
@ -79,8 +104,8 @@ void UartTestClass::gpsInit() {
|
|||||||
cfsetispeed(&tty, B9600);
|
cfsetispeed(&tty, B9600);
|
||||||
cfsetospeed(&tty, B9600);
|
cfsetospeed(&tty, B9600);
|
||||||
if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
|
if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
|
||||||
sif::warning << "tcsetattr call failed with error [" << errno << ", " << strerror(errno)
|
sif::warning << "UartTestClass::gpsInit: tcsetattr call failed with error [" << errno << ", "
|
||||||
<< std::endl;
|
<< strerror(errno) << std::endl;
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
// Flush received and unread data. Those are old NMEA strings which are not relevant anymore
|
// Flush received and unread data. Those are old NMEA strings which are not relevant anymore
|
||||||
@ -95,11 +120,11 @@ void UartTestClass::gpsPeriodic() {
|
|||||||
bytesRead = read(serialPort, reinterpret_cast<void*>(recBuf.data()),
|
bytesRead = read(serialPort, reinterpret_cast<void*>(recBuf.data()),
|
||||||
static_cast<unsigned int>(recBuf.size()));
|
static_cast<unsigned int>(recBuf.size()));
|
||||||
if (bytesRead < 0) {
|
if (bytesRead < 0) {
|
||||||
sif::warning << "UartTestClass::performPeriodicAction: read call failed with error [" << errno
|
sif::warning << "UartTestClass::gpsPeriodic: read call failed with error [" << errno << ", "
|
||||||
<< ", " << strerror(errno) << "]" << std::endl;
|
<< strerror(errno) << "]" << std::endl;
|
||||||
break;
|
break;
|
||||||
} else if (bytesRead >= static_cast<int>(recBuf.size())) {
|
} else if (bytesRead >= static_cast<int>(recBuf.size())) {
|
||||||
sif::debug << "UartTestClass::performPeriodicAction: "
|
sif::debug << "UartTestClass::gpsPeriodic: "
|
||||||
"recv buffer might not be large enough"
|
"recv buffer might not be large enough"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
} else if (bytesRead > 0) {
|
} else if (bytesRead > 0) {
|
||||||
@ -109,7 +134,7 @@ void UartTestClass::gpsPeriodic() {
|
|||||||
#endif
|
#endif
|
||||||
int result = lwgps_process(&gpsData, recBuf.data(), bytesRead);
|
int result = lwgps_process(&gpsData, recBuf.data(), bytesRead);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
sif::warning << "UartTestClass::performPeriodicAction: lwgps_process error" << std::endl;
|
sif::warning << "UartTestClass::gpsPeriodic: lwgps_process error" << std::endl;
|
||||||
}
|
}
|
||||||
recvCnt++;
|
recvCnt++;
|
||||||
if (recvCnt == 6) {
|
if (recvCnt == 6) {
|
||||||
@ -127,6 +152,114 @@ void UartTestClass::gpsPeriodic() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UartTestClass::scexInit() {
|
void UartTestClass::scexInit() {
|
||||||
|
if (scexMode == ScexModes::SIMPLE) {
|
||||||
|
scexSimpleInit();
|
||||||
|
} else {
|
||||||
|
if (reader == nullptr) {
|
||||||
|
sif::warning << "UartTestClass::scexInit: Reader invalid" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if defined(RASPBERRY_PI)
|
||||||
|
std::string devname = "/dev/serial0";
|
||||||
|
#else
|
||||||
|
std::string devname = "/dev/ul-scex";
|
||||||
|
#endif
|
||||||
|
uartCookie = new UartCookie(this->getObjectId(), devname, UartBaudRate::RATE_57600, 4096);
|
||||||
|
reader->setDebugMode(false);
|
||||||
|
ReturnValue_t result = reader->initializeInterface(uartCookie);
|
||||||
|
if (result != OK) {
|
||||||
|
sif::warning << "UartTestClass::scexInit: Initializing SCEX reader "
|
||||||
|
"UART IF failed"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UartTestClass::scexPeriodic() {
|
||||||
|
using namespace std;
|
||||||
|
using namespace scex;
|
||||||
|
|
||||||
|
if (scexMode == ScexModes::SIMPLE) {
|
||||||
|
scexSimplePeriodic();
|
||||||
|
} else {
|
||||||
|
if (reader == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (not cmdSent) {
|
||||||
|
size_t len = 0;
|
||||||
|
prepareScexCmd(currCmd, false, cmdBuf.data(), &len);
|
||||||
|
reader->sendMessage(uartCookie, cmdBuf.data(), len);
|
||||||
|
cmdSent = true;
|
||||||
|
cmdDone = false;
|
||||||
|
}
|
||||||
|
if (cmdSent and not cmdDone) {
|
||||||
|
uint8_t* decodedPacket = nullptr;
|
||||||
|
size_t len = 0;
|
||||||
|
do {
|
||||||
|
ReturnValue_t result = reader->readReceivedMessage(uartCookie, &decodedPacket, &len);
|
||||||
|
if (len == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ScexHelper helper;
|
||||||
|
const uint8_t* helperPtr = decodedPacket;
|
||||||
|
result = helper.deSerialize(&helperPtr, &len);
|
||||||
|
if (result == ScexHelper::INVALID_CRC) {
|
||||||
|
sif::warning << "UartTestClass::scexPeriodic: CRC invalid" << std::endl;
|
||||||
|
}
|
||||||
|
sif::info << helper << endl;
|
||||||
|
|
||||||
|
// ping
|
||||||
|
// if ping cmd
|
||||||
|
if (helper.getCmd() == PING) {
|
||||||
|
ofstream out("/tmp/scex-ping.bin", ofstream::binary);
|
||||||
|
if (out.bad()) {
|
||||||
|
sif::warning << "bad" << std::endl;
|
||||||
|
}
|
||||||
|
out << helper;
|
||||||
|
}
|
||||||
|
// fram
|
||||||
|
if (helper.getCmd() == FRAM) {
|
||||||
|
if (not fileNameSet) {
|
||||||
|
fileId = random_string(6);
|
||||||
|
fileName = "/tmp/scex-fram_" + fileId + ".bin";
|
||||||
|
fileNameSet = true;
|
||||||
|
}
|
||||||
|
if (helper.getPacketCounter() == 1) {
|
||||||
|
// countdown starten
|
||||||
|
finishCountdown.resetTimer();
|
||||||
|
ofstream out(fileName,
|
||||||
|
ofstream::binary); // neues file anlegen
|
||||||
|
} else {
|
||||||
|
ofstream out(fileName,
|
||||||
|
ofstream::binary | ofstream::app); // an bestehendes file appenden
|
||||||
|
out << helper;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finishCountdown.hasTimedOut()) {
|
||||||
|
triggerEvent(scex::EXPERIMENT_TIMEDOUT, currCmd, 0);
|
||||||
|
reader->finish();
|
||||||
|
sif::warning << "UartTestClass::scexPeriodic: Reader timeout" << endl;
|
||||||
|
cmdDone = true;
|
||||||
|
fileNameSet = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (helper.getPacketCounter() == helper.getTotalPacketCounter()) {
|
||||||
|
reader->finish();
|
||||||
|
sif::info << "UartTestClass::scexPeriodic: Reader is finished" << endl;
|
||||||
|
cmdDone = true;
|
||||||
|
fileNameSet = false;
|
||||||
|
if (helper.getCmd() == scex::Cmds::PING) {
|
||||||
|
cmdSent = false;
|
||||||
|
fileNameSet = true; // to not generate everytime new file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (len > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UartTestClass::scexSimpleInit() {
|
||||||
#if defined(RASPBERRY_PI)
|
#if defined(RASPBERRY_PI)
|
||||||
std::string devname = "/dev/serial0";
|
std::string devname = "/dev/serial0";
|
||||||
#else
|
#else
|
||||||
@ -135,8 +268,8 @@ void UartTestClass::scexInit() {
|
|||||||
/* Get file descriptor */
|
/* Get file descriptor */
|
||||||
serialPort = open(devname.c_str(), O_RDWR);
|
serialPort = open(devname.c_str(), O_RDWR);
|
||||||
if (serialPort < 0) {
|
if (serialPort < 0) {
|
||||||
sif::warning << "open call failed with error [" << errno << ", " << strerror(errno)
|
sif::warning << "UartTestClass::scexSimpleInit: Open call failed with error [" << errno << ", "
|
||||||
<< std::endl;
|
<< strerror(errno) << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Setting up UART parameters
|
// Setting up UART parameters
|
||||||
@ -152,74 +285,117 @@ void UartTestClass::scexInit() {
|
|||||||
|
|
||||||
// Non-blocking mode, read until either line is 0.1 second idle or maximum of 255 bytes are
|
// Non-blocking mode, read until either line is 0.1 second idle or maximum of 255 bytes are
|
||||||
// received in one go
|
// received in one go
|
||||||
tty.c_cc[VTIME] = 1; // In units of 0.1 seconds
|
tty.c_cc[VTIME] = 0; // In units of 0.1 seconds
|
||||||
tty.c_cc[VMIN] = 255; // Read up to 255 bytes
|
tty.c_cc[VMIN] = 0; // Read up to 255 bytes
|
||||||
|
|
||||||
// Q7S UART Lite has fixed baud rate. For other linux systems, set baud rate here.
|
// Q7S UART Lite has fixed baud rate. For other linux systems, set baud rate here.
|
||||||
#if !defined(XIPHOS_Q7S)
|
#if !defined(XIPHOS_Q7S)
|
||||||
if (cfsetispeed(&tty, B57600) != 0) {
|
if (cfsetispeed(&tty, B57600) != 0) {
|
||||||
sif::warning << "UartTestClass::scexInit: Setting baud rate failed" << std::endl;
|
sif::warning << "UartTestClass::scexSimpleInit: Setting baud rate failed" << std::endl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
|
if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
|
||||||
sif::warning << "tcsetattr call failed with error [" << errno << ", " << strerror(errno)
|
sif::warning << "UartTestClass::scexSimpleInit: tcsetattr call failed with error [" << errno
|
||||||
<< std::endl;
|
<< ", " << strerror(errno) << std::endl;
|
||||||
}
|
}
|
||||||
// Flush received and unread data
|
// Flush received and unread data
|
||||||
tcflush(serialPort, TCIFLUSH);
|
tcflush(serialPort, TCIOFLUSH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UartTestClass::scexPeriodic() {
|
void UartTestClass::scexSimplePeriodic() {
|
||||||
sif::info << "UartTestClass::scexInit: Sending ping command to SCEX" << std::endl;
|
using namespace scex;
|
||||||
int result = prepareScexPing();
|
ReturnValue_t result = OK;
|
||||||
|
if (not cmdSent) {
|
||||||
|
// Flush received and unread data
|
||||||
|
tcflush(serialPort, TCIFLUSH);
|
||||||
|
uint8_t tmpCmdBuf[32] = {};
|
||||||
|
size_t len = 0;
|
||||||
|
sif::info << "UartTestClass::scexSimplePeriodic: Sending command to SCEX" << std::endl;
|
||||||
|
prepareScexCmd(currCmd, false, tmpCmdBuf, &len);
|
||||||
|
result = dleEncoder.encode(tmpCmdBuf, len, cmdBuf.data(), cmdBuf.size(), &encodedLen, true);
|
||||||
|
if (result != OK) {
|
||||||
|
sif::warning << "UartTestClass::scexSimplePeriodic: Encoding failed" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
size_t bytesWritten = write(serialPort, cmdBuf.data(), encodedLen);
|
size_t bytesWritten = write(serialPort, cmdBuf.data(), encodedLen);
|
||||||
if (bytesWritten != encodedLen) {
|
if (bytesWritten != encodedLen) {
|
||||||
sif::warning << "Sending ping command to solar experiment failed" << std::endl;
|
sif::warning
|
||||||
|
<< "UartTestClass::scexSimplePeriodic: Sending command to solar experiment failed"
|
||||||
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
cmdSent = true;
|
||||||
|
cmdDone = false;
|
||||||
|
}
|
||||||
|
if (not cmdDone) {
|
||||||
// Read back reply immediately
|
// Read back reply immediately
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
do {
|
do {
|
||||||
bytesRead = read(serialPort, reinterpret_cast<void*>(recBuf.data()),
|
bytesRead = read(serialPort, reinterpret_cast<void*>(recBuf.data()),
|
||||||
static_cast<unsigned int>(recBuf.size()));
|
static_cast<unsigned int>(recBuf.size()));
|
||||||
if (bytesRead < 0) {
|
if (bytesRead == 0) {
|
||||||
sif::warning << "UartTestClass::performPeriodicAction: read call failed with error [" << errno
|
sif::warning << "UartTestClass::scexSimplePeriodic: Reading SCEX: Timeout or no bytes read"
|
||||||
|
<< std::endl;
|
||||||
|
} else if (bytesRead < 0) {
|
||||||
|
sif::warning << "UartTestClass::scexSimplePeriodic: read call failed with error [" << errno
|
||||||
<< ", " << strerror(errno) << "]" << std::endl;
|
<< ", " << strerror(errno) << "]" << std::endl;
|
||||||
break;
|
break;
|
||||||
} else if (bytesRead >= static_cast<int>(recBuf.size())) {
|
} else if (bytesRead >= static_cast<int>(recBuf.size())) {
|
||||||
sif::debug << "UartTestClass::performPeriodicAction: recv buffer might not be large enough"
|
sif::debug << "UartTestClass::scexSimplePeriodic: recv buffer might not be large "
|
||||||
<< std::endl;
|
"enough, bytes read:"
|
||||||
|
<< bytesRead << std::endl;
|
||||||
} else if (bytesRead > 0) {
|
} else if (bytesRead > 0) {
|
||||||
sif::info << "Received " << bytesRead
|
dleParser->passData(recBuf.data(), bytesRead);
|
||||||
<< " bytes from the Solar Cell Experiment:" << std::endl;
|
if (currCmd == Cmds::PING) {
|
||||||
arrayprinter::print(recBuf.data(), bytesRead, OutputType::HEX, false);
|
cmdDone = true;
|
||||||
|
cmdSent = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while (bytesRead > 0);
|
} while (bytesRead > 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int UartTestClass::prepareScexPing() {
|
int UartTestClass::prepareScexCmd(scex::Cmds cmd, bool tempCheck, uint8_t* cmdBuf, size_t* len) {
|
||||||
std::array<uint8_t, 128> tmpCmdBuf = {};
|
using namespace scex;
|
||||||
// Send ping command
|
// Send command
|
||||||
tmpCmdBuf[0] = scex::CMD_PING;
|
cmdBuf[0] = scex::createCmdByte(cmd, false);
|
||||||
// These two fields are the packet counter and the total packet count. Those are 1 and 1 for each
|
// These two fields are the packet counter and the total packet count. Those are 1 and 1 for each
|
||||||
// telecommand so far
|
// telecommand so far
|
||||||
tmpCmdBuf[1] = 1;
|
cmdBuf[1] = 1;
|
||||||
tmpCmdBuf[2] = 1;
|
cmdBuf[2] = 1;
|
||||||
uint16_t userDataLen = 0;
|
uint16_t userDataLen = 0;
|
||||||
tmpCmdBuf[3] = (userDataLen >> 8) & 0xff;
|
cmdBuf[3] = (userDataLen >> 8) & 0xff;
|
||||||
tmpCmdBuf[4] = userDataLen & 0xff;
|
cmdBuf[4] = userDataLen & 0xff;
|
||||||
uint16_t crc = CRC::crc16ccitt(tmpCmdBuf.data(), 5);
|
uint16_t crc = CRC::crc16ccitt(cmdBuf, 5);
|
||||||
tmpCmdBuf[5] = (crc >> 8) & 0xff;
|
cmdBuf[5] = (crc >> 8) & 0xff;
|
||||||
tmpCmdBuf[6] = crc & 0xff;
|
cmdBuf[6] = crc & 0xff;
|
||||||
ReturnValue_t result =
|
*len = 7;
|
||||||
dleEncoder.encode(tmpCmdBuf.data(), 7, cmdBuf.data(), cmdBuf.size(), &encodedLen, true);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
sif::warning << "UartTestClass::scexInit: Encoding failed" << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UartTestClass::handleFoundDlePacket(uint8_t* packet, size_t len) {
|
||||||
|
sif::info << "UartTestClass::handleFoundDlePacket: Detected DLE encoded packet with decoded size "
|
||||||
|
<< len << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string UartTestClass::random_string(std::string::size_type length) {
|
||||||
|
static auto& chrs =
|
||||||
|
"0123456789"
|
||||||
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
|
||||||
|
thread_local static std::mt19937 rg{std::random_device{}()};
|
||||||
|
thread_local static std::uniform_int_distribution<std::string::size_type> pick(0,
|
||||||
|
sizeof(chrs) - 2);
|
||||||
|
|
||||||
|
std::string s;
|
||||||
|
|
||||||
|
s.reserve(length);
|
||||||
|
|
||||||
|
while (length--) s += chrs[pick(rg)];
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
#ifndef LINUX_BOARDTEST_UARTTESTCLASS_H_
|
#ifndef LINUX_BOARDTEST_UARTTESTCLASS_H_
|
||||||
#define LINUX_BOARDTEST_UARTTESTCLASS_H_
|
#define LINUX_BOARDTEST_UARTTESTCLASS_H_
|
||||||
|
|
||||||
|
#include <fsfw/container/SimpleRingBuffer.h>
|
||||||
#include <fsfw/globalfunctions/DleEncoder.h>
|
#include <fsfw/globalfunctions/DleEncoder.h>
|
||||||
|
#include <fsfw/globalfunctions/DleParser.h>
|
||||||
|
#include <fsfw/timemanager/Countdown.h>
|
||||||
|
#include <fsfw_hal/linux/uart/UartCookie.h>
|
||||||
#include <termios.h> // Contains POSIX terminal control definitions
|
#include <termios.h> // Contains POSIX terminal control definitions
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "lwgps/lwgps.h"
|
#include "lwgps/lwgps.h"
|
||||||
|
#include "mission/devices/devicedefinitions/ScexDefinitions.h"
|
||||||
#include "test/testtasks/TestTask.h"
|
#include "test/testtasks/TestTask.h"
|
||||||
|
|
||||||
|
class ScexUartReader;
|
||||||
|
class ScexDleParser;
|
||||||
|
|
||||||
class UartTestClass : public TestTask {
|
class UartTestClass : public TestTask {
|
||||||
public:
|
public:
|
||||||
UartTestClass(object_id_t objectId);
|
UartTestClass(object_id_t objectId);
|
||||||
@ -24,20 +32,42 @@ class UartTestClass : public TestTask {
|
|||||||
SCEX
|
SCEX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ScexModes { SIMPLE, READER_TASK } scexMode;
|
||||||
|
|
||||||
void gpsInit();
|
void gpsInit();
|
||||||
void gpsPeriodic();
|
void gpsPeriodic();
|
||||||
|
|
||||||
void scexInit();
|
void scexInit();
|
||||||
void scexPeriodic();
|
void scexPeriodic();
|
||||||
int prepareScexPing();
|
int prepareScexCmd(scex::Cmds cmd, bool tempCheck, uint8_t* cmdBuf, size_t* len);
|
||||||
|
|
||||||
|
void scexSimplePeriodic();
|
||||||
|
void scexSimpleInit();
|
||||||
|
|
||||||
|
static void foundDlePacketHandler(const DleParser::Context& ctx);
|
||||||
|
void handleFoundDlePacket(uint8_t* packet, size_t len);
|
||||||
|
std::string random_string(std::string::size_type length);
|
||||||
|
|
||||||
|
std::string fileId = "";
|
||||||
|
std::string fileName = "";
|
||||||
|
bool fileNameSet = false;
|
||||||
|
Countdown finishCountdown = Countdown(180 * 1000);
|
||||||
|
bool cmdSent = false;
|
||||||
|
bool cmdDone = false;
|
||||||
|
scex::Cmds currCmd = scex::Cmds::PING;
|
||||||
TestModes mode = TestModes::GPS;
|
TestModes mode = TestModes::GPS;
|
||||||
DleEncoder dleEncoder = DleEncoder();
|
DleEncoder dleEncoder = DleEncoder();
|
||||||
|
UartCookie* uartCookie = nullptr;
|
||||||
size_t encodedLen = 0;
|
size_t encodedLen = 0;
|
||||||
lwgps_t gpsData = {};
|
lwgps_t gpsData = {};
|
||||||
struct termios tty = {};
|
struct termios tty = {};
|
||||||
int serialPort = 0;
|
int serialPort = 0;
|
||||||
|
bool startFound = false;
|
||||||
|
ScexUartReader* reader = nullptr;
|
||||||
std::array<uint8_t, 64> cmdBuf = {};
|
std::array<uint8_t, 64> cmdBuf = {};
|
||||||
std::array<uint8_t, 4096> recBuf = {};
|
std::array<uint8_t, 4096> recBuf = {};
|
||||||
|
ScexDleParser* dleParser;
|
||||||
|
scex::Cmds cmdHelper = scex::Cmds::INVALID;
|
||||||
uint8_t recvCnt = 0;
|
uint8_t recvCnt = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,7 +2,9 @@ if(EIVE_BUILD_GPSD_GPS_HANDLER)
|
|||||||
target_sources(${OBSW_NAME} PRIVATE GPSHyperionLinuxController.cpp)
|
target_sources(${OBSW_NAME} PRIVATE GPSHyperionLinuxController.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_sources(${OBSW_NAME} PRIVATE Max31865RtdLowlevelHandler.cpp)
|
target_sources(
|
||||||
|
${OBSW_NAME} PRIVATE Max31865RtdLowlevelHandler.cpp ScexUartReader.cpp
|
||||||
|
ScexDleParser.cpp ScexHelper.cpp)
|
||||||
|
|
||||||
add_subdirectory(ploc)
|
add_subdirectory(ploc)
|
||||||
add_subdirectory(startracker)
|
add_subdirectory(startracker)
|
||||||
|
7
linux/devices/ScexDleParser.cpp
Normal file
7
linux/devices/ScexDleParser.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "ScexDleParser.h"
|
||||||
|
|
||||||
|
ScexDleParser::ScexDleParser(SimpleRingBuffer &decodeRingBuf, DleEncoder &decoder,
|
||||||
|
BufPair encodedBuf, BufPair decodedBuf)
|
||||||
|
: DleParser(decodeRingBuf, decoder, encodedBuf, decodedBuf){};
|
||||||
|
|
||||||
|
ScexDleParser::~ScexDleParser(){};
|
13
linux/devices/ScexDleParser.h
Normal file
13
linux/devices/ScexDleParser.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fsfw/globalfunctions/DleParser.h>
|
||||||
|
|
||||||
|
class ScexDleParser : public DleParser {
|
||||||
|
public:
|
||||||
|
ScexDleParser(SimpleRingBuffer &decodeRingBuf, DleEncoder &decoder, BufPair encodedBuf,
|
||||||
|
BufPair decodedBuf);
|
||||||
|
|
||||||
|
virtual ~ScexDleParser();
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
86
linux/devices/ScexHelper.cpp
Normal file
86
linux/devices/ScexHelper.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include "ScexHelper.h"
|
||||||
|
|
||||||
|
#include <fsfw/globalfunctions/CRC.h>
|
||||||
|
|
||||||
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
|
using namespace returnvalue;
|
||||||
|
|
||||||
|
ScexHelper::ScexHelper() {}
|
||||||
|
|
||||||
|
ReturnValue_t ScexHelper::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||||
|
Endianness streamEndianness) const {
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ScexHelper::getSerializedSize() const { return totalPacketLen; }
|
||||||
|
|
||||||
|
ReturnValue_t ScexHelper::deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
|
Endianness streamEndianness) {
|
||||||
|
if (buffer == nullptr or size == nullptr) {
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
if (*size < 7) {
|
||||||
|
return STREAM_TOO_SHORT;
|
||||||
|
}
|
||||||
|
start = *buffer;
|
||||||
|
cmdByteRaw = **buffer;
|
||||||
|
cmd = static_cast<scex::Cmds>((cmdByteRaw >> 1) & 0b11111);
|
||||||
|
|
||||||
|
*buffer += 1;
|
||||||
|
packetCounter = **buffer;
|
||||||
|
|
||||||
|
*buffer += 1;
|
||||||
|
totalPacketCounter = **buffer;
|
||||||
|
|
||||||
|
*buffer += 1;
|
||||||
|
payloadLen = (**buffer << 8) | *(*buffer + 1);
|
||||||
|
|
||||||
|
*buffer += 2;
|
||||||
|
payloadStart = *buffer;
|
||||||
|
totalPacketLen = payloadLen + scex::HEADER_LEN + scex::CRC_LEN;
|
||||||
|
if (totalPacketLen >= *size) {
|
||||||
|
return STREAM_TOO_SHORT;
|
||||||
|
}
|
||||||
|
*buffer += payloadLen;
|
||||||
|
crc = (**buffer << 8) | *(*buffer + 1);
|
||||||
|
if (CRC::crc16ccitt(start, totalPacketLen) != 0) {
|
||||||
|
return INVALID_CRC;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
scex::Cmds ScexHelper::getCmd() const { return cmd; }
|
||||||
|
|
||||||
|
uint8_t ScexHelper::getCmdByteRaw() const { return cmdByteRaw; }
|
||||||
|
|
||||||
|
uint16_t ScexHelper::getCrc() const { return crc; }
|
||||||
|
|
||||||
|
size_t ScexHelper::getExpectedPacketLen() const { return totalPacketLen; }
|
||||||
|
|
||||||
|
uint8_t ScexHelper::getPacketCounter() const { return packetCounter; }
|
||||||
|
|
||||||
|
uint16_t ScexHelper::getPayloadLen() const { return payloadLen; }
|
||||||
|
|
||||||
|
const uint8_t* ScexHelper::getStart() const { return start; }
|
||||||
|
|
||||||
|
uint8_t ScexHelper::getTotalPacketCounter() const { return totalPacketCounter; }
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const ScexHelper& h) {
|
||||||
|
using namespace std;
|
||||||
|
sif::info << "Command Byte Raw: 0x" << std::setw(2) << std::setfill('0') << std::hex
|
||||||
|
<< (int)h.cmdByteRaw << " | Command: 0x" << std::setw(2) << std::setfill('0')
|
||||||
|
<< std::hex << static_cast<int>(h.cmd) << std::dec << std::endl;
|
||||||
|
sif::info << "PacketCounter: " << h.packetCounter << endl;
|
||||||
|
sif::info << "TotalPacketCount: " << h.totalPacketCounter << endl;
|
||||||
|
sif::info << "PayloadLength: " << h.payloadLen << endl;
|
||||||
|
sif::info << "TotalPacketLength: " << h.totalPacketLen;
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ofstream& operator<<(std::ofstream& of, const ScexHelper& h) {
|
||||||
|
of.write(reinterpret_cast<const char*>(h.start), h.getSerializedSize());
|
||||||
|
|
||||||
|
return of;
|
||||||
|
}
|
46
linux/devices/ScexHelper.h
Normal file
46
linux/devices/ScexHelper.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef LINUX_DEVICES_SCEXHELPER_H_
|
||||||
|
#define LINUX_DEVICES_SCEXHELPER_H_
|
||||||
|
#include <fsfw/serialize/SerializeIF.h>
|
||||||
|
#include <mission/devices/devicedefinitions/ScexDefinitions.h>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class ScexHelper : public SerializeIF {
|
||||||
|
public:
|
||||||
|
static const ReturnValue_t INVALID_CRC = returnvalue::makeCode(0, 2);
|
||||||
|
|
||||||
|
ScexHelper();
|
||||||
|
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
|
Endianness streamEndianness) const override;
|
||||||
|
|
||||||
|
size_t getSerializedSize() const override;
|
||||||
|
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||||
|
Endianness streamEndianness = Endianness::BIG) override;
|
||||||
|
friend std::ostream &operator<<(std::ostream &os, const ScexHelper &h);
|
||||||
|
friend std::ofstream &operator<<(std::ofstream &os, const ScexHelper &h);
|
||||||
|
|
||||||
|
scex::Cmds getCmd() const;
|
||||||
|
uint8_t getCmdByteRaw() const;
|
||||||
|
uint16_t getCrc() const;
|
||||||
|
size_t getExpectedPacketLen() const;
|
||||||
|
uint8_t getPacketCounter() const;
|
||||||
|
uint16_t getPayloadLen() const;
|
||||||
|
const uint8_t *getStart() const;
|
||||||
|
uint8_t getTotalPacketCounter() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const uint8_t *start = nullptr;
|
||||||
|
uint16_t crc = 0;
|
||||||
|
uint8_t cmdByteRaw = 0;
|
||||||
|
scex::Cmds cmd = scex::Cmds::INVALID;
|
||||||
|
int packetCounter = 0;
|
||||||
|
int totalPacketCounter = 0;
|
||||||
|
uint16_t payloadLen = 0;
|
||||||
|
const uint8_t *payloadStart = 0;
|
||||||
|
size_t totalPacketLen = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* LINUX_DEVICES_SCEXHELPER_H_ */
|
236
linux/devices/ScexUartReader.cpp
Normal file
236
linux/devices/ScexUartReader.cpp
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
#include "ScexUartReader.h"
|
||||||
|
|
||||||
|
#include <fcntl.h> // Contains file controls like O_RDWR
|
||||||
|
#include <fsfw/globalfunctions/arrayprinter.h>
|
||||||
|
#include <fsfw/ipc/MutexFactory.h>
|
||||||
|
#include <fsfw/ipc/MutexGuard.h>
|
||||||
|
#include <fsfw/tasks/SemaphoreFactory.h>
|
||||||
|
#include <fsfw/tasks/TaskFactory.h>
|
||||||
|
#include <fsfw_hal/linux/uart/UartCookie.h>
|
||||||
|
#include <unistd.h> // write(), read(), close()
|
||||||
|
|
||||||
|
#include <cerrno> // Error integer and strerror() function
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "OBSWConfig.h"
|
||||||
|
|
||||||
|
using namespace returnvalue;
|
||||||
|
|
||||||
|
ScexUartReader::ScexUartReader(object_id_t objectId)
|
||||||
|
: SystemObject(objectId),
|
||||||
|
decodeRingBuf(4096, true),
|
||||||
|
ipcRingBuf(200 * 2048, true),
|
||||||
|
ipcQueue(200),
|
||||||
|
dleParser(decodeRingBuf, dleEncoder, {encodedBuf.data(), encodedBuf.size()},
|
||||||
|
{decodedBuf.data(), decodedBuf.size()}) {
|
||||||
|
semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
|
||||||
|
semaphore->acquire();
|
||||||
|
lock = MutexFactory::instance()->createMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ScexUartReader::performOperation(uint8_t operationCode) {
|
||||||
|
lock->lockMutex();
|
||||||
|
state = States::IDLE;
|
||||||
|
lock->unlockMutex();
|
||||||
|
while (true) {
|
||||||
|
semaphore->acquire();
|
||||||
|
int bytesRead = 0;
|
||||||
|
// debugMode = true;
|
||||||
|
while (true) {
|
||||||
|
bytesRead = read(serialPort, reinterpret_cast<void *>(recBuf.data()),
|
||||||
|
static_cast<unsigned int>(recBuf.size()));
|
||||||
|
if (bytesRead == 0) {
|
||||||
|
{
|
||||||
|
MutexGuard mg(lock);
|
||||||
|
if (state == States::FINISH) {
|
||||||
|
dleParser.reset();
|
||||||
|
// Flush received and unread data
|
||||||
|
tcflush(serialPort, TCIOFLUSH);
|
||||||
|
state = States::IDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ReturnValue_t result = returnvalue::OK;
|
||||||
|
// Can be used to read frame, parity and overrun errors
|
||||||
|
// serial_icounter_struct icounter{};
|
||||||
|
// uart::readCountersAndErrors(serialPort, icounter);
|
||||||
|
while (result != DleParser::NO_PACKET_FOUND) {
|
||||||
|
result = tryDleParsing();
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskFactory::delayTask(400);
|
||||||
|
} else if (bytesRead < 0) {
|
||||||
|
sif::warning << "ScexUartReader::performOperation: read call failed with error [" << errno
|
||||||
|
<< ", " << strerror(errno) << "]" << std::endl;
|
||||||
|
break;
|
||||||
|
} else if (bytesRead >= static_cast<int>(recBuf.size())) {
|
||||||
|
sif::error << "ScexUartReader::performOperation: Receive buffer too small for " << bytesRead
|
||||||
|
<< " bytes" << std::endl;
|
||||||
|
} else if (bytesRead > 0) {
|
||||||
|
if (debugMode) {
|
||||||
|
sif::info << "Received " << bytesRead
|
||||||
|
<< " bytes from the Solar Cell Experiment:" << std::endl;
|
||||||
|
}
|
||||||
|
ReturnValue_t result = dleParser.passData(recBuf.data(), bytesRead);
|
||||||
|
if (result != OK) {
|
||||||
|
sif::warning << "ScexUartReader::performOperation: Passing data to DLE parser failed"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
result = tryDleParsing();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ScexUartReader::initializeInterface(CookieIF *cookie) {
|
||||||
|
UartCookie *uartCookie = dynamic_cast<UartCookie *>(cookie);
|
||||||
|
if (uartCookie == nullptr) {
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
std::string devname = uartCookie->getDeviceFile();
|
||||||
|
/* Get file descriptor */
|
||||||
|
serialPort = open(devname.c_str(), O_RDWR);
|
||||||
|
if (serialPort < 0) {
|
||||||
|
sif::warning << "ScexUartReader::initializeInterface: open call failed with error [" << errno
|
||||||
|
<< ", " << strerror(errno) << std::endl;
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
// Setting up UART parameters
|
||||||
|
tty.c_cflag &= ~PARENB; // Clear parity bit
|
||||||
|
if (uartCookie->getStopBits() == StopBits::TWO_STOP_BITS) {
|
||||||
|
// Use two stop bits
|
||||||
|
tty.c_cflag |= CSTOPB;
|
||||||
|
} else {
|
||||||
|
// Clear stop field, only one stop bit used in communication
|
||||||
|
tty.c_cflag &= ~CSTOPB;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty.c_cflag &= ~CSIZE; // Clear all the size bits
|
||||||
|
tty.c_cflag |= CS8; // 8 bits per byte
|
||||||
|
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control
|
||||||
|
tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)
|
||||||
|
|
||||||
|
// Use non-canonical mode and clear echo flag
|
||||||
|
tty.c_lflag &= ~(ICANON | ECHO);
|
||||||
|
|
||||||
|
// Non-blocking mode, use polling
|
||||||
|
tty.c_cc[VTIME] = 0;
|
||||||
|
tty.c_cc[VMIN] = 0;
|
||||||
|
|
||||||
|
// The SCEX experiment has a fixed baud rate.
|
||||||
|
if (cfsetispeed(&tty, B38400) != 0) {
|
||||||
|
sif::warning << "ScexUartReader::initializeInterface: Setting baud rate failed" << std::endl;
|
||||||
|
}
|
||||||
|
if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
|
||||||
|
sif::warning << "ScexUartReader::initializeInterface: tcsetattr call failed with error ["
|
||||||
|
<< errno << ", " << strerror(errno) << std::endl;
|
||||||
|
}
|
||||||
|
// Flush received and unread data
|
||||||
|
tcflush(serialPort, TCIOFLUSH);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ScexUartReader::sendMessage(CookieIF *cookie, const uint8_t *sendData,
|
||||||
|
size_t sendLen) {
|
||||||
|
ReturnValue_t result;
|
||||||
|
if (sendData == nullptr or sendLen == 0) {
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
lock->lockMutex();
|
||||||
|
if (state == States::NOT_READY or state == States::RUNNING) {
|
||||||
|
lock->unlockMutex();
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
tcflush(serialPort, TCIFLUSH);
|
||||||
|
state = States::RUNNING;
|
||||||
|
lock->unlockMutex();
|
||||||
|
|
||||||
|
result = semaphore->release();
|
||||||
|
if (result != OK) {
|
||||||
|
std::cout << "ScexUartReader::sendMessage: Releasing semaphore failed" << std::endl;
|
||||||
|
}
|
||||||
|
size_t encodedLen = 0;
|
||||||
|
result = dleEncoder.encode(sendData, sendLen, cmdbuf.data(), cmdbuf.size(), &encodedLen, true);
|
||||||
|
if (result != OK) {
|
||||||
|
sif::warning << "ScexUartReader::sendMessage: Encoding failed" << std::endl;
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
size_t bytesWritten = write(serialPort, cmdbuf.data(), encodedLen);
|
||||||
|
if (bytesWritten != encodedLen) {
|
||||||
|
sif::warning << "ScexUartReader::sendMessage: Sending ping command to solar experiment failed"
|
||||||
|
<< std::endl;
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ScexUartReader::getSendSuccess(CookieIF *cookie) { return OK; }
|
||||||
|
|
||||||
|
ReturnValue_t ScexUartReader::requestReceiveMessage(CookieIF *cookie, size_t requestLen) {
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScexUartReader::setDebugMode(bool enable) { this->debugMode = enable; }
|
||||||
|
|
||||||
|
ReturnValue_t ScexUartReader::finish() {
|
||||||
|
MutexGuard mg(lock);
|
||||||
|
if (state == States::IDLE) {
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
state = States::FINISH;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScexUartReader::handleFoundDlePacket(uint8_t *packet, size_t len) {
|
||||||
|
MutexGuard mg(lock);
|
||||||
|
ReturnValue_t result = ipcQueue.insert(len);
|
||||||
|
if (result != OK) {
|
||||||
|
sif::warning << "ScexUartReader::handleFoundDlePacket: IPCQueue error" << std::endl;
|
||||||
|
}
|
||||||
|
result = ipcRingBuf.writeData(packet, len);
|
||||||
|
if (result != OK) {
|
||||||
|
sif::warning << "ScexUartReader::handleFoundDlePacket: IPCRingBuf error" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ScexUartReader::tryDleParsing() {
|
||||||
|
size_t bytesRead = 0;
|
||||||
|
ReturnValue_t result = dleParser.parseRingBuf(bytesRead);
|
||||||
|
if (result == returnvalue::OK) {
|
||||||
|
// Packet found, advance read pointer.
|
||||||
|
auto &decodedPacket = dleParser.getContext().decodedPacket;
|
||||||
|
handleFoundDlePacket(decodedPacket.first, decodedPacket.second);
|
||||||
|
dleParser.confirmBytesRead(bytesRead);
|
||||||
|
} else if (result != DleParser::NO_PACKET_FOUND) {
|
||||||
|
sif::warning << "ScexUartReader::performOperation: Possible packet loss" << std::endl;
|
||||||
|
// Markers found at wrong place
|
||||||
|
// which might be a hint for a possibly lost packet.
|
||||||
|
dleParser.defaultErrorHandler();
|
||||||
|
dleParser.confirmBytesRead(bytesRead);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScexUartReader::reset() {
|
||||||
|
lock->lockMutex();
|
||||||
|
state = States::FINISH;
|
||||||
|
lock->unlockMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ScexUartReader::readReceivedMessage(CookieIF *cookie, uint8_t **buffer,
|
||||||
|
size_t *size) {
|
||||||
|
MutexGuard mg(lock);
|
||||||
|
if (ipcQueue.empty()) {
|
||||||
|
*size = 0;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
ipcQueue.retrieve(size);
|
||||||
|
*buffer = ipcBuffer.data();
|
||||||
|
ReturnValue_t result = ipcRingBuf.readData(ipcBuffer.data(), *size, true);
|
||||||
|
if (result != OK) {
|
||||||
|
sif::warning << "ScexUartReader::readReceivedMessage: Reading RingBuffer failed" << std::endl;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
61
linux/devices/ScexUartReader.h
Normal file
61
linux/devices/ScexUartReader.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fsfw/container/DynamicFIFO.h>
|
||||||
|
#include <fsfw/container/SimpleRingBuffer.h>
|
||||||
|
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
||||||
|
#include <fsfw/globalfunctions/DleEncoder.h>
|
||||||
|
#include <fsfw/objectmanager/SystemObject.h>
|
||||||
|
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||||
|
#include <fsfw/timemanager/Countdown.h>
|
||||||
|
#include <linux/devices/ScexDleParser.h>
|
||||||
|
#include <termios.h> // Contains POSIX terminal control definitions
|
||||||
|
|
||||||
|
class SemaphoreIF;
|
||||||
|
class MutexIF;
|
||||||
|
|
||||||
|
class ScexUartReader : public SystemObject,
|
||||||
|
public ExecutableObjectIF,
|
||||||
|
public DeviceCommunicationIF {
|
||||||
|
friend class UartTestClass;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum class States { NOT_READY, IDLE, RUNNING, FINISH };
|
||||||
|
ScexUartReader(object_id_t objectId);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
ReturnValue_t finish();
|
||||||
|
void setDebugMode(bool enable);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SemaphoreIF *semaphore;
|
||||||
|
bool debugMode = false;
|
||||||
|
MutexIF *lock;
|
||||||
|
int serialPort = 0;
|
||||||
|
States state = States::IDLE;
|
||||||
|
struct termios tty = {};
|
||||||
|
bool doFinish = false;
|
||||||
|
DleEncoder dleEncoder = DleEncoder();
|
||||||
|
SimpleRingBuffer decodeRingBuf;
|
||||||
|
|
||||||
|
std::array<uint8_t, 256> cmdbuf = {};
|
||||||
|
std::array<uint8_t, 4096> recBuf = {};
|
||||||
|
std::array<uint8_t, 4096> encodedBuf = {};
|
||||||
|
std::array<uint8_t, 4096> decodedBuf = {};
|
||||||
|
std::array<uint8_t, 4096> ipcBuffer = {};
|
||||||
|
SimpleRingBuffer ipcRingBuf;
|
||||||
|
DynamicFIFO<size_t> ipcQueue;
|
||||||
|
ScexDleParser dleParser;
|
||||||
|
|
||||||
|
static void foundDlePacketHandler(const DleParser::Context &ctx);
|
||||||
|
void handleFoundDlePacket(uint8_t *packet, size_t len);
|
||||||
|
ReturnValue_t tryDleParsing();
|
||||||
|
|
||||||
|
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||||
|
|
||||||
|
// DeviceCommunicationIF implementation
|
||||||
|
ReturnValue_t initializeInterface(CookieIF *cookie) override;
|
||||||
|
ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) override;
|
||||||
|
ReturnValue_t getSendSuccess(CookieIF *cookie) override;
|
||||||
|
ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) override;
|
||||||
|
ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) override;
|
||||||
|
};
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 222 translations.
|
* @brief Auto-generated event translation file. Contains 225 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2022-10-10 10:15:22
|
* Generated on: 2022-10-10 11:15:49
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
@ -218,6 +218,9 @@ const char *ALLOC_FAILURE_STRING = "ALLOC_FAILURE";
|
|||||||
const char *REBOOT_SW_STRING = "REBOOT_SW";
|
const char *REBOOT_SW_STRING = "REBOOT_SW";
|
||||||
const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED";
|
const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED";
|
||||||
const char *REBOOT_HW_STRING = "REBOOT_HW";
|
const char *REBOOT_HW_STRING = "REBOOT_HW";
|
||||||
|
const char *MISSING_PACKET_STRING = "MISSING_PACKET";
|
||||||
|
const char *EXPERIMENT_TIMEDOUT_STRING = "EXPERIMENT_TIMEDOUT";
|
||||||
|
const char *MULTI_PACKET_COMMAND_DONE_STRING = "MULTI_PACKET_COMMAND_DONE";
|
||||||
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
|
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
|
||||||
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
|
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
|
||||||
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
|
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
|
||||||
@ -652,15 +655,21 @@ const char *translateEvents(Event event) {
|
|||||||
return REBOOT_MECHANISM_TRIGGERED_STRING;
|
return REBOOT_MECHANISM_TRIGGERED_STRING;
|
||||||
case (13703):
|
case (13703):
|
||||||
return REBOOT_HW_STRING;
|
return REBOOT_HW_STRING;
|
||||||
|
case (13800):
|
||||||
|
return MISSING_PACKET_STRING;
|
||||||
case (13801):
|
case (13801):
|
||||||
return SET_CONFIGFILEVALUE_FAILED_STRING;
|
return EXPERIMENT_TIMEDOUT_STRING;
|
||||||
case (13802):
|
case (13802):
|
||||||
|
return MULTI_PACKET_COMMAND_DONE_STRING;
|
||||||
|
case (13901):
|
||||||
|
return SET_CONFIGFILEVALUE_FAILED_STRING;
|
||||||
|
case (13902):
|
||||||
return GET_CONFIGFILEVALUE_FAILED_STRING;
|
return GET_CONFIGFILEVALUE_FAILED_STRING;
|
||||||
case (13803):
|
case (13903):
|
||||||
return INSERT_CONFIGFILEVALUE_FAILED_STRING;
|
return INSERT_CONFIGFILEVALUE_FAILED_STRING;
|
||||||
case (13804):
|
case (13904):
|
||||||
return WRITE_CONFIGFILE_FAILED_STRING;
|
return WRITE_CONFIGFILE_FAILED_STRING;
|
||||||
case (13805):
|
case (13905):
|
||||||
return READ_CONFIGFILE_FAILED_STRING;
|
return READ_CONFIGFILE_FAILED_STRING;
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN_EVENT";
|
return "UNKNOWN_EVENT";
|
||||||
|
@ -49,6 +49,9 @@ enum sourceObjects : uint32_t {
|
|||||||
UART_COM_IF = 0x49030003,
|
UART_COM_IF = 0x49030003,
|
||||||
SPI_MAIN_COM_IF = 0x49020004,
|
SPI_MAIN_COM_IF = 0x49020004,
|
||||||
GPIO_IF = 0x49010005,
|
GPIO_IF = 0x49010005,
|
||||||
|
SCEX_UART_READER = 0x49010006,
|
||||||
|
|
||||||
|
/* Custom device handler */
|
||||||
SPI_RW_COM_IF = 0x49020005,
|
SPI_RW_COM_IF = 0x49020005,
|
||||||
|
|
||||||
/* 0x54 ('T') for test handlers */
|
/* 0x54 ('T') for test handlers */
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 136 translations.
|
* Contains 138 translations.
|
||||||
* Generated on: 2022-10-10 10:15:22
|
* Generated on: 2022-10-10 11:15:49
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
@ -55,6 +55,7 @@ const char *PTME_CONFIG_STRING = "PTME_CONFIG";
|
|||||||
const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER";
|
const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER";
|
||||||
const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER";
|
const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER";
|
||||||
const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER";
|
const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER";
|
||||||
|
const char *SCEX_STRING = "SCEX";
|
||||||
const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER";
|
const char *SOLAR_ARRAY_DEPL_HANDLER_STRING = "SOLAR_ARRAY_DEPL_HANDLER";
|
||||||
const char *HEATER_HANDLER_STRING = "HEATER_HANDLER";
|
const char *HEATER_HANDLER_STRING = "HEATER_HANDLER";
|
||||||
const char *TMP1075_HANDLER_1_STRING = "TMP1075_HANDLER_1";
|
const char *TMP1075_HANDLER_1_STRING = "TMP1075_HANDLER_1";
|
||||||
@ -78,6 +79,7 @@ const char *RTD_15_IC18_IMTQ_STRING = "RTD_15_IC18_IMTQ";
|
|||||||
const char *SYRLINKS_HK_HANDLER_STRING = "SYRLINKS_HK_HANDLER";
|
const char *SYRLINKS_HK_HANDLER_STRING = "SYRLINKS_HK_HANDLER";
|
||||||
const char *ARDUINO_COM_IF_STRING = "ARDUINO_COM_IF";
|
const char *ARDUINO_COM_IF_STRING = "ARDUINO_COM_IF";
|
||||||
const char *GPIO_IF_STRING = "GPIO_IF";
|
const char *GPIO_IF_STRING = "GPIO_IF";
|
||||||
|
const char *SCEX_UART_READER_STRING = "SCEX_UART_READER";
|
||||||
const char *SPI_MAIN_COM_IF_STRING = "SPI_MAIN_COM_IF";
|
const char *SPI_MAIN_COM_IF_STRING = "SPI_MAIN_COM_IF";
|
||||||
const char *SPI_RW_COM_IF_STRING = "SPI_RW_COM_IF";
|
const char *SPI_RW_COM_IF_STRING = "SPI_RW_COM_IF";
|
||||||
const char *SPI_RTD_COM_IF_STRING = "SPI_RTD_COM_IF";
|
const char *SPI_RTD_COM_IF_STRING = "SPI_RTD_COM_IF";
|
||||||
@ -243,6 +245,8 @@ const char *translateObject(object_id_t object) {
|
|||||||
return PLOC_SUPERVISOR_HANDLER_STRING;
|
return PLOC_SUPERVISOR_HANDLER_STRING;
|
||||||
case 0x44330017:
|
case 0x44330017:
|
||||||
return PLOC_SUPERVISOR_HELPER_STRING;
|
return PLOC_SUPERVISOR_HELPER_STRING;
|
||||||
|
case 0x44330032:
|
||||||
|
return SCEX_STRING;
|
||||||
case 0x444100A2:
|
case 0x444100A2:
|
||||||
return SOLAR_ARRAY_DEPL_HANDLER_STRING;
|
return SOLAR_ARRAY_DEPL_HANDLER_STRING;
|
||||||
case 0x444100A4:
|
case 0x444100A4:
|
||||||
@ -289,6 +293,8 @@ const char *translateObject(object_id_t object) {
|
|||||||
return ARDUINO_COM_IF_STRING;
|
return ARDUINO_COM_IF_STRING;
|
||||||
case 0x49010005:
|
case 0x49010005:
|
||||||
return GPIO_IF_STRING;
|
return GPIO_IF_STRING;
|
||||||
|
case 0x49010006:
|
||||||
|
return SCEX_UART_READER_STRING;
|
||||||
case 0x49020004:
|
case 0x49020004:
|
||||||
return SPI_MAIN_COM_IF_STRING;
|
return SPI_MAIN_COM_IF_STRING;
|
||||||
case 0x49020005:
|
case 0x49020005:
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "OBSWConfig.h"
|
||||||
#include "fsfw/ipc/QueueFactory.h"
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
@ -19,4 +19,7 @@ target_sources(
|
|||||||
max1227.cpp
|
max1227.cpp
|
||||||
SusHandler.cpp
|
SusHandler.cpp
|
||||||
PayloadPcduHandler.cpp
|
PayloadPcduHandler.cpp
|
||||||
SolarArrayDeploymentHandler.cpp)
|
SolarArrayDeploymentHandler.cpp
|
||||||
|
ScexDeviceHandler.cpp)
|
||||||
|
|
||||||
|
add_subdirectory(devicedefinitions)
|
||||||
|
@ -20,7 +20,7 @@ IMTQHandler::IMTQHandler(object_id_t objectId, object_id_t comIF, CookieIF* comC
|
|||||||
posZselfTestDataset(this),
|
posZselfTestDataset(this),
|
||||||
negZselfTestDataset(this),
|
negZselfTestDataset(this),
|
||||||
switcher(pwrSwitcher) {
|
switcher(pwrSwitcher) {
|
||||||
if (comCookie == NULL) {
|
if (comCookie == nullptr) {
|
||||||
sif::error << "IMTQHandler: Invalid com cookie" << std::endl;
|
sif::error << "IMTQHandler: Invalid com cookie" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -491,8 +491,8 @@ void PayloadPcduHandler::checkAdcValues() {
|
|||||||
|
|
||||||
void PayloadPcduHandler::checkJsonFileInit() {
|
void PayloadPcduHandler::checkJsonFileInit() {
|
||||||
if (not jsonFileInitComplete) {
|
if (not jsonFileInitComplete) {
|
||||||
sd::SdCard activeSd = sdcMan->getActiveSdCard();
|
auto activeSd = sdcMan->getActiveSdCard();
|
||||||
if (sdcMan->isSdCardUsable(activeSd)) {
|
if (activeSd and sdcMan->isSdCardUsable(activeSd.value())) {
|
||||||
params.initialize(sdcMan->getCurrentMountPrefix());
|
params.initialize(sdcMan->getCurrentMountPrefix());
|
||||||
jsonFileInitComplete = true;
|
jsonFileInitComplete = true;
|
||||||
}
|
}
|
||||||
|
369
mission/devices/ScexDeviceHandler.cpp
Normal file
369
mission/devices/ScexDeviceHandler.cpp
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
#include "ScexDeviceHandler.h"
|
||||||
|
|
||||||
|
#include <linux/devices/ScexHelper.h>
|
||||||
|
#include <mission/memory/SdCardMountedIF.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <ctime>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
#include "fsfw/globalfunctions/CRC.h"
|
||||||
|
#include "mission/devices/devicedefinitions/ScexDefinitions.h"
|
||||||
|
|
||||||
|
using std::ofstream;
|
||||||
|
using namespace returnvalue;
|
||||||
|
|
||||||
|
ScexDeviceHandler::ScexDeviceHandler(object_id_t objectId, ScexUartReader& reader, CookieIF* cookie,
|
||||||
|
SdCardMountedIF& sdcMan)
|
||||||
|
: DeviceHandlerBase(objectId, reader.getObjectId(), cookie), sdcMan(sdcMan), reader(reader) {}
|
||||||
|
|
||||||
|
ScexDeviceHandler::~ScexDeviceHandler() {}
|
||||||
|
|
||||||
|
void ScexDeviceHandler::doStartUp() { setMode(MODE_ON); }
|
||||||
|
|
||||||
|
void ScexDeviceHandler::doShutDown() {
|
||||||
|
reader.reset();
|
||||||
|
commandActive = false;
|
||||||
|
setMode(_MODE_POWER_DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ScexDeviceHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { return OK; }
|
||||||
|
|
||||||
|
ReturnValue_t ScexDeviceHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { return OK; }
|
||||||
|
|
||||||
|
ReturnValue_t ScexDeviceHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
||||||
|
const uint8_t* commandData,
|
||||||
|
size_t commandDataLen) {
|
||||||
|
using namespace scex;
|
||||||
|
|
||||||
|
auto cmdTyped = static_cast<scex::Cmds>(deviceCommand);
|
||||||
|
if (std::find(VALID_CMDS.begin(), VALID_CMDS.end(), deviceCommand) == VALID_CMDS.end()) {
|
||||||
|
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
bool tempCheck = false;
|
||||||
|
if (commandDataLen == 1) {
|
||||||
|
tempCheck = commandData[0];
|
||||||
|
}
|
||||||
|
if (commandActive) {
|
||||||
|
return DeviceHandlerIF::BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (deviceCommand) {
|
||||||
|
case (PING): {
|
||||||
|
finishCountdown.setTimeout(SHORT_CD);
|
||||||
|
// countdown starten
|
||||||
|
finishCountdown.resetTimer();
|
||||||
|
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen, {nullptr, 0},
|
||||||
|
tempCheck);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (EXP_STATUS_CMD): {
|
||||||
|
finishCountdown.setTimeout(SHORT_CD);
|
||||||
|
// countdown starten
|
||||||
|
finishCountdown.resetTimer();
|
||||||
|
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen, {nullptr, 0},
|
||||||
|
tempCheck);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (ION_CMD): {
|
||||||
|
finishCountdown.setTimeout(SHORT_CD);
|
||||||
|
// countdown starten
|
||||||
|
finishCountdown.resetTimer();
|
||||||
|
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen, {nullptr, 0},
|
||||||
|
tempCheck);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (TEMP_CMD): {
|
||||||
|
finishCountdown.setTimeout(SHORT_CD);
|
||||||
|
// countdown starten
|
||||||
|
finishCountdown.resetTimer();
|
||||||
|
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen, {nullptr, 0},
|
||||||
|
tempCheck);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (FRAM): {
|
||||||
|
finishCountdown.setTimeout(LONG_CD);
|
||||||
|
// countdown starten
|
||||||
|
finishCountdown.resetTimer();
|
||||||
|
if (debugMode) {
|
||||||
|
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
|
||||||
|
|
||||||
|
sif::info << "ScexDeviceHandler::buildCommandFromCommand: RemainingMillis: "
|
||||||
|
<< remainingMillis << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen,
|
||||||
|
{commandData + 1, commandDataLen - 1}, tempCheck);
|
||||||
|
updatePeriodicReply(true, deviceCommand);
|
||||||
|
finishAction(true, deviceCommand, OK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (ONE_CELL): {
|
||||||
|
finishCountdown.setTimeout(LONG_CD);
|
||||||
|
// countdown starts
|
||||||
|
finishCountdown.resetTimer();
|
||||||
|
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen,
|
||||||
|
{commandData + 1, commandDataLen - 1}, tempCheck);
|
||||||
|
updatePeriodicReply(true, deviceCommand);
|
||||||
|
finishAction(true, deviceCommand, OK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (ALL_CELLS_CMD): {
|
||||||
|
finishCountdown.setTimeout(LONG_CD);
|
||||||
|
// countdown starts
|
||||||
|
finishCountdown.resetTimer();
|
||||||
|
prepareScexCmd(cmdTyped, {cmdBuf.data(), cmdBuf.size()}, rawPacketLen,
|
||||||
|
{commandData + 1, commandDataLen - 1}, tempCheck);
|
||||||
|
finishAction(true, deviceCommand, OK);
|
||||||
|
updatePeriodicReply(true, deviceCommand);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commandActive = true;
|
||||||
|
rawPacket = cmdBuf.data();
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScexDeviceHandler::fillCommandAndReplyMap() {
|
||||||
|
insertInCommandAndReplyMap(scex::Cmds::PING, 5, nullptr, 0, false, false, 0, &finishCountdown);
|
||||||
|
insertInCommandAndReplyMap(scex::Cmds::ION_CMD, 3, nullptr, 0, false, false, 0, &finishCountdown);
|
||||||
|
insertInCommandAndReplyMap(scex::Cmds::TEMP_CMD, 3, nullptr, 0, false, false, 0,
|
||||||
|
&finishCountdown);
|
||||||
|
insertInCommandAndReplyMap(scex::Cmds::EXP_STATUS_CMD, 3, nullptr, 0, false, false, 0,
|
||||||
|
&finishCountdown);
|
||||||
|
|
||||||
|
insertInCommandAndReplyMap(scex::Cmds::ALL_CELLS_CMD, 0, nullptr, 0, true, false,
|
||||||
|
scex::Cmds::ALL_CELLS_CMD, &finishCountdown);
|
||||||
|
insertInCommandAndReplyMap(scex::Cmds::ONE_CELL, 0, nullptr, 0, true, false, scex::Cmds::ONE_CELL,
|
||||||
|
&finishCountdown);
|
||||||
|
insertInCommandAndReplyMap(scex::Cmds::FRAM, 0, nullptr, 0, true, false, scex::Cmds::FRAM,
|
||||||
|
&finishCountdown);
|
||||||
|
|
||||||
|
insertInReplyMap(scex::Cmds::ERROR_REPLY, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ScexDeviceHandler::scanForReply(const uint8_t* start, size_t remainingSize,
|
||||||
|
DeviceCommandId_t* foundId, size_t* foundLen) {
|
||||||
|
size_t len = remainingSize;
|
||||||
|
ReturnValue_t result = helper.deSerialize(&start, &len);
|
||||||
|
|
||||||
|
if (result == ScexHelper::INVALID_CRC) {
|
||||||
|
sif::warning << "ScexDeviceHandler::scanForReply: CRC invalid" << std::endl;
|
||||||
|
*foundLen = remainingSize;
|
||||||
|
} else {
|
||||||
|
result = handleValidReply(remainingSize, foundId, foundLen);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ScexDeviceHandler::handleValidReply(size_t remSize, DeviceCommandId_t* foundId,
|
||||||
|
size_t* foundLen) {
|
||||||
|
using namespace scex;
|
||||||
|
ReturnValue_t result = OK;
|
||||||
|
|
||||||
|
switch (helper.getCmd()) {
|
||||||
|
case (FRAM): {
|
||||||
|
if (debugMode) {
|
||||||
|
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
|
||||||
|
|
||||||
|
sif::info << "ScexDeviceHandler::handleValidReply: RemMillis: " << remainingMillis
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
result = APERIODIC_REPLY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (ONE_CELL): {
|
||||||
|
result = APERIODIC_REPLY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (ALL_CELLS_CMD): {
|
||||||
|
result = APERIODIC_REPLY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*foundId = helper.getCmd();
|
||||||
|
*foundLen = remSize;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) {
|
||||||
|
using namespace scex;
|
||||||
|
|
||||||
|
ReturnValue_t status = OK;
|
||||||
|
auto oneFileHandler = [&](std::string cmdName) {
|
||||||
|
fileId = date_time_string();
|
||||||
|
std::ostringstream oss;
|
||||||
|
auto prefix = sdcMan.getCurrentMountPrefix();
|
||||||
|
oss << prefix << "/scex/scex-" << cmdName << fileId << ".bin";
|
||||||
|
fileName = oss.str();
|
||||||
|
ofstream out(fileName, ofstream::binary);
|
||||||
|
if (out.bad()) {
|
||||||
|
sif::error << "ScexDeviceHandler::interpretDeviceReply: Could not open file " << fileName
|
||||||
|
<< std::endl;
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
out << helper;
|
||||||
|
return OK;
|
||||||
|
};
|
||||||
|
auto multiFileHandler = [&](std::string cmdName) {
|
||||||
|
if ((helper.getPacketCounter() == 1) or (not fileNameSet)) {
|
||||||
|
fileId = date_time_string();
|
||||||
|
std::ostringstream oss;
|
||||||
|
auto prefix = sdcMan.getCurrentMountPrefix();
|
||||||
|
oss << prefix << "/scex/scex-" << cmdName << fileId << ".bin";
|
||||||
|
fileName = oss.str();
|
||||||
|
fileNameSet = true;
|
||||||
|
ofstream out(fileName, ofstream::binary);
|
||||||
|
if (out.bad()) {
|
||||||
|
sif::error << "ScexDeviceHandler::handleValidReply: Could not open file " << fileName
|
||||||
|
<< std::endl;
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
out << helper;
|
||||||
|
} else {
|
||||||
|
ofstream out(fileName,
|
||||||
|
ofstream::binary | ofstream::app); // append
|
||||||
|
if (out.bad()) {
|
||||||
|
sif::error << "ScexDeviceHandler::handleValidReply: Could not open file " << fileName
|
||||||
|
<< std::endl;
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
out << helper;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
};
|
||||||
|
switch (id) {
|
||||||
|
case (PING): {
|
||||||
|
status = oneFileHandler("ping_");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (ION_CMD): {
|
||||||
|
status = oneFileHandler("ion_");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (TEMP_CMD): {
|
||||||
|
status = oneFileHandler("temp_");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (EXP_STATUS_CMD): {
|
||||||
|
status = oneFileHandler("exp_status_");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (FRAM): {
|
||||||
|
status = multiFileHandler("fram_");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (ONE_CELL): {
|
||||||
|
status = multiFileHandler("one_cell_");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (ALL_CELLS_CMD): {
|
||||||
|
status = multiFileHandler("multi_cell_");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// Unknown DeviceCommand
|
||||||
|
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
if (helper.getPacketCounter() == helper.getTotalPacketCounter()) {
|
||||||
|
reader.finish();
|
||||||
|
commandActive = false;
|
||||||
|
if (id != PING) {
|
||||||
|
fileNameSet = false;
|
||||||
|
}
|
||||||
|
if (id == FRAM or id == ALL_CELLS_CMD or id == ONE_CELL) {
|
||||||
|
triggerEvent(MULTI_PACKET_COMMAND_DONE, id);
|
||||||
|
updatePeriodicReply(false, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (debugMode) {
|
||||||
|
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
|
||||||
|
sif::info << __FILE__ << __func__ << "(" << __LINE__ << ") RemMillis: " << remainingMillis
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScexDeviceHandler::performOperationHook() {
|
||||||
|
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
|
||||||
|
if (commandActive and finishCountdown.hasTimedOut()) {
|
||||||
|
triggerEvent(scex::EXPERIMENT_TIMEDOUT, currCmd, 0);
|
||||||
|
reader.finish();
|
||||||
|
sif::warning << "ScexDeviceHandler::scanForReply: Reader timeout; RemMillis: "
|
||||||
|
<< remainingMillis << std::endl;
|
||||||
|
fileNameSet = false;
|
||||||
|
commandActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ScexDeviceHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return OK; }
|
||||||
|
|
||||||
|
ReturnValue_t ScexDeviceHandler::getSwitches(const uint8_t** switches, uint8_t* numberOfSwitches) {
|
||||||
|
if (switchId) {
|
||||||
|
*numberOfSwitches = 1;
|
||||||
|
*switches = &switchId.value();
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ScexDeviceHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||||
|
LocalDataPoolManager& poolManager) {
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ScexDeviceHandler::date_time_string() {
|
||||||
|
using namespace std;
|
||||||
|
string date_time;
|
||||||
|
Clock::TimeOfDay_t tod;
|
||||||
|
Clock::getDateAndTime(&tod);
|
||||||
|
ostringstream oss(std::ostringstream::ate);
|
||||||
|
|
||||||
|
if (tod.hour < 10) {
|
||||||
|
oss << tod.year << tod.month << tod.day << "_0" << tod.hour;
|
||||||
|
} else {
|
||||||
|
oss << tod.year << tod.month << tod.day << "_" << tod.hour;
|
||||||
|
}
|
||||||
|
if (tod.minute < 10) {
|
||||||
|
oss << 0 << tod.minute;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
oss << tod.minute;
|
||||||
|
}
|
||||||
|
if (tod.second < 10) {
|
||||||
|
oss << 0 << tod.second;
|
||||||
|
} else {
|
||||||
|
oss << tod.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
date_time = oss.str();
|
||||||
|
|
||||||
|
return date_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScexDeviceHandler::modeChanged() {}
|
||||||
|
|
||||||
|
void ScexDeviceHandler::setPowerSwitcher(PowerSwitchIF& powerSwitcher, power::Switch_t switchId) {
|
||||||
|
DeviceHandlerBase::setPowerSwitcher(&powerSwitcher);
|
||||||
|
this->switchId = switchId;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ScexDeviceHandler::initializeAfterTaskCreation() {
|
||||||
|
auto mntPrefix = sdcMan.getCurrentMountPrefix();
|
||||||
|
std::filesystem::path fullFilePath = mntPrefix;
|
||||||
|
fullFilePath /= "scex";
|
||||||
|
bool fileExists = std::filesystem::exists(fullFilePath);
|
||||||
|
|
||||||
|
if (not fileExists) {
|
||||||
|
std::filesystem::create_directory(fullFilePath);
|
||||||
|
}
|
||||||
|
return DeviceHandlerBase::initializeAfterTaskCreation();
|
||||||
|
}
|
64
mission/devices/ScexDeviceHandler.h
Normal file
64
mission/devices/ScexDeviceHandler.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef MISSION_DEVICES_SCEXDEVICEHANDLER_H_
|
||||||
|
#define MISSION_DEVICES_SCEXDEVICEHANDLER_H_
|
||||||
|
|
||||||
|
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||||
|
#include <linux/devices/ScexHelper.h>
|
||||||
|
#include <linux/devices/ScexUartReader.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "eive/eventSubsystemIds.h"
|
||||||
|
|
||||||
|
class SdCardMountedIF;
|
||||||
|
|
||||||
|
class ScexDeviceHandler : public DeviceHandlerBase {
|
||||||
|
public:
|
||||||
|
ScexDeviceHandler(object_id_t objectId, ScexUartReader &reader, CookieIF *cookie,
|
||||||
|
SdCardMountedIF &sdcMan);
|
||||||
|
void setPowerSwitcher(PowerSwitchIF &powerSwitcher, power::Switch_t switchId);
|
||||||
|
virtual ~ScexDeviceHandler();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr uint32_t LONG_CD = 180 * 1000;
|
||||||
|
static constexpr uint32_t SHORT_CD = 12000;
|
||||||
|
std::array<uint8_t, 64> cmdBuf = {};
|
||||||
|
|
||||||
|
std::optional<power::Switch_t> switchId;
|
||||||
|
std::string fileId = "";
|
||||||
|
std::string fileName = "";
|
||||||
|
bool fileNameSet = false;
|
||||||
|
bool commandActive = false;
|
||||||
|
bool debugMode = false;
|
||||||
|
|
||||||
|
scex::Cmds currCmd = scex::Cmds::PING;
|
||||||
|
SdCardMountedIF &sdcMan;
|
||||||
|
Countdown finishCountdown = Countdown(LONG_CD);
|
||||||
|
|
||||||
|
std::string date_time_string();
|
||||||
|
|
||||||
|
// DeviceHandlerBase private function implementation
|
||||||
|
void doStartUp() override;
|
||||||
|
void doShutDown() override;
|
||||||
|
ScexHelper helper;
|
||||||
|
ScexUartReader &reader;
|
||||||
|
|
||||||
|
void performOperationHook() override;
|
||||||
|
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
||||||
|
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override;
|
||||||
|
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData,
|
||||||
|
size_t commandDataLen) override;
|
||||||
|
void fillCommandAndReplyMap() override;
|
||||||
|
ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize, DeviceCommandId_t *foundId,
|
||||||
|
size_t *foundLen) override;
|
||||||
|
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
|
||||||
|
ReturnValue_t handleValidReply(size_t remSize, DeviceCommandId_t *foundId, size_t *foundLen);
|
||||||
|
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
|
||||||
|
ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override;
|
||||||
|
|
||||||
|
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||||
|
LocalDataPoolManager &poolManager) override;
|
||||||
|
ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
void modeChanged() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MISSION_DEVICES_SCEXDEVICEHANDLER_H_ */
|
1
mission/devices/devicedefinitions/CMakeLists.txt
Normal file
1
mission/devices/devicedefinitions/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
target_sources(${LIB_EIVE_MISSION} PRIVATE ScexDefinitions.cpp)
|
@ -1,13 +0,0 @@
|
|||||||
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_SCEXDEFINITIONS_H_
|
|
||||||
#define MISSION_DEVICES_DEVICEDEFINITIONS_SCEXDEFINITIONS_H_
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
// Definitions for the Solar Cell Experiment
|
|
||||||
namespace scex {
|
|
||||||
|
|
||||||
static constexpr uint8_t CMD_PING = 0x4e;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_SCEXDEFINITIONS_H_ */
|
|
35
mission/devices/devicedefinitions/ScexDefinitions.cpp
Normal file
35
mission/devices/devicedefinitions/ScexDefinitions.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "ScexDefinitions.h"
|
||||||
|
|
||||||
|
#include <fsfw/globalfunctions/CRC.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
uint8_t scex::createCmdByte(Cmds cmd, bool tempCheck) {
|
||||||
|
return (IDLE_BIT_0_DEF_STATE << 7) | (IDLE_BIT_1_DEF_STATE << 6) | (cmd << 1) | tempCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t scex::prepareScexCmd(Cmds cmd, std::pair<uint8_t*, size_t> cmdBufPair, size_t& cmdLen,
|
||||||
|
std::pair<const uint8_t*, size_t> usrDataPair, bool tempCheck) {
|
||||||
|
using namespace scex;
|
||||||
|
uint8_t* cmdBuf = cmdBufPair.first;
|
||||||
|
const uint8_t* userData = usrDataPair.first;
|
||||||
|
// Send command
|
||||||
|
if (cmdBuf == nullptr or (cmdBufPair.second < usrDataPair.second + HEADER_LEN + CRC_LEN) or
|
||||||
|
(usrDataPair.second > 0 and userData == nullptr)) {
|
||||||
|
cmdLen = 0;
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
cmdBuf[0] = createCmdByte(cmd, tempCheck);
|
||||||
|
// These two fields are the packet counter and the total packet count. Those are 1 and 1 for each
|
||||||
|
// telecommand so far
|
||||||
|
cmdBuf[1] = 1;
|
||||||
|
cmdBuf[2] = 1;
|
||||||
|
cmdBuf[3] = (usrDataPair.second >> 8) & 0xff;
|
||||||
|
cmdBuf[4] = usrDataPair.second & 0xff;
|
||||||
|
std::memcpy(cmdBuf + HEADER_LEN, userData, usrDataPair.second);
|
||||||
|
uint16_t crc = CRC::crc16ccitt(cmdBuf, usrDataPair.second + HEADER_LEN);
|
||||||
|
cmdBuf[usrDataPair.second + HEADER_LEN] = (crc >> 8) & 0xff;
|
||||||
|
cmdBuf[usrDataPair.second + HEADER_LEN + 1] = crc & 0xff;
|
||||||
|
cmdLen = usrDataPair.second + HEADER_LEN + CRC_LEN;
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
52
mission/devices/devicedefinitions/ScexDefinitions.h
Normal file
52
mission/devices/devicedefinitions/ScexDefinitions.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_SCEXDEFINITIONS_H_
|
||||||
|
#define MISSION_DEVICES_DEVICEDEFINITIONS_SCEXDEFINITIONS_H_
|
||||||
|
|
||||||
|
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||||
|
#include <fsfw/events/Event.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "eive/eventSubsystemIds.h"
|
||||||
|
#include "eive/objects.h"
|
||||||
|
|
||||||
|
// Definitions for the Solar Cell Experiment
|
||||||
|
namespace scex {
|
||||||
|
|
||||||
|
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SCEX_HANDLER;
|
||||||
|
|
||||||
|
static constexpr Event MISSING_PACKET = event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW);
|
||||||
|
static constexpr Event EXPERIMENT_TIMEDOUT = event::makeEvent(SUBSYSTEM_ID, 1, severity::LOW);
|
||||||
|
//! FRAM, One Cell or All cells command finished. P1: Command ID
|
||||||
|
static constexpr Event MULTI_PACKET_COMMAND_DONE =
|
||||||
|
event::makeEvent(SUBSYSTEM_ID, 2, severity::INFO);
|
||||||
|
|
||||||
|
enum Cmds : DeviceCommandId_t {
|
||||||
|
PING = 0b00111,
|
||||||
|
ALL_CELLS_CMD = 0b00101,
|
||||||
|
ONE_CELL = 0b00110,
|
||||||
|
FRAM = 0b00001,
|
||||||
|
EXP_STATUS_CMD = 0b00010,
|
||||||
|
TEMP_CMD = 0b00011,
|
||||||
|
ION_CMD = 0b00100,
|
||||||
|
ERROR_REPLY = 0b01000,
|
||||||
|
INVALID = 255
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::vector<DeviceCommandId_t> VALID_CMDS = {
|
||||||
|
PING, ALL_CELLS_CMD, ONE_CELL, FRAM, EXP_STATUS_CMD, TEMP_CMD, ION_CMD};
|
||||||
|
|
||||||
|
static constexpr uint8_t HEADER_LEN = 5;
|
||||||
|
static constexpr uint8_t CRC_LEN = 2;
|
||||||
|
|
||||||
|
static constexpr uint8_t IDLE_BIT_0_DEF_STATE = 0;
|
||||||
|
static constexpr uint8_t IDLE_BIT_1_DEF_STATE = 1;
|
||||||
|
|
||||||
|
uint8_t createCmdByte(Cmds cmd, bool tempCheck = false);
|
||||||
|
|
||||||
|
ReturnValue_t prepareScexCmd(Cmds cmd, std::pair<uint8_t*, size_t> cmdBufPair, size_t& cmdLen,
|
||||||
|
std::pair<const uint8_t*, size_t> usrDataPair, bool tempCheck = false);
|
||||||
|
|
||||||
|
} // namespace scex
|
||||||
|
|
||||||
|
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_SCEXDEFINITIONS_H_ */
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef MISSION_MEMORY_SDCARDMOUNTERIF_H_
|
#ifndef MISSION_MEMORY_SDCARDMOUNTERIF_H_
|
||||||
#define MISSION_MEMORY_SDCARDMOUNTERIF_H_
|
#define MISSION_MEMORY_SDCARDMOUNTERIF_H_
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "definitions.h"
|
#include "definitions.h"
|
||||||
@ -8,11 +9,11 @@
|
|||||||
class SdCardMountedIF {
|
class SdCardMountedIF {
|
||||||
public:
|
public:
|
||||||
virtual ~SdCardMountedIF(){};
|
virtual ~SdCardMountedIF(){};
|
||||||
virtual std::string getCurrentMountPrefix() const = 0;
|
virtual const std::string& getCurrentMountPrefix() const = 0;
|
||||||
virtual bool isSdCardUsable(sd::SdCard sdCard) = 0;
|
virtual bool isSdCardUsable(sd::SdCard sdCard) = 0;
|
||||||
virtual sd::SdCard getPreferredSdCard() const = 0;
|
virtual std::optional<sd::SdCard> getPreferredSdCard() const = 0;
|
||||||
virtual void setActiveSdCard(sd::SdCard sdCard) = 0;
|
virtual void setActiveSdCard(sd::SdCard sdCard) = 0;
|
||||||
virtual sd::SdCard getActiveSdCard() const = 0;
|
virtual std::optional<sd::SdCard> getActiveSdCard() const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
#ifndef MISSION_UTILITY_INITMISSION_H_
|
#pragma once
|
||||||
#define MISSION_UTILITY_INITMISSION_H_
|
|
||||||
|
|
||||||
#include <fsfw/objectmanager/SystemObjectIF.h>
|
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||||
|
|
||||||
namespace initmission {
|
namespace initmission {
|
||||||
|
|
||||||
void printAddObjectError(const char* name, object_id_t objectId) {
|
static void printAddObjectError(const char* name, object_id_t objectId) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "InitMission::printAddError: Adding object " << name << " with object ID 0x"
|
sif::error << "InitMission::printAddError: Adding object " << name << " with object ID 0x"
|
||||||
<< std::hex << std::setfill('0') << std::setw(8) << objectId << " failed!" << std::dec
|
<< std::hex << std::setfill('0') << std::setw(8) << objectId << " failed!" << std::dec
|
||||||
@ -18,5 +17,3 @@ void printAddObjectError(const char* name, object_id_t objectId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace initmission
|
} // namespace initmission
|
||||||
|
|
||||||
#endif /* MISSION_UTILITY_INITMISSION_H_ */
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
echo "-L 1538:raspberrypi.local:1538 for Raspberry Pi connect with TCF agent"
|
echo "-L 1538:raspberrypi.local:1538 for Raspberry Pi connect with TCF agent"
|
||||||
echo "-L 1539:raspberrypi.local:22 for Raspberry Pi file transfers"
|
echo "-L 1539:raspberrypi.local:22 for Raspberry Pi file transfers"
|
||||||
|
echo "-L 7301:raspberrypi.local:7301 for Raspberry Pi TMTC Commands"
|
||||||
|
|
||||||
ssh -L 1538:raspberrypi.local:1534 \
|
ssh -L 1538:raspberrypi.local:1534 \
|
||||||
-L 1539:raspberrypi.local:22 \
|
-L 1539:raspberrypi.local:22 \
|
||||||
|
-L 7301:raspberrypi.local:7301 \
|
||||||
eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 \
|
eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 \
|
||||||
-t 'CONSOLE_PREFIX="[RPi Tunnel]" /bin/bash'
|
-t 'CONSOLE_PREFIX="[RPi Tunnel]" /bin/bash'
|
||||||
|
2
tmtc
2
tmtc
@ -1 +1 @@
|
|||||||
Subproject commit 9cc079d71c96301e9200b6076f392e0733d14a53
|
Subproject commit a91d40f3337a948bc061b033e194dd629fd34be1
|
Loading…
Reference in New Issue
Block a user