fixed merge conflicts

This commit is contained in:
Jakob Meier 2021-04-26 17:50:36 +02:00
commit d63c825c7f
17 changed files with 929 additions and 23 deletions

View File

@ -277,7 +277,7 @@ Copying a file from Q7S to flatsat PC
scp -P 22 root@192.168.133.10:/tmp/kernel-config /tmp scp -P 22 root@192.168.133.10:/tmp/kernel-config /tmp
```` ````
From a windows machine files can be copied with putty tools From a windows machine files can be copied with putty tools (note: use IPv4 address)
```` ````
pscp -scp -P 22 eive@192.168.199.227:</directory-to-example-file/>/example-file </windows-machine-path/> pscp -scp -P 22 eive@192.168.199.227:</directory-to-example-file/>/example-file </windows-machine-path/>
```` ````
@ -579,4 +579,23 @@ to install the required GPIO libraries before cloning the system root folder.
When using Eclipse, there are two special build variables in the project properties When using Eclipse, there are two special build variables in the project properties
&rarr; C/C++ Build &rarr; Build Variables called `Q7S_SYSROOT` or `RPI_SYSROOT`. You can set &rarr; C/C++ Build &rarr; Build Variables called `Q7S_SYSROOT` or `RPI_SYSROOT`. You can set
the sysroot path in those variables to get any additional includes like `gpiod.h` in the the sysroot path in those variables to get any additional includes like `gpiod.h` in the
Eclipse indexer. Eclipse indexer.
## Xilinx UARTLIE
Get info about ttyUL* devices
````
cat /proc/tty/driver
````
## I2C
Getting information about I2C device
````
ls /sys/class/i2c-dev/i2c-0/device/device/driver
````
This shows the memory mapping of /dev/i2c-0
## Useful Q7S Linux Commands
Rebooting currently running image:
````
xsc_boot_copy -r
````

View File

