Index: Sources/Kernel/rX_Tim.c =================================================================== --- Sources/Kernel/rX_Tim.c (revision 2172) +++ Sources/Kernel/rX_Tim.c (working copy) @@ -97,12 +97,15 @@ if (ptOldTimer->bOpt == RX_TIM_AUTO_RELOAD) { - UINT uNewSpoke; - /* Recalculate new position of timer in wheel */ - ptOldTimer->ulMatch = ptOldTimer->ulPeriod + ulTimeTickToProcess; - uNewSpoke = ptOldTimer->ulMatch & s_uWheelModMask; - /* Reinsert timer into wheel */ - TAILQ_INSERT_TAIL(&s_patTimerWheelTbl[uNewSpoke], ptOldTimer, tTimerList); + if (0 != ptOldTimer->ulPeriod) { + UINT uNewSpoke; + /* Recalculate new position of timer in wheel */ + ptOldTimer->ulMatch = ptOldTimer->ulPeriod + ulTimeTickToProcess; + uNewSpoke = ptOldTimer->ulMatch & s_uWheelModMask; + /* Reinsert timer into wheel */ + TAILQ_INSERT_TAIL(&s_patTimerWheelTbl[uNewSpoke], ptOldTimer, tTimerList); + } else + ptOldTimer->bState = RX_TIMER_STATE_STOPPED; } else { /* Remove timer from wheel and indicate that the timer has completed */ Index: Tests/Kernel/Timer/TimerInfiniteLoopTest.c =================================================================== --- Tests/Kernel/Timer/TimerInfiniteLoopTest.c (revision 0) +++ Tests/Kernel/Timer/TimerInfiniteLoopTest.c (working copy) @@ -0,0 +1,75 @@ +#include "TLR_Includes.h" +#include "rX_Testcase.h" + +/* Two timers started at the same time can cause an infinite loop + * within the rXTimerTask, if their ulPeriod value is reset to 0. + * Resetting ulPeriod to 0 causes + * - ulMatch to never change + * - uSpoke & uNewSpoke to never change + * The timers will stay in the same timer slot/list and will get + * iterated over and over again. + */ + +#define TIMER_COUNT 2 + +static RX_HANDLE s_hTimer[TIMER_COUNT]; + +/* Forward declarations */ +static void TimerInfiniteLoopTest(void* pvParam); + +static TESTCASE_TABLE_T s_atTestcase[] TESTCASE_SECTION_NAME(TimerInfiniteLoopTest)= +{ + { + .szTestcase = "Timer Infinite Loop Test", + .pfnTestcase = TimerInfiniteLoopTest, + .pvParam = NULL, + } +}; + +static void TimerFnc(void* pvParam) +{ + /* Reset ulPeriod to 0 */ + rX_TimSetReload(pvParam, 0); +} + +/** + * \b test_start + * + * Start timer test. + * + */ +static void TimerInfiniteLoopTest(void* pvParam) +{ + RX_RESULT eRslt = RX_OK; + int32_t iIdx; + + for (iIdx = 0; iIdx < TIMER_COUNT; iIdx++) + { + s_hTimer[iIdx] = LIB_MALLOC(RX_TIMER_SIZE); + TEST_ASSERT_NOT_NULL(s_hTimer[iIdx]); + + eRslt = rX_TimCreateTimer(s_hTimer[iIdx], TimerFnc, (void*)(s_hTimer[iIdx]), RX_TIM_AUTO_RELOAD, 5, 0); + TEST_ASSERT_EQUAL_UINT(RX_OK, eRslt); + } + + /* Timer needs to be started at the same time to share the same ulMatch/uSpoke values. + * Only then they will be put in the same timer wheel list/slot. */ + for (iIdx = 0; iIdx < TIMER_COUNT; iIdx++) + { + eRslt = rX_TimResumeTimer(s_hTimer[iIdx]); + TEST_ASSERT_EQUAL_UINT(RX_OK, eRslt); + } + + TLR_TSK_SLEEP(5000); + + for (iIdx = 0; iIdx < TIMER_COUNT; iIdx++) + { + eRslt = rX_TimStopTimer(s_hTimer[iIdx]); + TEST_ASSERT_EQUAL_UINT(RX_OK, eRslt); + + eRslt = rX_TimDeleteTimer(s_hTimer[iIdx]); + TEST_ASSERT_EQUAL_UINT(RX_OK, eRslt); + + LIB_FREE(s_hTimer[iIdx]); + } +}