89 #define HW_TIMER_ADDITIONAL_CNT (1U)
96 typedef struct SYSTIMER_OBJECT
98 struct SYSTIMER_OBJECT *next;
99 struct SYSTIMER_OBJECT *prev;
113 SYSTIMER_OBJECT_t *g_timer_list = NULL;
116 uint32_t g_timer_tracker = 0U;
119 volatile uint32_t g_systick_count = 0U;
128 static void SYSTIMER_lInsertTimerList(uint32_t tbl_index);
133 static void SYSTIMER_lRemoveTimerList(uint32_t tbl_index);
138 static void SYSTIMER_lTimerHandler(
void);
144 void SysTick_Handler(
void);
149 __attribute__((always_inline)) __STATIC_INLINE uint32_t critical_section_enter(
void)
152 status = __get_PRIMASK();
157 __attribute__((always_inline)) __STATIC_INLINE
void critical_section_exit(uint32_t status)
159 __set_PRIMASK(status);
164 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
169 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
175 static void SYSTIMER_lInsertTimerList(uint32_t tbl_index)
177 SYSTIMER_OBJECT_t *object_ptr;
180 bool found_flag =
false;
183 timer_count = (int32_t)
g_timer_tbl[tbl_index].count;
185 if (NULL == g_timer_list)
193 object_ptr = g_timer_list;
195 delta_ticks = timer_count;
197 while ((NULL != object_ptr) && (
false == found_flag))
200 delta_ticks -= (int32_t)object_ptr->count;
202 if (delta_ticks <= 0)
205 if (NULL != object_ptr->prev)
227 if ((delta_ticks > 0) && (NULL == object_ptr->next))
232 g_timer_tbl[tbl_index].count = (uint32_t)delta_ticks;
237 object_ptr = object_ptr->next;
245 static void SYSTIMER_lRemoveTimerList(uint32_t tbl_index)
247 SYSTIMER_OBJECT_t *object_ptr;
251 if ((NULL == object_ptr->prev) && (NULL == object_ptr->next ))
257 else if (NULL == object_ptr->prev)
260 g_timer_list = object_ptr->next;
261 g_timer_list->prev = NULL;
262 g_timer_list->count += object_ptr->count;
263 object_ptr->next = NULL;
266 else if (NULL == object_ptr->next)
269 object_ptr->prev->next = NULL;
270 object_ptr->prev = NULL;
275 object_ptr->prev->next = object_ptr->next;
276 object_ptr->next->prev = object_ptr->prev;
277 object_ptr->next->count += object_ptr->count;
278 object_ptr->next = NULL;
279 object_ptr->prev = NULL;
287 static void SYSTIMER_lTimerHandler(
void)
289 SYSTIMER_OBJECT_t *object_ptr;
292 object_ptr = g_timer_list;
293 while ((NULL != object_ptr) && (0U == object_ptr->count))
301 SYSTIMER_lRemoveTimerList((uint32_t)object_ptr->id);
305 (object_ptr->callback)(object_ptr->args);
311 SYSTIMER_lRemoveTimerList((uint32_t)object_ptr->id);
313 object_ptr->count = object_ptr->reload;
315 SYSTIMER_lInsertTimerList((uint32_t)object_ptr->id);
317 (object_ptr->callback)(object_ptr->args);
321 object_ptr = g_timer_list;
329 void SysTick_Handler(
void)
331 SYSTIMER_OBJECT_t *object_ptr;
332 object_ptr = g_timer_list;
335 if (NULL != object_ptr)
337 if (object_ptr->count > 1UL)
343 object_ptr->count = 0U;
344 SYSTIMER_lTimerHandler();
358 DAVE_APP_VERSION_t version;
360 version.major = (uint8_t)SYSTIMER_MAJOR_VERSION;
361 version.minor = (uint8_t)SYSTIMER_MINOR_VERSION;
362 version.patch = (uint8_t)SYSTIMER_PATCH_VERSION;
374 XMC_ASSERT(
"SYSTIMER_Init: SYSTIMER APP handle pointer uninitialized", (handle != NULL));
384 status = (
SYSTIMER_STATUS_t)SysTick_Config((uint32_t)(SYSTIMER_SYSTICK_CLOCK * SYSTIMER_TICK_PERIOD));
388 XMC_DEBUG(
"SYSTIMER_Init: Timer reload value out of range");
392 #if (UC_FAMILY == XMC4)
394 NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(
395 NVIC_GetPriorityGrouping(), SYSTIMER_PRIORITY, SYSTIMER_SUBPRIORITY));
396 #elif (UC_FAMILY == XMC1)
398 NVIC_SetPriority(SysTick_IRQn, SYSTIMER_PRIORITY);
400 g_timer_tracker = 0U;
423 uint32_t period_ratio = 0U;
425 XMC_ASSERT(
"SYSTIMER_CreateTimer: Timer creation failure due to invalid period value",
426 ((period >= SYSTIMER_TICK_PERIOD_US) && (period > 0U) && (period <= 0xFFFFFFFFU)));
427 XMC_ASSERT(
"SYSTIMER_CreateTimer: Timer creation failure due to invalid timer mode",
429 XMC_ASSERT(
"SYSTIMER_CreateTimer: Can not create software without user callback", (NULL != callback));
431 if (period < SYSTIMER_TICK_PERIOD_US)
437 for (count = 0U; count < SYSTIMER_CFG_MAX_TMR; count++)
440 if (0U == (g_timer_tracker & (1U << count)))
443 g_timer_tracker |= (1U << count);
448 period_ratio = (uint32_t)(period / SYSTIMER_TICK_PERIOD_US);
449 g_timer_tbl[count].count = (period_ratio + HW_TIMER_ADDITIONAL_CNT);
476 ics = critical_section_enter();
480 critical_section_exit(ics);
494 XMC_ASSERT(
"SYSTIMER_StartTimer: Failure in timer restart operation due to invalid timer ID",
495 ((
id <= SYSTIMER_CFG_MAX_TMR) && (
id > 0U)));
496 XMC_ASSERT(
"SYSTIMER_StartTimer: Error during start of software timer", (0U != (g_timer_tracker & (1U << (
id - 1U)))));
505 SYSTIMER_lInsertTimerList((
id - 1U));
518 ics = critical_section_enter();
522 critical_section_exit(ics);
536 XMC_ASSERT(
"SYSTIMER_StopTimer: Failure in timer restart operation due to invalid timer ID",
537 ((
id <= SYSTIMER_CFG_MAX_TMR) && (
id > 0U)));
538 XMC_ASSERT(
"SYSTIMER_StopTimer: Error during stop of software timer", (0U != (g_timer_tracker & (1U << (
id - 1U)))));
551 SYSTIMER_lRemoveTimerList(
id - 1U);
563 ics = critical_section_enter();
567 critical_section_exit(ics);
577 uint32_t period_ratio = 0U;
582 XMC_ASSERT(
"SYSTIMER_RestartTimer: Failure in timer restart operation due to invalid timer ID",
583 ((
id <= SYSTIMER_CFG_MAX_TMR) && (
id > 0U)));
584 XMC_ASSERT(
"SYSTIMER_RestartTimer: Error during restart of software timer", (0U != (g_timer_tracker & (1U << (
id - 1U)))));
585 XMC_ASSERT(
"SYSTIMER_RestartTimer: Can not restart timer due to invalid period value",
586 (microsec >= SYSTIMER_TICK_PERIOD_US) && (microsec > 0U));
603 period_ratio = (uint32_t)(microsec / SYSTIMER_TICK_PERIOD_US);
618 ics = critical_section_enter();
622 critical_section_exit(ics);
636 XMC_ASSERT(
"SYSTIMER_DeleteTimer: Failure in timer restart operation due to invalid timer ID",
637 ((
id <= SYSTIMER_CFG_MAX_TMR) && (
id > 0U)));
638 XMC_ASSERT(
"SYSTIMER_DeleteTimer: Error during deletion of software timer", (0U != (g_timer_tracker & (1U << (
id - 1U)))));
652 g_timer_tracker &= ~(1U << (
id - 1U));
664 ics = critical_section_enter();
668 critical_section_exit(ics);
678 return (g_systick_count * SYSTIMER_TICK_PERIOD_US);
686 return (g_systick_count);