@ -135,6 +135,8 @@ void initmission::initTasks() {
initmission::printAddObjectError("PUS_17", objects::PUS_SERVICE_17_TEST); initmission::printAddObjectError("PUS_17", objects::PUS_SERVICE_17_TEST);
} }
#if TE0720 == 0
//TODO: Add handling of missed deadlines //TODO: Add handling of missed deadlines
/* Polling Sequence Table Default */ /* Polling Sequence Table Default */
#if Q7S_ADD_SPI_TEST == 0 #if Q7S_ADD_SPI_TEST == 0
@ -147,7 +149,6 @@ void initmission::initTasks() {
} }
#endif #endif
#if TE0720 == 0
FixedTimeslotTaskIF* gomSpacePstTask = factory-> FixedTimeslotTaskIF* gomSpacePstTask = factory->
createFixedTimeslotTask("GS_PST_TASK", 50, createFixedTimeslotTask("GS_PST_TASK", 50,
PeriodicTaskIF::MINIMUM_STACK_SIZE*8, 3.0, missedDeadlineFunc); PeriodicTaskIF::MINIMUM_STACK_SIZE*8, 3.0, missedDeadlineFunc);
@ -155,6 +156,15 @@ void initmission::initTasks() {
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: GomSpace PST initialization failed!" << std::endl; sif::error << "InitMission::initTasks: GomSpace PST initialization failed!" << std::endl;
} }
#else
FixedTimeslotTaskIF * pollingSequenceTableTE0720 = factory->createFixedTimeslotTask(
"PST_TASK_TE0720", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 3.0,
missedDeadlineFunc);
result = pst::pollingSequenceTE0720(pollingSequenceTableTE0720);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: Creating TE0720 PST failed!" << std::endl;
}
#endif #endif
#if OBSW_ADD_TEST_CODE == 1 #if OBSW_ADD_TEST_CODE == 1
@ -184,12 +194,11 @@ void initmission::initTasks() {
udpBridgeTask->startTask(); udpBridgeTask->startTask();
udpPollingTask->startTask(); udpPollingTask->startTask();
#if TE0720 == 0 #if TE0720 == 0 && Q7S_ADD_SPI_TEST == 0
gomSpacePstTask->startTask(); gomSpacePstTask->startTask();
#endif
#if Q7S_ADD_SPI_TEST == 0
pollingSequenceTableTaskDefault->startTask(); pollingSequenceTableTaskDefault->startTask();
#elif TE0720 == 1 && Q7S_ADD_SPI_TEST == 0
pollingSequenceTableTE0720->startTask();
#endif #endif
pusVerification->startTask(); pusVerification->startTask();

View File

@ -25,9 +25,11 @@
#include <mission/devices/MGMHandlerLIS3MDL.h> #include <mission/devices/MGMHandlerLIS3MDL.h>
#include <mission/devices/MGMHandlerRM3100.h> #include <mission/devices/MGMHandlerRM3100.h>
#include <mission/devices/GyroL3GD20Handler.h> #include <mission/devices/GyroL3GD20Handler.h>
#include <mission/devices/PlocHandler.h>
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h> #include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
#include <mission/devices/devicedefinitions/SyrlinksDefinitions.h> #include <mission/devices/devicedefinitions/SyrlinksDefinitions.h>
#include <mission/devices/devicedefinitions/PlocDefinitions.h>
#include <mission/utility/TmFunnel.h> #include <mission/utility/TmFunnel.h>
#include <linux/csp/CspCookie.h> #include <linux/csp/CspCookie.h>
@ -406,17 +408,23 @@ void ObjectFactory::produce(){
#endif /* Q7S_ADD_RTS_DEVICES == 1 */ #endif /* Q7S_ADD_RTS_DEVICES == 1 */
I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, IMTQ::MAX_REPLY_SIZE,
std::string("/dev/i2c-0"));
IMTQHandler* imtqHandler = new IMTQHandler(objects::IMTQ_HANDLER, objects::I2C_COM_IF, imtqI2cCookie);
imtqHandler->setStartUpImmediately();
UartCookie* plocUartCookie = new UartCookie(std::string("/dev/ttyUL3"), 115200,
PLOC::MAX_REPLY_SIZE);
PlocHandler* plocHandler = new PlocHandler(objects::PLOC_HANDLER, objects::UART_COM_IF,
plocUartCookie);
plocHandler->setStartUpImmediately();
#endif /* TE0720 == 0 */ #endif /* TE0720 == 0 */
new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR, objects::TM_STORE, new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR, objects::TM_STORE,
objects::TC_STORE); objects::TC_STORE);
new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE); new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, IMTQ::MAX_REPLY_SIZE,
std::string("/dev/i2c-0"));
IMTQHandler* imtqHandler = new IMTQHandler(objects::IMTQ_HANDLER, objects::I2C_COM_IF, imtqI2cCookie);
imtqHandler->setStartUpImmediately();
#if TE0720 == 1 && TEST_LIBGPIOD == 1 #if TE0720 == 1 && TEST_LIBGPIOD == 1
/* Configure MIO0 as input */ /* Configure MIO0 as input */
GpiodRegular gpioConfigMio0(std::string("gpiochip0"), 0, GpiodRegular gpioConfigMio0(std::string("gpiochip0"), 0,
@ -426,11 +434,18 @@ void ObjectFactory::produce(){
new LibgpiodTest(objects::LIBGPIOD_TEST, objects::GPIO_IF, gpioCookie); new LibgpiodTest(objects::LIBGPIOD_TEST, objects::GPIO_IF, gpioCookie);
#elif TE0720 == 1 #elif TE0720 == 1
/* Configuration for MIO0 on TE0720-03-1CFA */ /* Configuration for MIO0 on TE0720-03-1CFA */
GpiodRegular gpioConfigForDummyHeater(std::string("gpiochip0"), 0, GpiodRegular* heaterGpio = new GpiodRegular(std::string("gpiochip0"), 0, std::string("MIO0"), gpio::IN, 0);
std::string("Heater0"), gpio::OUT, 0); GpioCookie* gpioCookie = new GpioCookie;
heaterGpiosCookie->addGpio(gpioIds::HEATER_0, gpioConfigForDummyHeater); gpioCookie->addGpio(gpioIds::HEATER_0, heaterGpio);
new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, heaterGpiosCookie, new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, gpioCookie, objects::PCDU_HANDLER,
objects::PCDU_HANDLER, pcduSwitches::TCS_BOARD_8V_HEATER_IN); pcduSwitches::TCS_BOARD_8V_HEATER_IN);
UartCookie* plocUartCookie = new UartCookie(std::string("/dev/ttyPS1"), 115200,
PLOC::MAX_REPLY_SIZE);
/* Testing PlocHandler on TE0720-03-1CFA */
PlocHandler* plocHandler = new PlocHandler(objects::PLOC_HANDLER, objects::UART_COM_IF,
plocUartCookie);
plocHandler->setStartUpImmediately();
#endif #endif
#if Q7S_ADD_SPI_TEST == 1 #if Q7S_ADD_SPI_TEST == 1

View File

@ -58,8 +58,9 @@ ReturnValue_t HeaterHandler::initialize() {
if(mainLineSwitcherObjectId != objects::NO_OBJECT) { if(mainLineSwitcherObjectId != objects::NO_OBJECT) {
mainLineSwitcher = objectManager->get<PowerSwitchIF>(mainLineSwitcherObjectId); mainLineSwitcher = objectManager->get<PowerSwitchIF>(mainLineSwitcherObjectId);
if (mainLineSwitcher == nullptr) { if (mainLineSwitcher == nullptr) {
sif::error << "HeaterHandler::initialize: Main line switcher failed to fetch object" sif::error
<< "from object ID." << std::endl; << "HeaterHandler::initialize: Failed to get main line switcher. Make sure "
<< "main line switcher object is initialized." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
} }

View File

@ -21,7 +21,8 @@ enum: uint8_t {
MGM_RM3100, MGM_RM3100,
PCDU_HANDLER, PCDU_HANDLER,
HEATER_HANDLER, HEATER_HANDLER,
SA_DEPL_HANDLER SA_DEPL_HANDLER,
PLOC_HANDLER
}; };
} }

View File

@ -52,6 +52,7 @@ namespace objects {
GYRO_2_L3G_HANDLER = 0x44000013, GYRO_2_L3G_HANDLER = 0x44000013,
IMTQ_HANDLER = 0x44000014, IMTQ_HANDLER = 0x44000014,
PLOC_HANDLER = 0x44000015,
/* Custom device handler */ /* Custom device handler */
PCDU_HANDLER = 0x44001000, PCDU_HANDLER = 0x44001000,

View File

@ -5,13 +5,13 @@
#include <fsfw/devicehandlers/DeviceHandlerIF.h> #include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h> #include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include <fsfwconfig/objects/systemObjectList.h> #include <fsfwconfig/objects/systemObjectList.h>
#include <fsfwconfig/OBSWConfig.h>
ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
{ {
/* Length of a communication cycle */ /* Length of a communication cycle */
uint32_t length = thisSequence->getPeriodMs(); uint32_t length = thisSequence->getPeriodMs();
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0, thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0,
DeviceHandlerIF::PERFORM_OPERATION); DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0, thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0,
@ -40,6 +40,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
#endif /* Q7S_ADD_RTD_DEVICES */ #endif /* Q7S_ADD_RTD_DEVICES */
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.2, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.2, DeviceHandlerIF::SEND_WRITE);
@ -64,6 +65,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
#endif /* Q7S_ADD_RTD_DEVICES */ #endif /* Q7S_ADD_RTD_DEVICES */
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.4, DeviceHandlerIF::GET_WRITE);
@ -88,6 +90,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
#endif /* Q7S_ADD_RTD_DEVICES */ #endif /* Q7S_ADD_RTD_DEVICES */
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.6, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.6, DeviceHandlerIF::SEND_READ);
@ -112,6 +115,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
#endif /* Q7S_ADD_RTD_DEVICES */ #endif /* Q7S_ADD_RTD_DEVICES */
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.8, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.8, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.8, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.8, DeviceHandlerIF::GET_READ);
@ -136,6 +140,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
#endif /* Q7S_ADD_RTD_DEVICES */ #endif /* Q7S_ADD_RTD_DEVICES */
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -290,3 +295,25 @@ ReturnValue_t pst::pollingSequenceAcsTest(FixedTimeslotTaskIF *thisSequence) {
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t pst::pollingSequenceTE0720(FixedTimeslotTaskIF *thisSequence) {
uint32_t length = thisSequence->getPeriodMs();
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.2,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.4,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.6,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.8,
DeviceHandlerIF::GET_READ);
if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Initialization of TE0720 PST failed" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -35,6 +35,11 @@ ReturnValue_t pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence);
ReturnValue_t gomspacePstInit(FixedTimeslotTaskIF *thisSequence); ReturnValue_t gomspacePstInit(FixedTimeslotTaskIF *thisSequence);
ReturnValue_t pollingSequenceAcsTest(FixedTimeslotTaskIF* thisSequence); ReturnValue_t pollingSequenceAcsTest(FixedTimeslotTaskIF* thisSequence);
/**
* @brief This polling sequence will be created when the software is compiled for the TE0720.
*/
ReturnValue_t pollingSequenceTE0720(FixedTimeslotTaskIF* thisSequence);
} }

