1
0
Fork 0

Better organize CO_EM_RPDO_TIME_OUT detection. #618, #626

Move RPDO related code from CANopen.c into PDO.c, remove additional for loop.
Introduce new optional argument bool_t* timeoutState into CO_RPDO_process().
This commit is contained in:
Janez 2026-07-10 16:17:46 +02:00
parent 5a97d2d209
commit 9b8beed836
3 changed files with 14 additions and 16 deletions

View file

@ -741,7 +741,7 @@ CO_RPDO_initCallbackPre(CO_RPDO_t* RPDO, void* object, void (*pFunctSignalPre)(v
void
CO_RPDO_process(CO_RPDO_t* RPDO,
#if ((CO_CONFIG_PDO)&CO_CONFIG_RPDO_TIMERS_ENABLE) != 0
uint32_t timeDifference_us, uint32_t* timerNext_us,
uint32_t timeDifference_us, bool_t* timeoutState, uint32_t* timerNext_us,
#endif
bool_t NMTisOperational, bool_t syncWas) {
(void)syncWas;
@ -890,11 +890,6 @@ CO_RPDO_process(CO_RPDO_t* RPDO,
#if ((CO_CONFIG_PDO)&CO_CONFIG_RPDO_TIMERS_ENABLE) != 0
if (RPDO->timeoutTime_us > 0U) {
if (rpdoReceived) {
/* Do NOT call CO_errorReset here. CO_EM_RPDO_TIME_OUT is a
* single shared bit for all RPDOs. Resetting it when one RPDO
* recovers would clear the error even if other RPDOs are still
* timed out. The reset is handled in CO_process_RPDO() after
* all RPDOs are processed, only when none remain in timeout. */
/* enable monitoring */
RPDO->timeoutTimer = 1;
} else if ((RPDO->timeoutTimer > 0U) && (RPDO->timeoutTimer < RPDO->timeoutTime_us)) {
@ -905,6 +900,11 @@ CO_RPDO_process(CO_RPDO_t* RPDO,
}
} else { /* MISRA C 2004 14.10 */
}
if ((timeoutState != NULL) && RPDO->timeoutTimer > RPDO->timeoutTime_us) {
/* This output variable indicates that the RPDO has timed out. It can be used across all
* RPDOs to determine if any have timed out. If it remains false, CO_errorReset can be called. */
*timeoutState = true;
}
#if ((CO_CONFIG_PDO)&CO_CONFIG_FLAG_TIMERNEXT) != 0
if ((timerNext_us != NULL) && (RPDO->timeoutTimer < RPDO->timeoutTime_us)) {
uint32_t diff = RPDO->timeoutTime_us - RPDO->timeoutTimer;

View file

@ -278,13 +278,16 @@ void CO_RPDO_initCallbackPre(CO_RPDO_t* RPDO, void* object, void (*pFunctSignalP
*
* @param RPDO This object.
* @param timeDifference_us Time difference from previous function call.
* @param [out] timeoutState Pointer to a boolean variable that will be set to true if a RPDO has timed out.
* It can be used across all RPDOs to determine if any have timed out. If it remains false, CO_errorReset should be
* called. Can be NULL if not needed.
* @param [out] timerNext_us info to OS - see CO_process().
* @param NMTisOperational True if this node is in NMT_OPERATIONAL state.
* @param syncWas True, if CANopen SYNC message was just received or transmitted.
*/
void CO_RPDO_process(CO_RPDO_t* RPDO,
#if (((CO_CONFIG_PDO)&CO_CONFIG_RPDO_TIMERS_ENABLE) != 0) || defined CO_DOXYGEN
uint32_t timeDifference_us, uint32_t* timerNext_us,
uint32_t timeDifference_us, bool_t* timeoutState, uint32_t* timerNext_us,
#endif
bool_t NMTisOperational, bool_t syncWas);
#endif /* (CO_CONFIG_PDO) & CO_CONFIG_RPDO_ENABLE */

View file

@ -1439,11 +1439,14 @@ CO_process_RPDO(CO_t* co, bool_t syncWas, uint32_t timeDifference_us, uint32_t*
}
bool_t NMTisOperational = CO_NMT_getInternalState(co->NMT) == CO_NMT_OPERATIONAL;
#if ((CO_CONFIG_PDO)&CO_CONFIG_RPDO_TIMERS_ENABLE) != 0
bool_t anyTimeout = false;
#endif
for (uint16_t i = 0; i < CO_GET_CNT(RPDO); i++) {
CO_RPDO_process(&co->RPDO[i],
#if ((CO_CONFIG_PDO)&CO_CONFIG_RPDO_TIMERS_ENABLE) != 0
timeDifference_us, timerNext_us,
timeDifference_us, &anyTimeout, timerNext_us,
#endif
NMTisOperational, syncWas);
}
@ -1452,14 +1455,6 @@ CO_process_RPDO(CO_t* co, bool_t syncWas, uint32_t timeDifference_us, uint32_t*
/* CO_EM_RPDO_TIME_OUT is a single shared bit for all RPDOs. Only reset it
* after processing all RPDOs, and only when none remain in timeout.
* CO_errorReset() is a no-op when the error bit is already clear. */
bool_t anyTimeout = false;
for (uint16_t i = 0; i < CO_GET_CNT(RPDO); i++) {
CO_RPDO_t* rpdo = &co->RPDO[i];
if (rpdo->timeoutTime_us > 0U && rpdo->timeoutTimer > rpdo->timeoutTime_us) {
anyTimeout = true;
break;
}
}
if (!anyTimeout) {
CO_errorReset(co->em, CO_EM_RPDO_TIME_OUT, 0);
}