@@ -52,6 +52,7 @@ static volatile bool NGDEF(hw_event_scheduled);
5252static volatile timer_tick_t NGDEF (timer_offset );
5353static const hwtimer_info_t * timer_info ;
5454static bool timer_busy_programming = false;
55+ static bool fired_by_interrupt = true;
5556enum
5657{
5758 NO_EVENT = FRAMEWORK_TIMER_STACK_SIZE ,
@@ -80,11 +81,12 @@ error_t timer_init_event(timer_event* event, task_t callback)
8081 event -> f = callback ;
8182 event -> arg = NULL ;
8283 event -> priority = MAX_PRIORITY ;
84+ event -> period = 0 ;
8385 return (sched_register_task (callback )); // register the function callback to be called at the end of the timeout
8486}
8587
8688static void configure_next_event ();
87- __LINK_C error_t timer_post_task_prio (task_t task , timer_tick_t fire_time , uint8_t priority , void * arg )
89+ __LINK_C error_t timer_post_task_prio (task_t task , timer_tick_t fire_time , uint8_t priority , timer_tick_t period , void * arg )
8890{
8991 error_t status = ENOMEM ;
9092 if (priority > MIN_PRIORITY )
@@ -111,6 +113,7 @@ __LINK_C error_t timer_post_task_prio(task_t task, timer_tick_t fire_time, uint8
111113 // it is allowed to update only the fire time
112114 if (NG (timers )[i ].priority == priority )
113115 {
116+ NG (timers )[i ].period = period ;
114117 NG (timers )[i ].next_event = fire_time ;
115118 goto config ;
116119 }
@@ -129,6 +132,7 @@ __LINK_C error_t timer_post_task_prio(task_t task, timer_tick_t fire_time, uint8
129132 NG (timers )[empty_index ].next_event = fire_time ;
130133 NG (timers )[empty_index ].priority = priority ;
131134 NG (timers )[empty_index ].arg = arg ;
135+ NG (timers )[empty_index ].period = period ;
132136 }
133137 else
134138 goto end ;
@@ -153,7 +157,7 @@ __LINK_C error_t timer_post_task_prio(task_t task, timer_tick_t fire_time, uint8
153157 DPRINT ("next_fire_delay <%lu>" , next_fire_delay );
154158
155159 int32_t old_fire_delay = ((int32_t )NG (timers )[NG (next_event )].next_event ) - ((int32_t )counter );
156- do_config = next_fire_delay < old_fire_delay ;
160+ do_config = ( next_fire_delay < old_fire_delay ) || NG ( next_event ) == empty_index ; //when same index is overwritten, also update
157161 }
158162
159163 if (do_config )
@@ -193,7 +197,7 @@ __LINK_C error_t timer_cancel_task(task_t task)
193197
194198error_t timer_add_event (timer_event * event )
195199{
196- return timer_post_task_prio (event -> f , timer_get_counter_value () + event -> next_event , event -> priority , event -> arg );
200+ return timer_post_task_prio (event -> f , timer_get_counter_value () + event -> next_event , event -> priority , event -> period , event -> arg );
197201}
198202
199203void timer_cancel_event (timer_event * event )
@@ -279,14 +283,22 @@ static void configure_next_event()
279283 next_fire_time = NG (timers )[NG (next_event )].next_event ;
280284 if ( (((int32_t )next_fire_time ) - ((int32_t )current_time ) - timer_info -> min_delay_ticks ) <= 0 )
281285 {
282- DPRINT ("will be late, sched immediately" );
283- sched_post_task_prio (NG (timers )[NG (next_event )].f , NG (timers )[NG (next_event )].priority , NG (timers )[NG (next_event )].arg );
284- NG (timers )[NG (next_event )].f = 0x0 ;
286+ DPRINT ("will be late, sched immediately\n\n" );
287+ if (NG (timers )[NG (next_event )].f == 0 )
288+ DPRINT ("function was empty, skipping" );
289+ else {
290+ fired_by_interrupt = false;
291+ timer_fired ();
292+ }
285293 }
286294 }
287295 }
288296 while (NG (next_event ) != NO_EVENT && ( (((int32_t )next_fire_time ) - ((int32_t )current_time ) - timer_info -> min_delay_ticks ) <= 0 ) );
289297
298+ // if recursive event was scheduled immediately, don't set hw timer delay until last time in configure next event
299+ if (!fired_by_interrupt )
300+ return ;
301+
290302 //at this point NG(next_event) is eiter equal to NO_EVENT (no tasks left)
291303 //or we have the next event we can schedule
292304 if (NG (next_event ) == NO_EVENT )
@@ -355,11 +367,21 @@ static void timer_overflow()
355367
356368static void timer_fired ()
357369{
358- if (timer_busy_programming )
370+ if (timer_busy_programming && fired_by_interrupt )
359371 return ;
360372 assert (NG (next_event ) != NO_EVENT );
361373 assert (NG (timers )[NG (next_event )].f != 0x0 );
362374 sched_post_task_prio (NG (timers )[NG (next_event )].f , NG (timers )[NG (next_event )].priority , NG (timers )[NG (next_event )].arg );
375+ if (NG (timers )[NG (next_event )].period > 0 ) {
376+ task_t recursive_task = NG (timers )[NG (next_event )].f ;
377+ NG (timers )[NG (next_event )].f = 0x0 ;
378+ timer_post_task_prio (recursive_task , timer_get_counter_value () + NG (timers )[NG (next_event )].period , NG (timers )[NG (next_event )].priority , NG (timers )[NG (next_event )].period , NG (timers )[NG (next_event )].arg );
379+ fired_by_interrupt = true;
380+ return ;
381+ }
363382 NG (timers )[NG (next_event )].f = 0x0 ;
364- configure_next_event ();
383+ if (fired_by_interrupt )
384+ configure_next_event ();
385+ else
386+ fired_by_interrupt = true;
365387}
0 commit comments