- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/modules/ke/src/ke_timer.c

Go to the documentation of this file.

    00001
    00021 /*
    00022  * INCLUDE FILES
    00023  ****************************************************************************************
    00024  */
    00025 #include <stddef.h>
    00026 #include "co_int.h"
    00027 #include "co_bool.h"
    00028 #include "dbg_assert.h"
    00029
    00030 #include "ke_config.h"
    00031 #include "ke_mem.h"
    00032 #include "ke_env.h"
    00033 #include "ke_event.h"
    00034 #include "ke_timer.h"
    00035 #include "ke_task.h"
    00036 #include "dbg.h"
    00037
    00038 #include "hal_machw.h"
    00039
    00040
    00048 static void ke_timer_hw_set(struct ke_timer *timer)
    00049 {
    00050     GLOBAL_INT_DISABLE();
    00051     if (timer)
    00052     {
    00053         uint32_t timer_msk;
    00054
    00055         // set the abs timeout in HW
    00056         nxmac_abs_timer_set(HAL_KE_TIMER, timer->time);
    00057
    00058         // enable timer irq
    00059         timer_msk = nxmac_timers_int_un_mask_get();
    00060         if (!(timer_msk & HAL_KE_TIMER_BIT))
    00061         {
    00062             // if timer is not enabled, it is possible that the irq is raised
    00063             // due to a spurious value, so ack it before
    00064             nxmac_timers_int_event_clear(HAL_KE_TIMER_BIT);
    00065             nxmac_timers_int_un_mask_set(timer_msk | HAL_KE_TIMER_BIT);
    00066         }
    00067     }
    00068     else
    00069     {
    00070         // disable timer irq
    00071         nxmac_timers_int_un_mask_set(nxmac_timers_int_un_mask_get() & ~HAL_KE_TIMER_BIT);
    00072     }
    00073     GLOBAL_INT_RESTORE();
    00074 }
    00075
    00086 static bool cmp_abs_time(struct co_list_hdr const * timerA, struct co_list_hdr const * timerB)
    00087 {
    00088     uint32_t timeA = ((struct ke_timer*)timerA)->time;
    00089     uint32_t timeB = ((struct ke_timer*)timerB)->time;
    00090
    00091     return (((uint32_t)(timeA - timeB)) > KE_TIMER_DELAY_MAX);
    00092 }
    00093
    00104 static bool cmp_timer_id(struct co_list_hdr const * timer, uint32_t timer_task)
    00105 {
    00106     // trick to pack 2 u16 in u32
    00107     ke_msg_id_t timer_id = timer_task >> 16;
    00108     ke_task_id_t task_id = timer_task & 0xFFFF;
    00109
    00110     // insert the timer just before the first one older
    00111     return (timer_id == ((struct ke_timer*)timer)->id)
    00112         && (task_id == ((struct ke_timer*)timer)->task);
    00113 }
    00114
    00115
    00135 void ke_timer_set(ke_msg_id_t const timer_id,
    00136                   ke_task_id_t const task_id,
    00137                   uint32_t const delay)
    00138 {
    00139     bool hw_prog = false;
    00140
    00141     // Sanity checks
    00142     ASSERT_ERR(delay > 0); // Delay should not be zero
    00143     ASSERT_ERR(delay < KE_TIMER_DELAY_MAX); // Delay should not be more than maximum allowed
    00144
    00145     // Check if requested timer is first of the list of pending timer
    00146     struct ke_timer *first = (struct ke_timer *) ke_env.queue_timer.first;
    00147     if (first && (first->id == timer_id) && (first->task == task_id))
    00148         // Indicate that the HW timer will have to be reprogrammed
    00149         hw_prog = true;
    00150
    00151     // Extract the timer from the list if required
    00152     struct ke_timer *timer = (struct ke_timer*)
    00153         ke_queue_extract(&ke_env.queue_timer, cmp_timer_id, (uint32_t)timer_id << 16 | task_id);
    00154
    00155     if (timer == NULL)
    00156     {
    00157         // Create new one
    00158         timer = (struct ke_timer*) ke_malloc(sizeof(struct ke_timer));
    00159         ASSERT_ERR(timer);
    00160         timer->id = timer_id;
    00161         timer->task = task_id;
    00162     }
    00163
    00164     // update characteristics
    00165     uint32_t abs_time = ke_time() + delay;
    00166     timer->time = abs_time;
    00167
    00168     // insert in sorted timer list
    00169     co_list_insert(&ke_env.queue_timer,
    00170                    (struct co_list_hdr*) timer,
    00171                    cmp_abs_time);
    00172
    00173     // check if HW timer set needed
    00174     if (hw_prog || (ke_env.queue_timer.first == (struct co_list_hdr*) timer))
    00175     {
    00176         ke_timer_hw_set((struct ke_timer *)ke_env.queue_timer.first);
    00177     }
    00178
    00179     // Check that the timer did not expire before HW prog
    00180     if (ke_time_past(abs_time))
    00181     {
    00182         // Timer already expired, so schedule the timer event immediately
    00183         ke_evt_set(KE_EVT_KE_TIMER_BIT);
    00184     }
    00185 }
    00186
    00187
    00199 void ke_timer_clear(ke_msg_id_t const timer_id,
    00200                            ke_task_id_t const task_id)
    00201 {
    00202     struct ke_timer *timer = (struct ke_timer *) ke_env.queue_timer.first;
    00203
    00204     if (ke_env.queue_timer.first != NULL)
    00205     {
    00206         if ((timer->id == timer_id) && (timer->task == task_id))
    00207         {
    00208             // timer found and first to expire! pop it
    00209             ke_queue_pop(&ke_env.queue_timer);
    00210
    00211             struct ke_timer *first = (struct ke_timer *) ke_env.queue_timer.first;
    00212
    00213             // and set the following timer HW if any
    00214             ke_timer_hw_set(first);
    00215
    00216             // Check that the timer did not expire before HW prog
    00217             ASSERT_ERR(!first || !ke_time_past(first->time));
    00218         }
    00219         else
    00220         {
    00221             timer = (struct ke_timer *)
    00222                     ke_queue_extract(&ke_env.queue_timer, cmp_timer_id,
    00223                             (uint32_t)timer_id << 16 | task_id);
    00224         }
    00225
    00226         if (timer != NULL)
    00227         {
    00228             // free the cleared timer
    00229             ke_free(timer);
    00230         }
    00231     }
    00232 }
    00233
    00234
    00248 void ke_timer_schedule(int dummy)
    00249 {
    00250     struct ke_timer *timer;
    00251
    00252     for(;;)
    00253     {
    00254         ke_evt_clear(KE_EVT_KE_TIMER_BIT);
    00255
    00256         // check the next timer
    00257         timer = (struct ke_timer*) ke_env.queue_timer.first;
    00258
    00259         if (!timer)
    00260         {
    00261             // no more timers, disable HW irq and leave
    00262             ke_timer_hw_set(NULL);
    00263             break;
    00264         }
    00265
    00266         if (!ke_time_past(timer->time - 50))
    00267         {
    00268             // timer will expire in more than 32us, configure the HW
    00269             ke_timer_hw_set(timer);
    00270
    00271             // in most case, we will break here. However, if the timer expiration
    00272             // time has just passed, may be the HW was set too late (due to an IRQ)
    00273             // so we do not exit the loop to process it.
    00274             if (!ke_time_past(timer->time))
    00275                 break;
    00276         }
    00277
    00278         // at this point, the next timer in the queue has expired or is about to -> pop it
    00279         timer = (struct ke_timer*) ke_queue_pop(&ke_env.queue_timer);
    00280
    00281         // notify the task
    00282         ke_msg_send_basic(timer->id, timer->task, TASK_NONE);
    00283
    00284         // free the memory allocated for the timer
    00285         ke_free(timer);
    00286     }
    00287
    00288
    00289 }
    00304 bool ke_timer_active(ke_msg_id_t const timer_id, ke_task_id_t const task_id)
    00305 {
    00306     struct ke_timer *timer;
    00307     bool result;
    00308
    00309     // check the next timer
    00310     timer = (struct ke_timer*) ke_env.queue_timer.first;
    00311
    00312     /* scan the timer queue to look for a message element with the same id and destination*/
    00313     while (timer != NULL)
    00314     {
    00315         if ((timer->id == timer_id) &&
    00316             (timer->task == task_id) )
    00317         {
    00318             /* Element has been found                                                   */
    00319             break;
    00320         }
    00321
    00322         /* Check  next timer                                                            */
    00323         timer = timer->next;
    00324     }
    00325
    00326     /* If the element has been found                                                    */
    00327     if (timer != NULL)
    00328         result = true;
    00329     else
    00330         result = false;
    00331
    00332     return(result);
    00333 }
    00334
    00340 void ke_timer_reset(void)
    00341 {
    00342     struct ke_timer *timer;
    00343
    00344     // Disable the HW timer
    00345     nxmac_timers_int_un_mask_set(nxmac_timers_int_un_mask_get() & ~HAL_KE_TIMER_BIT);
    00346
    00347     // Clear the timer event in case it would have been scheduled just before
    00348     ke_evt_clear(KE_EVT_KE_TIMER_BIT);
    00349
    00350     for(;;)
    00351     {
    00352         // Pop the timer from the list until no more is programmed
    00353         timer = (struct ke_timer*) ke_queue_pop(&ke_env.queue_timer);
    00354         if (timer == NULL)
    00355             break;
    00356
    00357         // free the memory allocated for the timer
    00358         ke_free(timer);
    00359     }
    00360 }
    00361