custom CSP router task #516

Merged
muellerr merged 5 commits from custom_csp_router_task into develop 2023-03-24 14:47:56 +01:00
23 changed files with 239 additions and 115 deletions
Showing only changes of commit 52c439c501 - Show all commits

View File

@ -18,10 +18,23 @@ will consitute of a breaking change warranting a new major release:
## Fixed ## Fixed
- PAPB busy polling now implemented properly with an upper bound of how often the PAPB is allowed
to be busy before returning the BUSY returnvalue. Also propagate and check for that case properly.
Ideally, this will never be an issue and the PAPB VC interface should never block for a longer
period.
## Added
- The persistent TM stores now have low priorities and behave like background threads now. This
should prevent them from blocking or slowing down the system even during dumps
(at least in theory).
- STR: Fix weird issues on datalink layer data reception which sometimes occur. - STR: Fix weird issues on datalink layer data reception which sometimes occur.
## Changed ## Changed
- Rework FSFW OSALs to properly support regular scheduling (NICE priorities) and real-time
scheduling.
- Tweak scheduling priorities.
- STR: Move datalink layer to `StrComHandler` completely. DLL is now completely hidden from - STR: Move datalink layer to `StrComHandler` completely. DLL is now completely hidden from
device handler. device handler.
- STR: Is now scheduled twice in ACS PST. - STR: Is now scheduled twice in ACS PST.

View File