View File

@ -20,6 +20,7 @@ enum {
SA_DEPL_HANDLER, SA_DEPL_HANDLER,
SYRLINKS_HANDLER, SYRLINKS_HANDLER,
IMTQ_HANDLER, IMTQ_HANDLER,
PLOC_HANDLER
}; };
} }

View File

@ -363,6 +363,9 @@ ReturnValue_t UartComIF::readReceivedMessage(CookieIF *cookie,
*buffer = uartDeviceMapIter->second.replyBuffer.data(); *buffer = uartDeviceMapIter->second.replyBuffer.data();
*size = uartDeviceMapIter->second.replyLen; *size = uartDeviceMapIter->second.replyLen;
/* Length is reset to 0 to prevent reading the same data twice */
uartDeviceMapIter->second.replyLen = 0;
return RETURN_OK; return RETURN_OK;
} }

View File

@ -13,6 +13,7 @@ target_sources(${TARGET_NAME} PUBLIC
SyrlinksHkHandler.cpp SyrlinksHkHandler.cpp
Max31865PT1000Handler.cpp Max31865PT1000Handler.cpp
IMTQHandler.cpp IMTQHandler.cpp
PlocHandler.cpp
) )

View File

@ -21,7 +21,7 @@ void IMTQHandler::doStartUp(){
if(mode == _MODE_START_UP){ if(mode == _MODE_START_UP){
//TODO: Set to MODE_ON again //TODO: Set to MODE_ON again
setMode(MODE_NORMAL); setMode(MODE_NORMAL);
communicationStep = CommunicationStep::SELT_TEST; communicationStep = CommunicationStep::SELF_TEST;
} }
} }

View File

