📄 time_calls.c
字号:
/* *---------------------------------------------------------------------- * T-Kernel * * Copyright (C) 2004-2006 by Ken Sakamura. All rights reserved. * T-Kernel is distributed under the T-License. *---------------------------------------------------------------------- * * Version: 1.02.02 * Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/9. * *---------------------------------------------------------------------- *//* * 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"#include <sys/rominfo.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_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_reltim(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(SCTAG_TMAXCYCID, &max_cycid, 1); if ( n < 1 || NUM_CYCID < 1 ) { return E_SYS; } /* Create cyclic handler control block */ cyccb_table = Imalloc((UINT)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, uitoll(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 = lui_div(tm, cyccb->cyctim); ll_inc(&n); tm = lui_mul(n, cyccb->cyctim); tm = ll_add(cyccb->cyctmeb.time, tm); } return tm;}LOCAL void call_cychdr( CYCCB* cyccb );/* * Register timer event queue */Inline void cyc_timer_insert( CYCCB *cyccb, LSYSTIM tm ){ 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); CallUserHandlerP1(cyccb->exinf, cyccb->cychdr, cyccb); 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; CallUserHandlerP1(cyccb->exinf, cyccb->cychdr, cyccb); 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((char*)cyccb->name, (char*)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, uitoll(pk_ccyc->cycphs)); tm = ll_add(tm, uitoll(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); } /* FIRST ACTIVATION TIME * Adjust the first activation time with TIMER_PERIOD. * TIMER_PERIOD is Timer interrupt interval (millisecond). */ tm = ll_add(current_time, uitoll(cyccb->cyctim)); tm = ll_add(tm, uitoll(TIMER_PERIOD)); /* Start cyclic handler */ cyc_timer_insert(cyccb, tm); } 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, uitoll(TIMER_PERIOD)); if ( ll_sign(tm) < 0 ) { tm = ltoll(0); } pk_rcyc->exinf = cyccb->exinf; pk_rcyc->lfttim = (RELTIM)tm; pk_rcyc->cycstat = cyccb->cycstat; } END_CRITICAL_SECTION; return ercd;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -