FreeCalypso > hg > freecalypso-sw
diff gsm-fw/riviera/rvf/rvf_time.c @ 143:afceeeb2cba1
Our nuc-fw is destined to become gsm-fw, so I went ahead and did the big hg mv
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Tue, 12 Nov 2013 05:35:48 +0000 |
parents | nuc-fw/riviera/rvf/rvf_time.c@5fe5559003b7 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/riviera/rvf/rvf_time.c Tue Nov 12 05:35:48 2013 +0000 @@ -0,0 +1,617 @@ +/****************************************************************************/ +/* */ +/* Name rvf_time.c */ +/* */ +/* Function this file contains rvf time related functions */ +/* */ +/* Version 0.1 */ +/* */ +/* Date Modification */ +/* ------------------------------------ */ +/* 3/12/99 Create */ +/* 10/27/1999 remove all non-nucleus sections (#ifdef) */ +/* 30/11/99 compliant to RV coding guidelines */ +/* 31/01/2003 Timer Redesign/Impl.RV2 Gary TOTNEY */ +/* */ +/* Author David Lamy-Charrier (dlamy@tif.ti.com) */ +/* */ +/* (C) Copyright 1999 by Texas Instruments Incorporated, All Rights Reserved*/ +/****************************************************************************/ + +#include "../../include/config.h" + +#include "../rvm/rvm_use_id_list.h" +#include "../rvm/rvm_i.h" // only for MBs [coupling issue] +#include "../rvm/rvm_api.h" // MSG [coupling issue] +#include "rvf_i.h" +#include "rvf_api.h" + +#include "../../nucleus/nucleus.h" + +#include <string.h> + + + +/* +** Define the time control array +*/ +static NU_TIMER rvf_Timer[MAX_RVF_TASKS][RVF_NUM_TASK_TIMERS]; + +//extern T_RVF_MB_ID rvm_timer_mem_bank; + +#define _RALLOC_TIMER_BLK(tb) rvf_get_buf(rvm_timer_mem_bank, sizeof(NU_TIMER), tb) +#define _RALLOC_TMS_MSG(id, tb) rvf_get_msg_buf(rvm_tm_notify_mem_bank, sizeof(T_RVF_TMS_MSG), id, tb) + + +/* PRIVATE FUNC FWD DECLs */ +T_RV_TM_ID _invoke_tm(T_RVF_G_ADDR_ID gid, UINT32 t, UINT8 cont, void* action, UINT8 lg); + +/******************************************************************************* +** +** Function _rvf_timer_expire +** +** Description This internal function is called by Nucleus OS, when a task +** timer expires. It sets the corresponding event. +** +** Returns void +** +*******************************************************************************/ +void _rvf_timer_expire(UNSIGNED timer_id) +{ + rvf_disable(14); + /* send the corresponding timer event */ + rvf_send_event((UINT8)(timer_id / RVF_NUM_TASK_TIMERS),(UINT16)(EVENT_MASK(((timer_id % RVF_NUM_TASK_TIMERS)+4)) ) ); + rvf_enable(); +} + +void _rvf_tm_notify(UNSIGNED timer_id) { + T_RVF_TM_UBLK tmr; + T_RVF_TM_ATTRIB_UBLK attr; + UINT32 tmid=0, cont=0, d; + OPTION opt; + T_RVF_TMS_MSG* p_msg=NULL; + + if(timer_id) tmr.id=timer_id; + + if(NU_Timer_Information(tmr.ptr,attr.str, &opt, (UNSIGNED*)&d, (UNSIGNED*)&tmid, (UNSIGNED*)&d, (UNSIGNED*) &cont) == NU_INVALID_TIMER) { // use to get p_attrib + rvf_send_trace ("FATAL: RVF TIMER ATTIRBUTE ERROR!", + 49, + NULL_PARAM, + RV_TRACE_LEVEL_WARNING, + 0); + + } +/* printf("%ld %ld %d:", attr.attrib.host_addr_id, + attr.attrib.action, + attr.attrib.legacyFlag); +*/ + if(!pRtAddrIdTable[attr.attrib.host_addr_id]) return; // Don't waste time in HISR /* MUST BE REPLACED WITH CACHED MSG'ing */ + + // Will utilise active caching in near future, limiting HISR duration + if((_RALLOC_TMS_MSG(RVM_TMS_MSG, (T_RVF_MSG**)&p_msg))==RVF_RED){ + rvf_send_trace ("FATAL: RVF TIMER HISR: Insufficient resources!", + 49, + NULL_PARAM, + RV_TRACE_LEVEL_WARNING, + 0); + + return; // (RV_MEMORY_ERR); + } + p_msg->hdr.msg_id=RVM_TMS_MSG; + p_msg->tm_id=tmr.id; + p_msg->cont=cont; + p_msg->action=attr.attrib.action; + rvf_disable(14); + rvf_send_priority_msg(attr.attrib.host_addr_id, p_msg); // NOTE: must have id and recognised in FSM core + rvf_enable(); +} + +/********************************************************************************/ +/* */ +/* Function Name: rvf_create_timer */ +/* */ +/* Purpose: This function is reponsible for stopping timers. */ +/* */ +/* Revision History: */ +/* */ +/********************************************************************************/ +T_RVF_TIMER_ID rvf_create_timer(T_RVF_G_ADDR_ID g_addrId, + UINT32 tmDuration, + BOOLEAN isContinuous, + void* p_action) { + + return _invoke_tm(g_addrId, tmDuration, isContinuous, p_action, 0); +} + +// this exists as part of an on-going initiative to deprecate rvf: start/stop timers +T_RV_TM_ID _invoke_tm(T_RVF_G_ADDR_ID gid, UINT32 t, UINT8 cont, void* action, UINT8 lg) { + T_RVF_TM_UBLK tmr; + T_RVF_TM_ATTRIB_UBLK tm_attrib; + UINT32 re_sched=0; + OPTION opt=NU_DISABLE_TIMER; + STATUS status; + + if(t) opt=NU_ENABLE_TIMER; + if(cont) re_sched=t; + + // TO DO... ret. 0 if alloc fails + if(_RALLOC_TIMER_BLK((T_RVF_BUFFER**)&tmr.ptr)) return 0; + + tm_attrib.attrib.host_addr_id =gid; + tm_attrib.attrib.action =action; + tm_attrib.attrib.legacyFlag =lg; + + status=NU_Create_Timer( tmr.ptr, // TIMER CONTROL BLOCK + tm_attrib.str, // timer name (overloaded) + _rvf_tm_notify, // expiration routine to call + tmr.id, // unique id which enables to find a specific task and a specific timer + t, // duration + re_sched, // continuous = 1 + opt); + + if(status!=NU_SUCCESS) tmr.id=0; + + return (UINT32)tmr.id; +} + +/*T_RVF_RET rvf_get_remaining_time(T_RV_TM_ID tid, UINT32* t) { + T_RVF_TM_UBLK tmr; + + tmr.id=tid; + if(NU_Get_Remaining_Time(tmr.ptr, (UNSIGNED*)&t)==NU_INVALID_TIMER) return RV_INVALID_PARAMETER; + + return RVF_OK; +}*/ + +/******************************************************************************* +** +** Function rvf_del_timer +** +** Description This function is called by an application to delete a timer +** entry from a timer list. +** +** Returns void +** +*******************************************************************************/ +void rvf_del_timer(T_RV_TM_ID tm_id) { + T_RVF_TM_UBLK tmr; + + if(tm_id) tmr.id=tm_id; + + NU_Control_Timer(tmr.ptr, NU_DISABLE_TIMER); + NU_Delete_Timer(tmr.ptr); + rvf_free_buf(tmr.ptr); +} + +void rvf_reset_timer(T_RV_TM_ID tm_id, UINT32 new_duration, + BOOLEAN isContinuous) { + T_RVF_TM_UBLK tmr; + UINT32 re_sched=0; + + if(isContinuous)re_sched=new_duration; + if(tm_id) tmr.id=tm_id; + + NU_Control_Timer(tmr.ptr, NU_DISABLE_TIMER); + + if(new_duration) { + NU_Reset_Timer( tmr.ptr, + _rvf_tm_notify, + new_duration, + re_sched, + NU_ENABLE_TIMER); + } + +} + +/******************************************************************************* +** +** Function _rvf_timers_init +** +** Description This internal function is called once at startup to initialize +** all the timer structures. +** +** Returns void +** +*******************************************************************************/ +void _rvf_timers_init(void) +{ + UINT8 task_num, timer_num; + + for (task_num = 0; task_num< MAX_RVF_TASKS; task_num++) + { + for (timer_num = 0; timer_num < RVF_NUM_TASK_TIMERS; timer_num++) + { + NU_Create_Timer( &(rvf_Timer[task_num][timer_num]),/* TIMER CONTROL BLOCK*/ + "", /* timer name */ + _rvf_timer_expire, /* expiration routine to call*/ + (task_num * RVF_NUM_TASK_TIMERS) +timer_num, + /* unique id which enables to find a specific task and a specific timer*/ + 1, + 0, + NU_DISABLE_TIMER); + } + } +} + +/******************************************************************************* +** +** Function rvf_get_time_stamp +** +** Description This function formats the time into a user area +** +** Returns the address of the user area containing the formatted time +** +*******************************************************************************/ +char *rvf_get_time_stamp(char *tbuf) +{ + UINT32 ms_time; + UINT32 s_time; + UINT32 m_time; + UINT32 h_time; + char *p_out = tbuf; + + ms_time = rvf_get_tick_count(); + s_time = ms_time/100; /* 100 Ticks per second */ + m_time = s_time/60; + h_time = m_time/60; + + ms_time -= s_time*100; + s_time -= m_time*60; + m_time -= h_time*60; + + *p_out++ = (char)((h_time / 10) + '0'); + *p_out++ = (char)((h_time % 10) + '0'); + *p_out++ = ':'; + *p_out++ = (char)((m_time / 10) + '0'); + *p_out++ = (char)((m_time % 10) + '0'); + *p_out++ = ':'; + *p_out++ = (char)((s_time / 10) + '0'); + *p_out++ = (char)((s_time % 10) + '0'); + *p_out++ = ':'; + *p_out++ = (char)((ms_time / 10) + '0'); + *p_out++ = (char)((ms_time % 10) + '0'); + *p_out++ = ':'; + *p_out = 0; + + return tbuf; +} + + +/******************************************************************************* +** +** Function rvf_get_tick_count +** +** Description This function returns the current Nucleus system ticks +** +** Returns ticks +** +*******************************************************************************/ +UINT32 rvf_get_tick_count(void) +{ + return NU_Retrieve_Clock(); +} + + +/******************************************************************************* +** +** Function rvf_start_timer +** +** Description An application can call this function to start one of +** it's four general purpose timers. Any of the four timers +** can be 1-shot or continuous. If a timer is already running, +** it will be reset to the new paramaters. +** +** Returns void +** +*******************************************************************************/ +void rvf_start_timer (UINT8 tnum, UINT32 ticks, BOOLEAN is_continuous) +{ T_RVF_G_ADDR_ID task_id = rvf_get_taskid(); + + if(tnum==RVF_TIMER_3 || tnum==RVF_TIMER_2) { // reserved for rvf timer service + rvf_send_trace ("WARNING: Timers 2 & 3 are deprecated!", + 37, + NULL_PARAM, + RV_TRACE_LEVEL_DEBUG_LOW, + 0); +// return; + } + if (!ticks) // check if ticks == 0, set it to 1 + { ticks = 1; + } + + // disable Nucleus timer + NU_Control_Timer( &(rvf_Timer[task_id][tnum]), + NU_DISABLE_TIMER ); + + // reset the timer with the new settings + NU_Reset_Timer( &(rvf_Timer[task_id][tnum]), + _rvf_timer_expire, + ticks, + is_continuous? ticks:0, // if timer is continuous, reload it + NU_ENABLE_TIMER); +} + +/******************************************************************************* +** +** Function rvf_stop_timer +** +** Description An application can call this function to stop one of +** it's four general purpose timers. There is no harm in +** stopping a timer that is already stopped. +** +** Returns void +** +*******************************************************************************/ +void rvf_stop_timer (UINT8 tnum) +{ T_RVF_G_ADDR_ID task_id = rvf_get_taskid(); + + /* disable Nucleus timer */ + NU_Control_Timer( &(rvf_Timer[task_id][tnum]), + NU_DISABLE_TIMER ); +} + +/******************************************************************************* +** +** Function rvf_init_timer_list +** +** Description This function is called by applications when they +** want to initialize a timer list. +** +** Returns void +** +*******************************************************************************/ +void rvf_init_timer_list (T_RVF_TIMER_LIST_Q *p_timer_listq) +{ + p_timer_listq->p_first = NULL; + p_timer_listq->p_last = NULL; + p_timer_listq->last_ticks = 0; +} + +/******************************************************************************* +** +** Function rvf_init_timer_list_entry +** +** Description This function is called by the applications when they +** want to initialize a timer list entry. This must be +** done prior to first use of the entry. +** +** Returns void +** +*******************************************************************************/ +void rvf_init_timer_list_entry (T_RVF_TIMER_LIST_ENT *p_tle) +{ + p_tle->p_next = NULL; + p_tle->p_prev = NULL; + p_tle->ticks = 0xFFFFFFFFL; +} + + +/******************************************************************************* +** +** Function rvf_update_timer_list +** +** Description This function is called by the applications when they +** want to update a timer list. This should be at every +** timer list unit tick, e.g. once per sec, once per minute etc. +** +** Returns the number of timers that have expired +** +*******************************************************************************/ +UINT16 rvf_revise_timer_list (T_RVF_G_ADDR_ID gid){ + if(!pRtAddrIdTable[gid] ); +// !pRtAddrIdTable[gid]->p_tm_q || +// pRtAddrIdTable[gid]->p_tm_q->timerCnt==0 || +// pRtAddrIdTable[gid]->polling_tm!=0 ) return 0; /* rvf abort */ +// return rvf_update_timer_list(pRtAddrIdTable[gid]->p_tm_q); /* tms notify */ + return 0; +} +UINT16 rvf_update_timer_list (T_RVF_TIMER_LIST_Q *p_timer_listq) +{ + T_RVF_TIMER_LIST_ENT *p_tle; + UINT16 num_time_out = 0; + + p_tle = p_timer_listq->p_first; + + /* First, get the guys who have previously timed out */ + while ((p_tle) && (p_tle->ticks == 0)) + { + num_time_out++; + p_tle = p_tle->p_next; + } + + /* Now, get the guys who have just timed out */ + if ((p_tle) && (p_tle->ticks)) + { + if (--p_tle->ticks == 0) + { + while (p_tle != NULL && p_tle->ticks == 0) + { + num_time_out++; + p_tle = p_tle->p_next; + } + } + } + + if (p_timer_listq->last_ticks) + p_timer_listq->last_ticks--; + + return (num_time_out); +} + + + +/******************************************************************************* +** +** Function rvf_add_to_timer_list +** +** Description This function is called by an application to add a timer +** entry to a timer list. +** +** Returns void +** +*******************************************************************************/ +void rvf_add_to_timer_list (T_RVF_TIMER_LIST_Q *p_timer_listq, T_RVF_TIMER_LIST_ENT *p_tle) +{ + UINT32 nr_ticks_total; + T_RVF_TIMER_LIST_ENT *p_temp; + + if (p_tle->ticks >= p_timer_listq->last_ticks) + { + if (p_timer_listq->p_first == NULL) + p_timer_listq->p_first = p_tle; + else + { + if (p_timer_listq->p_last != NULL) + p_timer_listq->p_last->p_next = p_tle; + + p_tle->p_prev = p_timer_listq->p_last; + } + + p_tle->p_next = NULL; + p_timer_listq->p_last = p_tle; + nr_ticks_total = p_tle->ticks; + p_tle->ticks = p_tle->ticks - p_timer_listq->last_ticks; + + p_timer_listq->last_ticks = nr_ticks_total; + } + else + { + p_temp = p_timer_listq->p_first; + while (p_tle->ticks > p_temp->ticks) + { + p_tle->ticks = p_tle->ticks - p_temp->ticks; + p_temp = p_temp->p_next; + } + if (p_temp == p_timer_listq->p_first) + { + p_tle->p_next = p_timer_listq->p_first; + p_timer_listq->p_first->p_prev = p_tle; + p_timer_listq->p_first = p_tle; + } + else + { + p_temp->p_prev->p_next = p_tle; + p_tle->p_prev = p_temp->p_prev; + p_temp->p_prev = p_tle; + p_tle->p_next = p_temp; + } + p_temp->ticks = p_temp->ticks - p_tle->ticks; + } +} + +/******************************************************************************* +** +** Function rvf_remove_from_timer_list +** +** Description This function is called by an application to remove a timer +** entry from a timer list. +** +** Returns void +** +*******************************************************************************/ +void rvf_remove_from_timer_list (T_RVF_TIMER_LIST_Q *p_timer_listq, T_RVF_TIMER_LIST_ENT *p_tle) +{ + if (p_tle == NULL || p_tle->ticks == 0xFFFFFFFFL || p_timer_listq->p_first == NULL) + { + return; + } + + /* Add the ticks remaining in this timer to the next guy in the list. + */ + if (p_tle->p_next != NULL) + { + p_tle->p_next->ticks += p_tle->ticks; + } + else + { + p_timer_listq->last_ticks -= p_tle->ticks; + } + + /* Unlink timer from the list. + */ + if (p_timer_listq->p_first == p_tle) + { + p_timer_listq->p_first = p_tle->p_next; + + if (p_timer_listq->p_first != NULL) + p_timer_listq->p_first->p_prev = NULL; + + if (p_timer_listq->p_last == p_tle) + p_timer_listq->p_last = NULL; + } + else + { + if (p_timer_listq->p_last == p_tle) + { + p_timer_listq->p_last = p_tle->p_prev; + + if (p_timer_listq->p_last != NULL) + p_timer_listq->p_last->p_next = NULL; + } + else + { + if (p_tle->p_next != NULL && p_tle->p_next->p_prev == p_tle) + p_tle->p_next->p_prev = p_tle->p_prev; + else + { + /* Error case - chain messed up ?? */ + return; + } + + if (p_tle->p_prev != NULL && p_tle->p_prev->p_next == p_tle) + p_tle->p_prev->p_next = p_tle->p_next; + else + { + /* Error case - chain messed up ?? */ + return; + } + } + } + + p_tle->p_next = p_tle->p_prev = NULL; + p_tle->ticks = 0xFFFFFFFFL; +} + + +/******************************************************************************* +** +** Function rvf_get_expired_entry +** +** Description This function returns a pointer to the first expired entry in +** the timer list queue. +** If no entry in the queue has expired, it returns NULL. +** +** Returns T_RVF_TIMER_LIST_ENT * : pointer to the expired entry if any. +** +*******************************************************************************/ +T_RVF_TIMER_LIST_ENT * rvf_get_expired_entry (T_RVF_TIMER_LIST_Q *p_timer_listq) +{ + T_RVF_TIMER_LIST_ENT * p_tle; + /* test if the first entry in the queue has expired */ + if ( (p_timer_listq->p_first != NULL) && (p_timer_listq->p_first->ticks == 0) ) + { + + p_tle = p_timer_listq->p_first; + if(p_tle->t_init) { + p_tle->ticks=p_tle->t_init; + } else { + /* unlink entry from the list */ + p_timer_listq->p_first = p_tle->p_next; + + if (p_timer_listq->p_first != NULL) + p_timer_listq->p_first->p_prev = NULL; + + if (p_timer_listq->p_last == p_tle) + p_timer_listq->p_last = NULL; + + p_tle->p_next = NULL; + p_tle->p_prev = NULL; + p_tle->ticks = 0xFFFFFFFFL; + //return p_tle; + } + return p_tle; + } + else + { return NULL; + } +}