@ -0,0 +1,476 @@
#include "PlocHandler.h"
#include <fsfwconfig/OBSWConfig.h>
#include <fsfw/globalfunctions/CRC.h>
#include <fsfw/datapool/PoolReadGuard.h>
#include <fsfwconfig/OBSWConfig.h>
PlocHandler::PlocHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) :
DeviceHandlerBase(objectId, comIF, comCookie) {
if (comCookie == NULL) {
sif::error << "PlocHandler: Invalid com cookie" << std::endl;
}
}
PlocHandler::~PlocHandler() {
}
void PlocHandler::doStartUp(){
if(mode == _MODE_START_UP){
setMode(MODE_ON);
}
}
void PlocHandler::doShutDown(){
}
ReturnValue_t PlocHandler::buildNormalDeviceCommand(
DeviceCommandId_t * id) {
return RETURN_OK;
}
ReturnValue_t PlocHandler::buildTransitionDeviceCommand(
DeviceCommandId_t * id){
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PlocHandler::buildCommandFromCommand(
DeviceCommandId_t deviceCommand, const uint8_t * commandData,
size_t commandDataLen) {
switch(deviceCommand) {
case(PLOC::TC_MEM_WRITE): {
return prepareTcMemWriteCommand(commandData, commandDataLen);
}
case(PLOC::TC_MEM_READ): {
return prepareTcMemReadCommand(commandData, commandDataLen);
}
default:
sif::debug << "PlocHandler::buildCommandFromCommand: Command not implemented" << std::endl;
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
return HasReturnvaluesIF::RETURN_FAILED;
}
void PlocHandler::fillCommandAndReplyMap() {
this->insertInCommandMap(PLOC::TC_MEM_WRITE);
this->insertInCommandMap(PLOC::TC_MEM_READ);
this->insertInReplyMap(PLOC::ACK_REPORT, 1, nullptr, PLOC::SIZE_ACK_REPORT);
this->insertInReplyMap(PLOC::EXE_REPORT, 3, nullptr, PLOC::SIZE_EXE_REPORT);
this->insertInReplyMap(PLOC::TM_MEMORY_READ_REPORT, 2, nullptr, PLOC::SIZE_TM_MEM_READ_REPORT);
}
ReturnValue_t PlocHandler::scanForReply(const uint8_t *start,
size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) {
ReturnValue_t result = RETURN_OK;
uint16_t apid = (*(start) << 8 | *(start + 1)) & APID_MASK;
switch(apid) {
case(PLOC::APID_ACK_SUCCESS):
*foundLen = PLOC::SIZE_ACK_REPORT;
*foundId = PLOC::ACK_REPORT;
break;
case(PLOC::APID_ACK_FAILURE):
*foundLen = PLOC::SIZE_ACK_REPORT;
*foundId = PLOC::ACK_REPORT;
break;
case(PLOC::APID_TM_MEMORY_READ_REPORT):
*foundLen = PLOC::SIZE_TM_MEM_READ_REPORT;
*foundId = PLOC::TM_MEMORY_READ_REPORT;
break;
case(PLOC::APID_EXE_SUCCESS):
*foundLen = PLOC::SIZE_EXE_REPORT;
*foundId = PLOC::EXE_REPORT;
break;
case(PLOC::APID_EXE_FAILURE):
*foundLen = PLOC::SIZE_EXE_REPORT;
*foundId = PLOC::EXE_REPORT;
break;
default: {
sif::debug << "PlocHandler::scanForReply: Reply has invalid apid" << std::endl;
*foundLen = remainingSize;
result = INVALID_APID;
break;
}
}
return result;
}
ReturnValue_t PlocHandler::interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) {
ReturnValue_t result = RETURN_OK;
switch (id) {
case PLOC::ACK_REPORT: {
result = handleAckReport(packet);
break;
}
case (PLOC::TM_MEMORY_READ_REPORT): {
result = handleMemoryReadReport(packet);
break;
}
case (PLOC::EXE_REPORT): {
result = handleExecutionReport(packet);
break;
}
default: {
sif::debug << "PlocHandler::interpretDeviceReply: Unknown device reply id" << std::endl;
return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY;
}
}
return result;
}
void PlocHandler::setNormalDatapoolEntriesInvalid(){
}
uint32_t PlocHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){
return 500;
}
ReturnValue_t PlocHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
return HasReturnvaluesIF::RETURN_OK;
}
void PlocHandler::setModeNormal() {
mode = MODE_NORMAL;
}
ReturnValue_t PlocHandler::prepareTcMemWriteCommand(const uint8_t * commandData,
size_t commandDataLen) {
const uint32_t memoryAddress = *(commandData) << 24 | *(commandData + 1) << 16
| *(commandData + 2) << 8 | *(commandData + 3);
const uint32_t memoryData = *(commandData + 4) << 24 | *(commandData + 5) << 16
| *(commandData + 6) << 8 | *(commandData + 7);
PLOC::TcMemWrite tcMemWrite(memoryAddress, memoryData);
if (tcMemWrite.getFullSize() > PLOC::MAX_COMMAND_SIZE) {
sif::debug << "PlocHandler::prepareTcMemWriteCommand: Command too big" << std::endl;
return RETURN_FAILED;
}
memcpy(commandBuffer, tcMemWrite.getWholeData(), tcMemWrite.getFullSize());
rawPacket = commandBuffer;
rawPacketLen = tcMemWrite.getFullSize();
nextReplyId = PLOC::ACK_REPORT;
return RETURN_OK;
}
ReturnValue_t PlocHandler::prepareTcMemReadCommand(const uint8_t * commandData,
size_t commandDataLen) {
const uint32_t memoryAddress = *(commandData) << 24 | *(commandData + 1) << 16
| *(commandData + 2) << 8 | *(commandData + 3);
PLOC::TcMemRead tcMemRead(memoryAddress);
if (tcMemRead.getFullSize() > PLOC::MAX_COMMAND_SIZE) {
sif::debug << "PlocHandler::prepareTcMemReadCommand: Command too big" << std::endl;
return RETURN_FAILED;
}
memcpy(commandBuffer, tcMemRead.getWholeData(), tcMemRead.getFullSize());
rawPacket = commandBuffer;
rawPacketLen = tcMemRead.getFullSize();
nextReplyId = PLOC::ACK_REPORT;
return RETURN_OK;
}
ReturnValue_t PlocHandler::verifyPacket(const uint8_t* start, size_t foundLen) {
uint16_t receivedCrc = *(start + foundLen - 2) << 8 | *(start + foundLen - 1);
uint16_t recalculatedCrc = CRC::crc16ccitt(start, foundLen - 2, 0);
if (receivedCrc != recalculatedCrc) {
return CRC_FAILURE;
}
return RETURN_OK;
}
ReturnValue_t PlocHandler::handleAckReport(const uint8_t* data) {
ReturnValue_t result = RETURN_OK;
result = verifyPacket(data, PLOC::SIZE_ACK_REPORT);
if(result == CRC_FAILURE) {
sif::error << "PlocHandler::handleAckReport: CRC failure" << std::endl;
nextReplyId = PLOC::NONE;
replyRawReplyIfnotWiretapped(data, PLOC::SIZE_ACK_REPORT);
triggerEvent(CRC_FAILURE_EVENT);
sendFailureReport(PLOC::ACK_REPORT, CRC_FAILURE);
disableAllReplies();
return IGNORE_REPLY_DATA;
}
uint16_t apid = (*(data) << 8 | *(data + 1)) & APID_MASK;
switch(apid) {
case PLOC::APID_ACK_FAILURE: {
//TODO: Interpretation of status field in acknowledgment report
sif::debug << "PlocHandler::handleAckReport: Received Ack failure report" << std::endl;
DeviceCommandId_t commandId = getPendingCommand();
if (commandId != DeviceHandlerIF::NO_COMMAND_ID) {
triggerEvent(ACK_FAILURE, commandId);
}
sendFailureReport(PLOC::ACK_REPORT, RECEIVED_ACK_FAILURE);
disableAllReplies();
nextReplyId = PLOC::NONE;
result = IGNORE_REPLY_DATA;
break;
}
case PLOC::APID_ACK_SUCCESS: {
setNextReplyId();
break;
}
default: {
sif::debug << "PlocHandler::handleAckReport: Invalid APID in Ack report" << std::endl;
result = RETURN_FAILED;
break;
}
}
return result;
}
ReturnValue_t PlocHandler::handleExecutionReport(const uint8_t* data) {
ReturnValue_t result = RETURN_OK;
result = verifyPacket(data, PLOC::SIZE_EXE_REPORT);
if(result == CRC_FAILURE) {
sif::error << "PlocHandler::handleExecutionReport: CRC failure" << std::endl;
nextReplyId = PLOC::NONE;
return result;
}
uint16_t apid = (*(data) << 8 | *(data + 1)) & APID_MASK;
switch (apid) {
case (PLOC::APID_EXE_SUCCESS): {
break;
}
case (PLOC::APID_EXE_FAILURE): {
//TODO: Interpretation of status field in execution report
sif::error << "PlocHandler::handleExecutionReport: Received execution failure report"
<< std::endl;
DeviceCommandId_t commandId = getPendingCommand();
if (commandId != DeviceHandlerIF::NO_COMMAND_ID) {
triggerEvent(EXE_FAILURE, commandId);
}
else {
sif::debug << "PlocHandler::handleExecutionReport: Unknown command id" << std::endl;
}
sendFailureReport(PLOC::EXE_REPORT, RECEIVED_EXE_FAILURE);
disableExeReportReply();
result = IGNORE_REPLY_DATA;
break;
}
default: {
sif::error << "PlocHandler::handleExecutionReport: Unknown APID" << std::endl;
result = RETURN_FAILED;
break;
}
}
nextReplyId = PLOC::NONE;
return result;
}
ReturnValue_t PlocHandler::handleMemoryReadReport(const uint8_t* data) {
ReturnValue_t result = RETURN_OK;
result = verifyPacket(data, PLOC::SIZE_TM_MEM_READ_REPORT);
if(result == CRC_FAILURE) {
sif::error << "PlocHandler::handleMemoryReadReport: Memory read report has invalid crc"
<< std::endl;
}
/** Send data to commanding queue */
handleDeviceTM(data + PLOC::DATA_FIELD_OFFSET, PLOC::SIZE_MEM_READ_REPORT_DATA,
PLOC::TM_MEMORY_READ_REPORT);
nextReplyId = PLOC::EXE_REPORT;
return result;
}
ReturnValue_t PlocHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command,
uint8_t expectedReplies, bool useAlternateId,
DeviceCommandId_t alternateReplyID) {
ReturnValue_t result = RETURN_OK;
uint8_t enabledReplies = 0;
switch (command->first) {
case PLOC::TC_MEM_WRITE:
enabledReplies = 2;
break;
case PLOC::TC_MEM_READ: {
enabledReplies = 3;
result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true,
PLOC::TM_MEMORY_READ_REPORT);
if (result != RETURN_OK) {
sif::debug << "PlocHandler::enableReplyInReplyMap: Reply with id "
<< PLOC::TM_MEMORY_READ_REPORT << " not in replyMap" << std::endl;
}
break;
}
default:
sif::debug << "PlocHandler::enableReplyInReplyMap: Unknown command id" << std::endl;
break;
}
/**
* Every command causes at least one acknowledgment and one execution report. Therefore both
* replies will be enabled here.
*/
result = DeviceHandlerBase::enableReplyInReplyMap(command,
enabledReplies, true, PLOC::ACK_REPORT);
if (result != RETURN_OK) {
sif::debug << "PlocHandler::enableReplyInReplyMap: Reply with id " << PLOC::ACK_REPORT
<< " not in replyMap" << std::endl;
}
result = DeviceHandlerBase::enableReplyInReplyMap(command,
enabledReplies, true, PLOC::EXE_REPORT);
if (result != RETURN_OK) {
sif::debug << "PlocHandler::enableReplyInReplyMap: Reply with id " << PLOC::EXE_REPORT
<< " not in replyMap" << std::endl;
}
return RETURN_OK;
}
void PlocHandler::setNextReplyId() {
switch(getPendingCommand()) {
case PLOC::TC_MEM_READ:
nextReplyId = PLOC::TM_MEMORY_READ_REPORT;
break;
default:
/* If no telemetry is expected the next reply is always the execution report */
nextReplyId = PLOC::EXE_REPORT;
break;
}
}
size_t PlocHandler::getNextReplyLength(DeviceCommandId_t commandId){
size_t replyLen = 0;
if (nextReplyId == PLOC::NONE) {
return replyLen;
}
DeviceReplyIter iter = deviceReplyMap.find(nextReplyId);
if (iter != deviceReplyMap.end()) {
if (iter->second.delayCycles == 0) {
/* Reply inactive */
return replyLen;
}
replyLen = iter->second.replyLen;
}
else {
sif::debug << "PlocHandler::getNextReplyLength: No entry for reply with reply id "
<< std::hex << nextReplyId << " in deviceReplyMap" << std::endl;
}
return replyLen;
}
void PlocHandler::handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId) {
ReturnValue_t result = RETURN_OK;
if (wiretappingMode == RAW) {
/* Data already sent in doGetRead() */
return;
}
DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId);
if (iter == deviceReplyMap.end()) {
sif::debug << "PlocHandler::handleDeviceTM: Unknown reply id" << std::endl;
return;
}
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
if (queueId == NO_COMMANDER) {
return;
}
result = actionHelper.reportData(queueId, replyId, data, dataSize);
if (result != RETURN_OK) {
sif::debug << "PlocHandler::handleDeviceTM: Failed to report data" << std::endl;
}
}
void PlocHandler::disableAllReplies() {
DeviceReplyMap::iterator iter;
/* Disable ack reply */
iter = deviceReplyMap.find(PLOC::ACK_REPORT);
DeviceReplyInfo *info = &(iter->second);
info->delayCycles = 0;
info->command = deviceCommandMap.end();
DeviceCommandId_t commandId = getPendingCommand();
/* If the command expects a telemetry packet the appropriate tm reply will be disabled here */
switch (commandId) {
case PLOC::TC_MEM_WRITE:
break;
case PLOC::TC_MEM_READ: {
iter = deviceReplyMap.find(PLOC::TM_MEMORY_READ_REPORT);
info = &(iter->second);
info->delayCycles = 0;
info->command = deviceCommandMap.end();
break;
}
default: {
sif::debug << "PlocHandler::disableAllReplies: Unknown command id" << commandId
<< std::endl;
break;
}
}
/* We must always disable the execution report reply here */
disableExeReportReply();
}
void PlocHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status) {
DeviceReplyIter iter = deviceReplyMap.find(replyId);
if (iter == deviceReplyMap.end()) {
sif::debug << "PlocHandler::sendFailureReport: Reply not in reply map" << std::endl;
return;
}
DeviceCommandInfo* info = &(iter->second.command->second);
if (info == nullptr) {
sif::debug << "PlocHandler::sendFailureReport: Reply has no active command" << std::endl;
return;
}
if (info->sendReplyTo != NO_COMMANDER) {
actionHelper.finish(false, info->sendReplyTo, iter->first, status);
}
info->isExecuting = false;
}
void PlocHandler::disableExeReportReply() {
DeviceReplyIter iter = deviceReplyMap.find(PLOC::EXE_REPORT);
DeviceReplyInfo *info = &(iter->second);
info->delayCycles = 0;
info->command = deviceCommandMap.end();
/* Expected replies is set to one here. The value will set to 0 in replyToReply() */
info->command->second.expectedReplies = 0;
}

View File

@ -0,0 +1,173 @@
#ifndef MISSION_DEVICES_PLOCHANDLER_H_
#define MISSION_DEVICES_PLOCHANDLER_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <mission/devices/devicedefinitions/PlocDefinitions.h>
#include <string.h>
/**
* @brief This is the device handler for the PLOC.
*
* @details The PLOC uses the space packet protocol for communication. On each command the PLOC
* answers at least with one acknowledgment and one execution report.
*
* @author J. Meier
*/
class PlocHandler: public DeviceHandlerBase {
public:
PlocHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie);
virtual ~PlocHandler();
/**
* @brief Sets mode to MODE_NORMAL. Can be used for debugging.
*/
void setModeNormal();
protected:
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) override;
void fillCommandAndReplyMap() override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t * commandData,size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize,
DeviceCommandId_t *foundId, size_t *foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) override;
void setNormalDatapoolEntriesInvalid() override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command,
uint8_t expectedReplies = 1, bool useAlternateId = false,
DeviceCommandId_t alternateReplyID = 0) override;
size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override;
private:
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_HANDLER;
static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0); //!> Space Packet received from PLOC has invalid CRC
static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1); //!> Received ACK failure reply from PLOC
static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2); //!> Received execution failure reply from PLOC
static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3); //!> Received space packet with invalid APID from PLOC
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_HANDLER;
static const Event MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW); //!> PLOC crc failure in telemetry packet
static const Event ACK_FAILURE = MAKE_EVENT(2, severity::LOW); //!> PLOC receive acknowledgment failure report
static const Event EXE_FAILURE = MAKE_EVENT(3, severity::LOW); //!> PLOC receive execution failure report
static const Event CRC_FAILURE_EVENT = MAKE_EVENT(4, severity::LOW); //!> PLOC reply has invalid crc
static const uint16_t APID_MASK = 0x7FF;
uint8_t commandBuffer[PLOC::MAX_COMMAND_SIZE];
/**
* This variable is used to store the id of the next reply to receive. This is necessary
* because the PLOC sends as reply to each command at least one acknowledgment and execution
* report.
*/
DeviceCommandId_t nextReplyId = PLOC::NONE;
/**
* @brief This function fills the commandBuffer to initiate the write memory command.
*
* @param commandData Pointer to action command data.
* @param commanDataLen Size of command data in bytes.
*
* @return RETURN_OK if successful, else RETURN_FAILURE.
*/
ReturnValue_t prepareTcMemWriteCommand(const uint8_t * commandData, size_t commandDataLen);
/**
* @brief This function fills the commandBuffer to initiate the write reads command.
*
* @param commandData Pointer to action command data.
* @param commanDataLen Size of command data in bytes.
*
* @return RETURN_OK if successful, else RETURN_FAILURE.
*/
ReturnValue_t prepareTcMemReadCommand(const uint8_t * commandData, size_t commandDataLen);
/**
* @brief This function checks the crc of the received PLOC reply.
*
* @param start Pointer to the first byte of the reply.
* @param foundLen Pointer to the length of the whole packet.
*
* @return RETURN_OK if CRC is ok, otherwise CRC_FAILURE.
*/
ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen);
/**
* @brief This function handles the acknowledgment report.
*
* @param data Pointer to the data holding the acknowledgment report.
*
* @return RETURN_OK if successful, otherwise an error code.
*/
ReturnValue_t handleAckReport(const uint8_t* data);
/**
* @brief This function handles the data of a execution report.
*
* @param data Pointer to the received data packet.
*
* @return RETURN_OK if successful, otherwise an error code.
*/
ReturnValue_t handleExecutionReport(const uint8_t* data);
/**
* @brief This function handles the memory read report.
*
* @param data Pointer to the data buffer holding the memory read report.
*
* @return RETURN_OK if successful, otherwise an error code.
*/
ReturnValue_t handleMemoryReadReport(const uint8_t* data);
/**
* @brief Depending on the current active command, this function sets the reply id of the
* next reply after a successful acknowledgment report has been received. This is
* required by the function getNextReplyLength() to identify the length of the next
* reply to read.
*/
void setNextReplyId();
/**
* @brief This function handles action message replies in case the telemetry has been
* requested by another object.
*
* @param data Pointer to the telemetry data.
* @param dataSize Size of telemetry in bytes.
* @param replyId Id of the reply. This will be added to the ActionMessage.
*/
void handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId);
/**
* @brief In case an acknowledgment failure reply has been received this function disables
* all previously enabled commands and resets the exepected replies variable of an
* active command.
*/
void disableAllReplies();
/**
* @brief This function sends a failure report if the active action was commanded by an other
* object.
*
* @param replyId The id of the reply which signals a failure.
* @param status A status byte which gives information about the failure type.
*/
void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status);
/**
* @brief This function disables the execution report reply. Within this function also the
* the variable expectedReplies of an active command will be set to 0.
*/
void disableExeReportReply();
};
#endif /* MISSION_DEVICES_PLOCHANDLER_H_ */

