📄 time_calls.c
字号:
/* *---------------------------------------------------------------------- * T-Kernel * * Copyright (C) 2004 by Ken Sakamura. All rights reserved. * T-Kernel is distributed under the T-License. *---------------------------------------------------------------------- * * Version: 1.01.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2004/6/28. * *---------------------------------------------------------------------- *//* * time_calls.c (T-Kernel/OS) * Time Management Function */#include "kernel.h"#include "timer.h"#include "task.h"#include "wait.h"#include "check.h"#include "tkdev_timer.h"/* * Set system clock */SYSCALL ER _tk_set_tim( SYSTIM *pk_tim ){ CHECK_PAR(pk_tim->hi >= 0); BEGIN_CRITICAL_SECTION; real_time_ofs = ll_sub(toLSYSTIM(pk_tim), current_time); END_CRITICAL_SECTION; return E_OK;}/* * Refer system clock */SYSCALL ER _tk_get_tim( SYSTIM *pk_tim ){ BEGIN_CRITICAL_SECTION; *pk_tim = toSYSTIM(real_time()); END_CRITICAL_SECTION; return E_OK;}/* * Refer system operating time */SYSCALL ER _tk_get_otm( SYSTIM *pk_tim ){ BEGIN_CRITICAL_SECTION; *pk_tim = toSYSTIM(current_time); END_CRITICAL_SECTION; return E_OK;}#if USE_DBGSPT/* * Refer system clock */SYSCALL ER _td_get_tim( SYSTIM *tim, UINT *ofs ){ BEGIN_DISABLE_INTERRUPT; *ofs = get_hw_timer_nsec(); *tim = toSYSTIM(real_time()); END_DISABLE_INTERRUPT; return E_OK;}/* * Refer system operating time */SYSCALL ER _td_get_otm( SYSTIM *tim, UINT *ofs ){ BEGIN_DISABLE_INTERRUPT; *ofs = get_hw_timer_nsec(); *tim = toSYSTIM(current_time); END_DISABLE_INTERRUPT; return E_OK;}#endif /* USE_DBGSPT *//* ------------------------------------------------------------------------ *//* * Definition of task delay wait specification */LOCAL WSPEC wspec_dly = { TTW_DLY, NULL, NULL };/* * Task delay */SYSCALL ER _tk_dly_tsk( RELTIM dlytim ){ ER ercd = E_OK; CHECK_PAR((TMO)dlytim >= 0); CHECK_DISPATCH(); if ( dlytim > 0 ) { BEGIN_CRITICAL_SECTION; /* Check wait disable */ if ( (ctxtsk->waitmask & TTW_DLY) != 0 ) { ercd = E_DISWAI; } else { ctxtsk->wspec = &wspec_dly; ctxtsk->wid = 0; ctxtsk->wercd = &ercd; make_wait(dlytim, TA_NULL); QueInit(&ctxtsk->tskque); } END_CRITICAL_SECTION; } return ercd;}/* ------------------------------------------------------------------------ *//* * Cyclic handler */#ifdef NUM_CYCIDEXPORT ID max_cycid; /* Maximum interval start ID *//* * Cyclic handler control block */typedef struct cyclic_handler_control_block { VP exinf; /* Extended information */ ATR cycatr; /* Cyclic handler attribute */ FP cychdr; /* Cyclic handler address */ UINT cycstat; /* Cyclic handler state */ RELTIM cyctim; /* Cyclic time */ TMEB cyctmeb; /* Timer event block */#if TA_GP VP gp; /* Global pointer */#endif#if USE_OBJECT_NAME UB name[OBJECT_NAME_LENGTH]; /* name */#endif} CYCCB;LOCAL CYCCB *cyccb_table; /* Cyclic handler control block */LOCAL QUEUE free_cyccb; /* FreeQue */#define get_cyccb(id) ( &cyccb_table[INDEX_CYC(id)] )/* * Initialization of cyclic handler control block */EXPORT ER cyclichandler_initialize( void ){ CYCCB *cyccb, *end; W n; /* Get system information */ n = _tk_get_cfn("TMaxCycId", &max_cycid, 1); if ( n < 1 || NUM_CYCID < 1 ) return E_SYS; /* Create cyclic handler control block */ cyccb_table = Imalloc(NUM_CYCID * sizeof(CYCCB)); if ( cyccb_table == NULL ) return E_NOMEM; /* Register all control blocks onto FeeQue*/ QueInit(&free_cyccb); end = cyccb_table + NUM_CYCID; for ( cyccb = cyccb_table; cyccb < end; cyccb++ ) { cyccb->cychdr = NULL; /* Unregistered handler */ QueInsert((QUEUE*)cyccb, &free_cyccb); } return E_OK;}/* * Next startup time */Inline LSYSTIM cyc_next_time( CYCCB *cyccb ){ LSYSTIM tm; longlong n; tm = ll_add(cyccb->cyctmeb.time, ltoll(cyccb->cyctim)); if ( ll_cmp(tm, current_time) <= 0 ) { /* Adjust time to be later than current time */ tm = ll_sub(current_time, cyccb->cyctmeb.time); n = li_div(tm, cyccb->cyctim); ll_inc(&n); tm = li_mul(n, cyccb->cyctim); tm = ll_add(cyccb->cyctmeb.time, tm); } return tm;}/* * Register timer event queue */Inline void cyc_timer_insert( CYCCB *cyccb, LSYSTIM tm ){ LOCAL void call_cychdr( CYCCB* ); timer_insert_abs(&cyccb->cyctmeb, tm, (CBACK)call_cychdr, cyccb);}/* * Cyclic handler routine */LOCAL void call_cychdr( CYCCB *cyccb ){ /* Set next startup time */ cyc_timer_insert(cyccb, cyc_next_time(cyccb)); /* Execute cyclic handler / Enable interrupt nest */ ENABLE_INTERRUPT_UPTO(TIMER_INTLEVEL);#if TA_GP CallUserHandler((INT)cyccb->exinf, 0, 0, cyccb->cychdr, cyccb->gp);#else (*cyccb->cychdr)(cyccb->exinf);#endif DISABLE_INTERRUPT;}/* * Immediate call of cyclic handler */LOCAL void immediate_call_cychdr( CYCCB *cyccb ){ /* Set next startup time */ cyc_timer_insert(cyccb, cyc_next_time(cyccb)); /* Execute cyclic handler in task-independent part (Keep interrupt disabled) */ ENTER_TASK_INDEPENDENT;#if TA_GP CallUserHandler((INT)cyccb->exinf, 0, 0, cyccb->cychdr, cyccb->gp);#else (*cyccb->cychdr)(cyccb->exinf);#endif LEAVE_TASK_INDEPENDENT;}/* * Create cyclic handler */SYSCALL ID _tk_cre_cyc P1( T_CCYC *pk_ccyc ){ const ATR VALID_CYCATR = { TA_HLNG |TA_STA |TA_PHS |TA_GP#if USE_OBJECT_NAME |TA_DSNAME#endif }; CYCCB *cyccb; LSYSTIM tm; ER ercd = E_OK; CHECK_RSATR(pk_ccyc->cycatr, VALID_CYCATR); CHECK_PAR(pk_ccyc->cychdr != NULL); CHECK_PAR(pk_ccyc->cyctim > 0); BEGIN_CRITICAL_SECTION; /* Get control block from FreeQue */ cyccb = (CYCCB*)QueRemoveNext(&free_cyccb); if ( cyccb == NULL ) { ercd = E_LIMIT; goto error_exit; } /* Initialize control block */ cyccb->exinf = pk_ccyc->exinf; cyccb->cycatr = pk_ccyc->cycatr; cyccb->cychdr = pk_ccyc->cychdr; cyccb->cyctim = pk_ccyc->cyctim;#if USE_OBJECT_NAME if ( (pk_ccyc->cycatr & TA_DSNAME) != 0 ) { strncpy(cyccb->name, pk_ccyc->dsname, OBJECT_NAME_LENGTH); }#endif#if TA_GP if ( (pk_ccyc->cycatr & TA_GP) != 0 ) gp = pk_ccyc->gp; cyccb->gp = gp;#endif /* First startup time * To guarantee the start of handler after the specified time, * add TIMER_PERIOD. */ tm = ll_add(current_time, ltoll(pk_ccyc->cycphs)); tm = ll_add(tm, ltoll(TIMER_PERIOD)); if ( (pk_ccyc->cycatr & TA_STA) != 0 ) { /* Start cyclic handler */ cyccb->cycstat = TCYC_STA; if ( pk_ccyc->cycphs == 0 ) { /* Immediate execution */ cyccb->cyctmeb.time = tm; immediate_call_cychdr(cyccb); } else { /* Register onto timer event queue */ cyc_timer_insert(cyccb, tm); } } else { /* Initialize only counter */ cyccb->cycstat = TCYC_STP; cyccb->cyctmeb.time = tm; } ercd = ID_CYC(cyccb - cyccb_table); error_exit: END_CRITICAL_SECTION; return ercd;}/* * Delete cyclic handler */SYSCALL ER _tk_del_cyc( ID cycid ){ CYCCB *cyccb; ER ercd = E_OK; CHECK_CYCID(cycid); cyccb = get_cyccb(cycid); BEGIN_CRITICAL_SECTION; if ( cyccb->cychdr == NULL ) { /* Unregistered handler */ ercd = E_NOEXS; } else { if ( (cyccb->cycstat & TCYC_STA) != 0 ) { /* Delete timer event queue */ timer_delete(&cyccb->cyctmeb); } /* Return to FreeQue */ QueInsert((QUEUE*)cyccb, &free_cyccb); cyccb->cychdr = NULL; /* Unregistered handler */ } END_CRITICAL_SECTION; return ercd;}/* * Start cyclic handler */SYSCALL ER _tk_sta_cyc( ID cycid ){ CYCCB *cyccb; LSYSTIM tm; ER ercd = E_OK; CHECK_CYCID(cycid); cyccb = get_cyccb(cycid); BEGIN_CRITICAL_SECTION; if ( cyccb->cychdr == NULL ) { /* Unregistered handler */ ercd = E_NOEXS; goto error_exit; } if ( (cyccb->cycatr & TA_PHS) != 0 ) { /* Continue cyclic phase */ if ( (cyccb->cycstat & TCYC_STA) == 0 ) { /* Start cyclic handler */ tm = cyccb->cyctmeb.time; if ( ll_cmp(tm, current_time) <= 0 ) { tm = cyc_next_time(cyccb); } cyc_timer_insert(cyccb, tm); } } else { /* Reset cyclic interval */ if ( (cyccb->cycstat & TCYC_STA) != 0 ) { /* Stop once */ timer_delete(&cyccb->cyctmeb); } /* Start cyclic handler */ cyc_timer_insert(cyccb, ll_add(current_time, ltoll(cyccb->cyctim))); } cyccb->cycstat |= TCYC_STA; error_exit: END_CRITICAL_SECTION; return ercd;}/* * Stop cyclic handler */SYSCALL ER _tk_stp_cyc( ID cycid ){ CYCCB *cyccb; ER ercd = E_OK; CHECK_CYCID(cycid); cyccb = get_cyccb(cycid); BEGIN_CRITICAL_SECTION; if ( cyccb->cychdr == NULL ) { /* Unregistered handler */ ercd = E_NOEXS; } else { if ( (cyccb->cycstat & TCYC_STA) != 0 ) { /* Stop cyclic handler */ timer_delete(&cyccb->cyctmeb); } cyccb->cycstat &= ~TCYC_STA; } END_CRITICAL_SECTION; return ercd;}/* * Refer cyclic handler state */SYSCALL ER _tk_ref_cyc( ID cycid, T_RCYC* pk_rcyc ){ CYCCB *cyccb; LSYSTIM tm; ER ercd = E_OK; CHECK_CYCID(cycid); cyccb = get_cyccb(cycid); BEGIN_CRITICAL_SECTION; if ( cyccb->cychdr == NULL ) { /* Unregistered handler */ ercd = E_NOEXS; } else { tm = cyccb->cyctmeb.time; if ( (cyccb->cycstat & TCYC_STA) == 0 ) { if ( ll_cmp(tm, current_time) <= 0 ) { tm = cyc_next_time(cyccb); } } tm = ll_sub(tm, current_time); tm = ll_sub(tm, ltoll(TIMER_PERIOD)); if ( ll_sign(tm) < 0 ) tm = ltoll(0); pk_rcyc->exinf = cyccb->exinf; pk_rcyc->lfttim = tm; pk_rcyc->cycstat = cyccb->cycstat; } END_CRITICAL_SECTION; return ercd;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -