- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/lmac/src/mm/mm_timer.c

Go to the documentation of this file.

    00001
    00019 /*
    00020  * INCLUDE FILES
    00021  ****************************************************************************************
    00022  */
    00023 // standard includes
    00024 #include "co_int.h"
    00025 #include "co_bool.h"
    00026
    00027 #include "mm_timer.h"
    00028 #include "ke_event.h"
    00029 #include "hal_machw.h"
    00030 #include "reg_mac_core.h"
    00031 #include "ke_timer.h"
    00032
    00033 #if NX_MM_TIMER
    00034 /*
    00035  * DEFINES
    00036  ****************************************************************************************
    00037  */
    00038
    00039
    00040 /*
    00041  * GLOBAL VARIABLES
    00042  ****************************************************************************************
    00043  */
    00045 struct mm_timer_env_tag mm_timer_env;
    00046
    00047 /*
    00048  * FUNCTION PROTOTYPES
    00049  ****************************************************************************************
    00050  */
    00051 void mm_timer_init(void)
    00052 {
    00053     // Initialize the list of programmed timers
    00054     co_list_init(&mm_timer_env.prog);
    00055 }
    00056
    00057
    00065 static void mm_timer_hw_set(struct mm_timer_tag *timer)
    00066 {
    00067     GLOBAL_INT_DISABLE();
    00068     if (timer)
    00069     {
    00070         uint32_t timer_msk;
    00071
    00072         // set the abs timeout in HW
    00073         nxmac_abs_timer_set(HAL_MM_TIMER, timer->time);
    00074
    00075         // enable timer irq
    00076         timer_msk = nxmac_timers_int_un_mask_get();
    00077         if (!(timer_msk & HAL_MM_TIMER_BIT))
    00078         {
    00079             // if timer is not enabled, it is possible that the irq is raised
    00080             // due to a spurious value, so ack it before
    00081             nxmac_timers_int_event_clear(HAL_MM_TIMER_BIT);
    00082             nxmac_timers_int_un_mask_set(timer_msk | HAL_MM_TIMER_BIT);
    00083         }
    00084     }
    00085     else
    00086     {
    00087         // disable timer irq
    00088         nxmac_timers_int_un_mask_set(nxmac_timers_int_un_mask_get() & ~HAL_MM_TIMER_BIT);
    00089     }
    00090     GLOBAL_INT_RESTORE();
    00091 }
    00092
    00103 static bool cmp_abs_time(struct co_list_hdr const * timerA, struct co_list_hdr const * timerB)
    00104 {
    00105     uint32_t timeA = ((struct mm_timer_tag*)timerA)->time;
    00106     uint32_t timeB = ((struct mm_timer_tag*)timerB)->time;
    00107
    00108     return (hal_machw_time_cmp(timeA, timeB));
    00109 }
    00110
    00111 void mm_timer_set(struct mm_timer_tag *timer, uint32_t value)
    00112 {
    00113     bool hw_prog = false;
    00114
    00115     // Sanity check - Timeout value should not be in the past
    00116     ASSERT_ERR(!hal_machw_time_past(value));
    00117
    00118     // check if timer is already present in the list
    00119     if (co_list_pick(&mm_timer_env.prog) == (struct co_list_hdr*) timer)
    00120     {
    00121         // pop the timer from the list
    00122         co_list_pop_front(&mm_timer_env.prog);
    00123         // force the HW timer to be reprogrammed
    00124         hw_prog = true;
    00125     }
    00126     else
    00127     {
    00128         // extract the timer from the list
    00129         co_list_extract(&mm_timer_env.prog, &timer->list_hdr);
    00130     }
    00131
    00132     // update characteristics
    00133     timer->time = value;
    00134
    00135     // insert in sorted timer list
    00136     co_list_insert(&mm_timer_env.prog,
    00137                    (struct co_list_hdr*) timer,
    00138                    cmp_abs_time);
    00139
    00140     // check if HW timer set needed
    00141     if (hw_prog || (co_list_pick(&mm_timer_env.prog) == (struct co_list_hdr*) timer))
    00142     {
    00143         mm_timer_hw_set((struct mm_timer_tag *)co_list_pick(&mm_timer_env.prog));
    00144     }
    00145
    00146     // Check that the timer did not expire before HW prog
    00147     if (hal_machw_time_past(value))
    00148     {
    00149         // Timer already expired, so schedule the timer event immediately
    00150         ke_evt_set(KE_EVT_MM_TIMER_BIT);
    00151     }
    00152 }
    00153
    00154
    00155 void mm_timer_clear(struct mm_timer_tag *timer)
    00156 {
    00157     // Check if timer is first of the list
    00158     if (co_list_pick(&mm_timer_env.prog) == (struct co_list_hdr*) timer)
    00159     {
    00160         // Pop it
    00161         co_list_pop_front(&mm_timer_env.prog);
    00162
    00163         // And reprogram the HW timer
    00164         mm_timer_hw_set((struct mm_timer_tag *)co_list_pick(&mm_timer_env.prog));
    00165     }
    00166     else
    00167         // Extract the timer from the list
    00168         co_list_extract(&mm_timer_env.prog, &timer->list_hdr);
    00169 }
    00170
    00183 void mm_timer_schedule(int dummy)
    00184 {
    00185     struct mm_timer_tag *timer;
    00186
    00187     for(;;)
    00188     {
    00189         ke_evt_clear(KE_EVT_MM_TIMER_BIT);
    00190
    00191         // check the next timer
    00192         timer = (struct mm_timer_tag *)co_list_pick(&mm_timer_env.prog);
    00193         if (!timer)
    00194         {
    00195             // no more timers, disable HW irq and leave
    00196             mm_timer_hw_set(NULL);
    00197             break;
    00198         }
    00199
    00200         if (!hal_machw_time_past(timer->time - 50))
    00201         {
    00202             // timer will expire in more than 32us, configure the HW
    00203             mm_timer_hw_set(timer);
    00204
    00205             // in most case, we will break here. However, if the timer expiration
    00206             // time has just passed, may be the HW was set too late (due to an IRQ)
    00207             // so we do not exit the loop to process it.
    00208             if (!hal_machw_time_past(timer->time))
    00209             {
    00210                 break;
    00211             }
    00212         }
    00213
    00214         // at this point, the next timer in the queue has expired or is about to -> pop it
    00215         co_list_pop_front(&mm_timer_env.prog);
    00216
    00217         // Sanity check
    00218         ASSERT_ERR(timer->cb);
    00219
    00220         // notify the caller - It has to be done after popping the timer from the queue
    00221         // as the callback may set it again
    00222         timer->cb(timer->env);
    00223     }
    00224 }
    00225
    00226 #endif
    00227
    00229