View File

@ -32,6 +32,7 @@ namespace IMTQ {
static const uint8_t MAX_REPLY_SIZE = SIZE_ENG_HK_DATA_REPLY; static const uint8_t MAX_REPLY_SIZE = SIZE_ENG_HK_DATA_REPLY;
static const uint8_t MAX_COMMAND_SIZE = 9; static const uint8_t MAX_COMMAND_SIZE = 9;
/** Define entries in IMTQ specific dataset */
static const uint8_t ENG_HK_SET_POOL_ENTRIES = 11; static const uint8_t ENG_HK_SET_POOL_ENTRIES = 11;
static const uint8_t CAL_MTM_POOL_ENTRIES = 4; static const uint8_t CAL_MTM_POOL_ENTRIES = 4;

View File

@ -0,0 +1,173 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_PLOCDEFINITIONS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_PLOCDEFINITIONS_H_
#include <fsfw/tmtcpacket/SpacePacket.h>
#include <fsfw/globalfunctions/CRC.h>
#include <fsfw/serialize/SerializeAdapter.h>
namespace PLOC {
static const DeviceCommandId_t NONE = 0x0;
static const DeviceCommandId_t TC_MEM_WRITE = 0x1;
static const DeviceCommandId_t TC_MEM_READ = 0x2;
static const DeviceCommandId_t ACK_REPORT = 0x3;
static const DeviceCommandId_t EXE_REPORT = 0x5;
static const DeviceCommandId_t TM_MEMORY_READ_REPORT = 0x6;
static const uint16_t SIZE_ACK_REPORT = 14;
static const uint16_t SIZE_EXE_REPORT = 14;
static const uint16_t SIZE_TM_MEM_READ_REPORT = 18;
/**
* SpacePacket apids of PLOC telecommands and telemetry.
*/
static const uint16_t APID_TC_MEM_WRITE = 0x714;
static const uint16_t APID_TC_MEM_READ = 0x715;
static const uint16_t APID_TM_MEMORY_READ_REPORT = 0x404;
static const uint16_t APID_ACK_SUCCESS = 0x400;
static const uint16_t APID_ACK_FAILURE = 0x401;
static const uint16_t APID_EXE_SUCCESS = 0x402;
static const uint16_t APID_EXE_FAILURE = 0x403;
/** Offset from first byte in Space packet to first byte of data field */
static const uint8_t DATA_FIELD_OFFSET = 6;
/**
* The size of payload data which will be forwarded to the requesting object. e.g. PUS Service
* 8.
*/
static const uint8_t SIZE_MEM_READ_REPORT_DATA = 10;
/**
* PLOC space packet length for fixed size packets. This is the size of the whole packet data
* field. For the length field in the space packet this size will be substracted by one.
*/
static const uint16_t LENGTH_TC_MEM_WRITE = 12;
static const uint16_t LENGTH_TC_MEM_READ = 8;
static const size_t MAX_REPLY_SIZE = SIZE_TM_MEM_READ_REPORT;
static const size_t MAX_COMMAND_SIZE = 18;
/**
* @brief This class helps to build the memory read command for the PLOC.
*
* @details The last two bytes of the packet data field contain a CRC calculated over the whole
* space packet. This is the CRC-16-CCITT as specified in
* ECSS-E-ST-70-41C Telemetry and telecommand packet utilization.
*/
class TcMemRead : public SpacePacket {
public:
/**
* @brief Constructor
*
* @param memAddr The memory address to read from.
*/
TcMemRead(const uint32_t memAddr) :
SpacePacket(LENGTH_TC_MEM_READ - 1, true, APID_TC_MEM_READ) {
fillPacketDataField(&memAddr);
}
private:
/**
* @brief This function builds the packet data field for the mem read command.
*
* @param memAddrPtr Pointer to the memory address to read from.
*/
void fillPacketDataField(const uint32_t* memAddrPtr) {
/* Add memAddr to packet data field */
size_t serializedSize = 0;
uint8_t* memoryAddressPos = this->localData.fields.buffer;
SerializeAdapter::serialize<uint32_t>(memAddrPtr, &memoryAddressPos, &serializedSize,
sizeof(*memAddrPtr), SerializeIF::Endianness::BIG);
/* Add memLen to packet data field */
this->localData.fields.buffer[OFFSET_MEM_LEN_FIELD] = 0;
this->localData.fields.buffer[OFFSET_MEM_LEN_FIELD + 1] = 1;
/* Calculate crc */
uint16_t crc = CRC::crc16ccitt(this->localData.byteStream,
sizeof(CCSDSPrimaryHeader) + LENGTH_TC_MEM_READ - CRC_SIZE, 0);
/* Add crc to packet data field of space packet */
serializedSize = 0;
uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET;
SerializeAdapter::serialize<uint16_t>(&crc, &crcPos, &serializedSize,
sizeof(crc), SerializeIF::Endianness::BIG);
memcpy(this->localData.fields.buffer + CRC_OFFSET, &crc, sizeof(crc));
}
static const uint8_t OFFSET_MEM_LEN_FIELD = 4;
static const uint8_t CRC_OFFSET = 6;
};
/**
* @brief This class helps to generate the space packet to write to a memory address within
* the PLOC.
* @details The last two bytes of the packet data field contain a CRC calculated over the whole
* space packet. This is the CRC-16-CCITT as specified in
* ECSS-E-ST-70-41C Telemetry and telecommand packet utilization.
*/
class TcMemWrite : public SpacePacket {
public:
/**
* @brief Constructor
*
* @param memAddr The PLOC memory address where to write to.
* @param memoryData The data to write to the specified memory address.
*/
TcMemWrite(const uint32_t memAddr, const uint32_t memoryData) :
SpacePacket(LENGTH_TC_MEM_WRITE - 1, true, APID_TC_MEM_WRITE) {
fillPacketDataField(&memAddr, &memoryData);
}
private:
/**
* @brief This function builds the packet data field for the mem write command.
*
* @param memAddrPtr Pointer to the PLOC memory address where to write to.
* @param memoryDataPtr Pointer to the memoryData to write
*/
void fillPacketDataField(const uint32_t* memAddrPtr, const uint32_t* memoryDataPtr) {
/* Add memAddr to packet data field */
size_t serializedSize = 0;
uint8_t* memoryAddressPos = this->localData.fields.buffer;
SerializeAdapter::serialize<uint32_t>(memAddrPtr, &memoryAddressPos, &serializedSize,
sizeof(*memAddrPtr), SerializeIF::Endianness::BIG);
/* Add memLen to packet data field */
this->localData.fields.buffer[OFFSET_MEM_LEN_FIELD] = 0;
this->localData.fields.buffer[OFFSET_MEM_LEN_FIELD + 1] = 1;
/* Add memData to packet data field */
serializedSize = 0;
uint8_t* memoryDataPos = this->localData.fields.buffer + OFFSET_MEM_DATA_FIELD;
SerializeAdapter::serialize<uint32_t>(memoryDataPtr, &memoryDataPos, &serializedSize,
sizeof(*memoryDataPtr), SerializeIF::Endianness::BIG);
/* Calculate crc */
uint16_t crc = CRC::crc16ccitt(this->localData.byteStream,
sizeof(CCSDSPrimaryHeader) + LENGTH_TC_MEM_WRITE - CRC_SIZE, 0);
serializedSize = 0;
uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET;
/* Add crc to packet data field of space packet */
SerializeAdapter::serialize<uint16_t>(&crc, &crcPos, &serializedSize,
sizeof(crc), SerializeIF::Endianness::BIG);
memcpy(this->localData.fields.buffer + CRC_OFFSET, &crc, sizeof(crc));
}
/** Offsets from base address of packet data field */
static const uint8_t OFFSET_MEM_LEN_FIELD = 4;
static const uint8_t OFFSET_MEM_DATA_FIELD = 6;
static const uint8_t CRC_OFFSET = 10;
};
}
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_PLOCDEFINITIONS_H_ */

2
tmtc

@ -1 +1 @@
Subproject commit 4d2b7a61509a41e67cf62ecaa2864bba3acd9ef4 Subproject commit e23bc116088fc673aaec45768c7a07c20d75a2f6