Merge remote-tracking branch 'origin/develop' into meier/plocTmCamCmdReport
Some checks are pending
EIVE/eive-obsw/pipeline/pr-develop Build queued...
Some checks are pending
EIVE/eive-obsw/pipeline/pr-develop Build queued...
This commit is contained in:
@ -1,11 +1,16 @@
|
||||
add_subdirectory(csp)
|
||||
add_subdirectory(utility)
|
||||
add_subdirectory(callbacks)
|
||||
add_subdirectory(boardtest)
|
||||
add_subdirectory(devices)
|
||||
add_subdirectory(fsfwconfig)
|
||||
add_subdirectory(obc)
|
||||
add_subdirectory(ipcore)
|
||||
|
||||
target_sources(${OBSW_NAME} PUBLIC
|
||||
ObjectFactory.cpp
|
||||
)
|
||||
if(EIVE_ADD_LINUX_FSFWCONFIG)
|
||||
add_subdirectory(fsfwconfig)
|
||||
endif()
|
||||
|
||||
# Dependency on proprietary library
|
||||
if(TGT_BSP MATCHES "arm/q7s")
|
||||
add_subdirectory(csp)
|
||||
endif()
|
||||
|
||||
target_sources(${OBSW_NAME} PUBLIC ObjectFactory.cpp scheduling.cpp)
|
||||
|
@ -1,27 +1,41 @@
|
||||
#include "ObjectFactory.h"
|
||||
|
||||
#include <fsfw/power/PowerSwitchIF.h>
|
||||
#include <fsfw/subsystem/Subsystem.h>
|
||||
#include <fsfw_hal/common/gpio/GpioCookie.h>
|
||||
#include <fsfw_hal/common/gpio/GpioIF.h>
|
||||
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
|
||||
#include <fsfw_hal/linux/serial/SerialCookie.h>
|
||||
#include <fsfw_hal/linux/spi/SpiComIF.h>
|
||||
#include <fsfw_hal/linux/spi/SpiCookie.h>
|
||||
#include <linux/callbacks/gpioCallbacks.h>
|
||||
#include <mission/devices/Max31865PT1000Handler.h>
|
||||
#include <linux/devices/Max31865RtdPolling.h>
|
||||
#include <linux/devices/SusPolling.h>
|
||||
#include <mission/controller/AcsController.h>
|
||||
#include <mission/core/GenericFactory.h>
|
||||
#include <mission/devices/LegacySusHandler.h>
|
||||
#include <mission/devices/Max31865EiveHandler.h>
|
||||
#include <mission/devices/ScexDeviceHandler.h>
|
||||
#include <mission/devices/SusHandler.h>
|
||||
#include <mission/system/SusAssembly.h>
|
||||
#include <mission/system/TcsBoardAssembly.h>
|
||||
#include <mission/system/fdir/RtdFdir.h>
|
||||
#include <mission/system/fdir/SusFdir.h>
|
||||
#include <mission/system/objects/SusAssembly.h>
|
||||
#include <mission/system/objects/TcsBoardAssembly.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "devConf.h"
|
||||
#include "devices/addresses.h"
|
||||
#include "devices/gpioIds.h"
|
||||
#include "eive/definitions.h"
|
||||
#include "mission/system/tree/acsModeTree.h"
|
||||
#include "mission/system/tree/payloadModeTree.h"
|
||||
#include "mission/system/tree/tcsModeTree.h"
|
||||
|
||||
void ObjectFactory::createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiComIF,
|
||||
PowerSwitchIF* pwrSwitcher, std::string spiDev) {
|
||||
PowerSwitchIF& pwrSwitcher, std::string spiDev,
|
||||
bool swap0And6) {
|
||||
using namespace gpio;
|
||||
new SusPolling(objects::SUS_POLLING_TASK, *spiComIF, *gpioComIF);
|
||||
GpioCookie* gpioCookieSus = new GpioCookie();
|
||||
GpioCallback* susgpio = nullptr;
|
||||
|
||||
@ -67,100 +81,101 @@ void ObjectFactory::createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiCo
|
||||
#if OBSW_ADD_SUN_SENSORS == 1
|
||||
SusFdir* fdir = nullptr;
|
||||
std::array<SusHandler*, 12> susHandlers = {};
|
||||
SpiCookie* spiCookie = new SpiCookie(addresses::SUS_0, gpioIds::CS_SUS_0, SUS::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
SpiCookie* spiCookie =
|
||||
new SpiCookie(addresses::SUS_0, gpioIds::CS_SUS_0, susMax1227::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::SUS_CS_TIMEOUT);
|
||||
susHandlers[0] =
|
||||
new SusHandler(objects::SUS_0_N_LOC_XFYFZM_PT_XF, 0, objects::SPI_MAIN_COM_IF, spiCookie);
|
||||
new SusHandler(objects::SUS_0_N_LOC_XFYFZM_PT_XF, 0, objects::SUS_POLLING_TASK, spiCookie);
|
||||
fdir = new SusFdir(objects::SUS_0_N_LOC_XFYFZM_PT_XF);
|
||||
susHandlers[0]->setParent(objects::SUS_BOARD_ASS);
|
||||
susHandlers[0]->setCustomFdir(fdir);
|
||||
|
||||
spiCookie = new SpiCookie(addresses::SUS_1, gpioIds::CS_SUS_1, SUS::MAX_CMD_SIZE,
|
||||
spiCookie = new SpiCookie(addresses::SUS_1, gpioIds::CS_SUS_1, susMax1227::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::SUS_CS_TIMEOUT);
|
||||
susHandlers[1] =
|
||||
new SusHandler(objects::SUS_1_N_LOC_XBYFZM_PT_XB, 1, objects::SPI_MAIN_COM_IF, spiCookie);
|
||||
new SusHandler(objects::SUS_1_N_LOC_XBYFZM_PT_XB, 1, objects::SUS_POLLING_TASK, spiCookie);
|
||||
fdir = new SusFdir(objects::SUS_1_N_LOC_XBYFZM_PT_XB);
|
||||
susHandlers[1]->setParent(objects::SUS_BOARD_ASS);
|
||||
susHandlers[1]->setCustomFdir(fdir);
|
||||
|
||||
spiCookie = new SpiCookie(addresses::SUS_2, gpioIds::CS_SUS_2, SUS::MAX_CMD_SIZE,
|
||||
spiCookie = new SpiCookie(addresses::SUS_2, gpioIds::CS_SUS_2, susMax1227::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::SUS_CS_TIMEOUT);
|
||||
susHandlers[2] =
|
||||
new SusHandler(objects::SUS_2_N_LOC_XFYBZB_PT_YB, 2, objects::SPI_MAIN_COM_IF, spiCookie);
|
||||
new SusHandler(objects::SUS_2_N_LOC_XFYBZB_PT_YB, 2, objects::SUS_POLLING_TASK, spiCookie);
|
||||
fdir = new SusFdir(objects::SUS_2_N_LOC_XFYBZB_PT_YB);
|
||||
susHandlers[2]->setParent(objects::SUS_BOARD_ASS);
|
||||
susHandlers[2]->setCustomFdir(fdir);
|
||||
|
||||
spiCookie = new SpiCookie(addresses::SUS_3, gpioIds::CS_SUS_3, SUS::MAX_CMD_SIZE,
|
||||
spiCookie = new SpiCookie(addresses::SUS_3, gpioIds::CS_SUS_3, susMax1227::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::SUS_CS_TIMEOUT);
|
||||
susHandlers[3] =
|
||||
new SusHandler(objects::SUS_3_N_LOC_XFYBZF_PT_YF, 3, objects::SPI_MAIN_COM_IF, spiCookie);
|
||||
new SusHandler(objects::SUS_3_N_LOC_XFYBZF_PT_YF, 3, objects::SUS_POLLING_TASK, spiCookie);
|
||||
fdir = new SusFdir(objects::SUS_3_N_LOC_XFYBZF_PT_YF);
|
||||
susHandlers[3]->setParent(objects::SUS_BOARD_ASS);
|
||||
susHandlers[3]->setCustomFdir(fdir);
|
||||
|
||||
spiCookie = new SpiCookie(addresses::SUS_4, gpioIds::CS_SUS_4, SUS::MAX_CMD_SIZE,
|
||||
spiCookie = new SpiCookie(addresses::SUS_4, gpioIds::CS_SUS_4, susMax1227::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::SUS_CS_TIMEOUT);
|
||||
susHandlers[4] =
|
||||
new SusHandler(objects::SUS_4_N_LOC_XMYFZF_PT_ZF, 4, objects::SPI_MAIN_COM_IF, spiCookie);
|
||||
new SusHandler(objects::SUS_4_N_LOC_XMYFZF_PT_ZF, 4, objects::SUS_POLLING_TASK, spiCookie);
|
||||
fdir = new SusFdir(objects::SUS_4_N_LOC_XMYFZF_PT_ZF);
|
||||
susHandlers[4]->setParent(objects::SUS_BOARD_ASS);
|
||||
susHandlers[4]->setCustomFdir(fdir);
|
||||
|
||||
spiCookie = new SpiCookie(addresses::SUS_5, gpioIds::CS_SUS_5, SUS::MAX_CMD_SIZE,
|
||||
spiCookie = new SpiCookie(addresses::SUS_5, gpioIds::CS_SUS_5, susMax1227::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::SUS_CS_TIMEOUT);
|
||||
susHandlers[5] =
|
||||
new SusHandler(objects::SUS_5_N_LOC_XFYMZB_PT_ZB, 5, objects::SPI_MAIN_COM_IF, spiCookie);
|
||||
new SusHandler(objects::SUS_5_N_LOC_XFYMZB_PT_ZB, 5, objects::SUS_POLLING_TASK, spiCookie);
|
||||
fdir = new SusFdir(objects::SUS_5_N_LOC_XFYMZB_PT_ZB);
|
||||
susHandlers[5]->setParent(objects::SUS_BOARD_ASS);
|
||||
susHandlers[5]->setCustomFdir(fdir);
|
||||
|
||||
spiCookie = new SpiCookie(addresses::SUS_6, gpioIds::CS_SUS_6, SUS::MAX_CMD_SIZE,
|
||||
spiCookie = new SpiCookie(addresses::SUS_6, gpioIds::CS_SUS_6, susMax1227::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::SUS_CS_TIMEOUT);
|
||||
susHandlers[6] =
|
||||
new SusHandler(objects::SUS_6_R_LOC_XFYBZM_PT_XF, 6, objects::SPI_MAIN_COM_IF, spiCookie);
|
||||
new SusHandler(objects::SUS_6_R_LOC_XFYBZM_PT_XF, 6, objects::SUS_POLLING_TASK, spiCookie);
|
||||
fdir = new SusFdir(objects::SUS_6_R_LOC_XFYBZM_PT_XF);
|
||||
susHandlers[6]->setParent(objects::SUS_BOARD_ASS);
|
||||
susHandlers[6]->setCustomFdir(fdir);
|
||||
|
||||
spiCookie = new SpiCookie(addresses::SUS_7, gpioIds::CS_SUS_7, SUS::MAX_CMD_SIZE,
|
||||
spiCookie = new SpiCookie(addresses::SUS_7, gpioIds::CS_SUS_7, susMax1227::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::SUS_CS_TIMEOUT);
|
||||
susHandlers[7] =
|
||||
new SusHandler(objects::SUS_7_R_LOC_XBYBZM_PT_XB, 7, objects::SPI_MAIN_COM_IF, spiCookie);
|
||||
new SusHandler(objects::SUS_7_R_LOC_XBYBZM_PT_XB, 7, objects::SUS_POLLING_TASK, spiCookie);
|
||||
fdir = new SusFdir(objects::SUS_7_R_LOC_XBYBZM_PT_XB);
|
||||
susHandlers[7]->setParent(objects::SUS_BOARD_ASS);
|
||||
susHandlers[7]->setCustomFdir(fdir);
|
||||
|
||||
spiCookie = new SpiCookie(addresses::SUS_8, gpioIds::CS_SUS_8, SUS::MAX_CMD_SIZE,
|
||||
spiCookie = new SpiCookie(addresses::SUS_8, gpioIds::CS_SUS_8, susMax1227::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::SUS_CS_TIMEOUT);
|
||||
susHandlers[8] =
|
||||
new SusHandler(objects::SUS_8_R_LOC_XBYBZB_PT_YB, 8, objects::SPI_MAIN_COM_IF, spiCookie);
|
||||
new SusHandler(objects::SUS_8_R_LOC_XBYBZB_PT_YB, 8, objects::SUS_POLLING_TASK, spiCookie);
|
||||
fdir = new SusFdir(objects::SUS_8_R_LOC_XBYBZB_PT_YB);
|
||||
susHandlers[8]->setParent(objects::SUS_BOARD_ASS);
|
||||
susHandlers[8]->setCustomFdir(fdir);
|
||||
|
||||
spiCookie = new SpiCookie(addresses::SUS_9, gpioIds::CS_SUS_9, SUS::MAX_CMD_SIZE,
|
||||
spiCookie = new SpiCookie(addresses::SUS_9, gpioIds::CS_SUS_9, susMax1227::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::SUS_CS_TIMEOUT);
|
||||
susHandlers[9] =
|
||||
new SusHandler(objects::SUS_9_R_LOC_XBYBZB_PT_YF, 9, objects::SPI_MAIN_COM_IF, spiCookie);
|
||||
new SusHandler(objects::SUS_9_R_LOC_XBYBZB_PT_YF, 9, objects::SUS_POLLING_TASK, spiCookie);
|
||||
fdir = new SusFdir(objects::SUS_9_R_LOC_XBYBZB_PT_YF);
|
||||
susHandlers[9]->setParent(objects::SUS_BOARD_ASS);
|
||||
susHandlers[9]->setCustomFdir(fdir);
|
||||
|
||||
spiCookie = new SpiCookie(addresses::SUS_10, gpioIds::CS_SUS_10, SUS::MAX_CMD_SIZE,
|
||||
spiCookie = new SpiCookie(addresses::SUS_10, gpioIds::CS_SUS_10, susMax1227::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::SUS_CS_TIMEOUT);
|
||||
susHandlers[10] =
|
||||
new SusHandler(objects::SUS_10_N_LOC_XMYBZF_PT_ZF, 10, objects::SPI_MAIN_COM_IF, spiCookie);
|
||||
new SusHandler(objects::SUS_10_N_LOC_XMYBZF_PT_ZF, 10, objects::SUS_POLLING_TASK, spiCookie);
|
||||
fdir = new SusFdir(objects::SUS_10_N_LOC_XMYBZF_PT_ZF);
|
||||
susHandlers[10]->setParent(objects::SUS_BOARD_ASS);
|
||||
susHandlers[10]->setCustomFdir(fdir);
|
||||
|
||||
spiCookie = new SpiCookie(addresses::SUS_11, gpioIds::CS_SUS_11, SUS::MAX_CMD_SIZE,
|
||||
spiCookie = new SpiCookie(addresses::SUS_11, gpioIds::CS_SUS_11, susMax1227::MAX_CMD_SIZE,
|
||||
spi::SUS_MAX_1227_MODE, spi::SUS_MAX1227_SPI_FREQ);
|
||||
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::SUS_CS_TIMEOUT);
|
||||
susHandlers[11] =
|
||||
new SusHandler(objects::SUS_11_R_LOC_XBYMZB_PT_ZB, 11, objects::SPI_MAIN_COM_IF, spiCookie);
|
||||
new SusHandler(objects::SUS_11_R_LOC_XBYMZB_PT_ZB, 11, objects::SUS_POLLING_TASK, spiCookie);
|
||||
fdir = new SusFdir(objects::SUS_11_R_LOC_XBYMZB_PT_ZB);
|
||||
susHandlers[11]->setParent(objects::SUS_BOARD_ASS);
|
||||
susHandlers[11]->setCustomFdir(fdir);
|
||||
|
||||
for (auto& sus : susHandlers) {
|
||||
@ -174,22 +189,16 @@ void ObjectFactory::createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiCo
|
||||
#endif
|
||||
}
|
||||
}
|
||||
std::array<object_id_t, 12> susIds = {
|
||||
objects::SUS_0_N_LOC_XFYFZM_PT_XF, objects::SUS_1_N_LOC_XBYFZM_PT_XB,
|
||||
objects::SUS_2_N_LOC_XFYBZB_PT_YB, objects::SUS_3_N_LOC_XFYBZF_PT_YF,
|
||||
objects::SUS_4_N_LOC_XMYFZF_PT_ZF, objects::SUS_5_N_LOC_XFYMZB_PT_ZB,
|
||||
objects::SUS_6_R_LOC_XFYBZM_PT_XF, objects::SUS_7_R_LOC_XBYBZM_PT_XB,
|
||||
objects::SUS_8_R_LOC_XBYBZB_PT_YB, objects::SUS_9_R_LOC_XBYBZB_PT_YF,
|
||||
objects::SUS_10_N_LOC_XMYBZF_PT_ZF, objects::SUS_11_R_LOC_XBYMZB_PT_ZB};
|
||||
SusAssHelper susAssHelper = SusAssHelper(susIds);
|
||||
auto susAss =
|
||||
new SusAssembly(objects::SUS_BOARD_ASS, objects::NO_OBJECT, pwrSwitcher, susAssHelper);
|
||||
static_cast<void>(susAss);
|
||||
std::array<DeviceHandlerBase*, 12> susDhbs;
|
||||
for (unsigned i = 0; i < susDhbs.size(); i++) {
|
||||
susDhbs[i] = susHandlers[i];
|
||||
}
|
||||
createSusAssy(pwrSwitcher, susDhbs);
|
||||
#endif /* OBSW_ADD_SUN_SENSORS == 1 */
|
||||
}
|
||||
|
||||
void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF,
|
||||
PowerSwitchIF* pwrSwitcher) {
|
||||
PowerSwitchIF* pwrSwitcher, SpiComIF* comIF) {
|
||||
using namespace gpio;
|
||||
GpioCookie* rtdGpioCookie = new GpioCookie;
|
||||
|
||||
@ -245,8 +254,8 @@ void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF,
|
||||
gpioChecker(gpioComIF->addGpios(rtdGpioCookie), "RTDs");
|
||||
|
||||
#if OBSW_ADD_RTD_DEVICES == 1
|
||||
static constexpr uint8_t NUMBER_RTDS = 16;
|
||||
std::array<std::pair<address_t, gpioId_t>, NUMBER_RTDS> cookieArgs = {{
|
||||
using namespace EiveMax31855;
|
||||
std::array<std::pair<address_t, gpioId_t>, NUM_RTDS> cookieArgs = {{
|
||||
{addresses::RTD_IC_3, gpioIds::RTD_IC_3},
|
||||
{addresses::RTD_IC_4, gpioIds::RTD_IC_4},
|
||||
{addresses::RTD_IC_5, gpioIds::RTD_IC_5},
|
||||
@ -264,57 +273,71 @@ void ObjectFactory::createRtdComponents(std::string spiDev, GpioIF* gpioComIF,
|
||||
{addresses::RTD_IC_17, gpioIds::RTD_IC_17},
|
||||
{addresses::RTD_IC_18, gpioIds::RTD_IC_18},
|
||||
}};
|
||||
std::array<object_id_t, NUMBER_RTDS> rtdIds = {objects::RTD_0_IC3_PLOC_HEATSPREADER,
|
||||
objects::RTD_1_IC4_PLOC_MISSIONBOARD,
|
||||
objects::RTD_2_IC5_4K_CAMERA,
|
||||
objects::RTD_3_IC6_DAC_HEATSPREADER,
|
||||
objects::RTD_4_IC7_STARTRACKER,
|
||||
objects::RTD_5_IC8_RW1_MX_MY,
|
||||
objects::RTD_6_IC9_DRO,
|
||||
objects::RTD_7_IC10_SCEX,
|
||||
objects::RTD_8_IC11_X8,
|
||||
objects::RTD_9_IC12_HPA,
|
||||
objects::RTD_10_IC13_PL_TX,
|
||||
objects::RTD_11_IC14_MPA,
|
||||
objects::RTD_12_IC15_ACU,
|
||||
objects::RTD_13_IC16_PLPCDU_HEATSPREADER,
|
||||
objects::RTD_14_IC17_TCS_BOARD,
|
||||
objects::RTD_15_IC18_IMTQ};
|
||||
std::array<SpiCookie*, NUMBER_RTDS> rtdCookies = {};
|
||||
std::array<Max31865PT1000Handler*, NUMBER_RTDS> rtds = {};
|
||||
// HSPD: Heatspreader
|
||||
|
||||
std::array<SpiCookie*, NUM_RTDS> rtdCookies = {};
|
||||
std::array<Max31865EiveHandler*, NUM_RTDS> rtds = {};
|
||||
RtdFdir* rtdFdir = nullptr;
|
||||
for (uint8_t idx = 0; idx < NUMBER_RTDS; idx++) {
|
||||
rtdCookies[idx] =
|
||||
new SpiCookie(cookieArgs[idx].first, cookieArgs[idx].second,
|
||||
Max31865Definitions::MAX_REPLY_SIZE, spi::RTD_MODE, spi::RTD_SPEED);
|
||||
rtds[idx] = new Max31865PT1000Handler(rtdIds[idx], objects::SPI_MAIN_COM_IF, rtdCookies[idx]);
|
||||
rtds[idx]->setParent(objects::TCS_BOARD_ASS);
|
||||
rtdFdir = new RtdFdir(rtdIds[idx]);
|
||||
|
||||
TcsBoardAssembly* tcsBoardAss = ObjectFactory::createTcsBoardAssy(*pwrSwitcher);
|
||||
|
||||
// Create special low level reader communication interface
|
||||
new Max31865RtdPolling(objects::SPI_RTD_COM_IF, comIF, gpioComIF);
|
||||
for (uint8_t idx = 0; idx < NUM_RTDS; idx++) {
|
||||
rtdCookies[idx] = new SpiCookie(cookieArgs[idx].first, cookieArgs[idx].second,
|
||||
MAX31865::MAX_REPLY_SIZE, spi::RTD_MODE, spi::RTD_SPEED);
|
||||
rtdCookies[idx]->setMutexParams(MutexIF::TimeoutType::WAITING, spi::RTD_CS_TIMEOUT);
|
||||
Max31865ReaderCookie* rtdLowLevelCookie =
|
||||
new Max31865ReaderCookie(RTD_INFOS[idx].first, idx, RTD_INFOS[idx].second, rtdCookies[idx]);
|
||||
rtds[idx] =
|
||||
new Max31865EiveHandler(RTD_INFOS[idx].first, objects::SPI_RTD_COM_IF, rtdLowLevelCookie);
|
||||
rtds[idx]->setDeviceInfo(idx, RTD_INFOS[idx].second);
|
||||
ReturnValue_t result = rtds[idx]->connectModeTreeParent(*tcsBoardAss);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "Connecting RTD " << static_cast<int>(idx) << " to RTD Assembly failed"
|
||||
<< std::endl;
|
||||
}
|
||||
rtdFdir = new RtdFdir(RTD_INFOS[idx].first);
|
||||
rtds[idx]->setCustomFdir(rtdFdir);
|
||||
rtds[idx]->setDeviceIdx(idx + 3);
|
||||
#if OBSW_DEBUG_RTD == 1
|
||||
rtds[idx]->setDebugMode(true);
|
||||
rtds[idx]->setDebugMode(true, 5);
|
||||
#endif
|
||||
#if OBSW_TEST_RTD == 1
|
||||
rtds[idx]->setInstantNormal(true);
|
||||
rtds[idx]->setStartUpImmediately();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if OBSW_TEST_RTD == 1
|
||||
for (auto& rtd : rtds) {
|
||||
if (rtd != nullptr) {
|
||||
rtd->setStartUpImmediately();
|
||||
rtd->setInstantNormal(true);
|
||||
}
|
||||
}
|
||||
#endif // OBSW_TEST_RTD == 1
|
||||
TcsBoardHelper helper(rtdIds);
|
||||
TcsBoardAssembly* tcsBoardAss =
|
||||
new TcsBoardAssembly(objects::TCS_BOARD_ASS, objects::NO_OBJECT, pwrSwitcher,
|
||||
pcdu::Switches::PDU1_CH0_TCS_BOARD_3V3, helper);
|
||||
static_cast<void>(tcsBoardAss);
|
||||
#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 SerialCookie(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());
|
||||
}
|
||||
scexHandler->connectModeTreeParent(satsystem::pl::SUBSYSTEM);
|
||||
}
|
||||
|
||||
AcsController* ObjectFactory::createAcsController(bool connectSubsystem) {
|
||||
auto acsCtrl = new AcsController(objects::ACS_CONTROLLER);
|
||||
if (connectSubsystem) {
|
||||
acsCtrl->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
|
||||
}
|
||||
return acsCtrl;
|
||||
}
|
||||
|
||||
void ObjectFactory::gpioChecker(ReturnValue_t result, std::string output) {
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "ObjectFactory: Adding GPIOs failed for " << output << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <fsfw/power/definitions.h>
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
|
||||
#include <mission/memory/SdCardMountedIF.h>
|
||||
#include <mission/tmtc/CcsdsIpCoreHandler.h>
|
||||
#include <mission/tmtc/CfdpTmFunnel.h>
|
||||
#include <mission/tmtc/PusTmFunnel.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "mission/devices/HeaterHandler.h"
|
||||
|
||||
class GpioIF;
|
||||
class SpiComIF;
|
||||
class PowerSwitchIF;
|
||||
class AcsController;
|
||||
|
||||
namespace ObjectFactory {
|
||||
|
||||
void createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiComIF, PowerSwitchIF* pwrSwitcher,
|
||||
std::string spiDev);
|
||||
void createRtdComponents(std::string spiDev, GpioIF* gpioComIF, PowerSwitchIF* pwrSwitcher);
|
||||
void createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiComIF, PowerSwitchIF& pwrSwitcher,
|
||||
std::string spiDev, bool swap0And6);
|
||||
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);
|
||||
|
||||
AcsController* createAcsController(bool connectSubsystem);
|
||||
|
||||
} // namespace ObjectFactory
|
||||
|
@ -1,10 +1,2 @@
|
||||
target_sources(${OBSW_NAME} PRIVATE
|
||||
LibgpiodTest.cpp
|
||||
I2cTestClass.cpp
|
||||
SpiTestClass.cpp
|
||||
UartTestClass.cpp
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
target_sources(${OBSW_NAME} PRIVATE LibgpiodTest.cpp I2cTestClass.cpp
|
||||
SpiTestClass.cpp UartTestClass.cpp)
|
||||
|
@ -17,20 +17,20 @@ ReturnValue_t I2cTestClass::initialize() {
|
||||
if (mode == TestModes::BPX_BATTERY) {
|
||||
battInit();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t I2cTestClass::performPeriodicAction() {
|
||||
if (mode == TestModes::BPX_BATTERY) {
|
||||
battPeriodic();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void I2cTestClass::battInit() {
|
||||
sif::info << "I2cTestClass: BPX Initialization" << std::endl;
|
||||
UnixFileGuard fileHelper(i2cdev, &bpxInfo.fd, O_RDWR, "I2cTestClass::sendMessage");
|
||||
if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||
UnixFileGuard fileHelper(i2cdev, bpxInfo.fd, O_RDWR, "I2cTestClass::sendMessage");
|
||||
if (fileHelper.getOpenResult() != returnvalue::OK) {
|
||||
sif::error << "Opening I2C device" << i2cdev << " failed" << std::endl;
|
||||
return;
|
||||
}
|
||||
@ -41,13 +41,13 @@ void I2cTestClass::battInit() {
|
||||
cmdBuf[1] = 0x42;
|
||||
sendLen = 2;
|
||||
ReturnValue_t result = i2cWrite(bpxInfo.fd, cmdBuf.data(), sendLen);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
// Receive back port, error byte and ping reply
|
||||
recvLen = 3;
|
||||
result = i2cRead(bpxInfo.fd, replyBuf.data(), recvLen);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
sif::info << "Ping reply:" << std::endl;
|
||||
@ -58,8 +58,8 @@ void I2cTestClass::battInit() {
|
||||
}
|
||||
|
||||
void I2cTestClass::battPeriodic() {
|
||||
UnixFileGuard fileHelper(i2cdev, &bpxInfo.fd, O_RDWR, "I2cTestClass::sendMessage");
|
||||
if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||
UnixFileGuard fileHelper(i2cdev, bpxInfo.fd, O_RDWR, "I2cTestClass::sendMessage");
|
||||
if (fileHelper.getOpenResult() != returnvalue::OK) {
|
||||
sif::error << "Opening I2C device" << i2cdev << " failed" << std::endl;
|
||||
return;
|
||||
}
|
||||
@ -69,13 +69,13 @@ void I2cTestClass::battPeriodic() {
|
||||
cmdBuf[0] = BpxBattery::PORT_GET_HK;
|
||||
sendLen = 1;
|
||||
ReturnValue_t result = i2cWrite(bpxInfo.fd, cmdBuf.data(), sendLen);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
// Receive back HK set
|
||||
recvLen = 23;
|
||||
result = i2cRead(bpxInfo.fd, replyBuf.data(), recvLen);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
sif::info << "HK reply:" << std::endl;
|
||||
@ -86,16 +86,16 @@ ReturnValue_t I2cTestClass::i2cWrite(int fd, uint8_t* data, size_t len) {
|
||||
if (write(fd, data, len) != static_cast<ssize_t>(len)) {
|
||||
sif::error << "Failed to write to I2C bus" << std::endl;
|
||||
sif::error << "Error " << errno << ": " << strerror(errno) << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t I2cTestClass::i2cRead(int fd, uint8_t* data, size_t len) {
|
||||
if (read(fd, data, len) != static_cast<ssize_t>(len)) {
|
||||
sif::error << "Failed to read from I2C bus" << std::endl;
|
||||
sif::error << "Error " << errno << ": " << strerror(errno) << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef LINUX_BOARDTEST_I2CTESTCLASS_H_
|
||||
#define LINUX_BOARDTEST_I2CTESTCLASS_H_
|
||||
|
||||
#include <test/testtasks/TestTask.h>
|
||||
#include <test/TestTask.h>
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
@ -25,9 +25,9 @@ ReturnValue_t LibgpiodTest::performPeriodicAction() {
|
||||
switch (testCase) {
|
||||
case (TestCases::READ): {
|
||||
result = gpioInterface->readGpio(gpioIds::TEST_ID_0, gpioState);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "LibgpiodTest::performPeriodicAction: Failed to read gpio " << std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
} else {
|
||||
sif::debug << "LibgpiodTest::performPeriodicAction: MIO 0 state = "
|
||||
<< static_cast<int>(gpioState) << std::endl;
|
||||
@ -39,23 +39,23 @@ ReturnValue_t LibgpiodTest::performPeriodicAction() {
|
||||
}
|
||||
case (TestCases::BLINK): {
|
||||
result = gpioInterface->readGpio(gpioIds::TEST_ID_0, gpioState);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "LibgpiodTest::performPeriodicAction: Failed to read gpio " << std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (gpioState == gpio::Levels::HIGH) {
|
||||
result = gpioInterface->pullLow(gpioIds::TEST_ID_0);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "LibgpiodTest::performPeriodicAction: Could not pull GPIO low!"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
} else if (gpioState == gpio::Levels::LOW) {
|
||||
result = gpioInterface->pullHigh(gpioIds::TEST_ID_0);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "LibgpiodTest::performPeriodicAction: Could not pull GPIO high!"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
} else {
|
||||
sif::warning << "LibgpiodTest::performPeriodicAction: Invalid GPIO state" << std::endl;
|
||||
@ -68,7 +68,7 @@ ReturnValue_t LibgpiodTest::performPeriodicAction() {
|
||||
break;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t LibgpiodTest::performOneShotAction() {
|
||||
@ -84,44 +84,44 @@ ReturnValue_t LibgpiodTest::performOneShotAction() {
|
||||
}
|
||||
case (TestCases::LOOPBACK): {
|
||||
result = gpioInterface->pullHigh(gpioIds::TEST_ID_0);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result == returnvalue::OK) {
|
||||
sif::info << "LibgpiodTest::performOneShotAction: "
|
||||
"GPIO pulled high successfully for loopback test"
|
||||
<< std::endl;
|
||||
} else {
|
||||
sif::warning << "LibgpiodTest::performOneShotAction: Could not pull GPIO high!"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
result = gpioInterface->readGpio(gpioIds::TEST_ID_1, gpioState);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK and gpioState == gpio::Levels::HIGH) {
|
||||
if (result == returnvalue::OK and gpioState == gpio::Levels::HIGH) {
|
||||
sif::info << "LibgpiodTest::performOneShotAction: "
|
||||
"GPIO state read successfully and is high"
|
||||
<< std::endl;
|
||||
} else {
|
||||
sif::warning << "LibgpiodTest::performOneShotAction: GPIO read and is not high!"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
result = gpioInterface->pullLow(gpioIds::TEST_ID_0);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result == returnvalue::OK) {
|
||||
sif::info << "LibgpiodTest::performOneShotAction: "
|
||||
"GPIO pulled low successfully for loopback test"
|
||||
<< std::endl;
|
||||
}
|
||||
result = gpioInterface->readGpio(gpioIds::TEST_ID_1, gpioState);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK and gpioState == gpio::Levels::LOW) {
|
||||
if (result == returnvalue::OK and gpioState == gpio::Levels::LOW) {
|
||||
sif::info << "LibgpiodTest::performOneShotAction: "
|
||||
"GPIO state read successfully and is low"
|
||||
<< std::endl;
|
||||
} else {
|
||||
sif::warning << "LibgpiodTest::performOneShotAction: GPIO read and is not low!"
|
||||
<< std::endl;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <fsfw_hal/common/gpio/GpioCookie.h>
|
||||
#include <fsfw_hal/common/gpio/GpioIF.h>
|
||||
|
||||
#include "TestTask.h"
|
||||
#include "test/TestTask.h"
|
||||
|
||||
/**
|
||||
* @brief Test for the GPIO read implementation of the LinuxLibgpioIF.
|
||||
|
@ -53,7 +53,7 @@ ReturnValue_t SpiTestClass::performOneShotAction() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SpiTestClass::performPeriodicAction() {
|
||||
@ -65,7 +65,7 @@ ReturnValue_t SpiTestClass::performPeriodicAction() {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void SpiTestClass::performRm3100Test(uint8_t mgmId) {
|
||||
@ -94,7 +94,7 @@ void SpiTestClass::performRm3100Test(uint8_t mgmId) {
|
||||
#endif
|
||||
int fileDescriptor = 0;
|
||||
|
||||
UnixFileGuard fileHelper(deviceName, &fileDescriptor, O_RDWR, "SpiComIF::initializeInterface");
|
||||
UnixFileGuard fileHelper(deviceName, fileDescriptor, O_RDWR, "SpiComIF::initializeInterface");
|
||||
if (fileHelper.getOpenResult()) {
|
||||
sif::error << "SpiTestClass::performRm3100Test: File descriptor could not be opened!"
|
||||
<< std::endl;
|
||||
@ -137,7 +137,7 @@ void SpiTestClass::performRm3100Test(uint8_t mgmId) {
|
||||
if ((statusReg & 0b1000'0000) == 0) {
|
||||
sif::warning << "SpiTestClass::performRm3100Test: Data not ready!" << std::endl;
|
||||
TaskFactory::delayTask(10);
|
||||
uint8_t statusReg = readRm3100Register(fileDescriptor, currentGpioId, 0x34);
|
||||
statusReg = readRm3100Register(fileDescriptor, currentGpioId, 0x34);
|
||||
if ((statusReg & 0b1000'0000) == 0) {
|
||||
return;
|
||||
}
|
||||
@ -191,7 +191,7 @@ void SpiTestClass::performLis3MdlTest(uint8_t lis3Id) {
|
||||
#endif
|
||||
int fileDescriptor = 0;
|
||||
|
||||
UnixFileGuard fileHelper(deviceName, &fileDescriptor, O_RDWR, "SpiComIF::initializeInterface");
|
||||
UnixFileGuard fileHelper(deviceName, fileDescriptor, O_RDWR, "SpiComIF::initializeInterface");
|
||||
if (fileHelper.getOpenResult()) {
|
||||
sif::error << "SpiTestClass::performLis3Mdl3100Test: File descriptor could not be opened!"
|
||||
<< std::endl;
|
||||
@ -231,7 +231,7 @@ void SpiTestClass::performL3gTest(uint8_t l3gId) {
|
||||
#endif
|
||||
int fileDescriptor = 0;
|
||||
|
||||
UnixFileGuard fileHelper(deviceName, &fileDescriptor, O_RDWR, "SpiComIF::initializeInterface");
|
||||
UnixFileGuard fileHelper(deviceName, fileDescriptor, O_RDWR, "SpiComIF::initializeInterface");
|
||||
if (fileHelper.getOpenResult()) {
|
||||
sif::error << "SpiTestClass::performLis3Mdl3100Test: File descriptor could not be opened!"
|
||||
<< std::endl;
|
||||
@ -333,17 +333,15 @@ void SpiTestClass::performPeriodicMax1227Test() {
|
||||
}
|
||||
|
||||
void SpiTestClass::performMax1227Test() {
|
||||
std::string deviceName = "";
|
||||
#ifdef XIPHOS_Q7S
|
||||
std::string deviceName = q7s::SPI_DEFAULT_DEV;
|
||||
deviceName = q7s::SPI_DEFAULT_DEV;
|
||||
#elif defined(RASPBERRY_PI)
|
||||
std::string deviceName = "";
|
||||
#elif defined(EGSE)
|
||||
std::string deviceName = "";
|
||||
#elif defined(TE0720_1CFA)
|
||||
std::string deviceName = "";
|
||||
#endif
|
||||
int fd = 0;
|
||||
UnixFileGuard fileHelper(deviceName, &fd, O_RDWR, "SpiComIF::initializeInterface");
|
||||
UnixFileGuard fileHelper(deviceName, fd, O_RDWR, "SpiComIF::initializeInterface");
|
||||
if (fileHelper.getOpenResult()) {
|
||||
sif::error << "SpiTestClass::performLis3Mdl3100Test: File descriptor could not be opened!"
|
||||
<< std::endl;
|
||||
@ -381,8 +379,9 @@ void SpiTestClass::max1227RadSensorTest(int fd) {
|
||||
DiffSel::NONE_0);
|
||||
spiTransferStruct[0].len = 1;
|
||||
transfer(fd, gpioIds::CS_RAD_SENSOR);
|
||||
max1227::prepareExternallyClockedRead0ToN(sendBuffer.data(), 7, spiTransferStruct[0].len);
|
||||
size_t tmpLen = spiTransferStruct[0].len;
|
||||
size_t tmpSz = spiTransferStruct[0].len;
|
||||
max1227::prepareExternallyClockedRead0ToN(sendBuffer.data(), 7, tmpSz);
|
||||
size_t tmpLen = tmpSz;
|
||||
spiTransferStruct[0].len = 1;
|
||||
transfer(fd, gpioIds::CS_RAD_SENSOR);
|
||||
std::memcpy(sendBuffer.data(), sendBuffer.data() + 1, tmpLen - 1);
|
||||
@ -403,7 +402,8 @@ void SpiTestClass::max1227RadSensorTest(int fd) {
|
||||
for (int idx = 0; idx < 8; idx++) {
|
||||
sif::info << "ADC raw " << idx << ": " << adcRaw[idx] << std::endl;
|
||||
}
|
||||
max1227::prepareExternallyClockedTemperatureRead(sendBuffer.data(), spiTransferStruct[0].len);
|
||||
tmpSz = spiTransferStruct[0].len;
|
||||
max1227::prepareExternallyClockedTemperatureRead(sendBuffer.data(), tmpSz);
|
||||
spiTransferStruct[0].len = 1;
|
||||
transfer(fd, gpioIds::CS_RAD_SENSOR);
|
||||
usleep(65);
|
||||
@ -467,7 +467,8 @@ void SpiTestClass::max1227SusTest(int fd, SusTestCfg &cfg) {
|
||||
spiTransferStruct[0].len = 1;
|
||||
transfer(fd, cfg.gpioId);
|
||||
|
||||
max1227::prepareExternallyClockedRead0ToN(sendBuffer.data(), 5, spiTransferStruct[0].len);
|
||||
size_t tmpSz = spiTransferStruct[0].len;
|
||||
max1227::prepareExternallyClockedRead0ToN(sendBuffer.data(), 5, tmpSz);
|
||||
transfer(fd, cfg.gpioId);
|
||||
uint16_t adcRaw[6] = {};
|
||||
adcRaw[0] = (recvBuffer[1] << 8) | recvBuffer[2];
|
||||
@ -532,11 +533,11 @@ void SpiTestClass::max1227PlPcduTest(int fd) {
|
||||
adcCfg.vbatSwitch) {
|
||||
// This enables the ADC
|
||||
ReturnValue_t result = gpioIF->pullHigh(gpioIds::PLPCDU_ENB_VBAT0);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
result = gpioIF->pullHigh(gpioIds::PLPCDU_ENB_VBAT1);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
adcCfg.vbatSwitch = false;
|
||||
@ -552,7 +553,9 @@ void SpiTestClass::max1227PlPcduTest(int fd) {
|
||||
spiTransferStruct[0].len = 1;
|
||||
transfer(fd, gpioIds::PLPCDU_ADC_CS);
|
||||
uint8_t n = 11;
|
||||
max1227::prepareExternallyClockedRead0ToN(sendBuffer.data(), n, spiTransferStruct[0].len);
|
||||
size_t tmpSz = spiTransferStruct[0].len;
|
||||
max1227::prepareExternallyClockedRead0ToN(sendBuffer.data(), n, tmpSz);
|
||||
spiTransferStruct[0].len = tmpSz;
|
||||
size_t dummy = 0;
|
||||
max1227::prepareExternallyClockedTemperatureRead(sendBuffer.data() + spiTransferStruct[0].len,
|
||||
dummy);
|
||||
@ -585,9 +588,11 @@ void SpiTestClass::max1227PlPcduTest(int fd) {
|
||||
spiTransferStruct[0].len = 1;
|
||||
transfer(fd, gpioIds::PLPCDU_ADC_CS);
|
||||
uint8_t n = 11;
|
||||
max1227::prepareExternallyClockedRead0ToN(sendBuffer.data(), n, spiTransferStruct[0].len);
|
||||
size_t tmpLen = spiTransferStruct[0].len;
|
||||
max1227::prepareExternallyClockedRead0ToN(sendBuffer.data(), n, tmpLen);
|
||||
max1227::prepareExternallyClockedTemperatureRead(sendBuffer.data() + spiTransferStruct[0].len,
|
||||
spiTransferStruct[0].len);
|
||||
tmpLen);
|
||||
spiTransferStruct[0].len = tmpLen;
|
||||
transfer(fd, gpioIds::PLPCDU_ADC_CS);
|
||||
uint16_t adcRaw[n + 1] = {};
|
||||
for (uint8_t idx = 0; idx < n + 1; idx++) {
|
||||
@ -878,10 +883,10 @@ uint8_t SpiTestClass::readRegister(int fd, gpioId_t chipSelect, uint8_t reg) {
|
||||
|
||||
ReturnValue_t SpiTestClass::transfer(int fd, gpioId_t chipSelect = gpio::NO_GPIO) {
|
||||
int retval = 0;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
if (chipSelect != gpio::NO_GPIO) {
|
||||
result = gpioIF->pullLow(chipSelect);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -889,14 +894,14 @@ ReturnValue_t SpiTestClass::transfer(int fd, gpioId_t chipSelect = gpio::NO_GPIO
|
||||
retval = ioctl(fd, SPI_IOC_MESSAGE(1), &spiTransferStruct);
|
||||
if (retval < 0) {
|
||||
utility::handleIoctlError("SpiTestClass::transfer: ioctl failed");
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
if (chipSelect != gpio::NO_GPIO) {
|
||||
result = gpioIF->pullHigh(chipSelect);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include <fsfw_hal/common/gpio/GpioIF.h>
|
||||
#include <fsfw_hal/linux/spi/SpiCookie.h>
|
||||
#include <test/testtasks/TestTask.h>
|
||||
#include <test/TestTask.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
@ -3,14 +3,22 @@
|
||||
#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/serial/SerialCookie.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 "eive/objects.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 +26,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) {
|
||||
@ -26,10 +52,10 @@ ReturnValue_t UartTestClass::initialize() {
|
||||
} else if (mode == TestModes::SCEX) {
|
||||
scexInit();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t UartTestClass::performOneShotAction() { return HasReturnvaluesIF::RETURN_OK; }
|
||||
ReturnValue_t UartTestClass::performOneShotAction() { return returnvalue::OK; }
|
||||
|
||||
ReturnValue_t UartTestClass::performPeriodicAction() {
|
||||
if (mode == TestModes::GPS) {
|
||||
@ -37,21 +63,21 @@ ReturnValue_t UartTestClass::performPeriodicAction() {
|
||||
} else if (mode == TestModes::SCEX) {
|
||||
scexPeriodic();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
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 +105,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 +121,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 +135,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 +153,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 SerialCookie(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 +269,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 +286,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 != HasReturnvaluesIF::RETURN_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,13 +1,21 @@
|
||||
#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/serial/SerialCookie.h>
|
||||
#include <termios.h> // Contains POSIX terminal control definitions
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "lwgps/lwgps.h"
|
||||
#include "test/testtasks/TestTask.h"
|
||||
//#include "lwgps/lwgps.h"
|
||||
#include "mission/devices/devicedefinitions/ScexDefinitions.h"
|
||||
#include "test/TestTask.h"
|
||||
|
||||
class ScexUartReader;
|
||||
class ScexDleParser;
|
||||
|
||||
class UartTestClass : public TestTask {
|
||||
public:
|
||||
@ -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();
|
||||
SerialCookie* uartCookie = nullptr;
|
||||
size_t encodedLen = 0;
|
||||
lwgps_t gpsData = {};
|
||||
// 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;
|
||||
};
|
||||
|
||||
|
@ -1,3 +1 @@
|
||||
target_sources(${OBSW_NAME} PRIVATE
|
||||
gpioCallbacks.cpp
|
||||
)
|
||||
target_sources(${OBSW_NAME} PRIVATE gpioCallbacks.cpp)
|
||||
|
@ -1,8 +1 @@
|
||||
target_sources(${OBSW_NAME} PUBLIC
|
||||
CspComIF.cpp
|
||||
CspCookie.cpp
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
target_sources(${OBSW_NAME} PUBLIC CspComIF.cpp)
|
||||
|
@ -3,8 +3,16 @@
|
||||
#include <csp/drivers/can_socketcan.h>
|
||||
#include <fsfw/serialize/SerializeAdapter.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
|
||||
#include <p60acu.h>
|
||||
#include <p60dock.h>
|
||||
#include <p60pdu.h>
|
||||
#include <param/param_string.h>
|
||||
#include <param/rparam_client.h>
|
||||
|
||||
#include "CspCookie.h"
|
||||
#include "mission/csp/CspCookie.h"
|
||||
|
||||
using namespace GOMSPACE;
|
||||
|
||||
CspComIF::CspComIF(object_id_t objectId) : SystemObject(objectId) {}
|
||||
|
||||
@ -31,7 +39,7 @@ ReturnValue_t CspComIF::initializeInterface(CookieIF* cookie) {
|
||||
if (csp_init(cspOwnAddress) != CSP_ERR_NONE ||
|
||||
csp_buffer_init(buf_count, buf_size) != CSP_ERR_NONE) {
|
||||
sif::error << "Failed to init CSP\r\n" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
int promisc = 0; // Set filter mode on
|
||||
@ -45,7 +53,7 @@ ReturnValue_t CspComIF::initializeInterface(CookieIF* cookie) {
|
||||
int result = csp_rtable_set(address, netmask, csp_if_ptr, mac);
|
||||
if (result != CSP_ERR_NONE) {
|
||||
sif::error << "Failed to add can interface to router table" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
/* Start the route task */
|
||||
@ -54,7 +62,7 @@ ReturnValue_t CspComIF::initializeInterface(CookieIF* cookie) {
|
||||
result = csp_route_start_task(task_stack_size, priority);
|
||||
if (result != CSP_ERR_NONE) {
|
||||
sif::error << "Failed to start csp route task" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
sif::info << canInterface << " initialized successfully" << std::endl;
|
||||
}
|
||||
@ -63,78 +71,164 @@ ReturnValue_t CspComIF::initializeInterface(CookieIF* cookie) {
|
||||
uint16_t maxReplyLength = cspCookie->getMaxReplyLength();
|
||||
if (cspDeviceMap.find(cspAddress) == cspDeviceMap.end()) {
|
||||
/* Insert device information in CSP map */
|
||||
cspDeviceMap.emplace(cspAddress, vectorBuffer(maxReplyLength));
|
||||
cspDeviceMap.emplace(cspAddress, ReplyInfo(maxReplyLength));
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CspComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) {
|
||||
int result;
|
||||
if (cookie == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
if (cookie == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
CspCookie* cspCookie = dynamic_cast<CspCookie*>(cookie);
|
||||
if (cspCookie == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
if (cspCookie == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
/* Extract csp port and bytes to query from command buffer */
|
||||
uint8_t cspPort;
|
||||
uint16_t querySize = 0;
|
||||
result = getPortAndQuerySize(&sendData, &sendLen, &cspPort, &querySize);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
if (cspCookie->getRequest() == GOMSPACE::SpecialRequestTypes::DEFAULT_COM_IF) {
|
||||
/* Extract csp port and bytes to query from command buffer */
|
||||
result = getPortAndQuerySize(&sendData, &sendLen, &cspPort, &querySize);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
cspPort = cspCookie->getCspPort();
|
||||
querySize = cspCookie->getReplyLen();
|
||||
}
|
||||
if (querySize > cspCookie->getMaxReplyLength()) {
|
||||
sif::error << "Query size " << querySize << " is larger than maximum allowed "
|
||||
<< cspCookie->getMaxReplyLength() << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
uint8_t cspAddress = cspCookie->getCspAddress();
|
||||
auto iter = cspDeviceMap.find(cspAddress);
|
||||
if (iter == cspDeviceMap.end()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
switch (cspPort) {
|
||||
case (Ports::CSP_PING): {
|
||||
case (CspPorts::CSP_PING): {
|
||||
initiatePingRequest(cspAddress, querySize);
|
||||
break;
|
||||
}
|
||||
case (Ports::CSP_REBOOT): {
|
||||
case (CspPorts::CSP_REBOOT): {
|
||||
csp_reboot(cspAddress);
|
||||
break;
|
||||
}
|
||||
case (Ports::P60_PORT_GNDWDT_RESET):
|
||||
case (Ports::P60_PORT_RPARAM): {
|
||||
/* No CSP fixed port was selected. Send data to the specified port and
|
||||
* wait for querySize number of bytes */
|
||||
result = cspTransfer(cspAddress, cspPort, sendData, sendLen, querySize);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
case (CspPorts::P60_PORT_GNDWDT_RESET_ENUM):
|
||||
case (CspPorts::P60_PORT_RPARAM_ENUM): {
|
||||
if (cspCookie->getRequest() != SpecialRequestTypes::DEFAULT_COM_IF) {
|
||||
param_index_t requestStruct{};
|
||||
requestStruct.physaddr = iter->second.replyBuf.data();
|
||||
auto req = cspCookie->getRequest();
|
||||
if (req == GOMSPACE::SpecialRequestTypes::GET_PDU_HK) {
|
||||
if (!p60pdu_get_hk(&requestStruct, cspAddress, cspCookie->getTimeout())) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
} else if (req == GOMSPACE::SpecialRequestTypes::GET_ACU_HK) {
|
||||
if (!p60acu_get_hk(&requestStruct, cspAddress, cspCookie->getTimeout())) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
} else if (req == GOMSPACE::SpecialRequestTypes::GET_P60DOCK_HK) {
|
||||
if (!p60dock_get_hk(&requestStruct, cspAddress, cspCookie->getTimeout())) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
} else if (req == GOMSPACE::SpecialRequestTypes::GET_PDU_CONFIG) {
|
||||
requestStruct.table = p60pdu_config;
|
||||
requestStruct.mem_id = P60PDU_PARAM;
|
||||
requestStruct.count = p60pdu_config_count;
|
||||
requestStruct.size = P60PDU_PARAM_SIZE;
|
||||
result = rparam_get_full_table(&requestStruct, cspAddress, P60_PORT_RPARAM,
|
||||
requestStruct.mem_id, cspCookie->getTimeout());
|
||||
if (result != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
} else if (req == GOMSPACE::SpecialRequestTypes::GET_ACU_CONFIG) {
|
||||
requestStruct.table = p60acu_config;
|
||||
requestStruct.mem_id = P60ACU_PARAM;
|
||||
requestStruct.count = p60acu_config_count;
|
||||
requestStruct.size = P60ACU_PARAM_SIZE;
|
||||
result = rparam_get_full_table(&requestStruct, cspAddress, P60_PORT_RPARAM,
|
||||
requestStruct.mem_id, cspCookie->getTimeout());
|
||||
if (result != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
} else if (req == GOMSPACE::SpecialRequestTypes::GET_P60DOCK_CONFIG) {
|
||||
requestStruct.table = p60dock_config;
|
||||
requestStruct.mem_id = P60DOCK_PARAM;
|
||||
requestStruct.count = p60dock_config_count;
|
||||
requestStruct.size = P60DOCK_PARAM_SIZE;
|
||||
result = rparam_get_full_table(&requestStruct, cspAddress, P60_PORT_RPARAM,
|
||||
requestStruct.mem_id, cspCookie->getTimeout());
|
||||
if (result != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
} else if (req == GOMSPACE::SpecialRequestTypes::SAVE_TABLE) {
|
||||
if (sendLen < 2) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
const TableInfo* tableInfo = reinterpret_cast<const TableInfo*>(sendData);
|
||||
result = gs_rparam_save(cspAddress, cspCookie->getTimeout(), tableInfo->sourceTable,
|
||||
tableInfo->targetTable);
|
||||
if (result != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
} else if (req == GOMSPACE::SpecialRequestTypes::LOAD_TABLE) {
|
||||
if (sendLen < 2) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
const TableInfo* tableInfo = reinterpret_cast<const TableInfo*>(sendData);
|
||||
result = gs_rparam_load(cspAddress, cspCookie->getTimeout(), tableInfo->sourceTable,
|
||||
tableInfo->targetTable);
|
||||
if (result != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* No CSP fixed port was selected. Send data to the specified port and
|
||||
* wait for querySize number of bytes */
|
||||
result = cspTransfer(cspAddress, cspPort, sendData, sendLen, querySize);
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
replySize = querySize;
|
||||
iter->second.replyLen = querySize;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sif::error << "CspComIF: Invalid port specified" << std::endl;
|
||||
break;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CspComIF::getSendSuccess(CookieIF* cookie) { return HasReturnvaluesIF::RETURN_OK; }
|
||||
ReturnValue_t CspComIF::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
|
||||
|
||||
ReturnValue_t CspComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CspComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
|
||||
if (cookie == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
CspCookie* cspCookie = dynamic_cast<CspCookie*>(cookie);
|
||||
if (cspCookie == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
uint8_t cspAddress = cspCookie->getCspAddress();
|
||||
auto iter = cspDeviceMap.find(cspAddress);
|
||||
if (iter == cspDeviceMap.end()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
*buffer = iter->second.replyBuf.data();
|
||||
*size = iter->second.replyLen;
|
||||
|
||||
*buffer = cspDeviceMap[cspAddress].data();
|
||||
*size = replySize;
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CspComIF::cspTransfer(uint8_t cspAddress, uint8_t cspPort, const uint8_t* cmdBuffer,
|
||||
@ -142,13 +236,13 @@ ReturnValue_t CspComIF::cspTransfer(uint8_t cspAddress, uint8_t cspPort, const u
|
||||
uint32_t timeout_ms = 1000;
|
||||
uint16_t bytesRead = 0;
|
||||
int32_t expectedSize = static_cast<int32_t>(querySize);
|
||||
vectorBufferIter iter = cspDeviceMap.find(cspAddress);
|
||||
auto iter = cspDeviceMap.find(cspAddress);
|
||||
if (iter == cspDeviceMap.end()) {
|
||||
sif::error << "CSP device with address " << cspAddress << " no found in"
|
||||
<< " device map" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
uint8_t* replyBuffer = iter->second.data();
|
||||
uint8_t* replyBuffer = iter->second.replyBuf.data();
|
||||
|
||||
csp_conn_t* conn = csp_connect(CSP_PRIO_HIGH, cspAddress, cspPort, 0, CSP_O_NONE);
|
||||
|
||||
@ -157,7 +251,7 @@ ReturnValue_t CspComIF::cspTransfer(uint8_t cspAddress, uint8_t cspPort, const u
|
||||
sif::error << "CspComIF::cspTransfer: Failed to get memory for a csp packet from the csp "
|
||||
<< "stack" << std::endl;
|
||||
csp_close(conn);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
memcpy(commandPacket->data, cmdBuffer, cmdLen);
|
||||
@ -167,12 +261,12 @@ ReturnValue_t CspComIF::cspTransfer(uint8_t cspAddress, uint8_t cspPort, const u
|
||||
csp_buffer_free(commandPacket);
|
||||
sif::error << "CspComIF::cspTransfer: Failed to send csp packet" << std::endl;
|
||||
csp_close(conn);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
/* Return when no reply is expected */
|
||||
if (expectedSize == 0) {
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
csp_packet_t* reply;
|
||||
@ -180,7 +274,7 @@ ReturnValue_t CspComIF::cspTransfer(uint8_t cspAddress, uint8_t cspPort, const u
|
||||
if (reply == NULL) {
|
||||
sif::error << "CspComIF::cspTransfer: Failed to read csp packet" << std::endl;
|
||||
csp_close(conn);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
memcpy(replyBuffer, reply->data, reply->length);
|
||||
expectedSize = expectedSize - reply->length;
|
||||
@ -191,13 +285,13 @@ ReturnValue_t CspComIF::cspTransfer(uint8_t cspAddress, uint8_t cspPort, const u
|
||||
if (reply == NULL) {
|
||||
sif::error << "CspComIF::cspTransfer: Failed to read csp packet" << std::endl;
|
||||
csp_close(conn);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if ((reply->length + bytesRead) > iter->second.size()) {
|
||||
if ((reply->length + bytesRead) > iter->second.replyBuf.size()) {
|
||||
sif::error << "CspComIF::cspTransfer: Reply buffer to short" << std::endl;
|
||||
csp_buffer_free(reply);
|
||||
csp_close(conn);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
memcpy(replyBuffer + bytesRead, reply->data, reply->length);
|
||||
expectedSize = expectedSize - reply->length;
|
||||
@ -209,30 +303,30 @@ ReturnValue_t CspComIF::cspTransfer(uint8_t cspAddress, uint8_t cspPort, const u
|
||||
sif::error << "CspComIF::cspTransfer: Received more bytes than requested" << std::endl;
|
||||
sif::debug << "CspComIF::cspTransfer: Received bytes: " << bytesRead << std::endl;
|
||||
csp_close(conn);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
csp_close(conn);
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CspComIF::getPortAndQuerySize(const uint8_t** sendData, size_t* sendLen,
|
||||
uint8_t* cspPort, uint16_t* querySize) {
|
||||
ReturnValue_t result =
|
||||
SerializeAdapter::deSerialize(cspPort, sendData, sendLen, SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "CspComIF: Failed to deserialize CSP port from command "
|
||||
<< "buffer" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
SerializeAdapter::deSerialize(querySize, sendData, sendLen, SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "CspComIF: Failed to deserialize querySize from command "
|
||||
<< "buffer" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void CspComIF::initiatePingRequest(uint8_t cspAddress, uint16_t querySize) {
|
||||
@ -240,8 +334,12 @@ void CspComIF::initiatePingRequest(uint8_t cspAddress, uint16_t querySize) {
|
||||
uint32_t replyTime = csp_ping(cspAddress, timeout_ms, querySize, CSP_O_NONE);
|
||||
sif::info << "Ping address: " << cspAddress << ", reply after " << replyTime << " ms"
|
||||
<< std::endl;
|
||||
auto iter = cspDeviceMap.find(cspAddress);
|
||||
if (iter == cspDeviceMap.end()) {
|
||||
return;
|
||||
}
|
||||
/* Store reply time in reply buffer * */
|
||||
uint8_t* replyBuffer = cspDeviceMap[cspAddress].data();
|
||||
uint8_t* replyBuffer = iter->second.replyBuf.data();
|
||||
memcpy(replyBuffer, &replyTime, sizeof(replyTime));
|
||||
replySize = sizeof(replyTime);
|
||||
iter->second.replyLen = sizeof(replyTime);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <csp/csp.h>
|
||||
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@ -42,24 +42,22 @@ class CspComIF : public DeviceCommunicationIF, public SystemObject {
|
||||
ReturnValue_t cspTransfer(uint8_t cspAddress, uint8_t cspPort, const uint8_t *cmdBuffer,
|
||||
int cmdLen, uint16_t querySize);
|
||||
|
||||
enum Ports { CSP_PING = 1, CSP_REBOOT = 4, P60_PORT_RPARAM = 7, P60_PORT_GNDWDT_RESET = 9 };
|
||||
|
||||
typedef uint8_t node_t;
|
||||
using vectorBuffer = std::vector<uint8_t>;
|
||||
using VectorBufferMap = std::unordered_map<node_t, vectorBuffer>;
|
||||
using vectorBufferIter = VectorBufferMap::iterator;
|
||||
struct ReplyInfo {
|
||||
ReplyInfo(size_t maxLen) : replyBuf(maxLen){};
|
||||
std::vector<uint8_t> replyBuf;
|
||||
size_t replyLen = 0;
|
||||
};
|
||||
using VectorBufferMap = std::unordered_map<node_t, ReplyInfo>;
|
||||
|
||||
/* In this map assigns reply buffers to a CSP device */
|
||||
VectorBufferMap cspDeviceMap;
|
||||
|
||||
uint16_t replySize = 0;
|
||||
|
||||
/* This is the CSP address of the OBC. */
|
||||
node_t cspOwnAddress = 1;
|
||||
|
||||
/* Interface struct for csp protocol stack */
|
||||
csp_iface_t csp_if;
|
||||
|
||||
char canInterface[5] = "can0";
|
||||
int bitrate = 1000;
|
||||
|
||||
|
@ -1,10 +0,0 @@
|
||||
#include "CspCookie.h"
|
||||
|
||||
CspCookie::CspCookie(uint16_t maxReplyLength_, uint8_t cspAddress_)
|
||||
: maxReplyLength(maxReplyLength_), cspAddress(cspAddress_) {}
|
||||
|
||||
CspCookie::~CspCookie() {}
|
||||
|
||||
uint16_t CspCookie::getMaxReplyLength() { return maxReplyLength; }
|
||||
|
||||
uint8_t CspCookie::getCspAddress() { return cspAddress; }
|
@ -1,26 +0,0 @@
|
||||
#ifndef LINUX_CSP_CSPCOOKIE_H_
|
||||
#define LINUX_CSP_CSPCOOKIE_H_
|
||||
|
||||
#include <fsfw/devicehandlers/CookieIF.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* @brief This is the cookie for devices supporting the CSP (CubeSat Space
|
||||
* Protocol).
|
||||
* @author J. Meier
|
||||
*/
|
||||
class CspCookie : public CookieIF {
|
||||
public:
|
||||
CspCookie(uint16_t maxReplyLength_, uint8_t cspAddress_);
|
||||
virtual ~CspCookie();
|
||||
|
||||
uint16_t getMaxReplyLength();
|
||||
uint8_t getCspAddress();
|
||||
|
||||
private:
|
||||
uint16_t maxReplyLength;
|
||||
uint8_t cspAddress;
|
||||
};
|
||||
|
||||
#endif /* LINUX_CSP_CSPCOOKIE_H_ */
|
732
linux/devices/AcsBoardPolling.cpp
Normal file
732
linux/devices/AcsBoardPolling.cpp
Normal file
@ -0,0 +1,732 @@
|
||||
#include "AcsBoardPolling.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <fsfw/globalfunctions/arrayprinter.h>
|
||||
#include <fsfw/tasks/SemaphoreFactory.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
#include <fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h>
|
||||
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.h>
|
||||
#include <fsfw_hal/linux/UnixFileGuard.h>
|
||||
#include <fsfw_hal/linux/spi/SpiCookie.h>
|
||||
#include <fsfw_hal/linux/utility.h>
|
||||
#include <mission/devices/devicedefinitions/gyroAdisHelpers.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "devices/gpioIds.h"
|
||||
|
||||
using namespace returnvalue;
|
||||
|
||||
AcsBoardPolling::AcsBoardPolling(object_id_t objectId, SpiComIF& lowLevelComIF, GpioIF& gpioIF)
|
||||
: SystemObject(objectId), spiComIF(lowLevelComIF), gpioIF(gpioIF) {
|
||||
semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
|
||||
semaphore->acquire();
|
||||
ipcLock = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
ReturnValue_t AcsBoardPolling::performOperation(uint8_t operationCode) {
|
||||
while (true) {
|
||||
ipcLock->lockMutex(LOCK_TYPE, LOCK_TIMEOUT);
|
||||
state = InternalState::IDLE;
|
||||
ipcLock->unlockMutex();
|
||||
semaphore->acquire();
|
||||
// Give all tasks or the PST some time to submit all consecutive requests.
|
||||
TaskFactory::delayTask(2);
|
||||
{
|
||||
// Measured to take 0-1 ms in debug build.
|
||||
// Stopwatch watch;
|
||||
gyroAdisHandler(gyro0Adis);
|
||||
gyroAdisHandler(gyro2Adis);
|
||||
gyroL3gHandler(gyro1L3g);
|
||||
gyroL3gHandler(gyro3L3g);
|
||||
mgmRm3100Handler(mgm1Rm3100);
|
||||
mgmRm3100Handler(mgm3Rm3100);
|
||||
mgmLis3Handler(mgm0Lis3);
|
||||
mgmLis3Handler(mgm2Lis3);
|
||||
}
|
||||
// To prevent task being not reactivated by tardy tasks
|
||||
TaskFactory::delayTask(20);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AcsBoardPolling::initialize() { return returnvalue::OK; }
|
||||
|
||||
ReturnValue_t AcsBoardPolling::initializeInterface(CookieIF* cookie) {
|
||||
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
|
||||
if (spiCookie == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
switch (spiCookie->getChipSelectPin()) {
|
||||
case (gpioIds::MGM_0_LIS3_CS): {
|
||||
mgm0Lis3.cookie = spiCookie;
|
||||
break;
|
||||
}
|
||||
case (gpioIds::MGM_1_RM3100_CS): {
|
||||
mgm1Rm3100.cookie = spiCookie;
|
||||
break;
|
||||
}
|
||||
case (gpioIds::MGM_2_LIS3_CS): {
|
||||
mgm2Lis3.cookie = spiCookie;
|
||||
break;
|
||||
}
|
||||
case (gpioIds::MGM_3_RM3100_CS): {
|
||||
mgm3Rm3100.cookie = spiCookie;
|
||||
break;
|
||||
}
|
||||
case (gpioIds::GYRO_0_ADIS_CS): {
|
||||
gyro0Adis.cookie = spiCookie;
|
||||
break;
|
||||
}
|
||||
case (gpioIds::GYRO_1_L3G_CS): {
|
||||
gyro1L3g.cookie = spiCookie;
|
||||
break;
|
||||
}
|
||||
case (gpioIds::GYRO_2_ADIS_CS): {
|
||||
gyro2Adis.cookie = spiCookie;
|
||||
break;
|
||||
}
|
||||
case (gpioIds::GYRO_3_L3G_CS): {
|
||||
gyro3L3g.cookie = spiCookie;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sif::error << "AcsBoardPollingTask: invalid spi cookie" << std::endl;
|
||||
}
|
||||
}
|
||||
return spiComIF.initializeInterface(cookie);
|
||||
}
|
||||
|
||||
ReturnValue_t AcsBoardPolling::sendMessage(CookieIF* cookie, const uint8_t* sendData,
|
||||
size_t sendLen) {
|
||||
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
|
||||
if (spiCookie == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
auto handleAdisRequest = [&](GyroAdis& adis) {
|
||||
if (sendLen != sizeof(acs::Adis1650XRequest)) {
|
||||
sif::error << "AcsBoardPolling: invalid adis request send length";
|
||||
adis.replyResult = returnvalue::FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
auto* req = reinterpret_cast<const acs::Adis1650XRequest*>(sendData);
|
||||
if (req->mode != adis.mode) {
|
||||
if (req->mode == acs::SimpleSensorMode::NORMAL) {
|
||||
adis.type = req->type;
|
||||
adis.countdown.setTimeout(adis1650x::START_UP_TIME);
|
||||
if (adis.type == adis1650x::Type::ADIS16507) {
|
||||
adis.ownReply.data.accelScaling = adis1650x::ACCELEROMETER_RANGE_16507;
|
||||
} else if (adis.type == adis1650x::Type::ADIS16505) {
|
||||
adis.ownReply.data.accelScaling = adis1650x::ACCELEROMETER_RANGE_16505;
|
||||
} else {
|
||||
sif::warning << "AcsBoardPolling: Unknown ADIS type" << std::endl;
|
||||
}
|
||||
adis.performStartup = true;
|
||||
} else if (req->mode == acs::SimpleSensorMode::OFF) {
|
||||
adis.performStartup = false;
|
||||
adis.ownReply.cfgWasSet = false;
|
||||
adis.ownReply.dataWasSet = false;
|
||||
}
|
||||
adis.mode = req->mode;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
};
|
||||
auto handleL3gRequest = [&](GyroL3g& gyro) {
|
||||
if (sendLen != sizeof(acs::GyroL3gRequest)) {
|
||||
sif::error << "AcsBoardPolling: invalid l3g request send length";
|
||||
gyro.replyResult = returnvalue::FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
auto* req = reinterpret_cast<const acs::GyroL3gRequest*>(sendData);
|
||||
if (req->mode != gyro.mode) {
|
||||
if (req->mode == acs::SimpleSensorMode::NORMAL) {
|
||||
std::memcpy(gyro.sensorCfg, req->ctrlRegs, 5);
|
||||
gyro.performStartup = true;
|
||||
} else {
|
||||
gyro.ownReply.cfgWasSet = false;
|
||||
}
|
||||
gyro.mode = req->mode;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
};
|
||||
auto handleLis3Request = [&](MgmLis3& mgm) {
|
||||
if (sendLen != sizeof(acs::MgmLis3Request)) {
|
||||
sif::error << "AcsBoardPolling: invalid lis3 request send length";
|
||||
mgm.replyResult = returnvalue::FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
auto* req = reinterpret_cast<const acs::MgmLis3Request*>(sendData);
|
||||
if (req->mode != mgm.mode) {
|
||||
if (req->mode == acs::SimpleSensorMode::NORMAL) {
|
||||
mgm.performStartup = true;
|
||||
} else {
|
||||
mgm.ownReply.dataWasSet = false;
|
||||
mgm.ownReply.temperatureWasSet = false;
|
||||
}
|
||||
mgm.mode = req->mode;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
};
|
||||
auto handleRm3100Request = [&](MgmRm3100& mgm) {
|
||||
if (sendLen != sizeof(acs::MgmRm3100Request)) {
|
||||
sif::error << "AcsBoardPolling: invalid rm3100 request send length";
|
||||
mgm.replyResult = returnvalue::FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
auto* req = reinterpret_cast<const acs::MgmRm3100Request*>(sendData);
|
||||
if (req->mode != mgm.mode) {
|
||||
if (req->mode == acs::SimpleSensorMode::NORMAL) {
|
||||
mgm.performStartup = true;
|
||||
} else {
|
||||
mgm.ownReply.dataWasRead = false;
|
||||
}
|
||||
mgm.mode = req->mode;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
};
|
||||
{
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
switch (spiCookie->getChipSelectPin()) {
|
||||
case (gpioIds::MGM_0_LIS3_CS): {
|
||||
handleLis3Request(mgm0Lis3);
|
||||
break;
|
||||
}
|
||||
case (gpioIds::MGM_1_RM3100_CS): {
|
||||
handleRm3100Request(mgm1Rm3100);
|
||||
break;
|
||||
}
|
||||
case (gpioIds::MGM_2_LIS3_CS): {
|
||||
handleLis3Request(mgm2Lis3);
|
||||
break;
|
||||
}
|
||||
case (gpioIds::MGM_3_RM3100_CS): {
|
||||
handleRm3100Request(mgm3Rm3100);
|
||||
break;
|
||||
}
|
||||
case (gpioIds::GYRO_0_ADIS_CS): {
|
||||
handleAdisRequest(gyro0Adis);
|
||||
break;
|
||||
}
|
||||
case (gpioIds::GYRO_2_ADIS_CS): {
|
||||
handleAdisRequest(gyro2Adis);
|
||||
break;
|
||||
}
|
||||
case (gpioIds::GYRO_1_L3G_CS): {
|
||||
handleL3gRequest(gyro1L3g);
|
||||
break;
|
||||
}
|
||||
case (gpioIds::GYRO_3_L3G_CS): {
|
||||
handleL3gRequest(gyro3L3g);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (state == InternalState::IDLE) {
|
||||
state = InternalState::BUSY;
|
||||
}
|
||||
}
|
||||
semaphore->release();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AcsBoardPolling::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
|
||||
|
||||
ReturnValue_t AcsBoardPolling::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AcsBoardPolling::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
|
||||
size_t* size) {
|
||||
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
|
||||
if (spiCookie == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
auto handleAdisReply = [&](GyroAdis& gyro) {
|
||||
std::memcpy(&gyro.readerReply, &gyro.ownReply, sizeof(acs::Adis1650XReply));
|
||||
*buffer = reinterpret_cast<uint8_t*>(&gyro.readerReply);
|
||||
*size = sizeof(acs::Adis1650XReply);
|
||||
return gyro.replyResult;
|
||||
};
|
||||
auto handleL3gReply = [&](GyroL3g& gyro) {
|
||||
std::memcpy(&gyro.readerReply, &gyro.ownReply, sizeof(acs::GyroL3gReply));
|
||||
*buffer = reinterpret_cast<uint8_t*>(&gyro.readerReply);
|
||||
*size = sizeof(acs::GyroL3gReply);
|
||||
return gyro.replyResult;
|
||||
};
|
||||
auto handleRm3100Reply = [&](MgmRm3100& mgm) {
|
||||
std::memcpy(&mgm.readerReply, &mgm.ownReply, sizeof(acs::MgmRm3100Reply));
|
||||
*buffer = reinterpret_cast<uint8_t*>(&mgm.readerReply);
|
||||
*size = sizeof(acs::MgmRm3100Reply);
|
||||
return mgm.replyResult;
|
||||
};
|
||||
auto handleLis3Reply = [&](MgmLis3& mgm) {
|
||||
std::memcpy(&mgm.readerReply, &mgm.ownReply, sizeof(acs::MgmLis3Reply));
|
||||
*buffer = reinterpret_cast<uint8_t*>(&mgm.readerReply);
|
||||
*size = sizeof(acs::MgmLis3Reply);
|
||||
return mgm.replyResult;
|
||||
};
|
||||
switch (spiCookie->getChipSelectPin()) {
|
||||
case (gpioIds::MGM_0_LIS3_CS): {
|
||||
return handleLis3Reply(mgm0Lis3);
|
||||
}
|
||||
case (gpioIds::MGM_1_RM3100_CS): {
|
||||
return handleRm3100Reply(mgm1Rm3100);
|
||||
}
|
||||
case (gpioIds::MGM_2_LIS3_CS): {
|
||||
return handleLis3Reply(mgm2Lis3);
|
||||
}
|
||||
case (gpioIds::MGM_3_RM3100_CS): {
|
||||
return handleRm3100Reply(mgm3Rm3100);
|
||||
}
|
||||
case (gpioIds::GYRO_0_ADIS_CS): {
|
||||
return handleAdisReply(gyro0Adis);
|
||||
}
|
||||
case (gpioIds::GYRO_2_ADIS_CS): {
|
||||
return handleAdisReply(gyro2Adis);
|
||||
}
|
||||
case (gpioIds::GYRO_1_L3G_CS): {
|
||||
return handleL3gReply(gyro1L3g);
|
||||
}
|
||||
case (gpioIds::GYRO_3_L3G_CS): {
|
||||
return handleL3gReply(gyro3L3g);
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void AcsBoardPolling::gyroL3gHandler(GyroL3g& l3g) {
|
||||
ReturnValue_t result;
|
||||
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
|
||||
bool gyroPerformStartup = false;
|
||||
{
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
mode = l3g.mode;
|
||||
gyroPerformStartup = l3g.performStartup;
|
||||
}
|
||||
if (mode == acs::SimpleSensorMode::NORMAL) {
|
||||
if (gyroPerformStartup) {
|
||||
cmdBuf[0] = l3gd20h::CTRL_REG_1 | l3gd20h::AUTO_INCREMENT_MASK;
|
||||
std::memcpy(cmdBuf.data() + 1, l3g.sensorCfg, 5);
|
||||
result = spiComIF.sendMessage(l3g.cookie, cmdBuf.data(), 6);
|
||||
if (result != returnvalue::OK) {
|
||||
l3g.replyResult = returnvalue::OK;
|
||||
}
|
||||
// Ignore useless reply and red config
|
||||
cmdBuf[0] = l3gd20h::CTRL_REG_1 | l3gd20h::AUTO_INCREMENT_MASK | l3gd20h::READ_MASK;
|
||||
std::memset(cmdBuf.data() + 1, 0, 5);
|
||||
result = spiComIF.sendMessage(l3g.cookie, cmdBuf.data(), 6);
|
||||
if (result != returnvalue::OK) {
|
||||
l3g.replyResult = returnvalue::OK;
|
||||
}
|
||||
result = spiComIF.readReceivedMessage(l3g.cookie, &rawReply, &dummy);
|
||||
if (result != returnvalue::OK) {
|
||||
l3g.replyResult = returnvalue::OK;
|
||||
}
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
// Cross check configuration as verification that communication is working
|
||||
for (uint8_t idx = 0; idx < 5; idx++) {
|
||||
if (rawReply[idx + 1] != l3g.sensorCfg[idx]) {
|
||||
sif::warning << "AcsBoardPolling: l3g config check missmatch" << std::endl;
|
||||
l3g.replyResult = returnvalue::FAILED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
l3g.performStartup = false;
|
||||
l3g.ownReply.cfgWasSet = true;
|
||||
l3g.ownReply.sensitivity = l3gd20h::ctrlReg4ToSensitivity(l3g.sensorCfg[3]);
|
||||
}
|
||||
cmdBuf[0] = l3gd20h::READ_START | l3gd20h::AUTO_INCREMENT_MASK | l3gd20h::READ_MASK;
|
||||
std::memset(cmdBuf.data() + 1, 0, l3gd20h::READ_LEN);
|
||||
result = spiComIF.sendMessage(l3g.cookie, cmdBuf.data(), l3gd20h::READ_LEN + 1);
|
||||
if (result != returnvalue::OK) {
|
||||
l3g.replyResult = returnvalue::FAILED;
|
||||
return;
|
||||
}
|
||||
result = spiComIF.readReceivedMessage(l3g.cookie, &rawReply, &dummy);
|
||||
if (result != returnvalue::OK) {
|
||||
l3g.replyResult = returnvalue::FAILED;
|
||||
return;
|
||||
}
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
// The regular read function always returns the full sensor config as well. Use that
|
||||
// to verify communications.
|
||||
for (uint8_t idx = 0; idx < 5; idx++) {
|
||||
if (rawReply[idx + 1] != l3g.sensorCfg[idx]) {
|
||||
sif::warning << "AcsBoardPolling: l3g config check missmatch" << std::endl;
|
||||
l3g.replyResult = returnvalue::FAILED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
l3g.ownReply.statusReg = rawReply[l3gd20h::STATUS_IDX];
|
||||
l3g.ownReply.angVelocities[0] = (rawReply[l3gd20h::OUT_X_H] << 8) | rawReply[l3gd20h::OUT_X_L];
|
||||
l3g.ownReply.angVelocities[1] = (rawReply[l3gd20h::OUT_Y_H] << 8) | rawReply[l3gd20h::OUT_Y_L];
|
||||
l3g.ownReply.angVelocities[2] = (rawReply[l3gd20h::OUT_Z_H] << 8) | rawReply[l3gd20h::OUT_Z_L];
|
||||
l3g.ownReply.tempOffsetRaw = rawReply[l3gd20h::TEMPERATURE_IDX];
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t AcsBoardPolling::readAdisCfg(SpiCookie& cookie, size_t transferLen) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
int retval = 0;
|
||||
// Prepare transfer
|
||||
int fileDescriptor = 0;
|
||||
std::string device = spiComIF.getSpiDev();
|
||||
UnixFileGuard fileHelper(device, fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
|
||||
if (fileHelper.getOpenResult() != returnvalue::OK) {
|
||||
return SpiComIF::OPENING_FILE_FAILED;
|
||||
}
|
||||
spi::SpiModes spiMode = spi::SpiModes::MODE_0;
|
||||
uint32_t spiSpeed = 0;
|
||||
cookie.getSpiParameters(spiMode, spiSpeed, nullptr);
|
||||
spiComIF.setSpiSpeedAndMode(fileDescriptor, spiMode, spiSpeed);
|
||||
cookie.assignWriteBuffer(cmdBuf.data());
|
||||
cookie.setTransferSize(2);
|
||||
|
||||
gpioId_t gpioId = cookie.getChipSelectPin();
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t timeoutMs = 0;
|
||||
MutexIF* mutex = spiComIF.getCsMutex();
|
||||
cookie.getMutexParams(timeoutType, timeoutMs);
|
||||
if (mutex == nullptr) {
|
||||
sif::warning << "GyroADIS16507Handler::spiSendCallback: "
|
||||
"Mutex or GPIO interface invalid"
|
||||
<< std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
size_t idx = 0;
|
||||
spi_ioc_transfer* transferStruct = cookie.getTransferStructHandle();
|
||||
uint64_t origTx = transferStruct->tx_buf;
|
||||
uint64_t origRx = transferStruct->rx_buf;
|
||||
while (idx < transferLen) {
|
||||
result = mutex->lockMutex(timeoutType, timeoutMs);
|
||||
if (result != returnvalue::OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "AcsBoardPolling: Failed to lock mutex" << std::endl;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
// Pull SPI CS low. For now, no support for active high given
|
||||
if (gpioId != gpio::NO_GPIO) {
|
||||
gpioIF.pullLow(gpioId);
|
||||
}
|
||||
|
||||
// Execute transfer
|
||||
// Initiate a full duplex SPI transfer.
|
||||
retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie.getTransferStructHandle());
|
||||
if (retval < 0) {
|
||||
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
|
||||
result = SpiComIF::FULL_DUPLEX_TRANSFER_FAILED;
|
||||
}
|
||||
#if FSFW_HAL_SPI_WIRETAPPING == 1
|
||||
comIf->performSpiWiretapping(cookie);
|
||||
#endif /* FSFW_LINUX_SPI_WIRETAPPING == 1 */
|
||||
|
||||
if (gpioId != gpio::NO_GPIO) {
|
||||
gpioIF.pullHigh(gpioId);
|
||||
}
|
||||
mutex->unlockMutex();
|
||||
|
||||
idx += 2;
|
||||
transferStruct->tx_buf += 2;
|
||||
transferStruct->rx_buf += 2;
|
||||
if (idx < transferLen) {
|
||||
usleep(adis1650x::STALL_TIME_MICROSECONDS);
|
||||
}
|
||||
}
|
||||
transferStruct->tx_buf = origTx;
|
||||
transferStruct->rx_buf = origRx;
|
||||
cookie.setTransferSize(transferLen);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void AcsBoardPolling::gyroAdisHandler(GyroAdis& gyro) {
|
||||
ReturnValue_t result;
|
||||
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
|
||||
bool cdHasTimedOut = false;
|
||||
bool mustPerformStartup = false;
|
||||
{
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
mode = gyro.mode;
|
||||
cdHasTimedOut = gyro.countdown.hasTimedOut();
|
||||
mustPerformStartup = gyro.performStartup;
|
||||
}
|
||||
if (mode == acs::SimpleSensorMode::NORMAL and cdHasTimedOut) {
|
||||
if (mustPerformStartup) {
|
||||
uint8_t regList[6];
|
||||
// Read configuration
|
||||
regList[0] = adis1650x::DIAG_STAT_REG;
|
||||
regList[1] = adis1650x::FILTER_CTRL_REG;
|
||||
regList[2] = adis1650x::RANG_MDL_REG;
|
||||
regList[3] = adis1650x::MSC_CTRL_REG;
|
||||
regList[4] = adis1650x::DEC_RATE_REG;
|
||||
regList[5] = adis1650x::PROD_ID_REG;
|
||||
size_t transferLen =
|
||||
adis1650x::prepareReadCommand(regList, sizeof(regList), cmdBuf.data(), cmdBuf.size());
|
||||
result = readAdisCfg(*gyro.cookie, transferLen);
|
||||
if (result != returnvalue::OK) {
|
||||
gyro.replyResult = result;
|
||||
return;
|
||||
}
|
||||
result = spiComIF.readReceivedMessage(gyro.cookie, &rawReply, &dummy);
|
||||
if (result != returnvalue::OK or rawReply == nullptr) {
|
||||
gyro.replyResult = result;
|
||||
return;
|
||||
}
|
||||
uint16_t prodId = (rawReply[12] << 8) | rawReply[13];
|
||||
if (((gyro.type == adis1650x::Type::ADIS16505) and (prodId != adis1650x::PROD_ID_16505)) or
|
||||
((gyro.type == adis1650x::Type::ADIS16507) and (prodId != adis1650x::PROD_ID_16507))) {
|
||||
sif::warning << "AcsPollingTask: Invalid ADIS product ID " << prodId << std::endl;
|
||||
gyro.replyResult = returnvalue::FAILED;
|
||||
return;
|
||||
}
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
gyro.ownReply.cfgWasSet = true;
|
||||
gyro.ownReply.cfg.diagStat = (rawReply[2] << 8) | rawReply[3];
|
||||
gyro.ownReply.cfg.filterSetting = (rawReply[4] << 8) | rawReply[5];
|
||||
gyro.ownReply.cfg.rangMdl = (rawReply[6] << 8) | rawReply[7];
|
||||
gyro.ownReply.cfg.mscCtrlReg = (rawReply[8] << 8) | rawReply[9];
|
||||
gyro.ownReply.cfg.decRateReg = (rawReply[10] << 8) | rawReply[11];
|
||||
gyro.ownReply.cfg.prodId = prodId;
|
||||
gyro.ownReply.data.sensitivity = adis1650x::rangMdlToSensitivity(gyro.ownReply.cfg.rangMdl);
|
||||
gyro.performStartup = false;
|
||||
}
|
||||
// Read regular registers
|
||||
std::memcpy(cmdBuf.data(), adis1650x::BURST_READ_ENABLE.data(),
|
||||
adis1650x::BURST_READ_ENABLE.size());
|
||||
std::memset(cmdBuf.data() + 2, 0, 10 * 2);
|
||||
result = spiComIF.sendMessage(gyro.cookie, cmdBuf.data(), adis1650x::SENSOR_READOUT_SIZE);
|
||||
if (result != returnvalue::OK) {
|
||||
gyro.replyResult = returnvalue::FAILED;
|
||||
return;
|
||||
}
|
||||
result = spiComIF.readReceivedMessage(gyro.cookie, &rawReply, &dummy);
|
||||
if (result != returnvalue::OK or rawReply == nullptr) {
|
||||
gyro.replyResult = returnvalue::FAILED;
|
||||
return;
|
||||
}
|
||||
uint16_t checksum = (rawReply[20] << 8) | rawReply[21];
|
||||
|
||||
// Now verify the read checksum with the expected checksum according to datasheet p. 20
|
||||
uint16_t calcChecksum = 0;
|
||||
for (size_t idx = 2; idx < 20; idx++) {
|
||||
calcChecksum += rawReply[idx];
|
||||
}
|
||||
if (checksum != calcChecksum) {
|
||||
sif::warning << "AcsPollingTask: Invalid ADIS reply checksum" << std::endl;
|
||||
gyro.replyResult = returnvalue::FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
auto burstMode = adis1650x::burstModeFromMscCtrl(gyro.ownReply.cfg.mscCtrlReg);
|
||||
if (burstMode != adis1650x::BurstModes::BURST_16_BURST_SEL_0) {
|
||||
sif::error << "GyroADIS1650XHandler::interpretDeviceReply: Analysis for select burst mode"
|
||||
" not implemented!"
|
||||
<< std::endl;
|
||||
gyro.replyResult = returnvalue::FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
gyro.ownReply.dataWasSet = true;
|
||||
gyro.ownReply.cfg.diagStat = rawReply[2] << 8 | rawReply[3];
|
||||
gyro.ownReply.data.angVelocities[0] = (rawReply[4] << 8) | rawReply[5];
|
||||
gyro.ownReply.data.angVelocities[1] = (rawReply[6] << 8) | rawReply[7];
|
||||
gyro.ownReply.data.angVelocities[2] = (rawReply[8] << 8) | rawReply[9];
|
||||
|
||||
gyro.ownReply.data.accelerations[0] = (rawReply[10] << 8) | rawReply[11];
|
||||
gyro.ownReply.data.accelerations[1] = (rawReply[12] << 8) | rawReply[13];
|
||||
gyro.ownReply.data.accelerations[2] = (rawReply[14] << 8) | rawReply[15];
|
||||
|
||||
gyro.ownReply.data.temperatureRaw = (rawReply[16] << 8) | rawReply[17];
|
||||
}
|
||||
}
|
||||
|
||||
void AcsBoardPolling::mgmLis3Handler(MgmLis3& mgm) {
|
||||
ReturnValue_t result;
|
||||
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
|
||||
bool mustPerformStartup = false;
|
||||
{
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
mode = mgm.mode;
|
||||
mustPerformStartup = mgm.performStartup;
|
||||
}
|
||||
if (mode == acs::SimpleSensorMode::NORMAL) {
|
||||
if (mustPerformStartup) {
|
||||
// To check valid communication, read back identification
|
||||
// register which should always be the same value.
|
||||
cmdBuf[0] = mgmLis3::readCommand(mgmLis3::IDENTIFY_DEVICE_REG_ADDR);
|
||||
cmdBuf[1] = 0x00;
|
||||
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
|
||||
if (result != OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
|
||||
if (result != OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
if (rawReply[1] != mgmLis3::DEVICE_ID) {
|
||||
sif::error << "AcsPollingTask: invalid MGM lis3 device ID" << std::endl;
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
mgm.cfg[0] = mgmLis3::CTRL_REG1_DEFAULT;
|
||||
mgm.cfg[1] = mgmLis3::CTRL_REG2_DEFAULT;
|
||||
mgm.cfg[2] = mgmLis3::CTRL_REG3_DEFAULT;
|
||||
mgm.cfg[3] = mgmLis3::CTRL_REG4_DEFAULT;
|
||||
mgm.cfg[4] = mgmLis3::CTRL_REG5_DEFAULT;
|
||||
cmdBuf[0] = mgmLis3::writeCommand(mgmLis3::CTRL_REG1, true);
|
||||
std::memcpy(cmdBuf.data() + 1, mgm.cfg, 5);
|
||||
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 6);
|
||||
if (result != OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
// Done here. We can always read back config and data during periodic handling
|
||||
mgm.performStartup = false;
|
||||
}
|
||||
cmdBuf[0] = mgmLis3::readCommand(mgmLis3::CTRL_REG1, true);
|
||||
std::memset(cmdBuf.data() + 1, 0, mgmLis3::NR_OF_DATA_AND_CFG_REGISTERS);
|
||||
result =
|
||||
spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), mgmLis3::NR_OF_DATA_AND_CFG_REGISTERS + 1);
|
||||
if (result != returnvalue::OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
|
||||
if (result != returnvalue::OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
// Verify communication by re-checking config
|
||||
if (rawReply[1] != mgm.cfg[0] or rawReply[2] != mgm.cfg[1] or rawReply[3] != mgm.cfg[2] or
|
||||
rawReply[4] != mgm.cfg[3] or rawReply[5] != mgm.cfg[4]) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
{
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
mgm.ownReply.dataWasSet = true;
|
||||
mgm.ownReply.sensitivity = mgmLis3::getSensitivityFactor(mgmLis3::getSensitivity(mgm.cfg[1]));
|
||||
mgm.ownReply.mgmValuesRaw[0] =
|
||||
(rawReply[mgmLis3::X_HIGHBYTE_IDX] << 8) | rawReply[mgmLis3::X_LOWBYTE_IDX];
|
||||
mgm.ownReply.mgmValuesRaw[1] =
|
||||
(rawReply[mgmLis3::Y_HIGHBYTE_IDX] << 8) | rawReply[mgmLis3::Y_LOWBYTE_IDX];
|
||||
mgm.ownReply.mgmValuesRaw[2] =
|
||||
(rawReply[mgmLis3::Z_HIGHBYTE_IDX] << 8) | rawReply[mgmLis3::Z_LOWBYTE_IDX];
|
||||
}
|
||||
// Read tempetature
|
||||
cmdBuf[0] = mgmLis3::readCommand(mgmLis3::TEMP_LOWBYTE, true);
|
||||
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 3);
|
||||
if (result != returnvalue::OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
|
||||
if (result != returnvalue::OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
mgm.ownReply.temperatureWasSet = true;
|
||||
mgm.ownReply.temperatureRaw = (rawReply[2] << 8) | rawReply[1];
|
||||
}
|
||||
}
|
||||
|
||||
void AcsBoardPolling::mgmRm3100Handler(MgmRm3100& mgm) {
|
||||
ReturnValue_t result;
|
||||
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
|
||||
bool mustPerformStartup = false;
|
||||
{
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
mode = mgm.mode;
|
||||
mustPerformStartup = mgm.performStartup;
|
||||
}
|
||||
if (mode == acs::SimpleSensorMode::NORMAL) {
|
||||
if (mustPerformStartup) {
|
||||
// Configure CMM first
|
||||
cmdBuf[0] = mgmRm3100::CMM_REGISTER;
|
||||
cmdBuf[1] = mgmRm3100::CMM_VALUE;
|
||||
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
|
||||
if (result != OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
// Read back register
|
||||
cmdBuf[0] = mgmRm3100::CMM_REGISTER | mgmRm3100::READ_MASK;
|
||||
cmdBuf[1] = 0;
|
||||
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
|
||||
if (result != OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
|
||||
if (result != OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
if (rawReply[1] != mgmRm3100::CMM_VALUE) {
|
||||
sif::error << "AcsBoardPolling: MGM RM3100 read back CMM invalid" << std::endl;
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
// Configure TMRC register
|
||||
cmdBuf[0] = mgmRm3100::TMRC_REGISTER;
|
||||
// hardcoded for now
|
||||
cmdBuf[1] = mgm.tmrcValue;
|
||||
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
|
||||
if (result != OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
// Read back and verify value
|
||||
cmdBuf[0] = mgmRm3100::TMRC_REGISTER | mgmRm3100::READ_MASK;
|
||||
cmdBuf[1] = 0;
|
||||
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
|
||||
if (result != OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
|
||||
if (result != OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
if (rawReply[1] != mgm.tmrcValue) {
|
||||
sif::error << "AcsBoardPolling: MGM RM3100 read back TMRC invalid" << std::endl;
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
mgm.performStartup = false;
|
||||
}
|
||||
// Regular read operation
|
||||
cmdBuf[0] = mgmRm3100::MEASUREMENT_REG_START | mgmRm3100::READ_MASK;
|
||||
std::memset(cmdBuf.data() + 1, 0, 9);
|
||||
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 10);
|
||||
if (result != OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
|
||||
if (result != OK) {
|
||||
mgm.replyResult = result;
|
||||
return;
|
||||
}
|
||||
MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
for (uint8_t idx = 0; idx < 3; idx++) {
|
||||
// Hardcoded, but note that the gain depends on the cycle count
|
||||
// value which is configurable!
|
||||
mgm.ownReply.scaleFactors[idx] = 1.0 / mgmRm3100::DEFAULT_GAIN;
|
||||
}
|
||||
mgm.ownReply.dataWasRead = true;
|
||||
// Bitshift trickery to account for 24 bit signed value.
|
||||
mgm.ownReply.mgmValuesRaw[0] =
|
||||
((rawReply[1] << 24) | (rawReply[2] << 16) | (rawReply[3] << 8)) >> 8;
|
||||
mgm.ownReply.mgmValuesRaw[1] =
|
||||
((rawReply[4] << 24) | (rawReply[5] << 16) | (rawReply[6] << 8)) >> 8;
|
||||
mgm.ownReply.mgmValuesRaw[2] =
|
||||
((rawReply[7] << 24) | (rawReply[8] << 16) | (rawReply[9] << 8)) >> 8;
|
||||
}
|
||||
}
|
91
linux/devices/AcsBoardPolling.h
Normal file
91
linux/devices/AcsBoardPolling.h
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef LINUX_DEVICES_ACSBOARDPOLLING_H_
|
||||
#define LINUX_DEVICES_ACSBOARDPOLLING_H_
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/tasks/SemaphoreIF.h>
|
||||
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmRm3100Helpers.h>
|
||||
#include <fsfw_hal/linux/spi/SpiComIF.h>
|
||||
#include <mission/devices/devicedefinitions/acsPolling.h>
|
||||
#include <mission/devices/devicedefinitions/gyroAdisHelpers.h>
|
||||
|
||||
class AcsBoardPolling : public SystemObject,
|
||||
public ExecutableObjectIF,
|
||||
public DeviceCommunicationIF {
|
||||
public:
|
||||
AcsBoardPolling(object_id_t objectId, SpiComIF& lowLevelComIF, GpioIF& gpioIF);
|
||||
|
||||
ReturnValue_t performOperation(uint8_t operationCode) override;
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
private:
|
||||
enum class InternalState { IDLE, BUSY } state = InternalState::IDLE;
|
||||
MutexIF* ipcLock;
|
||||
static constexpr MutexIF::TimeoutType LOCK_TYPE = MutexIF::TimeoutType::WAITING;
|
||||
static constexpr uint32_t LOCK_TIMEOUT = 20;
|
||||
static constexpr char LOCK_CTX[] = "AcsBoardPolling";
|
||||
SemaphoreIF* semaphore;
|
||||
std::array<uint8_t, 32> cmdBuf;
|
||||
|
||||
struct DevBase {
|
||||
SpiCookie* cookie = nullptr;
|
||||
bool performStartup = false;
|
||||
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
|
||||
ReturnValue_t replyResult = returnvalue::OK;
|
||||
};
|
||||
|
||||
struct GyroAdis : public DevBase {
|
||||
adis1650x::Type type;
|
||||
Countdown countdown;
|
||||
acs::Adis1650XReply ownReply;
|
||||
acs::Adis1650XReply readerReply;
|
||||
};
|
||||
GyroAdis gyro0Adis{};
|
||||
GyroAdis gyro2Adis{};
|
||||
|
||||
struct GyroL3g : public DevBase {
|
||||
uint8_t sensorCfg[5];
|
||||
acs::GyroL3gReply ownReply;
|
||||
acs::GyroL3gReply readerReply;
|
||||
};
|
||||
GyroL3g gyro1L3g{};
|
||||
GyroL3g gyro3L3g{};
|
||||
|
||||
struct MgmRm3100 : public DevBase {
|
||||
uint8_t tmrcValue = mgmRm3100::TMRC_DEFAULT_37HZ_VALUE;
|
||||
acs::MgmRm3100Reply ownReply;
|
||||
acs::MgmRm3100Reply readerReply;
|
||||
};
|
||||
MgmRm3100 mgm1Rm3100;
|
||||
MgmRm3100 mgm3Rm3100;
|
||||
|
||||
struct MgmLis3 : public DevBase {
|
||||
uint8_t cfg[5]{};
|
||||
acs::MgmLis3Reply ownReply;
|
||||
acs::MgmLis3Reply readerReply;
|
||||
};
|
||||
MgmLis3 mgm0Lis3;
|
||||
MgmLis3 mgm2Lis3;
|
||||
|
||||
uint8_t* rawReply = nullptr;
|
||||
size_t dummy = 0;
|
||||
|
||||
SpiComIF& spiComIF;
|
||||
GpioIF& gpioIF;
|
||||
|
||||
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;
|
||||
|
||||
void gyroL3gHandler(GyroL3g& l3g);
|
||||
void gyroAdisHandler(GyroAdis& gyro);
|
||||
void mgmLis3Handler(MgmLis3& mgm);
|
||||
void mgmRm3100Handler(MgmRm3100& mgm);
|
||||
// Special readout: 16us stall time between small 2 byte transfers.
|
||||
ReturnValue_t readAdisCfg(SpiCookie& spiCookie, size_t transferLen);
|
||||
};
|
||||
|
||||
#endif /* LINUX_DEVICES_ACSBOARDPOLLING_H_ */
|
@ -1,8 +1,21 @@
|
||||
if(EIVE_BUILD_GPSD_GPS_HANDLER)
|
||||
target_sources(${OBSW_NAME} PRIVATE
|
||||
GPSHyperionLinuxController.cpp
|
||||
)
|
||||
target_sources(${OBSW_NAME} PRIVATE GpsHyperionLinuxController.cpp)
|
||||
endif()
|
||||
|
||||
target_sources(
|
||||
${OBSW_NAME}
|
||||
PRIVATE Max31865RtdPolling.cpp
|
||||
ScexUartReader.cpp
|
||||
ImtqPollingTask.cpp
|
||||
SusPolling.cpp
|
||||
ScexDleParser.cpp
|
||||
ScexHelper.cpp
|
||||
RwPollingTask.cpp
|
||||
AcsBoardPolling.cpp)
|
||||
|
||||
add_subdirectory(ploc)
|
||||
add_subdirectory(startracker)
|
||||
|
||||
# Dependency on proprietary library
|
||||
if(TGT_BSP MATCHES "arm/q7s")
|
||||
add_subdirectory(startracker)
|
||||
endif()
|
||||
|
@ -1,317 +0,0 @@
|
||||
#include "GPSHyperionLinuxController.h"
|
||||
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/datapool/PoolReadGuard.h"
|
||||
#include "fsfw/timemanager/Clock.h"
|
||||
#include "linux/utility/utility.h"
|
||||
#include "mission/utility/compileTime.h"
|
||||
|
||||
#if FSFW_DEV_HYPERION_GPS_CREATE_NMEA_CSV == 1
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#endif
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
|
||||
GPSHyperionLinuxController::GPSHyperionLinuxController(object_id_t objectId, object_id_t parentId,
|
||||
bool debugHyperionGps)
|
||||
: ExtendedControllerBase(objectId, objects::NO_OBJECT),
|
||||
gpsSet(this),
|
||||
debugHyperionGps(debugHyperionGps) {
|
||||
timeUpdateCd.resetTimer();
|
||||
}
|
||||
|
||||
GPSHyperionLinuxController::~GPSHyperionLinuxController() {
|
||||
gps_stream(&gps, WATCH_DISABLE, nullptr);
|
||||
gps_close(&gps);
|
||||
}
|
||||
|
||||
void GPSHyperionLinuxController::performControlOperation() {
|
||||
#ifdef FSFW_OSAL_LINUX
|
||||
readGpsDataFromGpsd();
|
||||
#endif
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase *GPSHyperionLinuxController::getDataSetHandle(sid_t sid) { return &gpsSet; }
|
||||
|
||||
ReturnValue_t GPSHyperionLinuxController::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) {
|
||||
if (not modeCommanded) {
|
||||
if (mode == MODE_ON or mode == MODE_OFF) {
|
||||
gpsNotOpenSwitch = true;
|
||||
// 5h time to reach fix
|
||||
*msToReachTheMode = MAX_SECONDS_TO_REACH_FIX;
|
||||
maxTimeToReachFix.resetTimer();
|
||||
modeCommanded = true;
|
||||
} else if (mode == MODE_NORMAL) {
|
||||
return HasModesIF::INVALID_MODE;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t GPSHyperionLinuxController::executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy,
|
||||
const uint8_t *data, size_t size) {
|
||||
switch (actionId) {
|
||||
case (GpsHyperion::TRIGGER_RESET_PIN): {
|
||||
if (resetCallback != nullptr) {
|
||||
PoolReadGuard pg(&gpsSet);
|
||||
// Set HK entries invalid
|
||||
gpsSet.setValidity(false, true);
|
||||
resetCallback(resetCallbackArgs);
|
||||
return HasActionsIF::EXECUTION_FINISHED;
|
||||
}
|
||||
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t GPSHyperionLinuxController::initializeLocalDataPool(
|
||||
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(GpsHyperion::ALTITUDE, new PoolEntry<double>({0.0}));
|
||||
localDataPoolMap.emplace(GpsHyperion::LONGITUDE, new PoolEntry<double>({0.0}));
|
||||
localDataPoolMap.emplace(GpsHyperion::LATITUDE, new PoolEntry<double>({0.0}));
|
||||
localDataPoolMap.emplace(GpsHyperion::SPEED, new PoolEntry<double>({0.0}));
|
||||
localDataPoolMap.emplace(GpsHyperion::YEAR, new PoolEntry<uint16_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::MONTH, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::DAY, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::HOURS, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::MINUTES, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::SECONDS, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::UNIX_SECONDS, new PoolEntry<uint32_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::SATS_IN_USE, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::SATS_IN_VIEW, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
|
||||
poolManager.subscribeForPeriodicPacket(gpsSet.getSid(), false, 30.0, false);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void GPSHyperionLinuxController::setResetPinTriggerFunction(gpioResetFunction_t resetCallback,
|
||||
void *args) {
|
||||
this->resetCallback = resetCallback;
|
||||
resetCallbackArgs = args;
|
||||
}
|
||||
|
||||
ReturnValue_t GPSHyperionLinuxController::initialize() {
|
||||
ReturnValue_t result = ExtendedControllerBase::initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
auto openError = [&](const char *type, int error) {
|
||||
if (gpsNotOpenSwitch) {
|
||||
// Opening failed
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Opening GPSMM " << type
|
||||
<< " failed | Error " << error << " | " << gps_errstr(error) << std::endl;
|
||||
#endif
|
||||
gpsNotOpenSwitch = false;
|
||||
}
|
||||
};
|
||||
if (readMode == ReadModes::SOCKET) {
|
||||
int retval = gps_open("localhost", DEFAULT_GPSD_PORT, &gps);
|
||||
if (retval != 0) {
|
||||
openError("Socket", retval);
|
||||
}
|
||||
} else if (readMode == ReadModes::SHM) {
|
||||
int retval = gps_open(GPSD_SHARED_MEMORY, "", &gps);
|
||||
if (retval != 0) {
|
||||
openError("SHM", retval);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t GPSHyperionLinuxController::handleCommandMessage(CommandMessage *message) {
|
||||
return ExtendedControllerBase::handleCommandMessage(message);
|
||||
}
|
||||
|
||||
#ifdef FSFW_OSAL_LINUX
|
||||
|
||||
void GPSHyperionLinuxController::readGpsDataFromGpsd() {
|
||||
auto readError = [&](int error) {
|
||||
if (gpsReadFailedSwitch) {
|
||||
gpsReadFailedSwitch = false;
|
||||
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Reading GPS data failed | "
|
||||
"Error "
|
||||
<< error << " | " << gps_errstr(error) << std::endl;
|
||||
}
|
||||
};
|
||||
currentClientBuf = gps_data(&gps);
|
||||
if (readMode == ReadModes::SOCKET) {
|
||||
gps_stream(&gps, WATCH_ENABLE | WATCH_JSON, nullptr);
|
||||
// Exit if no data is seen in 2 seconds (should not happen)
|
||||
if (not gps_waiting(&gps, 2000000)) {
|
||||
return;
|
||||
}
|
||||
int result = gps_read(&gps);
|
||||
if (result == -1) {
|
||||
readError(result);
|
||||
return;
|
||||
}
|
||||
if (MODE_SET != (MODE_SET & gps.set)) {
|
||||
if (noModeSetCntr >= 0) {
|
||||
noModeSetCntr++;
|
||||
}
|
||||
if (noModeSetCntr == 10) {
|
||||
// TODO: Trigger event here
|
||||
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: No mode could be "
|
||||
"read for 10 consecutive reads"
|
||||
<< std::endl;
|
||||
noModeSetCntr = -1;
|
||||
}
|
||||
}
|
||||
noModeSetCntr = 0;
|
||||
} else if (readMode == ReadModes::SHM) {
|
||||
int result = gps_read(&gps);
|
||||
if (result == -1) {
|
||||
readError(result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
handleGpsRead();
|
||||
}
|
||||
|
||||
ReturnValue_t GPSHyperionLinuxController::handleGpsRead() {
|
||||
PoolReadGuard pg(&gpsSet);
|
||||
if (pg.getReadResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Reading dataset failed" << std::endl;
|
||||
#endif
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
bool validFix = false;
|
||||
static_cast<void>(validFix);
|
||||
// 0: Not seen, 1: No fix, 2: 2D-Fix, 3: 3D-Fix
|
||||
int newFixMode = gps.fix.mode;
|
||||
if (newFixMode == 2 or newFixMode == 3) {
|
||||
validFix = true;
|
||||
}
|
||||
if (gpsSet.fixMode.value != newFixMode) {
|
||||
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, newFixMode);
|
||||
}
|
||||
gpsSet.fixMode.value = newFixMode;
|
||||
if (gps.fix.mode == 0 or gps.fix.mode == 1) {
|
||||
if (modeCommanded and maxTimeToReachFix.hasTimedOut()) {
|
||||
// We are supposed to be on and functioning, but not fix was found
|
||||
if (mode == MODE_ON or mode == MODE_NORMAL) {
|
||||
mode = MODE_OFF;
|
||||
}
|
||||
modeCommanded = false;
|
||||
}
|
||||
gpsSet.setValidity(false, true);
|
||||
} else if (gps.satellites_used > 0) {
|
||||
gpsSet.setValidity(true, true);
|
||||
}
|
||||
|
||||
gpsSet.satInUse.value = gps.satellites_used;
|
||||
gpsSet.satInView.value = gps.satellites_visible;
|
||||
|
||||
if (std::isfinite(gps.fix.latitude)) {
|
||||
// Negative latitude -> South direction
|
||||
gpsSet.latitude.value = gps.fix.latitude;
|
||||
} else {
|
||||
gpsSet.latitude.setValid(false);
|
||||
}
|
||||
|
||||
if (std::isfinite(gps.fix.longitude)) {
|
||||
// Negative longitude -> West direction
|
||||
gpsSet.longitude.value = gps.fix.longitude;
|
||||
} else {
|
||||
gpsSet.longitude.setValid(false);
|
||||
}
|
||||
|
||||
if (std::isfinite(gps.fix.altitude)) {
|
||||
gpsSet.altitude.value = gps.fix.altitude;
|
||||
} else {
|
||||
gpsSet.altitude.setValid(false);
|
||||
}
|
||||
|
||||
if (std::isfinite(gps.fix.speed)) {
|
||||
gpsSet.speed.value = gps.fix.speed;
|
||||
} else {
|
||||
gpsSet.speed.setValid(false);
|
||||
}
|
||||
|
||||
#if LIBGPS_VERSION_MINOR <= 17
|
||||
gpsSet.unixSeconds.value = gps.fix.time;
|
||||
#else
|
||||
gpsSet.unixSeconds.value = gps.fix.time.tv_sec;
|
||||
#endif
|
||||
timeval time = {};
|
||||
time.tv_sec = gpsSet.unixSeconds.value;
|
||||
#if LIBGPS_VERSION_MINOR <= 17
|
||||
double fractionalPart = gps.fix.time - std::floor(gps.fix.time);
|
||||
time.tv_usec = fractionalPart * 1000.0 * 1000.0;
|
||||
#else
|
||||
time.tv_usec = gps.fix.time.tv_nsec / 1000;
|
||||
#endif
|
||||
std::time_t t = std::time(nullptr);
|
||||
if (time.tv_sec == t) {
|
||||
timeIsConstantCounter++;
|
||||
} else {
|
||||
timeIsConstantCounter = 0;
|
||||
}
|
||||
if (timeInit and validFix) {
|
||||
if (not utility::timeSanityCheck()) {
|
||||
#if OBSW_VERBOSE_LEVEL >= 1
|
||||
time_t timeRaw = time.tv_sec;
|
||||
std::tm *timeTm = std::gmtime(&timeRaw);
|
||||
sif::info << "Setting invalid system time from GPS data directly: "
|
||||
<< std::put_time(timeTm, "%c %Z") << std::endl;
|
||||
#endif
|
||||
// For some reason, the clock needs to be somewhat correct for NTP to work. Really dumb..
|
||||
Clock::setClock(&time);
|
||||
}
|
||||
timeInit = false;
|
||||
}
|
||||
// If the received time does not change anymore for whatever reason, do not set it here
|
||||
// to avoid stale times. Also, don't do it too often often to avoid jumping times
|
||||
if (timeIsConstantCounter < 20 and timeUpdateCd.hasTimedOut()) {
|
||||
// Update the system time here for now. NTP seems to be unable to do so for whatever reason.
|
||||
// Further tests have shown that the time seems to be set by NTPD after some time..
|
||||
// Clock::setClock(&time);
|
||||
timeUpdateCd.resetTimer();
|
||||
}
|
||||
|
||||
Clock::TimeOfDay_t timeOfDay = {};
|
||||
Clock::convertTimevalToTimeOfDay(&time, &timeOfDay);
|
||||
gpsSet.year = timeOfDay.year;
|
||||
gpsSet.month = timeOfDay.month;
|
||||
gpsSet.day = timeOfDay.day;
|
||||
gpsSet.hours = timeOfDay.hour;
|
||||
gpsSet.minutes = timeOfDay.minute;
|
||||
gpsSet.seconds = timeOfDay.second;
|
||||
if (debugHyperionGps) {
|
||||
sif::info << "-- Hyperion GPS Data --" << std::endl;
|
||||
#if LIBGPS_VERSION_MINOR <= 17
|
||||
time_t timeRaw = gps.fix.time;
|
||||
#else
|
||||
time_t timeRaw = gps.fix.time.tv_sec;
|
||||
#endif
|
||||
std::tm *time = gmtime(&timeRaw);
|
||||
std::cout << "Time: " << std::put_time(time, "%c %Z") << std::endl;
|
||||
std::cout << "Visible satellites: " << gps.satellites_visible << std::endl;
|
||||
std::cout << "Satellites used: " << gps.satellites_used << std::endl;
|
||||
std::cout << "Fix (0:Not Seen|1:No Fix|2:2D|3:3D): " << gps.fix.mode << std::endl;
|
||||
std::cout << "Latitude: " << gps.fix.latitude << std::endl;
|
||||
std::cout << "Longitude: " << gps.fix.longitude << std::endl;
|
||||
#if LIBGPS_VERSION_MINOR <= 17
|
||||
std::cout << "Altitude(MSL): " << gps.fix.altitude << std::endl;
|
||||
#else
|
||||
std::cout << "Altitude(MSL): " << gps.fix.altMSL << std::endl;
|
||||
#endif
|
||||
std::cout << "Speed(m/s): " << gps.fix.speed << std::endl;
|
||||
std::time_t t = std::time(nullptr);
|
||||
std::tm tm = *std::gmtime(&t);
|
||||
std::cout << "C Time: " << std::put_time(&tm, "%c") << std::endl;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
#endif
|
379
linux/devices/GpsHyperionLinuxController.cpp
Normal file
379
linux/devices/GpsHyperionLinuxController.cpp
Normal file
@ -0,0 +1,379 @@
|
||||
#include "GpsHyperionLinuxController.h"
|
||||
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/datapool/PoolReadGuard.h"
|
||||
#include "fsfw/timemanager/Clock.h"
|
||||
#include "linux/utility/utility.h"
|
||||
#include "mission/utility/compileTime.h"
|
||||
|
||||
#if FSFW_DEV_HYPERION_GPS_CREATE_NMEA_CSV == 1
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#endif
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
|
||||
GpsHyperionLinuxController::GpsHyperionLinuxController(object_id_t objectId, object_id_t parentId,
|
||||
bool debugHyperionGps)
|
||||
: ExtendedControllerBase(objectId), gpsSet(this), debugHyperionGps(debugHyperionGps) {}
|
||||
|
||||
GpsHyperionLinuxController::~GpsHyperionLinuxController() {
|
||||
gps_stream(&gps, WATCH_DISABLE, nullptr);
|
||||
gps_close(&gps);
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase *GpsHyperionLinuxController::getDataSetHandle(sid_t sid) { return &gpsSet; }
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) {
|
||||
if (not modeCommanded) {
|
||||
if (mode == MODE_ON or mode == MODE_OFF) {
|
||||
// 5h time to reach fix
|
||||
*msToReachTheMode = MAX_SECONDS_TO_REACH_FIX;
|
||||
maxTimeToReachFix.resetTimer();
|
||||
modeCommanded = true;
|
||||
} else if (mode == MODE_NORMAL) {
|
||||
return HasModesIF::INVALID_MODE;
|
||||
}
|
||||
}
|
||||
if (mode == MODE_OFF) {
|
||||
PoolReadGuard pg(&gpsSet);
|
||||
gpsSet.setValidity(false, true);
|
||||
// There can't be a fix with a device that is off.
|
||||
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, 0);
|
||||
gpsSet.fixMode.value = 0;
|
||||
oneShotSwitches.reset();
|
||||
modeCommanded = false;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy,
|
||||
const uint8_t *data, size_t size) {
|
||||
switch (actionId) {
|
||||
case (GpsHyperion::TRIGGER_RESET_PIN_GNSS): {
|
||||
if (resetCallback != nullptr) {
|
||||
PoolReadGuard pg(&gpsSet);
|
||||
// Set HK entries invalid
|
||||
gpsSet.setValidity(false, true);
|
||||
resetCallback(data, size, resetCallbackArgs);
|
||||
return HasActionsIF::EXECUTION_FINISHED;
|
||||
}
|
||||
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::initializeLocalDataPool(
|
||||
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(GpsHyperion::ALTITUDE, new PoolEntry<double>({0.0}));
|
||||
localDataPoolMap.emplace(GpsHyperion::LONGITUDE, new PoolEntry<double>({0.0}));
|
||||
localDataPoolMap.emplace(GpsHyperion::LATITUDE, new PoolEntry<double>({0.0}));
|
||||
localDataPoolMap.emplace(GpsHyperion::SPEED, new PoolEntry<double>({0.0}));
|
||||
localDataPoolMap.emplace(GpsHyperion::YEAR, new PoolEntry<uint16_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::MONTH, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::DAY, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::HOURS, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::MINUTES, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::SECONDS, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::UNIX_SECONDS, new PoolEntry<uint32_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::SATS_IN_USE, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::SATS_IN_VIEW, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
|
||||
poolManager.subscribeForRegularPeriodicPacket({gpsSet.getSid(), false, 30.0});
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void GpsHyperionLinuxController::setResetPinTriggerFunction(gpioResetFunction_t resetCallback,
|
||||
void *args) {
|
||||
this->resetCallback = resetCallback;
|
||||
resetCallbackArgs = args;
|
||||
}
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::performOperation(uint8_t opCode) {
|
||||
handleQueue();
|
||||
poolManager.performHkOperation();
|
||||
while (true) {
|
||||
#if OBSW_THREAD_TRACING == 1
|
||||
trace::threadTrace(opCounter, "GPS CTRL");
|
||||
#endif
|
||||
bool callAgainImmediately = readGpsDataFromGpsd();
|
||||
if (not callAgainImmediately) {
|
||||
handleQueue();
|
||||
poolManager.performHkOperation();
|
||||
TaskFactory::delayTask(250);
|
||||
}
|
||||
}
|
||||
// Should never be reached.
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::initialize() {
|
||||
ReturnValue_t result = ExtendedControllerBase::initialize();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
auto openError = [&](const char *type, int error) {
|
||||
// Opening failed
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Opening GPSMM " << type
|
||||
<< " failed | Error " << error << " | " << gps_errstr(error) << std::endl;
|
||||
#endif
|
||||
};
|
||||
if (readMode == ReadModes::SOCKET) {
|
||||
int retval = gps_open("localhost", DEFAULT_GPSD_PORT, &gps);
|
||||
if (retval != 0) {
|
||||
openError("Socket", retval);
|
||||
return ObjectManager::CHILD_INIT_FAILED;
|
||||
}
|
||||
gps_stream(&gps, WATCH_ENABLE | WATCH_JSON, nullptr);
|
||||
} else if (readMode == ReadModes::SHM) {
|
||||
int retval = gps_open(GPSD_SHARED_MEMORY, "", &gps);
|
||||
if (retval != 0) {
|
||||
openError("SHM", retval);
|
||||
return ObjectManager::CHILD_INIT_FAILED;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::handleCommandMessage(CommandMessage *message) {
|
||||
return ExtendedControllerBase::handleCommandMessage(message);
|
||||
}
|
||||
|
||||
void GpsHyperionLinuxController::performControlOperation() {}
|
||||
|
||||
bool GpsHyperionLinuxController::readGpsDataFromGpsd() {
|
||||
auto readError = [&]() {
|
||||
if (oneShotSwitches.gpsReadFailedSwitch) {
|
||||
oneShotSwitches.gpsReadFailedSwitch = false;
|
||||
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Reading GPS data failed | "
|
||||
"Error "
|
||||
<< errno << " | " << gps_errstr(errno) << std::endl;
|
||||
}
|
||||
};
|
||||
// GPS is off, no point in reading data from GPSD.
|
||||
if (mode == MODE_OFF) {
|
||||
return false;
|
||||
}
|
||||
if (readMode == ReadModes::SOCKET) {
|
||||
// Poll the GPS.
|
||||
if (gps_waiting(&gps, 0)) {
|
||||
if (-1 == gps_read(&gps)) {
|
||||
readError();
|
||||
return false;
|
||||
}
|
||||
oneShotSwitches.gpsReadFailedSwitch = true;
|
||||
ReturnValue_t result = handleGpsReadData();
|
||||
if (result == returnvalue::OK) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
noModeSetCntr = 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (readMode == ReadModes::SHM) {
|
||||
sif::error << "GpsHyperionLinuxController::readGpsDataFromGpsdPermanentLoop: "
|
||||
"SHM read not implemented"
|
||||
<< std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
|
||||
bool modeIsSet = true;
|
||||
if (MODE_SET != (MODE_SET & gps.set)) {
|
||||
if (mode != MODE_OFF) {
|
||||
if (maxTimeToReachFix.hasTimedOut() and oneShotSwitches.cantGetFixSwitch) {
|
||||
sif::warning << "GpsHyperionLinuxController: No mode could be set in allowed "
|
||||
<< maxTimeToReachFix.getTimeoutMs() / 1000 << " seconds" << std::endl;
|
||||
triggerEvent(GpsHyperion::CANT_GET_FIX, maxTimeToReachFix.getTimeoutMs());
|
||||
oneShotSwitches.cantGetFixSwitch = false;
|
||||
}
|
||||
modeIsSet = false;
|
||||
} else {
|
||||
// GPS device is off anyway, so do other handling
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
PoolReadGuard pg(&gpsSet);
|
||||
if (pg.getReadResult() != returnvalue::OK) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
sif::warning << "GPSHyperionHandler::readGpsDataFromGpsd: Reading dataset failed" << std::endl;
|
||||
#endif
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
bool validFix = false;
|
||||
uint8_t newFix = 0;
|
||||
if (modeIsSet) {
|
||||
// 0: Not seen, 1: No fix, 2: 2D-Fix, 3: 3D-Fix
|
||||
if (gps.fix.mode == 2 or gps.fix.mode == 3) {
|
||||
validFix = true;
|
||||
}
|
||||
newFix = gps.fix.mode;
|
||||
if (newFix == 0 or newFix == 1) {
|
||||
if (modeCommanded and maxTimeToReachFix.hasTimedOut()) {
|
||||
// We are supposed to be on and functioning, but no fix was found
|
||||
if (mode == MODE_ON or mode == MODE_NORMAL) {
|
||||
mode = MODE_OFF;
|
||||
}
|
||||
modeCommanded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gpsSet.fixMode.value != newFix) {
|
||||
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, newFix);
|
||||
}
|
||||
gpsSet.fixMode = newFix;
|
||||
gpsSet.fixMode.setValid(modeIsSet);
|
||||
|
||||
// Only set on specific messages, so only set a valid flag to invalid
|
||||
// if not set for more than a full message set (10 messages here)
|
||||
if (SATELLITE_SET == (SATELLITE_SET & gps.set)) {
|
||||
gpsSet.satInUse.value = gps.satellites_used;
|
||||
gpsSet.satInView.value = gps.satellites_visible;
|
||||
if (not gpsSet.satInUse.isValid()) {
|
||||
gpsSet.satInUse.setValid(true);
|
||||
gpsSet.satInView.setValid(true);
|
||||
}
|
||||
satNotSetCounter = 0;
|
||||
} else {
|
||||
satNotSetCounter++;
|
||||
if (gpsSet.satInUse.isValid() and satNotSetCounter >= 10) {
|
||||
gpsSet.satInUse.setValid(false);
|
||||
gpsSet.satInView.setValid(false);
|
||||
}
|
||||
}
|
||||
|
||||
// LATLON is set for every message, no need for a counter
|
||||
bool latValid = false;
|
||||
bool longValid = false;
|
||||
if (LATLON_SET == (LATLON_SET & gps.set)) {
|
||||
if (std::isfinite(gps.fix.latitude)) {
|
||||
// Negative latitude -> South direction
|
||||
gpsSet.latitude.value = gps.fix.latitude;
|
||||
// As specified in gps.h: Only valid if mode >= 2
|
||||
if (gps.fix.mode >= 2) {
|
||||
latValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::isfinite(gps.fix.longitude)) {
|
||||
// Negative longitude -> West direction
|
||||
gpsSet.longitude.value = gps.fix.longitude;
|
||||
// As specified in gps.h: Only valid if mode >= 2
|
||||
if (gps.fix.mode >= 2) {
|
||||
longValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
gpsSet.latitude.setValid(latValid);
|
||||
gpsSet.longitude.setValid(longValid);
|
||||
|
||||
// ALTITUDE is set for every message, no need for a counter
|
||||
bool altitudeValid = false;
|
||||
if (ALTITUDE_SET == (ALTITUDE_SET & gps.set) && std::isfinite(gps.fix.altitude)) {
|
||||
gpsSet.altitude.value = gps.fix.altitude;
|
||||
// As specified in gps.h: Only valid if mode == 3
|
||||
if (gps.fix.mode == 3) {
|
||||
altitudeValid = true;
|
||||
}
|
||||
}
|
||||
gpsSet.altitude.setValid(altitudeValid);
|
||||
|
||||
// SPEED is set for every message, no need for a counter
|
||||
bool speedValid = false;
|
||||
if (SPEED_SET == (SPEED_SET & gps.set) && std::isfinite(gps.fix.speed)) {
|
||||
gpsSet.speed.value = gps.fix.speed;
|
||||
speedValid = true;
|
||||
}
|
||||
gpsSet.speed.setValid(speedValid);
|
||||
|
||||
// TIME is set for every message, no need for a counter
|
||||
bool timeValid = false;
|
||||
if (TIME_SET == (TIME_SET & gps.set)) {
|
||||
timeValid = true;
|
||||
timeval time = {};
|
||||
#if LIBGPS_VERSION_MINOR <= 17
|
||||
gpsSet.unixSeconds.value = std::floor(gps.fix.time);
|
||||
double fractionalPart = gps.fix.time - gpsSet.unixSeconds.value;
|
||||
time.tv_usec = fractionalPart * 1000.0 * 1000.0;
|
||||
#else
|
||||
gpsSet.unixSeconds.value = gps.fix.time.tv_sec;
|
||||
time.tv_usec = gps.fix.time.tv_nsec / 1000;
|
||||
#endif
|
||||
time.tv_sec = gpsSet.unixSeconds.value;
|
||||
// If the time is totally wrong (e.g. year 2000 after system reset because we do not have a RTC
|
||||
// and no time file available) we set it with the roughly valid time from the GPS.
|
||||
// NTP might only work if the time difference between sys time and current time is not too
|
||||
// large.
|
||||
overwriteTimeIfNotSane(time, validFix);
|
||||
Clock::TimeOfDay_t timeOfDay = {};
|
||||
Clock::convertTimevalToTimeOfDay(&time, &timeOfDay);
|
||||
gpsSet.year = timeOfDay.year;
|
||||
gpsSet.month = timeOfDay.month;
|
||||
gpsSet.day = timeOfDay.day;
|
||||
gpsSet.hours = timeOfDay.hour;
|
||||
gpsSet.minutes = timeOfDay.minute;
|
||||
gpsSet.seconds = timeOfDay.second;
|
||||
}
|
||||
gpsSet.unixSeconds.setValid(timeValid);
|
||||
gpsSet.year.setValid(timeValid);
|
||||
gpsSet.month.setValid(timeValid);
|
||||
gpsSet.day.setValid(timeValid);
|
||||
gpsSet.hours.setValid(timeValid);
|
||||
gpsSet.minutes.setValid(timeValid);
|
||||
gpsSet.seconds.setValid(timeValid);
|
||||
|
||||
if (debugHyperionGps) {
|
||||
sif::info << "-- Hyperion GPS Data --" << std::endl;
|
||||
#if LIBGPS_VERSION_MINOR <= 17
|
||||
time_t timeRaw = gpsSet.unixSeconds.value;
|
||||
#else
|
||||
time_t timeRaw = gps.fix.time.tv_sec;
|
||||
#endif
|
||||
std::tm *time = gmtime(&timeRaw);
|
||||
std::cout << "Time: " << std::put_time(time, "%c %Z") << std::endl;
|
||||
std::cout << "Visible satellites: " << gps.satellites_visible << std::endl;
|
||||
std::cout << "Satellites used: " << gps.satellites_used << std::endl;
|
||||
std::cout << "Fix (0:Not Seen|1:No Fix|2:2D|3:3D): " << gps.fix.mode << std::endl;
|
||||
std::cout << "Latitude: " << gps.fix.latitude << std::endl;
|
||||
std::cout << "Longitude: " << gps.fix.longitude << std::endl;
|
||||
#if LIBGPS_VERSION_MINOR <= 17
|
||||
std::cout << "Altitude(MSL): " << gps.fix.altitude << std::endl;
|
||||
#else
|
||||
std::cout << "Altitude(MSL): " << gps.fix.altMSL << std::endl;
|
||||
#endif
|
||||
std::cout << "Speed(m/s): " << gps.fix.speed << std::endl;
|
||||
std::time_t t = std::time(nullptr);
|
||||
std::tm tm = *std::gmtime(&t);
|
||||
std::cout << "C Time: " << std::put_time(&tm, "%c") << std::endl;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void GpsHyperionLinuxController::overwriteTimeIfNotSane(timeval time, bool validFix) {
|
||||
if (not timeInit and validFix) {
|
||||
if (not utility::timeSanityCheck()) {
|
||||
#if OBSW_VERBOSE_LEVEL >= 1
|
||||
time_t timeRaw = time.tv_sec;
|
||||
std::tm *timeTm = std::gmtime(&timeRaw);
|
||||
sif::info << "Overwriting invalid system time from GPS data directly: "
|
||||
<< std::put_time(timeTm, "%c %Z") << std::endl;
|
||||
#endif
|
||||
// For some reason, the clock needs to be somewhat correct for NTP to work. Really dumb..
|
||||
Clock::setClock(&time);
|
||||
}
|
||||
timeInit = true;
|
||||
}
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
#ifndef MISSION_DEVICES_GPSHYPERIONHANDLER_H_
|
||||
#define MISSION_DEVICES_GPSHYPERIONHANDLER_H_
|
||||
|
||||
#include "commonSubsystemIds.h"
|
||||
#include "eive/eventSubsystemIds.h"
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/controller/ExtendedControllerBase.h"
|
||||
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
|
||||
#include "mission/devices/devicedefinitions/GPSDefinitions.h"
|
||||
#include "mission/trace.h"
|
||||
|
||||
#ifdef FSFW_OSAL_LINUX
|
||||
#include <gps.h>
|
||||
@ -20,18 +21,20 @@
|
||||
* This device handler can only be used on Linux system where the gpsd daemon with shared memory
|
||||
* export is running.
|
||||
*/
|
||||
class GPSHyperionLinuxController : public ExtendedControllerBase {
|
||||
class GpsHyperionLinuxController : public ExtendedControllerBase {
|
||||
public:
|
||||
static constexpr uint32_t MAX_SECONDS_TO_REACH_FIX = 60 * 60 * 5;
|
||||
// 30 minutes
|
||||
static constexpr uint32_t MAX_SECONDS_TO_REACH_FIX = 60 * 30;
|
||||
|
||||
enum ReadModes { SHM = 0, SOCKET = 1 };
|
||||
|
||||
GPSHyperionLinuxController(object_id_t objectId, object_id_t parentId,
|
||||
GpsHyperionLinuxController(object_id_t objectId, object_id_t parentId,
|
||||
bool debugHyperionGps = false);
|
||||
virtual ~GPSHyperionLinuxController();
|
||||
virtual ~GpsHyperionLinuxController();
|
||||
|
||||
using gpioResetFunction_t = ReturnValue_t (*)(void* args);
|
||||
using gpioResetFunction_t = ReturnValue_t (*)(const uint8_t* actionData, size_t len, void* args);
|
||||
|
||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
void setResetPinTriggerFunction(gpioResetFunction_t resetCallback, void* args);
|
||||
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
|
||||
void performControlOperation() override;
|
||||
@ -49,7 +52,7 @@ class GPSHyperionLinuxController : public ExtendedControllerBase {
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
|
||||
ReturnValue_t handleGpsRead();
|
||||
ReturnValue_t handleGpsReadData();
|
||||
|
||||
private:
|
||||
GpsPrimaryDataset gpsSet;
|
||||
@ -57,16 +60,34 @@ class GPSHyperionLinuxController : public ExtendedControllerBase {
|
||||
const char* currentClientBuf = nullptr;
|
||||
ReadModes readMode = ReadModes::SOCKET;
|
||||
Countdown maxTimeToReachFix = Countdown(MAX_SECONDS_TO_REACH_FIX * 1000);
|
||||
bool modeCommanded = true;
|
||||
bool timeInit = true;
|
||||
bool gpsNotOpenSwitch = true;
|
||||
bool gpsReadFailedSwitch = true;
|
||||
bool modeCommanded = false;
|
||||
bool timeInit = false;
|
||||
uint8_t satNotSetCounter = 0;
|
||||
|
||||
#if OBSW_THREAD_TRACING == 1
|
||||
uint32_t opCounter = 0;
|
||||
#endif
|
||||
|
||||
struct OneShotSwitches {
|
||||
void reset() {
|
||||
gpsReadFailedSwitch = true;
|
||||
cantGetFixSwitch = true;
|
||||
}
|
||||
bool gpsReadFailedSwitch = true;
|
||||
bool cantGetFixSwitch = true;
|
||||
|
||||
} oneShotSwitches;
|
||||
|
||||
bool debugHyperionGps = false;
|
||||
int32_t noModeSetCntr = 0;
|
||||
uint32_t timeIsConstantCounter = 0;
|
||||
Countdown timeUpdateCd = Countdown(60);
|
||||
|
||||
void readGpsDataFromGpsd();
|
||||
// Returns true if the function should be called again or false if other
|
||||
// controller handling can be done.
|
||||
bool readGpsDataFromGpsd();
|
||||
// If the time is totally wrong (e.g. year 2000 after system reset because we do not have a RTC)
|
||||
// we set it with the roughly valid time from the GPS. For some reason, NTP might only work
|
||||
// if the time difference between sys time and current time is not too large
|
||||
void overwriteTimeIfNotSane(timeval time, bool validFix);
|
||||
};
|
||||
|
||||
#endif /* MISSION_DEVICES_GPSHYPERIONHANDLER_H_ */
|
477
linux/devices/ImtqPollingTask.cpp
Normal file
477
linux/devices/ImtqPollingTask.cpp
Normal file
@ -0,0 +1,477 @@
|
||||
#include "ImtqPollingTask.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <fsfw/tasks/SemaphoreFactory.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
#include <fsfw_hal/linux/UnixFileGuard.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
|
||||
ImtqPollingTask::ImtqPollingTask(object_id_t imtqPollingTask) : SystemObject(imtqPollingTask) {
|
||||
semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
|
||||
semaphore->acquire();
|
||||
ipcLock = MutexFactory::instance()->createMutex();
|
||||
bufLock = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
ReturnValue_t ImtqPollingTask::performOperation(uint8_t operationCode) {
|
||||
while (true) {
|
||||
ipcLock->lockMutex();
|
||||
state = InternalState::IDLE;
|
||||
ipcLock->unlockMutex();
|
||||
semaphore->acquire();
|
||||
|
||||
comStatus = returnvalue::OK;
|
||||
// Stopwatch watch;
|
||||
switch (currentRequest) {
|
||||
case imtq::RequestType::MEASURE_NO_ACTUATION: {
|
||||
// Measured to take 24 ms for debug and release builds.
|
||||
// Stopwatch watch;
|
||||
handleMeasureStep();
|
||||
break;
|
||||
}
|
||||
case imtq::RequestType::ACTUATE: {
|
||||
handleActuateStep();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void ImtqPollingTask::handleMeasureStep() {
|
||||
size_t replyLen = 0;
|
||||
uint8_t* replyPtr;
|
||||
ImtqRepliesDefault replies(replyBuf.data());
|
||||
// If some startup handling is added later, set configured after it was done once.
|
||||
replies.setConfigured();
|
||||
|
||||
// Can be used later to verify correct timing (e.g. all data has been read)
|
||||
clearReadFlagsDefault(replies);
|
||||
auto i2cCmdExecMeasure = [&](imtq::CC::CC cc) {
|
||||
ccToReplyPtrMeasure(replies, cc, &replyPtr, replyLen);
|
||||
return i2cCmdExecDefault(cc, replyPtr, replyLen, imtq::MGM_MEASUREMENT_LOW_LEVEL_ERROR);
|
||||
};
|
||||
|
||||
cmdLen = 1;
|
||||
cmdBuf[0] = imtq::CC::GET_SYSTEM_STATE;
|
||||
if (i2cCmdExecMeasure(imtq::CC::GET_SYSTEM_STATE) != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
ignoreNextActuateRequest =
|
||||
(replies.getSystemState()[2] == static_cast<uint8_t>(imtq::mode::SELF_TEST));
|
||||
if (ignoreNextActuateRequest) {
|
||||
// Do not command anything until self-test is done.
|
||||
return;
|
||||
}
|
||||
|
||||
if (specialRequest != imtq::SpecialRequest::NONE) {
|
||||
auto executeSelfTest = [&](imtq::selfTest::Axis axis) {
|
||||
cmdBuf[0] = imtq::CC::SELF_TEST_CMD;
|
||||
cmdBuf[1] = axis;
|
||||
return i2cCmdExecMeasure(imtq::CC::SELF_TEST_CMD);
|
||||
};
|
||||
// If a self-test is already ongoing, ignore the request.
|
||||
if (replies.getSystemState()[2] != static_cast<uint8_t>(imtq::mode::SELF_TEST)) {
|
||||
switch (specialRequest) {
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_POS_X): {
|
||||
executeSelfTest(imtq::selfTest::Axis::X_POSITIVE);
|
||||
break;
|
||||
}
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_NEG_X): {
|
||||
executeSelfTest(imtq::selfTest::Axis::X_NEGATIVE);
|
||||
break;
|
||||
}
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_POS_Y): {
|
||||
executeSelfTest(imtq::selfTest::Axis::Y_POSITIVE);
|
||||
break;
|
||||
}
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_NEG_Y): {
|
||||
executeSelfTest(imtq::selfTest::Axis::Y_NEGATIVE);
|
||||
break;
|
||||
}
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_POS_Z): {
|
||||
executeSelfTest(imtq::selfTest::Axis::Z_POSITIVE);
|
||||
break;
|
||||
}
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_NEG_Z): {
|
||||
executeSelfTest(imtq::selfTest::Axis::Z_NEGATIVE);
|
||||
break;
|
||||
}
|
||||
case (imtq::SpecialRequest::GET_SELF_TEST_RESULT): {
|
||||
cmdBuf[0] = imtq::CC::GET_SELF_TEST_RESULT;
|
||||
i2cCmdExecMeasure(imtq::CC::GET_SELF_TEST_RESULT);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Should never happen
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We are done. Only request self test or results here.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The I2C IP core on EIVE sometimes glitches out. Send start MTM measurement twice.
|
||||
cmdBuf[0] = imtq::CC::START_MTM_MEASUREMENT;
|
||||
if (i2cCmdExecMeasure(imtq::CC::START_MTM_MEASUREMENT) != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
cmdBuf[0] = imtq::CC::START_MTM_MEASUREMENT;
|
||||
if (i2cCmdExecMeasure(imtq::CC::START_MTM_MEASUREMENT) != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
// Takes a bit of time to take measurements. Subtract a bit because of the delay of previous
|
||||
// commands.
|
||||
TaskFactory::delayTask(currentIntegrationTimeMs + MGM_READ_BUFFER_TIME_MS);
|
||||
|
||||
cmdBuf[0] = imtq::CC::GET_RAW_MTM_MEASUREMENT;
|
||||
if (i2cCmdExecMeasure(imtq::CC::GET_RAW_MTM_MEASUREMENT) != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
bool mgmMeasurementTooOld = false;
|
||||
// See p.39 of the iMTQ user manual. If the NEW bit of the STAT bitfield is not set, we probably
|
||||
// have old data. Which can be really bad for ACS. And everything.
|
||||
if ((replyPtr[2] >> 7) == 0) {
|
||||
replyPtr[0] = false;
|
||||
mgmMeasurementTooOld = true;
|
||||
}
|
||||
|
||||
cmdBuf[0] = imtq::CC::GET_ENG_HK_DATA;
|
||||
if (i2cCmdExecMeasure(imtq::CC::GET_ENG_HK_DATA) != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
cmdBuf[0] = imtq::CC::GET_CAL_MTM_MEASUREMENT;
|
||||
if (i2cCmdExecMeasure(imtq::CC::GET_CAL_MTM_MEASUREMENT) != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
if (mgmMeasurementTooOld) {
|
||||
sif::error << "IMTQ: MGM measurement too old" << std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void ImtqPollingTask::handleActuateStep() {
|
||||
uint8_t* replyPtr = nullptr;
|
||||
size_t replyLen = 0;
|
||||
// No point when self-test mode is active.
|
||||
if (ignoreNextActuateRequest) {
|
||||
return;
|
||||
}
|
||||
ImtqRepliesWithTorque replies(replyBufActuation.data());
|
||||
// Can be used later to verify correct timing (e.g. all data has been read)
|
||||
clearReadFlagsWithTorque(replies);
|
||||
auto i2cCmdExecActuate = [&](imtq::CC::CC cc) {
|
||||
ccToReplyPtrActuate(replies, cc, &replyPtr, replyLen);
|
||||
return i2cCmdExecDefault(cc, replyPtr, replyLen, imtq::ACTUATE_CMD_LOW_LEVEL_ERROR);
|
||||
};
|
||||
buildDipoleCommand();
|
||||
if (i2cCmdExecActuate(imtq::CC::START_ACTUATION_DIPOLE) != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
TaskFactory::delayTask(10);
|
||||
|
||||
cmdLen = 1;
|
||||
// The I2C IP core on EIVE sometimes glitches out. Send start MTM measurement twice.
|
||||
cmdBuf[0] = imtq::CC::START_MTM_MEASUREMENT;
|
||||
if (i2cCmdExecActuate(imtq::CC::START_MTM_MEASUREMENT) != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
cmdBuf[0] = imtq::CC::START_MTM_MEASUREMENT;
|
||||
if (i2cCmdExecActuate(imtq::CC::START_MTM_MEASUREMENT) != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
TaskFactory::delayTask(currentIntegrationTimeMs + MGM_READ_BUFFER_TIME_MS);
|
||||
|
||||
cmdBuf[0] = imtq::CC::GET_RAW_MTM_MEASUREMENT;
|
||||
if (i2cCmdExecActuate(imtq::CC::GET_RAW_MTM_MEASUREMENT) != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
bool measurementWasTooOld = false;
|
||||
// See p.39 of the iMTQ user manual. If the NEW bit of the STAT bitfield is not set, we probably
|
||||
// have old data. Which can be really bad for ACS. And everything.
|
||||
if ((replyPtr[2] >> 7) == 0) {
|
||||
measurementWasTooOld = true;
|
||||
replyPtr[0] = false;
|
||||
}
|
||||
|
||||
cmdBuf[0] = imtq::CC::GET_ENG_HK_DATA;
|
||||
if (i2cCmdExecActuate(imtq::CC::GET_ENG_HK_DATA) != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (measurementWasTooOld) {
|
||||
sif::error << "IMTQ: MGM measurement too old" << std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ReturnValue_t ImtqPollingTask::initialize() { return returnvalue::OK; }
|
||||
|
||||
ReturnValue_t ImtqPollingTask::initializeInterface(CookieIF* cookie) {
|
||||
i2cCookie = dynamic_cast<I2cCookie*>(cookie);
|
||||
if (i2cCookie == nullptr) {
|
||||
sif::error << "ImtqPollingTask::initializeInterface: Invalid I2C cookie" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
i2cDev = i2cCookie->getDeviceFile().c_str();
|
||||
i2cAddr = i2cCookie->getAddress();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t ImtqPollingTask::sendMessage(CookieIF* cookie, const uint8_t* sendData,
|
||||
size_t sendLen) {
|
||||
const auto* imtqReq = reinterpret_cast<const imtq::Request*>(sendData);
|
||||
{
|
||||
MutexGuard mg(ipcLock);
|
||||
if (imtqReq->request == imtq::RequestType::ACTUATE) {
|
||||
std::memcpy(dipoles, imtqReq->dipoles, sizeof(dipoles));
|
||||
torqueDuration = imtqReq->torqueDuration;
|
||||
}
|
||||
currentRequest = imtqReq->request;
|
||||
specialRequest = imtqReq->specialRequest;
|
||||
if (state != InternalState::IDLE) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
state = InternalState::BUSY;
|
||||
}
|
||||
semaphore->release();
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t ImtqPollingTask::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
|
||||
|
||||
ReturnValue_t ImtqPollingTask::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void ImtqPollingTask::ccToReplyPtrMeasure(ImtqRepliesDefault& replies, imtq::CC::CC cc,
|
||||
uint8_t** replyBuf, size_t& replyLen) {
|
||||
replyLen = imtq::getReplySize(cc);
|
||||
switch (cc) {
|
||||
case (imtq::CC::CC::GET_ENG_HK_DATA): {
|
||||
*replyBuf = replies.engHk;
|
||||
break;
|
||||
}
|
||||
case (imtq::CC::CC::SOFTWARE_RESET): {
|
||||
*replyBuf = replies.swReset;
|
||||
break;
|
||||
}
|
||||
case (imtq::CC::CC::GET_SYSTEM_STATE): {
|
||||
*replyBuf = replies.systemState;
|
||||
break;
|
||||
}
|
||||
case (imtq::CC::CC::START_MTM_MEASUREMENT): {
|
||||
*replyBuf = replies.startMtmMeasurement;
|
||||
break;
|
||||
}
|
||||
case (imtq::CC::CC::GET_RAW_MTM_MEASUREMENT): {
|
||||
*replyBuf = replies.rawMgmMeasurement;
|
||||
break;
|
||||
}
|
||||
case (imtq::CC::CC::GET_CAL_MTM_MEASUREMENT): {
|
||||
*replyBuf = replies.calibMgmMeasurement;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
*replyBuf = replies.specialRequestReply;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImtqPollingTask::ccToReplyPtrActuate(ImtqRepliesWithTorque& replies, imtq::CC::CC cc,
|
||||
uint8_t** replyBuf, size_t& replyLen) {
|
||||
replyLen = imtq::getReplySize(cc);
|
||||
switch (cc) {
|
||||
case (imtq::CC::CC::START_ACTUATION_DIPOLE): {
|
||||
*replyBuf = replies.dipoleActuation;
|
||||
break;
|
||||
}
|
||||
case (imtq::CC::CC::GET_ENG_HK_DATA): {
|
||||
*replyBuf = replies.engHk;
|
||||
break;
|
||||
}
|
||||
case (imtq::CC::CC::START_MTM_MEASUREMENT): {
|
||||
*replyBuf = replies.startMtmMeasurement;
|
||||
break;
|
||||
}
|
||||
case (imtq::CC::CC::GET_RAW_MTM_MEASUREMENT): {
|
||||
*replyBuf = replies.rawMgmMeasurement;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
*replyBuf = nullptr;
|
||||
replyLen = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
size_t ImtqPollingTask::getExchangeBufLen(imtq::SpecialRequest specialRequest) {
|
||||
size_t baseLen = ImtqRepliesDefault::BASE_LEN;
|
||||
switch (specialRequest) {
|
||||
case (imtq::SpecialRequest::NONE):
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_POS_X):
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_NEG_X):
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_POS_Y):
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_NEG_Y):
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_POS_Z):
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_NEG_Z): {
|
||||
break;
|
||||
}
|
||||
case (imtq::SpecialRequest::GET_SELF_TEST_RESULT): {
|
||||
baseLen += imtq::replySize::SELF_TEST_RESULTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return baseLen;
|
||||
}
|
||||
|
||||
void ImtqPollingTask::buildDipoleCommand() {
|
||||
cmdBuf[0] = imtq::CC::CC::START_ACTUATION_DIPOLE;
|
||||
uint8_t* serPtr = cmdBuf.data() + 1;
|
||||
size_t serLen = 0;
|
||||
for (uint8_t idx = 0; idx < 3; idx++) {
|
||||
SerializeAdapter::serialize(&dipoles[idx], &serPtr, &serLen, cmdBuf.size(),
|
||||
SerializeIF::Endianness::LITTLE);
|
||||
}
|
||||
SerializeAdapter::serialize(&torqueDuration, &serPtr, &serLen, cmdBuf.size(),
|
||||
SerializeIF::Endianness::LITTLE);
|
||||
// sif::debug << "Dipole X: " << dipoles[0] << std::endl;
|
||||
// sif::debug << "Torqeu Dur: " << torqueDuration << std::endl;
|
||||
cmdLen = 1 + serLen;
|
||||
}
|
||||
|
||||
ReturnValue_t ImtqPollingTask::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
|
||||
size_t* size) {
|
||||
imtq::RequestType currentRequest;
|
||||
{
|
||||
MutexGuard mg(ipcLock);
|
||||
currentRequest = this->currentRequest;
|
||||
}
|
||||
|
||||
size_t replyLen = 0;
|
||||
MutexGuard mg(bufLock);
|
||||
if (currentRequest == imtq::RequestType::MEASURE_NO_ACTUATION) {
|
||||
replyLen = getExchangeBufLen(specialRequest);
|
||||
memcpy(exchangeBuf.data(), replyBuf.data(), replyLen);
|
||||
} else if (currentRequest == imtq::RequestType::ACTUATE) {
|
||||
replyLen = ImtqRepliesWithTorque::BASE_LEN;
|
||||
memcpy(exchangeBuf.data(), replyBufActuation.data(), replyLen);
|
||||
} else {
|
||||
*size = 0;
|
||||
}
|
||||
*buffer = exchangeBuf.data();
|
||||
*size = replyLen;
|
||||
return comStatus;
|
||||
}
|
||||
|
||||
void ImtqPollingTask::clearReadFlagsDefault(ImtqRepliesDefault& replies) {
|
||||
replies.calibMgmMeasurement[0] = false;
|
||||
replies.rawMgmMeasurement[0] = false;
|
||||
replies.systemState[0] = false;
|
||||
replies.specialRequestReply[0] = false;
|
||||
replies.engHk[0] = false;
|
||||
}
|
||||
|
||||
ReturnValue_t ImtqPollingTask::i2cCmdExecDefault(imtq::CC::CC cc, uint8_t* replyPtr,
|
||||
size_t replyLen, ReturnValue_t comErrIfFails) {
|
||||
ReturnValue_t res = performI2cFullRequest(replyPtr + 1, replyLen);
|
||||
if (res != returnvalue::OK) {
|
||||
sif::error << "IMTQ: I2C transaction for command 0x" << std::hex << std::setw(2) << cc
|
||||
<< " failed" << std::dec << std::endl;
|
||||
comStatus = comErrIfFails;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (replyPtr[1] != cc) {
|
||||
sif::warning << "IMTQ: Unexpected CC 0x" << std::hex << std::setw(2)
|
||||
<< static_cast<int>(replyPtr[1]) << " for command 0x" << cc << std::dec
|
||||
<< std::endl;
|
||||
comStatus = comErrIfFails;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
replyPtr[0] = true;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void ImtqPollingTask::clearReadFlagsWithTorque(ImtqRepliesWithTorque& replies) {
|
||||
replies.dipoleActuation[0] = false;
|
||||
replies.engHk[0] = false;
|
||||
replies.rawMgmMeasurement[0] = false;
|
||||
replies.startMtmMeasurement[0] = false;
|
||||
}
|
||||
|
||||
ReturnValue_t ImtqPollingTask::performI2cFullRequest(uint8_t* reply, size_t replyLen) {
|
||||
int fd = 0;
|
||||
if (cmdLen == 0 or reply == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
{
|
||||
UnixFileGuard fileHelper(i2cDev, fd, O_RDWR, "ImtqPollingTask::performI2cFullRequest");
|
||||
if (fileHelper.getOpenResult() != returnvalue::OK) {
|
||||
return fileHelper.getOpenResult();
|
||||
}
|
||||
if (ioctl(fd, I2C_SLAVE, i2cAddr) < 0) {
|
||||
sif::warning << "Opening IMTQ slave device failed with code " << errno << ": "
|
||||
<< strerror(errno) << std::endl;
|
||||
}
|
||||
|
||||
int written = write(fd, cmdBuf.data(), cmdLen);
|
||||
if (written < 0) {
|
||||
sif::error << "IMTQ: Failed to send with error code " << errno
|
||||
<< ". Error description: " << strerror(errno) << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
} else if (static_cast<size_t>(written) != cmdLen) {
|
||||
sif::error << "IMTQ: Could not write all bytes" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
#if FSFW_HAL_I2C_WIRETAPPING == 1
|
||||
sif::info << "Sent I2C data to bus " << deviceFile << ":" << std::endl;
|
||||
arrayprinter::print(sendData, sendLen);
|
||||
#endif
|
||||
|
||||
// wait 1 ms like specified in the datasheet. This is the time the IMTQ needs
|
||||
// to prepare a reply.
|
||||
usleep(1000);
|
||||
|
||||
{
|
||||
UnixFileGuard fileHelper(i2cDev, fd, O_RDWR, "ImtqPollingTask::performI2cFullRequest");
|
||||
if (fileHelper.getOpenResult() != returnvalue::OK) {
|
||||
return fileHelper.getOpenResult();
|
||||
}
|
||||
if (ioctl(fd, I2C_SLAVE, i2cAddr) < 0) {
|
||||
sif::warning << "Opening IMTQ slave device failed with code " << errno << ": "
|
||||
<< strerror(errno) << std::endl;
|
||||
}
|
||||
MutexGuard mg(bufLock);
|
||||
int readLen = read(fd, reply, replyLen);
|
||||
if (readLen != static_cast<int>(replyLen)) {
|
||||
if (readLen < 0) {
|
||||
sif::warning << "IMTQ: Reading failed with error code " << errno << " | " << strerror(errno)
|
||||
<< std::endl;
|
||||
} else {
|
||||
sif::warning << "IMTQ: Read only" << readLen << " from " << replyLen << " bytes"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reply[0] == 0xff or reply[1] == 0xff) {
|
||||
sif::warning << "IMTQ: No reply available after 1 millisecond";
|
||||
return NO_REPLY_AVAILABLE;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
71
linux/devices/ImtqPollingTask.h
Normal file
71
linux/devices/ImtqPollingTask.h
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef LINUX_DEVICES_IMTQPOLLINGTASK_H_
|
||||
#define LINUX_DEVICES_IMTQPOLLINGTASK_H_
|
||||
|
||||
#include <fsfw/tasks/SemaphoreIF.h>
|
||||
#include <fsfw_hal/linux/i2c/I2cCookie.h>
|
||||
|
||||
#include "fsfw/devicehandlers/DeviceCommunicationIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "mission/devices/devicedefinitions/imtqHelpers.h"
|
||||
|
||||
class ImtqPollingTask : public SystemObject,
|
||||
public ExecutableObjectIF,
|
||||
public DeviceCommunicationIF {
|
||||
public:
|
||||
ImtqPollingTask(object_id_t imtqPollingTask);
|
||||
|
||||
ReturnValue_t performOperation(uint8_t operationCode) override;
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
private:
|
||||
static constexpr ReturnValue_t NO_REPLY_AVAILABLE = returnvalue::makeCode(2, 0);
|
||||
|
||||
enum class InternalState { IDLE, BUSY } state = InternalState::IDLE;
|
||||
imtq::RequestType currentRequest = imtq::RequestType::MEASURE_NO_ACTUATION;
|
||||
|
||||
SemaphoreIF* semaphore;
|
||||
ReturnValue_t comStatus = returnvalue::OK;
|
||||
MutexIF* ipcLock;
|
||||
MutexIF* bufLock;
|
||||
I2cCookie* i2cCookie = nullptr;
|
||||
const char* i2cDev = nullptr;
|
||||
address_t i2cAddr = 0;
|
||||
uint32_t currentIntegrationTimeMs = 10;
|
||||
// Required in addition to integration time, otherwise old data might be read.
|
||||
static constexpr uint32_t MGM_READ_BUFFER_TIME_MS = 6;
|
||||
bool ignoreNextActuateRequest = false;
|
||||
|
||||
imtq::SpecialRequest specialRequest = imtq::SpecialRequest::NONE;
|
||||
int16_t dipoles[3] = {};
|
||||
uint16_t torqueDuration = 0;
|
||||
|
||||
std::array<uint8_t, 32> cmdBuf;
|
||||
std::array<uint8_t, 524> replyBuf;
|
||||
std::array<uint8_t, 524> replyBufActuation;
|
||||
std::array<uint8_t, 524> exchangeBuf;
|
||||
size_t cmdLen = 0;
|
||||
|
||||
// DeviceCommunicationIF overrides
|
||||
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;
|
||||
|
||||
void ccToReplyPtrMeasure(ImtqRepliesDefault& replies, imtq::CC::CC cc, uint8_t** replyBuf,
|
||||
size_t& replyLen);
|
||||
void ccToReplyPtrActuate(ImtqRepliesWithTorque& replies, imtq::CC::CC cc, uint8_t** replyBuf,
|
||||
size_t& replyLen);
|
||||
void clearReadFlagsDefault(ImtqRepliesDefault& replies);
|
||||
void clearReadFlagsWithTorque(ImtqRepliesWithTorque& replies);
|
||||
size_t getExchangeBufLen(imtq::SpecialRequest specialRequest);
|
||||
void buildDipoleCommand();
|
||||
void handleMeasureStep();
|
||||
void handleActuateStep();
|
||||
ReturnValue_t i2cCmdExecDefault(imtq::CC::CC cc, uint8_t* replyPtr, size_t replyLen,
|
||||
ReturnValue_t comErrIfFails);
|
||||
ReturnValue_t performI2cFullRequest(uint8_t* reply, size_t replyLen);
|
||||
};
|
||||
|
||||
#endif /* LINUX_DEVICES_IMTQPOLLINGTASK_H_ */
|
473
linux/devices/Max31865RtdPolling.cpp
Normal file
473
linux/devices/Max31865RtdPolling.cpp
Normal file
@ -0,0 +1,473 @@
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
#include <fsfw_hal/linux/spi/ManualCsLockGuard.h>
|
||||
#include <linux/devices/Max31865RtdPolling.h>
|
||||
|
||||
#define OBSW_RTD_AUTO_MODE 1
|
||||
|
||||
#if OBSW_RTD_AUTO_MODE == 1
|
||||
static constexpr uint8_t BASE_CFG = (MAX31865::Bias::ON << MAX31865::CfgBitPos::BIAS_SEL) |
|
||||
(MAX31865::Wires::FOUR_WIRE << MAX31865::CfgBitPos::WIRE_SEL) |
|
||||
(MAX31865::ConvMode::AUTO << MAX31865::CfgBitPos::CONV_MODE);
|
||||
#else
|
||||
static constexpr uint8_t BASE_CFG =
|
||||
(MAX31865::Bias::OFF << MAX31865::CfgBitPos::BIAS_SEL) |
|
||||
(MAX31865::Wires::FOUR_WIRE << MAX31865::CfgBitPos::WIRE_SEL) |
|
||||
(MAX31865::ConvMode::NORM_OFF << MAX31865::CfgBitPos::CONV_MODE);
|
||||
#endif
|
||||
|
||||
Max31865RtdPolling::Max31865RtdPolling(object_id_t objectId, SpiComIF* lowLevelComIF,
|
||||
GpioIF* gpioIF)
|
||||
: SystemObject(objectId), rtds(EiveMax31855::NUM_RTDS), comIF(lowLevelComIF), gpioIF(gpioIF) {
|
||||
readerLock = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::performOperation(uint8_t operationCode) {
|
||||
using namespace MAX31865;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
static_cast<void>(result);
|
||||
// Measured to take 0-1 ms in debug build
|
||||
// Stopwatch watch;
|
||||
periodicInitHandling();
|
||||
#if OBSW_RTD_AUTO_MODE == 0
|
||||
// 10 ms delay for VBIAS startup
|
||||
TaskFactory::delayTask(10);
|
||||
result = periodicReadReqHandling();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
// After requesting, 65 milliseconds delay required
|
||||
TaskFactory::delayTask(65);
|
||||
#endif
|
||||
|
||||
return periodicReadHandling();
|
||||
}
|
||||
|
||||
bool Max31865RtdPolling::rtdIsActive(uint8_t idx) {
|
||||
if (rtds[idx]->on and rtds[idx]->db.active and rtds[idx]->db.configured) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::periodicInitHandling() {
|
||||
using namespace MAX31865;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
for (auto& rtd : rtds) {
|
||||
if (rtd == nullptr) {
|
||||
continue;
|
||||
}
|
||||
bool mustPerformInitHandling = false;
|
||||
bool doWriteLowThreshold = false;
|
||||
bool doWriteHighThreshold = false;
|
||||
{
|
||||
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
if (mg.getLockResult() != returnvalue::OK) {
|
||||
sif::warning << "Max31865RtdReader::periodicInitHandling: Mutex lock failed" << std::endl;
|
||||
continue;
|
||||
}
|
||||
mustPerformInitHandling =
|
||||
(rtd->on or rtd->db.active) and not rtd->db.configured and rtd->cd.hasTimedOut();
|
||||
doWriteHighThreshold = rtd->writeHighThreshold;
|
||||
doWriteLowThreshold = rtd->writeLowThreshold;
|
||||
}
|
||||
if (mustPerformInitHandling) {
|
||||
// Please note that using the manual CS lock wrapper here is problematic. Might be a SPI
|
||||
// or hardware specific issue where the CS needs to be pulled high and then low again
|
||||
// between transfers
|
||||
result = writeCfgReg(rtd->spiCookie, BASE_CFG);
|
||||
if (result != returnvalue::OK) {
|
||||
handleSpiError(rtd, result, "writeCfgReg");
|
||||
continue;
|
||||
}
|
||||
if (doWriteLowThreshold) {
|
||||
result = writeLowThreshold(rtd->spiCookie, rtd->lowThreshold);
|
||||
if (result != returnvalue::OK) {
|
||||
handleSpiError(rtd, result, "writeLowThreshold");
|
||||
}
|
||||
}
|
||||
if (doWriteHighThreshold) {
|
||||
result = writeHighThreshold(rtd->spiCookie, rtd->highThreshold);
|
||||
if (result != returnvalue::OK) {
|
||||
handleSpiError(rtd, result, "writeHighThreshold");
|
||||
}
|
||||
}
|
||||
result = clearFaultStatus(rtd->spiCookie);
|
||||
if (result != returnvalue::OK) {
|
||||
handleSpiError(rtd, result, "clearFaultStatus");
|
||||
}
|
||||
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
rtd->db.configured = true;
|
||||
rtd->db.active = true;
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::periodicReadReqHandling() {
|
||||
using namespace MAX31865;
|
||||
updateActiveRtdsArray();
|
||||
// Now request one shot config for all active RTDs
|
||||
for (auto& rtd : rtds) {
|
||||
if (rtd == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (activeRtdsArray[rtd->idx]) {
|
||||
ReturnValue_t result = writeCfgReg(rtd->spiCookie, BASE_CFG | (1 << CfgBitPos::ONE_SHOT));
|
||||
if (result != returnvalue::OK) {
|
||||
handleSpiError(rtd, result, "writeCfgReg");
|
||||
// Release mutex ASAP
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::periodicReadHandling() {
|
||||
using namespace MAX31865;
|
||||
auto result = returnvalue::OK;
|
||||
updateActiveRtdsArray();
|
||||
// Now read the RTD values
|
||||
for (auto& rtd : rtds) {
|
||||
if (rtd == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (activeRtdsArray[rtd->idx]) {
|
||||
// Please note that using the manual CS lock wrapper here is problematic. Might be a SPI
|
||||
// or hardware specific issue where the CS needs to be pulled high and then low again
|
||||
// between transfers
|
||||
uint16_t rtdVal = 0;
|
||||
bool faultBitSet = false;
|
||||
result = writeCfgReg(rtd->spiCookie, BASE_CFG);
|
||||
if (result != returnvalue::OK) {
|
||||
handleSpiError(rtd, result, "writeCfgReg");
|
||||
continue;
|
||||
}
|
||||
result = readRtdVal(rtd->spiCookie, rtdVal, faultBitSet);
|
||||
// sif::debug << "RTD Val: " << rtdVal << std::endl;
|
||||
if (result != returnvalue::OK) {
|
||||
handleSpiError(rtd, result, "readRtdVal");
|
||||
continue;
|
||||
}
|
||||
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
if (faultBitSet) {
|
||||
rtd->db.faultBitSet = faultBitSet;
|
||||
}
|
||||
rtd->db.adcCode = rtdVal;
|
||||
}
|
||||
}
|
||||
#if OBSW_RTD_AUTO_MODE == 0
|
||||
for (auto& rtd : rtds) {
|
||||
if (rtd == nullptr) {
|
||||
continue;
|
||||
}
|
||||
// Even if a device was made inactive, turn off the bias here. If it was turned off, not
|
||||
// necessary anymore..
|
||||
if (rtd->on) {
|
||||
result = writeBiasSel(Bias::OFF, rtd->spiCookie, BASE_CFG);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::initializeInterface(CookieIF* cookie) {
|
||||
if (cookie == nullptr) {
|
||||
throw std::invalid_argument("Invalid MAX31865 Reader Cookie");
|
||||
}
|
||||
auto* rtdCookie = dynamic_cast<Max31865ReaderCookie*>(cookie);
|
||||
ReturnValue_t result = comIF->initializeInterface(rtdCookie->spiCookie);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (rtdCookie->idx > EiveMax31855::NUM_RTDS) {
|
||||
throw std::invalid_argument("Invalid RTD index");
|
||||
}
|
||||
rtds[rtdCookie->idx] = rtdCookie;
|
||||
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
if (dbLen == 0) {
|
||||
dbLen = rtdCookie->db.getSerializedSize();
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::sendMessage(CookieIF* cookie, const uint8_t* sendData,
|
||||
size_t sendLen) {
|
||||
if (cookie == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
auto* rtdCookie = dynamic_cast<Max31865ReaderCookie*>(cookie);
|
||||
if (rtdCookie == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
// Empty command.. don't fail for now
|
||||
if (sendLen < 1) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
if (mg.getLockResult() != returnvalue::OK) {
|
||||
sif::warning << "Max31865RtdReader::sendMessage: Mutex lock failed" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
uint8_t cmdRaw = sendData[0];
|
||||
if (cmdRaw > EiveMax31855::RtdCommands::NUM_CMDS) {
|
||||
sif::warning << "Max31865RtdReader::sendMessage: Invalid command" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
auto thresholdHandler = [&]() {
|
||||
rtdCookie->lowThreshold = (sendData[1] << 8) | sendData[2];
|
||||
rtdCookie->highThreshold = (sendData[3] << 8) | sendData[4];
|
||||
rtdCookie->writeLowThreshold = true;
|
||||
rtdCookie->writeHighThreshold = true;
|
||||
};
|
||||
|
||||
auto cmd = static_cast<EiveMax31855::RtdCommands>(sendData[0]);
|
||||
switch (cmd) {
|
||||
case (EiveMax31855::RtdCommands::ON): {
|
||||
if (not rtdCookie->on) {
|
||||
rtdCookie->cd.setTimeout(MAX31865::WARMUP_MS);
|
||||
rtdCookie->on = true;
|
||||
rtdCookie->db.active = false;
|
||||
rtdCookie->db.configured = false;
|
||||
if (sendLen == 5) {
|
||||
thresholdHandler();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (EiveMax31855::RtdCommands::ACTIVE): {
|
||||
if (not rtdCookie->on) {
|
||||
rtdCookie->cd.setTimeout(MAX31865::WARMUP_MS);
|
||||
rtdCookie->on = true;
|
||||
rtdCookie->db.active = true;
|
||||
rtdCookie->db.configured = false;
|
||||
} else {
|
||||
rtdCookie->db.active = true;
|
||||
}
|
||||
if (sendLen == 5) {
|
||||
thresholdHandler();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (EiveMax31855::RtdCommands::OFF): {
|
||||
rtdCookie->on = false;
|
||||
rtdCookie->db.active = false;
|
||||
rtdCookie->db.configured = false;
|
||||
break;
|
||||
}
|
||||
case (EiveMax31855::RtdCommands::HIGH_TRESHOLD): {
|
||||
if (sendLen == 3) {
|
||||
rtdCookie->highThreshold = (sendData[1] << 8) | sendData[2];
|
||||
rtdCookie->writeHighThreshold = true;
|
||||
} else {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (EiveMax31855::RtdCommands::LOW_THRESHOLD): {
|
||||
if (sendLen == 3) {
|
||||
rtdCookie->lowThreshold = (sendData[1] << 8) | sendData[2];
|
||||
rtdCookie->writeLowThreshold = true;
|
||||
} else {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (EiveMax31855::RtdCommands::CFG): {
|
||||
ReturnValue_t result = writeCfgReg(rtdCookie->spiCookie, BASE_CFG);
|
||||
if (result != returnvalue::OK) {
|
||||
handleSpiError(rtdCookie, result, "writeCfgReg");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// TODO: Only implement if needed
|
||||
break;
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
|
||||
size_t* size) {
|
||||
auto* rtdCookie = dynamic_cast<Max31865ReaderCookie*>(cookie);
|
||||
if (rtdCookie == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
if (mg.getLockResult() != returnvalue::OK) {
|
||||
// TODO: Emit warning
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
uint8_t* exchangePtr = rtdCookie->exchangeBuf.data();
|
||||
size_t serLen = 0;
|
||||
auto result = rtdCookie->db.serialize(&exchangePtr, &serLen, rtdCookie->exchangeBuf.size(),
|
||||
SerializeIF::Endianness::MACHINE);
|
||||
if (result != returnvalue::OK) {
|
||||
// TODO: Emit warning
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
*buffer = reinterpret_cast<uint8_t*>(rtdCookie->exchangeBuf.data());
|
||||
*size = serLen;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::writeCfgReg(SpiCookie* cookie, uint8_t cfg) {
|
||||
using namespace MAX31865;
|
||||
return writeNToReg(cookie, CONFIG, 1, &cfg, nullptr);
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::writeBiasSel(MAX31865::Bias bias, SpiCookie* cookie,
|
||||
uint8_t baseCfg) {
|
||||
using namespace MAX31865;
|
||||
if (bias == MAX31865::Bias::OFF) {
|
||||
baseCfg &= ~(1 << CfgBitPos::BIAS_SEL);
|
||||
} else {
|
||||
baseCfg |= (1 << CfgBitPos::BIAS_SEL);
|
||||
}
|
||||
return writeCfgReg(cookie, baseCfg);
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::clearFaultStatus(SpiCookie* cookie) {
|
||||
using namespace MAX31865;
|
||||
// Read back the current configuration to avoid overwriting it when clearing te fault status
|
||||
uint8_t currentCfg = 0;
|
||||
auto result = readCfgReg(cookie, currentCfg);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
// Clear bytes 5, 3 and 2 which need to be 0
|
||||
currentCfg &= ~0x2C;
|
||||
currentCfg |= (1 << CfgBitPos::FAULT_STATUS_CLEAR);
|
||||
return writeCfgReg(cookie, currentCfg);
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::readCfgReg(SpiCookie* cookie, uint8_t& cfg) {
|
||||
using namespace MAX31865;
|
||||
uint8_t* replyPtr = nullptr;
|
||||
auto result = readNFromReg(cookie, CONFIG, 1, &replyPtr);
|
||||
if (result == returnvalue::OK) {
|
||||
cfg = replyPtr[0];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::writeLowThreshold(SpiCookie* cookie, uint16_t val) {
|
||||
using namespace MAX31865;
|
||||
uint8_t cmd[2] = {static_cast<uint8_t>((val >> 8) & 0xff), static_cast<uint8_t>(val & 0xff)};
|
||||
return writeNToReg(cookie, LOW_THRESHOLD, 2, cmd, nullptr);
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::writeHighThreshold(SpiCookie* cookie, uint16_t val) {
|
||||
using namespace MAX31865;
|
||||
uint8_t cmd[2] = {static_cast<uint8_t>((val >> 8) & 0xff), static_cast<uint8_t>(val & 0xff)};
|
||||
return writeNToReg(cookie, HIGH_THRESHOLD, 2, cmd, nullptr);
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::readLowThreshold(SpiCookie* cookie, uint16_t& lowThreshold) {
|
||||
using namespace MAX31865;
|
||||
uint8_t* replyPtr = nullptr;
|
||||
auto result = readNFromReg(cookie, LOW_THRESHOLD, 2, &replyPtr);
|
||||
if (result == returnvalue::OK) {
|
||||
lowThreshold = (replyPtr[0] << 8) | replyPtr[1];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::readHighThreshold(SpiCookie* cookie, uint16_t& highThreshold) {
|
||||
using namespace MAX31865;
|
||||
uint8_t* replyPtr = nullptr;
|
||||
auto result = readNFromReg(cookie, HIGH_THRESHOLD, 2, &replyPtr);
|
||||
if (result == returnvalue::OK) {
|
||||
highThreshold = (replyPtr[0] << 8) | replyPtr[1];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::writeNToReg(SpiCookie* cookie, uint8_t reg, size_t n,
|
||||
uint8_t* cmd, uint8_t** reply) {
|
||||
using namespace MAX31865;
|
||||
if (n > cmdBuf.size() - 1) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
cmdBuf[0] = reg | WRITE_BIT;
|
||||
for (size_t idx = 0; idx < n; idx++) {
|
||||
cmdBuf[idx + 1] = cmd[idx];
|
||||
}
|
||||
return comIF->sendMessage(cookie, cmdBuf.data(), n + 1);
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::readRtdVal(SpiCookie* cookie, uint16_t& val, bool& faultBitSet) {
|
||||
using namespace MAX31865;
|
||||
uint8_t* replyPtr = nullptr;
|
||||
auto result = readNFromReg(cookie, RTD, 2, &replyPtr);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (replyPtr[1] & 0b0000'0001) {
|
||||
faultBitSet = true;
|
||||
}
|
||||
// Shift 1 to the right to remove fault bit
|
||||
val = ((replyPtr[0] << 8) | replyPtr[1]) >> 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::readNFromReg(SpiCookie* cookie, uint8_t reg, size_t n,
|
||||
uint8_t** reply) {
|
||||
using namespace MAX31865;
|
||||
if (n > 4) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
// Clear write bit in any case
|
||||
reg &= ~WRITE_BIT;
|
||||
cmdBuf[0] = reg;
|
||||
std::memset(cmdBuf.data() + 1, 0, n);
|
||||
ReturnValue_t result = comIF->sendMessage(cookie, cmdBuf.data(), n + 1);
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
size_t dummyLen = 0;
|
||||
uint8_t* replyPtr = nullptr;
|
||||
result = comIF->readReceivedMessage(cookie, &replyPtr, &dummyLen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (reply != nullptr) {
|
||||
*reply = replyPtr + 1;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::updateActiveRtdsArray() {
|
||||
MutexGuard mg(readerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
if (mg.getLockResult() != returnvalue::OK) {
|
||||
sif::warning << "Max31865RtdReader::periodicReadHandling: Mutex lock failed" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
for (const auto& rtd : rtds) {
|
||||
activeRtdsArray[rtd->idx] = rtdIsActive(rtd->idx);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::handleSpiError(Max31865ReaderCookie* cookie, ReturnValue_t result,
|
||||
const char* ctx) {
|
||||
cookie->db.spiErrorCount.value += 1;
|
||||
sif::warning << "Max31865RtdReader::handleSpiError: " << ctx << " | Failed with result " << result
|
||||
<< std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t Max31865RtdPolling::initialize() {
|
||||
csLock = comIF->getCsMutex();
|
||||
return SystemObject::initialize();
|
||||
}
|
93
linux/devices/Max31865RtdPolling.h
Normal file
93
linux/devices/Max31865RtdPolling.h
Normal file
@ -0,0 +1,93 @@
|
||||
#ifndef LINUX_DEVICES_MAX31865RTDREADER_H_
|
||||
#define LINUX_DEVICES_MAX31865RTDREADER_H_
|
||||
|
||||
#include <fsfw/ipc/MutexIF.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/timemanager/clockDefinitions.h>
|
||||
#include <fsfw_hal/linux/spi/SpiComIF.h>
|
||||
#include <fsfw_hal/linux/spi/SpiCookie.h>
|
||||
|
||||
#include "devConf.h"
|
||||
#include "fsfw/devicehandlers/DeviceCommunicationIF.h"
|
||||
#include "mission/devices/devicedefinitions/Max31865Definitions.h"
|
||||
|
||||
struct Max31865ReaderCookie : public CookieIF {
|
||||
Max31865ReaderCookie(){};
|
||||
Max31865ReaderCookie(object_id_t handlerId_, uint8_t idx_, const std::string& locString_,
|
||||
SpiCookie* spiCookie_)
|
||||
: idx(idx_), handlerId(handlerId_), locString(locString_), spiCookie(spiCookie_) {}
|
||||
|
||||
uint8_t idx = 0;
|
||||
object_id_t handlerId = objects::NO_OBJECT;
|
||||
|
||||
std::string locString = "";
|
||||
std::array<uint8_t, 12> exchangeBuf{};
|
||||
Countdown cd = Countdown(MAX31865::WARMUP_MS);
|
||||
|
||||
bool on = false;
|
||||
bool writeLowThreshold = false;
|
||||
bool writeHighThreshold = false;
|
||||
uint16_t lowThreshold = 0;
|
||||
uint16_t highThreshold = 0;
|
||||
SpiCookie* spiCookie = nullptr;
|
||||
|
||||
// Exchange data buffer struct
|
||||
EiveMax31855::ReadOutStruct db;
|
||||
};
|
||||
|
||||
class Max31865RtdPolling : public SystemObject,
|
||||
public ExecutableObjectIF,
|
||||
public DeviceCommunicationIF {
|
||||
public:
|
||||
Max31865RtdPolling(object_id_t objectId, SpiComIF* lowLevelComIF, GpioIF* gpioIF);
|
||||
|
||||
ReturnValue_t performOperation(uint8_t operationCode) override;
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
private:
|
||||
std::vector<Max31865ReaderCookie*> rtds;
|
||||
std::array<uint8_t, 4> cmdBuf = {};
|
||||
std::array<bool, 12> activeRtdsArray{};
|
||||
size_t dbLen = 0;
|
||||
MutexIF* readerLock;
|
||||
static constexpr MutexIF::TimeoutType LOCK_TYPE = MutexIF::TimeoutType::WAITING;
|
||||
static constexpr uint32_t LOCK_TIMEOUT = 20;
|
||||
static constexpr char LOCK_CTX[] = "Max31865RtdPolling";
|
||||
|
||||
SpiComIF* comIF;
|
||||
GpioIF* gpioIF;
|
||||
MutexIF::TimeoutType csTimeoutType = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t csTimeoutMs = spi::RTD_CS_TIMEOUT;
|
||||
MutexIF* csLock = nullptr;
|
||||
|
||||
ReturnValue_t periodicInitHandling();
|
||||
ReturnValue_t periodicReadReqHandling();
|
||||
ReturnValue_t periodicReadHandling();
|
||||
|
||||
bool rtdIsActive(uint8_t idx);
|
||||
ReturnValue_t writeCfgReg(SpiCookie* cookie, uint8_t cfg);
|
||||
ReturnValue_t writeBiasSel(MAX31865::Bias bias, SpiCookie* cookie, uint8_t baseCfg);
|
||||
ReturnValue_t readCfgReg(SpiCookie* cookie, uint8_t& cfg);
|
||||
ReturnValue_t readRtdVal(SpiCookie* cookie, uint16_t& val, bool& faultBitSet);
|
||||
ReturnValue_t writeLowThreshold(SpiCookie* cookie, uint16_t val);
|
||||
ReturnValue_t writeHighThreshold(SpiCookie* cookie, uint16_t val);
|
||||
ReturnValue_t readLowThreshold(SpiCookie* cookie, uint16_t& val);
|
||||
ReturnValue_t readHighThreshold(SpiCookie* cookie, uint16_t& val);
|
||||
ReturnValue_t clearFaultStatus(SpiCookie* cookie);
|
||||
|
||||
ReturnValue_t readNFromReg(SpiCookie* cookie, uint8_t reg, size_t n, uint8_t** reply);
|
||||
ReturnValue_t writeNToReg(SpiCookie* cookie, uint8_t reg, size_t n, uint8_t* cmd,
|
||||
uint8_t** reply);
|
||||
|
||||
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;
|
||||
|
||||
ReturnValue_t updateActiveRtdsArray();
|
||||
|
||||
ReturnValue_t handleSpiError(Max31865ReaderCookie* cookie, ReturnValue_t result, const char* ctx);
|
||||
};
|
||||
|
||||
#endif /* LINUX_DEVICES_MAX31865RTDREADER_H_ */
|
542
linux/devices/RwPollingTask.cpp
Normal file
542
linux/devices/RwPollingTask.cpp
Normal file
@ -0,0 +1,542 @@
|
||||
#include "RwPollingTask.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <fsfw/globalfunctions/CRC.h>
|
||||
#include <fsfw/tasks/SemaphoreFactory.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
#include <fsfw_hal/common/spi/spiCommon.h>
|
||||
#include <fsfw_hal/linux/utility.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "devConf.h"
|
||||
#include "mission/devices/devicedefinitions/rwHelpers.h"
|
||||
|
||||
RwPollingTask::RwPollingTask(object_id_t objectId, const char* spiDev, GpioIF& gpioIF)
|
||||
: SystemObject(objectId), spiDev(spiDev), gpioIF(gpioIF) {
|
||||
semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
|
||||
semaphore->acquire();
|
||||
ipcLock = MutexFactory::instance()->createMutex();
|
||||
spiLock = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::performOperation(uint8_t operationCode) {
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
if (rwCookies[i] == nullptr) {
|
||||
sif::error << "Invalid RW cookie at index" << i << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
ipcLock->lockMutex();
|
||||
state = InternalState::IDLE;
|
||||
ipcLock->unlockMutex();
|
||||
semaphore->acquire();
|
||||
// This loop takes 50 ms on a debug build.
|
||||
// Stopwatch watch;
|
||||
TaskFactory::delayTask(5);
|
||||
int fd = 0;
|
||||
for (auto& skip : skipCommandingForRw) {
|
||||
skip = false;
|
||||
}
|
||||
setAllReadFlagsFalse();
|
||||
ReturnValue_t result = openSpi(O_RDWR, fd);
|
||||
if (result != returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
|
||||
if (rwCookies[idx]->specialRequest == rws::SpecialRwRequest::RESET_MCU) {
|
||||
prepareSimpleCommand(rws::RESET_MCU);
|
||||
// No point in commanding that specific RW for the cycle.
|
||||
skipCommandingForRw[idx] = true;
|
||||
writeOneRwCmd(idx, fd);
|
||||
} else if (rwCookies[idx]->setSpeed) {
|
||||
prepareSetSpeedCmd(idx);
|
||||
if (writeOneRwCmd(idx, fd) != returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
closeSpi(fd);
|
||||
if (readAllRws(rws::SET_SPEED) != returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
prepareSimpleCommand(rws::GET_LAST_RESET_STATUS);
|
||||
if (writeAndReadAllRws(rws::GET_LAST_RESET_STATUS) != returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
prepareSimpleCommand(rws::GET_RW_STATUS);
|
||||
if (writeAndReadAllRws(rws::GET_RW_STATUS) != returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
prepareSimpleCommand(rws::GET_TEMPERATURE);
|
||||
if (writeAndReadAllRws(rws::GET_TEMPERATURE) != returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
prepareSimpleCommand(rws::CLEAR_LAST_RESET_STATUS);
|
||||
if (writeAndReadAllRws(rws::CLEAR_LAST_RESET_STATUS) != returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
handleSpecialRequests();
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::initialize() { return returnvalue::OK; }
|
||||
|
||||
ReturnValue_t RwPollingTask::initializeInterface(CookieIF* cookie) {
|
||||
// We don't need to set the speed because a SPI core is used, but the mode has to be set once
|
||||
// correctly for all RWs
|
||||
if (not modeAndSpeedWasSet) {
|
||||
int fd = open(spiDev, O_RDWR);
|
||||
if (fd < 0) {
|
||||
sif::error << "could not open RW SPI bus" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
spi::SpiModes mode = spi::RW_MODE;
|
||||
int retval = ioctl(fd, SPI_IOC_WR_MODE, reinterpret_cast<uint8_t*>(&mode));
|
||||
if (retval != 0) {
|
||||
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI mode failed");
|
||||
}
|
||||
|
||||
retval = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi::RW_SPEED);
|
||||
if (retval != 0) {
|
||||
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI speed failed");
|
||||
}
|
||||
close(fd);
|
||||
modeAndSpeedWasSet = true;
|
||||
}
|
||||
|
||||
auto* rwCookie = dynamic_cast<RwCookie*>(cookie);
|
||||
if (rwCookie == nullptr) {
|
||||
sif::error << "RwPollingTask::initializeInterface: Wrong cookie" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
rwCookies[rwCookie->rwIdx] = rwCookie;
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::sendMessage(CookieIF* cookie, const uint8_t* sendData,
|
||||
size_t sendLen) {
|
||||
if (sendData == nullptr or sendLen < 8) {
|
||||
return DeviceHandlerIF::INVALID_DATA;
|
||||
}
|
||||
int32_t speed = 0;
|
||||
uint16_t rampTime = 0;
|
||||
const uint8_t* currentBuf = sendData;
|
||||
bool setSpeed = currentBuf[0];
|
||||
currentBuf += 1;
|
||||
sendLen -= 1;
|
||||
SerializeAdapter::deSerialize(&speed, ¤tBuf, &sendLen, SerializeIF::Endianness::MACHINE);
|
||||
SerializeAdapter::deSerialize(&rampTime, ¤tBuf, &sendLen, SerializeIF::Endianness::MACHINE);
|
||||
rws::SpecialRwRequest specialRequest = rws::SpecialRwRequest::REQUEST_NONE;
|
||||
if (sendLen == 8 and sendData[7] < static_cast<uint8_t>(rws::SpecialRwRequest::NUM_REQUESTS)) {
|
||||
specialRequest = static_cast<rws::SpecialRwRequest>(sendData[7]);
|
||||
}
|
||||
RwCookie* rwCookie = dynamic_cast<RwCookie*>(cookie);
|
||||
if (rwCookie == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
{
|
||||
MutexGuard mg(ipcLock);
|
||||
rwCookie->setSpeed = setSpeed;
|
||||
rwCookie->currentRwSpeed = speed;
|
||||
rwCookie->currentRampTime = rampTime;
|
||||
rwCookie->specialRequest = specialRequest;
|
||||
if (state == InternalState::IDLE) {
|
||||
state = InternalState::BUSY;
|
||||
semaphore->release();
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
|
||||
|
||||
ReturnValue_t RwPollingTask::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
|
||||
RwCookie* rwCookie = dynamic_cast<RwCookie*>(cookie);
|
||||
if (rwCookie == nullptr or rwCookie->bufLock == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
{
|
||||
MutexGuard mg(rwCookie->bufLock);
|
||||
memcpy(rwCookie->exchangeBuf.data(), rwCookie->replyBuf.data(), rwCookie->replyBuf.size());
|
||||
}
|
||||
*buffer = rwCookie->exchangeBuf.data();
|
||||
*size = rwCookie->exchangeBuf.size();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::writeAndReadAllRws(DeviceCommandId_t id) {
|
||||
// Stopwatch watch;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
int fd = 0;
|
||||
result = openSpi(O_RDWR, fd);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
|
||||
if (skipCommandingForRw[idx]) {
|
||||
continue;
|
||||
}
|
||||
result = sendOneMessage(fd, *rwCookies[idx]);
|
||||
if (result != returnvalue::OK) {
|
||||
closeSpi(fd);
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
closeSpi(fd);
|
||||
return readAllRws(id);
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::openSpi(int flags, int& fd) {
|
||||
fd = open(spiDev, flags);
|
||||
if (fd < 0) {
|
||||
sif::error << "RwPollingTask::openSpi: Failed to open device file" << std::endl;
|
||||
return SpiComIF::OPENING_FILE_FAILED;
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::readNextReply(RwCookie& rwCookie, uint8_t* replyBuf,
|
||||
size_t maxReplyLen) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
int fd = 0;
|
||||
gpioId_t gpioId = rwCookie.getChipSelectPin();
|
||||
uint8_t byteRead = 0;
|
||||
result = openSpi(O_RDWR, fd);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
pullCsLow(gpioId, gpioIF);
|
||||
bool lastByteWasFrameMarker = false;
|
||||
Countdown cd(2000);
|
||||
size_t readIdx = 0;
|
||||
|
||||
while (true) {
|
||||
lastByteWasFrameMarker = false;
|
||||
if (read(fd, &byteRead, 1) != 1) {
|
||||
sif::error << "RwPollingTask: Read failed. " << strerror(errno) << std::endl;
|
||||
pullCsHigh(gpioId, gpioIF);
|
||||
closeSpi(fd);
|
||||
return rws::SPI_READ_FAILURE;
|
||||
}
|
||||
if (byteRead == rws::FRAME_DELIMITER) {
|
||||
lastByteWasFrameMarker = true;
|
||||
}
|
||||
// Start of frame detected.
|
||||
if (byteRead != rws::FRAME_DELIMITER and not lastByteWasFrameMarker) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (readIdx % 100 == 0 && cd.hasTimedOut()) {
|
||||
pullCsHigh(gpioId, gpioIF);
|
||||
closeSpi(fd);
|
||||
return rws::SPI_READ_FAILURE;
|
||||
}
|
||||
readIdx++;
|
||||
}
|
||||
|
||||
#if FSFW_HAL_SPI_WIRETAPPING == 1
|
||||
sif::info << "RW start marker detected" << std::endl;
|
||||
#endif
|
||||
|
||||
size_t decodedFrameLen = 0;
|
||||
MutexGuard mg(rwCookie.bufLock);
|
||||
|
||||
while (decodedFrameLen < maxReplyLen) {
|
||||
// First byte already read in
|
||||
if (decodedFrameLen != 0) {
|
||||
byteRead = 0;
|
||||
if (read(fd, &byteRead, 1) != 1) {
|
||||
sif::error << "RwPollingTask: Read failed" << std::endl;
|
||||
result = rws::SPI_READ_FAILURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (byteRead == rws::FRAME_DELIMITER) {
|
||||
// Reached end of frame
|
||||
break;
|
||||
} else if (byteRead == 0x7D) {
|
||||
if (read(fd, &byteRead, 1) != 1) {
|
||||
sif::error << "RwPollingTask: Read failed" << std::endl;
|
||||
result = rws::SPI_READ_FAILURE;
|
||||
break;
|
||||
}
|
||||
if (byteRead == 0x5E) {
|
||||
*(replyBuf + decodedFrameLen) = 0x7E;
|
||||
decodedFrameLen++;
|
||||
continue;
|
||||
} else if (byteRead == 0x5D) {
|
||||
*(replyBuf + decodedFrameLen) = 0x7D;
|
||||
decodedFrameLen++;
|
||||
continue;
|
||||
} else {
|
||||
sif::error << "RwPollingTask: Invalid substitute" << std::endl;
|
||||
result = rws::INVALID_SUBSTITUTE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
*(replyBuf + decodedFrameLen) = byteRead;
|
||||
decodedFrameLen++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check end marker.
|
||||
/**
|
||||
* There might be the unlikely case that each byte in a get-telemetry reply has been
|
||||
* replaced by its substitute. Then the next byte must correspond to the end sign 0x7E.
|
||||
* Otherwise there might be something wrong.
|
||||
*/
|
||||
if (decodedFrameLen == maxReplyLen) {
|
||||
if (read(fd, &byteRead, 1) != 1) {
|
||||
sif::error << "rwSpiCallback::spiCallback: Failed to read last byte" << std::endl;
|
||||
result = rws::SPI_READ_FAILURE;
|
||||
break;
|
||||
}
|
||||
if (byteRead != rws::FRAME_DELIMITER) {
|
||||
sif::error << "rwSpiCallback::spiCallback: Missing end sign "
|
||||
<< static_cast<int>(rws::FRAME_DELIMITER) << std::endl;
|
||||
decodedFrameLen--;
|
||||
result = rws::MISSING_END_SIGN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = returnvalue::OK;
|
||||
}
|
||||
|
||||
pullCsHigh(gpioId, gpioIF);
|
||||
closeSpi(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::writeOneRwCmd(uint8_t rwIdx, int fd) {
|
||||
ReturnValue_t result = sendOneMessage(fd, *rwCookies[rwIdx]);
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::readAllRws(DeviceCommandId_t id) {
|
||||
// SPI dev will be opened in readNextReply on demand.
|
||||
for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
|
||||
if (((id == rws::SET_SPEED) and !rwCookies[idx]->setSpeed) or skipCommandingForRw[idx]) {
|
||||
continue;
|
||||
}
|
||||
uint8_t* replyBuf;
|
||||
size_t maxReadLen = idAndIdxToReadBuffer(id, idx, &replyBuf);
|
||||
ReturnValue_t result = readNextReply(*rwCookies[idx], replyBuf + 1, maxReadLen);
|
||||
if (result == returnvalue::OK) {
|
||||
// The first byte is always a flag which shows whether the value was read
|
||||
// properly at least once.
|
||||
replyBuf[0] = true;
|
||||
}
|
||||
}
|
||||
// SPI is closed in readNextReply as well.
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
size_t RwPollingTask::idAndIdxToReadBuffer(DeviceCommandId_t id, uint8_t rwIdx, uint8_t** ptr) {
|
||||
uint8_t* rawStart = rwCookies[rwIdx]->replyBuf.data();
|
||||
RwReplies replies(rawStart);
|
||||
switch (id) {
|
||||
case (rws::GET_RW_STATUS): {
|
||||
*ptr = replies.rwStatusReply;
|
||||
break;
|
||||
}
|
||||
case (rws::SET_SPEED): {
|
||||
*ptr = replies.setSpeedReply;
|
||||
break;
|
||||
}
|
||||
case (rws::CLEAR_LAST_RESET_STATUS): {
|
||||
*ptr = replies.clearLastResetStatusReply;
|
||||
break;
|
||||
}
|
||||
case (rws::GET_LAST_RESET_STATUS): {
|
||||
*ptr = replies.getLastResetStatusReply;
|
||||
break;
|
||||
}
|
||||
case (rws::GET_TEMPERATURE): {
|
||||
*ptr = replies.readTemperatureReply;
|
||||
break;
|
||||
}
|
||||
case (rws::GET_TM): {
|
||||
*ptr = replies.hkDataReply;
|
||||
break;
|
||||
}
|
||||
case (rws::INIT_RW_CONTROLLER): {
|
||||
*ptr = replies.initRwControllerReply;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sif::error << "no reply buffer for rw command " << id << std::endl;
|
||||
*ptr = replies.dummyPointer;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return rws::idToPacketLen(id);
|
||||
}
|
||||
|
||||
void RwPollingTask::fillSpecialRequestArray() {
|
||||
for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
|
||||
if (skipCommandingForRw[idx]) {
|
||||
specialRequestIds[idx] = DeviceHandlerIF::NO_COMMAND_ID;
|
||||
continue;
|
||||
}
|
||||
switch (rwCookies[idx]->specialRequest) {
|
||||
case (rws::SpecialRwRequest::GET_TM): {
|
||||
specialRequestIds[idx] = rws::GET_TM;
|
||||
break;
|
||||
}
|
||||
case (rws::SpecialRwRequest::INIT_RW_CONTROLLER): {
|
||||
specialRequestIds[idx] = rws::INIT_RW_CONTROLLER;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
specialRequestIds[idx] = DeviceHandlerIF::NO_COMMAND_ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RwPollingTask::handleSpecialRequests() {
|
||||
int fd = 0;
|
||||
fillSpecialRequestArray();
|
||||
ReturnValue_t result = openSpi(O_RDWR, fd);
|
||||
if (result != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
|
||||
if (specialRequestIds[idx] == DeviceHandlerIF::NO_COMMAND_ID) {
|
||||
continue;
|
||||
}
|
||||
prepareSimpleCommand(specialRequestIds[idx]);
|
||||
writeOneRwCmd(idx, fd);
|
||||
}
|
||||
closeSpi(fd);
|
||||
usleep(rws::SPI_REPLY_DELAY);
|
||||
for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
|
||||
if (specialRequestIds[idx] == DeviceHandlerIF::NO_COMMAND_ID) {
|
||||
continue;
|
||||
}
|
||||
uint8_t* replyBuf;
|
||||
size_t maxReadLen = idAndIdxToReadBuffer(specialRequestIds[idx], idx, &replyBuf);
|
||||
result = readNextReply(*rwCookies[idx], replyBuf, maxReadLen);
|
||||
if (result == returnvalue::OK) {
|
||||
// The first byte is always a flag which shows whether the value was read
|
||||
// properly at least once.
|
||||
replyBuf[0] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RwPollingTask::setAllReadFlagsFalse() {
|
||||
for (auto& rwCookie : rwCookies) {
|
||||
RwReplies replies(rwCookie->replyBuf.data());
|
||||
replies.getLastResetStatusReply[0] = false;
|
||||
replies.clearLastResetStatusReply[0] = false;
|
||||
replies.hkDataReply[0] = false;
|
||||
replies.readTemperatureReply[0] = false;
|
||||
replies.rwStatusReply[0] = false;
|
||||
replies.setSpeedReply[0] = false;
|
||||
replies.initRwControllerReply[0] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// This closes the SPI
|
||||
void RwPollingTask::closeSpi(int fd) {
|
||||
// This will perform the function to close the SPI
|
||||
close(fd);
|
||||
// The SPI is now closed.
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::sendOneMessage(int fd, RwCookie& rwCookie) {
|
||||
gpioId_t gpioId = rwCookie.getChipSelectPin();
|
||||
if (spiLock == nullptr) {
|
||||
sif::debug << "rwSpiCallback::spiCallback: Mutex or GPIO interface invalid" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
// Add datalinklayer like specified in the datasheet.
|
||||
size_t lenToSend = 0;
|
||||
rws::encodeHdlc(writeBuffer.data(), writeLen, encodedBuffer.data(), lenToSend);
|
||||
pullCsLow(gpioId, gpioIF);
|
||||
if (write(fd, encodedBuffer.data(), lenToSend) != static_cast<ssize_t>(lenToSend)) {
|
||||
sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl;
|
||||
pullCsHigh(gpioId, gpioIF);
|
||||
return rws::SPI_WRITE_FAILURE;
|
||||
}
|
||||
pullCsHigh(gpioId, gpioIF);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::pullCsLow(gpioId_t gpioId, GpioIF& gpioIF) {
|
||||
ReturnValue_t result = spiLock->lockMutex(TIMEOUT_TYPE, TIMEOUT_MS);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::debug << "RwPollingTask::pullCsLow: Failed to lock mutex" << std::endl;
|
||||
return result;
|
||||
}
|
||||
// Pull SPI CS low. For now, no support for active high given
|
||||
if (gpioId != gpio::NO_GPIO) {
|
||||
result = gpioIF.pullLow(gpioId);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "RwPollingTask::pullCsLow: Failed to pull chip select low" << std::endl;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void RwPollingTask::pullCsHigh(gpioId_t gpioId, GpioIF& gpioIF) {
|
||||
if (gpioId != gpio::NO_GPIO) {
|
||||
if (gpioIF.pullHigh(gpioId) != returnvalue::OK) {
|
||||
sif::error << "closeSpi: Failed to pull chip select high" << std::endl;
|
||||
}
|
||||
}
|
||||
if (spiLock->unlockMutex() != returnvalue::OK) {
|
||||
sif::error << "RwPollingTask::pullCsHigh: Failed to unlock mutex" << std::endl;
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void RwPollingTask::prepareSimpleCommand(DeviceCommandId_t id) {
|
||||
writeBuffer[0] = static_cast<uint8_t>(id);
|
||||
uint16_t crc = CRC::crc16ccitt(writeBuffer.data(), 1, 0xFFFF);
|
||||
writeBuffer[1] = static_cast<uint8_t>(crc & 0xFF);
|
||||
writeBuffer[2] = static_cast<uint8_t>(crc >> 8 & 0xFF);
|
||||
writeLen = 3;
|
||||
}
|
||||
|
||||
ReturnValue_t RwPollingTask::prepareSetSpeedCmd(uint8_t rwIdx) {
|
||||
writeBuffer[0] = static_cast<uint8_t>(rws::SET_SPEED);
|
||||
uint8_t* serPtr = writeBuffer.data() + 1;
|
||||
int32_t speedToSet = 0;
|
||||
uint16_t rampTimeToSet = 10;
|
||||
{
|
||||
MutexGuard mg(ipcLock);
|
||||
speedToSet = rwCookies[rwIdx]->currentRwSpeed;
|
||||
rampTimeToSet = rwCookies[rwIdx]->currentRampTime;
|
||||
}
|
||||
size_t serLen = 1;
|
||||
SerializeAdapter::serialize(&speedToSet, &serPtr, &serLen, writeBuffer.size(),
|
||||
SerializeIF::Endianness::LITTLE);
|
||||
SerializeAdapter::serialize(&rampTimeToSet, &serPtr, &serLen, writeBuffer.size(),
|
||||
SerializeIF::Endianness::LITTLE);
|
||||
|
||||
uint16_t crc = CRC::crc16ccitt(writeBuffer.data(), 7, 0xFFFF);
|
||||
writeBuffer[7] = static_cast<uint8_t>(crc & 0xFF);
|
||||
writeBuffer[8] = static_cast<uint8_t>((crc >> 8) & 0xFF);
|
||||
writeLen = 9;
|
||||
return returnvalue::OK;
|
||||
}
|
91
linux/devices/RwPollingTask.h
Normal file
91
linux/devices/RwPollingTask.h
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef LINUX_DEVICES_RWPOLLINGTASK_H_
|
||||
#define LINUX_DEVICES_RWPOLLINGTASK_H_
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/tasks/SemaphoreIF.h>
|
||||
#include <fsfw_hal/common/gpio/GpioIF.h>
|
||||
#include <fsfw_hal/linux/spi/SpiComIF.h>
|
||||
#include <fsfw_hal/linux/spi/SpiCookie.h>
|
||||
|
||||
#include "mission/devices/devicedefinitions/rwHelpers.h"
|
||||
|
||||
class RwCookie : public SpiCookie {
|
||||
friend class RwPollingTask;
|
||||
|
||||
public:
|
||||
static constexpr size_t REPLY_BUF_LEN = 524;
|
||||
RwCookie(uint8_t rwIdx, address_t spiAddress, gpioId_t chipSelect, const size_t maxSize,
|
||||
spi::SpiModes spiMode, uint32_t spiSpeed)
|
||||
: SpiCookie(spiAddress, chipSelect, maxSize, spiMode, spiSpeed), rwIdx(rwIdx) {
|
||||
bufLock = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<uint8_t, REPLY_BUF_LEN> replyBuf{};
|
||||
std::array<uint8_t, REPLY_BUF_LEN> exchangeBuf{};
|
||||
MutexIF* bufLock;
|
||||
bool setSpeed = true;
|
||||
int32_t currentRwSpeed = 0;
|
||||
uint16_t currentRampTime = 0;
|
||||
rws::SpecialRwRequest specialRequest = rws::SpecialRwRequest::REQUEST_NONE;
|
||||
uint8_t rwIdx;
|
||||
};
|
||||
|
||||
class RwPollingTask : public SystemObject, public ExecutableObjectIF, public DeviceCommunicationIF {
|
||||
public:
|
||||
RwPollingTask(object_id_t objectId, const char* spiDev, GpioIF& gpioIF);
|
||||
|
||||
ReturnValue_t performOperation(uint8_t operationCode) override;
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
private:
|
||||
enum class InternalState { IDLE, BUSY } state = InternalState::IDLE;
|
||||
SemaphoreIF* semaphore;
|
||||
bool debugMode = false;
|
||||
bool modeAndSpeedWasSet = false;
|
||||
MutexIF* ipcLock;
|
||||
MutexIF* spiLock;
|
||||
const char* spiDev;
|
||||
GpioIF& gpioIF;
|
||||
std::array<bool, 4> skipCommandingForRw;
|
||||
std::array<DeviceCommandId_t, 4> specialRequestIds;
|
||||
std::array<RwCookie*, 4> rwCookies;
|
||||
std::array<uint8_t, rws::MAX_CMD_SIZE> writeBuffer;
|
||||
std::array<uint8_t, rws::MAX_CMD_SIZE * 2> encodedBuffer;
|
||||
|
||||
size_t writeLen = 0;
|
||||
static constexpr MutexIF::TimeoutType TIMEOUT_TYPE = MutexIF::TimeoutType::WAITING;
|
||||
static constexpr uint32_t TIMEOUT_MS = 20;
|
||||
static constexpr uint8_t MAX_RETRIES_REPLY = 5;
|
||||
|
||||
// DeviceCommunicationIF overrides
|
||||
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;
|
||||
|
||||
ReturnValue_t writeAndReadAllRws(DeviceCommandId_t id);
|
||||
ReturnValue_t writeOneRwCmd(uint8_t rwIdx, int fd);
|
||||
ReturnValue_t readAllRws(DeviceCommandId_t id);
|
||||
|
||||
ReturnValue_t sendOneMessage(int fd, RwCookie& rwCookie);
|
||||
ReturnValue_t readNextReply(RwCookie& rwCookie, uint8_t* replyBuf, size_t maxReplyLen);
|
||||
void handleSpecialRequests();
|
||||
|
||||
ReturnValue_t openSpi(int flags, int& fd);
|
||||
ReturnValue_t pullCsLow(gpioId_t gpioId, GpioIF& gpioIF);
|
||||
void prepareSimpleCommand(DeviceCommandId_t id);
|
||||
ReturnValue_t prepareSetSpeedCmd(uint8_t rwIdx);
|
||||
|
||||
size_t idAndIdxToReadBuffer(DeviceCommandId_t id, uint8_t rwIdx, uint8_t** readPtr);
|
||||
void fillSpecialRequestArray();
|
||||
void setAllReadFlagsFalse();
|
||||
|
||||
void pullCsHigh(gpioId_t gpioId, GpioIF& gpioIF);
|
||||
void closeSpi(int);
|
||||
};
|
||||
|
||||
#endif /* LINUX_DEVICES_RWPOLLINGTASK_H_ */
|
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_ */
|
230
linux/devices/ScexUartReader.cpp
Normal file
230
linux/devices/ScexUartReader.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
#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/serial/SerialCookie.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(150);
|
||||
} 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) {
|
||||
SerialCookie *uartCookie = dynamic_cast<SerialCookie *>(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
|
||||
uart::setStopbits(tty, uartCookie->getStopBits());
|
||||
uart::setBitsPerWord(tty, BitsPerWord::BITS_8);
|
||||
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control
|
||||
uart::enableRead(tty);
|
||||
uart::ignoreCtrlLines(tty);
|
||||
|
||||
// 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;
|
||||
|
||||
uart::setBaudrate(tty, uartCookie->getBaudrate());
|
||||
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;
|
||||
ipcRingBuf.clear();
|
||||
while (not ipcQueue.empty()) {
|
||||
ipcQueue.pop();
|
||||
}
|
||||
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;
|
||||
};
|
220
linux/devices/SusPolling.cpp
Normal file
220
linux/devices/SusPolling.cpp
Normal file
@ -0,0 +1,220 @@
|
||||
#include "SusPolling.h"
|
||||
|
||||
#include <fsfw/tasks/SemaphoreFactory.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
#include <fsfw_hal/linux/spi/SpiCookie.h>
|
||||
#include <mission/controller/acs/AcsParameters.h>
|
||||
#include <mission/devices/max1227.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "mission/devices/devicedefinitions/susMax1227Helpers.h"
|
||||
|
||||
using namespace returnvalue;
|
||||
|
||||
SusPolling::SusPolling(object_id_t objectId, SpiComIF& spiComIF, GpioIF& gpioIF)
|
||||
: SystemObject(objectId), spiComIF(spiComIF), gpioIF(gpioIF) {
|
||||
semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
|
||||
semaphore->acquire();
|
||||
ipcLock = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
ReturnValue_t SusPolling::performOperation(uint8_t operationCode) {
|
||||
while (true) {
|
||||
ipcLock->lockMutex();
|
||||
state = InternalState::IDLE;
|
||||
ipcLock->unlockMutex();
|
||||
semaphore->acquire();
|
||||
// Give SUS handlers a chance to submit all requests.
|
||||
TaskFactory::delayTask(2);
|
||||
{
|
||||
// Takes 4-5 ms in debug mode.
|
||||
// Stopwatch watch;
|
||||
handleSusPolling();
|
||||
}
|
||||
// Protection against tardy tasks unlocking the thread again immediately.
|
||||
TaskFactory::delayTask(20);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SusPolling::initialize() { return OK; }
|
||||
|
||||
ReturnValue_t SusPolling::initializeInterface(CookieIF* cookie) {
|
||||
auto* spiCookie = dynamic_cast<SpiCookie*>(cookie);
|
||||
if (spiCookie == nullptr) {
|
||||
return FAILED;
|
||||
}
|
||||
int susIdx = addressToIndex(spiCookie->getSpiAddress());
|
||||
if (susIdx < 0) {
|
||||
return FAILED;
|
||||
}
|
||||
susDevs[susIdx].cookie = spiCookie;
|
||||
return spiComIF.initializeInterface(cookie);
|
||||
}
|
||||
|
||||
ReturnValue_t SusPolling::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) {
|
||||
auto* spiCookie = dynamic_cast<SpiCookie*>(cookie);
|
||||
if (spiCookie == nullptr) {
|
||||
return FAILED;
|
||||
}
|
||||
int susIdx = addressToIndex(spiCookie->getSpiAddress());
|
||||
if (susIdx < 0) {
|
||||
return FAILED;
|
||||
}
|
||||
if (sendLen != sizeof(acs::SusRequest)) {
|
||||
return FAILED;
|
||||
}
|
||||
const auto* susReq = reinterpret_cast<const acs::SusRequest*>(sendData);
|
||||
MutexGuard mg(ipcLock);
|
||||
if (susDevs[susIdx].mode != susReq->mode) {
|
||||
if (susReq->mode == acs::SimpleSensorMode::NORMAL) {
|
||||
susDevs[susIdx].performStartup = true;
|
||||
} else {
|
||||
susDevs[susIdx].ownReply.cfgWasSet = false;
|
||||
susDevs[susIdx].ownReply.dataWasSet = false;
|
||||
}
|
||||
susDevs[susIdx].mode = susReq->mode;
|
||||
}
|
||||
if (state == InternalState::IDLE) {
|
||||
state = InternalState::BUSY;
|
||||
semaphore->release();
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SusPolling::getSendSuccess(CookieIF* cookie) { return OK; }
|
||||
|
||||
ReturnValue_t SusPolling::requestReceiveMessage(CookieIF* cookie, size_t requestLen) { return OK; }
|
||||
|
||||
ReturnValue_t SusPolling::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
|
||||
auto* spiCookie = dynamic_cast<SpiCookie*>(cookie);
|
||||
if (spiCookie == nullptr) {
|
||||
return FAILED;
|
||||
}
|
||||
int susIdx = addressToIndex(spiCookie->getSpiAddress());
|
||||
if (susIdx < 0) {
|
||||
return FAILED;
|
||||
}
|
||||
MutexGuard mg(ipcLock);
|
||||
std::memcpy(&susDevs[susIdx].readerReply, &susDevs[susIdx].ownReply, sizeof(acs::SusReply));
|
||||
*buffer = reinterpret_cast<uint8_t*>(&susDevs[susIdx].readerReply);
|
||||
*size = sizeof(acs::SusReply);
|
||||
return OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SusPolling::handleSusPolling() {
|
||||
ReturnValue_t result;
|
||||
acs::SimpleSensorMode modes[12];
|
||||
bool performStartups[12]{};
|
||||
bool cfgsWereSet[12]{};
|
||||
uint8_t idx = 0;
|
||||
{
|
||||
MutexGuard mg(ipcLock);
|
||||
for (idx = 0; idx < 12; idx++) {
|
||||
modes[idx] = susDevs[idx].mode;
|
||||
performStartups[idx] = susDevs[idx].performStartup;
|
||||
}
|
||||
}
|
||||
for (idx = 0; idx < 12; idx++) {
|
||||
if (modes[idx] == acs::SimpleSensorMode::NORMAL) {
|
||||
if (performStartups[idx]) {
|
||||
// Startup handling.
|
||||
cmdBuf[0] = susMax1227::SETUP_INT_CLOKED;
|
||||
result = spiComIF.sendMessage(susDevs[idx].cookie, cmdBuf.data(), 1);
|
||||
if (result != OK) {
|
||||
susDevs[idx].replyResult = result;
|
||||
continue;
|
||||
}
|
||||
MutexGuard mg(ipcLock);
|
||||
susDevs[idx].ownReply.cfgWasSet = true;
|
||||
cfgsWereSet[idx] = true;
|
||||
susDevs[idx].performStartup = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (idx = 0; idx < 12; idx++) {
|
||||
if (modes[idx] == acs::SimpleSensorMode::NORMAL and cfgsWereSet[idx]) {
|
||||
// Regular sensor polling.
|
||||
cmdBuf[0] = max1227::buildResetByte(true);
|
||||
cmdBuf[1] = susMax1227::CONVERSION;
|
||||
result = spiComIF.sendMessage(susDevs[idx].cookie, cmdBuf.data(), 2);
|
||||
if (result != OK) {
|
||||
susDevs[idx].replyResult = result;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Internal conversion time is 3.5 us
|
||||
usleep(4);
|
||||
|
||||
for (idx = 0; idx < 12; idx++) {
|
||||
if (modes[idx] == acs::SimpleSensorMode::NORMAL and cfgsWereSet[idx]) {
|
||||
std::memset(cmdBuf.data(), 0, susMax1227::SIZE_READ_INT_CONVERSIONS);
|
||||
result = spiComIF.sendMessage(susDevs[idx].cookie, cmdBuf.data(),
|
||||
susMax1227::SIZE_READ_INT_CONVERSIONS);
|
||||
if (result != OK) {
|
||||
susDevs[idx].replyResult = result;
|
||||
continue;
|
||||
}
|
||||
result = spiComIF.readReceivedMessage(susDevs[idx].cookie, &rawReply, &dummy);
|
||||
if (result != OK) {
|
||||
susDevs[idx].replyResult = result;
|
||||
continue;
|
||||
}
|
||||
MutexGuard mg(ipcLock);
|
||||
susDevs[idx].ownReply.tempRaw = ((rawReply[0] & 0x0f) << 8) | rawReply[1];
|
||||
for (unsigned chIdx = 0; chIdx < 6; chIdx++) {
|
||||
susDevs[idx].ownReply.channelsRaw[chIdx] =
|
||||
(rawReply[chIdx * 2 + 2] << 8) | rawReply[chIdx * 2 + 3];
|
||||
}
|
||||
susDevs[idx].ownReply.dataWasSet = true;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int SusPolling::addressToIndex(address_t addr) {
|
||||
switch (addr) {
|
||||
case (addresses::SUS_0):
|
||||
return 0;
|
||||
break;
|
||||
case (addresses::SUS_1):
|
||||
return 1;
|
||||
break;
|
||||
case (addresses::SUS_2):
|
||||
return 2;
|
||||
break;
|
||||
case (addresses::SUS_3):
|
||||
return 3;
|
||||
break;
|
||||
case (addresses::SUS_4):
|
||||
return 4;
|
||||
break;
|
||||
case (addresses::SUS_5):
|
||||
return 5;
|
||||
break;
|
||||
case (addresses::SUS_6):
|
||||
return 6;
|
||||
break;
|
||||
case (addresses::SUS_7):
|
||||
return 7;
|
||||
break;
|
||||
case (addresses::SUS_8):
|
||||
return 8;
|
||||
break;
|
||||
case (addresses::SUS_9):
|
||||
return 9;
|
||||
break;
|
||||
case (addresses::SUS_10):
|
||||
return 10;
|
||||
break;
|
||||
case (addresses::SUS_11):
|
||||
return 11;
|
||||
break;
|
||||
default: {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
52
linux/devices/SusPolling.h
Normal file
52
linux/devices/SusPolling.h
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef LINUX_DEVICES_SUSPOLLING_H_
|
||||
#define LINUX_DEVICES_SUSPOLLING_H_
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/tasks/SemaphoreIF.h>
|
||||
#include <fsfw_hal/linux/spi/SpiComIF.h>
|
||||
|
||||
#include "devices/addresses.h"
|
||||
#include "mission/devices/devicedefinitions/acsPolling.h"
|
||||
|
||||
class SusPolling : public SystemObject, public ExecutableObjectIF, public DeviceCommunicationIF {
|
||||
public:
|
||||
SusPolling(object_id_t objectId, SpiComIF& spiComIF, GpioIF& gpioIF);
|
||||
|
||||
ReturnValue_t performOperation(uint8_t operationCode) override;
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
private:
|
||||
enum class InternalState { IDLE, BUSY } state = InternalState::IDLE;
|
||||
|
||||
struct SusDev {
|
||||
SpiCookie* cookie = nullptr;
|
||||
bool performStartup = false;
|
||||
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
|
||||
ReturnValue_t replyResult = returnvalue::OK;
|
||||
acs::SusReply ownReply{};
|
||||
acs::SusReply readerReply{};
|
||||
};
|
||||
|
||||
MutexIF* ipcLock;
|
||||
SemaphoreIF* semaphore;
|
||||
uint8_t* rawReply = nullptr;
|
||||
size_t dummy = 0;
|
||||
SpiComIF& spiComIF;
|
||||
GpioIF& gpioIF;
|
||||
|
||||
std::array<SusDev, 12> susDevs;
|
||||
std::array<uint8_t, 32> cmdBuf;
|
||||
|
||||
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;
|
||||
|
||||
ReturnValue_t handleSusPolling();
|
||||
static int addressToIndex(address_t addr);
|
||||
};
|
||||
|
||||
#endif /* LINUX_DEVICES_SUSPOLLING_H_ */
|
@ -1,7 +1,8 @@
|
||||
#ifndef MPSOC_RETURN_VALUES_IF_H_
|
||||
#define MPSOC_RETURN_VALUES_IF_H_
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "eive/resultClassIds.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
class MPSoCReturnValuesIF {
|
||||
public:
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "eive/definitions.h"
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
#include "fsfw/serialize/SerializeAdapter.h"
|
||||
#include "fsfw/tmtcpacket/SpacePacket.h"
|
||||
#include "mission/devices/devicedefinitions/SpBase.h"
|
||||
|
||||
namespace mpsoc {
|
||||
|
||||
@ -73,6 +73,8 @@ static const char NULL_TERMINATOR = '\0';
|
||||
static const uint8_t MIN_SPACE_PACKET_LENGTH = 7;
|
||||
static const uint8_t SPACE_PACKET_HEADER_SIZE = 6;
|
||||
|
||||
static constexpr size_t CRC_SIZE = 2;
|
||||
|
||||
/**
|
||||
* The size of payload data which will be forwarded to the requesting object. e.g. PUS Service
|
||||
* 8.
|
||||
@ -88,8 +90,14 @@ static const size_t MAX_FILENAME_SIZE = 256;
|
||||
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 = SpacePacket::PACKET_MAX_SIZE * 3;
|
||||
static const size_t MAX_COMMAND_SIZE = SpacePacket::PACKET_MAX_SIZE;
|
||||
/**
|
||||
* Maximum SP packet size as specified in the TAS Supversior ICD.
|
||||
* https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_TAS-ILH-IRS/ICD-PLOC/TAS&fileid=942896
|
||||
* at sheet README
|
||||
*/
|
||||
static constexpr size_t SP_MAX_SIZE = 1024;
|
||||
static const size_t MAX_REPLY_SIZE = SP_MAX_SIZE * 3;
|
||||
static const size_t MAX_COMMAND_SIZE = SP_MAX_SIZE;
|
||||
static const size_t MAX_DATA_SIZE = 1016;
|
||||
|
||||
/**
|
||||
@ -100,13 +108,42 @@ static const uint16_t TC_WRITE_SEQ_EXECUTION_DELAY = 80;
|
||||
// Requires approx. 2 seconds for execution. 8 => 4 seconds
|
||||
static const uint16_t TC_DOWNLINK_PWR_ON_EXECUTION_DELAY = 8;
|
||||
|
||||
namespace status_code {
|
||||
static const uint16_t UNKNOWN_APID = 0x5DD;
|
||||
static const uint16_t INCORRECT_LENGTH = 0x5DE;
|
||||
static const uint16_t INCORRECT_CRC = 0x5DF;
|
||||
static const uint16_t INCORRECT_PKT_SEQ_CNT = 0x5E0;
|
||||
static const uint16_t TC_NOT_ALLOWED_IN_MODE = 0x5E1;
|
||||
static const uint16_t TC_EXEUTION_DISABLED = 0x5E2;
|
||||
static const uint16_t FLASH_MOUNT_FAILED = 0x5E3;
|
||||
static const uint16_t FLASH_FILE_ALREADY_CLOSED = 0x5E4;
|
||||
static const uint16_t FLASH_FILE_OPEN_FAILED = 0x5E5;
|
||||
static const uint16_t FLASH_FILE_ALREDY_OPEN = 0x5E6;
|
||||
static const uint16_t FLASH_FILE_NOT_OPEN = 0x5E7;
|
||||
static const uint16_t FLASH_UNMOUNT_FAILED = 0x5E8;
|
||||
static const uint16_t HEAP_ALLOCATION_FAILED = 0x5E9;
|
||||
static const uint16_t INVALID_PARAMETER = 0x5EA;
|
||||
static const uint16_t NOT_INITIALIZED = 0x5EB;
|
||||
static const uint16_t REBOOT_IMMINENT = 0x5EC;
|
||||
static const uint16_t CORRUPT_DATA = 0x5ED;
|
||||
static const uint16_t FLASH_CORRECTABLE_MISMATCH = 0x5EE;
|
||||
static const uint16_t FLASH_UNCORRECTABLE_MISMATCH = 0x5EF;
|
||||
static const uint16_t RESERVED_0 = 0x5F0;
|
||||
static const uint16_t RESERVED_1 = 0x5F1;
|
||||
static const uint16_t RESERVED_2 = 0x5F2;
|
||||
static const uint16_t RESERVED_3 = 0x5F3;
|
||||
static const uint16_t RESERVED_4 = 0x5F4;
|
||||
} // namespace status_code
|
||||
|
||||
/**
|
||||
* @brief Abstract base class for TC space packet of MPSoC.
|
||||
*/
|
||||
class TcBase : public SpacePacket, public MPSoCReturnValuesIF {
|
||||
class TcBase : public ploc::SpTcBase, public MPSoCReturnValuesIF {
|
||||
public:
|
||||
virtual ~TcBase() = default;
|
||||
|
||||
// Initial length field of space packet. Will always be updated when packet is created.
|
||||
static const uint16_t INIT_LENGTH = 1;
|
||||
static const uint16_t INIT_LENGTH = 2;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
@ -114,8 +151,12 @@ class TcBase : public SpacePacket, public MPSoCReturnValuesIF {
|
||||
* @param sequenceCount Sequence count of space packet which will be incremented with each
|
||||
* sent and received packets.
|
||||
*/
|
||||
TcBase(uint16_t apid, uint16_t sequenceCount)
|
||||
: SpacePacket(INIT_LENGTH, true, apid, sequenceCount) {}
|
||||
TcBase(ploc::SpTcParams params, uint16_t apid, uint16_t sequenceCount)
|
||||
: ploc::SpTcBase(params, apid, 0, sequenceCount) {
|
||||
spParams.setFullPayloadLen(INIT_LENGTH);
|
||||
}
|
||||
|
||||
ReturnValue_t buildPacket() { return buildPacket(nullptr, 0); }
|
||||
|
||||
/**
|
||||
* @brief Function to initialize the space packet
|
||||
@ -123,19 +164,24 @@ class TcBase : public SpacePacket, public MPSoCReturnValuesIF {
|
||||
* @param commandData Pointer to command specific data
|
||||
* @param commandDataLen Length of command data
|
||||
*
|
||||
* @return RETURN_OK if packet creation was successful, otherwise error return value
|
||||
* @return returnvalue::OK if packet creation was successful, otherwise error return value
|
||||
*/
|
||||
virtual ReturnValue_t createPacket(const uint8_t* commandData, size_t commandDataLen) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
result = initPacket(commandData, commandDataLen);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
ReturnValue_t buildPacket(const uint8_t* commandData, size_t commandDataLen) {
|
||||
payloadStart = spParams.buf + ccsds::HEADER_LEN;
|
||||
ReturnValue_t res;
|
||||
if (commandData != nullptr and commandDataLen > 0) {
|
||||
res = initPacket(commandData, commandDataLen);
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
result = addCrc();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
|
||||
updateSpFields();
|
||||
res = checkSizeAndSerializeHeader();
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
return result;
|
||||
return calcAndSetCrc();
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -146,46 +192,7 @@ class TcBase : public SpacePacket, public MPSoCReturnValuesIF {
|
||||
* @param commandDataLen Length of received command data
|
||||
*/
|
||||
virtual ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates and adds the CRC
|
||||
*/
|
||||
ReturnValue_t addCrc() {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
size_t serializedSize = 0;
|
||||
uint32_t full_size = getFullSize();
|
||||
uint16_t crc = CRC::crc16ccitt(getWholeData(), full_size - CRC_SIZE);
|
||||
result = SerializeAdapter::serialize<uint16_t>(
|
||||
&crc, this->localData.byteStream + full_size - CRC_SIZE, &serializedSize, sizeof(crc),
|
||||
SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::debug << "TcBase::addCrc: Failed to serialize crc field" << std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class for handling tm replies of the PLOC MPSoC.
|
||||
*/
|
||||
class TmPacket : public SpacePacket, public MPSoCReturnValuesIF {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor creates idle packet and sets length field to maximum allowed size.
|
||||
*/
|
||||
TmPacket() : SpacePacket(PACKET_MAX_SIZE) {}
|
||||
|
||||
ReturnValue_t checkCrc() {
|
||||
uint8_t* crcPtr = this->getPacketData() + this->getPacketDataLength() - 1;
|
||||
uint16_t receivedCrc = *(crcPtr) << 8 | *(crcPtr + 1);
|
||||
uint16_t recalculatedCrc =
|
||||
CRC::crc16ccitt(this->localData.byteStream, this->getFullSize() - CRC_SIZE);
|
||||
if (recalculatedCrc != receivedCrc) {
|
||||
return CRC_FAILURE;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
};
|
||||
|
||||
@ -197,27 +204,27 @@ class TcMemRead : public TcBase {
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
TcMemRead(uint16_t sequenceCount) : TcBase(apid::TC_MEM_READ, sequenceCount) {
|
||||
this->setPacketDataLength(PACKET_LENGTH);
|
||||
TcMemRead(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_MEM_READ, sequenceCount) {
|
||||
spParams.setFullPayloadLen(COMMAND_LENGTH + CRC_SIZE);
|
||||
}
|
||||
|
||||
uint16_t getMemLen() const { return memLen; }
|
||||
|
||||
protected:
|
||||
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = lengthCheck(commandDataLen);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::memcpy(this->localData.fields.buffer, commandData, MEM_ADDRESS_SIZE);
|
||||
std::memcpy(this->localData.fields.buffer + MEM_ADDRESS_SIZE, commandData + MEM_ADDRESS_SIZE,
|
||||
MEM_LEN_SIZE);
|
||||
std::memcpy(payloadStart, commandData, MEM_ADDRESS_SIZE);
|
||||
std::memcpy(payloadStart + MEM_ADDRESS_SIZE, commandData + MEM_ADDRESS_SIZE, MEM_LEN_SIZE);
|
||||
size_t size = sizeof(memLen);
|
||||
const uint8_t* memLenPtr = commandData + MEM_ADDRESS_SIZE;
|
||||
result =
|
||||
SerializeAdapter::deSerialize(&memLen, &memLenPtr, &size, SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
@ -232,10 +239,10 @@ class TcMemRead : public TcBase {
|
||||
uint16_t memLen = 0;
|
||||
|
||||
ReturnValue_t lengthCheck(size_t commandDataLen) {
|
||||
if (commandDataLen != COMMAND_LENGTH) {
|
||||
if (commandDataLen != COMMAND_LENGTH or checkPayloadLen() != returnvalue::OK) {
|
||||
return INVALID_LENGTH;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
};
|
||||
|
||||
@ -248,43 +255,56 @@ class TcMemWrite : public TcBase {
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
TcMemWrite(uint16_t sequenceCount) : TcBase(apid::TC_MEM_WRITE, sequenceCount) {}
|
||||
TcMemWrite(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_MEM_WRITE, sequenceCount) {}
|
||||
|
||||
protected:
|
||||
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = lengthCheck(commandDataLen);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::memcpy(this->localData.fields.buffer, commandData, commandDataLen);
|
||||
uint16_t memLen =
|
||||
*(commandData + MEM_ADDRESS_SIZE) << 8 | *(commandData + MEM_ADDRESS_SIZE + 1);
|
||||
this->setPacketDataLength(memLen * 4 + FIX_LENGTH - 1);
|
||||
spParams.setFullPayloadLen(MIN_FIXED_PAYLOAD_LENGTH + memLen * 4 + CRC_SIZE);
|
||||
result = checkPayloadLen();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::memcpy(payloadStart, commandData, commandDataLen);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
// Min length consists of 4 byte address, 2 byte mem length field, 4 byte data (1 word)
|
||||
static const size_t MIN_COMMAND_DATA_LENGTH = 10;
|
||||
// 4 byte address, 2 byte mem length field
|
||||
static const size_t MEM_ADDRESS_SIZE = 4;
|
||||
static const size_t FIX_LENGTH = 8;
|
||||
static const size_t MIN_FIXED_PAYLOAD_LENGTH = MEM_ADDRESS_SIZE + 2;
|
||||
// Min length consists of 4 byte address, 2 byte mem length field, 4 byte data (1 word)
|
||||
static const size_t MIN_COMMAND_DATA_LENGTH = MIN_FIXED_PAYLOAD_LENGTH + 4;
|
||||
|
||||
ReturnValue_t lengthCheck(size_t commandDataLen) {
|
||||
if (commandDataLen < MIN_COMMAND_DATA_LENGTH) {
|
||||
sif::warning << "TcMemWrite: Command has invalid length " << commandDataLen << std::endl;
|
||||
sif::warning << "TcMemWrite: Length " << commandDataLen << " smaller than minimum "
|
||||
<< MIN_COMMAND_DATA_LENGTH << std::endl;
|
||||
return INVALID_LENGTH;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
if (commandDataLen + CRC_SIZE > spParams.maxSize) {
|
||||
sif::warning << "TcMemWrite: Length " << commandDataLen << " larger than allowed "
|
||||
<< spParams.maxSize - CRC_SIZE << std::endl;
|
||||
return INVALID_LENGTH;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class to help creation of flash fopen command.
|
||||
*/
|
||||
class FlashFopen : public TcBase {
|
||||
class FlashFopen : public ploc::SpTcBase {
|
||||
public:
|
||||
FlashFopen(uint16_t sequenceCount) : TcBase(apid::TC_FLASHFOPEN, sequenceCount) {}
|
||||
FlashFopen(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: ploc::SpTcBase(params, apid::TC_FLASHFOPEN, sequenceCount) {}
|
||||
|
||||
static const char APPEND = 'a';
|
||||
static const char WRITE = 'w';
|
||||
@ -292,19 +312,17 @@ class FlashFopen : public TcBase {
|
||||
|
||||
ReturnValue_t createPacket(std::string filename, char accessMode_) {
|
||||
accessMode = accessMode_;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
size_t nameSize = filename.size();
|
||||
std::memcpy(this->getPacketData(), filename.c_str(), nameSize);
|
||||
*(this->getPacketData() + nameSize) = NULL_TERMINATOR;
|
||||
std::memcpy(this->getPacketData() + nameSize + sizeof(NULL_TERMINATOR), &accessMode,
|
||||
sizeof(accessMode));
|
||||
this->setPacketDataLength(nameSize + sizeof(NULL_TERMINATOR) + sizeof(accessMode) + CRC_SIZE -
|
||||
1);
|
||||
result = addCrc();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
spParams.setFullPayloadLen(nameSize + sizeof(NULL_TERMINATOR) + sizeof(accessMode) + CRC_SIZE);
|
||||
ReturnValue_t result = checkPayloadLen();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
std::memcpy(payloadStart, filename.c_str(), nameSize);
|
||||
*(spParams.buf + nameSize) = NULL_TERMINATOR;
|
||||
std::memcpy(payloadStart + nameSize + sizeof(NULL_TERMINATOR), &accessMode, sizeof(accessMode));
|
||||
updateSpFields();
|
||||
return calcAndSetCrc();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -314,52 +332,57 @@ class FlashFopen : public TcBase {
|
||||
/**
|
||||
* @brief Class to help creation of flash fclose command.
|
||||
*/
|
||||
class FlashFclose : public TcBase {
|
||||
class FlashFclose : public ploc::SpTcBase {
|
||||
public:
|
||||
FlashFclose(uint16_t sequenceCount) : TcBase(apid::TC_FLASHFCLOSE, sequenceCount) {}
|
||||
FlashFclose(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: ploc::SpTcBase(params, apid::TC_FLASHFCLOSE, sequenceCount) {}
|
||||
|
||||
ReturnValue_t createPacket(std::string filename) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
size_t nameSize = filename.size();
|
||||
std::memcpy(this->getPacketData(), filename.c_str(), nameSize);
|
||||
*(this->getPacketData() + nameSize) = NULL_TERMINATOR;
|
||||
this->setPacketDataLength(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE - 1);
|
||||
result = addCrc();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
spParams.setFullPayloadLen(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE);
|
||||
ReturnValue_t result = checkPayloadLen();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
std::memcpy(payloadStart, filename.c_str(), nameSize);
|
||||
*(payloadStart + nameSize) = NULL_TERMINATOR;
|
||||
return calcAndSetCrc();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class to build flash write space packet.
|
||||
*/
|
||||
class TcFlashWrite : public TcBase {
|
||||
class TcFlashWrite : public ploc::SpTcBase {
|
||||
public:
|
||||
TcFlashWrite(uint16_t sequenceCount) : TcBase(apid::TC_FLASHWRITE, sequenceCount) {}
|
||||
TcFlashWrite(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: ploc::SpTcBase(params, apid::TC_FLASHWRITE, sequenceCount) {}
|
||||
|
||||
ReturnValue_t createPacket(const uint8_t* writeData, uint32_t writeLen_) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t buildPacket(const uint8_t* writeData, uint32_t writeLen_) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
writeLen = writeLen_;
|
||||
if (writeLen > MAX_DATA_SIZE) {
|
||||
sif::debug << "FlashWrite::createPacket: Command data too big" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
size_t serializedSize = 0;
|
||||
result =
|
||||
SerializeAdapter::serialize<uint32_t>(&writeLen, this->getPacketData(), &serializedSize,
|
||||
sizeof(writeLen), SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
spParams.setFullPayloadLen(static_cast<uint16_t>(writeLen) + 4 + CRC_SIZE);
|
||||
result = checkPayloadLen();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::memcpy(this->getPacketData() + sizeof(writeLen), writeData, writeLen);
|
||||
this->setPacketDataLength(static_cast<uint16_t>(writeLen + CRC_SIZE - 1));
|
||||
result = addCrc();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
size_t serializedSize = ccsds::HEADER_LEN;
|
||||
result = SerializeAdapter::serialize(&writeLen, payloadStart, &serializedSize, spParams.maxSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
std::memcpy(payloadStart + sizeof(writeLen), writeData, writeLen);
|
||||
updateSpFields();
|
||||
auto res = checkSizeAndSerializeHeader();
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
return calcAndSetCrc();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -369,21 +392,27 @@ class TcFlashWrite : public TcBase {
|
||||
/**
|
||||
* @brief Class to help creation of flash delete command.
|
||||
*/
|
||||
class TcFlashDelete : public TcBase {
|
||||
class TcFlashDelete : public ploc::SpTcBase {
|
||||
public:
|
||||
TcFlashDelete(uint16_t sequenceCount) : TcBase(apid::TC_FLASHDELETE, sequenceCount) {}
|
||||
TcFlashDelete(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: ploc::SpTcBase(params, apid::TC_FLASHDELETE, sequenceCount) {}
|
||||
|
||||
ReturnValue_t createPacket(std::string filename) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t buildPacket(std::string filename) {
|
||||
size_t nameSize = filename.size();
|
||||
std::memcpy(this->getPacketData(), filename.c_str(), nameSize);
|
||||
*(this->getPacketData() + nameSize) = NULL_TERMINATOR;
|
||||
this->setPacketDataLength(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE - 1);
|
||||
result = addCrc();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
spParams.setFullPayloadLen(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE);
|
||||
auto res = checkPayloadLen();
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
return result;
|
||||
std::memcpy(payloadStart, filename.c_str(), nameSize);
|
||||
*(payloadStart + nameSize) = NULL_TERMINATOR;
|
||||
|
||||
updateSpFields();
|
||||
res = checkSizeAndSerializeHeader();
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
return calcAndSetCrc();
|
||||
}
|
||||
};
|
||||
|
||||
@ -392,17 +421,8 @@ class TcFlashDelete : public TcBase {
|
||||
*/
|
||||
class TcReplayStop : public TcBase {
|
||||
public:
|
||||
TcReplayStop(uint16_t sequenceCount) : TcBase(apid::TC_REPLAY_STOP, sequenceCount) {}
|
||||
|
||||
ReturnValue_t createPacket() {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
result = addCrc();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
this->setPacketDataLength(static_cast<uint16_t>(CRC_SIZE - 1));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
TcReplayStop(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_REPLAY_STOP, sequenceCount) {}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -413,21 +433,22 @@ class TcReplayStart : public TcBase {
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
TcReplayStart(uint16_t sequenceCount) : TcBase(apid::TC_REPLAY_START, sequenceCount) {}
|
||||
TcReplayStart(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_REPLAY_START, sequenceCount) {}
|
||||
|
||||
protected:
|
||||
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
spParams.setFullPayloadLen(commandDataLen + CRC_SIZE);
|
||||
result = lengthCheck(commandDataLen);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = checkData(*commandData);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::memcpy(this->localData.fields.buffer, commandData, commandDataLen);
|
||||
this->setPacketDataLength(commandDataLen + CRC_SIZE - 1);
|
||||
std::memcpy(payloadStart, commandData, commandDataLen);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -437,11 +458,11 @@ class TcReplayStart : public TcBase {
|
||||
static const uint8_t ONCE = 1;
|
||||
|
||||
ReturnValue_t lengthCheck(size_t commandDataLen) {
|
||||
if (commandDataLen != COMMAND_DATA_LENGTH) {
|
||||
if (commandDataLen != COMMAND_DATA_LENGTH or checkPayloadLen() != returnvalue::OK) {
|
||||
sif::warning << "TcReplayStart: Command has invalid length " << commandDataLen << std::endl;
|
||||
return INVALID_LENGTH;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t checkData(uint8_t replay) {
|
||||
@ -449,7 +470,7 @@ class TcReplayStart : public TcBase {
|
||||
sif::warning << "TcReplayStart::checkData: Invalid replay value" << std::endl;
|
||||
return INVALID_PARAMETER;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
};
|
||||
|
||||
@ -461,27 +482,31 @@ class TcDownlinkPwrOn : public TcBase {
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
TcDownlinkPwrOn(uint16_t sequenceCount) : TcBase(apid::TC_DOWNLINK_PWR_ON, sequenceCount) {}
|
||||
TcDownlinkPwrOn(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_DOWNLINK_PWR_ON, sequenceCount) {}
|
||||
|
||||
protected:
|
||||
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = lengthCheck(commandDataLen);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = modeCheck(*commandData);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = laneRateCheck(*(commandData + 1));
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::memcpy(this->localData.fields.buffer, commandData, commandDataLen);
|
||||
std::memcpy(this->localData.fields.buffer + commandDataLen, &MAX_AMPLITUDE,
|
||||
sizeof(MAX_AMPLITUDE));
|
||||
this->setPacketDataLength(commandDataLen + sizeof(MAX_AMPLITUDE) + CRC_SIZE - 1);
|
||||
spParams.setFullPayloadLen(commandDataLen + sizeof(MAX_AMPLITUDE) + CRC_SIZE);
|
||||
result = checkPayloadLen();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::memcpy(payloadStart, commandData, commandDataLen);
|
||||
std::memcpy(payloadStart + commandDataLen, &MAX_AMPLITUDE, sizeof(MAX_AMPLITUDE));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -503,7 +528,7 @@ class TcDownlinkPwrOn : public TcBase {
|
||||
sif::warning << "TcDownlinkPwrOn: Command has invalid length " << commandDataLen << std::endl;
|
||||
return INVALID_LENGTH;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t modeCheck(uint8_t mode) {
|
||||
@ -511,7 +536,7 @@ class TcDownlinkPwrOn : public TcBase {
|
||||
sif::warning << "TcDwonlinkPwrOn::modeCheck: Invalid JESD mode" << std::endl;
|
||||
return INVALID_MODE;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t laneRateCheck(uint8_t laneRate) {
|
||||
@ -519,7 +544,7 @@ class TcDownlinkPwrOn : public TcBase {
|
||||
sif::warning << "TcReplayStart::laneRateCheck: Invalid lane rate" << std::endl;
|
||||
return INVALID_LANE_RATE;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
};
|
||||
|
||||
@ -528,17 +553,8 @@ class TcDownlinkPwrOn : public TcBase {
|
||||
*/
|
||||
class TcDownlinkPwrOff : public TcBase {
|
||||
public:
|
||||
TcDownlinkPwrOff(uint16_t sequenceCount) : TcBase(apid::TC_DOWNLINK_PWR_OFF, sequenceCount) {}
|
||||
|
||||
ReturnValue_t createPacket() {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
result = addCrc();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
this->setPacketDataLength(static_cast<uint16_t>(CRC_SIZE - 1));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
TcDownlinkPwrOff(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_DOWNLINK_PWR_OFF, sequenceCount) {}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -549,19 +565,19 @@ class TcReplayWriteSeq : public TcBase {
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
TcReplayWriteSeq(uint16_t sequenceCount)
|
||||
: TcBase(apid::TC_REPLAY_WRITE_SEQUENCE, sequenceCount) {}
|
||||
TcReplayWriteSeq(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_REPLAY_WRITE_SEQUENCE, sequenceCount) {}
|
||||
|
||||
protected:
|
||||
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
spParams.setFullPayloadLen(commandDataLen + sizeof(NULL_TERMINATOR) + CRC_SIZE);
|
||||
result = lengthCheck(commandDataLen);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::memcpy(this->localData.fields.buffer, commandData, commandDataLen);
|
||||
*(this->localData.fields.buffer + commandDataLen) = NULL_TERMINATOR;
|
||||
this->setPacketDataLength(commandDataLen + sizeof(NULL_TERMINATOR) + CRC_SIZE - 1);
|
||||
std::memcpy(payloadStart, commandData, commandDataLen);
|
||||
*(payloadStart + commandDataLen) = NULL_TERMINATOR;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -569,12 +585,13 @@ class TcReplayWriteSeq : public TcBase {
|
||||
static const size_t USE_DECODING_LENGTH = 1;
|
||||
|
||||
ReturnValue_t lengthCheck(size_t commandDataLen) {
|
||||
if (commandDataLen > USE_DECODING_LENGTH + MAX_FILENAME_SIZE) {
|
||||
if (commandDataLen > USE_DECODING_LENGTH + MAX_FILENAME_SIZE or
|
||||
checkPayloadLen() != returnvalue::OK) {
|
||||
sif::warning << "TcReplayWriteSeq: Command has invalid length " << commandDataLen
|
||||
<< std::endl;
|
||||
return INVALID_LENGTH;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
};
|
||||
|
||||
@ -598,7 +615,7 @@ class FlashWritePusCmd : public MPSoCReturnValuesIF {
|
||||
if (mpsocFile.size() > MAX_FILENAME_SIZE) {
|
||||
return MPSOC_FILENAME_TOO_LONG;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
std::string getObcFile() { return obcFile; }
|
||||
@ -616,17 +633,8 @@ class FlashWritePusCmd : public MPSoCReturnValuesIF {
|
||||
*/
|
||||
class TcModeReplay : public TcBase {
|
||||
public:
|
||||
TcModeReplay(uint16_t sequenceCount) : TcBase(apid::TC_MODE_REPLAY, sequenceCount) {}
|
||||
|
||||
ReturnValue_t createPacket() {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
result = addCrc();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
this->setPacketDataLength(static_cast<uint16_t>(CRC_SIZE - 1));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
TcModeReplay(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_MODE_REPLAY, sequenceCount) {}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -634,33 +642,34 @@ class TcModeReplay : public TcBase {
|
||||
*/
|
||||
class TcModeIdle : public TcBase {
|
||||
public:
|
||||
TcModeIdle(uint16_t sequenceCount) : TcBase(apid::TC_MODE_IDLE, sequenceCount) {}
|
||||
|
||||
ReturnValue_t createPacket() {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
result = addCrc();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
this->setPacketDataLength(static_cast<uint16_t>(CRC_SIZE - 1));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
TcModeIdle(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_MODE_IDLE, sequenceCount) {}
|
||||
};
|
||||
|
||||
class TcCamcmdSend : public TcBase {
|
||||
public:
|
||||
TcCamcmdSend(uint16_t sequenceCount) : TcBase(apid::TC_CAM_CMD_SEND, sequenceCount) {}
|
||||
TcCamcmdSend(ploc::SpTcParams params, uint16_t sequenceCount)
|
||||
: TcBase(params, apid::TC_CAM_CMD_SEND, sequenceCount) {}
|
||||
|
||||
protected:
|
||||
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) {
|
||||
ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override {
|
||||
if (commandDataLen > MAX_DATA_LENGTH) {
|
||||
return INVALID_LENGTH;
|
||||
}
|
||||
std::memcpy(this->getPacketData(), commandData, commandDataLen);
|
||||
*(this->getPacketData() + commandDataLen) = CARRIAGE_RETURN;
|
||||
uint16_t trueLength = commandDataLen + sizeof(CARRIAGE_RETURN) + CRC_SIZE;
|
||||
this->setPacketDataLength(trueLength - 1);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
uint16_t dataLen = static_cast<uint16_t>(commandDataLen + sizeof(CARRIAGE_RETURN));
|
||||
spParams.setFullPayloadLen(sizeof(dataLen) + commandDataLen + sizeof(CARRIAGE_RETURN) +
|
||||
CRC_SIZE);
|
||||
auto res = checkPayloadLen();
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
size_t size = ccsds::HEADER_LEN;
|
||||
SerializeAdapter::serialize(&dataLen, payloadStart, &size, spParams.maxSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
std::memcpy(payloadStart + sizeof(dataLen), commandData, commandDataLen);
|
||||
*(payloadStart + sizeof(dataLen) + commandDataLen) = CARRIAGE_RETURN;
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
private:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -821,27 +821,27 @@ class ChecksumReply {
|
||||
*
|
||||
*/
|
||||
ChecksumReply(const uint8_t* datafield) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
region = *(datafield);
|
||||
const uint8_t* addressData = datafield + ADDRESS_OFFSET;
|
||||
size_t size = sizeof(address);
|
||||
result = SerializeAdapter::deSerialize(&address, &addressData, &size,
|
||||
SerializeIF::Endianness::LITTLE);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::debug << "ChecksumReply::ChecksumReply: Failed to deserialize address" << std::endl;
|
||||
}
|
||||
const uint8_t* lengthData = datafield + LENGTH_OFFSET;
|
||||
size = sizeof(length);
|
||||
result =
|
||||
SerializeAdapter::deSerialize(&length, &lengthData, &size, SerializeIF::Endianness::LITTLE);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::debug << "ChecksumReply::ChecksumReply: Failed to deserialize length" << std::endl;
|
||||
}
|
||||
const uint8_t* checksumData = datafield + CHECKSUM_OFFSET;
|
||||
size = sizeof(checksum);
|
||||
result = SerializeAdapter::deSerialize(&checksum, &checksumData, &size,
|
||||
SerializeIF::Endianness::LITTLE);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::debug << "ChecksumReply::ChecksumReply: Failed to deserialize checksum" << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
#ifndef SUPV_RETURN_VALUES_IF_H_
|
||||
#define SUPV_RETURN_VALUES_IF_H_
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
class SupvReturnValuesIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::SUPV_RETURN_VALUES_IF;
|
||||
|
||||
//! [EXPORT] : [COMMENT] Space Packet received from PLOC supervisor has invalid CRC
|
||||
static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0);
|
||||
//! [EXPORT] : [COMMENT] Received ACK failure reply from PLOC supervisor
|
||||
static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1);
|
||||
//! [EXPORT] : [COMMENT] Received execution failure reply from PLOC supervisor
|
||||
static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2);
|
||||
//! [EXPORT] : [COMMENT] Received space packet with invalid APID from PLOC supervisor
|
||||
static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3);
|
||||
//! [EXPORT] : [COMMENT] Failed to read current system time
|
||||
static const ReturnValue_t GET_TIME_FAILURE = MAKE_RETURN_CODE(0xA4);
|
||||
//! [EXPORT] : [COMMENT] Received command with invalid watchdog parameter. Valid watchdogs are 0
|
||||
//! for PS, 1 for PL and 2 for INT
|
||||
static const ReturnValue_t INVALID_WATCHDOG = MAKE_RETURN_CODE(0xA5);
|
||||
//! [EXPORT] : [COMMENT] Received watchdog timeout config command with invalid timeout. Valid
|
||||
//! timeouts must be in the range between 1000 and 360000 ms.
|
||||
static const ReturnValue_t INVALID_WATCHDOG_TIMEOUT = MAKE_RETURN_CODE(0xA6);
|
||||
//! [EXPORT] : [COMMENT] Received latchup config command with invalid latchup ID
|
||||
static const ReturnValue_t INVALID_LATCHUP_ID = MAKE_RETURN_CODE(0xA7);
|
||||
//! [EXPORT] : [COMMENT] Received set adc sweep period command with invalid sweep period. Must be
|
||||
//! larger than 21.
|
||||
static const ReturnValue_t SWEEP_PERIOD_TOO_SMALL = MAKE_RETURN_CODE(0xA8);
|
||||
//! [EXPORT] : [COMMENT] Receive auto EM test command with invalid test param. Valid params are 1
|
||||
//! and 2.
|
||||
static const ReturnValue_t INVALID_TEST_PARAM = MAKE_RETURN_CODE(0xA9);
|
||||
//! [EXPORT] : [COMMENT] Returned when scanning for MRAM dump packets failed.
|
||||
static const ReturnValue_t MRAM_PACKET_PARSING_FAILURE = MAKE_RETURN_CODE(0xAA);
|
||||
//! [EXPORT] : [COMMENT] Returned when the start and stop addresses of the MRAM dump or MRAM wipe
|
||||
//! commands are invalid (e.g. start address bigger than stop address)
|
||||
static const ReturnValue_t INVALID_MRAM_ADDRESSES = MAKE_RETURN_CODE(0xAB);
|
||||
//! [EXPORT] : [COMMENT] Expect reception of an MRAM dump packet but received space packet with
|
||||
//! other apid.
|
||||
static const ReturnValue_t NO_MRAM_PACKET = MAKE_RETURN_CODE(0xAC);
|
||||
//! [EXPORT] : [COMMENT] Path to PLOC directory on SD card does not exist
|
||||
static const ReturnValue_t PATH_DOES_NOT_EXIST = MAKE_RETURN_CODE(0xAD);
|
||||
//! [EXPORT] : [COMMENT] MRAM dump file does not exists. The file should actually already have
|
||||
//! been created with the reception of the first dump packet.
|
||||
static const ReturnValue_t MRAM_FILE_NOT_EXISTS = MAKE_RETURN_CODE(0xAE);
|
||||
//! [EXPORT] : [COMMENT] Received action command has invalid length
|
||||
static const ReturnValue_t INVALID_LENGTH = MAKE_RETURN_CODE(0xAF);
|
||||
//! [EXPORT] : [COMMENT] Filename too long
|
||||
static const ReturnValue_t FILENAME_TOO_LONG = MAKE_RETURN_CODE(0xB0);
|
||||
//! [EXPORT] : [COMMENT] Received update status report with invalid packet length field
|
||||
static const ReturnValue_t UPDATE_STATUS_REPORT_INVALID_LENGTH = MAKE_RETURN_CODE(0xB1);
|
||||
//! [EXPORT] : [COMMENT] Update status report does not contain expected CRC. There might be a bit
|
||||
//! flip in the update memory region.
|
||||
static const ReturnValue_t UPDATE_CRC_FAILURE = MAKE_RETURN_CODE(0xB2);
|
||||
//! [EXPORT] : [COMMENT] Supervisor helper task ist currently executing a command (wait until
|
||||
//! helper tas has finished or interrupt by sending the terminate command)
|
||||
static const ReturnValue_t SUPV_HELPER_EXECUTING = MAKE_RETURN_CODE(0xB3);
|
||||
};
|
||||
|
||||
#endif /* SUPV_RETURN_VALUES_IF_H_ */
|
@ -1,7 +1,4 @@
|
||||
target_sources(${OBSW_NAME} PRIVATE
|
||||
PlocSupervisorHandler.cpp
|
||||
PlocMemoryDumper.cpp
|
||||
PlocMPSoCHandler.cpp
|
||||
PlocMPSoCHelper.cpp
|
||||
PlocSupvHelper.cpp
|
||||
)
|
||||
target_sources(
|
||||
${OBSW_NAME}
|
||||
PRIVATE PlocSupervisorHandler.cpp PlocMemoryDumper.cpp PlocMPSoCHandler.cpp
|
||||
PlocMPSoCHelper.cpp PlocSupvUartMan.cpp)
|
||||
|
@ -19,17 +19,19 @@ PlocMPSoCHandler::PlocMPSoCHandler(object_id_t objectId, object_id_t uartComIFid
|
||||
eventQueue = QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5);
|
||||
commandActionHelperQueue =
|
||||
QueueFactory::instance()->createMessageQueue(EventMessage::EVENT_MESSAGE_SIZE * 5);
|
||||
spParams.maxSize = sizeof(commandBuffer);
|
||||
spParams.buf = commandBuffer;
|
||||
}
|
||||
|
||||
PlocMPSoCHandler::~PlocMPSoCHandler() {}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::initialize() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = DeviceHandlerBase::initialize();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uartComIf = dynamic_cast<UartComIF*>(communicationInterface);
|
||||
uartComIf = dynamic_cast<SerialComIF*>(communicationInterface);
|
||||
if (uartComIf == nullptr) {
|
||||
sif::warning << "PlocMPSoCHandler::initialize: Invalid uart com if" << std::endl;
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
@ -44,13 +46,13 @@ ReturnValue_t PlocMPSoCHandler::initialize() {
|
||||
;
|
||||
}
|
||||
result = manager->registerListener(eventQueue->getId());
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = manager->subscribeToEventRange(
|
||||
eventQueue->getId(), event::getEventId(PlocMPSoCHelper::MPSOC_FLASH_WRITE_FAILED),
|
||||
event::getEventId(PlocMPSoCHelper::MPSOC_FLASH_WRITE_SUCCESSFUL));
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "PlocMPSoCHandler::initialize: Failed to subscribe to events from "
|
||||
" ploc mpsoc helper"
|
||||
@ -60,13 +62,13 @@ ReturnValue_t PlocMPSoCHandler::initialize() {
|
||||
}
|
||||
|
||||
result = plocMPSoCHelper->setComIF(communicationInterface);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
plocMPSoCHelper->setComCookie(comCookie);
|
||||
plocMPSoCHelper->setSequenceCount(&sequenceCount);
|
||||
result = commandActionHelper.initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
return result;
|
||||
@ -74,7 +76,7 @@ ReturnValue_t PlocMPSoCHandler::initialize() {
|
||||
|
||||
void PlocMPSoCHandler::performOperationHook() {
|
||||
EventMessage event;
|
||||
for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == RETURN_OK;
|
||||
for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK;
|
||||
result = eventQueue->receiveMessage(&event)) {
|
||||
switch (event.getMessageId()) {
|
||||
case EventMessage::EVENT_MESSAGE:
|
||||
@ -88,9 +90,9 @@ void PlocMPSoCHandler::performOperationHook() {
|
||||
}
|
||||
CommandMessage message;
|
||||
for (ReturnValue_t result = commandActionHelperQueue->receiveMessage(&message);
|
||||
result == RETURN_OK; result = commandActionHelperQueue->receiveMessage(&message)) {
|
||||
result == returnvalue::OK; result = commandActionHelperQueue->receiveMessage(&message)) {
|
||||
result = commandActionHelper.handleReply(&message);
|
||||
if (result == RETURN_OK) {
|
||||
if (result == returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -98,7 +100,7 @@ void PlocMPSoCHandler::performOperationHook() {
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
switch (actionId) {
|
||||
case mpsoc::SET_UART_TX_TRISTATE: {
|
||||
uartIsolatorSwitch.pullLow();
|
||||
@ -125,12 +127,12 @@ ReturnValue_t PlocMPSoCHandler::executeAction(ActionId_t actionId, MessageQueueI
|
||||
}
|
||||
mpsoc::FlashWritePusCmd flashWritePusCmd;
|
||||
result = flashWritePusCmd.extractFields(data, size);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = plocMPSoCHelper->startFlashWrite(flashWritePusCmd.getObcFile(),
|
||||
flashWritePusCmd.getMPSoCFile());
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
plocMPSoCHelperExecuting = true;
|
||||
@ -182,12 +184,14 @@ void PlocMPSoCHandler::doShutDown() {
|
||||
powerState = PowerState::SHUTDOWN;
|
||||
break;
|
||||
case PowerState::OFF:
|
||||
sequenceCount = 0;
|
||||
setMode(_MODE_POWER_DOWN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#else
|
||||
sequenceCount = 0;
|
||||
uartIsolatorSwitch.pullLow();
|
||||
setMode(_MODE_POWER_DOWN);
|
||||
powerState = PowerState::OFF;
|
||||
@ -206,7 +210,8 @@ ReturnValue_t PlocMPSoCHandler::buildTransitionDeviceCommand(DeviceCommandId_t*
|
||||
ReturnValue_t PlocMPSoCHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
||||
const uint8_t* commandData,
|
||||
size_t commandDataLen) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
spParams.buf = commandBuffer;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
switch (deviceCommand) {
|
||||
case (mpsoc::TC_MEM_WRITE): {
|
||||
result = prepareTcMemWrite(commandData, commandDataLen);
|
||||
@ -259,7 +264,7 @@ ReturnValue_t PlocMPSoCHandler::buildCommandFromCommand(DeviceCommandId_t device
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == RETURN_OK) {
|
||||
if (result == returnvalue::OK) {
|
||||
/**
|
||||
* Flushing the receive buffer to make sure there are no data left from a faulty reply.
|
||||
*/
|
||||
@ -286,16 +291,23 @@ void PlocMPSoCHandler::fillCommandAndReplyMap() {
|
||||
this->insertInReplyMap(mpsoc::ACK_REPORT, 3, nullptr, mpsoc::SIZE_ACK_REPORT);
|
||||
this->insertInReplyMap(mpsoc::EXE_REPORT, 50, nullptr, mpsoc::SIZE_EXE_REPORT);
|
||||
this->insertInReplyMap(mpsoc::TM_MEMORY_READ_REPORT, 2, nullptr, mpsoc::SIZE_TM_MEM_READ_REPORT);
|
||||
this->insertInReplyMap(mpsoc::TM_CAM_CMD_RPT, 50, nullptr, SpacePacket::PACKET_MAX_SIZE);
|
||||
this->insertInReplyMap(mpsoc::TM_CAM_CMD_RPT, 50, nullptr, mpsoc::SP_MAX_SIZE);
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::scanForReply(const uint8_t* start, size_t remainingSize,
|
||||
DeviceCommandId_t* foundId, size_t* foundLen) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
SpacePacket spacePacket;
|
||||
std::memcpy(spacePacket.getWholeData(), start, remainingSize);
|
||||
uint16_t apid = spacePacket.getAPID();
|
||||
SpacePacketReader spacePacket;
|
||||
spacePacket.setReadOnlyData(start, remainingSize);
|
||||
if (spacePacket.isNull()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
auto res = spacePacket.checkSize();
|
||||
if (res != returnvalue::OK) {
|
||||
return res;
|
||||
}
|
||||
uint16_t apid = spacePacket.getApid();
|
||||
|
||||
switch (apid) {
|
||||
case (mpsoc::apid::ACK_SUCCESS):
|
||||
@ -311,7 +323,7 @@ ReturnValue_t PlocMPSoCHandler::scanForReply(const uint8_t* start, size_t remain
|
||||
*foundId = mpsoc::TM_MEMORY_READ_REPORT;
|
||||
break;
|
||||
case (mpsoc::apid::TM_CAM_CMD_RPT):
|
||||
*foundLen = spacePacket.getFullSize();
|
||||
*foundLen = spacePacket.getFullPacketLen();
|
||||
tmCamCmdRpt.rememberSpacePacketSize = *foundLen;
|
||||
*foundId = mpsoc::TM_CAM_CMD_RPT;
|
||||
break;
|
||||
@ -330,17 +342,18 @@ ReturnValue_t PlocMPSoCHandler::scanForReply(const uint8_t* start, size_t remain
|
||||
}
|
||||
}
|
||||
|
||||
sequenceCount++;
|
||||
uint16_t recvSeqCnt = (*(start + 2) << 8 | *(start + 3)) & PACKET_SEQUENCE_COUNT_MASK;
|
||||
if (recvSeqCnt != sequenceCount) {
|
||||
triggerEvent(MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH, sequenceCount, recvSeqCnt);
|
||||
sequenceCount = recvSeqCnt;
|
||||
}
|
||||
// This sequence count ping pong does not make any sense but it is how the MPSoC expects it.
|
||||
sequenceCount++;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
switch (id) {
|
||||
case mpsoc::ACK_REPORT: {
|
||||
@ -374,7 +387,7 @@ uint32_t PlocMPSoCHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo)
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PlocMPSoCHandler::handleEvent(EventMessage* eventMessage) {
|
||||
@ -392,31 +405,27 @@ void PlocMPSoCHandler::handleEvent(EventMessage* eventMessage) {
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::prepareTcMemWrite(const uint8_t* commandData,
|
||||
size_t commandDataLen) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
sequenceCount++;
|
||||
mpsoc::TcMemWrite tcMemWrite(sequenceCount);
|
||||
result = tcMemWrite.createPacket(commandData, commandDataLen);
|
||||
if (result != RETURN_OK) {
|
||||
sequenceCount--;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
mpsoc::TcMemWrite tcMemWrite(spParams, sequenceCount);
|
||||
result = tcMemWrite.buildPacket(commandData, commandDataLen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
copyToCommandBuffer(&tcMemWrite);
|
||||
return RETURN_OK;
|
||||
finishTcPrep(tcMemWrite.getFullPacketLen());
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::prepareTcMemRead(const uint8_t* commandData,
|
||||
size_t commandDataLen) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
sequenceCount++;
|
||||
mpsoc::TcMemRead tcMemRead(sequenceCount);
|
||||
result = tcMemRead.createPacket(commandData, commandDataLen);
|
||||
if (result != RETURN_OK) {
|
||||
sequenceCount--;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
mpsoc::TcMemRead tcMemRead(spParams, sequenceCount);
|
||||
result = tcMemRead.buildPacket(commandData, commandDataLen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
copyToCommandBuffer(&tcMemRead);
|
||||
finishTcPrep(tcMemRead.getFullPacketLen());
|
||||
tmMemReadReport.rememberRequestedSize = tcMemRead.getMemLen() * 4 + TmMemReadReport::FIX_SIZE;
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::prepareTcFlashDelete(const uint8_t* commandData,
|
||||
@ -424,155 +433,126 @@ ReturnValue_t PlocMPSoCHandler::prepareTcFlashDelete(const uint8_t* commandData,
|
||||
if (commandDataLen > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) {
|
||||
return MPSoCReturnValuesIF::NAME_TOO_LONG;
|
||||
}
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
sequenceCount++;
|
||||
mpsoc::TcFlashDelete tcFlashDelete(sequenceCount);
|
||||
result = tcFlashDelete.createPacket(
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
mpsoc::TcFlashDelete tcFlashDelete(spParams, sequenceCount);
|
||||
result = tcFlashDelete.buildPacket(
|
||||
std::string(reinterpret_cast<const char*>(commandData), commandDataLen));
|
||||
if (result != RETURN_OK) {
|
||||
sequenceCount--;
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
copyToCommandBuffer(&tcFlashDelete);
|
||||
return RETURN_OK;
|
||||
finishTcPrep(tcFlashDelete.getFullPacketLen());
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::prepareTcReplayStart(const uint8_t* commandData,
|
||||
size_t commandDataLen) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
sequenceCount++;
|
||||
mpsoc::TcReplayStart tcReplayStart(sequenceCount);
|
||||
result = tcReplayStart.createPacket(commandData, commandDataLen);
|
||||
if (result != RETURN_OK) {
|
||||
sequenceCount--;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
mpsoc::TcReplayStart tcReplayStart(spParams, sequenceCount);
|
||||
result = tcReplayStart.buildPacket(commandData, commandDataLen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
copyToCommandBuffer(&tcReplayStart);
|
||||
return RETURN_OK;
|
||||
finishTcPrep(tcReplayStart.getFullPacketLen());
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::prepareTcReplayStop() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
sequenceCount++;
|
||||
mpsoc::TcReplayStop tcReplayStop(sequenceCount);
|
||||
result = tcReplayStop.createPacket();
|
||||
if (result != RETURN_OK) {
|
||||
sequenceCount--;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
mpsoc::TcReplayStop tcReplayStop(spParams, sequenceCount);
|
||||
result = tcReplayStop.buildPacket();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
copyToCommandBuffer(&tcReplayStop);
|
||||
return RETURN_OK;
|
||||
finishTcPrep(tcReplayStop.getFullPacketLen());
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::prepareTcDownlinkPwrOn(const uint8_t* commandData,
|
||||
size_t commandDataLen) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
sequenceCount++;
|
||||
mpsoc::TcDownlinkPwrOn tcDownlinkPwrOn(sequenceCount);
|
||||
result = tcDownlinkPwrOn.createPacket(commandData, commandDataLen);
|
||||
if (result != RETURN_OK) {
|
||||
sequenceCount--;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
mpsoc::TcDownlinkPwrOn tcDownlinkPwrOn(spParams, sequenceCount);
|
||||
result = tcDownlinkPwrOn.buildPacket(commandData, commandDataLen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
copyToCommandBuffer(&tcDownlinkPwrOn);
|
||||
return RETURN_OK;
|
||||
finishTcPrep(tcDownlinkPwrOn.getFullPacketLen());
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::prepareTcDownlinkPwrOff() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
sequenceCount++;
|
||||
mpsoc::TcDownlinkPwrOff tcDownlinkPwrOff(sequenceCount);
|
||||
result = tcDownlinkPwrOff.createPacket();
|
||||
if (result != RETURN_OK) {
|
||||
sequenceCount--;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
mpsoc::TcDownlinkPwrOff tcDownlinkPwrOff(spParams, sequenceCount);
|
||||
result = tcDownlinkPwrOff.buildPacket();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
copyToCommandBuffer(&tcDownlinkPwrOff);
|
||||
return RETURN_OK;
|
||||
finishTcPrep(tcDownlinkPwrOff.getFullPacketLen());
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::prepareTcReplayWriteSequence(const uint8_t* commandData,
|
||||
size_t commandDataLen) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
sequenceCount++;
|
||||
mpsoc::TcReplayWriteSeq tcReplayWriteSeq(sequenceCount);
|
||||
result = tcReplayWriteSeq.createPacket(commandData, commandDataLen);
|
||||
if (result != RETURN_OK) {
|
||||
sequenceCount--;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
mpsoc::TcReplayWriteSeq tcReplayWriteSeq(spParams, sequenceCount);
|
||||
result = tcReplayWriteSeq.buildPacket(commandData, commandDataLen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
copyToCommandBuffer(&tcReplayWriteSeq);
|
||||
return RETURN_OK;
|
||||
finishTcPrep(tcReplayWriteSeq.getFullPacketLen());
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::prepareTcModeReplay() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
sequenceCount++;
|
||||
mpsoc::TcModeReplay tcModeReplay(sequenceCount);
|
||||
result = tcModeReplay.createPacket();
|
||||
if (result != RETURN_OK) {
|
||||
sequenceCount--;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
mpsoc::TcModeReplay tcModeReplay(spParams, sequenceCount);
|
||||
result = tcModeReplay.buildPacket();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
memcpy(commandBuffer, tcModeReplay.getWholeData(), tcModeReplay.getFullSize());
|
||||
rawPacket = commandBuffer;
|
||||
rawPacketLen = tcModeReplay.getFullSize();
|
||||
nextReplyId = mpsoc::ACK_REPORT;
|
||||
return RETURN_OK;
|
||||
finishTcPrep(tcModeReplay.getFullPacketLen());
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::prepareTcModeIdle() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
sequenceCount++;
|
||||
mpsoc::TcModeIdle tcModeIdle(sequenceCount);
|
||||
result = tcModeIdle.createPacket();
|
||||
if (result != RETURN_OK) {
|
||||
sequenceCount--;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
mpsoc::TcModeIdle tcModeIdle(spParams, sequenceCount);
|
||||
result = tcModeIdle.buildPacket();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
memcpy(commandBuffer, tcModeIdle.getWholeData(), tcModeIdle.getFullSize());
|
||||
rawPacket = commandBuffer;
|
||||
rawPacketLen = tcModeIdle.getFullSize();
|
||||
nextReplyId = mpsoc::ACK_REPORT;
|
||||
return RETURN_OK;
|
||||
finishTcPrep(tcModeIdle.getFullPacketLen());
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::prepareTcCamCmdSend(const uint8_t* commandData,
|
||||
size_t commandDataLen) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
sequenceCount++;
|
||||
mpsoc::TcCamcmdSend tcCamCmdSend(sequenceCount);
|
||||
result = tcCamCmdSend.createPacket(commandData, commandDataLen);
|
||||
if (result != RETURN_OK) {
|
||||
sequenceCount--;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
mpsoc::TcCamcmdSend tcCamCmdSend(spParams, sequenceCount);
|
||||
result = tcCamCmdSend.buildPacket(commandData, commandDataLen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
copyToCommandBuffer(&tcCamCmdSend);
|
||||
finishTcPrep(tcCamCmdSend.getFullPacketLen());
|
||||
nextReplyId = mpsoc::ACK_REPORT;
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PlocMPSoCHandler::copyToCommandBuffer(mpsoc::TcBase* tc) {
|
||||
if (tc == nullptr) {
|
||||
sif::debug << "PlocMPSoCHandler::copyToCommandBuffer: Invalid TC" << std::endl;
|
||||
}
|
||||
memcpy(commandBuffer, tc->getWholeData(), tc->getFullSize());
|
||||
rawPacket = commandBuffer;
|
||||
rawPacketLen = tc->getFullSize();
|
||||
void PlocMPSoCHandler::finishTcPrep(size_t packetLen) {
|
||||
nextReplyId = mpsoc::ACK_REPORT;
|
||||
rawPacket = commandBuffer;
|
||||
rawPacketLen = packetLen;
|
||||
sequenceCount++;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::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);
|
||||
if (receivedCrc != recalculatedCrc) {
|
||||
if (CRC::crc16ccitt(start, foundLen) != 0) {
|
||||
return MPSoCReturnValuesIF::CRC_FAILURE;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::handleAckReport(const uint8_t* data) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
result = verifyPacket(data, mpsoc::SIZE_ACK_REPORT);
|
||||
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
|
||||
@ -589,14 +569,14 @@ ReturnValue_t PlocMPSoCHandler::handleAckReport(const uint8_t* data) {
|
||||
|
||||
switch (apid) {
|
||||
case mpsoc::apid::ACK_FAILURE: {
|
||||
// TODO: Interpretation of status field in acknowledgment report
|
||||
sif::debug << "PlocMPSoCHandler::handleAckReport: Received Ack failure report" << std::endl;
|
||||
DeviceCommandId_t commandId = getPendingCommand();
|
||||
uint16_t status = getStatus(data);
|
||||
printStatus(data);
|
||||
if (commandId != DeviceHandlerIF::NO_COMMAND_ID) {
|
||||
triggerEvent(ACK_FAILURE, commandId, status);
|
||||
}
|
||||
sendFailureReport(mpsoc::ACK_REPORT, MPSoCReturnValuesIF::RECEIVED_ACK_FAILURE);
|
||||
sendFailureReport(mpsoc::ACK_REPORT, status);
|
||||
disableAllReplies();
|
||||
nextReplyId = mpsoc::NONE;
|
||||
result = IGNORE_REPLY_DATA;
|
||||
@ -608,7 +588,7 @@ ReturnValue_t PlocMPSoCHandler::handleAckReport(const uint8_t* data) {
|
||||
}
|
||||
default: {
|
||||
sif::debug << "PlocMPSoCHandler::handleAckReport: Invalid APID in Ack report" << std::endl;
|
||||
result = RETURN_FAILED;
|
||||
result = returnvalue::FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -617,7 +597,7 @@ ReturnValue_t PlocMPSoCHandler::handleAckReport(const uint8_t* data) {
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::handleExecutionReport(const uint8_t* data) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
result = verifyPacket(data, mpsoc::SIZE_EXE_REPORT);
|
||||
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
|
||||
@ -651,7 +631,7 @@ ReturnValue_t PlocMPSoCHandler::handleExecutionReport(const uint8_t* data) {
|
||||
}
|
||||
default: {
|
||||
sif::warning << "PlocMPSoCHandler::handleExecutionReport: Unknown APID" << std::endl;
|
||||
result = RETURN_FAILED;
|
||||
result = returnvalue::FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -660,7 +640,7 @@ ReturnValue_t PlocMPSoCHandler::handleExecutionReport(const uint8_t* data) {
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::handleMemoryReadReport(const uint8_t* data) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = verifyPacket(data, tmMemReadReport.rememberRequestedSize);
|
||||
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
|
||||
sif::warning << "PlocMPSoCHandler::handleMemoryReadReport: Memory read report has invalid crc"
|
||||
@ -676,31 +656,31 @@ ReturnValue_t PlocMPSoCHandler::handleMemoryReadReport(const uint8_t* data) {
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::handleCamCmdRpt(const uint8_t* data) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
SpacePacket packet;
|
||||
std::memcpy(packet.getWholeData(), data, tmCamCmdRpt.rememberSpacePacketSize);
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = verifyPacket(data, tmCamCmdRpt.rememberSpacePacketSize);
|
||||
if (result == MPSoCReturnValuesIF::CRC_FAILURE) {
|
||||
sif::warning << "PlocMPSoCHandler::handleCamCmdRpt: CRC failure" << std::endl;
|
||||
}
|
||||
const uint8_t* dataFieldPtr = data + mpsoc::SPACE_PACKET_HEADER_SIZE;
|
||||
SpacePacketReader packetReader(data, tmCamCmdRpt.rememberSpacePacketSize);
|
||||
const uint8_t* dataFieldPtr = data + mpsoc::SPACE_PACKET_HEADER_SIZE + sizeof(uint16_t);
|
||||
std::string camCmdRptMsg(
|
||||
reinterpret_cast<const char*>(dataFieldPtr),
|
||||
tmCamCmdRpt.rememberSpacePacketSize - mpsoc::SPACE_PACKET_HEADER_SIZE - 3);
|
||||
tmCamCmdRpt.rememberSpacePacketSize - mpsoc::SPACE_PACKET_HEADER_SIZE - sizeof(uint16_t) - 3);
|
||||
#if OBSW_DEBUG_PLOC_MPSOC == 1
|
||||
uint8_t ackValue = *(packet.getPacketData() + packet.getPacketDataLength() - 2);
|
||||
uint8_t ackValue = *(packetReader.getFullData() + packetReader.getFullPacketLen() - 2);
|
||||
sif::info << "PlocMPSoCHandler: CamCmdRpt message: " << camCmdRptMsg << std::endl;
|
||||
sif::info << "PlocMPSoCHandler: CamCmdRpt Ack value: 0x" << std::hex
|
||||
<< static_cast<unsigned int>(ackValue) << std::endl;
|
||||
#endif /* OBSW_DEBUG_PLOC_MPSOC == 1 */
|
||||
handleDeviceTM(packet.getPacketData(), packet.getPacketDataLength() - 1, mpsoc::TM_CAM_CMD_RPT);
|
||||
handleDeviceTM(packetReader.getPacketData() + sizeof(uint16_t),
|
||||
packetReader.getPacketDataLen() - 1, mpsoc::TM_CAM_CMD_RPT);
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command,
|
||||
uint8_t expectedReplies, bool useAlternateId,
|
||||
DeviceCommandId_t alternateReplyID) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
uint8_t enabledReplies = 0;
|
||||
|
||||
@ -720,7 +700,7 @@ ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator
|
||||
enabledReplies = 3;
|
||||
result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true,
|
||||
mpsoc::TM_MEMORY_READ_REPORT);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Reply with id "
|
||||
<< mpsoc::TM_MEMORY_READ_REPORT << " not in replyMap" << std::endl;
|
||||
return result;
|
||||
@ -731,7 +711,7 @@ ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator
|
||||
enabledReplies = 3;
|
||||
result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true,
|
||||
mpsoc::TM_CAM_CMD_RPT);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Reply with id "
|
||||
<< mpsoc::TM_CAM_CMD_RPT << " not in replyMap" << std::endl;
|
||||
return result;
|
||||
@ -751,14 +731,14 @@ ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator
|
||||
*/
|
||||
result =
|
||||
DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, mpsoc::ACK_REPORT);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Reply with id " << mpsoc::ACK_REPORT
|
||||
<< " not in replyMap" << std::endl;
|
||||
}
|
||||
|
||||
result =
|
||||
DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true, mpsoc::EXE_REPORT);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::debug << "PlocMPSoCHandler::enableReplyInReplyMap: Reply with id " << mpsoc::EXE_REPORT
|
||||
<< " not in replyMap" << std::endl;
|
||||
}
|
||||
@ -781,7 +761,7 @@ ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator
|
||||
break;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PlocMPSoCHandler::setNextReplyId() {
|
||||
@ -820,7 +800,7 @@ size_t PlocMPSoCHandler::getNextReplyLength(DeviceCommandId_t commandId) {
|
||||
case mpsoc::TM_CAM_CMD_RPT:
|
||||
// Read acknowledgment, camera and execution report in one go because length of camera
|
||||
// report is not fixed
|
||||
replyLen = SpacePacket::PACKET_MAX_SIZE;
|
||||
replyLen = mpsoc::SP_MAX_SIZE;
|
||||
break;
|
||||
default: {
|
||||
replyLen = iter->second.replyLen;
|
||||
@ -838,9 +818,9 @@ size_t PlocMPSoCHandler::getNextReplyLength(DeviceCommandId_t commandId) {
|
||||
ReturnValue_t PlocMPSoCHandler::doSendReadHook() {
|
||||
// Prevent DHB from polling UART during commands executed by the mpsoc helper task
|
||||
if (plocMPSoCHelperExecuting) {
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
MessageQueueIF* PlocMPSoCHandler::getCommandQueuePtr() { return commandActionHelperQueue; }
|
||||
@ -901,7 +881,7 @@ void PlocMPSoCHandler::completionFailedReceived(ActionId_t actionId, ReturnValue
|
||||
|
||||
void PlocMPSoCHandler::handleDeviceTM(const uint8_t* data, size_t dataSize,
|
||||
DeviceCommandId_t replyId) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
if (wiretappingMode == RAW) {
|
||||
/* Data already sent in doGetRead() */
|
||||
@ -920,7 +900,7 @@ void PlocMPSoCHandler::handleDeviceTM(const uint8_t* data, size_t dataSize,
|
||||
}
|
||||
|
||||
result = actionHelper.reportData(queueId, replyId, data, dataSize);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::debug << "PlocMPSoCHandler::handleDeviceTM: Failed to report data" << std::endl;
|
||||
}
|
||||
}
|
||||
@ -997,7 +977,7 @@ void PlocMPSoCHandler::disableExeReportReply() {
|
||||
|
||||
void PlocMPSoCHandler::printStatus(const uint8_t* data) {
|
||||
uint16_t status = *(data + STATUS_OFFSET) << 8 | *(data + STATUS_OFFSET + 1);
|
||||
sif::info << "Verification report status: 0x" << std::hex << status << std::endl;
|
||||
sif::info << "Verification report status: " << getStatusString(status) << std::endl;
|
||||
}
|
||||
|
||||
uint16_t PlocMPSoCHandler::getStatus(const uint8_t* data) {
|
||||
@ -1036,3 +1016,79 @@ void PlocMPSoCHandler::handleActionCommandFailure(ActionId_t actionId) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
std::string PlocMPSoCHandler::getStatusString(uint16_t status) {
|
||||
switch (status) {
|
||||
case (mpsoc::status_code::UNKNOWN_APID): {
|
||||
return "Unknown APID";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::INCORRECT_LENGTH): {
|
||||
return "Incorrect length";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::INCORRECT_CRC): {
|
||||
return "Incorrect crc";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::INCORRECT_PKT_SEQ_CNT): {
|
||||
return "Incorrect packet sequence count";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::TC_NOT_ALLOWED_IN_MODE): {
|
||||
return "TC not allowed in this mode";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::TC_EXEUTION_DISABLED): {
|
||||
return "TC execution disabled";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_MOUNT_FAILED): {
|
||||
return "Flash mount failed";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_FILE_ALREADY_CLOSED): {
|
||||
return "Flash file already closed";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_FILE_NOT_OPEN): {
|
||||
return "Flash file not open";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_UNMOUNT_FAILED): {
|
||||
return "Flash unmount failed";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::HEAP_ALLOCATION_FAILED): {
|
||||
return "Heap allocation failed";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::INVALID_PARAMETER): {
|
||||
return "Invalid parameter";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::NOT_INITIALIZED): {
|
||||
return "Not initialized";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::REBOOT_IMMINENT): {
|
||||
return "Reboot imminent";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::CORRUPT_DATA): {
|
||||
return "Corrupt data";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_CORRECTABLE_MISMATCH): {
|
||||
return "Flash correctable mismatch";
|
||||
break;
|
||||
}
|
||||
case (mpsoc::status_code::FLASH_UNCORRECTABLE_MISMATCH): {
|
||||
return "Flash uncorrectable mismatch";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
@ -8,10 +8,9 @@
|
||||
#include "fsfw/action/CommandsActionsIF.h"
|
||||
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/tmtcpacket/SpacePacket.h"
|
||||
#include "fsfw/tmtcservices/SourceSequenceCounter.h"
|
||||
#include "fsfw_hal/linux/gpio/Gpio.h"
|
||||
#include "fsfw_hal/linux/uart/UartComIF.h"
|
||||
#include "fsfw_hal/linux/serial/SerialComIF.h"
|
||||
#include "linux/devices/devicedefinitions/MPSoCReturnValuesIF.h"
|
||||
#include "linux/devices/devicedefinitions/PlocMPSoCDefinitions.h"
|
||||
#include "linux/devices/devicedefinitions/PlocSupervisorDefinitions.h"
|
||||
@ -108,10 +107,11 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
MessageQueueIF* eventQueue = nullptr;
|
||||
MessageQueueIF* commandActionHelperQueue = nullptr;
|
||||
|
||||
SourceSequenceCounter sequenceCount =
|
||||
SourceSequenceCounter(SpacePacketBase::LIMIT_SEQUENCE_COUNT - 1);
|
||||
SourceSequenceCounter sequenceCount = SourceSequenceCounter(0);
|
||||
|
||||
uint8_t commandBuffer[mpsoc::MAX_COMMAND_SIZE];
|
||||
SpacePacketCreator creator;
|
||||
ploc::SpTcParams spParams = ploc::SpTcParams(creator);
|
||||
|
||||
/**
|
||||
* This variable is used to store the id of the next reply to receive. This is necessary
|
||||
@ -120,7 +120,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
*/
|
||||
DeviceCommandId_t nextReplyId = mpsoc::NONE;
|
||||
|
||||
UartComIF* uartComIf = nullptr;
|
||||
SerialComIF* uartComIf = nullptr;
|
||||
|
||||
PlocMPSoCHelper* plocMPSoCHelper = nullptr;
|
||||
Gpio uartIsolatorSwitch;
|
||||
@ -145,7 +145,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
|
||||
struct TelemetryBuffer {
|
||||
uint16_t length = 0;
|
||||
uint8_t buffer[SpacePacket::PACKET_MAX_SIZE];
|
||||
uint8_t buffer[mpsoc::SP_MAX_SIZE];
|
||||
};
|
||||
|
||||
TelemetryBuffer tmBuffer;
|
||||
@ -169,10 +169,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
ReturnValue_t prepareTcReplayWriteSequence(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcCamCmdSend(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareTcModeIdle();
|
||||
/**
|
||||
* @brief Copies space packet into command buffer
|
||||
*/
|
||||
void copyToCommandBuffer(mpsoc::TcBase* tc);
|
||||
void finishTcPrep(size_t packetLen);
|
||||
|
||||
/**
|
||||
* @brief This function checks the crc of the received PLOC reply.
|
||||
@ -180,7 +177,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
* @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.
|
||||
* @return returnvalue::OK if CRC is ok, otherwise CRC_FAILURE.
|
||||
*/
|
||||
ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen);
|
||||
|
||||
@ -189,7 +186,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
*
|
||||
* @param data Pointer to the data holding the acknowledgment report.
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise an error code.
|
||||
* @return returnvalue::OK if successful, otherwise an error code.
|
||||
*/
|
||||
ReturnValue_t handleAckReport(const uint8_t* data);
|
||||
|
||||
@ -198,7 +195,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
*
|
||||
* @param data Pointer to the received data packet.
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise an error code.
|
||||
* @return returnvalue::OK if successful, otherwise an error code.
|
||||
*/
|
||||
ReturnValue_t handleExecutionReport(const uint8_t* data);
|
||||
|
||||
@ -207,7 +204,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
*
|
||||
* @param data Pointer to the data buffer holding the memory read report.
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise an error code.
|
||||
* @return returnvalue::OK if successful, otherwise an error code.
|
||||
*/
|
||||
ReturnValue_t handleMemoryReadReport(const uint8_t* data);
|
||||
|
||||
@ -260,6 +257,8 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF {
|
||||
uint16_t getStatus(const uint8_t* data);
|
||||
|
||||
void handleActionCommandFailure(ActionId_t actionId);
|
||||
|
||||
std::string getStatusString(uint16_t status);
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_ */
|
||||
|
@ -3,14 +3,18 @@
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/memory/FilesystemHelper.h"
|
||||
#include "bsp_q7s/fs/FilesystemHelper.h"
|
||||
#endif
|
||||
|
||||
#include "mission/utility/Timestamp.h"
|
||||
|
||||
PlocMPSoCHelper::PlocMPSoCHelper(object_id_t objectId) : SystemObject(objectId) {}
|
||||
using namespace ploc;
|
||||
|
||||
PlocMPSoCHelper::PlocMPSoCHelper(object_id_t objectId) : SystemObject(objectId) {
|
||||
spParams.buf = commandBuffer;
|
||||
spParams.maxSize = sizeof(commandBuffer);
|
||||
}
|
||||
|
||||
PlocMPSoCHelper::~PlocMPSoCHelper() {}
|
||||
|
||||
@ -19,16 +23,19 @@ ReturnValue_t PlocMPSoCHelper::initialize() {
|
||||
sdcMan = SdCardManager::instance();
|
||||
if (sdcMan == nullptr) {
|
||||
sif::warning << "PlocMPSoCHelper::initialize: Invalid SD Card Manager" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
#endif
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::performOperation(uint8_t operationCode) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
semaphore.acquire();
|
||||
while (true) {
|
||||
#if OBSW_THREAD_TRACING == 1
|
||||
trace::threadTrace(opCounter, "PLOC MPSOC Helper");
|
||||
#endif
|
||||
switch (internalState) {
|
||||
case InternalState::IDLE: {
|
||||
semaphore.acquire();
|
||||
@ -36,7 +43,7 @@ ReturnValue_t PlocMPSoCHelper::performOperation(uint8_t operationCode) {
|
||||
}
|
||||
case InternalState::FLASH_WRITE: {
|
||||
result = performFlashWrite();
|
||||
if (result == RETURN_OK) {
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL);
|
||||
} else {
|
||||
triggerEvent(MPSOC_FLASH_WRITE_FAILED);
|
||||
@ -52,12 +59,12 @@ ReturnValue_t PlocMPSoCHelper::performOperation(uint8_t operationCode) {
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::setComIF(DeviceCommunicationIF* communicationInterface_) {
|
||||
uartComIF = dynamic_cast<UartComIF*>(communicationInterface_);
|
||||
uartComIF = dynamic_cast<SerialComIF*>(communicationInterface_);
|
||||
if (uartComIF == nullptr) {
|
||||
sif::warning << "PlocMPSoCHelper::initialize: Invalid uart com if" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PlocMPSoCHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
|
||||
@ -67,14 +74,14 @@ void PlocMPSoCHelper::setSequenceCount(SourceSequenceCounter* sequenceCount_) {
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::startFlashWrite(std::string obcFile, std::string mpsocFile) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
#ifdef XIPHOS_Q7S
|
||||
result = FilesystemHelper::checkPath(obcFile);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = FilesystemHelper::fileExists(mpsocFile);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
@ -82,7 +89,7 @@ ReturnValue_t PlocMPSoCHelper::startFlashWrite(std::string obcFile, std::string
|
||||
if (not std::filesystem::exists(obcFile)) {
|
||||
sif::warning << "PlocMPSoCHelper::startFlashWrite: File " << obcFile << "does not exist"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -90,15 +97,16 @@ ReturnValue_t PlocMPSoCHelper::startFlashWrite(std::string obcFile, std::string
|
||||
flashWrite.mpsocFile = mpsocFile;
|
||||
internalState = InternalState::FLASH_WRITE;
|
||||
result = resetHelper();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::resetHelper() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
semaphore.release();
|
||||
spParams.buf = commandBuffer;
|
||||
terminate = false;
|
||||
result = uartComIF->flushUartRxBuffer(comCookie);
|
||||
return result;
|
||||
@ -107,9 +115,9 @@ ReturnValue_t PlocMPSoCHelper::resetHelper() {
|
||||
void PlocMPSoCHelper::stopProcess() { terminate = true; }
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::performFlashWrite() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = flashfopen();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint8_t tempData[mpsoc::MAX_DATA_SIZE];
|
||||
@ -122,7 +130,7 @@ ReturnValue_t PlocMPSoCHelper::performFlashWrite() {
|
||||
size_t bytesRead = 0;
|
||||
while (remainingSize > 0) {
|
||||
if (terminate) {
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
if (remainingSize > mpsoc::MAX_DATA_SIZE) {
|
||||
dataLength = mpsoc::MAX_DATA_SIZE;
|
||||
@ -138,71 +146,76 @@ ReturnValue_t PlocMPSoCHelper::performFlashWrite() {
|
||||
return FILE_CLOSED_ACCIDENTALLY;
|
||||
}
|
||||
(*sequenceCount)++;
|
||||
mpsoc::TcFlashWrite tc(*sequenceCount);
|
||||
tc.createPacket(tempData, dataLength);
|
||||
mpsoc::TcFlashWrite tc(spParams, *sequenceCount);
|
||||
result = tc.buildPacket(tempData, dataLength);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = handlePacketTransmission(tc);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
result = flashfclose();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::flashfopen() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
spParams.buf = commandBuffer;
|
||||
(*sequenceCount)++;
|
||||
mpsoc::FlashFopen flashFopen(*sequenceCount);
|
||||
mpsoc::FlashFopen flashFopen(spParams, *sequenceCount);
|
||||
result = flashFopen.createPacket(flashWrite.mpsocFile, mpsoc::FlashFopen::APPEND);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = handlePacketTransmission(flashFopen);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::flashfclose() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
spParams.buf = commandBuffer;
|
||||
(*sequenceCount)++;
|
||||
mpsoc::FlashFclose flashFclose(*sequenceCount);
|
||||
mpsoc::FlashFclose flashFclose(spParams, *sequenceCount);
|
||||
result = flashFclose.createPacket(flashWrite.mpsocFile);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = handlePacketTransmission(flashFclose);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::handlePacketTransmission(mpsoc::TcBase& tc) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t PlocMPSoCHelper::handlePacketTransmission(ploc::SpTcBase& tc) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = sendCommand(tc);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleAck();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleExe();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::sendCommand(mpsoc::TcBase& tc) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
result = uartComIF->sendMessage(comCookie, tc.getWholeData(), tc.getFullSize());
|
||||
if (result != RETURN_OK) {
|
||||
ReturnValue_t PlocMPSoCHelper::sendCommand(ploc::SpTcBase& tc) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = uartComIF->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen());
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PlocMPSoCHelper::sendCommand: Failed to send command" << std::endl;
|
||||
triggerEvent(MPSOC_SENDING_COMMAND_FAILED, result, static_cast<uint32_t>(internalState));
|
||||
return result;
|
||||
@ -211,18 +224,22 @@ ReturnValue_t PlocMPSoCHelper::sendCommand(mpsoc::TcBase& tc) {
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::handleAck() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
mpsoc::TmPacket tmPacket;
|
||||
result = handleTmReception(&tmPacket, mpsoc::SIZE_ACK_REPORT);
|
||||
if (result != RETURN_OK) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = handleTmReception(mpsoc::SIZE_ACK_REPORT);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint16_t apid = tmPacket.getAPID();
|
||||
SpTmReader tmPacket(tmBuf.data(), tmBuf.size());
|
||||
result = checkReceivedTm(tmPacket);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint16_t apid = tmPacket.getApid();
|
||||
if (apid != mpsoc::apid::ACK_SUCCESS) {
|
||||
handleAckApidFailure(apid);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PlocMPSoCHelper::handleAckApidFailure(uint16_t apid) {
|
||||
@ -238,18 +255,23 @@ void PlocMPSoCHelper::handleAckApidFailure(uint16_t apid) {
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::handleExe() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
mpsoc::TmPacket tmPacket;
|
||||
result = handleTmReception(&tmPacket, mpsoc::SIZE_EXE_REPORT);
|
||||
if (result != RETURN_OK) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
result = handleTmReception(mpsoc::SIZE_EXE_REPORT);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint16_t apid = tmPacket.getAPID();
|
||||
ploc::SpTmReader tmPacket(tmBuf.data(), tmBuf.size());
|
||||
result = checkReceivedTm(tmPacket);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint16_t apid = tmPacket.getApid();
|
||||
if (apid != mpsoc::apid::EXE_SUCCESS) {
|
||||
handleExeApidFailure(apid);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PlocMPSoCHelper::handleExeApidFailure(uint16_t apid) {
|
||||
@ -264,13 +286,13 @@ void PlocMPSoCHelper::handleExeApidFailure(uint16_t apid) {
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::handleTmReception(mpsoc::TmPacket* tmPacket, size_t remainingBytes) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t PlocMPSoCHelper::handleTmReception(size_t remainingBytes) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
size_t readBytes = 0;
|
||||
size_t currentBytes = 0;
|
||||
for (int retries = 0; retries < RETRIES; retries++) {
|
||||
result = receive(tmPacket->getWholeData() + readBytes, ¤tBytes, remainingBytes);
|
||||
if (result != RETURN_OK) {
|
||||
result = receive(tmBuf.data() + readBytes, ¤tBytes, remainingBytes);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
readBytes += currentBytes;
|
||||
@ -282,37 +304,49 @@ ReturnValue_t PlocMPSoCHelper::handleTmReception(mpsoc::TmPacket* tmPacket, size
|
||||
if (remainingBytes != 0) {
|
||||
sif::warning << "PlocMPSoCHelper::handleTmReception: Failed to receive reply" << std::endl;
|
||||
triggerEvent(MPSOC_MISSING_EXE, remainingBytes, static_cast<uint32_t>(internalState));
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
result = tmPacket->checkCrc();
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PlocMPSoCHelper::handleTmReception: CRC check failed" << std::endl;
|
||||
return result;
|
||||
}
|
||||
(*sequenceCount)++;
|
||||
uint16_t recvSeqCnt = tmPacket->getPacketSequenceCount();
|
||||
if (recvSeqCnt != *sequenceCount) {
|
||||
triggerEvent(MPSOC_HELPER_SEQ_CNT_MISMATCH, *sequenceCount, recvSeqCnt);
|
||||
*sequenceCount = recvSeqCnt;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::checkReceivedTm(SpTmReader& reader) {
|
||||
ReturnValue_t result = reader.checkSize();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "PlocMPSoCHelper::handleTmReception: Size check on received TM failed"
|
||||
<< std::endl;
|
||||
triggerEvent(MPSOC_TM_SIZE_ERROR);
|
||||
return result;
|
||||
}
|
||||
reader.checkCrc();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PlocMPSoCHelper::handleTmReception: CRC check failed" << std::endl;
|
||||
triggerEvent(MPSOC_TM_CRC_MISSMATCH, *sequenceCount);
|
||||
return result;
|
||||
}
|
||||
(*sequenceCount)++;
|
||||
uint16_t recvSeqCnt = reader.getSequenceCount();
|
||||
if (recvSeqCnt != *sequenceCount) {
|
||||
triggerEvent(MPSOC_HELPER_SEQ_CNT_MISMATCH, *sequenceCount, recvSeqCnt);
|
||||
*sequenceCount = recvSeqCnt;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMPSoCHelper::receive(uint8_t* data, size_t* readBytes, size_t requestBytes) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
uint8_t* buffer = nullptr;
|
||||
result = uartComIF->requestReceiveMessage(comCookie, requestBytes);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PlocMPSoCHelper::receive: Failed to request reply" << std::endl;
|
||||
triggerEvent(MPSOC_HELPER_REQUESTING_REPLY_FAILED, result,
|
||||
static_cast<uint32_t>(static_cast<uint32_t>(internalState)));
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = uartComIF->readReceivedMessage(comCookie, &buffer, readBytes);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PlocMPSoCHelper::receive: Failed to read received message" << std::endl;
|
||||
triggerEvent(MPSOC_HELPER_READING_REPLY_FAILED, result, static_cast<uint32_t>(internalState));
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (*readBytes > 0) {
|
||||
std::memcpy(data, buffer, *readBytes);
|
||||
|
@ -6,13 +6,14 @@
|
||||
#include "fsfw/devicehandlers/CookieIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/osal/linux/BinarySemaphore.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/tmtcservices/SourceSequenceCounter.h"
|
||||
#include "fsfw_hal/linux/uart/UartComIF.h"
|
||||
#include "fsfw_hal/linux/serial/SerialComIF.h"
|
||||
#include "linux/devices/devicedefinitions/PlocMPSoCDefinitions.h"
|
||||
#include "mission/trace.h"
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/memory/SdCardManager.h"
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -20,7 +21,7 @@
|
||||
* MPSoC and OBC.
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF {
|
||||
class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF {
|
||||
public:
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MPSOC_HELPER;
|
||||
|
||||
@ -67,6 +68,8 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF, public H
|
||||
//! P1: Expected sequence count
|
||||
//! P2: Received sequence count
|
||||
static const Event MPSOC_HELPER_SEQ_CNT_MISMATCH = MAKE_EVENT(11, severity::LOW);
|
||||
static const Event MPSOC_TM_SIZE_ERROR = MAKE_EVENT(12, severity::LOW);
|
||||
static const Event MPSOC_TM_CRC_MISSMATCH = MAKE_EVENT(13, severity::LOW);
|
||||
|
||||
PlocMPSoCHelper(object_id_t objectId);
|
||||
virtual ~PlocMPSoCHelper();
|
||||
@ -83,7 +86,7 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF, public H
|
||||
* @param obcFile File where to read from the data
|
||||
* @param mpsocFile The file of the MPSoC where should be written to
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise error return value
|
||||
* @return returnvalue::OK if successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t startFlashWrite(std::string obcFile, std::string mpsocFile);
|
||||
|
||||
@ -114,6 +117,10 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF, public H
|
||||
|
||||
struct FlashWrite flashWrite;
|
||||
|
||||
#if OBSW_THREAD_TRACING == 1
|
||||
uint32_t opCounter = 0;
|
||||
#endif
|
||||
|
||||
enum class InternalState { IDLE, FLASH_WRITE, FLASH_READ };
|
||||
|
||||
InternalState internalState = InternalState::IDLE;
|
||||
@ -123,6 +130,10 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF, public H
|
||||
SdCardManager* sdcMan = nullptr;
|
||||
#endif
|
||||
uint8_t commandBuffer[mpsoc::MAX_COMMAND_SIZE];
|
||||
SpacePacketCreator creator;
|
||||
ploc::SpTcParams spParams = ploc::SpTcParams(creator);
|
||||
|
||||
std::array<uint8_t, mpsoc::MAX_REPLY_SIZE> tmBuf;
|
||||
|
||||
bool terminate = false;
|
||||
|
||||
@ -130,24 +141,25 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF, public H
|
||||
* Communication interface of MPSoC responsible for low level access. Must be set by the
|
||||
* MPSoC Handler.
|
||||
*/
|
||||
UartComIF* uartComIF = nullptr;
|
||||
SerialComIF* uartComIF = nullptr;
|
||||
// Communication cookie. Must be set by the MPSoC Handler
|
||||
CookieIF* comCookie = nullptr;
|
||||
// Sequence count, must be set by Ploc MPSoC Handler
|
||||
SourceSequenceCounter* sequenceCount;
|
||||
SourceSequenceCounter* sequenceCount = nullptr;
|
||||
|
||||
ReturnValue_t resetHelper();
|
||||
ReturnValue_t performFlashWrite();
|
||||
ReturnValue_t flashfopen();
|
||||
ReturnValue_t flashfclose();
|
||||
ReturnValue_t handlePacketTransmission(mpsoc::TcBase& tc);
|
||||
ReturnValue_t sendCommand(mpsoc::TcBase& tc);
|
||||
ReturnValue_t handlePacketTransmission(ploc::SpTcBase& tc);
|
||||
ReturnValue_t sendCommand(ploc::SpTcBase& tc);
|
||||
ReturnValue_t receive(uint8_t* data, size_t* readBytes, size_t requestBytes);
|
||||
ReturnValue_t handleAck();
|
||||
ReturnValue_t handleExe();
|
||||
void handleAckApidFailure(uint16_t apid);
|
||||
void handleExeApidFailure(uint16_t apid);
|
||||
ReturnValue_t handleTmReception(mpsoc::TmPacket* tmPacket, size_t remainingBytes);
|
||||
ReturnValue_t handleTmReception(size_t remainingBytes);
|
||||
ReturnValue_t checkReceivedTm(ploc::SpTmReader& reader);
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_ */
|
||||
|
@ -19,25 +19,25 @@ PlocMemoryDumper::~PlocMemoryDumper() {}
|
||||
|
||||
ReturnValue_t PlocMemoryDumper::initialize() {
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = commandActionHelper.initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = actionHelper.initialize(commandQueue);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMemoryDumper::performOperation(uint8_t operationCode) {
|
||||
readCommandQueue();
|
||||
doStateMachine();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocMemoryDumper::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
@ -78,20 +78,20 @@ MessageQueueIF* PlocMemoryDumper::getCommandQueuePtr() { return commandQueue; }
|
||||
|
||||
void PlocMemoryDumper::readCommandQueue() {
|
||||
CommandMessage message;
|
||||
ReturnValue_t result;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
for (result = commandQueue->receiveMessage(&message); result == HasReturnvaluesIF::RETURN_OK;
|
||||
for (result = commandQueue->receiveMessage(&message); result == returnvalue::OK;
|
||||
result = commandQueue->receiveMessage(&message)) {
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
result = actionHelper.handleActionMessage(&message);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result == returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = commandActionHelper.handleReply(&message);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result == returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -161,7 +161,7 @@ void PlocMemoryDumper::completionFailedReceived(ActionId_t actionId, ReturnValue
|
||||
}
|
||||
|
||||
void PlocMemoryDumper::commandNextMramDump(ActionId_t dumpCommand) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
uint32_t tempStartAddress = 0;
|
||||
uint32_t tempEndAddress = 0;
|
||||
@ -181,7 +181,7 @@ void PlocMemoryDumper::commandNextMramDump(ActionId_t dumpCommand) {
|
||||
|
||||
result =
|
||||
commandActionHelper.commandAction(objects::PLOC_SUPERVISOR_HANDLER, dumpCommand, ¶ms);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PlocMemoryDumper::commandNextMramDump: Failed to send mram dump command "
|
||||
<< "with start address " << tempStartAddress << " and end address "
|
||||
<< tempEndAddress << std::endl;
|
||||
|
@ -5,16 +5,20 @@
|
||||
#include <linux/devices/devicedefinitions/PlocSupervisorDefinitions.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "bsp_q7s/memory/SdCardManager.h"
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
#endif
|
||||
|
||||
#include "eive/eventSubsystemIds.h"
|
||||
#include "fsfw/action/ActionHelper.h"
|
||||
#include "fsfw/action/CommandActionHelper.h"
|
||||
#include "fsfw/action/CommandsActionsIF.h"
|
||||
#include "fsfw/action/HasActionsIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/tmtcpacket/SpacePacket.h"
|
||||
#include "linux/fsfwconfig/objects/systemObjectList.h"
|
||||
#include "objects/systemObjectList.h"
|
||||
|
||||
/**
|
||||
* @brief Because the buffer of the linux tty driver is limited to 2 x 65535 bytes, this class is
|
||||
@ -27,7 +31,6 @@
|
||||
class PlocMemoryDumper : public SystemObject,
|
||||
public HasActionsIF,
|
||||
public ExecutableObjectIF,
|
||||
public HasReturnvaluesIF,
|
||||
public CommandsActionsIF {
|
||||
public:
|
||||
static const ActionId_t NONE = 0;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,17 +1,22 @@
|
||||
#ifndef MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_
|
||||
#define MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_
|
||||
|
||||
#include <linux/devices/ploc/PlocSupvUartMan.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "PlocSupvHelper.h"
|
||||
#include "bsp_q7s/memory/SdCardManager.h"
|
||||
#include "devices/powerSwitcherList.h"
|
||||
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
|
||||
#include "fsfw/timemanager/Countdown.h"
|
||||
#include "fsfw_hal/linux/gpio/Gpio.h"
|
||||
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
|
||||
#include "fsfw_hal/linux/uart/UartComIF.h"
|
||||
#include "fsfw_hal/linux/serial/SerialComIF.h"
|
||||
#include "linux/devices/devicedefinitions/PlocSupervisorDefinitions.h"
|
||||
#include "linux/devices/devicedefinitions/SupvReturnValuesIF.h"
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
#endif
|
||||
|
||||
using supv::ExecutionReport;
|
||||
|
||||
/**
|
||||
* @brief This is the device handler for the supervisor of the PLOC which is programmed by
|
||||
@ -27,9 +32,8 @@
|
||||
*/
|
||||
class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
public:
|
||||
PlocSupervisorHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF* comCookie,
|
||||
Gpio uartIsolatorSwitch, power::Switch_t powerSwitch,
|
||||
PlocSupvHelper* supvHelper);
|
||||
PlocSupervisorHandler(object_id_t objectId, CookieIF* comCookie, Gpio uartIsolatorSwitch,
|
||||
power::Switch_t powerSwitch, PlocSupvUartManager& supvHelper);
|
||||
virtual ~PlocSupervisorHandler();
|
||||
|
||||
virtual ReturnValue_t initialize() override;
|
||||
@ -48,7 +52,6 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
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;
|
||||
@ -56,7 +59,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
uint8_t expectedReplies = 1, bool useAlternateId = false,
|
||||
DeviceCommandId_t alternateReplyID = 0) override;
|
||||
size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override;
|
||||
ReturnValue_t doSendReadHook() override;
|
||||
// ReturnValue_t doSendReadHook() override;
|
||||
void doOffActivity() override;
|
||||
|
||||
private:
|
||||
@ -64,18 +67,21 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
|
||||
//! [EXPORT] : [COMMENT] PLOC supervisor crc failure in telemetry packet
|
||||
static const Event SUPV_MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Unhandled event. P1: APID, P2: Service ID
|
||||
static constexpr Event SUPV_UNKNOWN_TM = MAKE_EVENT(2, severity::LOW);
|
||||
static constexpr Event SUPV_UNINIMPLEMENTED_TM = MAKE_EVENT(3, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] PLOC supervisor received acknowledgment failure report
|
||||
static const Event SUPV_ACK_FAILURE = MAKE_EVENT(2, severity::LOW);
|
||||
static const Event SUPV_ACK_FAILURE = MAKE_EVENT(4, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] PLOC received execution failure report
|
||||
//! P1: ID of command for which the execution failed
|
||||
//! P2: Status code sent by the supervisor handler
|
||||
static const Event SUPV_EXE_FAILURE = MAKE_EVENT(3, severity::LOW);
|
||||
static const Event SUPV_EXE_FAILURE = MAKE_EVENT(5, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] PLOC supervisor reply has invalid crc
|
||||
static const Event SUPV_CRC_FAILURE_EVENT = MAKE_EVENT(4, severity::LOW);
|
||||
static const Event SUPV_CRC_FAILURE_EVENT = MAKE_EVENT(6, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Supervisor helper currently executing a command
|
||||
static const Event SUPV_HELPER_EXECUTING = MAKE_EVENT(5, severity::LOW);
|
||||
static const Event SUPV_HELPER_EXECUTING = MAKE_EVENT(7, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Failed to build the command to shutdown the MPSoC
|
||||
static const Event SUPV_MPSOC_SHUWDOWN_BUILD_FAILED = MAKE_EVENT(5, severity::LOW);
|
||||
static const Event SUPV_MPSOC_SHUTDOWN_BUILD_FAILED = MAKE_EVENT(8, severity::LOW);
|
||||
|
||||
static const uint16_t APID_MASK = 0x7FF;
|
||||
static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF;
|
||||
@ -91,13 +97,17 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
static const uint32_t COPY_ADC_TO_MRAM_TIMEOUT = 70000;
|
||||
// 60 s
|
||||
static const uint32_t MRAM_DUMP_TIMEOUT = 60000;
|
||||
// 2 s
|
||||
static const uint32_t BOOT_TIMEOUT = 2000;
|
||||
// 4 s
|
||||
static const uint32_t BOOT_TIMEOUT = 4000;
|
||||
enum class StartupState : uint8_t { OFF, BOOTING, SET_TIME, SET_TIME_EXECUTING, ON };
|
||||
|
||||
static constexpr bool SET_TIME_DURING_BOOT = true;
|
||||
|
||||
StartupState startupState = StartupState::OFF;
|
||||
|
||||
uint8_t commandBuffer[supv::MAX_COMMAND_SIZE];
|
||||
SpacePacketCreator creator;
|
||||
supv::TcParams spParams = supv::TcParams(creator);
|
||||
|
||||
/**
|
||||
* This variable is used to store the id of the next reply to receive. This is necessary
|
||||
@ -106,9 +116,10 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
*/
|
||||
DeviceCommandId_t nextReplyId = supv::NONE;
|
||||
|
||||
UartComIF* uartComIf = nullptr;
|
||||
SerialComIF* uartComIf = nullptr;
|
||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||
Gpio uartIsolatorSwitch;
|
||||
bool shutdownCmdSent = false;
|
||||
|
||||
supv::HkSet hkset;
|
||||
supv::BootStatusReport bootStatusReport;
|
||||
@ -117,8 +128,9 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
supv::AdcReport adcReport;
|
||||
|
||||
const power::Switch_t powerSwitch = power::NO_SWITCH;
|
||||
supv::TmBase tmReader;
|
||||
|
||||
PlocSupvHelper* supvHelper = nullptr;
|
||||
PlocSupvUartManager& uartManager;
|
||||
MessageQueueIF* eventQueue = nullptr;
|
||||
|
||||
/** Number of expected replies following the MRAM dump command */
|
||||
@ -126,29 +138,29 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
uint32_t receivedMramDumpPackets = 0;
|
||||
/** Set to true as soon as a complete space packet is present in the spacePacketBuffer */
|
||||
bool packetInBuffer = false;
|
||||
/** Points to the next free position in the space packet buffer */
|
||||
uint16_t bufferTop = 0;
|
||||
|
||||
/** This buffer is used to concatenate space packets received in two different read steps */
|
||||
uint8_t spacePacketBuffer[supv::MAX_PACKET_SIZE];
|
||||
|
||||
#ifndef TE0720_1CFA
|
||||
#ifdef XIPHOS_Q7S
|
||||
SdCardManager* sdcMan = nullptr;
|
||||
#endif /* BOARD_TE0720 == 0 */
|
||||
#endif
|
||||
|
||||
// Path to supervisor specific files on SD card
|
||||
std::string supervisorFilePath = "ploc/supervisor";
|
||||
std::string activeMramFile;
|
||||
|
||||
// Supervisor helper class currently executing a command
|
||||
bool plocSupvHelperExecuting = false;
|
||||
|
||||
Countdown executionReportTimeout = Countdown(EXECUTION_DEFAULT_TIMEOUT, false);
|
||||
Countdown acknowledgementReportTimeout = Countdown(ACKNOWLEDGE_DEFAULT_TIMEOUT, false);
|
||||
// Vorago nees some time to boot properly
|
||||
Countdown bootTimeout = Countdown(BOOT_TIMEOUT);
|
||||
Countdown mramDumpTimeout = Countdown(MRAM_DUMP_TIMEOUT);
|
||||
|
||||
PoolEntry<uint8_t> fmcStateEntry = PoolEntry<uint8_t>(1);
|
||||
PoolEntry<uint8_t> bootStateEntry = PoolEntry<uint8_t>(1);
|
||||
PoolEntry<uint8_t> bootCyclesEntry = PoolEntry<uint8_t>(1);
|
||||
PoolEntry<uint32_t> tempSupEntry = PoolEntry<uint32_t>(1);
|
||||
|
||||
/**
|
||||
* @brief Adjusts the timeout of the execution report dependent on command
|
||||
*/
|
||||
@ -167,7 +179,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
* @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.
|
||||
* @return returnvalue::OK if CRC is ok, otherwise CRC_FAILURE.
|
||||
*/
|
||||
ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen);
|
||||
|
||||
@ -176,7 +188,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
*
|
||||
* @param data Pointer to the data holding the acknowledgment report.
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise an error code.
|
||||
* @return returnvalue::OK if successful, otherwise an error code.
|
||||
*/
|
||||
ReturnValue_t handleAckReport(const uint8_t* data);
|
||||
|
||||
@ -185,7 +197,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
*
|
||||
* @param data Pointer to the received data packet.
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise an error code.
|
||||
* @return returnvalue::OK if successful, otherwise an error code.
|
||||
*/
|
||||
ReturnValue_t handleExecutionReport(const uint8_t* data);
|
||||
|
||||
@ -195,7 +207,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
*
|
||||
* @param data Pointer to the data buffer holding the housekeeping read report.
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise an error code.
|
||||
* @return returnvalue::OK if successful, otherwise an error code.
|
||||
*/
|
||||
ReturnValue_t handleHkReport(const uint8_t* data);
|
||||
|
||||
@ -206,7 +218,8 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
ReturnValue_t handleBootStatusReport(const uint8_t* data);
|
||||
|
||||
ReturnValue_t handleLatchupStatusReport(const uint8_t* data);
|
||||
ReturnValue_t handleLoggingReport(const uint8_t* data);
|
||||
void handleBadApidServiceCombination(Event result, unsigned int apid, unsigned int serviceId);
|
||||
// ReturnValue_t handleLoggingReport(const uint8_t* data);
|
||||
ReturnValue_t handleAdcReport(const uint8_t* data);
|
||||
|
||||
/**
|
||||
@ -225,20 +238,20 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
* @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);
|
||||
void handleDeviceTm(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId);
|
||||
|
||||
/**
|
||||
* @brief This function prepares a space packet which does not transport any data in the
|
||||
* packet data field apart from the crc.
|
||||
*/
|
||||
void prepareEmptyCmd(uint16_t apid);
|
||||
ReturnValue_t prepareEmptyCmd(uint16_t apid, uint8_t serviceId);
|
||||
|
||||
/**
|
||||
* @brief This function initializes the space packet to select the boot image of the MPSoC.
|
||||
*/
|
||||
void prepareSelBootImageCmd(const uint8_t* commandData);
|
||||
ReturnValue_t prepareSelBootImageCmd(const uint8_t* commandData);
|
||||
|
||||
void prepareDisableHk();
|
||||
ReturnValue_t prepareDisableHk();
|
||||
|
||||
/**
|
||||
* @brief This function fills the commandBuffer with the data to update the time of the
|
||||
@ -250,9 +263,11 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
* @brief This function fills the commandBuffer with the data to change the boot timeout
|
||||
* value in the PLOC supervisor.
|
||||
*/
|
||||
void prepareSetBootTimeoutCmd(const uint8_t* commandData);
|
||||
ReturnValue_t prepareSetBootTimeoutCmd(const uint8_t* commandData);
|
||||
|
||||
void prepareRestartTriesCmd(const uint8_t* commandData);
|
||||
ReturnValue_t prepareRestartTriesCmd(const uint8_t* commandData);
|
||||
|
||||
ReturnValue_t prepareFactoryResetCmd(const uint8_t* commandData, size_t len);
|
||||
|
||||
/**
|
||||
* @brief This function fills the command buffer with the packet to enable or disable the
|
||||
@ -269,21 +284,21 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
ReturnValue_t prepareLatchupConfigCmd(const uint8_t* commandData,
|
||||
DeviceCommandId_t deviceCommand);
|
||||
ReturnValue_t prepareSetAlertLimitCmd(const uint8_t* commandData);
|
||||
void prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData);
|
||||
void prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData);
|
||||
void prepareSetAdcThresholdCmd(const uint8_t* commandData);
|
||||
ReturnValue_t prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData);
|
||||
ReturnValue_t prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData);
|
||||
ReturnValue_t prepareSetAdcThresholdCmd(const uint8_t* commandData);
|
||||
ReturnValue_t prepareRunAutoEmTest(const uint8_t* commandData);
|
||||
ReturnValue_t prepareWipeMramCmd(const uint8_t* commandData);
|
||||
ReturnValue_t prepareDumpMramCmd(const uint8_t* commandData);
|
||||
void prepareSetGpioCmd(const uint8_t* commandData);
|
||||
void prepareReadGpioCmd(const uint8_t* commandData);
|
||||
ReturnValue_t prepareLoggingRequest(const uint8_t* commandData, size_t commandDataLen);
|
||||
ReturnValue_t prepareEnableNvmsCommand(const uint8_t* commandData);
|
||||
// ReturnValue_t prepareDumpMramCmd(const uint8_t* commandData);
|
||||
ReturnValue_t prepareSetGpioCmd(const uint8_t* commandData);
|
||||
ReturnValue_t prepareReadGpioCmd(const uint8_t* commandData);
|
||||
// ReturnValue_t prepareLoggingRequest(const uint8_t* commandData, size_t commandDataLen);
|
||||
// ReturnValue_t prepareEnableNvmsCommand(const uint8_t* commandData);
|
||||
|
||||
/**
|
||||
* @brief Copies the content of a space packet to the command buffer.
|
||||
*/
|
||||
void packetToOutBuffer(uint8_t* packetData, size_t fullSize);
|
||||
void finishTcPrep(size_t packetLen);
|
||||
|
||||
/**
|
||||
* @brief In case an acknowledgment failure reply has been received this function disables
|
||||
@ -313,7 +328,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
* @brief Function is called in scanForReply and fills the spacePacketBuffer with the read
|
||||
* data until a full packet has been received.
|
||||
*/
|
||||
ReturnValue_t parseMramPackets(const uint8_t* packet, size_t remainingSize, size_t* foundlen);
|
||||
// ReturnValue_t parseMramPackets(const uint8_t* packet, size_t remainingSize, size_t* foundlen);
|
||||
|
||||
/**
|
||||
* @brief This function generates the Service 8 packets for the MRAM dump data.
|
||||
@ -331,7 +346,7 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
* @brief Function checks if the packet written to the space packet buffer is really a
|
||||
* MRAM dump packet.
|
||||
*/
|
||||
ReturnValue_t checkMramPacketApid();
|
||||
// ReturnValue_t checkMramPacketApid();
|
||||
|
||||
/**
|
||||
* @brief Writes the data of the MRAM dump to a file. The file will be created when receiving
|
||||
@ -361,14 +376,18 @@ class PlocSupervisorHandler : public DeviceHandlerBase {
|
||||
ReturnValue_t createMramDumpFile();
|
||||
ReturnValue_t getTimeStampString(std::string& timeStamp);
|
||||
|
||||
void prepareSetShutdownTimeoutCmd(const uint8_t* commandData);
|
||||
ReturnValue_t prepareSetShutdownTimeoutCmd(const uint8_t* commandData);
|
||||
|
||||
ReturnValue_t extractUpdateCommand(const uint8_t* commandData, size_t size, std::string* file,
|
||||
uint8_t* memoryId, uint32_t* startAddress);
|
||||
ReturnValue_t extractUpdateCommand(const uint8_t* commandData, size_t size,
|
||||
supv::UpdateParams& params);
|
||||
ReturnValue_t extractBaseParams(const uint8_t** commandData, size_t& remSize,
|
||||
supv::UpdateParams& params);
|
||||
ReturnValue_t eventSubscription();
|
||||
|
||||
void handleExecutionSuccessReport(const uint8_t* data);
|
||||
void handleExecutionFailureReport(uint16_t statusCode);
|
||||
ReturnValue_t handleExecutionSuccessReport(ExecutionReport& report);
|
||||
void handleExecutionFailureReport(ExecutionReport& report);
|
||||
|
||||
void printAckFailureInfo(uint16_t statusCode, DeviceCommandId_t commandId);
|
||||
};
|
||||
|
||||
#endif /* MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ */
|
||||
|
@ -1,562 +0,0 @@
|
||||
#include "PlocSupvHelper.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/memory/FilesystemHelper.h"
|
||||
#include "bsp_q7s/memory/SdCardManager.h"
|
||||
#endif
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
#include "fsfw/timemanager/Countdown.h"
|
||||
#include "fsfw/tasks/TaskFactory.h"
|
||||
#include "mission/utility/Filenaming.h"
|
||||
#include "mission/utility/ProgressPrinter.h"
|
||||
#include "mission/utility/Timestamp.h"
|
||||
|
||||
PlocSupvHelper::PlocSupvHelper(object_id_t objectId) : SystemObject(objectId) {}
|
||||
|
||||
PlocSupvHelper::~PlocSupvHelper() {}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::initialize() {
|
||||
#ifdef XIPHOS_Q7S
|
||||
sdcMan = SdCardManager::instance();
|
||||
if (sdcMan == nullptr) {
|
||||
sif::warning << "PlocSupvHelper::initialize: Invalid SD Card Manager" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
#endif
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::performOperation(uint8_t operationCode) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
semaphore.acquire();
|
||||
while (true) {
|
||||
switch (internalState) {
|
||||
case InternalState::IDLE: {
|
||||
semaphore.acquire();
|
||||
break;
|
||||
}
|
||||
case InternalState::UPDATE: {
|
||||
result = performUpdate();
|
||||
if (result == RETURN_OK) {
|
||||
triggerEvent(SUPV_UPDATE_SUCCESSFUL, result);
|
||||
} else if (result == PROCESS_TERMINATED) {
|
||||
// Event already triggered
|
||||
} else {
|
||||
triggerEvent(SUPV_UPDATE_FAILED, result);
|
||||
}
|
||||
internalState = InternalState::IDLE;
|
||||
break;
|
||||
}
|
||||
case InternalState::CONTINUE_UPDATE: {
|
||||
result = continueUpdate();
|
||||
if (result == RETURN_OK) {
|
||||
triggerEvent(SUPV_CONTINUE_UPDATE_SUCCESSFUL, result);
|
||||
} else if (result == PROCESS_TERMINATED) {
|
||||
// Event already triggered
|
||||
} else {
|
||||
triggerEvent(SUPV_CONTINUE_UPDATE_FAILED, result);
|
||||
}
|
||||
internalState = InternalState::IDLE;
|
||||
break;
|
||||
}
|
||||
case InternalState::REQUEST_EVENT_BUFFER: {
|
||||
result = performEventBufferRequest();
|
||||
if (result == RETURN_OK) {
|
||||
triggerEvent(SUPV_EVENT_BUFFER_REQUEST_SUCCESSFUL, result);
|
||||
} else if (result == PROCESS_TERMINATED) {
|
||||
// Event already triggered
|
||||
break;
|
||||
} else {
|
||||
triggerEvent(SUPV_EVENT_BUFFER_REQUEST_FAILED, result);
|
||||
}
|
||||
internalState = InternalState::IDLE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sif::debug << "PlocSupvHelper::performOperation: Invalid state" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::setComIF(UartComIF* uartComIF_) {
|
||||
if (uartComIF_ == nullptr) {
|
||||
sif::warning << "PlocSupvHelper::initialize: Provided invalid uart com if" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
uartComIF = uartComIF_;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void PlocSupvHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
|
||||
|
||||
ReturnValue_t PlocSupvHelper::startUpdate(std::string file, uint8_t memoryId,
|
||||
uint32_t startAddress) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
#ifdef XIPHOS_Q7S
|
||||
result = FilesystemHelper::checkPath(file);
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PlocSupvHelper::startUpdate: File " << file << " does not exist" << std::endl;
|
||||
return result;
|
||||
}
|
||||
result = FilesystemHelper::fileExists(file);
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PlocSupvHelper::startUpdate: The file " << file << " does not exist"
|
||||
<< std::endl;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#ifdef TE0720_1CFA
|
||||
if (not std::filesystem::exists(file)) {
|
||||
sif::warning << "PlocSupvHelper::startUpdate: The file " << file << " does not exist"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
#endif
|
||||
update.file = file;
|
||||
update.length = getFileSize(update.file);
|
||||
update.memoryId = memoryId;
|
||||
update.startAddress = startAddress;
|
||||
update.remainingSize = update.length;
|
||||
update.bytesWritten = 0;
|
||||
update.packetNum = 1;
|
||||
update.sequenceCount = 1;
|
||||
internalState = InternalState::UPDATE;
|
||||
uartComIF->flushUartTxAndRxBuf(comCookie);
|
||||
semaphore.release();
|
||||
return result;
|
||||
}
|
||||
|
||||
void PlocSupvHelper::initiateUpdateContinuation() {
|
||||
internalState = InternalState::CONTINUE_UPDATE;
|
||||
semaphore.release();
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::startEventbBufferRequest(std::string path) {
|
||||
#ifdef XIPHOS_Q7S
|
||||
ReturnValue_t result = FilesystemHelper::checkPath(path);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
if (not std::filesystem::exists(path)) {
|
||||
return PATH_NOT_EXISTS;
|
||||
}
|
||||
eventBufferReq.path = path;
|
||||
internalState = InternalState::REQUEST_EVENT_BUFFER;
|
||||
uartComIF->flushUartTxAndRxBuf(comCookie);
|
||||
semaphore.release();
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void PlocSupvHelper::stopProcess() { terminate = true; }
|
||||
|
||||
ReturnValue_t PlocSupvHelper::performUpdate() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
result = calcImageCrc();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = selectMemory();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = prepareUpdate();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = eraseMemory();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = writeUpdatePackets();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleCheckMemoryCommand();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::continueUpdate() {
|
||||
ReturnValue_t result = prepareUpdate();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = writeUpdatePackets();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleCheckMemoryCommand();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::writeUpdatePackets() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
|
||||
ProgressPrinter progressPrinter("Supervisor update", update.length,
|
||||
ProgressPrinter::HALF_PERCENT);
|
||||
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
|
||||
uint8_t tempData[supv::WriteMemory::CHUNK_MAX];
|
||||
std::ifstream file(update.file, std::ifstream::binary);
|
||||
uint16_t dataLength = 0;
|
||||
supv::SequenceFlags seqFlags;
|
||||
while (update.remainingSize > 0) {
|
||||
if (terminate) {
|
||||
terminate = false;
|
||||
return PROCESS_TERMINATED;
|
||||
}
|
||||
if (update.remainingSize > supv::WriteMemory::CHUNK_MAX) {
|
||||
dataLength = supv::WriteMemory::CHUNK_MAX;
|
||||
} else {
|
||||
dataLength = static_cast<uint16_t>(update.remainingSize);
|
||||
}
|
||||
if (file.is_open()) {
|
||||
file.seekg(update.bytesWritten, file.beg);
|
||||
file.read(reinterpret_cast<char*>(tempData), dataLength);
|
||||
if (!file) {
|
||||
sif::warning << "PlocSupvHelper::performUpdate: Read only " << file.gcount() << " of "
|
||||
<< dataLength << " bytes" << std::endl;
|
||||
sif::info << "PlocSupvHelper::performUpdate: Failed when trying to read byte "
|
||||
<< update.bytesWritten << std::endl;
|
||||
}
|
||||
} else {
|
||||
return FILE_CLOSED_ACCIDENTALLY;
|
||||
}
|
||||
if (update.bytesWritten == 0) {
|
||||
seqFlags = supv::SequenceFlags::FIRST_PKT;
|
||||
} else if (update.remainingSize == 0) {
|
||||
seqFlags = supv::SequenceFlags::LAST_PKT;
|
||||
} else {
|
||||
seqFlags = supv::SequenceFlags::CONTINUED_PKT;
|
||||
}
|
||||
supv::WriteMemory packet(seqFlags, update.sequenceCount++, update.memoryId,
|
||||
update.startAddress + update.bytesWritten, dataLength, tempData);
|
||||
result = handlePacketTransmission(packet);
|
||||
if (result != RETURN_OK) {
|
||||
update.sequenceCount--;
|
||||
triggerEvent(WRITE_MEMORY_FAILED, update.packetNum);
|
||||
return result;
|
||||
}
|
||||
update.remainingSize -= dataLength;
|
||||
update.packetNum += 1;
|
||||
update.bytesWritten += dataLength;
|
||||
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
|
||||
progressPrinter.print(update.bytesWritten);
|
||||
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::performEventBufferRequest() {
|
||||
using namespace supv;
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
RequestLoggingData packet(RequestLoggingData::Sa::REQUEST_EVENT_BUFFERS);
|
||||
result = sendCommand(packet);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleAck();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleEventBufferReception();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleExe();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::selectMemory() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
supv::MPSoCBootSelect packet(update.memoryId);
|
||||
result = handlePacketTransmission(packet);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::prepareUpdate() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
supv::ApidOnlyPacket packet(supv::APID_PREPARE_UPDATE);
|
||||
result = handlePacketTransmission(packet, PREPARE_UPDATE_EXECUTION_REPORT);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::eraseMemory() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
supv::EraseMemory eraseMemory(update.memoryId, update.startAddress, update.length);
|
||||
result = handlePacketTransmission(eraseMemory, supv::recv_timeout::ERASE_MEMORY);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::handlePacketTransmission(SpacePacket& packet,
|
||||
uint32_t timeoutExecutionReport) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
result = sendCommand(packet);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleAck();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleExe(timeoutExecutionReport);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::sendCommand(SpacePacket& packet) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
rememberApid = packet.getAPID();
|
||||
result = uartComIF->sendMessage(comCookie, packet.getWholeData(), packet.getFullSize());
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PlocSupvHelper::sendCommand: Failed to send command" << std::endl;
|
||||
triggerEvent(SUPV_SENDING_COMMAND_FAILED, result, static_cast<uint32_t>(internalState));
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::handleAck() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
supv::AcknowledgmentReport ackReport;
|
||||
result = handleTmReception(&ackReport, supv::SIZE_ACK_REPORT);
|
||||
if (result != RETURN_OK) {
|
||||
triggerEvent(ACK_RECEPTION_FAILURE, result, static_cast<uint32_t>(rememberApid));
|
||||
sif::warning << "PlocSupvHelper::handleAck: Error in reception of acknowledgment report"
|
||||
<< std::endl;
|
||||
return result;
|
||||
}
|
||||
result = ackReport.checkApid();
|
||||
if (result != RETURN_OK) {
|
||||
if (result == SupvReturnValuesIF::RECEIVED_ACK_FAILURE) {
|
||||
triggerEvent(SUPV_ACK_FAILURE_REPORT, static_cast<uint32_t>(ackReport.getRefApid()));
|
||||
} else if (result == SupvReturnValuesIF::INVALID_APID) {
|
||||
triggerEvent(SUPV_ACK_INVALID_APID, static_cast<uint32_t>(rememberApid));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::handleExe(uint32_t timeout) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
supv::ExecutionReport exeReport;
|
||||
result = handleTmReception(&exeReport, supv::SIZE_EXE_REPORT, timeout);
|
||||
if (result != RETURN_OK) {
|
||||
triggerEvent(EXE_RECEPTION_FAILURE, result, static_cast<uint32_t>(rememberApid));
|
||||
sif::warning << "PlocSupvHelper::handleExe: Error in reception of execution report"
|
||||
<< std::endl;
|
||||
return result;
|
||||
}
|
||||
result = exeReport.checkApid();
|
||||
if (result != RETURN_OK) {
|
||||
if (result == SupvReturnValuesIF::RECEIVED_EXE_FAILURE) {
|
||||
triggerEvent(SUPV_EXE_FAILURE_REPORT, static_cast<uint32_t>(exeReport.getRefApid()));
|
||||
} else if (result == SupvReturnValuesIF::INVALID_APID) {
|
||||
triggerEvent(SUPV_EXE_INVALID_APID, static_cast<uint32_t>(rememberApid));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::handleTmReception(supv::TmPacket* tmPacket, size_t remainingBytes,
|
||||
uint32_t timeout) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
size_t readBytes = 0;
|
||||
size_t currentBytes = 0;
|
||||
Countdown countdown(timeout);
|
||||
while (!countdown.hasTimedOut()) {
|
||||
result = receive(tmPacket->getWholeData() + readBytes, ¤tBytes, remainingBytes);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
readBytes += currentBytes;
|
||||
remainingBytes = remainingBytes - currentBytes;
|
||||
if (remainingBytes == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (remainingBytes != 0) {
|
||||
sif::warning << "PlocSupvHelper::handleTmReception: Failed to read " << std::dec
|
||||
<< remainingBytes << " bytes" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
result = tmPacket->checkCrc();
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PlocSupvHelper::handleTmReception: CRC check failed" << std::endl;
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::receive(uint8_t* data, size_t* readBytes, size_t requestBytes) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
uint8_t* buffer = nullptr;
|
||||
result = uartComIF->requestReceiveMessage(comCookie, requestBytes);
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PlocSupvHelper::receive: Failed to request reply" << std::endl;
|
||||
triggerEvent(SUPV_HELPER_REQUESTING_REPLY_FAILED, result,
|
||||
static_cast<uint32_t>(static_cast<uint32_t>(internalState)));
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
result = uartComIF->readReceivedMessage(comCookie, &buffer, readBytes);
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PlocSupvHelper::receive: Failed to read received message" << std::endl;
|
||||
triggerEvent(SUPV_HELPER_READING_REPLY_FAILED, result, static_cast<uint32_t>(internalState));
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
if (*readBytes > 0) {
|
||||
std::memcpy(data, buffer, *readBytes);
|
||||
}
|
||||
else {
|
||||
TaskFactory::delayTask(40);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::calcImageCrc() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
#ifdef XIPHOS_Q7S
|
||||
result = FilesystemHelper::checkPath(update.file);
|
||||
#endif
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PlocSupvHelper::calcImageCrc: File " << update.file << " does not exist"
|
||||
<< std::endl;
|
||||
return result;
|
||||
}
|
||||
std::ifstream file(update.file, std::ifstream::binary);
|
||||
uint16_t remainder = CRC16_INIT;
|
||||
uint8_t input;
|
||||
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
|
||||
ProgressPrinter progress("Supervisor update crc calculation", update.length,
|
||||
ProgressPrinter::ONE_PERCENT);
|
||||
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
|
||||
uint32_t byteCount = 0;
|
||||
for (byteCount = 0; byteCount < update.length; byteCount++) {
|
||||
file.seekg(byteCount, file.beg);
|
||||
file.read(reinterpret_cast<char*>(&input), 1);
|
||||
remainder = CRC::crc16ccitt(&input, sizeof(input), remainder);
|
||||
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
|
||||
progress.print(byteCount);
|
||||
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
|
||||
}
|
||||
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
|
||||
progress.print(byteCount);
|
||||
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
|
||||
file.close();
|
||||
update.crc = remainder;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::handleCheckMemoryCommand() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
// Verification of update write procedure
|
||||
supv::CheckMemory packet(update.memoryId, update.startAddress, update.length);
|
||||
result = sendCommand(packet);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = handleAck();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
supv::UpdateStatusReport updateStatusReport;
|
||||
result = handleTmReception(&updateStatusReport,
|
||||
static_cast<size_t>(updateStatusReport.getNominalSize()),
|
||||
supv::recv_timeout::UPDATE_STATUS_REPORT);
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning
|
||||
<< "PlocSupvHelper::handleCheckMemoryCommand: Failed to receive update status report"
|
||||
<< std::endl;
|
||||
return result;
|
||||
}
|
||||
result = handleExe(CRC_EXECUTION_TIMEOUT);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = updateStatusReport.parseDataField();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = updateStatusReport.verifycrc(update.crc);
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "PlocSupvHelper::handleCheckMemoryCommand: CRC failure. Expected CRC 0x"
|
||||
<< std::hex << update.crc << " but received CRC 0x" << updateStatusReport.getCrc()
|
||||
<< std::endl;
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t PlocSupvHelper::getFileSize(std::string filename) {
|
||||
std::ifstream file(filename, std::ifstream::binary);
|
||||
file.seekg(0, file.end);
|
||||
uint32_t size = file.tellg();
|
||||
file.close();
|
||||
return size;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupvHelper::handleEventBufferReception() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
std::string filename = Filenaming::generateAbsoluteFilename(
|
||||
eventBufferReq.path, eventBufferReq.filename, timestamping);
|
||||
std::ofstream file(filename, std::ios_base::app | std::ios_base::out);
|
||||
uint32_t packetsRead = 0;
|
||||
size_t requestLen = 0;
|
||||
supv::TmPacket tmPacket;
|
||||
for (packetsRead = 0; packetsRead < NUM_EVENT_BUFFER_PACKETS; packetsRead++) {
|
||||
if (terminate) {
|
||||
triggerEvent(SUPV_EVENT_BUFFER_REQUEST_TERMINATED, packetsRead - 1);
|
||||
file.close();
|
||||
return PROCESS_TERMINATED;
|
||||
}
|
||||
if (packetsRead == NUM_EVENT_BUFFER_PACKETS - 1) {
|
||||
requestLen = SIZE_EVENT_BUFFER_LAST_PACKET;
|
||||
} else {
|
||||
requestLen = SIZE_EVENT_BUFFER_FULL_PACKET;
|
||||
}
|
||||
result = handleTmReception(&tmPacket, requestLen);
|
||||
if (result != RETURN_OK) {
|
||||
sif::debug << "PlocSupvHelper::handleEventBufferReception: Failed while trying to read packet"
|
||||
<< " " << packetsRead + 1 << std::endl;
|
||||
file.close();
|
||||
return result;
|
||||
}
|
||||
uint16_t apid = tmPacket.getAPID();
|
||||
if (apid != supv::APID_MRAM_DUMP_TM) {
|
||||
sif::warning << "PlocSupvHelper::handleEventBufferReception: Did not expect space packet "
|
||||
<< "with APID 0x" << std::hex << apid << std::endl;
|
||||
file.close();
|
||||
return EVENT_BUFFER_REPLY_INVALID_APID;
|
||||
}
|
||||
file.write(reinterpret_cast<const char*>(tmPacket.getPacketData()),
|
||||
tmPacket.getPayloadDataLength());
|
||||
}
|
||||
return result;
|
||||
}
|
@ -1,241 +0,0 @@
|
||||
#ifndef BSP_Q7S_DEVICES_PLOCSUPVHELPER_H_
|
||||
#define BSP_Q7S_DEVICES_PLOCSUPVHELPER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/devicehandlers/CookieIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/osal/linux/BinarySemaphore.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw_hal/linux/uart/UartComIF.h"
|
||||
#include "linux/devices/devicedefinitions/PlocSupervisorDefinitions.h"
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/memory/SdCardManager.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Helper class for supervisor of PLOC intended to accelerate large data transfers between
|
||||
* the supervisor and the OBC.
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PlocSupvHelper : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF {
|
||||
public:
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_SUPV_HELPER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] update failed
|
||||
static const Event SUPV_UPDATE_FAILED = MAKE_EVENT(0, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] update successful
|
||||
static const Event SUPV_UPDATE_SUCCESSFUL = MAKE_EVENT(1, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Continue update command failed
|
||||
static const Event SUPV_CONTINUE_UPDATE_FAILED = MAKE_EVENT(2, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Continue update command successful
|
||||
static const Event SUPV_CONTINUE_UPDATE_SUCCESSFUL = MAKE_EVENT(3, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Terminated update procedure by command
|
||||
static const Event TERMINATED_UPDATE_PROCEDURE = MAKE_EVENT(4, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Requesting event buffer was successful
|
||||
static const Event SUPV_EVENT_BUFFER_REQUEST_SUCCESSFUL = MAKE_EVENT(5, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Requesting event buffer failed
|
||||
static const Event SUPV_EVENT_BUFFER_REQUEST_FAILED = MAKE_EVENT(6, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Terminated event buffer request by command
|
||||
//! P1: Number of packets read before process was terminated
|
||||
static const Event SUPV_EVENT_BUFFER_REQUEST_TERMINATED = MAKE_EVENT(7, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Communication interface returned failure when trying to send the command
|
||||
//! to the supervisor
|
||||
//! P1: Return value returned by the communication interface sendMessage function
|
||||
//! P2: Internal state of supervisor helper
|
||||
static const Event SUPV_SENDING_COMMAND_FAILED = MAKE_EVENT(8, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Request receive message of communication interface failed
|
||||
//! P1: Return value returned by the communication interface requestReceiveMessage function
|
||||
//! P2: Internal state of supervisor helper
|
||||
static const Event SUPV_HELPER_REQUESTING_REPLY_FAILED = MAKE_EVENT(9, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Reading receive message of communication interface failed
|
||||
//! P1: Return value returned by the communication interface readingReceivedMessage function
|
||||
//! P2: Internal state of supervisor helper
|
||||
static const Event SUPV_HELPER_READING_REPLY_FAILED = MAKE_EVENT(10, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Did not receive acknowledgement report
|
||||
//! P1: Number of bytes missing
|
||||
//! P2: Internal state of MPSoC helper
|
||||
static const Event SUPV_MISSING_ACK = MAKE_EVENT(11, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Supervisor did not receive execution report
|
||||
//! P1: Number of bytes missing
|
||||
//! P2: Internal state of supervisor helper
|
||||
static const Event SUPV_MISSING_EXE = MAKE_EVENT(12, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Supervisor received acknowledgment failure report
|
||||
//! P1: Internal state of supervisor helper
|
||||
static const Event SUPV_ACK_FAILURE_REPORT = MAKE_EVENT(13, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Execution report failure
|
||||
//! P1:
|
||||
static const Event SUPV_EXE_FAILURE_REPORT = MAKE_EVENT(14, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Supervisor expected acknowledgment report but received space packet with
|
||||
//! other apid P1: Apid of received space packet P2: Internal state of supervisor helper
|
||||
static const Event SUPV_ACK_INVALID_APID = MAKE_EVENT(15, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Supervisor helper expected execution report but received space packet
|
||||
//! with other apid P1: Apid of received space packet P2: Internal state of supervisor helper
|
||||
static const Event SUPV_EXE_INVALID_APID = MAKE_EVENT(16, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Failed to receive acknowledgment report
|
||||
//! P1: Return value
|
||||
//! P2: Apid of command for which the reception of the acknowledgment report failed
|
||||
static const Event ACK_RECEPTION_FAILURE = MAKE_EVENT(17, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Failed to receive execution report
|
||||
//! P1: Return value
|
||||
//! P2: Apid of command for which the reception of the execution report failed
|
||||
static const Event EXE_RECEPTION_FAILURE = MAKE_EVENT(18, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Update procedure failed when sending packet with number P1
|
||||
//! P1: Packet number for which the memory write command fails
|
||||
static const Event WRITE_MEMORY_FAILED = MAKE_EVENT(19, severity::LOW);
|
||||
|
||||
PlocSupvHelper(object_id_t objectId);
|
||||
virtual ~PlocSupvHelper();
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||
|
||||
ReturnValue_t setComIF(UartComIF* uartComfIF_);
|
||||
void setComCookie(CookieIF* comCookie_);
|
||||
|
||||
/**
|
||||
* @brief Starts update procedure
|
||||
*
|
||||
* @param file File containing the update data
|
||||
* @param memoryId ID of the memory where to write to
|
||||
* @param startAddress Address where to write data
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t startUpdate(std::string file, uint8_t memoryId, uint32_t startAddress);
|
||||
|
||||
/**
|
||||
* @brief This initiate the continuation of a failed update.
|
||||
*/
|
||||
void initiateUpdateContinuation();
|
||||
|
||||
/**
|
||||
* @brief Calling this function will initiate the procedure to request the event buffer
|
||||
*/
|
||||
ReturnValue_t startEventbBufferRequest(std::string path);
|
||||
|
||||
/**
|
||||
* @brief Can be used to interrupt a running data transfer.
|
||||
*/
|
||||
void stopProcess();
|
||||
|
||||
private:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_SUPV_HELPER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] File accidentally close
|
||||
static const ReturnValue_t FILE_CLOSED_ACCIDENTALLY = MAKE_RETURN_CODE(0xA0);
|
||||
//! [EXPORT] : [COMMENT] Process has been terminated by command
|
||||
static const ReturnValue_t PROCESS_TERMINATED = MAKE_RETURN_CODE(0xA1);
|
||||
//! [EXPORT] : [COMMENT] Received command with invalid pathname
|
||||
static const ReturnValue_t PATH_NOT_EXISTS = MAKE_RETURN_CODE(0xA2);
|
||||
//! [EXPORT] : [COMMENT] Expected event buffer TM but received space packet with other APID
|
||||
static const ReturnValue_t EVENT_BUFFER_REPLY_INVALID_APID = MAKE_RETURN_CODE(0xA3);
|
||||
|
||||
static const uint16_t CRC16_INIT = 0xFFFF;
|
||||
// Event buffer reply will carry 24 space packets with 1016 bytes and one space packet with
|
||||
// 192 bytes
|
||||
static const uint8_t NUM_EVENT_BUFFER_PACKETS = 25;
|
||||
static const size_t SIZE_EVENT_BUFFER_FULL_PACKET = 1024;
|
||||
static const size_t SIZE_EVENT_BUFFER_LAST_PACKET = 200;
|
||||
static const uint32_t CRC_EXECUTION_TIMEOUT = 60000;
|
||||
static const uint32_t PREPARE_UPDATE_EXECUTION_REPORT = 2000;
|
||||
|
||||
struct Update {
|
||||
uint8_t memoryId;
|
||||
uint32_t startAddress;
|
||||
// Absolute name of file containing update data
|
||||
std::string file;
|
||||
// Size of update
|
||||
uint32_t length;
|
||||
uint32_t crc;
|
||||
size_t remainingSize;
|
||||
size_t bytesWritten;
|
||||
uint32_t packetNum;
|
||||
uint16_t sequenceCount;
|
||||
};
|
||||
|
||||
struct Update update;
|
||||
|
||||
struct EventBufferRequest {
|
||||
std::string path = "";
|
||||
// Default name of file where event buffer data will be written to. Timestamp will be added to
|
||||
// name when new file is created
|
||||
std::string filename = "event-buffer.bin";
|
||||
};
|
||||
|
||||
EventBufferRequest eventBufferReq;
|
||||
|
||||
enum class InternalState { IDLE, UPDATE, CONTINUE_UPDATE, REQUEST_EVENT_BUFFER };
|
||||
|
||||
InternalState internalState = InternalState::IDLE;
|
||||
|
||||
BinarySemaphore semaphore;
|
||||
#ifdef XIPHOS_Q7S
|
||||
SdCardManager* sdcMan = nullptr;
|
||||
#endif
|
||||
uint8_t commandBuffer[supv::MAX_COMMAND_SIZE];
|
||||
|
||||
bool terminate = false;
|
||||
|
||||
/**
|
||||
* Communication interface responsible for data transactions between OBC and Supervisor.
|
||||
*/
|
||||
UartComIF* uartComIF = nullptr;
|
||||
// Communication cookie. Must be set by the supervisor Handler
|
||||
CookieIF* comCookie = nullptr;
|
||||
|
||||
bool timestamping = true;
|
||||
|
||||
// Remembers APID to know at which command a procedure failed
|
||||
uint16_t rememberApid = 0;
|
||||
|
||||
ReturnValue_t performUpdate();
|
||||
ReturnValue_t continueUpdate();
|
||||
ReturnValue_t writeUpdatePackets();
|
||||
ReturnValue_t performEventBufferRequest();
|
||||
ReturnValue_t handlePacketTransmission(SpacePacket& packet,
|
||||
uint32_t timeoutExecutionReport = 60000);
|
||||
ReturnValue_t sendCommand(SpacePacket& packet);
|
||||
/**
|
||||
* @brief Function which reads form the communication interface
|
||||
*
|
||||
* @param data Pointer to buffer where read data will be written to
|
||||
* @param raedBytes Actual number of bytes read
|
||||
* @param requestBytes Number of bytes to read
|
||||
*/
|
||||
ReturnValue_t receive(uint8_t* data, size_t* readBytes, size_t requestBytes);
|
||||
ReturnValue_t handleAck();
|
||||
ReturnValue_t handleExe(uint32_t timeout = 1000);
|
||||
/**
|
||||
* @brief Handles reading of TM packets from the communication interface
|
||||
*
|
||||
* @param tmPacket Pointer to space packet where received data will be written to
|
||||
* @param reaminingBytes Number of bytes to read in the space packet
|
||||
* @param timeout Receive timeout in milliseconds
|
||||
*
|
||||
* @note It can take up to 70 seconds until the supervisor replies with an acknowledgment
|
||||
* failure report.
|
||||
*/
|
||||
ReturnValue_t handleTmReception(supv::TmPacket* tmPacket, size_t remainingBytes,
|
||||
uint32_t timeout = 70000);
|
||||
ReturnValue_t selectMemory();
|
||||
ReturnValue_t prepareUpdate();
|
||||
ReturnValue_t eraseMemory();
|
||||
// Calculates CRC over image. Will be used for verification after update writing has
|
||||
// finished.
|
||||
ReturnValue_t calcImageCrc();
|
||||
ReturnValue_t handleCheckMemoryCommand();
|
||||
/**
|
||||
* @brief Return size of file with name filename
|
||||
*
|
||||
* @param filename
|
||||
*
|
||||
* @return The size of the file
|
||||
*/
|
||||
uint32_t getFileSize(std::string filename);
|
||||
ReturnValue_t handleEventBufferReception();
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_DEVICES_PLOCSUPVHELPER_H_ */
|
1164
linux/devices/ploc/PlocSupvUartMan.cpp
Normal file
1164
linux/devices/ploc/PlocSupvUartMan.cpp
Normal file
File diff suppressed because it is too large
Load Diff
378
linux/devices/ploc/PlocSupvUartMan.h
Normal file
378
linux/devices/ploc/PlocSupvUartMan.h
Normal file
@ -0,0 +1,378 @@
|
||||
#ifndef BSP_Q7S_DEVICES_PLOCSUPVHELPER_H_
|
||||
#define BSP_Q7S_DEVICES_PLOCSUPVHELPER_H_
|
||||
|
||||
#include <fsfw/container/SimpleRingBuffer.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/container/FIFO.h"
|
||||
#include "fsfw/devicehandlers/CookieIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/osal/linux/BinarySemaphore.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw_hal/linux/serial/SerialComIF.h"
|
||||
#include "linux/devices/devicedefinitions/PlocSupervisorDefinitions.h"
|
||||
#include "mission/trace.h"
|
||||
#include "tas/crc.h"
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Helper class for supervisor of PLOC intended to accelerate large data transfers between
|
||||
* the supervisor and the OBC.
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PlocSupvUartManager : public DeviceCommunicationIF,
|
||||
public SystemObject,
|
||||
public ExecutableObjectIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_SUPV_HELPER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] File accidentally close
|
||||
static const ReturnValue_t FILE_CLOSED_ACCIDENTALLY = MAKE_RETURN_CODE(0xA0);
|
||||
//! [EXPORT] : [COMMENT] Process has been terminated by command
|
||||
static const ReturnValue_t PROCESS_TERMINATED = MAKE_RETURN_CODE(0xA1);
|
||||
//! [EXPORT] : [COMMENT] Received command with invalid pathname
|
||||
static const ReturnValue_t PATH_NOT_EXISTS = MAKE_RETURN_CODE(0xA2);
|
||||
//! [EXPORT] : [COMMENT] Expected event buffer TM but received space packet with other APID
|
||||
static const ReturnValue_t EVENT_BUFFER_REPLY_INVALID_APID = MAKE_RETURN_CODE(0xA3);
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_SUPV_HELPER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] update failed
|
||||
static const Event SUPV_UPDATE_FAILED = MAKE_EVENT(0, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] update successful
|
||||
static const Event SUPV_UPDATE_SUCCESSFUL = MAKE_EVENT(1, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Continue update command failed
|
||||
static const Event SUPV_CONTINUE_UPDATE_FAILED = MAKE_EVENT(2, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Continue update command successful
|
||||
static const Event SUPV_CONTINUE_UPDATE_SUCCESSFUL = MAKE_EVENT(3, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Terminated update procedure by command
|
||||
static const Event TERMINATED_UPDATE_PROCEDURE = MAKE_EVENT(4, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Requesting event buffer was successful
|
||||
static const Event SUPV_EVENT_BUFFER_REQUEST_SUCCESSFUL = MAKE_EVENT(5, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Requesting event buffer failed
|
||||
static const Event SUPV_EVENT_BUFFER_REQUEST_FAILED = MAKE_EVENT(6, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Terminated event buffer request by command
|
||||
//! P1: Number of packets read before process was terminated
|
||||
static const Event SUPV_EVENT_BUFFER_REQUEST_TERMINATED = MAKE_EVENT(7, severity::LOW);
|
||||
//! Status of memory check command
|
||||
//! P1: Returncode, 0 for success, other value with returncode for failure
|
||||
static constexpr Event SUPV_MEM_CHECK_OK = MAKE_EVENT(8, severity::INFO);
|
||||
static constexpr Event SUPV_MEM_CHECK_FAIL = MAKE_EVENT(9, severity::INFO);
|
||||
|
||||
//! [EXPORT] : [COMMENT] Communication interface returned failure when trying to send the command
|
||||
//! to the supervisor
|
||||
//! P1: Return value returned by the communication interface sendMessage function
|
||||
//! P2: Internal state of supervisor helper
|
||||
static const Event SUPV_SENDING_COMMAND_FAILED = MAKE_EVENT(16, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Request receive message of communication interface failed
|
||||
//! P1: Return value returned by the communication interface requestReceiveMessage function
|
||||
//! P2: Internal state of supervisor helper
|
||||
static const Event SUPV_HELPER_REQUESTING_REPLY_FAILED = MAKE_EVENT(17, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Reading receive message of communication interface failed
|
||||
//! P1: Return value returned by the communication interface readingReceivedMessage function
|
||||
//! P2: Internal state of supervisor helper
|
||||
static const Event SUPV_HELPER_READING_REPLY_FAILED = MAKE_EVENT(18, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Did not receive acknowledgement report
|
||||
//! P1: Number of bytes missing
|
||||
//! P2: Internal state of MPSoC helper
|
||||
static const Event SUPV_MISSING_ACK = MAKE_EVENT(19, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Supervisor did not receive execution report
|
||||
//! P1: Number of bytes missing
|
||||
//! P2: Internal state of supervisor helper
|
||||
static const Event SUPV_MISSING_EXE = MAKE_EVENT(20, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Supervisor received acknowledgment failure report
|
||||
//! P1: Internal state of supervisor helper
|
||||
static const Event SUPV_ACK_FAILURE_REPORT = MAKE_EVENT(21, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Execution report failure
|
||||
//! P1:
|
||||
static const Event SUPV_EXE_FAILURE_REPORT = MAKE_EVENT(22, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Supervisor expected acknowledgment report but received space packet with
|
||||
//! other apid P1: Apid of received space packet P2: Internal state of supervisor helper
|
||||
static const Event SUPV_ACK_INVALID_APID = MAKE_EVENT(23, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Supervisor helper expected execution report but received space packet
|
||||
//! with other apid P1: Apid of received space packet P2: Internal state of supervisor helper
|
||||
static const Event SUPV_EXE_INVALID_APID = MAKE_EVENT(24, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Failed to receive acknowledgment report
|
||||
//! P1: Return value
|
||||
//! P2: Apid of command for which the reception of the acknowledgment report failed
|
||||
static const Event ACK_RECEPTION_FAILURE = MAKE_EVENT(25, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Failed to receive execution report
|
||||
//! P1: Return value
|
||||
//! P2: Apid of command for which the reception of the execution report failed
|
||||
static const Event EXE_RECEPTION_FAILURE = MAKE_EVENT(26, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Update procedure failed when sending packet.
|
||||
//! P1: First byte percent, third and fourth byte Sequence Count, P2: Bytes written
|
||||
static const Event WRITE_MEMORY_FAILED = MAKE_EVENT(27, severity::LOW);
|
||||
static const Event SUPV_REPLY_SIZE_MISSMATCH = MAKE_EVENT(28, severity::LOW);
|
||||
static const Event SUPV_REPLY_CRC_MISSMATCH = MAKE_EVENT(29, severity::LOW);
|
||||
|
||||
//! [EXPORT] : [COMMENT] Will be triggered every 5 percent of the update progress.
|
||||
//! P1: First byte percent, third and fourth byte Sequence Count, P2: Bytes written
|
||||
static constexpr Event SUPV_UPDATE_PROGRESS = MAKE_EVENT(30, severity::INFO);
|
||||
static constexpr Event HDLC_FRAME_REMOVAL_ERROR = MAKE_EVENT(31, severity::INFO);
|
||||
static constexpr Event HDLC_CRC_ERROR = MAKE_EVENT(32, severity::INFO);
|
||||
|
||||
PlocSupvUartManager(object_id_t objectId);
|
||||
virtual ~PlocSupvUartManager();
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||
|
||||
/**
|
||||
* @brief Starts update procedure
|
||||
*
|
||||
* @param file File containing the update data
|
||||
* @param memoryId ID of the memory where to write to
|
||||
* @param startAddress Address where to write data
|
||||
*
|
||||
* @return returnvalue::OK if successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t performUpdate(const supv::UpdateParams& params);
|
||||
ReturnValue_t startUpdate(std::string file, uint8_t memoryId, uint32_t startAddress);
|
||||
|
||||
ReturnValue_t performMemCheck(std::string file, uint8_t memoryId, uint32_t startAddress,
|
||||
size_t sizeToCheck, bool checkCrc);
|
||||
ReturnValue_t performMemCheck(std::string file, uint8_t memoryId, uint32_t startAddress);
|
||||
|
||||
/**
|
||||
* @brief This initiate the continuation of a failed update.
|
||||
*/
|
||||
ReturnValue_t initiateUpdateContinuation();
|
||||
|
||||
/**
|
||||
* @brief Calling this function will initiate the procedure to request the event buffer
|
||||
*/
|
||||
// ReturnValue_t startEventBufferRequest(std::string path);
|
||||
|
||||
/**
|
||||
* @brief Can be used to stop the UART reception and put the task to sleep
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* @brief Can be used to start the UART reception
|
||||
*/
|
||||
void start();
|
||||
bool longerRequestActive() const;
|
||||
|
||||
static uint32_t buildProgParams1(uint8_t percent, uint16_t seqCount);
|
||||
static uint32_t buildApidServiceParam1(uint8_t apid, uint8_t serviceId);
|
||||
|
||||
private:
|
||||
static constexpr ReturnValue_t REQUEST_DONE = returnvalue::makeCode(1, 0);
|
||||
static constexpr ReturnValue_t NO_PACKET_FOUND = returnvalue::makeCode(1, 1);
|
||||
static constexpr ReturnValue_t DECODE_BUF_TOO_SMALL = returnvalue::makeCode(1, 2);
|
||||
static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS_CONSECUTIVE_START =
|
||||
returnvalue::makeCode(1, 3);
|
||||
static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS_CONSECUTIVE_END = returnvalue::makeCode(1, 4);
|
||||
static constexpr ReturnValue_t HDLC_ERROR = returnvalue::makeCode(1, 5);
|
||||
|
||||
static const uint16_t CRC16_INIT = 0xFFFF;
|
||||
// Event buffer reply will carry 24 space packets with 1016 bytes and one space packet with
|
||||
// 192 bytes
|
||||
static const uint8_t NUM_EVENT_BUFFER_PACKETS = 25;
|
||||
static const size_t SIZE_EVENT_BUFFER_FULL_PACKET = 1024;
|
||||
static const size_t SIZE_EVENT_BUFFER_LAST_PACKET = 200;
|
||||
static const uint32_t PREPARE_UPDATE_EXECUTION_REPORT = 2000;
|
||||
|
||||
static constexpr uint8_t MAX_STORED_DECODED_PACKETS = 4;
|
||||
static constexpr uint8_t HDLC_START_MARKER = 0x7E;
|
||||
static constexpr uint8_t HDLC_END_MARKER = 0x7C;
|
||||
|
||||
struct Update {
|
||||
uint8_t memoryId;
|
||||
uint32_t startAddress;
|
||||
// Absolute name of file containing update data
|
||||
std::string file;
|
||||
// Length of full file
|
||||
size_t fullFileSize = 0;
|
||||
// Size of update
|
||||
uint32_t length = 0;
|
||||
uint32_t crc = 0;
|
||||
bool crcShouldBeChecked = true;
|
||||
size_t bytesWritten;
|
||||
uint32_t packetNum;
|
||||
uint16_t sequenceCount;
|
||||
uint8_t progressPercent;
|
||||
bool deleteMemory = false;
|
||||
};
|
||||
|
||||
struct Update update;
|
||||
|
||||
SemaphoreIF* semaphore;
|
||||
MutexIF* lock;
|
||||
MutexIF* ipcLock;
|
||||
supv::TmBase tmReader;
|
||||
int serialPort = 0;
|
||||
struct termios tty = {};
|
||||
#if OBSW_THREAD_TRACING == 1
|
||||
uint32_t opCounter = 0;
|
||||
#endif
|
||||
|
||||
struct EventBufferRequest {
|
||||
std::string path = "";
|
||||
// Default name of file where event buffer data will be written to. Timestamp will be added to
|
||||
// name when new file is created
|
||||
std::string filename = "event-buffer.bin";
|
||||
};
|
||||
|
||||
EventBufferRequest eventBufferReq;
|
||||
|
||||
enum class InternalState { SLEEPING, DEFAULT, DEDICATED_REQUEST, GO_TO_SLEEP };
|
||||
|
||||
enum class Request {
|
||||
DEFAULT,
|
||||
UPDATE,
|
||||
CONTINUE_UPDATE,
|
||||
REQUEST_EVENT_BUFFER,
|
||||
CHECK_MEMORY,
|
||||
};
|
||||
InternalState state = InternalState::SLEEPING;
|
||||
Request request = Request::DEFAULT;
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
SdCardManager* sdcMan = nullptr;
|
||||
#endif
|
||||
SimpleRingBuffer recRingBuf;
|
||||
std::array<uint8_t, 1200> cmdBuf = {};
|
||||
std::array<uint8_t, 2048> encodedSendBuf = {};
|
||||
std::array<uint8_t, 2048> recBuf = {};
|
||||
std::array<uint8_t, 2048> encodedBuf = {};
|
||||
std::array<uint8_t, 1200> decodedBuf = {};
|
||||
std::array<uint8_t, 1200> ipcBuffer = {};
|
||||
SimpleRingBuffer decodedRingBuf;
|
||||
FIFO<size_t, MAX_STORED_DECODED_PACKETS> decodedQueue;
|
||||
SimpleRingBuffer ipcRingBuf;
|
||||
FIFO<size_t, MAX_STORED_DECODED_PACKETS> ipcQueue;
|
||||
|
||||
SpacePacketCreator creator;
|
||||
supv::TcParams spParams = supv::TcParams(creator);
|
||||
|
||||
std::array<uint8_t, supv::MAX_COMMAND_SIZE> tmBuf{};
|
||||
|
||||
bool printTc = false;
|
||||
bool debugMode = false;
|
||||
bool timestamping = true;
|
||||
|
||||
// Remembers APID to know at which command a procedure failed
|
||||
uint16_t rememberApid = 0;
|
||||
|
||||
ReturnValue_t handleRunningLongerRequest();
|
||||
ReturnValue_t handleUartReception();
|
||||
void addHdlcFraming(const uint8_t* src, size_t slen, uint8_t* dst, size_t* dlen, size_t maxDest);
|
||||
int removeHdlcFramingWithCrcCheck(const uint8_t* src, size_t slen, uint8_t* dst, size_t* dlen);
|
||||
|
||||
ReturnValue_t encodeAndSendPacket(const uint8_t* sendData, size_t sendLen);
|
||||
void executeFullCheckMemoryCommand();
|
||||
|
||||
ReturnValue_t tryHdlcParsing();
|
||||
ReturnValue_t parseRecRingBufForHdlc(size_t& readSize, size_t& decodedLen);
|
||||
ReturnValue_t executeUpdate();
|
||||
ReturnValue_t continueUpdate();
|
||||
ReturnValue_t updateOperation();
|
||||
ReturnValue_t writeUpdatePackets();
|
||||
// ReturnValue_t performEventBufferRequest();
|
||||
ReturnValue_t handlePacketTransmissionNoReply(supv::TcBase& packet,
|
||||
uint32_t timeoutExecutionReport);
|
||||
int handleAckReception(supv::TcBase& tc, size_t packetLen);
|
||||
int handleExeAckReception(supv::TcBase& tc, size_t packetLen);
|
||||
|
||||
/**
|
||||
* @brief Handles reading of TM packets from the communication interface
|
||||
*
|
||||
* @param tmPacket Pointer to space packet where received data will be written to
|
||||
* @param reaminingBytes Number of bytes to read in the space packet
|
||||
* @param timeout Receive timeout in milliseconds
|
||||
*
|
||||
* @note It can take up to 70 seconds until the supervisor replies with an acknowledgment
|
||||
* failure report.
|
||||
*/
|
||||
ReturnValue_t handleTmReception(size_t remainingBytes, uint8_t* readBuf = nullptr,
|
||||
uint32_t timeout = 70000);
|
||||
ReturnValue_t checkReceivedTm();
|
||||
|
||||
ReturnValue_t selectMemory();
|
||||
ReturnValue_t prepareUpdate();
|
||||
ReturnValue_t eraseMemory();
|
||||
// Calculates CRC over image. Will be used for verification after update writing has
|
||||
// finished.
|
||||
ReturnValue_t calcImageCrc();
|
||||
ReturnValue_t handleCheckMemoryCommand(uint8_t failStep);
|
||||
ReturnValue_t exeReportHandling();
|
||||
/**
|
||||
* @brief Return size of file with name filename
|
||||
*
|
||||
* @param filename
|
||||
*
|
||||
* @return The size of the file
|
||||
*/
|
||||
uint32_t getFileSize(std::string filename);
|
||||
ReturnValue_t handleEventBufferReception(ploc::SpTmReader& reader);
|
||||
|
||||
void resetSpParams();
|
||||
void pushIpcData(const uint8_t* data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Device specific initialization, using the cookie.
|
||||
* @details
|
||||
* The cookie is already prepared in the factory. If the communication
|
||||
* interface needs to be set up in some way and requires cookie information,
|
||||
* this can be performed in this function, which is called on device handler
|
||||
* initialization.
|
||||
* @param cookie
|
||||
* @return
|
||||
* - @c returnvalue::OK if initialization was successfull
|
||||
* - Everything else triggers failure event with returnvalue as parameter 1
|
||||
*/
|
||||
ReturnValue_t initializeInterface(CookieIF* cookie) override;
|
||||
|
||||
/**
|
||||
* Called by DHB in the SEND_WRITE doSendWrite().
|
||||
* This function is used to send data to the physical device
|
||||
* by implementing and calling related drivers or wrapper functions.
|
||||
* @param cookie
|
||||
* @param data
|
||||
* @param len If this is 0, nothing shall be sent.
|
||||
* @return
|
||||
* - @c returnvalue::OK for successfull send
|
||||
* - Everything else triggers failure event with returnvalue as parameter 1
|
||||
*/
|
||||
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
|
||||
/**
|
||||
* Called by DHB in the GET_WRITE doGetWrite().
|
||||
* Get send confirmation that the data in sendMessage() was sent successfully.
|
||||
* @param cookie
|
||||
* @return
|
||||
* - @c returnvalue::OK if data was sent successfully but a reply is expected
|
||||
* - NO_REPLY_EXPECTED if data was sent successfully and no reply is expected
|
||||
* - Everything else to indicate failure
|
||||
*/
|
||||
ReturnValue_t getSendSuccess(CookieIF* cookie) override;
|
||||
/**
|
||||
* Called by DHB in the SEND_WRITE doSendRead().
|
||||
* It is assumed that it is always possible to request a reply
|
||||
* from a device. If a requestLen of 0 is supplied, no reply was enabled
|
||||
* and communication specific action should be taken (e.g. read nothing
|
||||
* or read everything).
|
||||
*
|
||||
* @param cookie
|
||||
* @param requestLen Size of data to read
|
||||
* @return - @c returnvalue::OK to confirm the request for data has been sent.
|
||||
* - Everything else triggers failure event with
|
||||
* returnvalue as parameter 1
|
||||
*/
|
||||
ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override;
|
||||
ReturnValue_t readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) override;
|
||||
|
||||
void performUartShutdown();
|
||||
void updateVtime(uint8_t vtime);
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_DEVICES_PLOCSUPVHELPER_H_ */
|
@ -34,15 +34,15 @@ ReturnValue_t ArcsecDatalinkLayer::decodeFrame(const uint8_t* rawData, size_t ra
|
||||
case ARC_DEC_SYNC: {
|
||||
// Reset length of SLIP struct for next frame
|
||||
slipInfo.length = 0;
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
default:
|
||||
sif::debug << "ArcsecDatalinkLayer::decodeFrame: Unknown result code" << std::endl;
|
||||
break;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
uint8_t ArcsecDatalinkLayer::getReplyFrameType() { return decodedFrame[0]; }
|
||||
|
@ -1,7 +1,8 @@
|
||||
#ifndef BSP_Q7S_DEVICES_ARCSECDATALINKLAYER_H_
|
||||
#define BSP_Q7S_DEVICES_ARCSECDATALINKLAYER_H_
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "eive/resultClassIds.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
|
||||
|
||||
extern "C" {
|
||||
@ -11,7 +12,7 @@ extern "C" {
|
||||
/**
|
||||
* @brief Helper class to handle the datalinklayer of replies from the star tracker of arcsec.
|
||||
*/
|
||||
class ArcsecDatalinkLayer : public HasReturnvaluesIF {
|
||||
class ArcsecDatalinkLayer {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::STR_HANDLER;
|
||||
|
||||
|
@ -5,15 +5,15 @@
|
||||
ArcsecJsonParamBase::ArcsecJsonParamBase(std::string setName) : setName(setName) {}
|
||||
|
||||
ReturnValue_t ArcsecJsonParamBase::create(std::string fullname, uint8_t* buffer) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
result = init(fullname);
|
||||
if (result != RETURN_OK) {
|
||||
sif::warning << "ArcsecJsonParamBase::create: Failed to init parameter command for set "
|
||||
<< setName << std::endl;
|
||||
return result;
|
||||
}
|
||||
result = createCommand(buffer);
|
||||
if (result != RETURN_OK) {
|
||||
// ReturnValue_t result = returnvalue::OK;
|
||||
// result = init(fullname);
|
||||
// if (result != returnvalue::OK) {
|
||||
// sif::warning << "ArcsecJsonParamBase::create: Failed to init parameter command for set "
|
||||
// << setName << std::endl;
|
||||
// return result;
|
||||
// }
|
||||
ReturnValue_t result = createCommand(buffer);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "ArcsecJsonParamBase::create: Failed to create parameter command for set "
|
||||
<< setName << std::endl;
|
||||
}
|
||||
@ -25,7 +25,7 @@ ReturnValue_t ArcsecJsonParamBase::getParam(const std::string name, std::string&
|
||||
if ((*it)[arcseckeys::NAME] == name) {
|
||||
value = (*it)[arcseckeys::VALUE];
|
||||
convertEmpty(value);
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
}
|
||||
return PARAM_NOT_EXISTS;
|
||||
@ -68,18 +68,23 @@ void ArcsecJsonParamBase::addSetParamHeader(uint8_t* buffer, uint8_t setId) {
|
||||
}
|
||||
|
||||
ReturnValue_t ArcsecJsonParamBase::init(const std::string filename) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
if (not std::filesystem::exists(filename)) {
|
||||
sif::warning << "ArcsecJsonParamBase::init: JSON file " << filename << " does not exist"
|
||||
<< std::endl;
|
||||
return JSON_FILE_NOT_EXISTS;
|
||||
}
|
||||
createJsonObject(filename);
|
||||
result = initSet();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
try {
|
||||
createJsonObject(filename);
|
||||
result = initSet();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
} catch (json::exception& e) {
|
||||
// TODO: Re-create json file from backup here.
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void ArcsecJsonParamBase::createJsonObject(const std::string fullname) {
|
||||
@ -94,7 +99,7 @@ ReturnValue_t ArcsecJsonParamBase::initSet() {
|
||||
for (json::iterator it = properties.begin(); it != properties.end(); ++it) {
|
||||
if ((*it)["name"] == setName) {
|
||||
set = (*it)["fields"];
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
}
|
||||
sif::warning << "ArcsecJsonParamBase::initSet: Set " << setName << "not present in json file"
|
||||
|
@ -5,7 +5,8 @@
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "eive/resultClassIds.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
|
||||
|
||||
extern "C" {
|
||||
@ -22,7 +23,7 @@ using json = nlohmann::json;
|
||||
*
|
||||
* @author J. Meier
|
||||
*/
|
||||
class ArcsecJsonParamBase : public HasReturnvaluesIF {
|
||||
class ArcsecJsonParamBase {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ARCSEC_JSON_BASE;
|
||||
//! [EXPORT] : [COMMENT] Specified json file does not exist
|
||||
@ -32,6 +33,7 @@ class ArcsecJsonParamBase : public HasReturnvaluesIF {
|
||||
//! [EXPORT] : [COMMENT] Requested parameter does not exist in json file
|
||||
static const ReturnValue_t PARAM_NOT_EXISTS = MAKE_RETURN_CODE(3);
|
||||
|
||||
virtual ~ArcsecJsonParamBase() = default;
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
@ -39,6 +41,17 @@ class ArcsecJsonParamBase : public HasReturnvaluesIF {
|
||||
*/
|
||||
ArcsecJsonParamBase(std::string setName);
|
||||
|
||||
/**
|
||||
* @brief Initializes the properties json object and the set json object
|
||||
*
|
||||
* @param fullname Name including absolute path to json file
|
||||
* @param setName The name of the set to work on
|
||||
*
|
||||
* @param return JSON_FILE_NOT_EXISTS if specified file does not exist, otherwise
|
||||
* returnvalue::OK
|
||||
*/
|
||||
ReturnValue_t init(const std::string filename);
|
||||
|
||||
/**
|
||||
* @brief Fills a buffer with a parameter set
|
||||
*
|
||||
@ -60,7 +73,7 @@ class ArcsecJsonParamBase : public HasReturnvaluesIF {
|
||||
* @param name The name of the parameter
|
||||
* @param value The string representation of the read value
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise PARAM_NOT_EXISTS
|
||||
* @return returnvalue::OK if successful, otherwise PARAM_NOT_EXISTS
|
||||
*/
|
||||
ReturnValue_t getParam(const std::string name, std::string& value);
|
||||
|
||||
@ -122,17 +135,6 @@ class ArcsecJsonParamBase : public HasReturnvaluesIF {
|
||||
*/
|
||||
virtual ReturnValue_t createCommand(uint8_t* buffer) = 0;
|
||||
|
||||
/**
|
||||
* @brief Initializes the properties json object and the set json object
|
||||
*
|
||||
* @param fullname Name including absolute path to json file
|
||||
* @param setName The name of the set to work on
|
||||
*
|
||||
* @param return JSON_FILE_NOT_EXISTS if specified file does not exist, otherwise
|
||||
* RETURN_OK
|
||||
*/
|
||||
ReturnValue_t init(const std::string filename);
|
||||
|
||||
void createJsonObject(const std::string fullname);
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,4 @@
|
||||
target_sources(${OBSW_NAME} PRIVATE
|
||||
StarTrackerHandler.cpp
|
||||
StarTrackerJsonCommands.cpp
|
||||
ArcsecDatalinkLayer.cpp
|
||||
ArcsecJsonParamBase.cpp
|
||||
StrHelper.cpp
|
||||
)
|
||||
target_sources(
|
||||
${OBSW_NAME}
|
||||
PRIVATE StarTrackerHandler.cpp StarTrackerJsonCommands.cpp
|
||||
ArcsecDatalinkLayer.cpp ArcsecJsonParamBase.cpp StrHelper.cpp)
|
||||
|
@ -1,8 +1,11 @@
|
||||
#include "StarTrackerHandler.h"
|
||||
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "StarTrackerJsonCommands.h"
|
||||
@ -14,8 +17,11 @@ extern "C" {
|
||||
#include "common/misc.h"
|
||||
}
|
||||
|
||||
std::atomic_bool JCFG_DONE(false);
|
||||
|
||||
StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
|
||||
StrHelper* strHelper, power::Switch_t powerSwitch)
|
||||
const char* jsonFileStr, StrHelper* strHelper,
|
||||
power::Switch_t powerSwitch)
|
||||
: DeviceHandlerBase(objectId, comIF, comCookie),
|
||||
temperatureSet(this),
|
||||
versionSet(this),
|
||||
@ -40,6 +46,7 @@ StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF,
|
||||
logSubscriptionSet(this),
|
||||
debugCameraSet(this),
|
||||
strHelper(strHelper),
|
||||
paramJsonFile(jsonFileStr),
|
||||
powerSwitch(powerSwitch) {
|
||||
if (comCookie == nullptr) {
|
||||
sif::error << "StarTrackerHandler: Invalid com cookie" << std::endl;
|
||||
@ -53,12 +60,17 @@ StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF,
|
||||
StarTrackerHandler::~StarTrackerHandler() {}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::initialize() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = DeviceHandlerBase::initialize();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Spin up a thread to do the JSON initialization, takes 200-250 ms which would
|
||||
// delay whole satellite boot process.
|
||||
jcfgCountdown.resetTimer();
|
||||
jsonCfgTask = std::thread{setUpJsonCfgs, std::ref(jcfgs), paramJsonFile.c_str()};
|
||||
|
||||
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
||||
if (manager == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
@ -68,13 +80,13 @@ ReturnValue_t StarTrackerHandler::initialize() {
|
||||
;
|
||||
}
|
||||
result = manager->registerListener(eventQueue->getId());
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = manager->subscribeToEventRange(eventQueue->getId(),
|
||||
event::getEventId(StrHelper::IMAGE_UPLOAD_FAILED),
|
||||
event::getEventId(StrHelper::FIRMWARE_UPDATE_FAILED));
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "StarTrackerHandler::initialize: Failed to subscribe to events from "
|
||||
" str helper"
|
||||
@ -84,16 +96,16 @@ ReturnValue_t StarTrackerHandler::initialize() {
|
||||
}
|
||||
|
||||
result = strHelper->setComIF(communicationInterface);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
strHelper->setComCookie(comCookie);
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
switch (actionId) {
|
||||
case (startracker::STOP_IMAGE_LOADER): {
|
||||
@ -122,12 +134,12 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
}
|
||||
|
||||
result = checkMode(actionId);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = checkCommand(actionId);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -135,14 +147,14 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
switch (actionId) {
|
||||
case (startracker::UPLOAD_IMAGE): {
|
||||
result = DeviceHandlerBase::acceptExternalDeviceCommands();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (size > MAX_PATH_SIZE + MAX_FILE_NAME) {
|
||||
return FILE_PATH_TOO_LONG;
|
||||
}
|
||||
result = strHelper->startImageUpload(std::string(reinterpret_cast<const char*>(data), size));
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
strHelperExecuting = true;
|
||||
@ -150,7 +162,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
}
|
||||
case (startracker::DOWNLOAD_IMAGE): {
|
||||
result = DeviceHandlerBase::acceptExternalDeviceCommands();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (size > MAX_PATH_SIZE) {
|
||||
@ -158,7 +170,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
}
|
||||
result =
|
||||
strHelper->startImageDownload(std::string(reinterpret_cast<const char*>(data), size));
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
strHelperExecuting = true;
|
||||
@ -166,11 +178,11 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
}
|
||||
case (startracker::FLASH_READ): {
|
||||
result = DeviceHandlerBase::acceptExternalDeviceCommands();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = executeFlashReadCommand(data, size);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
strHelperExecuting = true;
|
||||
@ -192,7 +204,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
}
|
||||
case (startracker::FIRMWARE_UPDATE): {
|
||||
result = DeviceHandlerBase::acceptExternalDeviceCommands();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (size > MAX_PATH_SIZE + MAX_FILE_NAME) {
|
||||
@ -200,7 +212,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
}
|
||||
result =
|
||||
strHelper->startFirmwareUpdate(std::string(reinterpret_cast<const char*>(data), size));
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
strHelperExecuting = true;
|
||||
@ -214,7 +226,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
|
||||
void StarTrackerHandler::performOperationHook() {
|
||||
EventMessage event;
|
||||
for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == RETURN_OK;
|
||||
for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK;
|
||||
result = eventQueue->receiveMessage(&event)) {
|
||||
switch (event.getMessageId()) {
|
||||
case EventMessage::EVENT_MESSAGE:
|
||||
@ -240,13 +252,23 @@ void StarTrackerHandler::doStartUp() {
|
||||
// the device handler's submode to the star tracker's mode
|
||||
return;
|
||||
case StartupState::DONE:
|
||||
submode = SUBMODE_BOOTLOADER;
|
||||
if (jcfgCountdown.isBusy()) {
|
||||
startupState = StartupState::WAIT_JCFG;
|
||||
return;
|
||||
}
|
||||
startupState = StartupState::IDLE;
|
||||
break;
|
||||
case StartupState::WAIT_JCFG: {
|
||||
if (jcfgCountdown.hasTimedOut()) {
|
||||
startupState = StartupState::IDLE;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
setMode(_MODE_TO_ON);
|
||||
setMode(_MODE_TO_ON, SUBMODE_BOOTLOADER);
|
||||
}
|
||||
|
||||
void StarTrackerHandler::doShutDown() {
|
||||
@ -385,120 +407,106 @@ ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t
|
||||
ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
||||
const uint8_t* commandData,
|
||||
size_t commandDataLen) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
switch (deviceCommand) {
|
||||
case (startracker::PING_REQUEST): {
|
||||
preparePingRequest();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::REQ_TIME): {
|
||||
prepareTimeRequest();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::BOOT): {
|
||||
prepareBootCommand();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::REQ_VERSION): {
|
||||
prepareVersionRequest();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::REQ_INTERFACE): {
|
||||
prepareInterfaceRequest();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::REQ_POWER): {
|
||||
preparePowerRequest();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::SWITCH_TO_BOOTLOADER_PROGRAM): {
|
||||
prepareSwitchToBootloaderCmd();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::TAKE_IMAGE): {
|
||||
prepareTakeImageCommand(commandData);
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::SUBSCRIPTION): {
|
||||
Subscription subscription;
|
||||
result = prepareParamCommand(commandData, commandDataLen, subscription);
|
||||
return RETURN_OK;
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.subscription);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::REQ_SOLUTION): {
|
||||
prepareSolutionRequest();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::REQ_TEMPERATURE): {
|
||||
prepareTemperatureRequest();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::REQ_HISTOGRAM): {
|
||||
prepareHistogramRequest();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::LIMITS): {
|
||||
Limits limits;
|
||||
result = prepareParamCommand(commandData, commandDataLen, limits);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.limits);
|
||||
return result;
|
||||
}
|
||||
case (startracker::MOUNTING): {
|
||||
Mounting mounting;
|
||||
result = prepareParamCommand(commandData, commandDataLen, mounting);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.mounting);
|
||||
return result;
|
||||
}
|
||||
case (startracker::IMAGE_PROCESSOR): {
|
||||
ImageProcessor imageProcessor;
|
||||
result = prepareParamCommand(commandData, commandDataLen, imageProcessor);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.imageProcessor);
|
||||
return result;
|
||||
}
|
||||
case (startracker::CAMERA): {
|
||||
Camera camera;
|
||||
result = prepareParamCommand(commandData, commandDataLen, camera);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.camera);
|
||||
return result;
|
||||
}
|
||||
case (startracker::CENTROIDING): {
|
||||
Centroiding centroiding;
|
||||
result = prepareParamCommand(commandData, commandDataLen, centroiding);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.centroiding);
|
||||
return result;
|
||||
}
|
||||
case (startracker::LISA): {
|
||||
Lisa lisa;
|
||||
result = prepareParamCommand(commandData, commandDataLen, lisa);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.lisa);
|
||||
return result;
|
||||
}
|
||||
case (startracker::MATCHING): {
|
||||
Matching matching;
|
||||
result = prepareParamCommand(commandData, commandDataLen, matching);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.matching);
|
||||
return result;
|
||||
}
|
||||
case (startracker::VALIDATION): {
|
||||
Validation validation;
|
||||
result = prepareParamCommand(commandData, commandDataLen, validation);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.validation);
|
||||
return result;
|
||||
}
|
||||
case (startracker::ALGO): {
|
||||
Algo algo;
|
||||
result = prepareParamCommand(commandData, commandDataLen, algo);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.algo);
|
||||
return result;
|
||||
}
|
||||
case (startracker::TRACKING): {
|
||||
Tracking tracking;
|
||||
result = prepareParamCommand(commandData, commandDataLen, tracking);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.tracking);
|
||||
return result;
|
||||
}
|
||||
case (startracker::LOGLEVEL): {
|
||||
LogLevel logLevel;
|
||||
result = prepareParamCommand(commandData, commandDataLen, logLevel);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logLevel);
|
||||
return result;
|
||||
}
|
||||
case (startracker::LOGSUBSCRIPTION): {
|
||||
LogSubscription logSubscription;
|
||||
result = prepareParamCommand(commandData, commandDataLen, logSubscription);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logSubscription);
|
||||
return result;
|
||||
}
|
||||
case (startracker::DEBUG_CAMERA): {
|
||||
DebugCamera debugCamera;
|
||||
result = prepareParamCommand(commandData, commandDataLen, debugCamera);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.debugCamera);
|
||||
return result;
|
||||
}
|
||||
case (startracker::CHECKSUM): {
|
||||
@ -564,7 +572,7 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
|
||||
default:
|
||||
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
void StarTrackerHandler::fillCommandAndReplyMap() {
|
||||
@ -654,7 +662,7 @@ void StarTrackerHandler::fillCommandAndReplyMap() {
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::isModeCombinationValid(Mode_t mode, Submode_t submode) {
|
||||
if (this->mode == MODE_NORMAL && mode == MODE_ON) {
|
||||
if (getMode() == MODE_NORMAL && mode == MODE_ON) {
|
||||
return TRANS_NOT_ALLOWED;
|
||||
}
|
||||
switch (mode) {
|
||||
@ -662,13 +670,13 @@ ReturnValue_t StarTrackerHandler::isModeCombinationValid(Mode_t mode, Submode_t
|
||||
case MODE_NORMAL:
|
||||
case MODE_RAW:
|
||||
if (submode == SUBMODE_NONE) {
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
} else {
|
||||
return INVALID_SUBMODE;
|
||||
}
|
||||
case MODE_ON:
|
||||
if (submode == SUBMODE_BOOTLOADER || submode == SUBMODE_FIRMWARE) {
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
} else {
|
||||
return INVALID_SUBMODE;
|
||||
}
|
||||
@ -678,7 +686,7 @@ ReturnValue_t StarTrackerHandler::isModeCombinationValid(Mode_t mode, Submode_t
|
||||
}
|
||||
|
||||
void StarTrackerHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
|
||||
switch (mode) {
|
||||
switch (getMode()) {
|
||||
case _MODE_TO_ON:
|
||||
doOnTransition(subModeFrom);
|
||||
break;
|
||||
@ -698,17 +706,18 @@ void StarTrackerHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
|
||||
}
|
||||
|
||||
void StarTrackerHandler::doOnTransition(Submode_t subModeFrom) {
|
||||
if (submode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_FIRMWARE) {
|
||||
uint8_t dhbSubmode = getSubmode();
|
||||
if (dhbSubmode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_FIRMWARE) {
|
||||
bootBootloader();
|
||||
} else if (submode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_FIRMWARE) {
|
||||
} else if (dhbSubmode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_FIRMWARE) {
|
||||
setMode(MODE_ON);
|
||||
} else if (submode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_BOOTLOADER) {
|
||||
} else if (dhbSubmode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_BOOTLOADER) {
|
||||
bootFirmware(MODE_ON);
|
||||
} else if (submode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_BOOTLOADER) {
|
||||
} else if (dhbSubmode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_BOOTLOADER) {
|
||||
setMode(MODE_ON);
|
||||
} else if (submode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_NONE) {
|
||||
} else if (dhbSubmode == SUBMODE_BOOTLOADER && subModeFrom == SUBMODE_NONE) {
|
||||
setMode(MODE_ON);
|
||||
} else if (submode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_NONE) {
|
||||
} else if (dhbSubmode == SUBMODE_FIRMWARE && subModeFrom == SUBMODE_NONE) {
|
||||
setMode(MODE_ON);
|
||||
}
|
||||
}
|
||||
@ -746,6 +755,24 @@ void StarTrackerHandler::bootFirmware(Mode_t toMode) {
|
||||
}
|
||||
}
|
||||
|
||||
void StarTrackerHandler::setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonFile) {
|
||||
cfgs.tracking.init(paramJsonFile);
|
||||
cfgs.logLevel.init(paramJsonFile);
|
||||
cfgs.logSubscription.init(paramJsonFile);
|
||||
cfgs.debugCamera.init(paramJsonFile);
|
||||
cfgs.algo.init(paramJsonFile);
|
||||
cfgs.validation.init(paramJsonFile);
|
||||
cfgs.matching.init(paramJsonFile);
|
||||
cfgs.lisa.init(paramJsonFile);
|
||||
cfgs.centroiding.init(paramJsonFile);
|
||||
cfgs.camera.init(paramJsonFile);
|
||||
cfgs.imageProcessor.init(paramJsonFile);
|
||||
cfgs.mounting.init(paramJsonFile);
|
||||
cfgs.limits.init(paramJsonFile);
|
||||
cfgs.subscription.init(paramJsonFile);
|
||||
JCFG_DONE = true;
|
||||
}
|
||||
|
||||
void StarTrackerHandler::bootBootloader() {
|
||||
if (internalState == InternalState::IDLE) {
|
||||
internalState = InternalState::BOOT_BOOTLOADER;
|
||||
@ -759,7 +786,7 @@ void StarTrackerHandler::bootBootloader() {
|
||||
|
||||
ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t remainingSize,
|
||||
DeviceCommandId_t* foundId, size_t* foundLen) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
size_t bytesLeft = 0;
|
||||
|
||||
result = dataLinkLayer.decodeFrame(start, remainingSize, &bytesLeft);
|
||||
@ -769,7 +796,7 @@ ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t rema
|
||||
// Need a second doSendRead pass to reaa in whole packet
|
||||
return IGNORE_REPLY_DATA;
|
||||
}
|
||||
case RETURN_OK: {
|
||||
case returnvalue::OK: {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -801,7 +828,7 @@ ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t rema
|
||||
}
|
||||
default: {
|
||||
sif::debug << "StarTrackerHandler::scanForReply: Reply has invalid type id" << std::endl;
|
||||
result = RETURN_FAILED;
|
||||
result = returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -812,7 +839,7 @@ ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t rema
|
||||
|
||||
ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||
const uint8_t* packet) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
switch (id) {
|
||||
case (startracker::REQ_TIME): {
|
||||
@ -832,11 +859,11 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||
}
|
||||
case (startracker::REQ_VERSION): {
|
||||
result = handleTm(versionSet, startracker::VersionSet::SIZE);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = checkProgram();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
@ -1209,7 +1236,22 @@ ReturnValue_t StarTrackerHandler::initializeLocalDataPool(localpool::DataPool& l
|
||||
localDataPoolMap.emplace(startracker::DEBUG_CAMERA_TEST, new PoolEntry<uint32_t>({0}));
|
||||
|
||||
localDataPoolMap.emplace(startracker::CHKSUM, new PoolEntry<uint32_t>({0}));
|
||||
return RETURN_OK;
|
||||
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(temperatureSet.getSid(), false, 10.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(powerSet.getSid(), false, 10.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(interfaceSet.getSid(), false, 10.0));
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(solutionSet.getSid(), false, 5.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(cameraSet.getSid(), false, 10.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(histogramSet.getSid(), false, 10.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(lisaSet.getSid(), false, 10.0));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
size_t StarTrackerHandler::getNextReplyLength(DeviceCommandId_t commandId) {
|
||||
@ -1219,9 +1261,9 @@ size_t StarTrackerHandler::getNextReplyLength(DeviceCommandId_t commandId) {
|
||||
ReturnValue_t StarTrackerHandler::doSendReadHook() {
|
||||
// Prevent DHB from polling UART during commands executed by the image loader task
|
||||
if (strHelperExecuting) {
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::getSwitches(const uint8_t** switches, uint8_t* numberOfSwitches) {
|
||||
@ -1230,7 +1272,7 @@ ReturnValue_t StarTrackerHandler::getSwitches(const uint8_t** switches, uint8_t*
|
||||
}
|
||||
*numberOfSwitches = 1;
|
||||
*switches = &powerSwitch;
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::checkMode(ActionId_t actionId) {
|
||||
@ -1244,7 +1286,7 @@ ReturnValue_t StarTrackerHandler::checkMode(ActionId_t actionId) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::scanForActionReply(DeviceCommandId_t* foundId) {
|
||||
@ -1273,9 +1315,9 @@ ReturnValue_t StarTrackerHandler::scanForActionReply(DeviceCommandId_t* foundId)
|
||||
default:
|
||||
sif::warning << "StarTrackerHandler::scanForActionReply: Unknown parameter reply id"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::scanForSetParameterReply(DeviceCommandId_t* foundId) {
|
||||
@ -1340,9 +1382,9 @@ ReturnValue_t StarTrackerHandler::scanForSetParameterReply(DeviceCommandId_t* fo
|
||||
default:
|
||||
sif::debug << "StarTrackerHandler::scanForParameterReply: Unknown parameter reply id"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::scanForGetParameterReply(DeviceCommandId_t* foundId) {
|
||||
@ -1406,11 +1448,11 @@ ReturnValue_t StarTrackerHandler::scanForGetParameterReply(DeviceCommandId_t* fo
|
||||
}
|
||||
default: {
|
||||
sif::warning << "tarTrackerHandler::scanForGetParameterReply: UnkNown ID" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::scanForTmReply(DeviceCommandId_t* foundId) {
|
||||
@ -1447,11 +1489,11 @@ ReturnValue_t StarTrackerHandler::scanForTmReply(DeviceCommandId_t* foundId) {
|
||||
default: {
|
||||
sif::debug << "StarTrackerHandler::scanForTmReply: Reply contains invalid reply id: "
|
||||
<< static_cast<unsigned int>(*reply) << std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void StarTrackerHandler::handleEvent(EventMessage* eventMessage) {
|
||||
@ -1471,7 +1513,7 @@ void StarTrackerHandler::handleEvent(EventMessage* eventMessage) {
|
||||
|
||||
ReturnValue_t StarTrackerHandler::executeFlashReadCommand(const uint8_t* commandData,
|
||||
size_t commandDataLen) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
if (commandDataLen < FlashReadCmd::MIN_LENGTH) {
|
||||
sif::warning << "StarTrackerHandler::executeFlashReadCommand: Command too short" << std::endl;
|
||||
return COMMAND_TOO_SHORT;
|
||||
@ -1481,7 +1523,7 @@ ReturnValue_t StarTrackerHandler::executeFlashReadCommand(const uint8_t* command
|
||||
size_t size = sizeof(length);
|
||||
const uint8_t* lengthPtr = commandData + sizeof(startRegion);
|
||||
result = SerializeAdapter::deSerialize(&length, lengthPtr, &size, SerializeIF::Endianness::BIG);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::debug << "StarTrackerHandler::executeFlashReadCommand: Deserialization of length failed"
|
||||
<< std::endl;
|
||||
return result;
|
||||
@ -1495,7 +1537,7 @@ ReturnValue_t StarTrackerHandler::executeFlashReadCommand(const uint8_t* command
|
||||
std::string fullname = std::string(reinterpret_cast<const char*>(filePtr),
|
||||
commandDataLen - sizeof(startRegion) - sizeof(length));
|
||||
result = strHelper->startFlashRead(fullname, startRegion, length);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
@ -1513,7 +1555,7 @@ void StarTrackerHandler::prepareBootCommand() {
|
||||
ReturnValue_t StarTrackerHandler::prepareChecksumCommand(const uint8_t* commandData,
|
||||
size_t commandDataLen) {
|
||||
struct ChecksumActionRequest req;
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
if (commandDataLen != ChecksumCmd::LENGTH) {
|
||||
sif::warning << "StarTrackerHandler::prepareChecksumCommand: Invalid length" << std::endl;
|
||||
return INVALID_LENGTH;
|
||||
@ -1523,7 +1565,7 @@ ReturnValue_t StarTrackerHandler::prepareChecksumCommand(const uint8_t* commandD
|
||||
const uint8_t* addressPtr = commandData + ChecksumCmd::ADDRESS_OFFSET;
|
||||
result =
|
||||
SerializeAdapter::deSerialize(&req.address, addressPtr, &size, SerializeIF::Endianness::BIG);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::debug << "StarTrackerHandler::prepareChecksumCommand: Deserialization of address "
|
||||
<< "failed" << std::endl;
|
||||
return result;
|
||||
@ -1532,7 +1574,7 @@ ReturnValue_t StarTrackerHandler::prepareChecksumCommand(const uint8_t* commandD
|
||||
const uint8_t* lengthPtr = commandData + ChecksumCmd::LENGTH_OFFSET;
|
||||
result =
|
||||
SerializeAdapter::deSerialize(&req.length, lengthPtr, &size, SerializeIF::Endianness::BIG);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::debug << "StarTrackerHandler::prepareChecksumCommand: Deserialization of length failed"
|
||||
<< std::endl;
|
||||
return result;
|
||||
@ -1591,7 +1633,7 @@ void StarTrackerHandler::preparePowerRequest() {
|
||||
|
||||
void StarTrackerHandler::prepareSwitchToBootloaderCmd() {
|
||||
uint32_t length = 0;
|
||||
struct RebootActionRequest rebootReq;
|
||||
struct RebootActionRequest rebootReq {};
|
||||
arc_pack_reboot_action_req(&rebootReq, commandBuffer, &length);
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
@ -1635,20 +1677,21 @@ void StarTrackerHandler::prepareHistogramRequest() {
|
||||
ReturnValue_t StarTrackerHandler::prepareParamCommand(const uint8_t* commandData,
|
||||
size_t commandDataLen,
|
||||
ArcsecJsonParamBase& paramSet) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
// Stopwatch watch;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
if (commandDataLen > MAX_PATH_SIZE) {
|
||||
return FILE_PATH_TOO_LONG;
|
||||
}
|
||||
std::string fullName(reinterpret_cast<const char*>(commandData), commandDataLen);
|
||||
|
||||
result = paramSet.create(fullName, commandBuffer);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
dataLinkLayer.encodeFrame(commandBuffer, paramSet.getSize());
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestCameraParams() {
|
||||
@ -1657,7 +1700,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestCameraParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestLimitsParams() {
|
||||
@ -1666,7 +1709,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestLimitsParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestLogLevelParams() {
|
||||
@ -1675,7 +1718,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestLogLevelParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestMountingParams() {
|
||||
@ -1684,7 +1727,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestMountingParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestImageProcessorParams() {
|
||||
@ -1693,7 +1736,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestImageProcessorParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestCentroidingParams() {
|
||||
@ -1702,7 +1745,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestCentroidingParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestLisaParams() {
|
||||
@ -1711,7 +1754,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestLisaParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestMatchingParams() {
|
||||
@ -1720,7 +1763,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestMatchingParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestTrackingParams() {
|
||||
@ -1729,7 +1772,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestTrackingParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestValidationParams() {
|
||||
@ -1738,7 +1781,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestValidationParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestAlgoParams() {
|
||||
@ -1747,7 +1790,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestAlgoParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestSubscriptionParams() {
|
||||
@ -1756,7 +1799,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestSubscriptionParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestLogSubscriptionParams() {
|
||||
@ -1765,7 +1808,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestLogSubscriptionParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareRequestDebugCameraParams() {
|
||||
@ -1774,7 +1817,7 @@ ReturnValue_t StarTrackerHandler::prepareRequestDebugCameraParams() {
|
||||
dataLinkLayer.encodeFrame(commandBuffer, length);
|
||||
rawPacket = dataLinkLayer.getEncodedFrame();
|
||||
rawPacketLen = dataLinkLayer.getEncodedLength();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::handleSetParamReply() {
|
||||
@ -1792,7 +1835,7 @@ ReturnValue_t StarTrackerHandler::handleSetParamReply() {
|
||||
if (internalState != InternalState::IDLE) {
|
||||
handleStartup(reply + PARAMETER_ID_OFFSET);
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::handleActionReply() {
|
||||
@ -1805,13 +1848,13 @@ ReturnValue_t StarTrackerHandler::handleActionReply() {
|
||||
<< static_cast<unsigned int>(status) << std::endl;
|
||||
return ACTION_FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::handleChecksumReply() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = handleActionReply();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
const uint8_t* replyData = dataLinkLayer.getReply() + ACTION_DATA_OFFSET;
|
||||
@ -1830,29 +1873,29 @@ ReturnValue_t StarTrackerHandler::handleChecksumReply() {
|
||||
}
|
||||
PoolReadGuard rg(&checksumSet);
|
||||
checksumSet.checksum = checksumReply.getChecksum();
|
||||
handleDeviceTM(&checksumSet, startracker::CHECKSUM);
|
||||
handleDeviceTm(checksumSet, startracker::CHECKSUM);
|
||||
#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1
|
||||
checksumReply.printChecksum();
|
||||
#endif /* OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1 */
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::handleParamRequest(LocalPoolDataSetBase& dataset, size_t size) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = dataset.read(TIMEOUT_TYPE, MUTEX_TIMEOUT);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
const uint8_t* reply = dataLinkLayer.getReply() + PARAMS_OFFSET;
|
||||
dataset.setValidityBufferGeneration(false);
|
||||
result = dataset.deSerialize(&reply, &size, SerializeIF::Endianness::LITTLE);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "StarTrackerHandler::handleParamRequest Deserialization failed" << std::endl;
|
||||
}
|
||||
dataset.setValidityBufferGeneration(true);
|
||||
dataset.setValidity(true, true);
|
||||
result = dataset.commit(TIMEOUT_TYPE, MUTEX_TIMEOUT);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1
|
||||
@ -1862,7 +1905,7 @@ ReturnValue_t StarTrackerHandler::handleParamRequest(LocalPoolDataSetBase& datas
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::handlePingReply() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
uint32_t pingId = 0;
|
||||
const uint8_t* reply = dataLinkLayer.getReply();
|
||||
uint8_t status = dataLinkLayer.getStatusField();
|
||||
@ -1894,7 +1937,7 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
|
||||
if (internalState == InternalState::VERIFY_BOOT) {
|
||||
sif::warning << "StarTrackerHandler::checkProgram: Failed to boot firmware" << std::endl;
|
||||
// Device handler will run into timeout and fall back to transition source mode
|
||||
triggerEvent(BOOTING_FIRMWARE_FAILED);
|
||||
triggerEvent(BOOTING_FIRMWARE_FAILED_EVENT);
|
||||
internalState = InternalState::FAILED_FIRMWARE_BOOT;
|
||||
} else if (internalState == InternalState::BOOTLOADER_CHECK) {
|
||||
internalState = InternalState::DONE;
|
||||
@ -1907,7 +1950,7 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
|
||||
if (internalState == InternalState::VERIFY_BOOT) {
|
||||
internalState = InternalState::LOGLEVEL;
|
||||
} else if (internalState == InternalState::BOOTLOADER_CHECK) {
|
||||
triggerEvent(BOOTING_BOOTLOADER_FAILED);
|
||||
triggerEvent(BOOTING_BOOTLOADER_FAILED_EVENT);
|
||||
internalState = InternalState::BOOTING_BOOTLOADER_FAILED;
|
||||
}
|
||||
break;
|
||||
@ -1916,11 +1959,11 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
|
||||
<< std::endl;
|
||||
return INVALID_PROGRAM;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::handleTm(LocalPoolDataSetBase& dataset, size_t size) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
uint8_t status = *(dataLinkLayer.getReply() + STATUS_OFFSET);
|
||||
if (status != startracker::STATUS_OK) {
|
||||
sif::warning << "StarTrackerHandler::handleTm: Reply error: "
|
||||
@ -1928,19 +1971,19 @@ ReturnValue_t StarTrackerHandler::handleTm(LocalPoolDataSetBase& dataset, size_t
|
||||
return REPLY_ERROR;
|
||||
}
|
||||
result = dataset.read(TIMEOUT_TYPE, MUTEX_TIMEOUT);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
const uint8_t* reply = dataLinkLayer.getReply() + TICKS_OFFSET;
|
||||
dataset.setValidityBufferGeneration(false);
|
||||
result = dataset.deSerialize(&reply, &size, SerializeIF::Endianness::LITTLE);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "StarTrackerHandler::handleTm: Deserialization failed" << std::endl;
|
||||
}
|
||||
dataset.setValidityBufferGeneration(true);
|
||||
dataset.setValidity(true, true);
|
||||
result = dataset.commit(TIMEOUT_TYPE, MUTEX_TIMEOUT);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1
|
||||
@ -1950,7 +1993,7 @@ ReturnValue_t StarTrackerHandler::handleTm(LocalPoolDataSetBase& dataset, size_t
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::handleActionReplySet(LocalPoolDataSetBase& dataset, size_t size) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
uint8_t status = *(dataLinkLayer.getReply() + STATUS_OFFSET);
|
||||
if (status != startracker::STATUS_OK) {
|
||||
sif::warning << "StarTrackerHandler::handleActionReplySet: Reply error: "
|
||||
@ -1958,19 +2001,19 @@ ReturnValue_t StarTrackerHandler::handleActionReplySet(LocalPoolDataSetBase& dat
|
||||
return REPLY_ERROR;
|
||||
}
|
||||
result = dataset.read(TIMEOUT_TYPE, MUTEX_TIMEOUT);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
const uint8_t* reply = dataLinkLayer.getReply() + ACTION_DATA_OFFSET;
|
||||
dataset.setValidityBufferGeneration(false);
|
||||
result = dataset.deSerialize(&reply, &size, SerializeIF::Endianness::LITTLE);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "StarTrackerHandler::handleActionReplySet Deserialization failed" << std::endl;
|
||||
}
|
||||
dataset.setValidityBufferGeneration(true);
|
||||
dataset.setValidity(true, true);
|
||||
result = dataset.commit(TIMEOUT_TYPE, MUTEX_TIMEOUT);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
#if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_STARTRACKER == 1
|
||||
@ -2067,18 +2110,18 @@ ReturnValue_t StarTrackerHandler::checkCommand(ActionId_t actionId) {
|
||||
case startracker::REQ_SUBSCRIPTION:
|
||||
case startracker::REQ_LOG_SUBSCRIPTION:
|
||||
case startracker::REQ_DEBUG_CAMERA:
|
||||
if (not(mode == MODE_ON && submode == startracker::Program::FIRMWARE)) {
|
||||
if (not(getMode() == MODE_ON && getSubmode() == startracker::Program::FIRMWARE)) {
|
||||
return STARTRACKER_RUNNING_BOOTLOADER;
|
||||
}
|
||||
break;
|
||||
case startracker::FIRMWARE_UPDATE:
|
||||
case startracker::FLASH_READ:
|
||||
if (not(mode == MODE_ON && submode == startracker::Program::BOOTLOADER)) {
|
||||
if (not(getMode() == MODE_ON && getSubmode() == startracker::Program::BOOTLOADER)) {
|
||||
return STARTRACKER_RUNNING_FIRMWARE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -2,6 +2,9 @@
|
||||
#define MISSION_DEVICES_STARTRACKERHANDLER_H_
|
||||
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <linux/devices/startracker/StarTrackerJsonCommands.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "ArcsecDatalinkLayer.h"
|
||||
#include "ArcsecJsonParamBase.h"
|
||||
@ -35,7 +38,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
* to high to enable the device.
|
||||
*/
|
||||
StarTrackerHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
|
||||
StrHelper* strHelper, power::Switch_t powerSwitch);
|
||||
const char* jsonFileStr, StrHelper* strHelper, power::Switch_t powerSwitch);
|
||||
virtual ~StarTrackerHandler();
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
@ -72,7 +75,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
/**
|
||||
* @brief Overwritten here to always read all available data from the UartComIF.
|
||||
* @brief Overwritten here to always read all available data from theSerialComIF.
|
||||
*/
|
||||
virtual size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override;
|
||||
virtual ReturnValue_t doSendReadHook() override;
|
||||
@ -140,9 +143,9 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::STR_HANDLER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] Failed to boot firmware
|
||||
static const Event BOOTING_FIRMWARE_FAILED = MAKE_EVENT(1, severity::LOW);
|
||||
static const Event BOOTING_FIRMWARE_FAILED_EVENT = MAKE_EVENT(1, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Failed to boot star tracker into bootloader mode
|
||||
static const Event BOOTING_BOOTLOADER_FAILED = MAKE_EVENT(2, severity::LOW);
|
||||
static const Event BOOTING_BOOTLOADER_FAILED_EVENT = MAKE_EVENT(2, severity::LOW);
|
||||
|
||||
static const size_t MAX_PATH_SIZE = 50;
|
||||
static const size_t MAX_FILE_NAME = 30;
|
||||
@ -216,15 +219,29 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
// Loading firmware requires some time and the command will not trigger a reply when executed
|
||||
Countdown bootCountdown;
|
||||
|
||||
#ifdef EGSE
|
||||
std::string paramJsonFile = "/home/pi/arcsec/json/flight-config.json";
|
||||
#else
|
||||
#if OBSW_STAR_TRACKER_GROUND_CONFIG == 1
|
||||
std::string paramJsonFile = "/mnt/sd0/startracker/ground-config.json";
|
||||
#else
|
||||
std::string paramJsonFile = "/mnt/sd0/startracker/flight-config.json";
|
||||
#endif
|
||||
#endif
|
||||
struct JsonConfigs {
|
||||
Tracking tracking;
|
||||
LogLevel logLevel;
|
||||
LogSubscription logSubscription;
|
||||
DebugCamera debugCamera;
|
||||
Algo algo;
|
||||
Validation validation;
|
||||
Matching matching;
|
||||
Lisa lisa;
|
||||
Centroiding centroiding;
|
||||
Camera camera;
|
||||
ImageProcessor imageProcessor;
|
||||
Mounting mounting;
|
||||
Limits limits;
|
||||
Subscription subscription;
|
||||
};
|
||||
JsonConfigs jcfgs;
|
||||
Countdown jcfgCountdown = Countdown(250);
|
||||
bool commandExecuted = false;
|
||||
std::thread jsonCfgTask;
|
||||
static void setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonFile);
|
||||
|
||||
std::string paramJsonFile;
|
||||
|
||||
enum class NormalState { TEMPERATURE_REQUEST, SOLUTION_REQUEST };
|
||||
|
||||
@ -262,7 +279,14 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
|
||||
InternalState internalState = InternalState::IDLE;
|
||||
|
||||
enum class StartupState { IDLE, CHECK_PROGRAM, WAIT_CHECK_PROGRAM, BOOT_BOOTLOADER, DONE };
|
||||
enum class StartupState {
|
||||
IDLE,
|
||||
CHECK_PROGRAM,
|
||||
WAIT_CHECK_PROGRAM,
|
||||
BOOT_BOOTLOADER,
|
||||
WAIT_JCFG,
|
||||
DONE
|
||||
};
|
||||
|
||||
StartupState startupState = StartupState::IDLE;
|
||||
|
||||
@ -314,7 +338,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
* @param commandData Pointer to received command data
|
||||
* @param commandDataLen Size of received command data
|
||||
*
|
||||
* @return RETURN_OK if start of execution was successful, otherwise error return value
|
||||
* @return returnvalue::OK if start of execution was successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t executeFlashReadCommand(const uint8_t* commandData, size_t commandDataLen);
|
||||
|
||||
@ -385,7 +409,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
* @param commandDataLen Length of command
|
||||
* @param paramSet The object defining the command generation
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise error return Value
|
||||
* @return returnvalue::OK if successful, otherwise error return Value
|
||||
*/
|
||||
ReturnValue_t prepareParamCommand(const uint8_t* commandData, size_t commandDataLen,
|
||||
ArcsecJsonParamBase& paramSet);
|
||||
@ -454,7 +478,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
* @param dataset Dataset where reply data will be written to
|
||||
* @param size Size of the dataset
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise error return value
|
||||
* @return returnvalue::OK if successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t handleTm(LocalPoolDataSetBase& dataset, size_t size);
|
||||
|
||||
@ -463,7 +487,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
*
|
||||
* @param actioId Id of received command
|
||||
*
|
||||
* @return RETURN_OK if star tracker is in valid mode, otherwise error return value
|
||||
* @return returnvalue::OK if star tracker is in valid mode, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t checkCommand(ActionId_t actionId);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,12 @@
|
||||
#include "StrHelper.h"
|
||||
|
||||
#include <fsfw/filesystem/HasFileSystemIF.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "eive/definitions.h"
|
||||
#include "fsfw/timemanager/Countdown.h"
|
||||
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
|
||||
#include "mission/utility/Filenaming.h"
|
||||
@ -19,14 +22,14 @@ ReturnValue_t StrHelper::initialize() {
|
||||
sdcMan = SdCardManager::instance();
|
||||
if (sdcMan == nullptr) {
|
||||
sif::warning << "StrHelper::initialize: Invalid SD Card Manager" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
#endif
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
semaphore.acquire();
|
||||
while (true) {
|
||||
switch (internalState) {
|
||||
@ -36,7 +39,7 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
|
||||
}
|
||||
case InternalState::UPLOAD_IMAGE: {
|
||||
result = performImageUpload();
|
||||
if (result == RETURN_OK) {
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(IMAGE_UPLOAD_SUCCESSFUL);
|
||||
} else {
|
||||
triggerEvent(IMAGE_UPLOAD_FAILED);
|
||||
@ -46,7 +49,7 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
|
||||
}
|
||||
case InternalState::DOWNLOAD_IMAGE: {
|
||||
result = performImageDownload();
|
||||
if (result == RETURN_OK) {
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(IMAGE_DOWNLOAD_SUCCESSFUL);
|
||||
} else {
|
||||
triggerEvent(IMAGE_DOWNLOAD_FAILED);
|
||||
@ -56,7 +59,7 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
|
||||
}
|
||||
case InternalState::FLASH_READ: {
|
||||
result = performFlashRead();
|
||||
if (result == RETURN_OK) {
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(FLASH_READ_SUCCESSFUL);
|
||||
} else {
|
||||
triggerEvent(FLASH_READ_FAILED);
|
||||
@ -66,7 +69,7 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
|
||||
}
|
||||
case InternalState::FIRMWARE_UPDATE: {
|
||||
result = performFirmwareUpdate();
|
||||
if (result == RETURN_OK) {
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(FIRMWARE_UPDATE_SUCCESSFUL);
|
||||
} else {
|
||||
triggerEvent(FIRMWARE_UPDATE_FAILED);
|
||||
@ -82,12 +85,12 @@ ReturnValue_t StrHelper::performOperation(uint8_t operationCode) {
|
||||
}
|
||||
|
||||
ReturnValue_t StrHelper::setComIF(DeviceCommunicationIF* communicationInterface_) {
|
||||
uartComIF = dynamic_cast<UartComIF*>(communicationInterface_);
|
||||
uartComIF = dynamic_cast<SerialComIF*>(communicationInterface_);
|
||||
if (uartComIF == nullptr) {
|
||||
sif::warning << "StrHelper::initialize: Invalid uart com if" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void StrHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
|
||||
@ -95,7 +98,7 @@ void StrHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; }
|
||||
ReturnValue_t StrHelper::startImageUpload(std::string fullname) {
|
||||
#ifdef XIPHOS_Q7S
|
||||
ReturnValue_t result = checkPath(fullname);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
@ -106,13 +109,13 @@ ReturnValue_t StrHelper::startImageUpload(std::string fullname) {
|
||||
internalState = InternalState::UPLOAD_IMAGE;
|
||||
semaphore.release();
|
||||
terminate = false;
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StrHelper::startImageDownload(std::string path) {
|
||||
#ifdef XIPHOS_Q7S
|
||||
ReturnValue_t result = checkPath(path);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
@ -123,7 +126,7 @@ ReturnValue_t StrHelper::startImageDownload(std::string path) {
|
||||
internalState = InternalState::DOWNLOAD_IMAGE;
|
||||
terminate = false;
|
||||
semaphore.release();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void StrHelper::stopProcess() { terminate = true; }
|
||||
@ -135,7 +138,7 @@ void StrHelper::setFlashReadFilename(std::string filename) { flashRead.filename
|
||||
ReturnValue_t StrHelper::startFirmwareUpdate(std::string fullname) {
|
||||
#ifdef XIPHOS_Q7S
|
||||
ReturnValue_t result = checkPath(fullname);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
@ -148,13 +151,13 @@ ReturnValue_t StrHelper::startFirmwareUpdate(std::string fullname) {
|
||||
internalState = InternalState::FIRMWARE_UPDATE;
|
||||
semaphore.release();
|
||||
terminate = false;
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StrHelper::startFlashRead(std::string path, uint8_t startRegion, uint32_t length) {
|
||||
#ifdef XIPHOS_Q7S
|
||||
ReturnValue_t result = checkPath(path);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
@ -167,7 +170,7 @@ ReturnValue_t StrHelper::startFlashRead(std::string path, uint8_t startRegion, u
|
||||
internalState = InternalState::FLASH_READ;
|
||||
semaphore.release();
|
||||
terminate = false;
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void StrHelper::disableTimestamping() { timestamping = false; }
|
||||
@ -175,6 +178,11 @@ void StrHelper::disableTimestamping() { timestamping = false; }
|
||||
void StrHelper::enableTimestamping() { timestamping = true; }
|
||||
|
||||
ReturnValue_t StrHelper::performImageDownload() {
|
||||
#ifdef XIPHOS_Q7S
|
||||
if (not sdcMan->getActiveSdCard()) {
|
||||
return HasFileSystemIF::FILESYSTEM_INACTIVE;
|
||||
}
|
||||
#endif
|
||||
ReturnValue_t result;
|
||||
#if OBSW_DEBUG_STARTRACKER == 1
|
||||
ProgressPrinter progressPrinter("Image download", ImageDownload::LAST_POSITION);
|
||||
@ -192,11 +200,11 @@ ReturnValue_t StrHelper::performImageDownload() {
|
||||
while (downloadReq.position < ImageDownload::LAST_POSITION) {
|
||||
if (terminate) {
|
||||
file.close();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
arc_pack_download_action_req(&downloadReq, commandBuffer, &size);
|
||||
result = sendAndRead(size, downloadReq.position);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
|
||||
uartComIF->flushUartRxBuffer(comCookie);
|
||||
retries++;
|
||||
@ -206,7 +214,7 @@ ReturnValue_t StrHelper::performImageDownload() {
|
||||
return result;
|
||||
}
|
||||
result = checkActionReply();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
|
||||
uartComIF->flushUartRxBuffer(comCookie);
|
||||
retries++;
|
||||
@ -216,7 +224,7 @@ ReturnValue_t StrHelper::performImageDownload() {
|
||||
return result;
|
||||
}
|
||||
result = checkReplyPosition(downloadReq.position);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
|
||||
uartComIF->flushUartRxBuffer(comCookie);
|
||||
retries++;
|
||||
@ -234,20 +242,25 @@ ReturnValue_t StrHelper::performImageDownload() {
|
||||
retries = 0;
|
||||
}
|
||||
file.close();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StrHelper::performImageUpload() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
uint32_t size = 0;
|
||||
uint32_t imageSize = 0;
|
||||
struct UploadActionRequest uploadReq;
|
||||
uploadReq.position = 0;
|
||||
#ifdef XIPHOS_Q7S
|
||||
if (not sdcMan->getActiveSdCard()) {
|
||||
return HasFileSystemIF::FILESYSTEM_INACTIVE;
|
||||
}
|
||||
#endif
|
||||
std::memset(&uploadReq.data, 0, sizeof(uploadReq.data));
|
||||
if (not std::filesystem::exists(uploadImage.uploadFile)) {
|
||||
triggerEvent(STR_HELPER_FILE_NOT_EXISTS, static_cast<uint32_t>(internalState));
|
||||
internalState = InternalState::IDLE;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
std::ifstream file(uploadImage.uploadFile, std::ifstream::binary);
|
||||
// Set position of next character to end of file input stream
|
||||
@ -260,18 +273,18 @@ ReturnValue_t StrHelper::performImageUpload() {
|
||||
while ((uploadReq.position + 1) * SIZE_IMAGE_PART < imageSize) {
|
||||
if (terminate) {
|
||||
file.close();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg);
|
||||
file.read(reinterpret_cast<char*>(uploadReq.data), SIZE_IMAGE_PART);
|
||||
arc_pack_upload_action_req(&uploadReq, commandBuffer, &size);
|
||||
result = sendAndRead(size, uploadReq.position);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
file.close();
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = checkActionReply();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
file.close();
|
||||
return result;
|
||||
}
|
||||
@ -288,25 +301,25 @@ ReturnValue_t StrHelper::performImageUpload() {
|
||||
uploadReq.position++;
|
||||
arc_pack_upload_action_req(&uploadReq, commandBuffer, &size);
|
||||
result = sendAndRead(size, uploadReq.position);
|
||||
if (result != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = checkActionReply();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
#if OBSW_DEBUG_STARTRACKER == 1
|
||||
progressPrinter.print((uploadReq.position + 1) * SIZE_IMAGE_PART);
|
||||
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StrHelper::performFirmwareUpdate() {
|
||||
using namespace startracker;
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = unlockAndEraseRegions(static_cast<uint32_t>(startracker::FirmwareRegions::FIRST),
|
||||
static_cast<uint32_t>(startracker::FirmwareRegions::LAST));
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = performFlashWrite();
|
||||
@ -314,7 +327,12 @@ ReturnValue_t StrHelper::performFirmwareUpdate() {
|
||||
}
|
||||
|
||||
ReturnValue_t StrHelper::performFlashWrite() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
#ifdef XIPHOS_Q7S
|
||||
if (not sdcMan->getActiveSdCard()) {
|
||||
return HasFileSystemIF::FILESYSTEM_INACTIVE;
|
||||
}
|
||||
#endif
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
uint32_t size = 0;
|
||||
uint32_t bytesWritten = 0;
|
||||
uint32_t fileSize = 0;
|
||||
@ -322,14 +340,14 @@ ReturnValue_t StrHelper::performFlashWrite() {
|
||||
if (not std::filesystem::exists(flashWrite.fullname)) {
|
||||
triggerEvent(STR_HELPER_FILE_NOT_EXISTS, static_cast<uint32_t>(internalState));
|
||||
internalState = InternalState::IDLE;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
std::ifstream file(flashWrite.fullname, std::ifstream::binary);
|
||||
file.seekg(0, file.end);
|
||||
fileSize = file.tellg();
|
||||
if (fileSize > FLASH_REGION_SIZE * (flashWrite.lastRegion - flashWrite.firstRegion)) {
|
||||
sif::warning << "StrHelper::performFlashWrite: Invalid file" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
#if OBSW_DEBUG_STARTRACKER == 1
|
||||
ProgressPrinter progressPrinter("Flash write", fileSize);
|
||||
@ -341,7 +359,7 @@ ReturnValue_t StrHelper::performFlashWrite() {
|
||||
for (uint32_t idx = 0; idx < fileChunks; idx++) {
|
||||
if (terminate) {
|
||||
file.close();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
file.seekg(idx * CHUNK_SIZE, file.beg);
|
||||
file.read(reinterpret_cast<char*>(req.data), CHUNK_SIZE);
|
||||
@ -352,12 +370,12 @@ ReturnValue_t StrHelper::performFlashWrite() {
|
||||
req.address = bytesWritten;
|
||||
arc_pack_write_action_req(&req, commandBuffer, &size);
|
||||
result = sendAndRead(size, req.address);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
file.close();
|
||||
return result;
|
||||
}
|
||||
result = checkActionReply();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
file.close();
|
||||
return result;
|
||||
}
|
||||
@ -379,20 +397,25 @@ ReturnValue_t StrHelper::performFlashWrite() {
|
||||
bytesWritten += remainingBytes;
|
||||
arc_pack_write_action_req(&req, commandBuffer, &size);
|
||||
result = sendAndRead(size, req.address);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = checkActionReply();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
#if OBSW_DEBUG_STARTRACKER == 1
|
||||
progressPrinter.print(fileSize);
|
||||
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StrHelper::performFlashRead() {
|
||||
#ifdef XIPHOS_Q7S
|
||||
if (not sdcMan->getActiveSdCard()) {
|
||||
return HasFileSystemIF::FILESYSTEM_INACTIVE;
|
||||
}
|
||||
#endif
|
||||
ReturnValue_t result;
|
||||
#if OBSW_DEBUG_STARTRACKER == 1
|
||||
ProgressPrinter progressPrinter("Flash read", flashRead.size);
|
||||
@ -412,7 +435,7 @@ ReturnValue_t StrHelper::performFlashRead() {
|
||||
req.address = 0;
|
||||
while (bytesRead < flashRead.size) {
|
||||
if (terminate) {
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
if ((flashRead.size - bytesRead) < CHUNK_SIZE) {
|
||||
req.length = flashRead.size - bytesRead;
|
||||
@ -421,7 +444,7 @@ ReturnValue_t StrHelper::performFlashRead() {
|
||||
}
|
||||
arc_pack_read_action_req(&req, commandBuffer, &size);
|
||||
result = sendAndRead(size, req.address);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
|
||||
uartComIF->flushUartRxBuffer(comCookie);
|
||||
retries++;
|
||||
@ -431,7 +454,7 @@ ReturnValue_t StrHelper::performFlashRead() {
|
||||
return result;
|
||||
}
|
||||
result = checkActionReply();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
if (retries < CONFIG_MAX_DOWNLOAD_RETRIES) {
|
||||
uartComIF->flushUartRxBuffer(comCookie);
|
||||
retries++;
|
||||
@ -454,12 +477,12 @@ ReturnValue_t StrHelper::performFlashRead() {
|
||||
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
|
||||
}
|
||||
file.close();
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StrHelper::sendAndRead(size_t size, uint32_t parameter, uint32_t delayMs) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t decResult = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
ReturnValue_t decResult = returnvalue::OK;
|
||||
size_t receivedDataLen = 0;
|
||||
uint8_t* receivedData = nullptr;
|
||||
size_t bytesLeft = 0;
|
||||
@ -467,10 +490,10 @@ ReturnValue_t StrHelper::sendAndRead(size_t size, uint32_t parameter, uint32_t d
|
||||
datalinkLayer.encodeFrame(commandBuffer, size);
|
||||
result = uartComIF->sendMessage(comCookie, datalinkLayer.getEncodedFrame(),
|
||||
datalinkLayer.getEncodedLength());
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "StrHelper::sendAndRead: Failed to send packet" << std::endl;
|
||||
triggerEvent(STR_HELPER_SENDING_PACKET_FAILED, result, parameter);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
decResult = ArcsecDatalinkLayer::DEC_IN_PROGRESS;
|
||||
while (decResult == ArcsecDatalinkLayer::DEC_IN_PROGRESS) {
|
||||
@ -479,23 +502,23 @@ ReturnValue_t StrHelper::sendAndRead(size_t size, uint32_t parameter, uint32_t d
|
||||
while (delay.isBusy()) {
|
||||
}
|
||||
result = uartComIF->requestReceiveMessage(comCookie, startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "StrHelper::sendAndRead: Failed to request reply" << std::endl;
|
||||
triggerEvent(STR_HELPER_REQUESTING_MSG_FAILED, result, parameter);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = uartComIF->readReceivedMessage(comCookie, &receivedData, &receivedDataLen);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "StrHelper::sendAndRead: Failed to read received message" << std::endl;
|
||||
triggerEvent(STR_HELPER_READING_REPLY_FAILED, result, parameter);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (receivedDataLen == 0 && missedReplies < MAX_POLLS) {
|
||||
missedReplies++;
|
||||
continue;
|
||||
} else if ((receivedDataLen == 0) && (missedReplies >= MAX_POLLS)) {
|
||||
triggerEvent(STR_HELPER_NO_REPLY, parameter);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
} else {
|
||||
missedReplies = 0;
|
||||
}
|
||||
@ -504,14 +527,14 @@ ReturnValue_t StrHelper::sendAndRead(size_t size, uint32_t parameter, uint32_t d
|
||||
// This should never happen
|
||||
sif::warning << "StrHelper::sendAndRead: Bytes left after decoding" << std::endl;
|
||||
triggerEvent(STR_HELPER_COM_ERROR, result, parameter);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
if (decResult != RETURN_OK) {
|
||||
if (decResult != returnvalue::OK) {
|
||||
triggerEvent(STR_HELPER_DEC_ERROR, decResult, parameter);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StrHelper::checkActionReply() {
|
||||
@ -526,7 +549,7 @@ ReturnValue_t StrHelper::checkActionReply() {
|
||||
<< static_cast<unsigned int>(status) << std::endl;
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StrHelper::checkReplyPosition(uint32_t expectedPosition) {
|
||||
@ -534,32 +557,31 @@ ReturnValue_t StrHelper::checkReplyPosition(uint32_t expectedPosition) {
|
||||
std::memcpy(&receivedPosition, datalinkLayer.getReply() + POS_OFFSET, sizeof(receivedPosition));
|
||||
if (receivedPosition != expectedPosition) {
|
||||
triggerEvent(POSITION_MISMATCH, receivedPosition);
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
ReturnValue_t StrHelper::checkPath(std::string name) {
|
||||
if (name.substr(0, sizeof(SdCardManager::SD_0_MOUNT_POINT)) ==
|
||||
std::string(SdCardManager::SD_0_MOUNT_POINT)) {
|
||||
if (!sdcMan->isSdCardMounted(sd::SLOT_0)) {
|
||||
if (name.substr(0, sizeof(config::SD_0_MOUNT_POINT)) == std::string(config::SD_0_MOUNT_POINT)) {
|
||||
if (!sdcMan->isSdCardUsable(sd::SLOT_0)) {
|
||||
sif::warning << "StrHelper::checkPath: SD card 0 not mounted" << std::endl;
|
||||
return SD_NOT_MOUNTED;
|
||||
}
|
||||
} else if (name.substr(0, sizeof(SdCardManager::SD_1_MOUNT_POINT)) ==
|
||||
std::string(SdCardManager::SD_1_MOUNT_POINT)) {
|
||||
if (!sdcMan->isSdCardMounted(sd::SLOT_0)) {
|
||||
} else if (name.substr(0, sizeof(config::SD_1_MOUNT_POINT)) ==
|
||||
std::string(config::SD_1_MOUNT_POINT)) {
|
||||
if (!sdcMan->isSdCardUsable(sd::SLOT_0)) {
|
||||
sif::warning << "StrHelper::checkPath: SD card 1 not mounted" << std::endl;
|
||||
return SD_NOT_MOUNTED;
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
ReturnValue_t StrHelper::unlockAndEraseRegions(uint32_t from, uint32_t to) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
#if OBSW_DEBUG_STARTRACKER == 1
|
||||
ProgressPrinter progressPrinter("Unlock and erase", to - from);
|
||||
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
|
||||
@ -572,7 +594,7 @@ ReturnValue_t StrHelper::unlockAndEraseRegions(uint32_t from, uint32_t to) {
|
||||
arc_pack_unlock_action_req(&unlockReq, commandBuffer, &size);
|
||||
sendAndRead(size, unlockReq.region);
|
||||
result = checkActionReply();
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "StrHelper::unlockAndEraseRegions: Failed to unlock region with id "
|
||||
<< static_cast<unsigned int>(unlockReq.region) << std::endl;
|
||||
return result;
|
||||
@ -580,7 +602,7 @@ ReturnValue_t StrHelper::unlockAndEraseRegions(uint32_t from, uint32_t to) {
|
||||
eraseReq.region = idx;
|
||||
arc_pack_erase_action_req(&eraseReq, commandBuffer, &size);
|
||||
result = sendAndRead(size, eraseReq.region, FLASH_ERASE_DELAY);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "StrHelper::unlockAndEraseRegions: Failed to erase region with id "
|
||||
<< static_cast<unsigned int>(eraseReq.region) << std::endl;
|
||||
return result;
|
||||
|
@ -7,15 +7,15 @@
|
||||
#include "OBSWConfig.h"
|
||||
|
||||
#ifdef XIPHOS_Q7S
|
||||
#include "bsp_q7s/memory/SdCardManager.h"
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
#endif
|
||||
|
||||
#include "fsfw/devicehandlers/CookieIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/osal/linux/BinarySemaphore.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw_hal/linux/uart/UartComIF.h"
|
||||
#include "fsfw_hal/linux/serial/SerialComIF.h"
|
||||
|
||||
extern "C" {
|
||||
#include "thirdparty/arcsec_star_tracker/client/generated/actionreq.h"
|
||||
@ -27,7 +27,7 @@ extern "C" {
|
||||
*
|
||||
* @author J. Meier
|
||||
*/
|
||||
class StrHelper : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF {
|
||||
class StrHelper : public SystemObject, public ExecutableObjectIF {
|
||||
public:
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::STR_HELPER;
|
||||
|
||||
@ -255,7 +255,7 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
|
||||
* UART communication object responsible for low level access of star tracker
|
||||
* Must be set by star tracker handler
|
||||
*/
|
||||
UartComIF* uartComIF = nullptr;
|
||||
SerialComIF* uartComIF = nullptr;
|
||||
// Communication cookie. Must be set by the star tracker handler
|
||||
CookieIF* comCookie = nullptr;
|
||||
|
||||
@ -270,7 +270,7 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
|
||||
/**
|
||||
* @brief Performs firmware update
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise error return value
|
||||
* @return returnvalue::OK if successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t performFirmwareUpdate();
|
||||
|
||||
@ -289,7 +289,7 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
|
||||
*
|
||||
* @param ID of first region to write to
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise RETURN_FAILED
|
||||
* @return returnvalue::OK if successful, otherwise returnvalue::FAILED
|
||||
*/
|
||||
ReturnValue_t performFlashWrite();
|
||||
|
||||
@ -307,14 +307,14 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
|
||||
* @param parameter Parameter 2 of trigger event function
|
||||
* @param delayMs Delay in milliseconds between send and receive call
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise RETURN_FAILED
|
||||
* @return returnvalue::OK if successful, otherwise returnvalue::FAILED
|
||||
*/
|
||||
ReturnValue_t sendAndRead(size_t size, uint32_t parameter, uint32_t delayMs = 0);
|
||||
|
||||
/**
|
||||
* @brief Checks the header (type id and status fields) of the action reply
|
||||
*
|
||||
* @return RETURN_OK if reply confirms success of packet transfer, otherwise REUTRN_FAILED
|
||||
* @return returnvalue::OK if reply confirms success of packet transfer, otherwise REUTRN_FAILED
|
||||
*/
|
||||
ReturnValue_t checkActionReply();
|
||||
|
||||
@ -323,7 +323,8 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
|
||||
*
|
||||
* @param expectedPosition Value of expected position
|
||||
*
|
||||
* @return RETURN_OK if received position matches expected position, otherwise RETURN_FAILED
|
||||
* @return returnvalue::OK if received position matches expected position, otherwise
|
||||
* returnvalue::FAILED
|
||||
*/
|
||||
ReturnValue_t checkReplyPosition(uint32_t expectedPosition);
|
||||
|
||||
@ -331,7 +332,7 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu
|
||||
/**
|
||||
* @brief Checks if a path points to an sd card and whether the SD card is monuted.
|
||||
*
|
||||
* @return SD_NOT_MOUNTED id SD card is not mounted, otherwise RETURN_OK
|
||||
* @return SD_NOT_MOUNTED id SD card is not mounted, otherwise returnvalue::OK
|
||||
*/
|
||||
ReturnValue_t checkPath(std::string name);
|
||||
#endif
|
||||
|
@ -1,28 +1,15 @@
|
||||
target_sources(${OBSW_NAME} PRIVATE
|
||||
ipc/MissionMessageTypes.cpp
|
||||
pollingsequence/pollingSequenceFactory.cpp
|
||||
)
|
||||
target_sources(${OBSW_NAME} PRIVATE ipc/MissionMessageTypes.cpp)
|
||||
|
||||
target_include_directories(${OBSW_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
target_include_directories(${OBSW_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
# If a special translation file for object IDs exists, compile it.
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp")
|
||||
target_sources(${OBSW_NAME} PRIVATE
|
||||
objects/translateObjects.cpp
|
||||
)
|
||||
target_sources(${UNITTEST_NAME} PRIVATE
|
||||
objects/translateObjects.cpp
|
||||
)
|
||||
target_sources(${OBSW_NAME} PRIVATE objects/translateObjects.cpp)
|
||||
target_sources(${UNITTEST_NAME} PRIVATE objects/translateObjects.cpp)
|
||||
endif()
|
||||
|
||||
# If a special translation file for events exists, compile it.
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp")
|
||||
target_sources(${OBSW_NAME} PRIVATE
|
||||
events/translateEvents.cpp
|
||||
)
|
||||
target_sources(${UNITTEST_NAME} PRIVATE
|
||||
events/translateEvents.cpp
|
||||
)
|
||||
target_sources(${OBSW_NAME} PRIVATE events/translateEvents.cpp)
|
||||
target_sources(${UNITTEST_NAME} PRIVATE events/translateEvents.cpp)
|
||||
endif()
|
||||
|
@ -4,6 +4,10 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
// It is assumed the user has a subsystem and class ID list in some user header files.
|
||||
#include "events/subsystemIdRanges.h"
|
||||
#include "returnvalues/classIds.h"
|
||||
|
||||
//! Used to determine whether C++ ostreams are used which can increase
|
||||
//! the binary size significantly. If this is disabled,
|
||||
//! the C stdio functions can be used alternatively
|
||||
@ -30,7 +34,7 @@
|
||||
|
||||
#if FSFW_OBJ_EVENT_TRANSLATION == 1
|
||||
//! Specify whether info events are printed too.
|
||||
#define FSFW_DEBUG_INFO 1
|
||||
#define FSFW_DEBUG_INFO @FSFW_DEBUG_INFO@
|
||||
#include "objects/translateObjects.h"
|
||||
#include "events/translateEvents.h"
|
||||
#else
|
||||
@ -38,7 +42,7 @@
|
||||
|
||||
//! When using the newlib nano library, C99 support for stdio facilities
|
||||
//! will not be provided. This define should be set to 1 if this is the case.
|
||||
#define FSFW_NO_C99_IO 1
|
||||
#define FSFW_NO_C99_IO 0
|
||||
|
||||
//! Specify whether a special mode store is used for Subsystem components.
|
||||
#define FSFW_USE_MODESTORE 0
|
||||
|
@ -1 +0,0 @@
|
||||
#include "addresses.h"
|
@ -1,87 +0,0 @@
|
||||
#ifndef FSFWCONFIG_DEVICES_ADDRESSES_H_
|
||||
#define FSFWCONFIG_DEVICES_ADDRESSES_H_
|
||||
|
||||
#include <fsfw/devicehandlers/CookieIF.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "objects/systemObjectList.h"
|
||||
|
||||
namespace addresses {
|
||||
/* Logical addresses have uint32_t datatype */
|
||||
enum logicalAddresses : address_t {
|
||||
PCDU,
|
||||
|
||||
MGM_0_LIS3 = objects::MGM_0_LIS3_HANDLER,
|
||||
MGM_1_RM3100 = objects::MGM_1_RM3100_HANDLER,
|
||||
MGM_2_LIS3 = objects::MGM_2_LIS3_HANDLER,
|
||||
MGM_3_RM3100 = objects::MGM_3_RM3100_HANDLER,
|
||||
|
||||
GYRO_0_ADIS = objects::GYRO_0_ADIS_HANDLER,
|
||||
GYRO_1_L3G = objects::GYRO_1_L3G_HANDLER,
|
||||
GYRO_2_ADIS = objects::GYRO_2_ADIS_HANDLER,
|
||||
GYRO_3_L3G = objects::GYRO_3_L3G_HANDLER,
|
||||
|
||||
RAD_SENSOR = objects::RAD_SENSOR,
|
||||
|
||||
SUS_0 = objects::SUS_0_N_LOC_XFYFZM_PT_XF,
|
||||
SUS_1 = objects::SUS_1_N_LOC_XBYFZM_PT_XB,
|
||||
SUS_2 = objects::SUS_2_N_LOC_XFYBZB_PT_YB,
|
||||
SUS_3 = objects::SUS_3_N_LOC_XFYBZF_PT_YF,
|
||||
SUS_4 = objects::SUS_4_N_LOC_XMYFZF_PT_ZF,
|
||||
SUS_5 = objects::SUS_5_N_LOC_XFYMZB_PT_ZB,
|
||||
SUS_6 = objects::SUS_6_R_LOC_XFYBZM_PT_XF,
|
||||
SUS_7 = objects::SUS_7_R_LOC_XBYBZM_PT_XB,
|
||||
SUS_8 = objects::SUS_8_R_LOC_XBYBZB_PT_YB,
|
||||
SUS_9 = objects::SUS_9_R_LOC_XBYBZB_PT_YF,
|
||||
SUS_10 = objects::SUS_10_N_LOC_XMYBZF_PT_ZF,
|
||||
SUS_11 = objects::SUS_11_R_LOC_XBYMZB_PT_ZB,
|
||||
|
||||
/* Dummy and Test Addresses */
|
||||
DUMMY_ECHO = 129,
|
||||
DUMMY_GPS0 = 130,
|
||||
DUMMY_GPS1 = 131,
|
||||
};
|
||||
|
||||
enum i2cAddresses : address_t {
|
||||
BPX_BATTERY = 0x07,
|
||||
IMTQ = 0x10,
|
||||
TMP1075_TCS_1 = 0x48,
|
||||
TMP1075_TCS_2 = 0x49,
|
||||
};
|
||||
|
||||
enum spiAddresses : address_t {
|
||||
RTD_IC_3,
|
||||
RTD_IC_4,
|
||||
RTD_IC_5,
|
||||
RTD_IC_6,
|
||||
RTD_IC_7,
|
||||
RTD_IC_8,
|
||||
RTD_IC_9,
|
||||
RTD_IC_10,
|
||||
RTD_IC_11,
|
||||
RTD_IC_12,
|
||||
RTD_IC_13,
|
||||
RTD_IC_14,
|
||||
RTD_IC_15,
|
||||
RTD_IC_16,
|
||||
RTD_IC_17,
|
||||
RTD_IC_18,
|
||||
RW1,
|
||||
RW2,
|
||||
RW3,
|
||||
RW4,
|
||||
PLPCDU_ADC
|
||||
};
|
||||
|
||||
/* Addresses of devices supporting the CSP protocol */
|
||||
enum cspAddresses : uint8_t {
|
||||
P60DOCK = 4,
|
||||
ACU = 2,
|
||||
PDU1 = 3,
|
||||
/* PDU2 occupies X4 slot of P60Dock */
|
||||
PDU2 = 6
|
||||
};
|
||||
} // namespace addresses
|
||||
|
||||
#endif /* FSFWCONFIG_DEVICES_ADDRESSES_H_ */
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "common/config/commonSubsystemIds.h"
|
||||
#include "eive/eventSubsystemIds.h"
|
||||
#include "fsfw/events/fwSubsystemIdRanges.h"
|
||||
|
||||
/**
|
||||
@ -13,7 +13,6 @@
|
||||
namespace SUBSYSTEM_ID {
|
||||
enum : uint8_t {
|
||||
SUBSYSTEM_ID_START = COMMON_SUBSYSTEM_ID_END,
|
||||
CORE = 137,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 203 translations.
|
||||
* @brief Auto-generated event translation file. Contains 277 translations.
|
||||
* @details
|
||||
* Generated on: 2022-05-21 10:25:06
|
||||
* Generated on: 2023-03-11 15:01:05
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -75,29 +75,49 @@ const char *OVERWRITING_HEALTH_STRING = "OVERWRITING_HEALTH";
|
||||
const char *TRYING_RECOVERY_STRING = "TRYING_RECOVERY";
|
||||
const char *RECOVERY_STEP_STRING = "RECOVERY_STEP";
|
||||
const char *RECOVERY_DONE_STRING = "RECOVERY_DONE";
|
||||
const char *HANDLE_PACKET_FAILED_STRING = "HANDLE_PACKET_FAILED";
|
||||
const char *RF_AVAILABLE_STRING = "RF_AVAILABLE";
|
||||
const char *RF_LOST_STRING = "RF_LOST";
|
||||
const char *BIT_LOCK_STRING = "BIT_LOCK";
|
||||
const char *BIT_LOCK_LOST_STRING = "BIT_LOCK_LOST";
|
||||
const char *FRAME_PROCESSING_FAILED_STRING = "FRAME_PROCESSING_FAILED";
|
||||
const char *CLOCK_SET_STRING = "CLOCK_SET";
|
||||
const char *CLOCK_DUMP_STRING = "CLOCK_DUMP";
|
||||
const char *CLOCK_SET_FAILURE_STRING = "CLOCK_SET_FAILURE";
|
||||
const char *TC_DELETION_FAILED_STRING = "TC_DELETION_FAILED";
|
||||
const char *TEST_STRING = "TEST";
|
||||
const char *CHANGE_OF_SETUP_PARAMETER_STRING = "CHANGE_OF_SETUP_PARAMETER";
|
||||
const char *STORE_ERROR_STRING = "STORE_ERROR";
|
||||
const char *MSG_QUEUE_ERROR_STRING = "MSG_QUEUE_ERROR";
|
||||
const char *SERIALIZATION_ERROR_STRING = "SERIALIZATION_ERROR";
|
||||
const char *FILESTORE_ERROR_STRING = "FILESTORE_ERROR";
|
||||
const char *FILENAME_TOO_LARGE_ERROR_STRING = "FILENAME_TOO_LARGE_ERROR";
|
||||
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
|
||||
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
||||
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
||||
const char *MEKF_INVALID_INFO_STRING = "MEKF_INVALID_INFO";
|
||||
const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION";
|
||||
const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT";
|
||||
const char *SWITCH_HAS_CHANGED_STRING = "SWITCH_HAS_CHANGED";
|
||||
const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED";
|
||||
const char *FDIR_REACTION_IGNORED_STRING = "FDIR_REACTION_IGNORED";
|
||||
const char *GPIO_PULL_HIGH_FAILED_STRING = "GPIO_PULL_HIGH_FAILED";
|
||||
const char *GPIO_PULL_LOW_FAILED_STRING = "GPIO_PULL_LOW_FAILED";
|
||||
const char *HEATER_WENT_ON_STRING = "HEATER_WENT_ON";
|
||||
const char *HEATER_WENT_OFF_STRING = "HEATER_WENT_OFF";
|
||||
const char *SWITCH_ALREADY_ON_STRING = "SWITCH_ALREADY_ON";
|
||||
const char *SWITCH_ALREADY_OFF_STRING = "SWITCH_ALREADY_OFF";
|
||||
const char *MAIN_SWITCH_TIMEOUT_STRING = "MAIN_SWITCH_TIMEOUT";
|
||||
const char *FAULTY_HEATER_WAS_ON_STRING = "FAULTY_HEATER_WAS_ON";
|
||||
const char *BURN_PHASE_START_STRING = "BURN_PHASE_START";
|
||||
const char *BURN_PHASE_DONE_STRING = "BURN_PHASE_DONE";
|
||||
const char *MAIN_SWITCH_ON_TIMEOUT_STRING = "MAIN_SWITCH_ON_TIMEOUT";
|
||||
const char *MAIN_SWITCH_OFF_TIMEOUT_STRING = "MAIN_SWITCH_OFF_TIMEOUT";
|
||||
const char *DEPLOYMENT_FAILED_STRING = "DEPLOYMENT_FAILED";
|
||||
const char *DEPL_SA1_GPIO_SWTICH_ON_FAILED_STRING = "DEPL_SA1_GPIO_SWTICH_ON_FAILED";
|
||||
const char *DEPL_SA2_GPIO_SWTICH_ON_FAILED_STRING = "DEPL_SA2_GPIO_SWTICH_ON_FAILED";
|
||||
const char *DEPL_SA1_GPIO_SWTICH_OFF_FAILED_STRING = "DEPL_SA1_GPIO_SWTICH_OFF_FAILED";
|
||||
const char *DEPL_SA2_GPIO_SWTICH_OFF_FAILED_STRING = "DEPL_SA2_GPIO_SWTICH_OFF_FAILED";
|
||||
const char *AUTONOMOUS_DEPLOYMENT_COMPLETED_STRING = "AUTONOMOUS_DEPLOYMENT_COMPLETED";
|
||||
const char *MEMORY_READ_RPT_CRC_FAILURE_STRING = "MEMORY_READ_RPT_CRC_FAILURE";
|
||||
const char *ACK_FAILURE_STRING = "ACK_FAILURE";
|
||||
const char *EXE_FAILURE_STRING = "EXE_FAILURE";
|
||||
@ -114,13 +134,16 @@ const char *SELF_TEST_COIL_CURRENT_FAILURE_STRING = "SELF_TEST_COIL_CURRENT_FAIL
|
||||
const char *INVALID_ERROR_BYTE_STRING = "INVALID_ERROR_BYTE";
|
||||
const char *ERROR_STATE_STRING = "ERROR_STATE";
|
||||
const char *RESET_OCCURED_STRING = "RESET_OCCURED";
|
||||
const char *BOOTING_FIRMWARE_FAILED_STRING = "BOOTING_FIRMWARE_FAILED";
|
||||
const char *BOOTING_BOOTLOADER_FAILED_STRING = "BOOTING_BOOTLOADER_FAILED";
|
||||
const char *BOOTING_FIRMWARE_FAILED_EVENT_STRING = "BOOTING_FIRMWARE_FAILED_EVENT";
|
||||
const char *BOOTING_BOOTLOADER_FAILED_EVENT_STRING = "BOOTING_BOOTLOADER_FAILED_EVENT";
|
||||
const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE";
|
||||
const char *SUPV_UNKNOWN_TM_STRING = "SUPV_UNKNOWN_TM";
|
||||
const char *SUPV_UNINIMPLEMENTED_TM_STRING = "SUPV_UNINIMPLEMENTED_TM";
|
||||
const char *SUPV_ACK_FAILURE_STRING = "SUPV_ACK_FAILURE";
|
||||
const char *SUPV_EXE_FAILURE_STRING = "SUPV_EXE_FAILURE";
|
||||
const char *SUPV_CRC_FAILURE_EVENT_STRING = "SUPV_CRC_FAILURE_EVENT";
|
||||
const char *SUPV_MPSOC_SHUWDOWN_BUILD_FAILED_STRING = "SUPV_MPSOC_SHUWDOWN_BUILD_FAILED";
|
||||
const char *SUPV_HELPER_EXECUTING_STRING = "SUPV_HELPER_EXECUTING";
|
||||
const char *SUPV_MPSOC_SHUTDOWN_BUILD_FAILED_STRING = "SUPV_MPSOC_SHUTDOWN_BUILD_FAILED";
|
||||
const char *SANITIZATION_FAILED_STRING = "SANITIZATION_FAILED";
|
||||
const char *MOUNTED_SD_CARD_STRING = "MOUNTED_SD_CARD";
|
||||
const char *SEND_MRAM_DUMP_FAILED_STRING = "SEND_MRAM_DUMP_FAILED";
|
||||
@ -130,6 +153,13 @@ const char *INVALID_TC_FRAME_STRING = "INVALID_TC_FRAME";
|
||||
const char *INVALID_FAR_STRING = "INVALID_FAR";
|
||||
const char *CARRIER_LOCK_STRING = "CARRIER_LOCK";
|
||||
const char *BIT_LOCK_PDEC_STRING = "BIT_LOCK_PDEC";
|
||||
const char *LOST_CARRIER_LOCK_PDEC_STRING = "LOST_CARRIER_LOCK_PDEC";
|
||||
const char *LOST_BIT_LOCK_PDEC_STRING = "LOST_BIT_LOCK_PDEC";
|
||||
const char *TOO_MANY_IRQS_STRING = "TOO_MANY_IRQS";
|
||||
const char *POLL_SYSCALL_ERROR_PDEC_STRING = "POLL_SYSCALL_ERROR_PDEC";
|
||||
const char *WRITE_SYSCALL_ERROR_PDEC_STRING = "WRITE_SYSCALL_ERROR_PDEC";
|
||||
const char *PDEC_RESET_FAILED_STRING = "PDEC_RESET_FAILED";
|
||||
const char *OPEN_IRQ_FILE_FAILED_STRING = "OPEN_IRQ_FILE_FAILED";
|
||||
const char *IMAGE_UPLOAD_FAILED_STRING = "IMAGE_UPLOAD_FAILED";
|
||||
const char *IMAGE_DOWNLOAD_FAILED_STRING = "IMAGE_DOWNLOAD_FAILED";
|
||||
const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL";
|
||||
@ -159,6 +189,8 @@ const char *MPSOC_EXE_FAILURE_REPORT_STRING = "MPSOC_EXE_FAILURE_REPORT";
|
||||
const char *MPSOC_ACK_INVALID_APID_STRING = "MPSOC_ACK_INVALID_APID";
|
||||
const char *MPSOC_EXE_INVALID_APID_STRING = "MPSOC_EXE_INVALID_APID";
|
||||
const char *MPSOC_HELPER_SEQ_CNT_MISMATCH_STRING = "MPSOC_HELPER_SEQ_CNT_MISMATCH";
|
||||
const char *MPSOC_TM_SIZE_ERROR_STRING = "MPSOC_TM_SIZE_ERROR";
|
||||
const char *MPSOC_TM_CRC_MISSMATCH_STRING = "MPSOC_TM_CRC_MISSMATCH";
|
||||
const char *TRANSITION_BACK_TO_OFF_STRING = "TRANSITION_BACK_TO_OFF";
|
||||
const char *NEG_V_OUT_OF_BOUNDS_STRING = "NEG_V_OUT_OF_BOUNDS";
|
||||
const char *U_DRO_OUT_OF_BOUNDS_STRING = "U_DRO_OUT_OF_BOUNDS";
|
||||
@ -177,6 +209,7 @@ const char *POWER_STATE_MACHINE_TIMEOUT_STRING = "POWER_STATE_MACHINE_TIMEOUT";
|
||||
const char *SIDE_SWITCH_TRANSITION_NOT_ALLOWED_STRING = "SIDE_SWITCH_TRANSITION_NOT_ALLOWED";
|
||||
const char *CHILDREN_LOST_MODE_STRING = "CHILDREN_LOST_MODE";
|
||||
const char *GPS_FIX_CHANGE_STRING = "GPS_FIX_CHANGE";
|
||||
const char *CANT_GET_FIX_STRING = "CANT_GET_FIX";
|
||||
const char *P60_BOOT_COUNT_STRING = "P60_BOOT_COUNT";
|
||||
const char *BATT_MODE_STRING = "BATT_MODE";
|
||||
const char *BATT_MODE_CHANGED_STRING = "BATT_MODE_CHANGED";
|
||||
@ -188,6 +221,8 @@ const char *TERMINATED_UPDATE_PROCEDURE_STRING = "TERMINATED_UPDATE_PROCEDURE";
|
||||
const char *SUPV_EVENT_BUFFER_REQUEST_SUCCESSFUL_STRING = "SUPV_EVENT_BUFFER_REQUEST_SUCCESSFUL";
|
||||
const char *SUPV_EVENT_BUFFER_REQUEST_FAILED_STRING = "SUPV_EVENT_BUFFER_REQUEST_FAILED";
|
||||
const char *SUPV_EVENT_BUFFER_REQUEST_TERMINATED_STRING = "SUPV_EVENT_BUFFER_REQUEST_TERMINATED";
|
||||
const char *SUPV_MEM_CHECK_OK_STRING = "SUPV_MEM_CHECK_OK";
|
||||
const char *SUPV_MEM_CHECK_FAIL_STRING = "SUPV_MEM_CHECK_FAIL";
|
||||
const char *SUPV_SENDING_COMMAND_FAILED_STRING = "SUPV_SENDING_COMMAND_FAILED";
|
||||
const char *SUPV_HELPER_REQUESTING_REPLY_FAILED_STRING = "SUPV_HELPER_REQUESTING_REPLY_FAILED";
|
||||
const char *SUPV_HELPER_READING_REPLY_FAILED_STRING = "SUPV_HELPER_READING_REPLY_FAILED";
|
||||
@ -200,10 +235,48 @@ const char *SUPV_EXE_INVALID_APID_STRING = "SUPV_EXE_INVALID_APID";
|
||||
const char *ACK_RECEPTION_FAILURE_STRING = "ACK_RECEPTION_FAILURE";
|
||||
const char *EXE_RECEPTION_FAILURE_STRING = "EXE_RECEPTION_FAILURE";
|
||||
const char *WRITE_MEMORY_FAILED_STRING = "WRITE_MEMORY_FAILED";
|
||||
const char *SUPV_REPLY_SIZE_MISSMATCH_STRING = "SUPV_REPLY_SIZE_MISSMATCH";
|
||||
const char *SUPV_REPLY_CRC_MISSMATCH_STRING = "SUPV_REPLY_CRC_MISSMATCH";
|
||||
const char *SUPV_UPDATE_PROGRESS_STRING = "SUPV_UPDATE_PROGRESS";
|
||||
const char *HDLC_FRAME_REMOVAL_ERROR_STRING = "HDLC_FRAME_REMOVAL_ERROR";
|
||||
const char *HDLC_CRC_ERROR_STRING = "HDLC_CRC_ERROR";
|
||||
const char *TX_ON_STRING = "TX_ON";
|
||||
const char *TX_OFF_STRING = "TX_OFF";
|
||||
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";
|
||||
const char *WRITE_CONFIGFILE_FAILED_STRING = "WRITE_CONFIGFILE_FAILED";
|
||||
const char *READ_CONFIGFILE_FAILED_STRING = "READ_CONFIGFILE_FAILED";
|
||||
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 *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE";
|
||||
const char *VERSION_INFO_STRING = "VERSION_INFO";
|
||||
const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
|
||||
const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER";
|
||||
const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
|
||||
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
||||
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
||||
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
||||
const char *PLOC_OVERHEATING_STRING = "PLOC_OVERHEATING";
|
||||
const char *OBC_OVERHEATING_STRING = "OBC_OVERHEATING";
|
||||
const char *HPA_OVERHEATING_STRING = "HPA_OVERHEATING";
|
||||
const char *PLPCDU_OVERHEATING_STRING = "PLPCDU_OVERHEATING";
|
||||
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
|
||||
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
|
||||
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
|
||||
const char *FILE_TOO_LARGE_STRING = "FILE_TOO_LARGE";
|
||||
const char *BUSY_DUMPING_EVENT_STRING = "BUSY_DUMPING_EVENT";
|
||||
const char *DUMP_WAS_CANCELLED_STRING = "DUMP_WAS_CANCELLED";
|
||||
const char *DUMP_OK_STORE_DONE_STRING = "DUMP_OK_STORE_DONE";
|
||||
const char *DUMP_NOK_STORE_DONE_STRING = "DUMP_NOK_STORE_DONE";
|
||||
const char *DUMP_MISC_STORE_DONE_STRING = "DUMP_MISC_STORE_DONE";
|
||||
const char *DUMP_HK_STORE_DONE_STRING = "DUMP_HK_STORE_DONE";
|
||||
const char *DUMP_CFDP_STORE_DONE_STRING = "DUMP_CFDP_STORE_DONE";
|
||||
|
||||
const char *translateEvents(Event event) {
|
||||
switch ((event & 0xFFFF)) {
|
||||
@ -347,6 +420,8 @@ const char *translateEvents(Event event) {
|
||||
return RECOVERY_STEP_STRING;
|
||||
case (7512):
|
||||
return RECOVERY_DONE_STRING;
|
||||
case (7600):
|
||||
return HANDLE_PACKET_FAILED_STRING;
|
||||
case (7900):
|
||||
return RF_AVAILABLE_STRING;
|
||||
case (7901):
|
||||
@ -360,11 +435,35 @@ const char *translateEvents(Event event) {
|
||||
case (8900):
|
||||
return CLOCK_SET_STRING;
|
||||
case (8901):
|
||||
return CLOCK_DUMP_STRING;
|
||||
case (8902):
|
||||
return CLOCK_SET_FAILURE_STRING;
|
||||
case (9100):
|
||||
return TC_DELETION_FAILED_STRING;
|
||||
case (9700):
|
||||
return TEST_STRING;
|
||||
case (10600):
|
||||
return CHANGE_OF_SETUP_PARAMETER_STRING;
|
||||
case (10800):
|
||||
return STORE_ERROR_STRING;
|
||||
case (10801):
|
||||
return MSG_QUEUE_ERROR_STRING;
|
||||
case (10802):
|
||||
return SERIALIZATION_ERROR_STRING;
|
||||
case (10803):
|
||||
return FILESTORE_ERROR_STRING;
|
||||
case (10804):
|
||||
return FILENAME_TOO_LARGE_ERROR_STRING;
|
||||
case (11200):
|
||||
return SAFE_RATE_VIOLATION_STRING;
|
||||
case (11201):
|
||||
return SAFE_RATE_RECOVERY_STRING;
|
||||
case (11202):
|
||||
return MULTIPLE_RW_INVALID_STRING;
|
||||
case (11203):
|
||||
return MEKF_INVALID_INFO_STRING;
|
||||
case (11204):
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
case (11300):
|
||||
return SWITCH_CMD_SENT_STRING;
|
||||
case (11301):
|
||||
@ -378,21 +477,35 @@ const char *translateEvents(Event event) {
|
||||
case (11401):
|
||||
return GPIO_PULL_LOW_FAILED_STRING;
|
||||
case (11402):
|
||||
return SWITCH_ALREADY_ON_STRING;
|
||||
return HEATER_WENT_ON_STRING;
|
||||
case (11403):
|
||||
return SWITCH_ALREADY_OFF_STRING;
|
||||
return HEATER_WENT_OFF_STRING;
|
||||
case (11404):
|
||||
return SWITCH_ALREADY_ON_STRING;
|
||||
case (11405):
|
||||
return SWITCH_ALREADY_OFF_STRING;
|
||||
case (11406):
|
||||
return MAIN_SWITCH_TIMEOUT_STRING;
|
||||
case (11407):
|
||||
return FAULTY_HEATER_WAS_ON_STRING;
|
||||
case (11500):
|
||||
return MAIN_SWITCH_ON_TIMEOUT_STRING;
|
||||
return BURN_PHASE_START_STRING;
|
||||
case (11501):
|
||||
return MAIN_SWITCH_OFF_TIMEOUT_STRING;
|
||||
return BURN_PHASE_DONE_STRING;
|
||||
case (11502):
|
||||
return DEPLOYMENT_FAILED_STRING;
|
||||
return MAIN_SWITCH_ON_TIMEOUT_STRING;
|
||||
case (11503):
|
||||
return DEPL_SA1_GPIO_SWTICH_ON_FAILED_STRING;
|
||||
return MAIN_SWITCH_OFF_TIMEOUT_STRING;
|
||||
case (11504):
|
||||
return DEPL_SA1_GPIO_SWTICH_ON_FAILED_STRING;
|
||||
case (11505):
|
||||
return DEPL_SA2_GPIO_SWTICH_ON_FAILED_STRING;
|
||||
case (11506):
|
||||
return DEPL_SA1_GPIO_SWTICH_OFF_FAILED_STRING;
|
||||
case (11507):
|
||||
return DEPL_SA2_GPIO_SWTICH_OFF_FAILED_STRING;
|
||||
case (11508):
|
||||
return AUTONOMOUS_DEPLOYMENT_COMPLETED_STRING;
|
||||
case (11601):
|
||||
return MEMORY_READ_RPT_CRC_FAILURE_STRING;
|
||||
case (11602):
|
||||
@ -426,19 +539,25 @@ const char *translateEvents(Event event) {
|
||||
case (11802):
|
||||
return RESET_OCCURED_STRING;
|
||||
case (11901):
|
||||
return BOOTING_FIRMWARE_FAILED_STRING;
|
||||
return BOOTING_FIRMWARE_FAILED_EVENT_STRING;
|
||||
case (11902):
|
||||
return BOOTING_BOOTLOADER_FAILED_STRING;
|
||||
return BOOTING_BOOTLOADER_FAILED_EVENT_STRING;
|
||||
case (12001):
|
||||
return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING;
|
||||
case (12002):
|
||||
return SUPV_ACK_FAILURE_STRING;
|
||||
return SUPV_UNKNOWN_TM_STRING;
|
||||
case (12003):
|
||||
return SUPV_EXE_FAILURE_STRING;
|
||||
return SUPV_UNINIMPLEMENTED_TM_STRING;
|
||||
case (12004):
|
||||
return SUPV_CRC_FAILURE_EVENT_STRING;
|
||||
return SUPV_ACK_FAILURE_STRING;
|
||||
case (12005):
|
||||
return SUPV_MPSOC_SHUWDOWN_BUILD_FAILED_STRING;
|
||||
return SUPV_EXE_FAILURE_STRING;
|
||||
case (12006):
|
||||
return SUPV_CRC_FAILURE_EVENT_STRING;
|
||||
case (12007):
|
||||
return SUPV_HELPER_EXECUTING_STRING;
|
||||
case (12008):
|
||||
return SUPV_MPSOC_SHUTDOWN_BUILD_FAILED_STRING;
|
||||
case (12100):
|
||||
return SANITIZATION_FAILED_STRING;
|
||||
case (12101):
|
||||
@ -457,6 +576,20 @@ const char *translateEvents(Event event) {
|
||||
return CARRIER_LOCK_STRING;
|
||||
case (12404):
|
||||
return BIT_LOCK_PDEC_STRING;
|
||||
case (12405):
|
||||
return LOST_CARRIER_LOCK_PDEC_STRING;
|
||||
case (12406):
|
||||
return LOST_BIT_LOCK_PDEC_STRING;
|
||||
case (12407):
|
||||
return TOO_MANY_IRQS_STRING;
|
||||
case (12408):
|
||||
return POLL_SYSCALL_ERROR_PDEC_STRING;
|
||||
case (12409):
|
||||
return WRITE_SYSCALL_ERROR_PDEC_STRING;
|
||||
case (12410):
|
||||
return PDEC_RESET_FAILED_STRING;
|
||||
case (12411):
|
||||
return OPEN_IRQ_FILE_FAILED_STRING;
|
||||
case (12500):
|
||||
return IMAGE_UPLOAD_FAILED_STRING;
|
||||
case (12501):
|
||||
@ -515,6 +648,10 @@ const char *translateEvents(Event event) {
|
||||
return MPSOC_EXE_INVALID_APID_STRING;
|
||||
case (12611):
|
||||
return MPSOC_HELPER_SEQ_CNT_MISMATCH_STRING;
|
||||
case (12612):
|
||||
return MPSOC_TM_SIZE_ERROR_STRING;
|
||||
case (12613):
|
||||
return MPSOC_TM_CRC_MISSMATCH_STRING;
|
||||
case (12700):
|
||||
return TRANSITION_BACK_TO_OFF_STRING;
|
||||
case (12701):
|
||||
@ -551,6 +688,8 @@ const char *translateEvents(Event event) {
|
||||
return CHILDREN_LOST_MODE_STRING;
|
||||
case (13100):
|
||||
return GPS_FIX_CHANGE_STRING;
|
||||
case (13101):
|
||||
return CANT_GET_FIX_STRING;
|
||||
case (13200):
|
||||
return P60_BOOT_COUNT_STRING;
|
||||
case (13201):
|
||||
@ -574,37 +713,117 @@ const char *translateEvents(Event event) {
|
||||
case (13607):
|
||||
return SUPV_EVENT_BUFFER_REQUEST_TERMINATED_STRING;
|
||||
case (13608):
|
||||
return SUPV_SENDING_COMMAND_FAILED_STRING;
|
||||
return SUPV_MEM_CHECK_OK_STRING;
|
||||
case (13609):
|
||||
return SUPV_HELPER_REQUESTING_REPLY_FAILED_STRING;
|
||||
case (13610):
|
||||
return SUPV_HELPER_READING_REPLY_FAILED_STRING;
|
||||
case (13611):
|
||||
return SUPV_MISSING_ACK_STRING;
|
||||
case (13612):
|
||||
return SUPV_MISSING_EXE_STRING;
|
||||
case (13613):
|
||||
return SUPV_ACK_FAILURE_REPORT_STRING;
|
||||
case (13614):
|
||||
return SUPV_EXE_FAILURE_REPORT_STRING;
|
||||
case (13615):
|
||||
return SUPV_ACK_INVALID_APID_STRING;
|
||||
return SUPV_MEM_CHECK_FAIL_STRING;
|
||||
case (13616):
|
||||
return SUPV_EXE_INVALID_APID_STRING;
|
||||
return SUPV_SENDING_COMMAND_FAILED_STRING;
|
||||
case (13617):
|
||||
return ACK_RECEPTION_FAILURE_STRING;
|
||||
return SUPV_HELPER_REQUESTING_REPLY_FAILED_STRING;
|
||||
case (13618):
|
||||
return EXE_RECEPTION_FAILURE_STRING;
|
||||
return SUPV_HELPER_READING_REPLY_FAILED_STRING;
|
||||
case (13619):
|
||||
return SUPV_MISSING_ACK_STRING;
|
||||
case (13620):
|
||||
return SUPV_MISSING_EXE_STRING;
|
||||
case (13621):
|
||||
return SUPV_ACK_FAILURE_REPORT_STRING;
|
||||
case (13622):
|
||||
return SUPV_EXE_FAILURE_REPORT_STRING;
|
||||
case (13623):
|
||||
return SUPV_ACK_INVALID_APID_STRING;
|
||||
case (13624):
|
||||
return SUPV_EXE_INVALID_APID_STRING;
|
||||
case (13625):
|
||||
return ACK_RECEPTION_FAILURE_STRING;
|
||||
case (13626):
|
||||
return EXE_RECEPTION_FAILURE_STRING;
|
||||
case (13627):
|
||||
return WRITE_MEMORY_FAILED_STRING;
|
||||
case (13700):
|
||||
return ALLOC_FAILURE_STRING;
|
||||
case (13628):
|
||||
return SUPV_REPLY_SIZE_MISSMATCH_STRING;
|
||||
case (13629):
|
||||
return SUPV_REPLY_CRC_MISSMATCH_STRING;
|
||||
case (13630):
|
||||
return SUPV_UPDATE_PROGRESS_STRING;
|
||||
case (13631):
|
||||
return HDLC_FRAME_REMOVAL_ERROR_STRING;
|
||||
case (13632):
|
||||
return HDLC_CRC_ERROR_STRING;
|
||||
case (13701):
|
||||
return REBOOT_SW_STRING;
|
||||
return TX_ON_STRING;
|
||||
case (13702):
|
||||
return TX_OFF_STRING;
|
||||
case (13800):
|
||||
return MISSING_PACKET_STRING;
|
||||
case (13801):
|
||||
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 (13903):
|
||||
return INSERT_CONFIGFILEVALUE_FAILED_STRING;
|
||||
case (13904):
|
||||
return WRITE_CONFIGFILE_FAILED_STRING;
|
||||
case (13905):
|
||||
return READ_CONFIGFILE_FAILED_STRING;
|
||||
case (14000):
|
||||
return ALLOC_FAILURE_STRING;
|
||||
case (14001):
|
||||
return REBOOT_SW_STRING;
|
||||
case (14002):
|
||||
return REBOOT_MECHANISM_TRIGGERED_STRING;
|
||||
case (13703):
|
||||
case (14003):
|
||||
return REBOOT_HW_STRING;
|
||||
case (14004):
|
||||
return NO_SD_CARD_ACTIVE_STRING;
|
||||
case (14005):
|
||||
return VERSION_INFO_STRING;
|
||||
case (14006):
|
||||
return CURRENT_IMAGE_INFO_STRING;
|
||||
case (14007):
|
||||
return REBOOT_COUNTER_STRING;
|
||||
case (14008):
|
||||
return INDIVIDUAL_BOOT_COUNTS_STRING;
|
||||
case (14100):
|
||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||
case (14101):
|
||||
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
|
||||
case (14102):
|
||||
return SYRLINKS_OVERHEATING_STRING;
|
||||
case (14103):
|
||||
return PLOC_OVERHEATING_STRING;
|
||||
case (14104):
|
||||
return OBC_OVERHEATING_STRING;
|
||||
case (14105):
|
||||
return HPA_OVERHEATING_STRING;
|
||||
case (14106):
|
||||
return PLPCDU_OVERHEATING_STRING;
|
||||
case (14201):
|
||||
return TX_TIMER_EXPIRED_STRING;
|
||||
case (14202):
|
||||
return BIT_LOCK_TX_ON_STRING;
|
||||
case (14300):
|
||||
return POSSIBLE_FILE_CORRUPTION_STRING;
|
||||
case (14301):
|
||||
return FILE_TOO_LARGE_STRING;
|
||||
case (14302):
|
||||
return BUSY_DUMPING_EVENT_STRING;
|
||||
case (14303):
|
||||
return DUMP_WAS_CANCELLED_STRING;
|
||||
case (14305):
|
||||
return DUMP_OK_STORE_DONE_STRING;
|
||||
case (14306):
|
||||
return DUMP_NOK_STORE_DONE_STRING;
|
||||
case (14307):
|
||||
return DUMP_MISC_STORE_DONE_STRING;
|
||||
case (14308):
|
||||
return DUMP_HK_STORE_DONE_STRING;
|
||||
case (14309):
|
||||
return DUMP_CFDP_STORE_DONE_STRING;
|
||||
default:
|
||||
return "UNKNOWN_EVENT";
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
#ifndef HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
|
||||
#define HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
|
||||
#ifndef LINUX_FSFWCONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
|
||||
#define LINUX_FSFWCONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
|
||||
|
||||
#include <fsfw/objectmanager/frameworkObjects.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "commonObjects.h"
|
||||
#include "eive/objects.h"
|
||||
|
||||
// The objects will be instantiated in the ID order
|
||||
// For naming scheme see flight manual
|
||||
@ -39,24 +39,14 @@ enum sourceObjects : uint32_t {
|
||||
FW_ADDRESS_END = TIME_STAMPER,
|
||||
PUS_SERVICE_6 = 0x51000500,
|
||||
|
||||
CCSDS_IP_CORE_BRIDGE = 0x73500000,
|
||||
TM_FUNNEL = 0x73000100,
|
||||
|
||||
/* 0x49 ('I') for Communication Interfaces **/
|
||||
ARDUINO_COM_IF = 0x49000000,
|
||||
CSP_COM_IF = 0x49050001,
|
||||
I2C_COM_IF = 0x49040002,
|
||||
UART_COM_IF = 0x49030003,
|
||||
SPI_MAIN_COM_IF = 0x49020004,
|
||||
GPIO_IF = 0x49010005,
|
||||
SPI_RW_COM_IF = 0x49020005,
|
||||
|
||||
/* Custom device handler */
|
||||
PCDU_HANDLER = 0x442000A1,
|
||||
SOLAR_ARRAY_DEPL_HANDLER = 0x444100A2,
|
||||
SYRLINKS_HK_HANDLER = 0x445300A3,
|
||||
HEATER_HANDLER = 0x444100A4,
|
||||
RAD_SENSOR = 0x443200A5,
|
||||
|
||||
/* 0x54 ('T') for test handlers */
|
||||
TEST_TASK = 0x54694269,
|
||||
@ -67,7 +57,8 @@ enum sourceObjects : uint32_t {
|
||||
DUMMY_INTERFACE = 0x5400CAFE,
|
||||
DUMMY_HANDLER = 0x5400AFFE,
|
||||
P60DOCK_TEST_TASK = 0x00005060,
|
||||
DUMMY_COM_IF = 0x54000040
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* BSP_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */
|
||||
#endif /* LINUX_FSFWCONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */
|
||||
|
@ -1,14 +1,15 @@
|
||||
/**
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 118 translations.
|
||||
* Generated on: 2022-05-21 10:25:00
|
||||
* Contains 173 translations.
|
||||
* Generated on: 2023-03-11 15:01:05
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
const char *P60DOCK_TEST_TASK_STRING = "P60DOCK_TEST_TASK";
|
||||
const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER";
|
||||
const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER";
|
||||
const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER";
|
||||
const char *GLOBAL_JSON_CFG_STRING = "GLOBAL_JSON_CFG";
|
||||
const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER";
|
||||
const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER";
|
||||
const char *GYRO_0_ADIS_HANDLER_STRING = "GYRO_0_ADIS_HANDLER";
|
||||
@ -36,6 +37,7 @@ const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER";
|
||||
const char *RW4_STRING = "RW4";
|
||||
const char *STAR_TRACKER_STRING = "STAR_TRACKER";
|
||||
const char *GPS_CONTROLLER_STRING = "GPS_CONTROLLER";
|
||||
const char *IMTQ_POLLING_STRING = "IMTQ_POLLING";
|
||||
const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER";
|
||||
const char *PCDU_HANDLER_STRING = "PCDU_HANDLER";
|
||||
const char *P60DOCK_HANDLER_STRING = "P60DOCK_HANDLER";
|
||||
@ -45,16 +47,27 @@ const char *ACU_HANDLER_STRING = "ACU_HANDLER";
|
||||
const char *BPX_BATT_HANDLER_STRING = "BPX_BATT_HANDLER";
|
||||
const char *PLPCDU_HANDLER_STRING = "PLPCDU_HANDLER";
|
||||
const char *RAD_SENSOR_STRING = "RAD_SENSOR";
|
||||
const char *PLOC_UPDATER_STRING = "PLOC_UPDATER";
|
||||
const char *PLOC_MEMORY_DUMPER_STRING = "PLOC_MEMORY_DUMPER";
|
||||
const char *STR_HELPER_STRING = "STR_HELPER";
|
||||
const char *PLOC_MPSOC_HELPER_STRING = "PLOC_MPSOC_HELPER";
|
||||
const char *AXI_PTME_CONFIG_STRING = "AXI_PTME_CONFIG";
|
||||
const char *PTME_CONFIG_STRING = "PTME_CONFIG";
|
||||
const char *PTME_VC0_LIVE_TM_STRING = "PTME_VC0_LIVE_TM";
|
||||
const char *PTME_VC1_LOG_TM_STRING = "PTME_VC1_LOG_TM";
|
||||
const char *PTME_VC2_HK_TM_STRING = "PTME_VC2_HK_TM";
|
||||
const char *PTME_VC3_CFDP_TM_STRING = "PTME_VC3_CFDP_TM";
|
||||
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";
|
||||
const char *TMP1075_HANDLER_2_STRING = "TMP1075_HANDLER_2";
|
||||
const char *TMP1075_HANDLER_TCS_0_STRING = "TMP1075_HANDLER_TCS_0";
|
||||
const char *TMP1075_HANDLER_TCS_1_STRING = "TMP1075_HANDLER_TCS_1";
|
||||
const char *TMP1075_HANDLER_PLPCDU_0_STRING = "TMP1075_HANDLER_PLPCDU_0";
|
||||
const char *TMP1075_HANDLER_PLPCDU_1_STRING = "TMP1075_HANDLER_PLPCDU_1";
|
||||
const char *TMP1075_HANDLER_IF_BOARD_STRING = "TMP1075_HANDLER_IF_BOARD";
|
||||
const char *RTD_0_IC3_PLOC_HEATSPREADER_STRING = "RTD_0_IC3_PLOC_HEATSPREADER";
|
||||
const char *RTD_1_IC4_PLOC_MISSIONBOARD_STRING = "RTD_1_IC4_PLOC_MISSIONBOARD";
|
||||
const char *RTD_2_IC5_4K_CAMERA_STRING = "RTD_2_IC5_4K_CAMERA";
|
||||
@ -71,18 +84,24 @@ const char *RTD_12_IC15_ACU_STRING = "RTD_12_IC15_ACU";
|
||||
const char *RTD_13_IC16_PLPCDU_HEATSPREADER_STRING = "RTD_13_IC16_PLPCDU_HEATSPREADER";
|
||||
const char *RTD_14_IC17_TCS_BOARD_STRING = "RTD_14_IC17_TCS_BOARD";
|
||||
const char *RTD_15_IC18_IMTQ_STRING = "RTD_15_IC18_IMTQ";
|
||||
const char *SYRLINKS_HK_HANDLER_STRING = "SYRLINKS_HK_HANDLER";
|
||||
const char *SYRLINKS_HANDLER_STRING = "SYRLINKS_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 *UART_COM_IF_STRING = "UART_COM_IF";
|
||||
const char *I2C_COM_IF_STRING = "I2C_COM_IF";
|
||||
const char *CSP_COM_IF_STRING = "CSP_COM_IF";
|
||||
const char *ACS_BOARD_POLLING_TASK_STRING = "ACS_BOARD_POLLING_TASK";
|
||||
const char *RW_POLLING_TASK_STRING = "RW_POLLING_TASK";
|
||||
const char *SPI_RTD_COM_IF_STRING = "SPI_RTD_COM_IF";
|
||||
const char *SUS_POLLING_TASK_STRING = "SUS_POLLING_TASK";
|
||||
const char *CCSDS_PACKET_DISTRIBUTOR_STRING = "CCSDS_PACKET_DISTRIBUTOR";
|
||||
const char *PUS_PACKET_DISTRIBUTOR_STRING = "PUS_PACKET_DISTRIBUTOR";
|
||||
const char *TMTC_BRIDGE_STRING = "TMTC_BRIDGE";
|
||||
const char *TMTC_POLLING_TASK_STRING = "TMTC_POLLING_TASK";
|
||||
const char *TCP_TMTC_SERVER_STRING = "TCP_TMTC_SERVER";
|
||||
const char *UDP_TMTC_SERVER_STRING = "UDP_TMTC_SERVER";
|
||||
const char *TCP_TMTC_POLLING_TASK_STRING = "TCP_TMTC_POLLING_TASK";
|
||||
const char *UDP_TMTC_POLLING_TASK_STRING = "UDP_TMTC_POLLING_TASK";
|
||||
const char *FILE_SYSTEM_HANDLER_STRING = "FILE_SYSTEM_HANDLER";
|
||||
const char *SDC_MANAGER_STRING = "SDC_MANAGER";
|
||||
const char *PTME_STRING = "PTME";
|
||||
@ -96,6 +115,8 @@ const char *PUS_SERVICE_3_HOUSEKEEPING_STRING = "PUS_SERVICE_3_HOUSEKEEPING";
|
||||
const char *PUS_SERVICE_5_EVENT_REPORTING_STRING = "PUS_SERVICE_5_EVENT_REPORTING";
|
||||
const char *PUS_SERVICE_8_FUNCTION_MGMT_STRING = "PUS_SERVICE_8_FUNCTION_MGMT";
|
||||
const char *PUS_SERVICE_9_TIME_MGMT_STRING = "PUS_SERVICE_9_TIME_MGMT";
|
||||
const char *PUS_SERVICE_11_TC_SCHEDULER_STRING = "PUS_SERVICE_11_TC_SCHEDULER";
|
||||
const char *PUS_SERVICE_15_TM_STORAGE_STRING = "PUS_SERVICE_15_TM_STORAGE";
|
||||
const char *PUS_SERVICE_17_TEST_STRING = "PUS_SERVICE_17_TEST";
|
||||
const char *PUS_SERVICE_20_PARAMETERS_STRING = "PUS_SERVICE_20_PARAMETERS";
|
||||
const char *PUS_SERVICE_200_MODE_MGMT_STRING = "PUS_SERVICE_200_MODE_MGMT";
|
||||
@ -109,30 +130,66 @@ const char *TC_STORE_STRING = "TC_STORE";
|
||||
const char *TM_STORE_STRING = "TM_STORE";
|
||||
const char *IPC_STORE_STRING = "IPC_STORE";
|
||||
const char *TIME_STAMPER_STRING = "TIME_STAMPER";
|
||||
const char *VERIFICATION_REPORTER_STRING = "VERIFICATION_REPORTER";
|
||||
const char *FSFW_OBJECTS_END_STRING = "FSFW_OBJECTS_END";
|
||||
const char *SPI_TEST_STRING = "SPI_TEST";
|
||||
const char *UART_TEST_STRING = "UART_TEST";
|
||||
const char *I2C_TEST_STRING = "I2C_TEST";
|
||||
const char *DUMMY_COM_IF_STRING = "DUMMY_COM_IF";
|
||||
const char *DUMMY_HANDLER_STRING = "DUMMY_HANDLER";
|
||||
const char *DUMMY_INTERFACE_STRING = "DUMMY_INTERFACE";
|
||||
const char *LIBGPIOD_TEST_STRING = "LIBGPIOD_TEST";
|
||||
const char *TEST_TASK_STRING = "TEST_TASK";
|
||||
const char *HEATER_0_PLOC_PROC_BRD_STRING = "HEATER_0_PLOC_PROC_BRD";
|
||||
const char *HEATER_1_PCDU_BRD_STRING = "HEATER_1_PCDU_BRD";
|
||||
const char *HEATER_2_ACS_BRD_STRING = "HEATER_2_ACS_BRD";
|
||||
const char *HEATER_3_OBC_BRD_STRING = "HEATER_3_OBC_BRD";
|
||||
const char *HEATER_4_CAMERA_STRING = "HEATER_4_CAMERA";
|
||||
const char *HEATER_5_STR_STRING = "HEATER_5_STR";
|
||||
const char *HEATER_6_DRO_STRING = "HEATER_6_DRO";
|
||||
const char *HEATER_7_SYRLINKS_STRING = "HEATER_7_SYRLINKS";
|
||||
const char *ACS_BOARD_ASS_STRING = "ACS_BOARD_ASS";
|
||||
const char *SUS_BOARD_ASS_STRING = "SUS_BOARD_ASS";
|
||||
const char *TCS_BOARD_ASS_STRING = "TCS_BOARD_ASS";
|
||||
const char *RW_ASS_STRING = "RW_ASS";
|
||||
const char *RW_ASSY_STRING = "RW_ASSY";
|
||||
const char *CAM_SWITCHER_STRING = "CAM_SWITCHER";
|
||||
const char *SYRLINKS_ASSY_STRING = "SYRLINKS_ASSY";
|
||||
const char *IMTQ_ASSY_STRING = "IMTQ_ASSY";
|
||||
const char *STR_ASSY_STRING = "STR_ASSY";
|
||||
const char *TM_FUNNEL_STRING = "TM_FUNNEL";
|
||||
const char *PUS_TM_FUNNEL_STRING = "PUS_TM_FUNNEL";
|
||||
const char *CFDP_TM_FUNNEL_STRING = "CFDP_TM_FUNNEL";
|
||||
const char *CFDP_HANDLER_STRING = "CFDP_HANDLER";
|
||||
const char *CFDP_DISTRIBUTOR_STRING = "CFDP_DISTRIBUTOR";
|
||||
const char *EIVE_SYSTEM_STRING = "EIVE_SYSTEM";
|
||||
const char *ACS_SUBSYSTEM_STRING = "ACS_SUBSYSTEM";
|
||||
const char *PL_SUBSYSTEM_STRING = "PL_SUBSYSTEM";
|
||||
const char *TCS_SUBSYSTEM_STRING = "TCS_SUBSYSTEM";
|
||||
const char *COM_SUBSYSTEM_STRING = "COM_SUBSYSTEM";
|
||||
const char *MISC_TM_STORE_STRING = "MISC_TM_STORE";
|
||||
const char *OK_TM_STORE_STRING = "OK_TM_STORE";
|
||||
const char *NOT_OK_TM_STORE_STRING = "NOT_OK_TM_STORE";
|
||||
const char *HK_TM_STORE_STRING = "HK_TM_STORE";
|
||||
const char *CFDP_TM_STORE_STRING = "CFDP_TM_STORE";
|
||||
const char *LIVE_TM_TASK_STRING = "LIVE_TM_TASK";
|
||||
const char *LOG_STORE_AND_TM_TASK_STRING = "LOG_STORE_AND_TM_TASK";
|
||||
const char *HK_STORE_AND_TM_TASK_STRING = "HK_STORE_AND_TM_TASK";
|
||||
const char *CFDP_STORE_AND_TM_TASK_STRING = "CFDP_STORE_AND_TM_TASK";
|
||||
const char *DOWNLINK_RAM_STORE_STRING = "DOWNLINK_RAM_STORE";
|
||||
const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE";
|
||||
const char *THERMAL_TEMP_INSERTER_STRING = "THERMAL_TEMP_INSERTER";
|
||||
const char *NO_OBJECT_STRING = "NO_OBJECT";
|
||||
|
||||
const char *translateObject(object_id_t object) {
|
||||
switch ((object & 0xFFFFFFFF)) {
|
||||
case 0x00005060:
|
||||
return P60DOCK_TEST_TASK_STRING;
|
||||
case 0x43000002:
|
||||
return ACS_CONTROLLER_STRING;
|
||||
case 0x43000003:
|
||||
return CORE_CONTROLLER_STRING;
|
||||
case 0x43100002:
|
||||
return ACS_CONTROLLER_STRING;
|
||||
case 0x43000006:
|
||||
return GLOBAL_JSON_CFG_STRING;
|
||||
case 0x43400001:
|
||||
return THERMAL_CONTROLLER_STRING;
|
||||
case 0x44120006:
|
||||
@ -187,6 +244,8 @@ const char *translateObject(object_id_t object) {
|
||||
return STAR_TRACKER_STRING;
|
||||
case 0x44130045:
|
||||
return GPS_CONTROLLER_STRING;
|
||||
case 0x44140013:
|
||||
return IMTQ_POLLING_STRING;
|
||||
case 0x44140014:
|
||||
return IMTQ_HANDLER_STRING;
|
||||
case 0x442000A1:
|
||||
@ -205,26 +264,48 @@ const char *translateObject(object_id_t object) {
|
||||
return PLPCDU_HANDLER_STRING;
|
||||
case 0x443200A5:
|
||||
return RAD_SENSOR_STRING;
|
||||
case 0x44330000:
|
||||
return PLOC_UPDATER_STRING;
|
||||
case 0x44330001:
|
||||
return PLOC_MEMORY_DUMPER_STRING;
|
||||
case 0x44330002:
|
||||
return STR_HELPER_STRING;
|
||||
case 0x44330003:
|
||||
return PLOC_MPSOC_HELPER_STRING;
|
||||
case 0x44330004:
|
||||
return AXI_PTME_CONFIG_STRING;
|
||||
case 0x44330005:
|
||||
return PTME_CONFIG_STRING;
|
||||
case 0x44330006:
|
||||
return PTME_VC0_LIVE_TM_STRING;
|
||||
case 0x44330007:
|
||||
return PTME_VC1_LOG_TM_STRING;
|
||||
case 0x44330008:
|
||||
return PTME_VC2_HK_TM_STRING;
|
||||
case 0x44330009:
|
||||
return PTME_VC3_CFDP_TM_STRING;
|
||||
case 0x44330015:
|
||||
return PLOC_MPSOC_HANDLER_STRING;
|
||||
case 0x44330016:
|
||||
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:
|
||||
return HEATER_HANDLER_STRING;
|
||||
case 0x44420004:
|
||||
return TMP1075_HANDLER_1_STRING;
|
||||
return TMP1075_HANDLER_TCS_0_STRING;
|
||||
case 0x44420005:
|
||||
return TMP1075_HANDLER_2_STRING;
|
||||
return TMP1075_HANDLER_TCS_1_STRING;
|
||||
case 0x44420006:
|
||||
return TMP1075_HANDLER_PLPCDU_0_STRING;
|
||||
case 0x44420007:
|
||||
return TMP1075_HANDLER_PLPCDU_1_STRING;
|
||||
case 0x44420008:
|
||||
return TMP1075_HANDLER_IF_BOARD_STRING;
|
||||
case 0x44420016:
|
||||
return RTD_0_IC3_PLOC_HEATSPREADER_STRING;
|
||||
case 0x44420017:
|
||||
@ -258,29 +339,41 @@ const char *translateObject(object_id_t object) {
|
||||
case 0x44420031:
|
||||
return RTD_15_IC18_IMTQ_STRING;
|
||||
case 0x445300A3:
|
||||
return SYRLINKS_HK_HANDLER_STRING;
|
||||
return SYRLINKS_HANDLER_STRING;
|
||||
case 0x49000000:
|
||||
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:
|
||||
return SPI_RW_COM_IF_STRING;
|
||||
case 0x49030003:
|
||||
return UART_COM_IF_STRING;
|
||||
case 0x49040002:
|
||||
return I2C_COM_IF_STRING;
|
||||
case 0x49050001:
|
||||
return CSP_COM_IF_STRING;
|
||||
case 0x49060004:
|
||||
return ACS_BOARD_POLLING_TASK_STRING;
|
||||
case 0x49060005:
|
||||
return RW_POLLING_TASK_STRING;
|
||||
case 0x49060006:
|
||||
return SPI_RTD_COM_IF_STRING;
|
||||
case 0x49060007:
|
||||
return SUS_POLLING_TASK_STRING;
|
||||
case 0x50000100:
|
||||
return CCSDS_PACKET_DISTRIBUTOR_STRING;
|
||||
case 0x50000200:
|
||||
return PUS_PACKET_DISTRIBUTOR_STRING;
|
||||
case 0x50000300:
|
||||
return TMTC_BRIDGE_STRING;
|
||||
return TCP_TMTC_SERVER_STRING;
|
||||
case 0x50000301:
|
||||
return UDP_TMTC_SERVER_STRING;
|
||||
case 0x50000400:
|
||||
return TMTC_POLLING_TASK_STRING;
|
||||
return TCP_TMTC_POLLING_TASK_STRING;
|
||||
case 0x50000401:
|
||||
return UDP_TMTC_POLLING_TASK_STRING;
|
||||
case 0x50000500:
|
||||
return FILE_SYSTEM_HANDLER_STRING;
|
||||
case 0x50000550:
|
||||
@ -307,6 +400,10 @@ const char *translateObject(object_id_t object) {
|
||||
return PUS_SERVICE_8_FUNCTION_MGMT_STRING;
|
||||
case 0x53000009:
|
||||
return PUS_SERVICE_9_TIME_MGMT_STRING;
|
||||
case 0x53000011:
|
||||
return PUS_SERVICE_11_TC_SCHEDULER_STRING;
|
||||
case 0x53000015:
|
||||
return PUS_SERVICE_15_TM_STORAGE_STRING;
|
||||
case 0x53000017:
|
||||
return PUS_SERVICE_17_TEST_STRING;
|
||||
case 0x53000020:
|
||||
@ -333,6 +430,8 @@ const char *translateObject(object_id_t object) {
|
||||
return IPC_STORE_STRING;
|
||||
case 0x53500010:
|
||||
return TIME_STAMPER_STRING;
|
||||
case 0x53500020:
|
||||
return VERIFICATION_REPORTER_STRING;
|
||||
case 0x53ffffff:
|
||||
return FSFW_OBJECTS_END_STRING;
|
||||
case 0x54000010:
|
||||
@ -341,6 +440,8 @@ const char *translateObject(object_id_t object) {
|
||||
return UART_TEST_STRING;
|
||||
case 0x54000030:
|
||||
return I2C_TEST_STRING;
|
||||
case 0x54000040:
|
||||
return DUMMY_COM_IF_STRING;
|
||||
case 0x5400AFFE:
|
||||
return DUMMY_HANDLER_STRING;
|
||||
case 0x5400CAFE:
|
||||
@ -349,6 +450,22 @@ const char *translateObject(object_id_t object) {
|
||||
return LIBGPIOD_TEST_STRING;
|
||||
case 0x54694269:
|
||||
return TEST_TASK_STRING;
|
||||
case 0x60000000:
|
||||
return HEATER_0_PLOC_PROC_BRD_STRING;
|
||||
case 0x60000001:
|
||||
return HEATER_1_PCDU_BRD_STRING;
|
||||
case 0x60000002:
|
||||
return HEATER_2_ACS_BRD_STRING;
|
||||
case 0x60000003:
|
||||
return HEATER_3_OBC_BRD_STRING;
|
||||
case 0x60000004:
|
||||
return HEATER_4_CAMERA_STRING;
|
||||
case 0x60000005:
|
||||
return HEATER_5_STR_STRING;
|
||||
case 0x60000006:
|
||||
return HEATER_6_DRO_STRING;
|
||||
case 0x60000007:
|
||||
return HEATER_7_SYRLINKS_STRING;
|
||||
case 0x73000001:
|
||||
return ACS_BOARD_ASS_STRING;
|
||||
case 0x73000002:
|
||||
@ -356,11 +473,59 @@ const char *translateObject(object_id_t object) {
|
||||
case 0x73000003:
|
||||
return TCS_BOARD_ASS_STRING;
|
||||
case 0x73000004:
|
||||
return RW_ASS_STRING;
|
||||
return RW_ASSY_STRING;
|
||||
case 0x73000006:
|
||||
return CAM_SWITCHER_STRING;
|
||||
case 0x73000007:
|
||||
return SYRLINKS_ASSY_STRING;
|
||||
case 0x73000008:
|
||||
return IMTQ_ASSY_STRING;
|
||||
case 0x73000009:
|
||||
return STR_ASSY_STRING;
|
||||
case 0x73000100:
|
||||
return TM_FUNNEL_STRING;
|
||||
case 0x73000101:
|
||||
return PUS_TM_FUNNEL_STRING;
|
||||
case 0x73000102:
|
||||
return CFDP_TM_FUNNEL_STRING;
|
||||
case 0x73000205:
|
||||
return CFDP_HANDLER_STRING;
|
||||
case 0x73000206:
|
||||
return CFDP_DISTRIBUTOR_STRING;
|
||||
case 0x73010000:
|
||||
return EIVE_SYSTEM_STRING;
|
||||
case 0x73010001:
|
||||
return ACS_SUBSYSTEM_STRING;
|
||||
case 0x73010002:
|
||||
return PL_SUBSYSTEM_STRING;
|
||||
case 0x73010003:
|
||||
return TCS_SUBSYSTEM_STRING;
|
||||
case 0x73010004:
|
||||
return COM_SUBSYSTEM_STRING;
|
||||
case 0x73020001:
|
||||
return MISC_TM_STORE_STRING;
|
||||
case 0x73020002:
|
||||
return OK_TM_STORE_STRING;
|
||||
case 0x73020003:
|
||||
return NOT_OK_TM_STORE_STRING;
|
||||
case 0x73020004:
|
||||
return HK_TM_STORE_STRING;
|
||||
case 0x73030000:
|
||||
return CFDP_TM_STORE_STRING;
|
||||
case 0x73040000:
|
||||
return LIVE_TM_TASK_STRING;
|
||||
case 0x73040001:
|
||||
return LOG_STORE_AND_TM_TASK_STRING;
|
||||
case 0x73040002:
|
||||
return HK_STORE_AND_TM_TASK_STRING;
|
||||
case 0x73040003:
|
||||
return CFDP_STORE_AND_TM_TASK_STRING;
|
||||
case 0x73040004:
|
||||
return DOWNLINK_RAM_STORE_STRING;
|
||||
case 0x73500000:
|
||||
return CCSDS_IP_CORE_BRIDGE_STRING;
|
||||
case 0x90000003:
|
||||
return THERMAL_TEMP_INSERTER_STRING;
|
||||
case 0xFFFFFFFF:
|
||||
return NO_OBJECT_STRING;
|
||||
default:
|
||||
|
@ -1,705 +0,0 @@
|
||||
#include "pollingSequenceFactory.h"
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||
#include <fsfw/objectmanager/ObjectManagerIF.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
|
||||
|
||||
#ifndef RPI_TEST_ADIS16507
|
||||
#define RPI_TEST_ADIS16507 0
|
||||
#endif
|
||||
|
||||
#ifndef RPI_TEST_GPS_HANDLER
|
||||
#define RPI_TEST_GPS_HANDLER 0
|
||||
#endif
|
||||
|
||||
ReturnValue_t pst::pstGpio(FixedTimeslotTaskIF *thisSequence) {
|
||||
// Length of a communication cycle
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
|
||||
thisSequence->addSlot(objects::HEATER_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SOLAR_ARRAY_DEPL_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
|
||||
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
sif::error << "PollingSequence::initialize has errors!" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t pst::pstSpiRw(FixedTimeslotTaskIF *thisSequence) {
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
static_cast<void>(length);
|
||||
thisSequence->addSlot(objects::RW1, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RW2, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RW3, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RW4, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
|
||||
thisSequence->addSlot(objects::RW1, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RW2, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RW3, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RW4, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
|
||||
thisSequence->addSlot(objects::RW1, length * 0.8, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RW2, length * 0.8, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RW3, length * 0.8, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RW4, length * 0.8, DeviceHandlerIF::GET_WRITE);
|
||||
|
||||
thisSequence->addSlot(objects::RW1, length * 0.8, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RW2, length * 0.8, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RW3, length * 0.8, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RW4, length * 0.8, DeviceHandlerIF::SEND_READ);
|
||||
|
||||
thisSequence->addSlot(objects::RW1, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RW2, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RW3, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RW4, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
return thisSequence->checkSequence();
|
||||
}
|
||||
|
||||
ReturnValue_t pst::pstSpi(FixedTimeslotTaskIF *thisSequence) {
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
static_cast<void>(length);
|
||||
#if OBSW_ADD_PL_PCDU == 1
|
||||
thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
#if OBSW_ADD_TMP_DEVICES == 1
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
#endif
|
||||
#if OBSW_ADD_RTD_DEVICES == 1
|
||||
thisSequence->addSlot(objects::RTD_0_IC3_PLOC_HEATSPREADER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_1_IC4_PLOC_MISSIONBOARD, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_2_IC5_4K_CAMERA, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_3_IC6_DAC_HEATSPREADER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_4_IC7_STARTRACKER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_5_IC8_RW1_MX_MY, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_6_IC9_DRO, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_7_IC10_SCEX, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_8_IC11_X8, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_9_IC12_HPA, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_10_IC13_PL_TX, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_11_IC14_MPA, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_12_IC15_ACU, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_13_IC16_PLPCDU_HEATSPREADER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_14_IC17_TCS_BOARD, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RTD_15_IC18_IMTQ, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
#endif /* OBSW_ADD_RTD_DEVICES */
|
||||
|
||||
#if OBSW_ADD_TMP_DEVICES == 1
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
#endif
|
||||
#if OBSW_ADD_RTD_DEVICES == 1
|
||||
thisSequence->addSlot(objects::RTD_0_IC3_PLOC_HEATSPREADER, length * 0.2,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_1_IC4_PLOC_MISSIONBOARD, length * 0.2,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_2_IC5_4K_CAMERA, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_3_IC6_DAC_HEATSPREADER, length * 0.2,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_4_IC7_STARTRACKER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_5_IC8_RW1_MX_MY, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_6_IC9_DRO, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_7_IC10_SCEX, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_8_IC11_X8, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_9_IC12_HPA, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_10_IC13_PL_TX, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_11_IC14_MPA, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_12_IC15_ACU, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_13_IC16_PLPCDU_HEATSPREADER, length * 0.2,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_14_IC17_TCS_BOARD, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_15_IC18_IMTQ, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
#endif /* OBSW_ADD_RTD_DEVICES */
|
||||
|
||||
#if OBSW_ADD_TMP_DEVICES == 1
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
#endif
|
||||
#if OBSW_ADD_RTD_DEVICES == 1
|
||||
thisSequence->addSlot(objects::RTD_0_IC3_PLOC_HEATSPREADER, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_1_IC4_PLOC_MISSIONBOARD, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_2_IC5_4K_CAMERA, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_3_IC6_DAC_HEATSPREADER, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_4_IC7_STARTRACKER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_5_IC8_RW1_MX_MY, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_6_IC9_DRO, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_7_IC10_SCEX, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_8_IC11_X8, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_9_IC12_HPA, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_10_IC13_PL_TX, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_11_IC14_MPA, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_12_IC15_ACU, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_13_IC16_PLPCDU_HEATSPREADER, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_14_IC17_TCS_BOARD, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RTD_15_IC18_IMTQ, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
#endif /* OBSW_ADD_RTD_DEVICES */
|
||||
|
||||
#if OBSW_ADD_TMP_DEVICES == 1
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
#endif
|
||||
#if OBSW_ADD_RTD_DEVICES == 1
|
||||
thisSequence->addSlot(objects::RTD_0_IC3_PLOC_HEATSPREADER, length * 0.6,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_1_IC4_PLOC_MISSIONBOARD, length * 0.6,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_2_IC5_4K_CAMERA, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_3_IC6_DAC_HEATSPREADER, length * 0.6,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_4_IC7_STARTRACKER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_5_IC8_RW1_MX_MY, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_6_IC9_DRO, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_7_IC10_SCEX, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_8_IC11_X8, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_9_IC12_HPA, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_10_IC13_PL_TX, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_11_IC14_MPA, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_12_IC15_ACU, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_13_IC16_PLPCDU_HEATSPREADER, length * 0.6,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_14_IC17_TCS_BOARD, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RTD_15_IC18_IMTQ, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
#endif /* OBSW_ADD_RTD_DEVICES */
|
||||
|
||||
#if OBSW_ADD_TMP_DEVICES == 1
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
#if OBSW_ADD_RTD_DEVICES == 1
|
||||
thisSequence->addSlot(objects::RTD_0_IC3_PLOC_HEATSPREADER, length * 0.8,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_1_IC4_PLOC_MISSIONBOARD, length * 0.8,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_2_IC5_4K_CAMERA, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_3_IC6_DAC_HEATSPREADER, length * 0.8,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_4_IC7_STARTRACKER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_5_IC8_RW1_MX_MY, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_6_IC9_DRO, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_7_IC10_SCEX, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_8_IC11_X8, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_9_IC12_HPA, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_10_IC13_PL_TX, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_11_IC14_MPA, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_12_IC15_ACU, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_13_IC16_PLPCDU_HEATSPREADER, length * 0.8,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_14_IC17_TCS_BOARD, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::RTD_15_IC18_IMTQ, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
#endif /* OBSW_ADD_RTD_DEVICES */
|
||||
|
||||
#if OBSW_ADD_RAD_SENSORS == 1
|
||||
/* Radiation sensor */
|
||||
thisSequence->addSlot(objects::RAD_SENSOR, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::RAD_SENSOR, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::RAD_SENSOR, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::RAD_SENSOR, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RAD_SENSOR, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
|
||||
#if OBSW_ADD_SUN_SENSORS == 1
|
||||
|
||||
bool addSus0 = true;
|
||||
bool addSus1 = true;
|
||||
bool addSus2 = true;
|
||||
bool addSus3 = true;
|
||||
bool addSus4 = true;
|
||||
bool addSus5 = true;
|
||||
bool addSus6 = true;
|
||||
bool addSus7 = true;
|
||||
bool addSus8 = true;
|
||||
bool addSus9 = true;
|
||||
bool addSus10 = true;
|
||||
bool addSus11 = true;
|
||||
|
||||
if (addSus0) {
|
||||
/* Write setup */
|
||||
thisSequence->addSlot(objects::SUS_0_N_LOC_XFYFZM_PT_XF, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SUS_0_N_LOC_XFYFZM_PT_XF, length * 0,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_0_N_LOC_XFYFZM_PT_XF, length * 0,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_0_N_LOC_XFYFZM_PT_XF, length * 0,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_0_N_LOC_XFYFZM_PT_XF, length * 0, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::SUS_0_N_LOC_XFYFZM_PT_XF, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_0_N_LOC_XFYFZM_PT_XF, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_0_N_LOC_XFYFZM_PT_XF, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_0_N_LOC_XFYFZM_PT_XF, length * 0.4,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
if (addSus1) {
|
||||
thisSequence->addSlot(objects::SUS_1_N_LOC_XBYFZM_PT_XB, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SUS_1_N_LOC_XBYFZM_PT_XB, length * 0,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_1_N_LOC_XBYFZM_PT_XB, length * 0,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_1_N_LOC_XBYFZM_PT_XB, length * 0,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_1_N_LOC_XBYFZM_PT_XB, length * 0, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::SUS_1_N_LOC_XBYFZM_PT_XB, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_1_N_LOC_XBYFZM_PT_XB, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_1_N_LOC_XBYFZM_PT_XB, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_1_N_LOC_XBYFZM_PT_XB, length * 0.4,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
if (addSus2) {
|
||||
thisSequence->addSlot(objects::SUS_2_N_LOC_XFYBZB_PT_YB, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SUS_2_N_LOC_XFYBZB_PT_YB, length * 0,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_2_N_LOC_XFYBZB_PT_YB, length * 0,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_2_N_LOC_XFYBZB_PT_YB, length * 0,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_2_N_LOC_XFYBZB_PT_YB, length * 0, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::SUS_2_N_LOC_XFYBZB_PT_YB, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_2_N_LOC_XFYBZB_PT_YB, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_2_N_LOC_XFYBZB_PT_YB, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_2_N_LOC_XFYBZB_PT_YB, length * 0.4,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
if (addSus3) {
|
||||
thisSequence->addSlot(objects::SUS_3_N_LOC_XFYBZF_PT_YF, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SUS_3_N_LOC_XFYBZF_PT_YF, length * 0,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_3_N_LOC_XFYBZF_PT_YF, length * 0,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_3_N_LOC_XFYBZF_PT_YF, length * 0,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_3_N_LOC_XFYBZF_PT_YF, length * 0, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::SUS_3_N_LOC_XFYBZF_PT_YF, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_3_N_LOC_XFYBZF_PT_YF, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_3_N_LOC_XFYBZF_PT_YF, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_3_N_LOC_XFYBZF_PT_YF, length * 0.4,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
if (addSus4) {
|
||||
thisSequence->addSlot(objects::SUS_4_N_LOC_XMYFZF_PT_ZF, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SUS_4_N_LOC_XMYFZF_PT_ZF, length * 0,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_4_N_LOC_XMYFZF_PT_ZF, length * 0,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_4_N_LOC_XMYFZF_PT_ZF, length * 0,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_4_N_LOC_XMYFZF_PT_ZF, length * 0, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::SUS_4_N_LOC_XMYFZF_PT_ZF, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_4_N_LOC_XMYFZF_PT_ZF, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_4_N_LOC_XMYFZF_PT_ZF, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_4_N_LOC_XMYFZF_PT_ZF, length * 0.4,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
if (addSus5) {
|
||||
thisSequence->addSlot(objects::SUS_5_N_LOC_XFYMZB_PT_ZB, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SUS_5_N_LOC_XFYMZB_PT_ZB, length * 0,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_5_N_LOC_XFYMZB_PT_ZB, length * 0,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_5_N_LOC_XFYMZB_PT_ZB, length * 0,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_5_N_LOC_XFYMZB_PT_ZB, length * 0, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::SUS_5_N_LOC_XFYMZB_PT_ZB, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_5_N_LOC_XFYMZB_PT_ZB, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_5_N_LOC_XFYMZB_PT_ZB, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_5_N_LOC_XFYMZB_PT_ZB, length * 0.4,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
|
||||
if (addSus6) {
|
||||
thisSequence->addSlot(objects::SUS_6_R_LOC_XFYBZM_PT_XF, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SUS_6_R_LOC_XFYBZM_PT_XF, length * 0,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_6_R_LOC_XFYBZM_PT_XF, length * 0,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_6_R_LOC_XFYBZM_PT_XF, length * 0,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_6_R_LOC_XFYBZM_PT_XF, length * 0, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::SUS_6_R_LOC_XFYBZM_PT_XF, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_6_R_LOC_XFYBZM_PT_XF, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_6_R_LOC_XFYBZM_PT_XF, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_6_R_LOC_XFYBZM_PT_XF, length * 0.4,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
|
||||
if (addSus7) {
|
||||
thisSequence->addSlot(objects::SUS_7_R_LOC_XBYBZM_PT_XB, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SUS_7_R_LOC_XBYBZM_PT_XB, length * 0,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_7_R_LOC_XBYBZM_PT_XB, length * 0,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_7_R_LOC_XBYBZM_PT_XB, length * 0,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_7_R_LOC_XBYBZM_PT_XB, length * 0, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::SUS_7_R_LOC_XBYBZM_PT_XB, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_7_R_LOC_XBYBZM_PT_XB, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_7_R_LOC_XBYBZM_PT_XB, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_7_R_LOC_XBYBZM_PT_XB, length * 0.4,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
|
||||
if (addSus8) {
|
||||
thisSequence->addSlot(objects::SUS_8_R_LOC_XBYBZB_PT_YB, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SUS_8_R_LOC_XBYBZB_PT_YB, length * 0,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_8_R_LOC_XBYBZB_PT_YB, length * 0,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_8_R_LOC_XBYBZB_PT_YB, length * 0,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_8_R_LOC_XBYBZB_PT_YB, length * 0, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::SUS_8_R_LOC_XBYBZB_PT_YB, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_8_R_LOC_XBYBZB_PT_YB, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_8_R_LOC_XBYBZB_PT_YB, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_8_R_LOC_XBYBZB_PT_YB, length * 0.4,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
|
||||
if (addSus9) {
|
||||
thisSequence->addSlot(objects::SUS_9_R_LOC_XBYBZB_PT_YF, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SUS_9_R_LOC_XBYBZB_PT_YF, length * 0,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_9_R_LOC_XBYBZB_PT_YF, length * 0,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_9_R_LOC_XBYBZB_PT_YF, length * 0,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_9_R_LOC_XBYBZB_PT_YF, length * 0, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::SUS_9_R_LOC_XBYBZB_PT_YF, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_9_R_LOC_XBYBZB_PT_YF, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_9_R_LOC_XBYBZB_PT_YF, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_9_R_LOC_XBYBZB_PT_YF, length * 0.4,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
|
||||
if (addSus10) {
|
||||
thisSequence->addSlot(objects::SUS_10_N_LOC_XMYBZF_PT_ZF, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SUS_10_N_LOC_XMYBZF_PT_ZF, length * 0,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_10_N_LOC_XMYBZF_PT_ZF, length * 0,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_10_N_LOC_XMYBZF_PT_ZF, length * 0,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_10_N_LOC_XMYBZF_PT_ZF, length * 0,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::SUS_10_N_LOC_XMYBZF_PT_ZF, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_10_N_LOC_XMYBZF_PT_ZF, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_10_N_LOC_XMYBZF_PT_ZF, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_10_N_LOC_XMYBZF_PT_ZF, length * 0.4,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
|
||||
if (addSus11) {
|
||||
thisSequence->addSlot(objects::SUS_11_R_LOC_XBYMZB_PT_ZB, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SUS_11_R_LOC_XBYMZB_PT_ZB, length * 0,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_11_R_LOC_XBYMZB_PT_ZB, length * 0,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_11_R_LOC_XBYMZB_PT_ZB, length * 0,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_11_R_LOC_XBYMZB_PT_ZB, length * 0,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::SUS_11_R_LOC_XBYMZB_PT_ZB, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_11_R_LOC_XBYMZB_PT_ZB, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SUS_11_R_LOC_XBYMZB_PT_ZB, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SUS_11_R_LOC_XBYMZB_PT_ZB, length * 0.4,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
#endif /* OBSW_ADD_SUN_SENSORS == 1 */
|
||||
|
||||
#if OBSW_ADD_ACS_BOARD == 1 && OBSW_ADD_ACS_HANDLERS == 1
|
||||
bool enableAside = true;
|
||||
bool enableBside = true;
|
||||
if (enableAside) {
|
||||
// A side
|
||||
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.25, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.6, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.7, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.85, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.25,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.6, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.7, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.85, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0.25, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0.6, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0.7, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0.85, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.25, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.6, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.7, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.85, DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
|
||||
if (enableBside) {
|
||||
// B side
|
||||
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.25, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.6, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.7, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.85, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER, length * 0.25,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER, length * 0.6, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER, length * 0.7, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER, length * 0.85, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER, length * 0.25, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER, length * 0.6, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER, length * 0.7, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER, length * 0.85, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * 0.25, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * 0.6, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * 0.7, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * 0.85, DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
#endif /* OBSW_ADD_ACS_BOARD == 1 && OBSW_ADD_ACS_HANDLERS == 1 */
|
||||
|
||||
return thisSequence->checkSequence();
|
||||
}
|
||||
|
||||
ReturnValue_t pst::pstI2c(FixedTimeslotTaskIF *thisSequence) {
|
||||
// Length of a communication cycle
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
static_cast<void>(length);
|
||||
#if OBSW_ADD_MGT == 1
|
||||
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
|
||||
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
static_cast<void>(length);
|
||||
return thisSequence->checkSequence();
|
||||
}
|
||||
|
||||
ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) {
|
||||
// Length of a communication cycle
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
bool uartPstEmpty = true;
|
||||
|
||||
#if OBSW_ADD_PLOC_MPSOC == 1
|
||||
uartPstEmpty = false;
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::PLOC_MPSOC_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
|
||||
thisSequence->addSlot(objects::PLOC_MEMORY_DUMPER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
#if OBSW_ADD_PLOC_SUPERVISOR == 1
|
||||
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.2,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::PLOC_SUPERVISOR_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
|
||||
#if OBSW_ADD_SYRLINKS == 1
|
||||
uartPstEmpty = false;
|
||||
thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SYRLINKS_HK_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
|
||||
#if OBSW_ADD_STAR_TRACKER == 1
|
||||
uartPstEmpty = false;
|
||||
thisSequence->addSlot(objects::STAR_TRACKER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::STAR_TRACKER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::STAR_TRACKER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::STAR_TRACKER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::STAR_TRACKER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
static_cast<void>(length);
|
||||
if (uartPstEmpty) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "UART PST initialization failed" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t pst::pstGompaceCan(FixedTimeslotTaskIF *thisSequence) {
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
// PCDU handlers receives two messages and both must be handled
|
||||
thisSequence->addSlot(objects::PCDU_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "GomSpace PST initialization failed" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
static_cast<void>(length);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t pst::pstTest(FixedTimeslotTaskIF *thisSequence) {
|
||||
/* Length of a communication cycle */
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
bool notEmpty = false;
|
||||
|
||||
#if RPI_TEST_ADIS16507 == 1
|
||||
notEmpty = true;
|
||||
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
|
||||
#if RPI_TEST_GPS_HANDLER == 1
|
||||
notEmpty = true;
|
||||
thisSequence->addSlot(objects::GPS0_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
|
||||
thisSequence->addSlot(objects::GPS0_HANDLER, length * 0, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::GPS0_HANDLER, length * 0, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::GPS0_HANDLER, length * 0.5, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::GPS0_HANDLER, length * 0.5, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
static_cast<void>(length);
|
||||
if (not notEmpty) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "Test PST initialization failed" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
#ifndef POLLINGSEQUENCEFACTORY_H_
|
||||
#define POLLINGSEQUENCEFACTORY_H_
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#if defined(RASPBERRY_PI)
|
||||
#include "rpiConfig.h"
|
||||
#elif defined(XIPHOS_Q7S)
|
||||
#include "q7sConfig.h"
|
||||
#endif
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
class FixedTimeslotTaskIF;
|
||||
|
||||
/**
|
||||
* All device handlers are scheduled by adding them into
|
||||
* Polling Sequence Tables (PST) to satisfy stricter timing requirements of
|
||||
* device communication, a device handler has four different communication steps:
|
||||
* 1. DeviceHandlerIF::SEND_WRITE -> Send write via interface
|
||||
* 2. DeviceHandlerIF::GET_WRITE -> Get confirmation for write
|
||||
* 3. DeviceHandlerIF::SEND_READ -> Send read request
|
||||
* 4. DeviceHandlerIF::GET_READ -> Read from interface
|
||||
* The PST specifies precisely when the respective ComIF functions are called
|
||||
* during the communication cycle time.
|
||||
* The task is created using the FixedTimeslotTaskIF,
|
||||
* which utilises the underlying Operating System Abstraction Layer (OSAL)
|
||||
*
|
||||
* @param thisSequence FixedTimeslotTaskIF * object is passed inside the
|
||||
* Factory class when creating the PST
|
||||
* @return
|
||||
*/
|
||||
namespace pst {
|
||||
|
||||
/* 0.4 second period init*/
|
||||
ReturnValue_t pstGpio(FixedTimeslotTaskIF* thisSequence);
|
||||
|
||||
/**
|
||||
* @brief This function creates the PST for all gomspace devices.
|
||||
* @details
|
||||
* Scheduled in a separate PST because the gomspace library uses blocking calls when requesting
|
||||
* data from devices.
|
||||
*/
|
||||
ReturnValue_t pstGompaceCan(FixedTimeslotTaskIF* thisSequence);
|
||||
|
||||
ReturnValue_t pstUart(FixedTimeslotTaskIF* thisSequence);
|
||||
|
||||
ReturnValue_t pstSpi(FixedTimeslotTaskIF* thisSequence);
|
||||
|
||||
ReturnValue_t pstSpiRw(FixedTimeslotTaskIF* thisSequence);
|
||||
|
||||
ReturnValue_t pstI2c(FixedTimeslotTaskIF* thisSequence);
|
||||
|
||||
/**
|
||||
* Generic test PST
|
||||
* @param thisSequence
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t pstTest(FixedTimeslotTaskIF* thisSequence);
|
||||
} // namespace pst
|
||||
|
||||
#endif /* POLLINGSEQUENCEINIT_H_ */
|
@ -1,9 +1,10 @@
|
||||
#ifndef FSFWCONFIG_RETURNVALUES_CLASSIDS_H_
|
||||
#define FSFWCONFIG_RETURNVALUES_CLASSIDS_H_
|
||||
|
||||
#include <common/config/commonClassIds.h>
|
||||
#include <fsfw/returnvalues/FwClassIds.h>
|
||||
|
||||
#include "eive/resultClassIds.h"
|
||||
|
||||
/**
|
||||
* Source IDs starts at 73 for now
|
||||
* Framework IDs for ReturnValues run from 0 to 56
|
||||
@ -12,9 +13,8 @@
|
||||
namespace CLASS_ID {
|
||||
enum {
|
||||
CLASS_ID_START = COMMON_CLASS_ID_END,
|
||||
SD_CARD_MANAGER, // SDMA
|
||||
SCRATCH_BUFFER, // SCBU
|
||||
CLASS_ID_END // [EXPORT] : [END]
|
||||
SCRATCH_BUFFER, // SCBU
|
||||
CLASS_ID_END // [EXPORT] : [END]
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
#ifndef CONFIG_TMTC_PUSIDS_HPP_
|
||||
#define CONFIG_TMTC_PUSIDS_HPP_
|
||||
|
||||
namespace pus {
|
||||
enum Ids {
|
||||
PUS_SERVICE_1 = 1,
|
||||
PUS_SERVICE_2 = 2,
|
||||
PUS_SERVICE_3 = 3,
|
||||
PUS_SERVICE_3_PSB = 3,
|
||||
PUS_SERVICE_5 = 5,
|
||||
PUS_SERVICE_6 = 6,
|
||||
PUS_SERVICE_8 = 8,
|
||||
PUS_SERVICE_9 = 9,
|
||||
PUS_SERVICE_17 = 17,
|
||||
PUS_SERVICE_19 = 19,
|
||||
PUS_SERVICE_20 = 20,
|
||||
PUS_SERVICE_23 = 23,
|
||||
PUS_SERVICE_200 = 200,
|
||||
PUS_SERVICE_201 = 201,
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* CONFIG_TMTC_PUSIDS_HPP_ */
|
@ -4,7 +4,7 @@
|
||||
#include "fsfw_hal/linux/uio/UioMapper.h"
|
||||
|
||||
AxiPtmeConfig::AxiPtmeConfig(object_id_t objectId, std::string axiUio, int mapNum)
|
||||
: SystemObject(objectId), axiUio(axiUio), mapNum(mapNum) {
|
||||
: SystemObject(objectId), axiUio(std::move(axiUio)), mapNum(mapNum) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
if (mutex == nullptr) {
|
||||
sif::warning << "Failed to create mutex" << std::endl;
|
||||
@ -14,106 +14,106 @@ AxiPtmeConfig::AxiPtmeConfig(object_id_t objectId, std::string axiUio, int mapNu
|
||||
AxiPtmeConfig::~AxiPtmeConfig() {}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::initialize() {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
UioMapper uioMapper(axiUio, mapNum);
|
||||
result = uioMapper.getMappedAdress(&baseAddress, UioMapper::Permissions::READ_WRITE);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = mutex->lockMutex(timeoutType, mutexTimeout);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "AxiPtmeConfig::writeCaduRateReg: Failed to lock mutex" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
*(baseAddress + CADU_BITRATE_REG) = static_cast<uint32_t>(rateVal);
|
||||
result = mutex->unlockMutex();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "AxiPtmeConfig::writeCaduRateReg: Failed to unlock mutex" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::enableTxclockManipulator() {
|
||||
ReturnValue_t result = writeBit(COMMON_CONFIG_REG, true, BitPos::EN_TX_CLK_MANIPULATOR);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::disableTxclockManipulator() {
|
||||
ReturnValue_t result = writeBit(COMMON_CONFIG_REG, false, BitPos::EN_TX_CLK_MANIPULATOR);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::enableTxclockInversion() {
|
||||
ReturnValue_t result = writeBit(COMMON_CONFIG_REG, true, BitPos::INVERT_CLOCK);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::disableTxclockInversion() {
|
||||
ReturnValue_t result = writeBit(COMMON_CONFIG_REG, false, BitPos::INVERT_CLOCK);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::writeReg(uint32_t regOffset, uint32_t writeVal) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = mutex->lockMutex(timeoutType, mutexTimeout);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "AxiPtmeConfig::readReg: Failed to lock mutex" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
*(baseAddress + regOffset / ADRESS_DIVIDER) = writeVal;
|
||||
result = mutex->unlockMutex();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "AxiPtmeConfig::readReg: Failed to unlock mutex" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::readReg(uint32_t regOffset, uint32_t* readVal) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = mutex->lockMutex(timeoutType, mutexTimeout);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "AxiPtmeConfig::readReg: Failed to lock mutex" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
*readVal = *(baseAddress + regOffset / ADRESS_DIVIDER);
|
||||
result = mutex->unlockMutex();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "AxiPtmeConfig::readReg: Failed to unlock mutex" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::writeBit(uint32_t regOffset, bool bitVal, BitPos bitPos) {
|
||||
uint32_t readVal = 0;
|
||||
ReturnValue_t result = readReg(regOffset, &readVal);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint32_t writeVal =
|
||||
(readVal & ~(1 << static_cast<uint32_t>(bitPos))) | bitVal << static_cast<uint32_t>(bitPos);
|
||||
result = writeReg(regOffset, writeVal);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "fsfw/ipc/MutexIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
/**
|
||||
* @brief Class providing low level access to the configuration interface of the PTME.
|
||||
@ -94,7 +94,7 @@ class AxiPtmeConfig : public SystemObject {
|
||||
* @param bitVal The value of the bit to set (1 or 0)
|
||||
* @param bitPos The position of the bit within the register to set
|
||||
*
|
||||
* @return RETURN_OK if successful, otherwise RETURN_FAILED
|
||||
* @return returnvalue::OK if successful, otherwise returnvalue::FAILED
|
||||
*/
|
||||
ReturnValue_t writeBit(uint32_t regOffset, bool bitVal, BitPos bitPos);
|
||||
};
|
3
linux/ipcore/CMakeLists.txt
Normal file
3
linux/ipcore/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
target_sources(
|
||||
${OBSW_NAME} PUBLIC PapbVcInterface.cpp Ptme.cpp PdecHandler.cpp
|
||||
PdecConfig.cpp PtmeConfig.cpp AxiPtmeConfig.cpp)
|
@ -1,5 +1,5 @@
|
||||
#include <fsfw_hal/linux/uio/UioMapper.h>
|
||||
#include <linux/obc/PapbVcInterface.h>
|
||||
#include <linux/ipcore/PapbVcInterface.h>
|
||||
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
@ -8,7 +8,7 @@ PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId,
|
||||
: gpioComIF(gpioComIF),
|
||||
papbBusyId(papbBusyId),
|
||||
papbEmptyId(papbEmptyId),
|
||||
uioFile(uioFile),
|
||||
uioFile(std::move(uioFile)),
|
||||
mapNum(mapNum) {}
|
||||
|
||||
PapbVcInterface::~PapbVcInterface() {}
|
||||
@ -19,54 +19,53 @@ ReturnValue_t PapbVcInterface::initialize() {
|
||||
}
|
||||
|
||||
ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
|
||||
if (pollPapbBusySignal() == RETURN_OK) {
|
||||
if (pollPapbBusySignal() == returnvalue::OK) {
|
||||
startPacketTransfer();
|
||||
}
|
||||
for (size_t idx = 0; idx < size; idx++) {
|
||||
if (pollPapbBusySignal() == RETURN_OK) {
|
||||
if (pollPapbBusySignal() == returnvalue::OK) {
|
||||
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(*(data + idx));
|
||||
} else {
|
||||
sif::warning << "PapbVcInterface::write: Only written " << idx << " of " << size << " data"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
if (pollPapbBusySignal() == RETURN_OK) {
|
||||
if (pollPapbBusySignal() == returnvalue::OK) {
|
||||
endPacketTransfer();
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PapbVcInterface::startPacketTransfer() { *vcBaseReg = CONFIG_START; }
|
||||
|
||||
void PapbVcInterface::endPacketTransfer() { *vcBaseReg = CONFIG_END; }
|
||||
|
||||
ReturnValue_t PapbVcInterface::pollPapbBusySignal() {
|
||||
ReturnValue_t PapbVcInterface::pollPapbBusySignal() const {
|
||||
gpio::Levels papbBusyState = gpio::Levels::LOW;
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
/** Check if PAPB interface is ready to receive data */
|
||||
result = gpioComIF->readGpio(papbBusyId, papbBusyState);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PapbVcInterface::pollPapbBusySignal: Failed to read papb busy signal"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (papbBusyState == gpio::Levels::LOW) {
|
||||
sif::warning << "PapbVcInterface::pollPapbBusySignal: PAPB busy" << std::endl;
|
||||
return PAPB_BUSY;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PapbVcInterface::isVcInterfaceBufferEmpty() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
gpio::Levels papbEmptyState = gpio::Levels::HIGH;
|
||||
|
||||
result = gpioComIF->readGpio(papbEmptyId, papbEmptyState);
|
||||
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal"
|
||||
<< std::endl;
|
||||
return;
|
||||
@ -80,6 +79,8 @@ void PapbVcInterface::isVcInterfaceBufferEmpty() {
|
||||
return;
|
||||
}
|
||||
|
||||
bool PapbVcInterface::isBusy() const { return pollPapbBusySignal() == PAPB_BUSY; }
|
||||
|
||||
ReturnValue_t PapbVcInterface::sendTestFrame() {
|
||||
/** Size of one complete transfer frame data field amounts to 1105 bytes */
|
||||
uint8_t testPacket[1105];
|
||||
@ -90,9 +91,9 @@ ReturnValue_t PapbVcInterface::sendTestFrame() {
|
||||
}
|
||||
|
||||
ReturnValue_t result = write(testPacket, 1105);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
@ -3,10 +3,10 @@
|
||||
|
||||
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
|
||||
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
|
||||
#include <linux/ipcore/VirtualChannelIF.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "linux/obc/VcInterfaceIF.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
/**
|
||||
* @brief This class handles the transmission of data to a virtual channel of the PTME IP Core
|
||||
@ -14,7 +14,7 @@
|
||||
*
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PapbVcInterface : public VcInterfaceIF, public HasReturnvaluesIF {
|
||||
class PapbVcInterface : public VirtualChannelIF {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
@ -32,6 +32,13 @@ class PapbVcInterface : public VcInterfaceIF, public HasReturnvaluesIF {
|
||||
std::string uioFile, int mapNum);
|
||||
virtual ~PapbVcInterface();
|
||||
|
||||
bool isBusy() const override;
|
||||
/**
|
||||
*
|
||||
* @param data
|
||||
* @param size
|
||||
* @return returnvalue::OK on successfull write, PAPB_BUSY if PAPB is busy.
|
||||
*/
|
||||
ReturnValue_t write(const uint8_t* data, size_t size) override;
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
@ -93,9 +100,9 @@ class PapbVcInterface : public VcInterfaceIF, public HasReturnvaluesIF {
|
||||
* interface is ready to receive more data or not. PAPB is ready when
|
||||
* PAPB_Busy_N == '1'.
|
||||
*
|
||||
* @return RETURN_OK when ready to receive data else PAPB_BUSY.
|
||||
* @return returnvalue::OK when ready to receive data else PAPB_BUSY.
|
||||
*/
|
||||
ReturnValue_t pollPapbBusySignal();
|
||||
ReturnValue_t pollPapbBusySignal() const;
|
||||
|
||||
/**
|
||||
* @brief This function can be used for debugging to check whether there are packets in
|
191
linux/ipcore/PdecConfig.cpp
Normal file
191
linux/ipcore/PdecConfig.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
#include "PdecConfig.h"
|
||||
|
||||
#include "fsfw/filesystem/HasFileSystemIF.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "pdecconfigdefs.h"
|
||||
|
||||
PdecConfig::PdecConfig()
|
||||
: localParameterHandler("conf/pdecconfig.json", SdCardManager::instance()) {}
|
||||
|
||||
PdecConfig::~PdecConfig() {}
|
||||
|
||||
void PdecConfig::setMemoryBaseAddress(uint32_t* memoryBaseAddress_) {
|
||||
memoryBaseAddress = memoryBaseAddress_;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::write() {
|
||||
if (memoryBaseAddress == nullptr) {
|
||||
sif::error << "PdecConfig::write: Memory base address not set" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
ReturnValue_t result = initializePersistentParameters();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = writeFrameHeaderFirstOctet();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = writeFrameHeaderSecondOctet();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
writeMapConfig();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::initializePersistentParameters() {
|
||||
ReturnValue_t result = localParameterHandler.initialize();
|
||||
if (result == HasFileSystemIF::FILE_DOES_NOT_EXIST) {
|
||||
result = createPersistentConfig();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::createPersistentConfig() {
|
||||
ReturnValue_t result = localParameterHandler.addParameter(
|
||||
pdecconfigdefs::paramkeys::POSITIVE_WINDOW, pdecconfigdefs::defaultvalue::positiveWindow);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "PdecConfig::createPersistentConfig: Failed to set positive window" << std::endl;
|
||||
return result;
|
||||
}
|
||||
result = localParameterHandler.addParameter(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW,
|
||||
pdecconfigdefs::defaultvalue::negativeWindow);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "PdecConfig::createPersistentConfig: Failed to set negative window" << std::endl;
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
uint32_t PdecConfig::getImrReg() {
|
||||
return static_cast<uint32_t>(enableNewFarIrq << 2) |
|
||||
static_cast<uint32_t>(enableTcAbortIrq << 1) | static_cast<uint32_t>(enableTcNewIrq);
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::setPositiveWindow(uint8_t pw) {
|
||||
if (memoryBaseAddress == nullptr) {
|
||||
sif::error << "PdecConfig::setPositiveWindow: Memory base address not set" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
ReturnValue_t result =
|
||||
localParameterHandler.updateParameter(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, pw);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
// Rewrite second config word which contains the positive window parameter
|
||||
writeFrameHeaderSecondOctet();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::setNegativeWindow(uint8_t nw) {
|
||||
if (memoryBaseAddress == nullptr) {
|
||||
sif::error << "PdecConfig::setPositiveWindow: Memory base address not set" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
ReturnValue_t result =
|
||||
localParameterHandler.updateParameter(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, nw);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
// Rewrite second config word which contains the negative window parameter
|
||||
writeFrameHeaderSecondOctet();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::getPositiveWindow(uint8_t& positiveWindow) {
|
||||
ReturnValue_t result =
|
||||
localParameterHandler.getValue(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, positiveWindow);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::getNegativeWindow(uint8_t& negativeWindow) {
|
||||
ReturnValue_t result =
|
||||
localParameterHandler.getValue(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, negativeWindow);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::writeFrameHeaderFirstOctet() {
|
||||
uint32_t word = 0;
|
||||
word |= (VERSION_ID << 30);
|
||||
|
||||
// Setting the bypass flag and the control command flag should not have any
|
||||
// implication on the operation of the PDEC IP Core
|
||||
word |= (BYPASS_FLAG << 29);
|
||||
word |= (CONTROL_COMMAND_FLAG << 28);
|
||||
|
||||
word |= (RESERVED_FIELD_A << 26);
|
||||
word |= (SPACECRAFT_ID << 16);
|
||||
word |= (VIRTUAL_CHANNEL << 10);
|
||||
word |= (DUMMY_BITS << 8);
|
||||
uint8_t positiveWindow = 0;
|
||||
ReturnValue_t result =
|
||||
localParameterHandler.getValue(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, positiveWindow);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
word |= static_cast<uint32_t>(positiveWindow);
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET) = word;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecConfig::writeFrameHeaderSecondOctet() {
|
||||
uint8_t negativeWindow = 0;
|
||||
ReturnValue_t result =
|
||||
localParameterHandler.getValue(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, negativeWindow);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint32_t word = 0;
|
||||
word = 0;
|
||||
word |= (static_cast<uint32_t>(negativeWindow) << 24);
|
||||
word |= (HIGH_AU_MAP_ID << 16);
|
||||
word |= (ENABLE_DERANDOMIZER << 8);
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = word;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PdecConfig::writeMapConfig() {
|
||||
// Configure all MAP IDs as invalid
|
||||
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
|
||||
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + idx / 4) =
|
||||
NO_DESTINATION << 24 | NO_DESTINATION << 16 | NO_DESTINATION << 8 | NO_DESTINATION;
|
||||
}
|
||||
|
||||
// All TCs with MAP ID 7 will be routed to the PM module (can then be read from memory)
|
||||
uint8_t routeToPm = calcMapAddrEntry(PM_BUFFER);
|
||||
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + 1) =
|
||||
(NO_DESTINATION << 24) | (NO_DESTINATION << 16) | (NO_DESTINATION << 8) | routeToPm;
|
||||
|
||||
// Write map id clock frequencies
|
||||
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
|
||||
*(memoryBaseAddress + MAP_CLK_FREQ_OFFSET + idx / 4) =
|
||||
MAP_CLK_FREQ << 24 | MAP_CLK_FREQ << 16 | MAP_CLK_FREQ << 8 | MAP_CLK_FREQ;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t PdecConfig::calcMapAddrEntry(uint8_t moduleId) {
|
||||
uint8_t lutEntry = 0;
|
||||
uint8_t parity = getOddParity(moduleId | (1 << VALID_POSITION));
|
||||
lutEntry = (parity << PARITY_POSITION) | (1 << VALID_POSITION) | moduleId;
|
||||
return lutEntry;
|
||||
}
|
||||
|
||||
uint8_t PdecConfig::getOddParity(uint8_t number) {
|
||||
uint8_t parityBit = 0;
|
||||
uint8_t countBits = 0;
|
||||
for (unsigned int idx = 0; idx < sizeof(number) * 8; idx++) {
|
||||
countBits += (number >> idx) & 0x1;
|
||||
}
|
||||
parityBit = ~(countBits & 0x1) & 0x1;
|
||||
return parityBit;
|
||||
}
|
131
linux/ipcore/PdecConfig.h
Normal file
131
linux/ipcore/PdecConfig.h
Normal file
@ -0,0 +1,131 @@
|
||||
#ifndef LINUX_OBC_PDECCONFIG_H_
|
||||
#define LINUX_OBC_PDECCONFIG_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
#include "bsp_q7s/memory/LocalParameterHandler.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "pdec.h"
|
||||
|
||||
/**
|
||||
* @brief This class generates the configuration words for the configuration memory of the PDEC
|
||||
* IP Cores.
|
||||
*
|
||||
* @details Fields are initialized according to specification in PDEC datasheet section 6.11.3.1
|
||||
* PROM usage.
|
||||
*
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PdecConfig {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
PdecConfig();
|
||||
virtual ~PdecConfig();
|
||||
|
||||
/**
|
||||
* @brief Sets the memory base address pointer
|
||||
*/
|
||||
void setMemoryBaseAddress(uint32_t* memoryBaseAddress_);
|
||||
|
||||
/**
|
||||
* @brief Will write the config to the PDEC configuration memory. New config
|
||||
* becomes active after resetting PDEC.
|
||||
*/
|
||||
ReturnValue_t write();
|
||||
|
||||
/**
|
||||
* @brief Returns the value to write to the interrupt mask register. This
|
||||
* value defines which interrupts should be enabled/disabled.
|
||||
*/
|
||||
uint32_t getImrReg();
|
||||
|
||||
ReturnValue_t setPositiveWindow(uint8_t pw);
|
||||
ReturnValue_t setNegativeWindow(uint8_t nw);
|
||||
|
||||
ReturnValue_t getPositiveWindow(uint8_t& positiveWindow);
|
||||
ReturnValue_t getNegativeWindow(uint8_t& negativeWindow);
|
||||
|
||||
private:
|
||||
// TC transfer frame configuration parameters
|
||||
static const uint8_t VERSION_ID = 0;
|
||||
// BD Frames
|
||||
static const uint8_t BYPASS_FLAG = 1;
|
||||
static const uint8_t CONTROL_COMMAND_FLAG = 0;
|
||||
|
||||
static const uint8_t VIRTUAL_CHANNEL = 0;
|
||||
static const uint8_t RESERVED_FIELD_A = 0;
|
||||
static const uint16_t SPACECRAFT_ID = 0x3DC;
|
||||
static const uint16_t DUMMY_BITS = 0;
|
||||
static const uint8_t HIGH_AU_MAP_ID = 0xF;
|
||||
static const uint8_t ENABLE_DERANDOMIZER = 1;
|
||||
|
||||
static const uint8_t CONFIG_WORDS_NUM = 2;
|
||||
|
||||
// 0x200 / 4 = 0x80
|
||||
static const uint32_t FRAME_HEADER_OFFSET = 0x80;
|
||||
|
||||
static const uint32_t MAP_ADDR_LUT_OFFSET = 0xA0;
|
||||
static const uint32_t MAP_CLK_FREQ_OFFSET = 0x90;
|
||||
// MAP clock frequency. Must be a value between 1 and 13 otherwise the TC segment will be
|
||||
// discarded
|
||||
static const uint8_t MAP_CLK_FREQ = 2;
|
||||
|
||||
static const uint8_t MAX_MAP_ADDR = 63;
|
||||
// Writing this to the map address in the look up table will invalidate a MAP ID.
|
||||
static const uint8_t NO_DESTINATION = 0;
|
||||
static const uint8_t VALID_POSITION = 6;
|
||||
static const uint8_t PARITY_POSITION = 7;
|
||||
|
||||
/**
|
||||
* TCs with map addresses (also know as Map IDs) assigned to this channel will be stored in
|
||||
* the PDEC memory.
|
||||
*/
|
||||
static const uint8_t PM_BUFFER = 7;
|
||||
|
||||
uint32_t* memoryBaseAddress = nullptr;
|
||||
|
||||
// Pointer to object providing access to persistent configuration parameters
|
||||
LocalParameterHandler localParameterHandler;
|
||||
|
||||
uint32_t configWords[CONFIG_WORDS_NUM];
|
||||
bool enableTcNewIrq = true;
|
||||
bool enableTcAbortIrq = true;
|
||||
bool enableNewFarIrq = true;
|
||||
|
||||
ReturnValue_t initializePersistentParameters();
|
||||
/**
|
||||
* @brief If the json file containing the persistent config parameters does
|
||||
* not exist it will be created here.
|
||||
*/
|
||||
ReturnValue_t createPersistentConfig();
|
||||
|
||||
ReturnValue_t writeFrameHeaderFirstOctet();
|
||||
ReturnValue_t writeFrameHeaderSecondOctet();
|
||||
void writeMapConfig();
|
||||
|
||||
/**
|
||||
* @brief This function calculates the entry for the configuration of the MAP ID routing.
|
||||
*
|
||||
* @param mapAddr The MAP ID to configure
|
||||
* @param moduleId The destination module where all TCs with the map id mapAddr will be routed
|
||||
* to.
|
||||
*
|
||||
* @details The PDEC has different modules where the TCs can be routed to. A lookup table is
|
||||
* used which links the MAP ID field to the destination module. The entry for this
|
||||
* lookup table is created by this function and must be stored in the configuration
|
||||
* memory region of the PDEC. The entry has a specific format
|
||||
*/
|
||||
uint8_t calcMapAddrEntry(uint8_t moduleId);
|
||||
|
||||
/**
|
||||
* @brief This functions calculates the odd parity of the bits in number.
|
||||
*
|
||||
* @param number The number from which to calculate the odd parity.
|
||||
*/
|
||||
uint8_t getOddParity(uint8_t number);
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_PDECCONFIG_H_ */
|
@ -1,28 +1,36 @@
|
||||
#include "PdecHandler.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <poll.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||
#include "fsfw_hal/linux/uio/UioMapper.h"
|
||||
#include "pdec.h"
|
||||
|
||||
using namespace pdec;
|
||||
|
||||
// If this is ever shared, protect it with a mutex!
|
||||
uint32_t PdecHandler::CURRENT_FAR = 0;
|
||||
|
||||
PdecHandler::PdecHandler(object_id_t objectId, object_id_t tcDestinationId,
|
||||
LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, std::string uioConfigMemory,
|
||||
std::string uioRamMemory, std::string uioRegisters)
|
||||
LinuxLibgpioIF* gpioComIF, gpioId_t pdecReset, UioNames names)
|
||||
: SystemObject(objectId),
|
||||
tcDestinationId(tcDestinationId),
|
||||
gpioComIF(gpioComIF),
|
||||
pdecReset(pdecReset),
|
||||
uioConfigMemory(uioConfigMemory),
|
||||
uioRamMemory(uioRamMemory),
|
||||
uioRegisters(uioRegisters),
|
||||
actionHelper(this, nullptr) {
|
||||
actionHelper(this, nullptr),
|
||||
uioNames(names),
|
||||
paramHelper(this) {
|
||||
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||
QUEUE_SIZE, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
||||
@ -44,145 +52,398 @@ ReturnValue_t PdecHandler::initialize() {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
UioMapper regMapper(uioRegisters);
|
||||
UioMapper regMapper(uioNames.registers);
|
||||
result = regMapper.getMappedAdress(®isterBaseAddress, UioMapper::Permissions::READ_WRITE);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
UioMapper configMemMapper(uioConfigMemory);
|
||||
UioMapper configMemMapper(uioNames.configMemory);
|
||||
result = configMemMapper.getMappedAdress(&memoryBaseAddress, UioMapper::Permissions::READ_WRITE);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
} else {
|
||||
pdecConfig.setMemoryBaseAddress(memoryBaseAddress);
|
||||
}
|
||||
UioMapper ramMapper(uioRamMemory);
|
||||
UioMapper ramMapper(uioNames.ramMemory);
|
||||
result = ramMapper.getMappedAdress(&ramBaseAddress, UioMapper::Permissions::READ_WRITE);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
writePdecConfig();
|
||||
|
||||
result = releasePdec();
|
||||
if (result != RETURN_OK) {
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
if (OP_MODE == Modes::IRQ and uioNames.irq == nullptr) {
|
||||
sif::error << "Can not use IRQ mode if IRQ UIO name is invalid" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
result = actionHelper.initialize(commandQueue);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
result = paramHelper.initialize();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
MessageQueueId_t PdecHandler::getCommandQueue() const { return commandQueue->getId(); }
|
||||
|
||||
void PdecHandler::writePdecConfig() {
|
||||
PdecConfig pdecConfig;
|
||||
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET) = pdecConfig.getConfigWord(0);
|
||||
*(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = pdecConfig.getConfigWord(1);
|
||||
|
||||
// Configure all MAP IDs as invalid
|
||||
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
|
||||
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + idx + 1 / 4) =
|
||||
NO_DESTINATION << 24 | NO_DESTINATION << 16 | NO_DESTINATION << 8 | NO_DESTINATION;
|
||||
ReturnValue_t PdecHandler::firstLoop() {
|
||||
ReturnValue_t result = pdecConfig.write();
|
||||
if (result != returnvalue::OK) {
|
||||
if (result == LocalParameterHandler::SD_NOT_READY) {
|
||||
return result;
|
||||
} else {
|
||||
sif::error << "PdecHandler::firstLoop: Failed to write PDEC config" << std::endl;
|
||||
}
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
// All TCs with MAP ID 7 will be routed to the PM module (can then be read from memory)
|
||||
uint8_t routeToPm = calcMapAddrEntry(PM_BUFFER);
|
||||
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + 1) =
|
||||
(NO_DESTINATION << 24) | (NO_DESTINATION << 16) | (NO_DESTINATION << 8) | routeToPm;
|
||||
|
||||
// Write map id clock frequencies
|
||||
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
|
||||
*(memoryBaseAddress + MAP_CLK_FREQ_OFFSET + idx / 4) =
|
||||
MAP_CLK_FREQ << 24 | MAP_CLK_FREQ << 16 | MAP_CLK_FREQ << 8 | MAP_CLK_FREQ;
|
||||
result = releasePdec();
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::resetFarStatFlag() {
|
||||
uint32_t pdecFar = *(registerBaseAddress + PDEC_FAR_OFFSET);
|
||||
if (pdecFar != FAR_RESET) {
|
||||
sif::warning << "PdecHandler::resetFarStatFlag: FAR register did not match expected value."
|
||||
<< " Read value: 0x" << std::hex << static_cast<unsigned int>(pdecFar)
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
// This configuration must be done while the PDEC is not held in reset.
|
||||
if (OP_MODE == Modes::IRQ) {
|
||||
// Configure interrupt mask register to enable interrupts
|
||||
*(registerBaseAddress + PDEC_IMR_OFFSET) = pdecConfig.getImrReg();
|
||||
}
|
||||
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
||||
sif::debug << "PdecHandler::resetFarStatFlag: read FAR with value: 0x" << std::hex << pdecFar
|
||||
<< std::endl;
|
||||
#endif /* OBSW_DEBUG_PDEC_HANDLER == 1 */
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::releasePdec() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
result = gpioComIF->pullHigh(pdecReset);
|
||||
if (result != RETURN_OK) {
|
||||
sif::error << "PdecHandler::releasePdec: Failed to release PDEC reset signal" << std::endl;
|
||||
result = resetFarStatFlag();
|
||||
if (result != returnvalue::OK) {
|
||||
// Requires reconfiguration and reinitialization of PDEC
|
||||
triggerEvent(INVALID_FAR);
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::performOperation(uint8_t operationCode) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
if (OP_MODE == Modes::POLLED) {
|
||||
return polledOperation();
|
||||
} else if (OP_MODE == Modes::IRQ) {
|
||||
return irqOperation();
|
||||
}
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::polledOperation() {
|
||||
readCommandQueue();
|
||||
|
||||
switch (state) {
|
||||
case State::INIT:
|
||||
resetFarStatFlag();
|
||||
if (result != RETURN_OK) {
|
||||
// Requires reconfiguration and reinitialization of PDEC
|
||||
triggerEvent(INVALID_FAR);
|
||||
state = State::WAIT_FOR_RECOVERY;
|
||||
return result;
|
||||
}
|
||||
state = State::RUNNING;
|
||||
case State::INIT: {
|
||||
handleInitState();
|
||||
break;
|
||||
case State::RUNNING:
|
||||
}
|
||||
case State::RUNNING: {
|
||||
if (newTcReceived()) {
|
||||
handleNewTc();
|
||||
}
|
||||
checkLocks();
|
||||
break;
|
||||
}
|
||||
case State::PDEC_RESET: {
|
||||
ReturnValue_t result = pdecToReset();
|
||||
if (result != returnvalue::OK) {
|
||||
triggerEvent(PDEC_RESET_FAILED);
|
||||
}
|
||||
state = State::INIT;
|
||||
break;
|
||||
}
|
||||
case State::WAIT_FOR_RECOVERY:
|
||||
break;
|
||||
default:
|
||||
sif::debug << "PdecHandler::performOperation: Invalid state" << std::endl;
|
||||
sif::error << "PdecHandler::performOperation: Invalid state" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
// See https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt.html for more information.
|
||||
ReturnValue_t PdecHandler::irqOperation() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
int fd = -1;
|
||||
// Used to unmask IRQ
|
||||
uint32_t info = 1;
|
||||
|
||||
interruptWindowCd.resetTimer();
|
||||
|
||||
// Clear interrupts with dummy read before unmasking the interrupt. Use a volatile to prevent
|
||||
// read being optimized away.
|
||||
volatile uint32_t dummy = *(registerBaseAddress + PDEC_PIR_OFFSET);
|
||||
|
||||
while (true) {
|
||||
// Default value to unmask IRQ on the write call.
|
||||
info = 1;
|
||||
readCommandQueue();
|
||||
switch (state) {
|
||||
case State::INIT: {
|
||||
result = handleInitState();
|
||||
if (result == returnvalue::OK) {
|
||||
openIrqFile(&fd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case State::PDEC_RESET: {
|
||||
result = pdecToReset();
|
||||
if (result != returnvalue::OK) {
|
||||
triggerEvent(PDEC_RESET_FAILED);
|
||||
}
|
||||
state = State::INIT;
|
||||
break;
|
||||
}
|
||||
case State::RUNNING: {
|
||||
checkLocks();
|
||||
checkAndHandleIrqs(fd, info);
|
||||
break;
|
||||
}
|
||||
case State::WAIT_FOR_RECOVERY:
|
||||
TaskFactory::delayTask(400);
|
||||
break;
|
||||
default:
|
||||
// Should never happen.
|
||||
sif::error << "PdecHandler::performOperation: Invalid state" << std::endl;
|
||||
TaskFactory::delayTask(400);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// To avoid compiler warning
|
||||
static_cast<void>(dummy);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::handleInitState() {
|
||||
ReturnValue_t result = firstLoop();
|
||||
if (result != returnvalue::OK) {
|
||||
if (result == LocalParameterHandler::SD_NOT_READY) {
|
||||
TaskFactory::delayTask(400);
|
||||
if (initTries == MAX_INIT_TRIES) {
|
||||
sif::error << "PdecHandler::handleInitState: SD card never "
|
||||
"becomes ready"
|
||||
<< std::endl;
|
||||
state = State::WAIT_FOR_RECOVERY;
|
||||
} else {
|
||||
state = State::INIT;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
state = State::WAIT_FOR_RECOVERY;
|
||||
return result;
|
||||
}
|
||||
state = State::RUNNING;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PdecHandler::openIrqFile(int* fd) {
|
||||
*fd = open(uioNames.irq, O_RDWR);
|
||||
if (*fd < 0) {
|
||||
sif::error << "PdecHandler::irqOperation: Opening UIO IRQ file" << uioNames.irq << " failed"
|
||||
<< std::endl;
|
||||
triggerEvent(OPEN_IRQ_FILE_FAILED);
|
||||
state = State::WAIT_FOR_RECOVERY;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) {
|
||||
ssize_t nb = write(fd, &info, sizeof(info));
|
||||
if (nb != static_cast<ssize_t>(sizeof(info))) {
|
||||
sif::error << "PdecHandler::irqOperation: Unmasking IRQ failed" << std::endl;
|
||||
triggerEvent(WRITE_SYSCALL_ERROR_PDEC, errno);
|
||||
close(fd);
|
||||
state = State::INIT;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
struct pollfd fds = {.fd = fd, .events = POLLIN, .revents = 0};
|
||||
int ret = poll(&fds, 1, IRQ_TIMEOUT_MS);
|
||||
if (ret == 0) {
|
||||
// No TCs for timeout period
|
||||
genericCheckCd.resetTimer();
|
||||
resetIrqLimiters();
|
||||
} else if (ret >= 1) {
|
||||
// Interrupt handling.
|
||||
nb = read(fd, &info, sizeof(info));
|
||||
interruptCounter++;
|
||||
if (nb == static_cast<ssize_t>(sizeof(info))) {
|
||||
uint32_t pisr = *(registerBaseAddress + PDEC_PISR_OFFSET);
|
||||
if ((pisr & TC_NEW_MASK) == TC_NEW_MASK) {
|
||||
// handle TC
|
||||
handleNewTc();
|
||||
}
|
||||
if ((pisr & TC_ABORT_MASK) == TC_ABORT_MASK) {
|
||||
tcAbortCounter += 1;
|
||||
}
|
||||
if ((pisr & NEW_FAR_MASK) == NEW_FAR_MASK) {
|
||||
// Read FAR here
|
||||
CURRENT_FAR = readFar();
|
||||
checkFrameAna(CURRENT_FAR);
|
||||
}
|
||||
// Clear interrupts with dummy read. Volatile is important here to prevent
|
||||
// compiler opitmizations in release builds!
|
||||
volatile uint32_t dummy = *(registerBaseAddress + PDEC_PIR_OFFSET);
|
||||
static_cast<void>(dummy);
|
||||
|
||||
if (genericCheckCd.hasTimedOut()) {
|
||||
genericCheckCd.resetTimer();
|
||||
if (interruptWindowCd.hasTimedOut()) {
|
||||
if (interruptCounter >= MAX_ALLOWED_IRQS_PER_WINDOW) {
|
||||
sif::error << "PdecHandler::irqOperation: Possible IRQ storm" << std::endl;
|
||||
triggerEvent(TOO_MANY_IRQS, MAX_ALLOWED_IRQS_PER_WINDOW);
|
||||
resetIrqLimiters();
|
||||
TaskFactory::delayTask(400);
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
resetIrqLimiters();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sif::error << "PdecHandler::irqOperation: Poll error with errno " << errno << ": "
|
||||
<< strerror(errno) << std::endl;
|
||||
triggerEvent(POLL_SYSCALL_ERROR_PDEC, errno);
|
||||
close(fd);
|
||||
state = State::INIT;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PdecHandler::readCommandQueue(void) {
|
||||
CommandMessage commandMessage;
|
||||
ReturnValue_t result = RETURN_FAILED;
|
||||
CommandMessage message;
|
||||
ReturnValue_t result = returnvalue::FAILED;
|
||||
|
||||
result = commandQueue->receiveMessage(&commandMessage);
|
||||
if (result == RETURN_OK) {
|
||||
result = actionHelper.handleActionMessage(&commandMessage);
|
||||
if (result == RETURN_OK) {
|
||||
result = commandQueue->receiveMessage(&message);
|
||||
if (result == returnvalue::OK) {
|
||||
result = actionHelper.handleActionMessage(&message);
|
||||
if (result == returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
result = paramHelper.handleParameterMessage(&message);
|
||||
if (result == returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
CommandMessage reply;
|
||||
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, commandMessage.getCommand());
|
||||
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, message.getCommand());
|
||||
commandQueue->reply(&reply);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MessageQueueId_t PdecHandler::getCommandQueue() const { return commandQueue->getId(); }
|
||||
|
||||
ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) {
|
||||
switch (actionId) {
|
||||
case PRINT_CLCW:
|
||||
printClcw();
|
||||
return EXECUTION_FINISHED;
|
||||
case PRINT_PDEC_MON:
|
||||
printPdecMon();
|
||||
return EXECUTION_FINISHED;
|
||||
default:
|
||||
return COMMAND_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
||||
ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||
if ((domainId == 0) and (uniqueIdentifier == ParameterId::POSITIVE_WINDOW)) {
|
||||
uint8_t newVal = 0;
|
||||
ReturnValue_t result = newValues->getElement(&newVal);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint8_t positiveWindow = 0;
|
||||
result = pdecConfig.getPositiveWindow(positiveWindow);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PdecHandler::getParameter: Failed to get positive window from pdec config"
|
||||
<< std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
parameterWrapper->set(positiveWindow);
|
||||
result = pdecConfig.setPositiveWindow(newVal);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PdecHandler::getParameter: Failed to set positive window" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
// PDEC needs reset to apply this parameter change
|
||||
state = State::PDEC_RESET;
|
||||
return returnvalue::OK;
|
||||
} else if ((domainId == 0) and (uniqueIdentifier == ParameterId::NEGATIVE_WINDOW)) {
|
||||
uint8_t newVal = 0;
|
||||
ReturnValue_t result = newValues->getElement(&newVal);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
uint8_t negativeWindow = 0;
|
||||
result = pdecConfig.getNegativeWindow(negativeWindow);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PdecHandler::getParameter: Failed to get negative window from pdec config"
|
||||
<< std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
parameterWrapper->set(negativeWindow);
|
||||
result = pdecConfig.setNegativeWindow(newVal);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PdecHandler::getParameter: Failed to set negative window" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
// PDEC needs reset to apply this parameter change
|
||||
state = State::PDEC_RESET;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::resetFarStatFlag() {
|
||||
uint32_t pdecFar = readFar();
|
||||
if ((pdecFar & FAR_STAT_MASK) != 0) {
|
||||
sif::warning << "PdecHandler::resetFarStatFlag: FAR register stat bit is not 0."
|
||||
<< " Read value for FAR: 0x" << std::hex << static_cast<unsigned int>(pdecFar)
|
||||
<< std::endl;
|
||||
CURRENT_FAR = pdecFar;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
||||
sif::debug << "PdecHandler::resetFarStatFlag: read FAR with value: 0x" << std::hex << pdecFar
|
||||
<< std::endl;
|
||||
#endif /* OBSW_DEBUG_PDEC_HANDLER == 1 */
|
||||
CURRENT_FAR = pdecFar;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::releasePdec() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = gpioComIF->pullHigh(pdecReset);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "PdecHandler::releasePdec: Failed to release PDEC reset signal" << std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::pdecToReset() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = gpioComIF->pullLow(pdecReset);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "PdecHandler::pdecToReset: Failed to pull PDEC reset line"
|
||||
" to low"
|
||||
<< std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PdecHandler::newTcReceived() {
|
||||
uint32_t pdecFar = *(registerBaseAddress + PDEC_FAR_OFFSET);
|
||||
uint32_t pdecFar = readFar();
|
||||
|
||||
if (pdecFar >> STAT_POSITION != NEW_FAR_RECEIVED) {
|
||||
CURRENT_FAR = pdecFar;
|
||||
return false;
|
||||
}
|
||||
if (!checkFrameAna(pdecFar)) {
|
||||
CURRENT_FAR = pdecFar;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -190,15 +451,20 @@ bool PdecHandler::newTcReceived() {
|
||||
|
||||
void PdecHandler::checkLocks() {
|
||||
uint32_t clcw = getClcw();
|
||||
if (!(clcw & NO_RF_MASK) && (lastClcw & NO_RF_MASK)) {
|
||||
// Rf available changed from 0 to 1
|
||||
if (not(clcw & NO_RF_MASK) && not carrierLock) {
|
||||
triggerEvent(CARRIER_LOCK);
|
||||
carrierLock = true;
|
||||
} else if ((clcw & NO_RF_MASK) && carrierLock) {
|
||||
carrierLock = false;
|
||||
triggerEvent(LOST_CARRIER_LOCK_PDEC);
|
||||
}
|
||||
if (!(clcw & NO_BITLOCK_MASK) && (lastClcw & NO_BITLOCK_MASK)) {
|
||||
// Bit lock changed from 0 to 1
|
||||
if (not(clcw & NO_BITLOCK_MASK) && not bitLock) {
|
||||
triggerEvent(BIT_LOCK_PDEC);
|
||||
bitLock = true;
|
||||
} else if ((clcw & NO_BITLOCK_MASK) && bitLock) {
|
||||
bitLock = false;
|
||||
triggerEvent(LOST_BIT_LOCK_PDEC);
|
||||
}
|
||||
lastClcw = clcw;
|
||||
}
|
||||
|
||||
bool PdecHandler::checkFrameAna(uint32_t pdecFar) {
|
||||
@ -206,12 +472,12 @@ bool PdecHandler::checkFrameAna(uint32_t pdecFar) {
|
||||
FrameAna_t frameAna = static_cast<FrameAna_t>((pdecFar & FRAME_ANA_MASK) >> FRAME_ANA_POSITION);
|
||||
switch (frameAna) {
|
||||
case (FrameAna_t::ABANDONED_CLTU): {
|
||||
triggerEvent(INVALID_TC_FRAME, ABANDONED_CLTU);
|
||||
triggerEvent(INVALID_TC_FRAME, ABANDONED_CLTU_RETVAL);
|
||||
sif::warning << "PdecHandler::checkFrameAna: Abondoned CLTU" << std::endl;
|
||||
break;
|
||||
}
|
||||
case (FrameAna_t::FRAME_DIRTY): {
|
||||
triggerEvent(INVALID_TC_FRAME, FRAME_DIRTY);
|
||||
triggerEvent(INVALID_TC_FRAME, FRAME_DIRTY_RETVAL);
|
||||
sif::warning << "PdecHandler::checkFrameAna: Frame dirty" << std::endl;
|
||||
break;
|
||||
}
|
||||
@ -226,13 +492,13 @@ bool PdecHandler::checkFrameAna(uint32_t pdecFar) {
|
||||
break;
|
||||
}
|
||||
case (FrameAna_t::AD_DISCARDED_LOCKOUT): {
|
||||
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_LOCKOUT);
|
||||
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_LOCKOUT_RETVAL);
|
||||
sif::warning << "PdecHandler::checkFrameAna: AD frame discarded because of lockout"
|
||||
<< std::endl;
|
||||
break;
|
||||
}
|
||||
case (FrameAna_t::AD_DISCARDED_WAIT): {
|
||||
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_LOCKOUT);
|
||||
triggerEvent(INVALID_TC_FRAME, AD_DISCARDED_LOCKOUT_RETVAL);
|
||||
sif::warning << "PdecHandler::checkFrameAna: AD frame discarded because of wait" << std::endl;
|
||||
break;
|
||||
}
|
||||
@ -261,40 +527,40 @@ void PdecHandler::handleIReason(uint32_t pdecFar, ReturnValue_t parameter1) {
|
||||
IReason_t ireason = static_cast<IReason_t>((pdecFar & IREASON_MASK) >> IREASON_POSITION);
|
||||
switch (ireason) {
|
||||
case (IReason_t::NO_REPORT): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, NO_REPORT);
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, NO_REPORT_RETVAL);
|
||||
sif::info << "PdecHandler::handleIReason: No illegal report" << std::endl;
|
||||
break;
|
||||
}
|
||||
case (IReason_t::ERROR_VERSION_NUMBER): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, ERROR_VERSION_NUMBER);
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, ERROR_VERSION_NUMBER_RETVAL);
|
||||
sif::info << "PdecHandler::handleIReason: Error in version number and reserved A and B "
|
||||
<< "fields" << std::endl;
|
||||
break;
|
||||
}
|
||||
case (IReason_t::ILLEGAL_COMBINATION): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, ILLEGAL_COMBINATION);
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, ILLEGAL_COMBINATION_RETVAL);
|
||||
sif::info << "PdecHandler::handleIReason: Illegal combination (AC) of bypass and control "
|
||||
<< "command flags" << std::endl;
|
||||
break;
|
||||
}
|
||||
case (IReason_t::INVALID_SC_ID): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_SC_ID);
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_SC_ID_RETVAL);
|
||||
sif::info << "PdecHandler::handleIReason: Invalid spacecraft identifier " << std::endl;
|
||||
break;
|
||||
}
|
||||
case (IReason_t::INVALID_VC_ID_MSB): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_MSB);
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_MSB_RETVAL);
|
||||
sif::info << "PdecHandler::handleIReason: VC identifier bit 0 to 4 did not match "
|
||||
<< std::endl;
|
||||
break;
|
||||
}
|
||||
case (IReason_t::INVALID_VC_ID_LSB): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_LSB);
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, INVALID_VC_ID_LSB_RETVAL);
|
||||
sif::info << "PdecHandler::handleIReason: VC identifier bit 5 did not match " << std::endl;
|
||||
break;
|
||||
}
|
||||
case (IReason_t::NS_NOT_ZERO): {
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, NS_NOT_ZERO);
|
||||
triggerEvent(INVALID_TC_FRAME, parameter1, NS_NOT_ZERO_RETVAL);
|
||||
sif::info << "PdecHandler::handleIReason: N(S) of BC or BD frame not set to all zeros"
|
||||
<< std::endl;
|
||||
break;
|
||||
@ -312,11 +578,11 @@ void PdecHandler::handleIReason(uint32_t pdecFar, ReturnValue_t parameter1) {
|
||||
}
|
||||
|
||||
void PdecHandler::handleNewTc() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
uint32_t tcLength = 0;
|
||||
result = readTc(tcLength);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
#if OBSW_DEBUG_PDEC_HANDLER == 1
|
||||
@ -325,10 +591,9 @@ void PdecHandler::handleNewTc() {
|
||||
printTC(tcLength);
|
||||
#endif /* OBSW_DEBUG_PDEC_HANDLER */
|
||||
|
||||
#if OBSW_TC_FROM_PDEC == 1
|
||||
store_address_t storeId;
|
||||
result = tcStore->addData(&storeId, tcSegment + 1, tcLength - 1);
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PdecHandler::handleNewTc: Failed to add received space packet to store"
|
||||
<< std::endl;
|
||||
return;
|
||||
@ -337,13 +602,12 @@ void PdecHandler::handleNewTc() {
|
||||
TmTcMessage message(storeId);
|
||||
|
||||
result = MessageQueueSenderIF::sendMessage(tcDestination->getRequestQueue(), &message);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PdecHandler::handleNewTc: Failed to send message to TC destination"
|
||||
<< std::endl;
|
||||
tcStore->deleteData(storeId);
|
||||
return;
|
||||
}
|
||||
#endif /* OBSW_TC_FROM_PDEC == 1 */
|
||||
|
||||
return;
|
||||
}
|
||||
@ -364,7 +628,7 @@ ReturnValue_t PdecHandler::readTc(uint32_t& tcLength) {
|
||||
if (tcLength > MAX_TC_SEGMENT_SIZE) {
|
||||
sif::warning << "PdecHandler::handleNewTc: Read invalid TC length from PDEC register"
|
||||
<< std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
uint32_t idx = 0;
|
||||
@ -395,7 +659,7 @@ ReturnValue_t PdecHandler::readTc(uint32_t& tcLength) {
|
||||
// Backend buffer is handled back to PDEC3
|
||||
*(registerBaseAddress + PDEC_BFREE_OFFSET) = 0;
|
||||
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PdecHandler::printTC(uint32_t tcLength) {
|
||||
@ -408,23 +672,6 @@ void PdecHandler::printTC(uint32_t tcLength) {
|
||||
sif::info << tcSegmentStream.str() << std::endl;
|
||||
}
|
||||
|
||||
uint8_t PdecHandler::calcMapAddrEntry(uint8_t moduleId) {
|
||||
uint8_t lutEntry = 0;
|
||||
uint8_t parity = getOddParity(moduleId | (1 << VALID_POSITION));
|
||||
lutEntry = (parity << PARITY_POSITION) | (1 << VALID_POSITION) | moduleId;
|
||||
return lutEntry;
|
||||
}
|
||||
|
||||
uint8_t PdecHandler::getOddParity(uint8_t number) {
|
||||
uint8_t parityBit = 0;
|
||||
uint8_t countBits = 0;
|
||||
for (unsigned int idx = 0; idx < sizeof(number) * 8; idx++) {
|
||||
countBits += (number >> idx) & 0x1;
|
||||
}
|
||||
parityBit = ~(countBits & 0x1) & 0x1;
|
||||
return parityBit;
|
||||
}
|
||||
|
||||
uint32_t PdecHandler::getClcw() { return *(registerBaseAddress + PDEC_CLCW_OFFSET); }
|
||||
|
||||
uint32_t PdecHandler::getPdecMon() { return *(registerBaseAddress + PDEC_MON_OFFSET); }
|
||||
@ -494,6 +741,13 @@ void PdecHandler::printPdecMon() {
|
||||
sif::info << std::setw(30) << std::left << "Start sequence lock: " << lock << std::endl;
|
||||
}
|
||||
|
||||
uint32_t PdecHandler::readFar() { return *(registerBaseAddress + PDEC_FAR_OFFSET); }
|
||||
|
||||
void PdecHandler::resetIrqLimiters() {
|
||||
interruptWindowCd.resetTimer();
|
||||
interruptCounter = 0;
|
||||
}
|
||||
|
||||
std::string PdecHandler::getMonStatusString(uint32_t status) {
|
||||
switch (status) {
|
||||
case TC_CHANNEL_INACTIVE:
|
||||
@ -508,17 +762,3 @@ std::string PdecHandler::getMonStatusString(uint32_t status) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) {
|
||||
switch (actionId) {
|
||||
case PRINT_CLCW:
|
||||
printClcw();
|
||||
return EXECUTION_FINISHED;
|
||||
case PRINT_PDEC_MON:
|
||||
printPdecMon();
|
||||
return EXECUTION_FINISHED;
|
||||
default:
|
||||
return COMMAND_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
@ -1,18 +1,30 @@
|
||||
#ifndef LINUX_OBC_PDECHANDLER_H_
|
||||
#define LINUX_OBC_PDECHANDLER_H_
|
||||
|
||||
#include <fsfw/timemanager/Countdown.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "PdecConfig.h"
|
||||
#include "eive/definitions.h"
|
||||
#include "fsfw/action/ActionHelper.h"
|
||||
#include "fsfw/action/HasActionsIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw/parameters/ParameterHelper.h"
|
||||
#include "fsfw/parameters/ReceivesParameterMessagesIF.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
|
||||
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
|
||||
|
||||
struct UioNames {
|
||||
const char* configMemory;
|
||||
const char* ramMemory;
|
||||
const char* registers;
|
||||
const char* irq;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This class controls the PDEC IP Core implemented in the programmable logic of the
|
||||
* Zynq-7020. All registers and memories of the PDEC IP Core are accessed via UIO
|
||||
@ -33,9 +45,13 @@
|
||||
*/
|
||||
class PdecHandler : public SystemObject,
|
||||
public ExecutableObjectIF,
|
||||
public HasReturnvaluesIF,
|
||||
public HasActionsIF {
|
||||
public HasActionsIF,
|
||||
public ReceivesParameterMessagesIF {
|
||||
public:
|
||||
static constexpr dur_millis_t IRQ_TIMEOUT_MS = 500;
|
||||
|
||||
enum class Modes { POLLED, IRQ };
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param objectId Object ID of PDEC handler system object
|
||||
@ -46,8 +62,7 @@ class PdecHandler : public SystemObject,
|
||||
* @param uioregsiters String of uio device file same mapped to the PDEC register space
|
||||
*/
|
||||
PdecHandler(object_id_t objectId, object_id_t tcDestinationId, LinuxLibgpioIF* gpioComIF,
|
||||
gpioId_t pdecReset, std::string uioConfigMemory, std::string uioRamMemory,
|
||||
std::string uioRegisters);
|
||||
gpioId_t pdecReset, UioNames names);
|
||||
|
||||
virtual ~PdecHandler();
|
||||
|
||||
@ -60,6 +75,10 @@ class PdecHandler : public SystemObject,
|
||||
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) override;
|
||||
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||
uint16_t startAtIndex) override;
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PDEC_HANDLER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] Frame acceptance report signals an invalid frame
|
||||
@ -73,86 +92,60 @@ class PdecHandler : public SystemObject,
|
||||
static const Event CARRIER_LOCK = MAKE_EVENT(3, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Bit lock detected (data valid)
|
||||
static const Event BIT_LOCK_PDEC = MAKE_EVENT(4, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Lost carrier lock
|
||||
static const Event LOST_CARRIER_LOCK_PDEC = MAKE_EVENT(5, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Lost bit lock
|
||||
static const Event LOST_BIT_LOCK_PDEC = MAKE_EVENT(6, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Too many IRQs over the time window of one second. P1: Allowed TCs
|
||||
static constexpr Event TOO_MANY_IRQS = MAKE_EVENT(7, severity::MEDIUM);
|
||||
static constexpr Event POLL_SYSCALL_ERROR_PDEC =
|
||||
event::makeEvent(SUBSYSTEM_ID, 8, severity::MEDIUM);
|
||||
static constexpr Event WRITE_SYSCALL_ERROR_PDEC =
|
||||
event::makeEvent(SUBSYSTEM_ID, 9, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Failed to pull PDEC reset to low
|
||||
static constexpr Event PDEC_RESET_FAILED = event::makeEvent(SUBSYSTEM_ID, 10, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Failed to open the IRQ uio file
|
||||
static constexpr Event OPEN_IRQ_FILE_FAILED = event::makeEvent(SUBSYSTEM_ID, 11, severity::HIGH);
|
||||
|
||||
private:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::PDEC_HANDLER;
|
||||
|
||||
static const ReturnValue_t ABANDONED_CLTU = MAKE_RETURN_CODE(0xA0);
|
||||
static const ReturnValue_t FRAME_DIRTY = MAKE_RETURN_CODE(0xA1);
|
||||
static constexpr Modes OP_MODE = Modes::IRQ;
|
||||
|
||||
static const ReturnValue_t ABANDONED_CLTU_RETVAL = MAKE_RETURN_CODE(0xA0);
|
||||
static const ReturnValue_t FRAME_DIRTY_RETVAL = MAKE_RETURN_CODE(0xA1);
|
||||
static const ReturnValue_t FRAME_ILLEGAL_ONE_REASON = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t FRAME_ILLEGAL_MULTIPLE_REASONS = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t AD_DISCARDED_LOCKOUT = MAKE_RETURN_CODE(0xA3);
|
||||
static const ReturnValue_t AD_DISCARDED_WAIT = MAKE_RETURN_CODE(0xA4);
|
||||
static const ReturnValue_t AD_DISCARDED_LOCKOUT_RETVAL = MAKE_RETURN_CODE(0xA3);
|
||||
static const ReturnValue_t AD_DISCARDED_WAIT_RETVAL = MAKE_RETURN_CODE(0xA4);
|
||||
static const ReturnValue_t AD_DISCARDED_NS_VS = MAKE_RETURN_CODE(0xA5);
|
||||
|
||||
//! [EXPORT] : [COMMENT] Received action message with unknown action id
|
||||
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xB0);
|
||||
|
||||
static const ReturnValue_t NO_REPORT = MAKE_RETURN_CODE(0xA6);
|
||||
static const ReturnValue_t NO_REPORT_RETVAL = MAKE_RETURN_CODE(0xA6);
|
||||
//! Error in version number and reserved A and B fields
|
||||
static const ReturnValue_t ERROR_VERSION_NUMBER = MAKE_RETURN_CODE(0xA7);
|
||||
static const ReturnValue_t ERROR_VERSION_NUMBER_RETVAL = MAKE_RETURN_CODE(0xA7);
|
||||
//! Illegal combination of bypass and control command flag
|
||||
static const ReturnValue_t ILLEGAL_COMBINATION = MAKE_RETURN_CODE(0xA8);
|
||||
static const ReturnValue_t ILLEGAL_COMBINATION_RETVAL = MAKE_RETURN_CODE(0xA8);
|
||||
//! Spacecraft identifier did not match
|
||||
static const ReturnValue_t INVALID_SC_ID = MAKE_RETURN_CODE(0xA9);
|
||||
static const ReturnValue_t INVALID_SC_ID_RETVAL = MAKE_RETURN_CODE(0xA9);
|
||||
//! VC identifier bits 0 to 4 did not match
|
||||
static const ReturnValue_t INVALID_VC_ID_MSB = MAKE_RETURN_CODE(0xAA);
|
||||
static const ReturnValue_t INVALID_VC_ID_MSB_RETVAL = MAKE_RETURN_CODE(0xAA);
|
||||
//! VC identifier bit 5 did not match
|
||||
static const ReturnValue_t INVALID_VC_ID_LSB = MAKE_RETURN_CODE(0xAB);
|
||||
static const ReturnValue_t INVALID_VC_ID_LSB_RETVAL = MAKE_RETURN_CODE(0xAB);
|
||||
//! N(S) of BC or BD frame not set to all zeros
|
||||
static const ReturnValue_t NS_NOT_ZERO = MAKE_RETURN_CODE(0xAC);
|
||||
static const ReturnValue_t NS_NOT_ZERO_RETVAL = MAKE_RETURN_CODE(0xAC);
|
||||
//! Invalid BC control command
|
||||
static const ReturnValue_t INVALID_BC_CC = MAKE_RETURN_CODE(0xAE);
|
||||
|
||||
static const uint32_t QUEUE_SIZE = common::CCSDS_HANDLER_QUEUE_SIZE;
|
||||
static const uint32_t QUEUE_SIZE = config::CCSDS_HANDLER_QUEUE_SIZE;
|
||||
|
||||
// Action IDs
|
||||
static const ActionId_t PRINT_CLCW = 0;
|
||||
// Print PDEC monitor register
|
||||
static const ActionId_t PRINT_PDEC_MON = 1;
|
||||
|
||||
static const uint8_t STAT_POSITION = 31;
|
||||
static const uint8_t FRAME_ANA_POSITION = 28;
|
||||
static const uint8_t IREASON_POSITION = 25;
|
||||
|
||||
static const uint8_t NEW_FAR_RECEIVED = 0;
|
||||
|
||||
static const uint32_t FRAME_ANA_MASK = 0x70000000;
|
||||
static const uint32_t IREASON_MASK = 0x0E000000;
|
||||
|
||||
static const uint32_t TC_CHANNEL_INACTIVE = 0x0;
|
||||
static const uint32_t TC_CHANNEL_ACTIVE = 0x1;
|
||||
static const uint32_t TC_CHANNEL_TIMEDOUT = 0x2;
|
||||
|
||||
static const uint32_t TC0_STATUS_MASK = 0x3;
|
||||
static const uint32_t TC1_STATUS_MASK = 0xC;
|
||||
static const uint32_t TC2_STATUS_MASK = 0x300;
|
||||
static const uint32_t TC3_STATUS_MASK = 0xC00;
|
||||
static const uint32_t TC4_STATUS_MASK = 0x30000;
|
||||
static const uint32_t TC5_STATUS_MASK = 0xc00000;
|
||||
// Lock register set to 1 when start sequence has been found (CLTU is beeing processed)
|
||||
static const uint32_t LOCK_MASK = 0xc00000;
|
||||
|
||||
static const uint32_t TC0_STATUS_POS = 0;
|
||||
static const uint32_t TC1_STATUS_POS = 2;
|
||||
static const uint32_t TC2_STATUS_POS = 4;
|
||||
static const uint32_t TC3_STATUS_POS = 6;
|
||||
static const uint32_t TC4_STATUS_POS = 8;
|
||||
static const uint32_t TC5_STATUS_POS = 10;
|
||||
// Lock register set to 1 when start sequence has been found (CLTU is beeing processed)
|
||||
static const uint32_t LOCK_POS = 12;
|
||||
|
||||
/**
|
||||
* UIO is 4 byte aligned. Thus offset is calculated with "true offset" / 4
|
||||
* Example: PDEC_FAR = 0x2840 => Offset in virtual address space is 0xA10
|
||||
*/
|
||||
static const uint32_t PDEC_FAR_OFFSET = 0xA10;
|
||||
static const uint32_t PDEC_CLCW_OFFSET = 0xA12;
|
||||
static const uint32_t PDEC_BFREE_OFFSET = 0xA24;
|
||||
static const uint32_t PDEC_BPTR_OFFSET = 0xA25;
|
||||
static const uint32_t PDEC_SLEN_OFFSET = 0xA26;
|
||||
static const uint32_t PDEC_MON_OFFSET = 0xA27;
|
||||
|
||||
#ifdef TE0720_1CFA
|
||||
static const int CONFIG_MEMORY_MAP_SIZE = 0x400;
|
||||
static const int RAM_MAP_SIZE = 0x4000;
|
||||
@ -163,9 +156,6 @@ class PdecHandler : public SystemObject,
|
||||
static const int REGISTER_MAP_SIZE = 0x4000;
|
||||
#endif /* BOARD_TE0720 == 1 */
|
||||
|
||||
// 0x200 / 4 = 0x80
|
||||
static const uint32_t FRAME_HEADER_OFFSET = 0x80;
|
||||
|
||||
static const size_t MAX_TC_SEGMENT_SIZE = 1017;
|
||||
static const uint8_t MAP_ID_MASK = 0x3F;
|
||||
|
||||
@ -175,15 +165,6 @@ class PdecHandler : public SystemObject,
|
||||
static const uint32_t PHYSICAL_RAM_BASE_ADDRESS = 0x26000000;
|
||||
#endif
|
||||
|
||||
static const uint32_t MAP_ADDR_LUT_OFFSET = 0xA0;
|
||||
static const uint32_t MAP_CLK_FREQ_OFFSET = 0x90;
|
||||
|
||||
static const uint8_t MAX_MAP_ADDR = 63;
|
||||
// Writing this to the map address in the look up table will invalidate a MAP ID.
|
||||
static const uint8_t NO_DESTINATION = 0;
|
||||
static const uint8_t VALID_POSITION = 6;
|
||||
static const uint8_t PARITY_POSITION = 7;
|
||||
|
||||
// Expected value stored in FAR register after reset
|
||||
static const uint32_t FAR_RESET = 0x7FE0;
|
||||
|
||||
@ -192,15 +173,17 @@ class PdecHandler : public SystemObject,
|
||||
static const uint32_t NO_RF_MASK = 0x8000;
|
||||
static const uint32_t NO_BITLOCK_MASK = 0x4000;
|
||||
|
||||
/**
|
||||
* TCs with map addresses (also know as Map IDs) assigned to this channel will be stored in
|
||||
* the PDEC memory.
|
||||
*/
|
||||
static const uint8_t PM_BUFFER = 7;
|
||||
static const uint32_t MAX_INIT_TRIES = 20;
|
||||
|
||||
// MAP clock frequency. Must be a value between 1 and 13 otherwise the TC segment will be
|
||||
// discarded
|
||||
static const uint8_t MAP_CLK_FREQ = 2;
|
||||
class ParameterId {
|
||||
public:
|
||||
// ID of the parameter to update the positive window of AD frames
|
||||
static const uint8_t POSITIVE_WINDOW = 0;
|
||||
// ID of the parameter to update the negative window of AD frames
|
||||
static const uint8_t NEGATIVE_WINDOW = 1;
|
||||
};
|
||||
|
||||
static constexpr uint32_t MAX_ALLOWED_IRQS_PER_WINDOW = 800;
|
||||
|
||||
enum class FrameAna_t : uint8_t {
|
||||
ABANDONED_CLTU,
|
||||
@ -224,18 +207,91 @@ class PdecHandler : public SystemObject,
|
||||
INCORRECT_BC_CC
|
||||
};
|
||||
|
||||
enum class State : uint8_t { INIT, RUNNING, WAIT_FOR_RECOVERY };
|
||||
enum class State : uint8_t { INIT, PDEC_RESET, RUNNING, WAIT_FOR_RECOVERY };
|
||||
|
||||
static uint32_t CURRENT_FAR;
|
||||
|
||||
Countdown genericCheckCd = Countdown(IRQ_TIMEOUT_MS);
|
||||
object_id_t tcDestinationId;
|
||||
|
||||
AcceptsTelecommandsIF* tcDestination = nullptr;
|
||||
|
||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||
|
||||
uint32_t interruptCounter = 0;
|
||||
Countdown interruptWindowCd = Countdown(1000);
|
||||
|
||||
/**
|
||||
* Reset signal is required to hold PDEC in reset state until the configuration has been
|
||||
* written to the appropriate memory space.
|
||||
* Can also be used to reboot PDEC in case of erros.
|
||||
*/
|
||||
gpioId_t pdecReset = gpio::NO_GPIO;
|
||||
|
||||
uint32_t tcAbortCounter = 0;
|
||||
|
||||
ActionHelper actionHelper;
|
||||
|
||||
StorageManagerIF* tcStore = nullptr;
|
||||
|
||||
MessageQueueIF* commandQueue = nullptr;
|
||||
|
||||
State state = State::INIT;
|
||||
|
||||
/**
|
||||
* Pointer pointing to base address of the PDEC memory space.
|
||||
* This address is equivalent with the base address of the section named configuration area in
|
||||
* the PDEC datasheet.
|
||||
*/
|
||||
uint32_t* memoryBaseAddress = nullptr;
|
||||
|
||||
uint32_t* ramBaseAddress = nullptr;
|
||||
|
||||
// Pointer pointing to base address of register space
|
||||
uint32_t* registerBaseAddress = nullptr;
|
||||
|
||||
uint8_t tcSegment[TC_SEGMENT_LEN];
|
||||
|
||||
// Used to check carrier and bit lock changes (default set to no rf and no bitlock)
|
||||
uint32_t lastClcw = 0xC000;
|
||||
|
||||
bool carrierLock = false;
|
||||
bool bitLock = false;
|
||||
|
||||
UioNames uioNames;
|
||||
|
||||
ParameterHelper paramHelper;
|
||||
|
||||
PdecConfig pdecConfig;
|
||||
|
||||
uint32_t initTries = 0;
|
||||
|
||||
/**
|
||||
* @brief Performs initialization stuff which must be performed in first
|
||||
* loop of running task
|
||||
*
|
||||
* @return OK if successful, otherwise FAILED
|
||||
*/
|
||||
ReturnValue_t firstLoop();
|
||||
|
||||
/**
|
||||
* @brief Reads and handles messages stored in the commandQueue
|
||||
*/
|
||||
void readCommandQueue(void);
|
||||
|
||||
ReturnValue_t polledOperation();
|
||||
ReturnValue_t irqOperation();
|
||||
ReturnValue_t handleInitState();
|
||||
void openIrqFile(int* fd);
|
||||
ReturnValue_t checkAndHandleIrqs(int fd, uint32_t& info);
|
||||
|
||||
uint32_t readFar();
|
||||
|
||||
/**
|
||||
* @brief This functions writes the configuration parameters to the configuration
|
||||
* section of the PDEC.
|
||||
*/
|
||||
void writePdecConfig();
|
||||
void writePdecConfigDuringReset(PdecConfig& config);
|
||||
|
||||
/**
|
||||
* @brief Reading the FAR resets the set stat flag which signals a new TC. Without clearing
|
||||
@ -252,6 +308,14 @@ class PdecHandler : public SystemObject,
|
||||
*/
|
||||
ReturnValue_t releasePdec();
|
||||
|
||||
/**
|
||||
* @brief Will set PDEC in reset state. Use releasePdec() to release PDEC
|
||||
* from reset state
|
||||
*
|
||||
* @return OK if successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t pdecToReset();
|
||||
|
||||
/**
|
||||
* @brief Reads the FAR register and checks if a new TC has been received.
|
||||
*/
|
||||
@ -263,6 +327,8 @@ class PdecHandler : public SystemObject,
|
||||
*/
|
||||
void checkLocks();
|
||||
|
||||
void resetIrqLimiters();
|
||||
|
||||
/**
|
||||
* @brief Analyzes the FramAna field (frame analysis data) of a FAR report.
|
||||
*
|
||||
@ -313,13 +379,6 @@ class PdecHandler : public SystemObject,
|
||||
*/
|
||||
uint8_t calcMapAddrEntry(uint8_t moduleId);
|
||||
|
||||
/**
|
||||
* @brief This functions calculates the odd parity of the bits in number.
|
||||
*
|
||||
* @param number The number from which to calculate the odd parity.
|
||||
*/
|
||||
uint8_t getOddParity(uint8_t number);
|
||||
|
||||
/**
|
||||
* brief Returns the 32-bit wide communication link control word (CLCW)
|
||||
*/
|
||||
@ -342,55 +401,6 @@ class PdecHandler : public SystemObject,
|
||||
void printPdecMon();
|
||||
|
||||
std::string getMonStatusString(uint32_t status);
|
||||
|
||||
object_id_t tcDestinationId;
|
||||
|
||||
AcceptsTelecommandsIF* tcDestination = nullptr;
|
||||
|
||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||
|
||||
/**
|
||||
* Reset signal is required to hold PDEC in reset state until the configuration has been
|
||||
* written to the appropriate memory space.
|
||||
* Can also be used to reboot PDEC in case of erros.
|
||||
*/
|
||||
gpioId_t pdecReset = gpio::NO_GPIO;
|
||||
|
||||
// UIO device file giving access to the PDEC configuration memory section
|
||||
std::string uioConfigMemory;
|
||||
|
||||
// UIO device file giving access to the PDEC RAM section
|
||||
std::string uioRamMemory;
|
||||
|
||||
// UIO device file giving access to the PDEC register space
|
||||
std::string uioRegisters;
|
||||
|
||||
ActionHelper actionHelper;
|
||||
|
||||
StorageManagerIF* tcStore = nullptr;
|
||||
|
||||
MessageQueueIF* commandQueue = nullptr;
|
||||
|
||||
State state = State::INIT;
|
||||
|
||||
/**
|
||||
* Pointer pointing to base address of the PDEC memory space.
|
||||
* This address is equivalent with the base address of the section named configuration area in
|
||||
* the PDEC datasheet.
|
||||
*/
|
||||
uint32_t* memoryBaseAddress = nullptr;
|
||||
|
||||
uint32_t* ramBaseAddress = nullptr;
|
||||
|
||||
// Pointer pointing to base address of register space
|
||||
uint32_t* registerBaseAddress = nullptr;
|
||||
|
||||
uint32_t pdecFar = 0;
|
||||
|
||||
uint8_t tcSegment[TC_SEGMENT_LEN];
|
||||
|
||||
// Used to check carrier and bit lock changes (default set to no rf and no bitlock)
|
||||
uint32_t lastClcw = 0xC000;
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_PDECHANDLER_H_ */
|
@ -1,9 +1,10 @@
|
||||
#include <fcntl.h>
|
||||
#include <linux/obc/Ptme.h>
|
||||
#include <linux/ipcore/Ptme.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "PtmeConfig.h"
|
||||
#include "eive/definitions.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
Ptme::Ptme(object_id_t objectId) : SystemObject(objectId) {}
|
||||
@ -15,11 +16,11 @@ ReturnValue_t Ptme::initialize() {
|
||||
for (iter = vcInterfaceMap.begin(); iter != vcInterfaceMap.end(); iter++) {
|
||||
iter->second->initialize();
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t* data, size_t size) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId);
|
||||
if (vcInterfaceMapIter == vcInterfaceMap.end()) {
|
||||
sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual "
|
||||
@ -31,8 +32,8 @@ ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t* data, size_t size) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void Ptme::addVcInterface(VcId_t vcId, VcInterfaceIF* vc) {
|
||||
if (vcId > common::NUMBER_OF_VIRTUAL_CHANNELS) {
|
||||
void Ptme::addVcInterface(VcId_t vcId, VirtualChannelIF* vc) {
|
||||
if (vcId > config::NUMBER_OF_VIRTUAL_CHANNELS) {
|
||||
sif::warning << "Ptme::addVcInterface: Invalid virtual channel ID" << std::endl;
|
||||
return;
|
||||
}
|
||||
@ -50,3 +51,14 @@ void Ptme::addVcInterface(VcId_t vcId, VcInterfaceIF* vc) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool Ptme::isBusy(uint8_t vcId) const {
|
||||
const auto& vcInterfaceMapIter = vcInterfaceMap.find(vcId);
|
||||
if (vcInterfaceMapIter == vcInterfaceMap.end()) {
|
||||
sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual "
|
||||
"channel with id "
|
||||
<< static_cast<unsigned int>(vcId) << std::endl;
|
||||
return UNKNOWN_VC_ID;
|
||||
}
|
||||
return vcInterfaceMapIter->second->isBusy();
|
||||
}
|
@ -3,22 +3,25 @@
|
||||
|
||||
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
|
||||
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
|
||||
#include <linux/ipcore/VirtualChannelIF.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "linux/obc/PtmeIF.h"
|
||||
#include "linux/obc/VcInterfaceIF.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "linux/ipcore/PtmeIF.h"
|
||||
|
||||
/**
|
||||
* @brief This class handles the interfacing to the telemetry (PTME) IP core responsible for the
|
||||
* encoding of telemetry packets according to the CCSDS standards CCSDS 131.0-B-3 (TM
|
||||
* Synchro- nization and channel coding) and CCSDS 132.0-B-2 (TM Space Data Link Protocoll). The IP
|
||||
* cores are implemented on the programmable logic and are accessible through the linux UIO driver.
|
||||
* @brief This class handles the interfacing to the telemetry (PTME) IP core.
|
||||
*
|
||||
* @details
|
||||
* This module is responsible for the encoding of telemetry packets according to the CCSDS
|
||||
* standards CCSDS 131.0-B-3 (TM Synchronization and channel coding) and CCSDS 132.0-B-2
|
||||
* (TM Space Data Link Protocoll). The IP cores are implemented on the programmable logic and are
|
||||
* accessible through the linux UIO driver.
|
||||
*/
|
||||
class Ptme : public PtmeIF, public SystemObject, public HasReturnvaluesIF {
|
||||
class Ptme : public PtmeIF, public SystemObject {
|
||||
public:
|
||||
using VcId_t = uint8_t;
|
||||
|
||||
@ -32,12 +35,13 @@ class Ptme : public PtmeIF, public SystemObject, public HasReturnvaluesIF {
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) override;
|
||||
bool isBusy(uint8_t vcId) const override;
|
||||
|
||||
/**
|
||||
* @brief This function adds the reference to a virtual channel interface to the vcInterface
|
||||
* map.
|
||||
*/
|
||||
void addVcInterface(VcId_t vcId, VcInterfaceIF* vc);
|
||||
void addVcInterface(VcId_t vcId, VirtualChannelIF* vc);
|
||||
|
||||
private:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::PTME;
|
||||
@ -70,7 +74,7 @@ class Ptme : public PtmeIF, public SystemObject, public HasReturnvaluesIF {
|
||||
|
||||
uint32_t* ptmeBaseAddress = nullptr;
|
||||
|
||||
using VcInterfaceMap = std::unordered_map<VcId_t, VcInterfaceIF*>;
|
||||
using VcInterfaceMap = std::unordered_map<VcId_t, VirtualChannelIF*>;
|
||||
using VcInterfaceMapIter = VcInterfaceMap::iterator;
|
||||
|
||||
VcInterfaceMap vcInterfaceMap;
|
@ -10,9 +10,9 @@ PtmeConfig::~PtmeConfig() {}
|
||||
ReturnValue_t PtmeConfig::initialize() {
|
||||
if (axiPtmeConfig == nullptr) {
|
||||
sif::warning << "PtmeConfig::initialize: Invalid AxiPtmeConfig object" << std::endl;
|
||||
return RETURN_FAILED;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PtmeConfig::setRate(uint32_t bitRate) {
|
||||
@ -27,20 +27,20 @@ ReturnValue_t PtmeConfig::setRate(uint32_t bitRate) {
|
||||
}
|
||||
|
||||
ReturnValue_t PtmeConfig::invertTxClock(bool invert) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
if (invert) {
|
||||
result = axiPtmeConfig->enableTxclockInversion();
|
||||
} else {
|
||||
result = axiPtmeConfig->disableTxclockInversion();
|
||||
}
|
||||
if (result != RETURN_OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
return CLK_INVERSION_FAILED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PtmeConfig::configTxManipulator(bool enable) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
if (enable) {
|
||||
result = axiPtmeConfig->enableTxclockManipulator();
|
||||
} else {
|
@ -3,15 +3,16 @@
|
||||
|
||||
#include "AxiPtmeConfig.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "linux/obc/PtmeConfig.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include "linux/ipcore/PtmeConfig.h"
|
||||
#include "returnvalues/classIds.h"
|
||||
|
||||
/**
|
||||
* @brief Class to configure donwlink specific parameters in the PTME IP core.
|
||||
*
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PtmeConfig : public SystemObject, public HasReturnvaluesIF {
|
||||
class PtmeConfig : public SystemObject {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
@ -1,7 +1,7 @@
|
||||
#ifndef LINUX_OBC_PTMEIF_H_
|
||||
#define LINUX_OBC_PTMEIF_H_
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
/**
|
||||
* @brief Interface class for managing the PTME IP Core implemented in the programmable logic.
|
||||
@ -22,6 +22,7 @@ class PtmeIF {
|
||||
* @param size Number of bytes to write
|
||||
*/
|
||||
virtual ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) = 0;
|
||||
virtual bool isBusy(uint8_t vcId) const = 0;
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_PTMEIF_H_ */
|
23
linux/ipcore/VirtualChannelIF.h
Normal file
23
linux/ipcore/VirtualChannelIF.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef LINUX_OBC_VCINTERFACEIF_H_
|
||||
#define LINUX_OBC_VCINTERFACEIF_H_
|
||||
|
||||
#include <mission/tmtc/DirectTmSinkIF.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
/**
|
||||
* @brief Interface class for managing different virtual channels of the PTME IP core implemented
|
||||
* in the programmable logic.
|
||||
* @details
|
||||
* Also implements @DirectTmSinkIF to allow wiriting to the VC directly.
|
||||
* @author J. Meier
|
||||
*/
|
||||
class VirtualChannelIF : public DirectTmSinkIF {
|
||||
public:
|
||||
virtual ~VirtualChannelIF(){};
|
||||
|
||||
virtual ReturnValue_t initialize() = 0;
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_VCINTERFACEIF_H_ */
|
61
linux/ipcore/pdec.h
Normal file
61
linux/ipcore/pdec.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef LINUX_OBC_PDEC_H_
|
||||
#define LINUX_OBC_PDEC_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace pdec {
|
||||
|
||||
static const uint8_t STAT_POSITION = 31;
|
||||
static const uint8_t FRAME_ANA_POSITION = 28;
|
||||
static const uint8_t IREASON_POSITION = 25;
|
||||
|
||||
static const uint8_t NEW_FAR_RECEIVED = 0;
|
||||
|
||||
static constexpr uint32_t NEW_FAR_MASK = 1 << 2;
|
||||
static constexpr uint32_t TC_ABORT_MASK = 1 << 1;
|
||||
static constexpr uint32_t TC_NEW_MASK = 1 << 0;
|
||||
|
||||
static constexpr uint32_t FAR_STAT_MASK = 1UL << 31;
|
||||
|
||||
static const uint32_t FRAME_ANA_MASK = 0x70000000;
|
||||
static const uint32_t IREASON_MASK = 0x0E000000;
|
||||
|
||||
static const uint32_t TC_CHANNEL_INACTIVE = 0x0;
|
||||
static const uint32_t TC_CHANNEL_ACTIVE = 0x1;
|
||||
static const uint32_t TC_CHANNEL_TIMEDOUT = 0x2;
|
||||
|
||||
static const uint32_t TC0_STATUS_MASK = 0x3;
|
||||
static const uint32_t TC1_STATUS_MASK = 0xC;
|
||||
static const uint32_t TC2_STATUS_MASK = 0x300;
|
||||
static const uint32_t TC3_STATUS_MASK = 0xC00;
|
||||
static const uint32_t TC4_STATUS_MASK = 0x30000;
|
||||
static const uint32_t TC5_STATUS_MASK = 0xc00000;
|
||||
// Lock register set to 1 when start sequence has been found (CLTU is beeing processed)
|
||||
static const uint32_t LOCK_MASK = 0xc00000;
|
||||
|
||||
static const uint32_t TC0_STATUS_POS = 0;
|
||||
static const uint32_t TC1_STATUS_POS = 2;
|
||||
static const uint32_t TC2_STATUS_POS = 4;
|
||||
static const uint32_t TC3_STATUS_POS = 6;
|
||||
static const uint32_t TC4_STATUS_POS = 8;
|
||||
static const uint32_t TC5_STATUS_POS = 10;
|
||||
// Lock register set to 1 when start sequence has been found (CLTU is beeing processed)
|
||||
static const uint32_t LOCK_POS = 12;
|
||||
|
||||
/**
|
||||
* UIO is 4 byte aligned. Thus offset is calculated with "true offset" / 4
|
||||
* Example: PDEC_FAR = 0x2840 => Offset in virtual address space is 0xA10
|
||||
*/
|
||||
static constexpr uint32_t PDEC_PISR_OFFSET = 0xA02;
|
||||
static constexpr uint32_t PDEC_PIR_OFFSET = 0xA03;
|
||||
static constexpr uint32_t PDEC_IMR_OFFSET = 0xA04;
|
||||
static const uint32_t PDEC_FAR_OFFSET = 0xA10;
|
||||
static const uint32_t PDEC_CLCW_OFFSET = 0xA12;
|
||||
static const uint32_t PDEC_BFREE_OFFSET = 0xA24;
|
||||
static const uint32_t PDEC_BPTR_OFFSET = 0xA25;
|
||||
static const uint32_t PDEC_SLEN_OFFSET = 0xA26;
|
||||
static const uint32_t PDEC_MON_OFFSET = 0xA27;
|
||||
|
||||
} // namespace pdec
|
||||
|
||||
#endif /* LINUX_OBC_PDEC_H_ */
|
20
linux/ipcore/pdecconfigdefs.h
Normal file
20
linux/ipcore/pdecconfigdefs.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef LINUX_IPCORE_PDECCONFIGDEFS_H_
|
||||
#define LINUX_IPCORE_PDECCONFIGDEFS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace pdecconfigdefs {
|
||||
|
||||
namespace paramkeys {
|
||||
static const std::string POSITIVE_WINDOW = "positive_window";
|
||||
static const std::string NEGATIVE_WINDOW = "negattive_window";
|
||||
} // namespace paramkeys
|
||||
|
||||
namespace defaultvalue {
|
||||
static const uint8_t positiveWindow = 10;
|
||||
static const uint8_t negativeWindow = 151;
|
||||
} // namespace defaultvalue
|
||||
|
||||
} // namespace pdecconfigdefs
|
||||
|
||||
#endif /* LINUX_IPCORE_PDECCONFIGDEFS_H_ */
|
@ -1,10 +0,0 @@
|
||||
target_sources(${OBSW_NAME} PUBLIC
|
||||
PapbVcInterface.cpp
|
||||
Ptme.cpp
|
||||
PdecHandler.cpp
|
||||
PdecConfig.cpp
|
||||
PtmeConfig.cpp
|
||||
AxiPtmeConfig.cpp
|
||||
)
|
||||
|
||||
|
@ -1,33 +0,0 @@
|
||||
#include "PdecConfig.h"
|
||||
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
PdecConfig::PdecConfig() { initialize(); }
|
||||
|
||||
PdecConfig::~PdecConfig() {}
|
||||
|
||||
void PdecConfig::initialize() {
|
||||
uint32_t word = 0;
|
||||
word |= (VERSION_ID << 30);
|
||||
word |= (BYPASS_FLAG << 29);
|
||||
word |= (CONTROL_COMMAND_FLAG << 28);
|
||||
word |= (RESERVED_FIELD_A << 26);
|
||||
word |= (SPACECRAFT_ID << 16);
|
||||
word |= (VIRTUAL_CHANNEL << 10);
|
||||
word |= (DUMMY_BITS << 8);
|
||||
word |= POSITIVE_WINDOW;
|
||||
configWords[0] = word;
|
||||
word = 0;
|
||||
word |= (NEGATIVE_WINDOW << 24);
|
||||
word |= (HIGH_AU_MAP_ID << 16);
|
||||
word |= (ENABLE_DERANDOMIZER << 8);
|
||||
configWords[1] = word;
|
||||
}
|
||||
|
||||
uint32_t PdecConfig::getConfigWord(uint8_t wordNo) {
|
||||
if (wordNo >= CONFIG_WORDS_NUM) {
|
||||
sif::error << "PdecConfig::getConfigWord: Invalid word number" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
return configWords[wordNo];
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
#ifndef LINUX_OBC_PDECCONFIG_H_
|
||||
#define LINUX_OBC_PDECCONFIG_H_
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
/**
|
||||
* @brief This class generates the configuration words for the configuration memory of the PDEC
|
||||
* IP Cores.
|
||||
*
|
||||
* @details Fields are initialized according to pecification in PDEC datasheet section 6.11.3.1
|
||||
* PROM usage.
|
||||
*
|
||||
* @author J. Meier
|
||||
*/
|
||||
class PdecConfig {
|
||||
public:
|
||||
PdecConfig();
|
||||
virtual ~PdecConfig();
|
||||
|
||||
/**
|
||||
* @brief Returns the configuration word by specifying the position.
|
||||
*/
|
||||
uint32_t getConfigWord(uint8_t wordNo);
|
||||
|
||||
private:
|
||||
// TC transfer frame configuration parameters
|
||||
static const uint8_t VERSION_ID = 0;
|
||||
// BD Frames
|
||||
static const uint8_t BYPASS_FLAG = 1;
|
||||
static const uint8_t CONTROL_COMMAND_FLAG = 0;
|
||||
|
||||
static const uint8_t VIRTUAL_CHANNEL = 0;
|
||||
static const uint8_t RESERVED_FIELD_A = 0;
|
||||
static const uint16_t SPACECRAFT_ID = 0x274;
|
||||
static const uint16_t DUMMY_BITS = 0;
|
||||
// Parameters to control the FARM for AD frames
|
||||
// Set here for future use
|
||||
static const uint8_t POSITIVE_WINDOW = 10;
|
||||
static const uint8_t NEGATIVE_WINDOW = 151;
|
||||
static const uint8_t HIGH_AU_MAP_ID = 0xF;
|
||||
static const uint8_t ENABLE_DERANDOMIZER = 1;
|
||||
|
||||
static const uint8_t CONFIG_WORDS_NUM = 2;
|
||||
|
||||
uint32_t configWords[CONFIG_WORDS_NUM];
|
||||
|
||||
void initialize();
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_PDECCONFIG_H_ */
|
@ -1,30 +0,0 @@
|
||||
#ifndef LINUX_OBC_VCINTERFACEIF_H_
|
||||
#define LINUX_OBC_VCINTERFACEIF_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
/**
|
||||
* @brief Interface class for managing different virtual channels of the PTME IP core implemented
|
||||
* in the programmable logic.
|
||||
*
|
||||
* @author J. Meier
|
||||
*/
|
||||
class VcInterfaceIF {
|
||||
public:
|
||||
virtual ~VcInterfaceIF(){};
|
||||
|
||||
/**
|
||||
* @brief Implememts the functionality to write data in the virtual channel of the PTME IP
|
||||
* Core.
|
||||
*
|
||||
* @param data Pointer to buffer holding the data to write
|
||||
* @param size Number of bytes to write
|
||||
*/
|
||||
virtual ReturnValue_t write(const uint8_t* data, size_t size) = 0;
|
||||
|
||||
virtual ReturnValue_t initialize() = 0;
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_VCINTERFACEIF_H_ */
|
81
linux/scheduling.cpp
Normal file
81
linux/scheduling.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "scheduling.h"
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||
#include <fsfw/tasks/PeriodicTaskIF.h>
|
||||
#include <mission/utility/InitMission.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "ObjectFactory.h"
|
||||
#include "eive/objects.h"
|
||||
|
||||
void scheduling::scheduleScexReader(TaskFactory& factory, PeriodicTaskIF*& scexReaderTask) {
|
||||
using namespace scheduling;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
#if OBSW_PRINT_MISSED_DEADLINES == 1
|
||||
void (*missedDeadlineFunc)(void) = TaskFactory::printMissedDeadline;
|
||||
#else
|
||||
void (*missedDeadlineFunc)(void) = nullptr;
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void scheduling::addMpsocSupvHandlers(PeriodicTaskIF* plTask) {
|
||||
#if OBSW_ADD_PLOC_SUPERVISOR == 1
|
||||
plTask->addComponent(objects::PLOC_SUPERVISOR_HANDLER, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
plTask->addComponent(objects::PLOC_SUPERVISOR_HANDLER, DeviceHandlerIF::SEND_WRITE);
|
||||
plTask->addComponent(objects::PLOC_SUPERVISOR_HANDLER, DeviceHandlerIF::GET_WRITE);
|
||||
plTask->addComponent(objects::PLOC_SUPERVISOR_HANDLER, DeviceHandlerIF::SEND_READ);
|
||||
plTask->addComponent(objects::PLOC_SUPERVISOR_HANDLER, DeviceHandlerIF::GET_READ);
|
||||
plTask->addComponent(objects::PLOC_SUPERVISOR_HANDLER, DeviceHandlerIF::SEND_READ);
|
||||
plTask->addComponent(objects::PLOC_SUPERVISOR_HANDLER, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
|
||||
#if OBSW_ADD_PLOC_MPSOC == 1
|
||||
plTask->addComponent(objects::PLOC_MPSOC_HANDLER, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
plTask->addComponent(objects::PLOC_MPSOC_HANDLER, DeviceHandlerIF::SEND_WRITE);
|
||||
plTask->addComponent(objects::PLOC_MPSOC_HANDLER, DeviceHandlerIF::GET_WRITE);
|
||||
plTask->addComponent(objects::PLOC_MPSOC_HANDLER, DeviceHandlerIF::SEND_READ);
|
||||
plTask->addComponent(objects::PLOC_MPSOC_HANDLER, DeviceHandlerIF::GET_READ);
|
||||
plTask->addComponent(objects::PLOC_MPSOC_HANDLER, DeviceHandlerIF::SEND_READ);
|
||||
plTask->addComponent(objects::PLOC_MPSOC_HANDLER, DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
}
|
||||
|
||||
void scheduling::scheduleScexDev(PeriodicTaskIF*& scexDevHandler) {
|
||||
ReturnValue_t 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);
|
||||
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);
|
||||
if (result != returnvalue::OK) {
|
||||
printAddObjectError("SCEX_DEV", objects::SCEX);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user