Merge pull request 'scex code' (#303) from scex-additions into develop
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good

Reviewed-on: #303
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
This commit is contained in:
Robin Müller 2022-10-10 17:36:36 +02:00
commit 4f7ad7154b
59 changed files with 1562 additions and 170 deletions

View File

@ -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
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/294
- 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

View File

@ -125,6 +125,9 @@ set(OBSW_ADD_GOMSPACE_PCDU
set(OBSW_ADD_RW
${INIT_VAL}
CACHE STRING "Add RW modules")
set(OBSW_ADD_SCEX_DEVICE
${INIT_VAL}
CACHE STRING "Add Solar Cell Experiment module")
# ##############################################################################
# Pre-Sources preparation
@ -389,21 +392,19 @@ add_subdirectory(${TEST_PATH})
add_subdirectory(${UNITTEST_PATH})
# This should have already been downloaded by the FSFW Still include it to be
# safe
find_package(etl ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET)
# Not installed, so use FetchContent to download and provide etl
if(NOT etl_FOUND)
message(
STATUS
"No ETL installation was found with find_package. Installing and providing "
"etl with FindPackage")
include(FetchContent)
FetchContent_Declare(
etl
GIT_REPOSITORY https://github.com/ETLCPP/etl
GIT_TAG ${FSFW_ETL_LIB_VERSION})
list(APPEND FSFW_FETCH_CONTENT_TARGETS etl)
endif()
# safe find_package(etl ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET) Not
# installed, so use FetchContent to download and provide etl if(NOT etl_FOUND)
message(
STATUS
"No ETL installation was found with find_package. Installing and providing "
"etl with FindPackage")
include(FetchContent)
FetchContent_Declare(
etl
GIT_REPOSITORY https://github.com/ETLCPP/etl
GIT_TAG ${FSFW_ETL_LIB_VERSION})
list(APPEND FSFW_FETCH_CONTENT_TARGETS etl)
# endif()
# Use same Catch2 version as framework
if(NOT (TGT_BSP MATCHES "arm/te0720-1cfa")

View File

@ -1,5 +1,5 @@
target_sources(${OBSW_NAME} PUBLIC InitMission.cpp main.cpp gpioInit.cpp
ObjectFactory.cpp)
ObjectFactory.cpp RPiSdCardManager.cpp)
add_subdirectory(boardconfig)
add_subdirectory(boardtest)

View File

@ -1,5 +1,6 @@
#include "InitMission.h"
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/objectmanager/ObjectManagerIF.h>
#include <fsfw/returnvalues/returnvalue.h>
@ -7,6 +8,7 @@
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include <fsfw/tasks/PeriodicTaskIF.h>
#include <fsfw/tasks/TaskFactory.h>
#include <linux/InitMission.h>
#include <mission/utility/InitMission.h>
#include <iostream>
@ -77,6 +79,12 @@ void initmission::initTasks() {
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 */
std::vector<PeriodicTaskIF*> pusTasks;
createPusTasks(*factory, missedDeadlineFunc, pusTasks);
@ -109,6 +117,10 @@ void initmission::initTasks() {
#endif /* OBSW_ADD_TEST_CODE == 1 */
taskStarter(pstTasks, "PST Tasks");
#if OBSW_ADD_SCEX_DEVICE == 1
scexDevHandler->startTask();
scexReaderTask->startTask();
#endif
#if OBSW_ADD_TEST_PST == 1
if (startTestPst) {
pstTestTask->startTask();
@ -195,9 +207,12 @@ void initmission::createPstTasks(TaskFactory& factory,
"SPI_PST", 70, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 1.0, missedDeadlineFunc);
result = pst::pstSpi(spiPst);
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
}
@ -228,6 +243,13 @@ void initmission::createTestTasks(TaskFactory& factory,
if (result != returnvalue::OK) {
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 */
taskVec.push_back(testTask);

View File

@ -28,6 +28,7 @@
#define OBSW_ADD_RTD_DEVICES 0
#define OBSW_ADD_PL_PCDU 0
#define OBSW_ADD_TMP_DEVICES 0
#define OBSW_ADD_SCEX_DEVICE 1
#define OBSW_ADD_RAD_SENSORS 0
#define OBSW_ADD_SYRLINKS 0
#define OBSW_STAR_TRACKER_GROUND_CONFIG 1
@ -102,6 +103,12 @@
/*******************************************************************/
#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_MINOR @LIBGPS_VERSION_MINOR@

View File

@ -1,5 +1,8 @@
#include "ObjectFactory.h"
#include <bsp_linux_board/RPiSdCardManager.h>
#include <linux/devices/ScexUartReader.h>
#include "OBSWConfig.h"
#include "devConf.h"
#include "devices/addresses.h"
@ -18,9 +21,8 @@
#include "mission/core/GenericFactory.h"
#include "mission/devices/GPSHyperionHandler.h"
#include "mission/devices/GyroADIS1650XHandler.h"
#include "mission/utility/TmFunnel.h"
#include "mission/tmtc/TmFunnel.h"
#include "objects/systemObjectList.h"
#include "tmtc/apid.h"
#include "tmtc/pusIds.h"
/* UDP server includes */
@ -45,8 +47,8 @@
#include "fsfw_hal/linux/spi/SpiCookie.h"
void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::packetDestination = objects::TM_FUNNEL;
PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_PACKET_DISTRIBUTOR;
PusServiceBase::PACKET_DESTINATION = objects::TM_FUNNEL;
CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL;
@ -54,9 +56,6 @@ void Factory::setStaticFrameworkObjectIds() {
TmFunnel::downlinkDestination = objects::TMTC_BRIDGE;
// No storage object for now.
TmFunnel::storageDestination = objects::NO_OBJECT;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
TmPacketBase::timeStamperId = objects::TIME_STAMPER;
}
void ObjectFactory::produce(void* args) {
@ -76,12 +75,17 @@ void ObjectFactory::produce(void* args) {
createRpiAcsBoard(gpioIF, spiDev);
#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
rpi::gpio::initSpiCsDecoder(gpioIF);
#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
createSunSensorComponents(gpioIF, spiComIF, pwrSwitcher, spi::DEV);
#endif

View 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; }

View 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_ */

View File

@ -13,6 +13,12 @@ static constexpr char DEV[] = "/dev/spidev0.1";
}
namespace uart {
static constexpr char DEV[] = "/dev/serial0";
}
/* Adapt these values accordingly */
namespace gpio {
static constexpr uint8_t MGM_0_BCM_PIN = 17;

View File

@ -35,6 +35,7 @@
#define OBSW_ADD_TCS_CTRL @OBSW_ADD_TCS_CTRL@
#define OBSW_ADD_RW @OBSW_ADD_RW@
#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_RAD_SENSORS @OBSW_ADD_RAD_SENSORS@
#define OBSW_ADD_PL_PCDU @OBSW_ADD_PL_PCDU@

View File

@ -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_SYRLINKS_DEV[] = "/dev/ul-syrlinks";
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_PTME[] = "/dev/uio1";

View File

@ -142,7 +142,11 @@ ReturnValue_t CoreController::initialize() {
ReturnValue_t CoreController::initializeAfterTaskCreation() {
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) {
sif::error << "CoreController::initializeAfterTaskCreation: "
"Issues getting preferred SD card, setting to 0"

View File

@ -1,6 +1,7 @@
#include "bsp_q7s/core/InitMission.h"
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <linux/InitMission.h>
#include <iostream>
#include <vector>
@ -252,6 +253,11 @@ void initmission::initTasks() {
initmission::printAddObjectError("PTME_TEST", objects::CCSDS_IP_CORE_BRIDGE);
}
#endif
#if OBSW_ADD_SCEX_DEVICE == 1
PeriodicTaskIF* scexDevHandler;
PeriodicTaskIF* scexReaderTask;
scheduling::schedulingScex(*factory, scexDevHandler, scexReaderTask);
#endif
std::vector<PeriodicTaskIF*> pusTasks;
createPusTasks(*factory, missedDeadlineFunc, pusTasks);
@ -290,8 +296,9 @@ void initmission::initTasks() {
taskStarter(pstTasks, "PST task vector");
taskStarter(pusTasks, "PUS task vector");
#if OBSW_ADD_TEST_CODE == 1
taskStarter(testTasks, "Test task vector");
#if OBSW_ADD_SCEX_DEVICE == 1
scexDevHandler->startTask();
scexReaderTask->startTask();
#endif
#if OBSW_TEST_CCSDS_BRIDGE == 1
@ -315,6 +322,11 @@ void initmission::initTasks() {
#if OBSW_ADD_PLOC_SUPERVISOR == 1
supvHelperTask->startTask();
#endif /* OBSW_ADD_PLOC_SUPERVISOR == 1 */
#if OBSW_ADD_TEST_CODE == 1
taskStarter(testTasks, "Test task vector");
#endif
sif::info << "Tasks started.." << std::endl;
}

View File

@ -1,5 +1,7 @@
#include "ObjectFactory.h"
#include <linux/devices/ScexUartReader.h>
#include "OBSWConfig.h"
#include "bsp_q7s/boardtest/Q7STestTask.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);
#endif
#if OBSW_ADD_UART_TEST_CODE == 1
// auto* reader= new ScexUartReader(objects::SCEX_UART_READER);
new UartTestClass(objects::UART_TEST);
#endif
}

View File

@ -1,3 +1,5 @@
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
#include "OBSWConfig.h"
#include "bsp_q7s/core/CoreController.h"
#include "bsp_q7s/core/ObjectFactory.h"
@ -56,6 +58,11 @@ void ObjectFactory::produce(void* args) {
#if OBSW_USE_CCSDS_IP_CORE == 1
createCcsdsComponents(gpioComIF);
#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 */
#if OBSW_ADD_TEST_CODE == 1
createTestComponents(gpioComIF);

View File

@ -304,11 +304,6 @@ ReturnValue_t SdCardManager::sanitizeState(SdStatePair* statusPair, sd::SdCard p
blocking = true;
resetNonBlockingState = true;
}
if (prefSdCard == sd::SdCard::NONE) {
result = getPreferredSdCard();
if (result != returnvalue::OK) {
}
}
if (statusPair == nullptr) {
sdStatusPtr = std::make_unique<SdStatePair>();
statusPair = sdStatusPtr.get();
@ -383,7 +378,7 @@ void SdCardManager::processSdStatusLine(std::pair<sd::SdState, sd::SdState>& act
idx++;
}
sd::SdCard SdCardManager::getPreferredSdCard() const {
std::optional<sd::SdCard> SdCardManager::getPreferredSdCard() const {
MutexGuard mg(mutex);
auto res = mg.getLockResult();
if (res != returnvalue::OK) {
@ -416,13 +411,9 @@ ReturnValue_t SdCardManager::updateSdCardStateFile() {
return result;
}
std::string SdCardManager::getCurrentMountPrefix() const {
const std::string& SdCardManager::getCurrentMountPrefix() const {
MutexGuard mg(mutex);
if (sdInfo.active == sd::SdCard::SLOT_0) {
return config::SD_0_MOUNT_POINT;
} else {
return config::SD_1_MOUNT_POINT;
}
return currentPrefix;
}
SdCardManager::OpStatus SdCardManager::checkCurrentOp(Operations& currentOp) {
@ -558,6 +549,17 @@ ReturnValue_t SdCardManager::performFsck(sd::SdCard sdcard, bool printOutput, in
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;
}

View File

@ -91,7 +91,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
* @param sdCard
* @return
*/
sd::SdCard getPreferredSdCard() const override;
std::optional<sd::SdCard> getPreferredSdCard() const override;
/**
* Switch on the specified SD card.
@ -158,7 +158,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
* mounted
* @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
@ -187,7 +187,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
* @param prefSdCardPtr
* @return
*/
std::string getCurrentMountPrefix() const override;
const std::string& getCurrentMountPrefix() const override;
OpStatus checkCurrentOp(Operations& currentOp);

View File

@ -1,8 +1,8 @@
#include "scratchApi.h"
ReturnValue_t scratch::writeString(std::string name, std::string string) {
std::ostringstream oss;
oss << "xsc_scratch write " << name << " \"" << string << "\"";
std::ostringstream oss("xsc_scratch write ", std::ostringstream::ate);
oss << name << " \"" << string << "\"";
int result = std::system(oss.str().c_str());
if (result != 0) {
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) {
std::ostringstream oss;
oss << "xsc_scratch clear " << key;
std::ostringstream oss("xsc_scratch clear ", std::ostringstream::ate);
oss << key;
int result = std::system(oss.str().c_str());
if (result != 0) {
utility::handleSystemError(result, "scratch::clearValue");

View File

@ -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>
inline ReturnValue_t writeNumber(std::string key, T num) noexcept {
std::ostringstream oss;
oss << "xsc_scratch write " << key << " " << std::to_string(num);
std::ostringstream oss("xsc_scratch write ", std::ostringstream::ate);
oss << key << " " << std::to_string(num);
int result = std::system(oss.str().c_str());
if (result != 0) {
utility::handleSystemError(result, "scratch::writeNumber");

View File

@ -55,6 +55,7 @@ namespace uart {
static constexpr size_t HYPERION_GPS_REPLY_MAX_BUFFER = 1024;
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 PLOC_MPSOC_BAUD = UartBaudRate::RATE_115200;
static constexpr UartBaudRate PLOC_SUPV_BAUD = UartBaudRate::RATE_115200;

View File

@ -33,7 +33,8 @@ enum : uint8_t {
ACU_HANDLER = 135,
PLOC_SUPV_HELPER = 136,
SYRLINKS = 137,
CONFIGHANDLER = 138,
SCEX_HANDLER = 138,
CONFIGHANDLER = 139,
COMMON_SUBSYSTEM_ID_END
};

View File

@ -58,6 +58,7 @@ enum commonObjects : uint32_t {
PLOC_MPSOC_HANDLER = 0x44330015,
PLOC_SUPERVISOR_HANDLER = 0x44330016,
PLOC_SUPERVISOR_HELPER = 0x44330017,
SCEX = 0x44330032,
SOLAR_ARRAY_DEPL_HANDLER = 0x444100A2,
HEATER_HANDLER = 0x444100A4,

2
fsfw

@ -1 +1 @@
Subproject commit 692be9df8d06beb3bfc83aad77cefd727d8f7c35
Subproject commit a8fb83dfcedb5391ac942d6bcffa64f0cbca38c5

View File

@ -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
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
13801;0x35e9;SET_CONFIGFILEVALUE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
13802;0x35ea;GET_CONFIGFILEVALUE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
13803;0x35eb;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
13804;0x35ec;WRITE_CONFIGFILE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
13805;0x35ed;READ_CONFIGFILE_FAILED;MEDIUM;;mission/utility/GlobalConfigHandler.h
13800;0x35e8;MISSING_PACKET;LOW;;mission/devices/devicedefinitions/ScexDefinitions.h
13801;0x35e9;EXPERIMENT_TIMEDOUT;LOW;;mission/devices/devicedefinitions/ScexDefinitions.h
13802;0x35ea;MULTI_PACKET_COMMAND_DONE;INFO;;mission/devices/devicedefinitions/ScexDefinitions.h
13901;0x364d;SET_CONFIGFILEVALUE_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

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
216 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
217 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
218 13703 0x3587 REBOOT_HW MEDIUM bsp_q7s/core/CoreController.h
219 13801 13800 0x35e9 0x35e8 SET_CONFIGFILEVALUE_FAILED MISSING_PACKET MEDIUM LOW mission/utility/GlobalConfigHandler.h mission/devices/devicedefinitions/ScexDefinitions.h
220 13802 13801 0x35ea 0x35e9 GET_CONFIGFILEVALUE_FAILED EXPERIMENT_TIMEDOUT MEDIUM LOW mission/utility/GlobalConfigHandler.h mission/devices/devicedefinitions/ScexDefinitions.h
221 13803 13802 0x35eb 0x35ea INSERT_CONFIGFILEVALUE_FAILED MULTI_PACKET_COMMAND_DONE MEDIUM INFO mission/utility/GlobalConfigHandler.h mission/devices/devicedefinitions/ScexDefinitions.h
222 13804 13901 0x35ec 0x364d WRITE_CONFIGFILE_FAILED SET_CONFIGFILEVALUE_FAILED MEDIUM mission/utility/GlobalConfigHandler.h
223 13805 13902 0x35ed 0x364e READ_CONFIGFILE_FAILED GET_CONFIGFILEVALUE_FAILED MEDIUM mission/utility/GlobalConfigHandler.h
224 13903 0x364f INSERT_CONFIGFILEVALUE_FAILED MEDIUM mission/utility/GlobalConfigHandler.h
225 13904 0x3650 WRITE_CONFIGFILE_FAILED MEDIUM mission/utility/GlobalConfigHandler.h
226 13905 0x3651 READ_CONFIGFILE_FAILED MEDIUM mission/utility/GlobalConfigHandler.h

View File

@ -47,6 +47,7 @@
0x44330015;PLOC_MPSOC_HANDLER
0x44330016;PLOC_SUPERVISOR_HANDLER
0x44330017;PLOC_SUPERVISOR_HELPER
0x44330032;SCEX
0x444100A2;SOLAR_ARRAY_DEPL_HANDLER
0x444100A4;HEATER_HANDLER
0x44420004;TMP1075_HANDLER_1
@ -70,6 +71,7 @@
0x445300A3;SYRLINKS_HK_HANDLER
0x49000000;ARDUINO_COM_IF
0x49010005;GPIO_IF
0x49010006;SCEX_UART_READER
0x49020004;SPI_MAIN_COM_IF
0x49020005;SPI_RW_COM_IF
0x49020006;SPI_RTD_COM_IF

1 0x00005060 P60DOCK_TEST_TASK
47 0x44330015 PLOC_MPSOC_HANDLER
48 0x44330016 PLOC_SUPERVISOR_HANDLER
49 0x44330017 PLOC_SUPERVISOR_HELPER
50 0x44330032 SCEX
51 0x444100A2 SOLAR_ARRAY_DEPL_HANDLER
52 0x444100A4 HEATER_HANDLER
53 0x44420004 TMP1075_HANDLER_1
71 0x445300A3 SYRLINKS_HK_HANDLER
72 0x49000000 ARDUINO_COM_IF
73 0x49010005 GPIO_IF
74 0x49010006 SCEX_UART_READER
75 0x49020004 SPI_MAIN_COM_IF
76 0x49020005 SPI_RW_COM_IF
77 0x49020006 SPI_RTD_COM_IF

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 222 translations.
* @brief Auto-generated event translation file. Contains 225 translations.
* @details
* Generated on: 2022-10-10 10:15:22
* Generated on: 2022-10-10 11:15:49
*/
#include "translateEvents.h"
@ -218,6 +218,9 @@ const char *ALLOC_FAILURE_STRING = "ALLOC_FAILURE";
const char *REBOOT_SW_STRING = "REBOOT_SW";
const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED";
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 *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_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;
case (13703):
return REBOOT_HW_STRING;
case (13800):
return MISSING_PACKET_STRING;
case (13801):
return SET_CONFIGFILEVALUE_FAILED_STRING;
return EXPERIMENT_TIMEDOUT_STRING;
case (13802):
return MULTI_PACKET_COMMAND_DONE_STRING;
case (13901):
return SET_CONFIGFILEVALUE_FAILED_STRING;
case (13902):
return GET_CONFIGFILEVALUE_FAILED_STRING;
case (13803):
case (13903):
return INSERT_CONFIGFILEVALUE_FAILED_STRING;
case (13804):
case (13904):
return WRITE_CONFIGFILE_FAILED_STRING;
case (13805):
case (13905):
return READ_CONFIGFILE_FAILED_STRING;
default:
return "UNKNOWN_EVENT";

View File

@ -1,8 +1,8 @@
/**
* @brief Auto-generated object translation file.
* @details
* Contains 136 translations.
* Generated on: 2022-10-10 10:15:22
* Contains 138 translations.
* Generated on: 2022-10-10 11:15:49
*/
#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_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER";
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 *HEATER_HANDLER_STRING = "HEATER_HANDLER";
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 *ARDUINO_COM_IF_STRING = "ARDUINO_COM_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_RW_COM_IF_STRING = "SPI_RW_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;
case 0x44330017:
return PLOC_SUPERVISOR_HELPER_STRING;
case 0x44330032:
return SCEX_STRING;
case 0x444100A2:
return SOLAR_ARRAY_DEPL_HANDLER_STRING;
case 0x444100A4:
@ -289,6 +293,8 @@ const char *translateObject(object_id_t object) {
return ARDUINO_COM_IF_STRING;
case 0x49010005:
return GPIO_IF_STRING;
case 0x49010006:
return SCEX_UART_READER_STRING;
case 0x49020004:
return SPI_MAIN_COM_IF_STRING;
case 0x49020005:

View File

@ -6,4 +6,4 @@ add_subdirectory(devices)
add_subdirectory(fsfwconfig)
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
View 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
View File

@ -0,0 +1,7 @@
#pragma once
#include <fsfw/tasks/TaskFactory.h>
namespace scheduling {
void schedulingScex(TaskFactory& factory, PeriodicTaskIF*& scexDevHandler,
PeriodicTaskIF*& scexReaderTask);
}

View File

@ -6,12 +6,14 @@
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
#include <fsfw_hal/linux/spi/SpiComIF.h>
#include <fsfw_hal/linux/spi/SpiCookie.h>
#include <fsfw_hal/linux/uart/UartCookie.h>
#include <linux/callbacks/gpioCallbacks.h>
#include <linux/devices/Max31865RtdLowlevelHandler.h>
#include <mission/controller/AcsController.h>
#include <mission/controller/ThermalController.h>
#include <mission/devices/Max31865EiveHandler.h>
#include <mission/devices/Max31865PT1000Handler.h>
#include <mission/devices/ScexDeviceHandler.h>
#include <mission/devices/SusHandler.h>
#include <mission/system/SusAssembly.h>
#include <mission/system/TcsBoardAssembly.h>
@ -321,6 +323,22 @@ void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF,
#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() {
new ThermalController(objects::THERMAL_CONTROLLER, objects::NO_OBJECT);
}

View File

@ -1,8 +1,11 @@
#pragma once
#include <fsfw/power/definitions.h>
#include <fsfw/returnvalues/returnvalue.h>
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
#include <mission/memory/SdCardMountedIF.h>
#include <optional>
#include <string>
class GpioIF;
@ -16,6 +19,10 @@ void createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiComIF, PowerSwitc
void createRtdComponents(std::string spiDev, GpioIF* gpioComIF, PowerSwitchIF* pwrSwitcher,
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 createThermalController();

View File

@ -3,14 +3,21 @@
#include <errno.h> // Error integer and strerror() function
#include <fcntl.h> // Contains file controls like O_RDWR
#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 <random>
#include <string>
#include "OBSWConfig.h"
#include "fsfw/globalfunctions/CRC.h"
#include "fsfw/globalfunctions/DleEncoder.h"
#include "fsfw/globalfunctions/arrayprinter.h"
#include "fsfw/serviceinterface.h"
#include "mission/devices/devicedefinitions/SCEXDefinitions.h"
#include "mission/devices/devicedefinitions/ScexDefinitions.h"
#define GPS_REPLY_WIRETAPPING 0
@ -18,7 +25,25 @@
#define RPI_TEST_GPS_HANDLER 0
#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() {
if (mode == TestModes::GPS) {
@ -44,14 +69,14 @@ void UartTestClass::gpsInit() {
#if RPI_TEST_GPS_HANDLER == 1
int result = lwgps_init(&gpsData);
if (result == 0) {
sif::warning << "lwgps_init error: " << result << std::endl;
sif::warning << "UartTestClass::gpsInit: lwgps_init error: " << result << std::endl;
}
/* Get file descriptor */
serialPort = open("/dev/serial0", O_RDWR);
if (serialPort < 0) {
sif::warning << "open call failed with error [" << errno << ", " << strerror(errno)
<< std::endl;
sif::warning << "UartTestClass::gpsInit: open call failed with error [" << errno << ", "
<< strerror(errno) << std::endl;
}
/* Setting up UART parameters */
tty.c_cflag &= ~PARENB; // Clear parity bit
@ -79,8 +104,8 @@ void UartTestClass::gpsInit() {
cfsetispeed(&tty, B9600);
cfsetospeed(&tty, B9600);
if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
sif::warning << "tcsetattr call failed with error [" << errno << ", " << strerror(errno)
<< std::endl;
sif::warning << "UartTestClass::gpsInit: tcsetattr call failed with error [" << errno << ", "
<< strerror(errno) << std::endl;
;
}
// 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()),
static_cast<unsigned int>(recBuf.size()));
if (bytesRead < 0) {
sif::warning << "UartTestClass::performPeriodicAction: read call failed with error [" << errno
<< ", " << strerror(errno) << "]" << std::endl;
sif::warning << "UartTestClass::gpsPeriodic: read call failed with error [" << errno << ", "
<< strerror(errno) << "]" << std::endl;
break;
} else if (bytesRead >= static_cast<int>(recBuf.size())) {
sif::debug << "UartTestClass::performPeriodicAction: "
sif::debug << "UartTestClass::gpsPeriodic: "
"recv buffer might not be large enough"
<< std::endl;
} else if (bytesRead > 0) {
@ -109,7 +134,7 @@ void UartTestClass::gpsPeriodic() {
#endif
int result = lwgps_process(&gpsData, recBuf.data(), bytesRead);
if (result == 0) {
sif::warning << "UartTestClass::performPeriodicAction: lwgps_process error" << std::endl;
sif::warning << "UartTestClass::gpsPeriodic: lwgps_process error" << std::endl;
}
recvCnt++;
if (recvCnt == 6) {
@ -127,6 +152,114 @@ void UartTestClass::gpsPeriodic() {
}
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)
std::string devname = "/dev/serial0";
#else
@ -135,8 +268,8 @@ void UartTestClass::scexInit() {
/* Get file descriptor */
serialPort = open(devname.c_str(), O_RDWR);
if (serialPort < 0) {
sif::warning << "open call failed with error [" << errno << ", " << strerror(errno)
<< std::endl;
sif::warning << "UartTestClass::scexSimpleInit: Open call failed with error [" << errno << ", "
<< strerror(errno) << std::endl;
return;
}
// 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
// received in one go
tty.c_cc[VTIME] = 1; // In units of 0.1 seconds
tty.c_cc[VMIN] = 255; // Read up to 255 bytes
tty.c_cc[VTIME] = 0; // In units of 0.1 seconds
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.
#if !defined(XIPHOS_Q7S)
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
if (tcsetattr(serialPort, TCSANOW, &tty) != 0) {
sif::warning << "tcsetattr call failed with error [" << errno << ", " << strerror(errno)
<< std::endl;
sif::warning << "UartTestClass::scexSimpleInit: tcsetattr call failed with error [" << errno
<< ", " << strerror(errno) << std::endl;
}
// Flush received and unread data
tcflush(serialPort, TCIFLUSH);
tcflush(serialPort, TCIOFLUSH);
}
void UartTestClass::scexPeriodic() {
sif::info << "UartTestClass::scexInit: Sending ping command to SCEX" << std::endl;
int result = prepareScexPing();
if (result != 0) {
return;
};
size_t bytesWritten = write(serialPort, cmdBuf.data(), encodedLen);
if (bytesWritten != encodedLen) {
sif::warning << "Sending ping command to solar experiment failed" << std::endl;
}
// Read back reply immediately
int bytesRead = 0;
do {
bytesRead = read(serialPort, reinterpret_cast<void*>(recBuf.data()),
static_cast<unsigned int>(recBuf.size()));
if (bytesRead < 0) {
sif::warning << "UartTestClass::performPeriodicAction: read call failed with error [" << errno
<< ", " << strerror(errno) << "]" << std::endl;
break;
} else if (bytesRead >= static_cast<int>(recBuf.size())) {
sif::debug << "UartTestClass::performPeriodicAction: recv buffer might not be large enough"
<< std::endl;
} else if (bytesRead > 0) {
sif::info << "Received " << bytesRead
<< " bytes from the Solar Cell Experiment:" << std::endl;
arrayprinter::print(recBuf.data(), bytesRead, OutputType::HEX, false);
void UartTestClass::scexSimplePeriodic() {
using namespace scex;
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;
}
} while (bytesRead > 0);
if (result != 0) {
return;
};
size_t bytesWritten = write(serialPort, cmdBuf.data(), encodedLen);
if (bytesWritten != encodedLen) {
sif::warning
<< "UartTestClass::scexSimplePeriodic: Sending command to solar experiment failed"
<< std::endl;
}
cmdSent = true;
cmdDone = false;
}
if (not cmdDone) {
// Read back reply immediately
int bytesRead = 0;
do {
bytesRead = read(serialPort, reinterpret_cast<void*>(recBuf.data()),
static_cast<unsigned int>(recBuf.size()));
if (bytesRead == 0) {
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;
break;
} else if (bytesRead >= static_cast<int>(recBuf.size())) {
sif::debug << "UartTestClass::scexSimplePeriodic: recv buffer might not be large "
"enough, bytes read:"
<< bytesRead << std::endl;
} else if (bytesRead > 0) {
dleParser->passData(recBuf.data(), bytesRead);
if (currCmd == Cmds::PING) {
cmdDone = true;
cmdSent = false;
}
}
} while (bytesRead > 0);
}
}
int UartTestClass::prepareScexPing() {
std::array<uint8_t, 128> tmpCmdBuf = {};
// Send ping command
tmpCmdBuf[0] = scex::CMD_PING;
int UartTestClass::prepareScexCmd(scex::Cmds cmd, bool tempCheck, uint8_t* cmdBuf, size_t* len) {
using namespace scex;
// Send command
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
// telecommand so far
tmpCmdBuf[1] = 1;
tmpCmdBuf[2] = 1;
cmdBuf[1] = 1;
cmdBuf[2] = 1;
uint16_t userDataLen = 0;
tmpCmdBuf[3] = (userDataLen >> 8) & 0xff;
tmpCmdBuf[4] = userDataLen & 0xff;
uint16_t crc = CRC::crc16ccitt(tmpCmdBuf.data(), 5);
tmpCmdBuf[5] = (crc >> 8) & 0xff;
tmpCmdBuf[6] = crc & 0xff;
ReturnValue_t result =
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;
}
cmdBuf[3] = (userDataLen >> 8) & 0xff;
cmdBuf[4] = userDataLen & 0xff;
uint16_t crc = CRC::crc16ccitt(cmdBuf, 5);
cmdBuf[5] = (crc >> 8) & 0xff;
cmdBuf[6] = crc & 0xff;
*len = 7;
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;
}

View File

@ -1,14 +1,22 @@
#ifndef LINUX_BOARDTEST_UARTTESTCLASS_H_
#define LINUX_BOARDTEST_UARTTESTCLASS_H_
#include <fsfw/container/SimpleRingBuffer.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 <array>
#include "lwgps/lwgps.h"
#include "mission/devices/devicedefinitions/ScexDefinitions.h"
#include "test/testtasks/TestTask.h"
class ScexUartReader;
class ScexDleParser;
class UartTestClass : public TestTask {
public:
UartTestClass(object_id_t objectId);
@ -24,20 +32,42 @@ class UartTestClass : public TestTask {
SCEX
};
enum ScexModes { SIMPLE, READER_TASK } scexMode;
void gpsInit();
void gpsPeriodic();
void scexInit();
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;
DleEncoder dleEncoder = DleEncoder();
UartCookie* uartCookie = nullptr;
size_t encodedLen = 0;
lwgps_t gpsData = {};
struct termios tty = {};
int serialPort = 0;
bool startFound = false;
ScexUartReader* reader = nullptr;
std::array<uint8_t, 64> cmdBuf = {};
std::array<uint8_t, 4096> recBuf = {};
ScexDleParser* dleParser;
scex::Cmds cmdHelper = scex::Cmds::INVALID;
uint8_t recvCnt = 0;
};

View File

@ -2,7 +2,9 @@ if(EIVE_BUILD_GPSD_GPS_HANDLER)
target_sources(${OBSW_NAME} PRIVATE GPSHyperionLinuxController.cpp)
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(startracker)

View 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(){};

View 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:
};

View 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;
}

View 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_ */

View 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;
}

View 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;
};

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 222 translations.
* @brief Auto-generated event translation file. Contains 225 translations.
* @details
* Generated on: 2022-10-10 10:15:22
* Generated on: 2022-10-10 11:15:49
*/
#include "translateEvents.h"
@ -218,6 +218,9 @@ const char *ALLOC_FAILURE_STRING = "ALLOC_FAILURE";
const char *REBOOT_SW_STRING = "REBOOT_SW";
const char *REBOOT_MECHANISM_TRIGGERED_STRING = "REBOOT_MECHANISM_TRIGGERED";
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 *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_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;
case (13703):
return REBOOT_HW_STRING;
case (13800):
return MISSING_PACKET_STRING;
case (13801):
return SET_CONFIGFILEVALUE_FAILED_STRING;
return EXPERIMENT_TIMEDOUT_STRING;
case (13802):
return MULTI_PACKET_COMMAND_DONE_STRING;
case (13901):
return SET_CONFIGFILEVALUE_FAILED_STRING;
case (13902):
return GET_CONFIGFILEVALUE_FAILED_STRING;
case (13803):
case (13903):
return INSERT_CONFIGFILEVALUE_FAILED_STRING;
case (13804):
case (13904):
return WRITE_CONFIGFILE_FAILED_STRING;
case (13805):
case (13905):
return READ_CONFIGFILE_FAILED_STRING;
default:
return "UNKNOWN_EVENT";

View File

@ -49,6 +49,9 @@ enum sourceObjects : uint32_t {
UART_COM_IF = 0x49030003,
SPI_MAIN_COM_IF = 0x49020004,
GPIO_IF = 0x49010005,
SCEX_UART_READER = 0x49010006,
/* Custom device handler */
SPI_RW_COM_IF = 0x49020005,
/* 0x54 ('T') for test handlers */

View File

@ -1,8 +1,8 @@
/**
* @brief Auto-generated object translation file.
* @details
* Contains 136 translations.
* Generated on: 2022-10-10 10:15:22
* Contains 138 translations.
* Generated on: 2022-10-10 11:15:49
*/
#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_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER";
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 *HEATER_HANDLER_STRING = "HEATER_HANDLER";
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 *ARDUINO_COM_IF_STRING = "ARDUINO_COM_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_RW_COM_IF_STRING = "SPI_RW_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;
case 0x44330017:
return PLOC_SUPERVISOR_HELPER_STRING;
case 0x44330032:
return SCEX_STRING;
case 0x444100A2:
return SOLAR_ARRAY_DEPL_HANDLER_STRING;
case 0x444100A4:
@ -289,6 +293,8 @@ const char *translateObject(object_id_t object) {
return ARDUINO_COM_IF_STRING;
case 0x49010005:
return GPIO_IF_STRING;
case 0x49010006:
return SCEX_UART_READER_STRING;
case 0x49020004:
return SPI_MAIN_COM_IF_STRING;
case 0x49020005:

View File

@ -6,6 +6,7 @@
#include <cstring>
#include <sstream>
#include "OBSWConfig.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h"

View File

@ -19,4 +19,7 @@ target_sources(
max1227.cpp
SusHandler.cpp
PayloadPcduHandler.cpp
SolarArrayDeploymentHandler.cpp)
SolarArrayDeploymentHandler.cpp
ScexDeviceHandler.cpp)
add_subdirectory(devicedefinitions)

View File

@ -20,7 +20,7 @@ IMTQHandler::IMTQHandler(object_id_t objectId, object_id_t comIF, CookieIF* comC
posZselfTestDataset(this),
negZselfTestDataset(this),
switcher(pwrSwitcher) {
if (comCookie == NULL) {
if (comCookie == nullptr) {
sif::error << "IMTQHandler: Invalid com cookie" << std::endl;
}
}

View File

@ -491,8 +491,8 @@ void PayloadPcduHandler::checkAdcValues() {
void PayloadPcduHandler::checkJsonFileInit() {
if (not jsonFileInitComplete) {
sd::SdCard activeSd = sdcMan->getActiveSdCard();
if (sdcMan->isSdCardUsable(activeSd)) {
auto activeSd = sdcMan->getActiveSdCard();
if (activeSd and sdcMan->isSdCardUsable(activeSd.value())) {
params.initialize(sdcMan->getCurrentMountPrefix());
jsonFileInitComplete = true;
}

View 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();
}

View 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_ */

View File

@ -0,0 +1 @@
target_sources(${LIB_EIVE_MISSION} PRIVATE ScexDefinitions.cpp)

View File

@ -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_ */

View 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;
}

View 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_ */

View File

@ -1,6 +1,7 @@
#ifndef MISSION_MEMORY_SDCARDMOUNTERIF_H_
#define MISSION_MEMORY_SDCARDMOUNTERIF_H_
#include <optional>
#include <string>
#include "definitions.h"
@ -8,11 +9,11 @@
class SdCardMountedIF {
public:
virtual ~SdCardMountedIF(){};
virtual std::string getCurrentMountPrefix() const = 0;
virtual const std::string& getCurrentMountPrefix() const = 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 sd::SdCard getActiveSdCard() const = 0;
virtual std::optional<sd::SdCard> getActiveSdCard() const = 0;
private:
};

View File

@ -1,12 +1,11 @@
#ifndef MISSION_UTILITY_INITMISSION_H_
#define MISSION_UTILITY_INITMISSION_H_
#pragma once
#include <fsfw/objectmanager/SystemObjectIF.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
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
sif::error << "InitMission::printAddError: Adding object " << name << " with object ID 0x"
<< 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
#endif /* MISSION_UTILITY_INITMISSION_H_ */

View File

@ -1,8 +1,10 @@
#!/bin/bash
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 7301:raspberrypi.local:7301 for Raspberry Pi TMTC Commands"
ssh -L 1538:raspberrypi.local:1534 \
-L 1539:raspberrypi.local:22 \
eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 \
-L 7301:raspberrypi.local:7301 \
eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 \
-t 'CONSOLE_PREFIX="[RPi Tunnel]" /bin/bash'

2
tmtc

@ -1 +1 @@
Subproject commit 9cc079d71c96301e9200b6076f392e0733d14a53
Subproject commit a91d40f3337a948bc061b033e194dd629fd34be1

View File

@ -15,7 +15,7 @@ TEST_CASE("Thermal Controller", "[ThermalController]") {
new TemperatureSensorsDummy();
new SusDummy();
//testEnvironment::initialize();
// testEnvironment::initialize();
ThermalController controller(THERMAL_CONTROLLER_ID, objects::NO_OBJECT);
ReturnValue_t result = controller.initialize();