Merge pull request 'scex code' (#303) from scex-additions into develop
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
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:
commit
4f7ad7154b
@ -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
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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@
|
||||
|
||||
|
@ -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
|
||||
|
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 */
|
||||
namespace gpio {
|
||||
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_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@
|
||||
|
@ -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";
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
};
|
||||
|
@ -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
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
|
||||
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
|
||||
|
|
@ -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,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";
|
||||
|
@ -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:
|
||||
|
@ -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
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/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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
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
|
||||
* 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";
|
||||
|
@ -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 */
|
||||
|
@ -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:
|
||||
|
@ -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"
|
||||
|
@ -19,4 +19,7 @@ target_sources(
|
||||
max1227.cpp
|
||||
SusHandler.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),
|
||||
negZselfTestDataset(this),
|
||||
switcher(pwrSwitcher) {
|
||||
if (comCookie == NULL) {
|
||||
if (comCookie == nullptr) {
|
||||
sif::error << "IMTQHandler: Invalid com cookie" << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
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_
|
||||
#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:
|
||||
};
|
||||
|
@ -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_ */
|
||||
|
@ -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
2
tmtc
@ -1 +1 @@
|
||||
Subproject commit 9cc079d71c96301e9200b6076f392e0733d14a53
|
||||
Subproject commit a91d40f3337a948bc061b033e194dd629fd34be1
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user