@ -72,8 +72,9 @@ void scheduling::initTasks() {
#if OBSW_ADD_SA_DEPL == 1 #if OBSW_ADD_SA_DEPL == 1
// Could add this to the core controller but the core controller does so many thing that I would // Could add this to the core controller but the core controller does so many thing that I would
// prefer to have the solar array deployment in a seprate task. // prefer to have the solar array deployment in a seprate task.
PeriodicTaskIF* solarArrayDeplTask = factory->createPeriodicTask( PeriodicTaskIF* solarArrayDeplTask =
"SOLAR_ARRAY_DEPL", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc); factory->createPeriodicTask("SOLAR_ARRAY_DEPL", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4,
missedDeadlineFunc, &RR_SCHEDULING);
result = solarArrayDeplTask->addComponent(objects::SOLAR_ARRAY_DEPL_HANDLER); result = solarArrayDeplTask->addComponent(objects::SOLAR_ARRAY_DEPL_HANDLER);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("SOLAR_ARRAY_DEPL", objects::SOLAR_ARRAY_DEPL_HANDLER); scheduling::printAddObjectError("SOLAR_ARRAY_DEPL", objects::SOLAR_ARRAY_DEPL_HANDLER);
@ -81,7 +82,7 @@ void scheduling::initTasks() {
#endif #endif
PeriodicTaskIF* coreCtrlTask = factory->createPeriodicTask( PeriodicTaskIF* coreCtrlTask = factory->createPeriodicTask(
"CORE_CTRL", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc); "CORE_CTRL", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc, &RR_SCHEDULING);
result = coreCtrlTask->addComponent(objects::CORE_CONTROLLER); result = coreCtrlTask->addComponent(objects::CORE_CONTROLLER);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("CORE_CTRL", objects::CORE_CONTROLLER); scheduling::printAddObjectError("CORE_CTRL", objects::CORE_CONTROLLER);
@ -89,7 +90,7 @@ void scheduling::initTasks() {
/* TMTC Distribution */ /* TMTC Distribution */
PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask( PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask(
"DIST", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); "TC_DIST", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc, &RR_SCHEDULING);
#if OBSW_ADD_TCPIP_SERVERS == 1 #if OBSW_ADD_TCPIP_SERVERS == 1
#if OBSW_ADD_TMTC_UDP_SERVER == 1 #if OBSW_ADD_TMTC_UDP_SERVER == 1
result = tmTcDistributor->addComponent(objects::UDP_TMTC_SERVER); result = tmTcDistributor->addComponent(objects::UDP_TMTC_SERVER);
@ -119,16 +120,18 @@ void scheduling::initTasks() {
#if OBSW_ADD_TCPIP_SERVERS == 1 #if OBSW_ADD_TCPIP_SERVERS == 1
#if OBSW_ADD_TMTC_UDP_SERVER == 1 #if OBSW_ADD_TMTC_UDP_SERVER == 1
PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask( PeriodicTaskIF* udpPollingTask =
"UDP_TMTC_POLLING", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc); factory->createPeriodicTask("UDP_TMTC_POLLING", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0,
missedDeadlineFunc, &RR_SCHEDULING);
result = udpPollingTask->addComponent(objects::UDP_TMTC_POLLING_TASK); result = udpPollingTask->addComponent(objects::UDP_TMTC_POLLING_TASK);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("UDP_POLLING", objects::UDP_TMTC_POLLING_TASK); scheduling::printAddObjectError("UDP_POLLING", objects::UDP_TMTC_POLLING_TASK);
} }
#endif #endif
#if OBSW_ADD_TMTC_TCP_SERVER == 1 #if OBSW_ADD_TMTC_TCP_SERVER == 1
PeriodicTaskIF* tcpPollingTask = factory->createPeriodicTask( PeriodicTaskIF* tcpPollingTask =
"TCP_TMTC_POLLING", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc); factory->createPeriodicTask("TCP_TMTC_POLLING", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0,
missedDeadlineFunc, &RR_SCHEDULING);
result = tcpPollingTask->addComponent(objects::TCP_TMTC_POLLING_TASK); result = tcpPollingTask->addComponent(objects::TCP_TMTC_POLLING_TASK);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("UDP_POLLING", objects::TCP_TMTC_POLLING_TASK); scheduling::printAddObjectError("UDP_POLLING", objects::TCP_TMTC_POLLING_TASK);
@ -136,8 +139,9 @@ void scheduling::initTasks() {
#endif #endif
#endif #endif
PeriodicTaskIF* genericSysTask = factory->createPeriodicTask( PeriodicTaskIF* genericSysTask =
"SYSTEM_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc); factory->createPeriodicTask("SYSTEM_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5,
missedDeadlineFunc, &RR_SCHEDULING);
result = genericSysTask->addComponent(objects::EIVE_SYSTEM); result = genericSysTask->addComponent(objects::EIVE_SYSTEM);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("EIVE_SYSTEM", objects::EIVE_SYSTEM); scheduling::printAddObjectError("EIVE_SYSTEM", objects::EIVE_SYSTEM);
@ -171,7 +175,7 @@ void scheduling::initTasks() {
// Runs in IRQ mode, frequency does not really matter // Runs in IRQ mode, frequency does not really matter
PeriodicTaskIF* pdecHandlerTask = factory->createPeriodicTask( PeriodicTaskIF* pdecHandlerTask = factory->createPeriodicTask(
"PDEC_HANDLER", 75, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc); "PDEC_HANDLER", 75, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr, &RR_SCHEDULING);
result = pdecHandlerTask->addComponent(objects::PDEC_HANDLER); result = pdecHandlerTask->addComponent(objects::PDEC_HANDLER);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("PDEC Handler", objects::PDEC_HANDLER); scheduling::printAddObjectError("PDEC Handler", objects::PDEC_HANDLER);
@ -179,50 +183,53 @@ void scheduling::initTasks() {
#endif /* OBSW_ADD_CCSDS_IP_CORE == 1 */ #endif /* OBSW_ADD_CCSDS_IP_CORE == 1 */
// All the TM store tasks run in permanent loops, frequency does not matter // All the TM store tasks run in permanent loops, frequency does not matter
PeriodicTaskIF* liveTmTask = PeriodicTaskIF* liveTmTask = factory->createPeriodicTask(
factory->createPeriodicTask("LIVE_TM", 55, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); "LIVE_TM", 55, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr, &RR_SCHEDULING);
result = liveTmTask->addComponent(objects::LIVE_TM_TASK); result = liveTmTask->addComponent(objects::LIVE_TM_TASK);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("LIVE_TM", objects::LIVE_TM_TASK); scheduling::printAddObjectError("LIVE_TM", objects::LIVE_TM_TASK);
} }
PeriodicTaskIF* logTmTask = factory->createPeriodicTask( PeriodicTaskIF* logTmTask = factory->createPeriodicTask(
"LOG_STORE_AND_TM", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); "LOG_PSTORE", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr);
result = logTmTask->addComponent(objects::LOG_STORE_AND_TM_TASK); result = logTmTask->addComponent(objects::LOG_STORE_AND_TM_TASK);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("LOG_STORE_AND_TM", objects::LOG_STORE_AND_TM_TASK); scheduling::printAddObjectError("LOG_STORE_AND_TM", objects::LOG_STORE_AND_TM_TASK);
} }
PeriodicTaskIF* hkTmTask = factory->createPeriodicTask( PeriodicTaskIF* hkTmTask = factory->createPeriodicTask(
"HK_STORE_AND_TM", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); "HK_PSTORE", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr);
result = hkTmTask->addComponent(objects::HK_STORE_AND_TM_TASK); result = hkTmTask->addComponent(objects::HK_STORE_AND_TM_TASK);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("HK_STORE_AND_TM", objects::HK_STORE_AND_TM_TASK); scheduling::printAddObjectError("HK_STORE_AND_TM", objects::HK_STORE_AND_TM_TASK);
} }
PeriodicTaskIF* cfdpTmTask = factory->createPeriodicTask( PeriodicTaskIF* cfdpTmTask = factory->createPeriodicTask(
"CFDP_STORE_AND_TM", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); "CFDP_PSTORE", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr);
result = cfdpTmTask->addComponent(objects::CFDP_STORE_AND_TM_TASK); result = cfdpTmTask->addComponent(objects::CFDP_STORE_AND_TM_TASK);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("CFDP_STORE_AND_TM", objects::CFDP_STORE_AND_TM_TASK); scheduling::printAddObjectError("CFDP_STORE_AND_TM", objects::CFDP_STORE_AND_TM_TASK);
} }
#if OBSW_ADD_CFDP_COMPONENTS == 1 #if OBSW_ADD_CFDP_COMPONENTS == 1
PeriodicTaskIF* cfdpTask = factory->createPeriodicTask( PeriodicTaskIF* cfdpTask =
"CFDP Handler", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc); factory->createPeriodicTask("CFDP_HANDLER", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4,
missedDeadlineFunc, &RR_SCHEDULING);
result = cfdpTask->addComponent(objects::CFDP_HANDLER); result = cfdpTask->addComponent(objects::CFDP_HANDLER);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("CFDP Handler", objects::CFDP_HANDLER); scheduling::printAddObjectError("CFDP Handler", objects::CFDP_HANDLER);
} }
#endif #endif
PeriodicTaskIF* gpsTask = factory->createPeriodicTask( PeriodicTaskIF* gpsTask =
"GPS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); factory->createPeriodicTask("GPS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4,
missedDeadlineFunc, &RR_SCHEDULING);
result = gpsTask->addComponent(objects::GPS_CONTROLLER); result = gpsTask->addComponent(objects::GPS_CONTROLLER);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("GPS_CTRL", objects::GPS_CONTROLLER); scheduling::printAddObjectError("GPS_CTRL", objects::GPS_CONTROLLER);
} }
#if OBSW_ADD_ACS_BOARD == 1 #if OBSW_ADD_ACS_BOARD == 1
PeriodicTaskIF* acsBrdPolling = factory->createPeriodicTask( PeriodicTaskIF* acsBrdPolling =
"ACS_BOARD_POLLING", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); factory->createPeriodicTask("ACS_BOARD_POLLING", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2,
0.4, missedDeadlineFunc, &RR_SCHEDULING);
result = acsBrdPolling->addComponent(objects::ACS_BOARD_POLLING_TASK); result = acsBrdPolling->addComponent(objects::ACS_BOARD_POLLING_TASK);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("ACS_BOARD_POLLING", objects::ACS_BOARD_POLLING_TASK); scheduling::printAddObjectError("ACS_BOARD_POLLING", objects::ACS_BOARD_POLLING_TASK);
@ -230,16 +237,18 @@ void scheduling::initTasks() {
#endif #endif
#if OBSW_ADD_RW == 1 #if OBSW_ADD_RW == 1
PeriodicTaskIF* rwPolling = factory->createPeriodicTask( PeriodicTaskIF* rwPolling =
"RW_POLLING_TASK", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); factory->createPeriodicTask("RW_POLLING_TASK", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2,
0.4, missedDeadlineFunc, &RR_SCHEDULING);
result = rwPolling->addComponent(objects::RW_POLLING_TASK); result = rwPolling->addComponent(objects::RW_POLLING_TASK);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("RW_POLLING_TASK", objects::RW_POLLING_TASK); scheduling::printAddObjectError("RW_POLLING_TASK", objects::RW_POLLING_TASK);
} }
#endif #endif
#if OBSW_ADD_MGT == 1 #if OBSW_ADD_MGT == 1
PeriodicTaskIF* imtqPolling = factory->createPeriodicTask( PeriodicTaskIF* imtqPolling =
"IMTQ_POLLING_TASK", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); factory->createPeriodicTask("IMTQ_POLLING_TASK", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2,
0.4, missedDeadlineFunc, &RR_SCHEDULING);
result = imtqPolling->addComponent(objects::IMTQ_POLLING); result = imtqPolling->addComponent(objects::IMTQ_POLLING);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("IMTQ_POLLING_TASK", objects::IMTQ_POLLING); scheduling::printAddObjectError("IMTQ_POLLING_TASK", objects::IMTQ_POLLING);
@ -247,16 +256,18 @@ void scheduling::initTasks() {
#endif #endif
#if OBSW_ADD_SUN_SENSORS == 1 #if OBSW_ADD_SUN_SENSORS == 1
PeriodicTaskIF* susPolling = factory->createPeriodicTask( PeriodicTaskIF* susPolling =
"SUS_POLLING_TASK", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); factory->createPeriodicTask("SUS_POLLING_TASK", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2,
0.4, missedDeadlineFunc, &RR_SCHEDULING);
result = susPolling->addComponent(objects::SUS_POLLING_TASK); result = susPolling->addComponent(objects::SUS_POLLING_TASK);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("SUS_POLLING_TASK", objects::SUS_POLLING_TASK); scheduling::printAddObjectError("SUS_POLLING_TASK", objects::SUS_POLLING_TASK);
} }
#endif #endif
PeriodicTaskIF* acsSysTask = factory->createPeriodicTask( PeriodicTaskIF* acsSysTask =
"ACS_SYS_TASK", 55, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); factory->createPeriodicTask("ACS_SYS_TASK", 55, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4,
missedDeadlineFunc, &RR_SCHEDULING);
result = acsSysTask->addComponent(objects::ACS_SUBSYSTEM); result = acsSysTask->addComponent(objects::ACS_SUBSYSTEM);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("ACS_SUBSYSTEM", objects::ACS_SUBSYSTEM); scheduling::printAddObjectError("ACS_SUBSYSTEM", objects::ACS_SUBSYSTEM);
@ -283,7 +294,7 @@ void scheduling::initTasks() {
} }
PeriodicTaskIF* tcsSystemTask = factory->createPeriodicTask( PeriodicTaskIF* tcsSystemTask = factory->createPeriodicTask(
"TCS_TASK", 55, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc); "TCS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc, &RR_SCHEDULING);
scheduling::scheduleRtdSensors(tcsSystemTask); scheduling::scheduleRtdSensors(tcsSystemTask);
result = tcsSystemTask->addComponent(objects::TCS_SUBSYSTEM); result = tcsSystemTask->addComponent(objects::TCS_SUBSYSTEM);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
@ -308,8 +319,9 @@ void scheduling::initTasks() {
#if OBSW_ADD_STAR_TRACKER == 1 #if OBSW_ADD_STAR_TRACKER == 1
// Relatively high priority to make sure STR COM works well. // Relatively high priority to make sure STR COM works well.
PeriodicTaskIF* strHelperTask = factory->createPeriodicTask( PeriodicTaskIF* strHelperTask =
"STR_HELPER", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); factory->createPeriodicTask("STR_HELPER", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2,
missedDeadlineFunc, &RR_SCHEDULING);
result = strHelperTask->addComponent(objects::STR_COM_IF); result = strHelperTask->addComponent(objects::STR_COM_IF);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("STR_HELPER", objects::STR_COM_IF); scheduling::printAddObjectError("STR_HELPER", objects::STR_COM_IF);
@ -317,8 +329,9 @@ void scheduling::initTasks() {
#endif /* OBSW_ADD_STAR_TRACKER == 1 */ #endif /* OBSW_ADD_STAR_TRACKER == 1 */
#if OBSW_ADD_PLOC_MPSOC == 1 #if OBSW_ADD_PLOC_MPSOC == 1
PeriodicTaskIF* mpsocHelperTask = factory->createPeriodicTask( PeriodicTaskIF* mpsocHelperTask =
"PLOC_MPSOC_HELPER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); factory->createPeriodicTask("PLOC_MPSOC_HELPER", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2,
missedDeadlineFunc);
result = mpsocHelperTask->addComponent(objects::PLOC_MPSOC_HELPER); result = mpsocHelperTask->addComponent(objects::PLOC_MPSOC_HELPER);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("PLOC_MPSOC_HELPER", objects::PLOC_MPSOC_HELPER); scheduling::printAddObjectError("PLOC_MPSOC_HELPER", objects::PLOC_MPSOC_HELPER);
@ -326,8 +339,9 @@ void scheduling::initTasks() {
#endif /* OBSW_ADD_PLOC_MPSOC */ #endif /* OBSW_ADD_PLOC_MPSOC */
#if OBSW_ADD_PLOC_SUPERVISOR == 1 #if OBSW_ADD_PLOC_SUPERVISOR == 1
PeriodicTaskIF* supvHelperTask = factory->createPeriodicTask( PeriodicTaskIF* supvHelperTask =
"PLOC_SUPV_HELPER", 10, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc); factory->createPeriodicTask("PLOC_SUPV_HELPER", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0,
missedDeadlineFunc);
result = supvHelperTask->addComponent(objects::PLOC_SUPERVISOR_HELPER); result = supvHelperTask->addComponent(objects::PLOC_SUPERVISOR_HELPER);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("PLOC_SUPV_HELPER", objects::PLOC_SUPERVISOR_HELPER); scheduling::printAddObjectError("PLOC_SUPV_HELPER", objects::PLOC_SUPERVISOR_HELPER);
@ -335,7 +349,7 @@ void scheduling::initTasks() {
#endif /* OBSW_ADD_PLOC_SUPERVISOR */ #endif /* OBSW_ADD_PLOC_SUPERVISOR */
PeriodicTaskIF* plTask = factory->createPeriodicTask( PeriodicTaskIF* plTask = factory->createPeriodicTask(
"PL_TASK", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc); "PL_TASK", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc, &RR_SCHEDULING);
plTask->addComponent(objects::CAM_SWITCHER); plTask->addComponent(objects::CAM_SWITCHER);
scheduling::addMpsocSupvHandlers(plTask); scheduling::addMpsocSupvHandlers(plTask);
scheduling::scheduleScexDev(plTask); scheduling::scheduleScexDev(plTask);
@ -456,8 +470,9 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction
#else #else
static constexpr float acsPstPeriod = 0.4; static constexpr float acsPstPeriod = 0.4;
#endif #endif
FixedTimeslotTaskIF* acsTcsPst = factory.createFixedTimeslotTask( FixedTimeslotTaskIF* acsTcsPst =
"ACS_TCS_PST", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, acsPstPeriod, missedDeadlineFunc); factory.createFixedTimeslotTask("ACS_TCS_PST", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2,
acsPstPeriod, missedDeadlineFunc, &RR_SCHEDULING);
result = pst::pstTcsAndAcs(acsTcsPst, cfg); result = pst::pstTcsAndAcs(acsTcsPst, cfg);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) { if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) {
@ -471,8 +486,9 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction
/* Polling Sequence Table Default */ /* Polling Sequence Table Default */
#if OBSW_ADD_SPI_TEST_CODE == 0 #if OBSW_ADD_SPI_TEST_CODE == 0
FixedTimeslotTaskIF* syrlinksPst = factory.createFixedTimeslotTask( FixedTimeslotTaskIF* syrlinksPst =
"SYRLINKS", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, missedDeadlineFunc); factory.createFixedTimeslotTask("SYRLINKS", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5,
missedDeadlineFunc, &RR_SCHEDULING);
result = pst::pstSyrlinks(syrlinksPst); result = pst::pstSyrlinks(syrlinksPst);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) { if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) {
@ -486,8 +502,9 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction
#endif #endif
#if OBSW_ADD_I2C_TEST_CODE == 0 #if OBSW_ADD_I2C_TEST_CODE == 0
FixedTimeslotTaskIF* i2cPst = factory.createFixedTimeslotTask( FixedTimeslotTaskIF* i2cPst =
"I2C_PST", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.4, missedDeadlineFunc); factory.createFixedTimeslotTask("I2C_PS_PST", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.6,
missedDeadlineFunc, &RR_SCHEDULING);
result = pst::pstI2cProcessingSystem(i2cPst); result = pst::pstI2cProcessingSystem(i2cPst);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) { if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) {
@ -500,8 +517,9 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction
} }
#endif #endif
FixedTimeslotTaskIF* gomSpacePstTask = factory.createFixedTimeslotTask( FixedTimeslotTaskIF* gomSpacePstTask =
"GS_PST_TASK", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, missedDeadlineFunc); factory.createFixedTimeslotTask("GS_PST_TASK", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4,
0.5, missedDeadlineFunc, &RR_SCHEDULING);
result = pst::pstGompaceCan(gomSpacePstTask); result = pst::pstGompaceCan(gomSpacePstTask);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
if (result != FixedTimeslotTaskIF::SLOT_LIST_EMPTY) { if (result != FixedTimeslotTaskIF::SLOT_LIST_EMPTY) {
@ -515,8 +533,9 @@ void scheduling::createPusTasks(TaskFactory& factory, TaskDeadlineMissedFunction
std::vector<PeriodicTaskIF*>& taskVec) { std::vector<PeriodicTaskIF*>& taskVec) {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
/* PUS Services */ /* PUS Services */
PeriodicTaskIF* pusHighPrio = factory.createPeriodicTask( PeriodicTaskIF* pusHighPrio =
"PUS_HIGH_PRIO", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); factory.createPeriodicTask("PUS_HIGH_PRIO", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2,
missedDeadlineFunc, &RR_SCHEDULING);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_1_VERIFICATION); result = pusHighPrio->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS_VERIF", objects::PUS_SERVICE_1_VERIFICATION); scheduling::printAddObjectError("PUS_VERIF", objects::PUS_SERVICE_1_VERIFICATION);
@ -535,8 +554,9 @@ void scheduling::createPusTasks(TaskFactory& factory, TaskDeadlineMissedFunction
} }
taskVec.push_back(pusHighPrio); taskVec.push_back(pusHighPrio);
PeriodicTaskIF* pusMedPrio = factory.createPeriodicTask( PeriodicTaskIF* pusMedPrio =
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc); factory.createPeriodicTask("PUS_MED_PRIO", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8,
missedDeadlineFunc, &RR_SCHEDULING);
result = pusMedPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING); result = pusMedPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS_3", objects::PUS_SERVICE_3_HOUSEKEEPING); scheduling::printAddObjectError("PUS_3", objects::PUS_SERVICE_3_HOUSEKEEPING);

View File

@ -1,5 +1,6 @@
#include <fsfw_hal/linux/uio/UioMapper.h> #include <fsfw_hal/linux/uio/UioMapper.h>
#include <linux/ipcore/PapbVcInterface.h> #include <linux/ipcore/PapbVcInterface.h>
#include <unistd.h>
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
@ -15,47 +16,67 @@ PapbVcInterface::~PapbVcInterface() {}
ReturnValue_t PapbVcInterface::initialize() { ReturnValue_t PapbVcInterface::initialize() {
UioMapper uioMapper(uioFile, mapNum); UioMapper uioMapper(uioFile, mapNum);
return uioMapper.getMappedAdress(&vcBaseReg, UioMapper::Permissions::WRITE_ONLY); uint32_t* baseReg;
ReturnValue_t result = uioMapper.getMappedAdress(&baseReg, UioMapper::Permissions::WRITE_ONLY);
if (result != returnvalue::OK) {
return result;
}
vcBaseReg = baseReg;
return returnvalue::OK;
} }
ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) { ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
if (pollPapbBusySignal() == returnvalue::OK) { if (pollPapbBusySignal(0, 0) == returnvalue::OK) {
startPacketTransfer(); startPacketTransfer();
} else {
return DirectTmSinkIF::IS_BUSY;
} }
for (size_t idx = 0; idx < size; idx++) { for (size_t idx = 0; idx < size; idx++) {
if (pollPapbBusySignal() == returnvalue::OK) { if (pollPapbBusySignal(10, 10) == returnvalue::OK) {
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(*(data + idx)); *(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
} else { } else {
sif::warning << "PapbVcInterface::write: Only written " << idx << " of " << size << " data" abortPacketTransfer();
<< std::endl;
return returnvalue::FAILED; return returnvalue::FAILED;
} }
} }
if (pollPapbBusySignal() == returnvalue::OK) { if (pollPapbBusySignal(10, 10) == returnvalue::OK) {
endPacketTransfer(); completePacketTransfer();
} else {
abortPacketTransfer();
return returnvalue::FAILED;
} }
return returnvalue::OK; return returnvalue::OK;
} }
void PapbVcInterface::startPacketTransfer() { *vcBaseReg = CONFIG_START; } void PapbVcInterface::startPacketTransfer() { *vcBaseReg = CONFIG_START; }
void PapbVcInterface::endPacketTransfer() { *vcBaseReg = CONFIG_END; } void PapbVcInterface::completePacketTransfer() { *vcBaseReg = CONFIG_END; }
ReturnValue_t PapbVcInterface::pollPapbBusySignal() const { ReturnValue_t PapbVcInterface::pollPapbBusySignal(uint32_t maxPollRetries,
uint32_t retryDelayUs) const {
gpio::Levels papbBusyState = gpio::Levels::LOW; gpio::Levels papbBusyState = gpio::Levels::LOW;
ReturnValue_t result = returnvalue::OK; ReturnValue_t result;
uint32_t busyIdx = 0;
/** Check if PAPB interface is ready to receive data */ while (true) {
result = gpioComIF->readGpio(papbBusyId, papbBusyState); /** Check if PAPB interface is ready to receive data */
if (result != returnvalue::OK) { result = gpioComIF->readGpio(papbBusyId, papbBusyState);
sif::warning << "PapbVcInterface::pollPapbBusySignal: Failed to read papb busy signal" if (result != returnvalue::OK) {
<< std::endl; sif::warning << "PapbVcInterface::pollPapbBusySignal: Failed to read papb busy signal"
return returnvalue::FAILED; << std::endl;
} return returnvalue::FAILED;
if (papbBusyState == gpio::Levels::LOW) { }
return PAPB_BUSY; if (papbBusyState == gpio::Levels::HIGH) {
} return returnvalue::OK;
}
busyIdx++;
if (busyIdx >= maxPollRetries) {
return PAPB_BUSY;
}
usleep(retryDelayUs);
}
return returnvalue::OK; return returnvalue::OK;
} }
@ -79,7 +100,9 @@ void PapbVcInterface::isVcInterfaceBufferEmpty() {
return; return;
} }
bool PapbVcInterface::isBusy() const { return pollPapbBusySignal() == PAPB_BUSY; } bool PapbVcInterface::isBusy() const { return pollPapbBusySignal(0, 0) == PAPB_BUSY; }
void PapbVcInterface::cancelTransfer() { abortPacketTransfer(); }
ReturnValue_t PapbVcInterface::sendTestFrame() { ReturnValue_t PapbVcInterface::sendTestFrame() {
/** Size of one complete transfer frame data field amounts to 1105 bytes */ /** Size of one complete transfer frame data field amounts to 1105 bytes */
@ -97,3 +120,5 @@ ReturnValue_t PapbVcInterface::sendTestFrame() {
return returnvalue::OK; return returnvalue::OK;
} }
void PapbVcInterface::abortPacketTransfer() { *vcBaseReg = CONFIG_ABORT; }

View File

@ -41,6 +41,8 @@ class PapbVcInterface : public VirtualChannelIF {
*/ */
ReturnValue_t write(const uint8_t* data, size_t size) override; ReturnValue_t write(const uint8_t* data, size_t size) override;
void cancelTransfer() override;
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
private: private:
@ -51,16 +53,21 @@ class PapbVcInterface : public VirtualChannelIF {
/** /**
* Configuration bits: * Configuration bits:
* bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00 * bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00
* bit[2]: Set this bit to 1 to abort a transfered packet * bit[2]: Set this bit to 1 to abort a transferred packet
* bit[3]: Signals to VcInterface the start of a new telemetry packet * bit[3]: Signals to VcInterface the start of a new telemetry packet
*/ */
static const uint32_t CONFIG_START = 0x8; static constexpr uint32_t CONFIG_START = 0b00001000;
/**
* Abort a transferred packet.
*/
static constexpr uint32_t CONFIG_ABORT = 0b00000100;
/** /**
* Writing this word to the VcInterface base address signals to the virtual channel interface * Writing this word to the VcInterface base address signals to the virtual channel interface
* that a complete tm packet has been transferred. * that a complete tm packet has been transferred.
*/ */
static const uint32_t CONFIG_END = 0x0; static constexpr uint32_t CONFIG_END = 0x0;
/** /**
* Writing to this offset within the memory space of a virtual channel will insert data for * Writing to this offset within the memory space of a virtual channel will insert data for
@ -79,7 +86,7 @@ class PapbVcInterface : public VirtualChannelIF {
std::string uioFile; std::string uioFile;
int mapNum = 0; int mapNum = 0;
uint32_t* vcBaseReg = nullptr; volatile uint32_t* vcBaseReg = nullptr;
uint32_t vcOffset = 0; uint32_t vcOffset = 0;
@ -89,11 +96,13 @@ class PapbVcInterface : public VirtualChannelIF {
*/ */
void startPacketTransfer(); void startPacketTransfer();
void abortPacketTransfer();
/** /**
* @brief This function sends the config byte to the virtual channel interface of the PTME * @brief This function sends the config byte to the virtual channel interface of the PTME
* IP Core to signal the end of a packet transfer. * IP Core to signal the end of a packet transfer.
*/ */
void endPacketTransfer(); void completePacketTransfer();
/** /**
* @brief This function reads the papb busy signal indicating whether the virtual channel * @brief This function reads the papb busy signal indicating whether the virtual channel
@ -102,7 +111,7 @@ class PapbVcInterface : public VirtualChannelIF {
* *
* @return returnvalue::OK when ready to receive data else PAPB_BUSY. * @return returnvalue::OK when ready to receive data else PAPB_BUSY.
*/ */
ReturnValue_t pollPapbBusySignal() const; ReturnValue_t pollPapbBusySignal(uint32_t maxPollRetries, uint32_t retryDelayUs) const;
/** /**
* @brief This function can be used for debugging to check whether there are packets in * @brief This function can be used for debugging to check whether there are packets in

View File

@ -20,7 +20,6 @@ ReturnValue_t Ptme::initialize() {
} }
ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t* data, size_t size) { ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t* data, size_t size) {
ReturnValue_t result = returnvalue::OK;
VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId); VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId);
if (vcInterfaceMapIter == vcInterfaceMap.end()) { if (vcInterfaceMapIter == vcInterfaceMap.end()) {
sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual " sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual "
@ -28,8 +27,7 @@ ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t* data, size_t size) {
<< static_cast<unsigned int>(vcId) << std::endl; << static_cast<unsigned int>(vcId) << std::endl;
return UNKNOWN_VC_ID; return UNKNOWN_VC_ID;
} }
result = vcInterfaceMapIter->second->write(data, size); return vcInterfaceMapIter->second->write(data, size);
return result;
} }
void Ptme::addVcInterface(VcId_t vcId, VirtualChannelIF* vc) { void Ptme::addVcInterface(VcId_t vcId, VirtualChannelIF* vc) {
@ -62,3 +60,11 @@ bool Ptme::isBusy(uint8_t vcId) const {
} }
return vcInterfaceMapIter->second->isBusy(); return vcInterfaceMapIter->second->isBusy();
} }
void Ptme::cancelTransfer(uint8_t vcId) {
VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId);
if (vcInterfaceMapIter == vcInterfaceMap.end()) {
return;
}
return vcInterfaceMapIter->second->cancelTransfer();
}

View File

@ -36,6 +36,7 @@ class Ptme : public PtmeIF, public SystemObject {
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) override; ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) override;
bool isBusy(uint8_t vcId) const override; bool isBusy(uint8_t vcId) const override;
void cancelTransfer(uint8_t vcId) override;
/** /**
* @brief This function adds the reference to a virtual channel interface to the vcInterface * @brief This function adds the reference to a virtual channel interface to the vcInterface

View File

@ -23,6 +23,7 @@ class PtmeIF {
*/ */
virtual ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) = 0; virtual ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) = 0;
virtual bool isBusy(uint8_t vcId) const = 0; virtual bool isBusy(uint8_t vcId) const = 0;
virtual void cancelTransfer(uint8_t vcId) = 0;
}; };
#endif /* LINUX_OBC_PTMEIF_H_ */ #endif /* LINUX_OBC_PTMEIF_H_ */

View File

@ -18,6 +18,7 @@ class VirtualChannelIF : public DirectTmSinkIF {
virtual ~VirtualChannelIF(){}; virtual ~VirtualChannelIF(){};
virtual ReturnValue_t initialize() = 0; virtual ReturnValue_t initialize() = 0;
virtual void cancelTransfer() = 0;
}; };
#endif /* LINUX_OBC_VCINTERFACEIF_H_ */ #endif /* LINUX_OBC_VCINTERFACEIF_H_ */

View File

@ -8,6 +8,9 @@
#include "ObjectFactory.h" #include "ObjectFactory.h"
#include "eive/objects.h" #include "eive/objects.h"
PosixThreadArgs scheduling::RR_SCHEDULING = {.policy = SchedulingPolicy::RR};
PosixThreadArgs scheduling::NORMAL_SCHEDULING;
void scheduling::scheduleScexReader(TaskFactory& factory, PeriodicTaskIF*& scexReaderTask) { void scheduling::scheduleScexReader(TaskFactory& factory, PeriodicTaskIF*& scexReaderTask) {
using namespace scheduling; using namespace scheduling;
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
@ -18,8 +21,9 @@ void scheduling::scheduleScexReader(TaskFactory& factory, PeriodicTaskIF*& scexR
#endif #endif
result = returnvalue::OK; result = returnvalue::OK;
scexReaderTask = factory.createPeriodicTask( scexReaderTask =
"SCEX_UART_READER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc); factory.createPeriodicTask("SCEX_UART_READER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0,
missedDeadlineFunc, &NORMAL_SCHEDULING);
result = scexReaderTask->addComponent(objects::SCEX_UART_READER); result = scexReaderTask->addComponent(objects::SCEX_UART_READER);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
printAddObjectError("SCEX_UART_READER", objects::SCEX_UART_READER); printAddObjectError("SCEX_UART_READER", objects::SCEX_UART_READER);

View File

@ -1,8 +1,13 @@
#pragma once #pragma once
#include <fsfw/osal/linux/PosixThread.h>
#include <fsfw/tasks/TaskFactory.h> #include <fsfw/tasks/TaskFactory.h>
namespace scheduling { namespace scheduling {
extern PosixThreadArgs RR_SCHEDULING;
extern PosixThreadArgs NORMAL_SCHEDULING;
void scheduleScexDev(PeriodicTaskIF*& scexDevHandler); void scheduleScexDev(PeriodicTaskIF*& scexDevHandler);
void scheduleScexReader(TaskFactory& factory, PeriodicTaskIF*& scexReaderTask); void scheduleScexReader(TaskFactory& factory, PeriodicTaskIF*& scexReaderTask);
void addMpsocSupvHandlers(PeriodicTaskIF* task); void addMpsocSupvHandlers(PeriodicTaskIF* task);

View File

@ -206,6 +206,8 @@ ReturnValue_t CcsdsIpCoreHandler::executeAction(ActionId_t actionId, MessageQueu
void CcsdsIpCoreHandler::updateLinkState() { linkState = LINK_UP; } void CcsdsIpCoreHandler::updateLinkState() { linkState = LINK_UP; }
void CcsdsIpCoreHandler::enableTransmit() { void CcsdsIpCoreHandler::enableTransmit() {
// Reset PTME on each transmit enable.
updateBatPriorityFromParam();
#ifndef TE0720_1CFA #ifndef TE0720_1CFA
gpioIF->pullHigh(ptmeGpios.enableTxClock); gpioIF->pullHigh(ptmeGpios.enableTxClock);
gpioIF->pullHigh(ptmeGpios.enableTxData); gpioIF->pullHigh(ptmeGpios.enableTxData);

View File

@ -153,7 +153,7 @@ class CcsdsIpCoreHandler : public SystemObject,
PtmeConfig& ptmeConfig; PtmeConfig& ptmeConfig;
PtmeGpios ptmeGpios; PtmeGpios ptmeGpios;
// BAT priority bit on by default to enable priority selection mode for the PTME. // BAT priority bit on by default to enable priority selection mode for the PTME.
uint8_t batPriorityParam = 1; uint8_t batPriorityParam = 0;
bool updateBatPriorityOnTxOff = false; bool updateBatPriorityOnTxOff = false;
GpioIF* gpioIF = nullptr; GpioIF* gpioIF = nullptr;

View File

@ -11,6 +11,9 @@ ReturnValue_t LiveTmTask::performOperation(uint8_t opCode) {
while (true) { while (true) {
// The funnel tasks are scheduled here directly as well. // The funnel tasks are scheduled here directly as well.
ReturnValue_t result = channel.sendNextTm(); ReturnValue_t result = channel.sendNextTm();
if (result == DirectTmSinkIF::IS_BUSY) {
sif::error << "Lost live TM, PAPB busy" << std::endl;
}
if (result == MessageQueueIF::EMPTY) { if (result == MessageQueueIF::EMPTY) {
if (tmFunnelCd.hasTimedOut()) { if (tmFunnelCd.hasTimedOut()) {
pusFunnel.performOperation(0); pusFunnel.performOperation(0);

View File

@ -13,26 +13,32 @@ PersistentLogTmStoreTask::PersistentLogTmStoreTask(object_id_t objectId, Storage
miscStoreContext(persTmStore::DUMP_MISC_STORE_DONE) {} miscStoreContext(persTmStore::DUMP_MISC_STORE_DONE) {}
ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) { ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) {
bool someonesBusy = false;
auto stateHandlingForStore = [&](bool storeIsBusy) {
if (storeIsBusy) {
someonesBusy = true;
}
if (fileHasSwapped) {
someFileWasSwapped = fileHasSwapped;
}
};
while (true) { while (true) {
if (not cyclicStoreCheck()) { if (not cyclicStoreCheck()) {
continue; continue;
} }
bool someonesBusy = false; someonesBusy = false;
bool busy = false; someFileWasSwapped = false;
busy = handleOneStore(stores.okStore, okStoreContext); stateHandlingForStore(handleOneStore(stores.okStore, okStoreContext));
if (busy) { stateHandlingForStore(handleOneStore(stores.notOkStore, notOkStoreContext));
someonesBusy = true; stateHandlingForStore(handleOneStore(stores.miscStore, miscStoreContext));
}
busy = handleOneStore(stores.notOkStore, notOkStoreContext);
if (busy) {
someonesBusy = true;
}
busy = handleOneStore(stores.miscStore, miscStoreContext);
if (busy) {
someonesBusy = true;
}
if (not someonesBusy) { if (not someonesBusy) {
TaskFactory::delayTask(40); TaskFactory::delayTask(100);
} else /* and graceDelayDuringDumping.hasTimedOut()*/ {
if (someFileWasSwapped) {
TaskFactory::delayTask(20);
}
// TaskFactory::delayTask(2);
// graceDelayDuringDumping.resetTimer();
} }
} }
} }

View File

@ -32,6 +32,8 @@ class PersistentLogTmStoreTask : public TmStoreTaskBase, public ExecutableObject
DumpContext notOkStoreContext; DumpContext notOkStoreContext;
DumpContext miscStoreContext; DumpContext miscStoreContext;
Countdown tcHandlingCd = Countdown(400); Countdown tcHandlingCd = Countdown(400);
Countdown graceDelayDuringDumping = Countdown(200);
bool someFileWasSwapped = false;
bool initStoresIfPossible(); bool initStoresIfPossible();
}; };

View File

@ -17,7 +17,15 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) {
} }
bool busy = handleOneStore(storeWithQueue, dumpContext); bool busy = handleOneStore(storeWithQueue, dumpContext);
if (not busy) { if (not busy) {
TaskFactory::delayTask(40); TaskFactory::delayTask(100);
} else {
if (fileHasSwapped) {
TaskFactory::delayTask(20);
}
// if (fileHasSwapped and graceDelayDuringDumping.hasTimedOut()) {
// TaskFactory::delayTask(2);
// graceDelayDuringDumping.resetTimer();
// }
} }
} }
} }

View File

@ -19,6 +19,7 @@ class PersistentSingleTmStoreTask : public TmStoreTaskBase, public ExecutableObj
PersistentTmStoreWithTmQueue& storeWithQueue; PersistentTmStoreWithTmQueue& storeWithQueue;
DumpContext dumpContext; DumpContext dumpContext;
Countdown tcHandlingCd = Countdown(400); Countdown tcHandlingCd = Countdown(400);
Countdown graceDelayDuringDumping = Countdown(100);
bool initStoresIfPossible(); bool initStoresIfPossible();
}; };

View File

@ -195,11 +195,7 @@ ReturnValue_t PersistentTmStore::startDumpFromUpTo(uint32_t fromUnixSeconds,
dumpParams.fromUnixTime = fromUnixSeconds; dumpParams.fromUnixTime = fromUnixSeconds;
dumpParams.untilUnixTime = upToUnixSeconds; dumpParams.untilUnixTime = upToUnixSeconds;
state = State::DUMPING; state = State::DUMPING;
if (loadNextDumpFile() == DUMP_DONE) { return loadNextDumpFile();
// State will be set inside the function loading the next file.
return DUMP_DONE;
}
return returnvalue::OK;
} }
ReturnValue_t PersistentTmStore::loadNextDumpFile() { ReturnValue_t PersistentTmStore::loadNextDumpFile() {
@ -218,7 +214,7 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() {
} }
sif::debug << "Path: " << dumpParams.dirEntry.path() << std::endl; sif::debug << "Path: " << dumpParams.dirEntry.path() << std::endl;
// Can't even read CCSDS header. // File empty or can't even read CCSDS header.
if (dumpParams.fileSize <= 6) { if (dumpParams.fileSize <= 6) {
continue; continue;
} }
@ -247,14 +243,12 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() {
static_cast<std::streamsize>(dumpParams.fileSize)); static_cast<std::streamsize>(dumpParams.fileSize));
// Increment iterator for next cycle. // Increment iterator for next cycle.
dumpParams.dirIter++; dumpParams.dirIter++;
break; return returnvalue::OK;
} }
} }
if (dumpParams.dirIter == directory_iterator()) { // Directory iterator was consumed and we are done.
state = State::IDLE; state = State::IDLE;
return DUMP_DONE; return DUMP_DONE;
}
return returnvalue::OK;
} }
ReturnValue_t PersistentTmStore::dumpNextPacket(DirectTmSinkIF& tmSink, size_t& dumpedLen, ReturnValue_t PersistentTmStore::dumpNextPacket(DirectTmSinkIF& tmSink, size_t& dumpedLen,

View File

@ -25,10 +25,12 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store,
// Dump TMs when applicable // Dump TMs when applicable
if (store.getState() == PersistentTmStore::State::DUMPING) { if (store.getState() == PersistentTmStore::State::DUMPING) {
size_t dumpedLen = 0; size_t dumpedLen = 0;
bool fileHasSwapped;
if (not channel.isBusy()) { if (not channel.isBusy()) {
tmSinkBusyCd.resetTimer(); tmSinkBusyCd.resetTimer();
result = store.dumpNextPacket(channel, dumpedLen, fileHasSwapped); result = store.dumpNextPacket(channel, dumpedLen, fileHasSwapped);
if (result == DirectTmSinkIF::IS_BUSY) {
sif::warning << "Unexpected PAPB busy" << std::endl;
}
if ((result == PersistentTmStore::DUMP_DONE or result == returnvalue::OK) and dumpedLen > 0) { if ((result == PersistentTmStore::DUMP_DONE or result == returnvalue::OK) and dumpedLen > 0) {
dumpContext.dumpedBytes += dumpedLen; dumpContext.dumpedBytes += dumpedLen;
dumpContext.numberOfDumpedPackets += 1; dumpContext.numberOfDumpedPackets += 1;
@ -43,6 +45,13 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store,
} else if (result == returnvalue::OK) { } else if (result == returnvalue::OK) {
dumpsPerformed = true; dumpsPerformed = true;
} }
} else {
dumpContext.ptmeBusyCounter++;
if (dumpContext.ptmeBusyCounter == 50) {
sif::warning << "PTME busy for longer period. Dumped length so far: "
<< dumpContext.dumpedBytes << std::endl;
dumpContext.ptmeBusyCounter = 0;
}
} }
if (cancelDumpCd.hasTimedOut() or tmSinkBusyCd.hasTimedOut()) { if (cancelDumpCd.hasTimedOut() or tmSinkBusyCd.hasTimedOut()) {
triggerEvent(persTmStore::DUMP_WAS_CANCELLED, store.getObjectId()); triggerEvent(persTmStore::DUMP_WAS_CANCELLED, store.getObjectId());

View File

@ -16,6 +16,7 @@ class TmStoreTaskBase : public SystemObject {
const Event eventIfDone; const Event eventIfDone;
uint32_t numberOfDumpedPackets = 0; uint32_t numberOfDumpedPackets = 0;
uint32_t dumpedBytes = 0; uint32_t dumpedBytes = 0;
uint32_t ptmeBusyCounter = 0;
}; };
TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore, VirtualChannel& channel, TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore, VirtualChannel& channel,
@ -45,6 +46,7 @@ class TmStoreTaskBase : public SystemObject {
Countdown tmSinkBusyCd = Countdown(60 * 1000); Countdown tmSinkBusyCd = Countdown(60 * 1000);
VirtualChannel& channel; VirtualChannel& channel;
bool storesInitialized = false; bool storesInitialized = false;
bool fileHasSwapped = false;
SdCardMountedIF& sdcMan; SdCardMountedIF& sdcMan;
}; };

View File

@ -25,4 +25,12 @@ uint8_t VirtualChannel::getVcid() const { return vcId; }
const char* VirtualChannel::getName() const { return vcName.c_str(); } const char* VirtualChannel::getName() const { return vcName.c_str(); }
bool VirtualChannel::isBusy() const { return ptme.isBusy(vcId); } bool VirtualChannel::isBusy() const {
// Data is discarded, so channel is not busy.
if (linkStateProvider.load()) {
return false;
}
return ptme.isBusy(vcId);
}
void VirtualChannel::cancelTransfer() { ptme.cancelTransfer(vcId); }

View File

@ -28,6 +28,7 @@ class VirtualChannel : public SystemObject, public VirtualChannelIF {
ReturnValue_t sendNextTm(const uint8_t* data, size_t size); ReturnValue_t sendNextTm(const uint8_t* data, size_t size);
bool isBusy() const override; bool isBusy() const override;
ReturnValue_t write(const uint8_t* data, size_t size) override; ReturnValue_t write(const uint8_t* data, size_t size) override;
void cancelTransfer() override;
uint8_t getVcid() const; uint8_t getVcid() const;
const char* getName() const; const char* getName() const;

View File

@ -36,7 +36,10 @@ ReturnValue_t VirtualChannelWithQueue::sendNextTm() {
return result; return result;
} }
write(data, size); result = write(data, size);
if (result != returnvalue::OK) {
return result;
}
tmStore.deleteData(storeId); tmStore.deleteData(storeId);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;