/* ********************************************************************************************************* * uC/TCP-IP * The Embedded TCP/IP Suite * * (c) Copyright 2003-2007; Micrium, Inc.; Weston, FL * * All rights reserved. Protected by international copyright laws. * * uC/TCP-IP is provided in source form for FREE evaluation, for educational * use or peaceful research. If you plan on using uC/TCP-IP in a commercial * product you need to contact Micrium to properly license its use in your * product. We provide ALL the source code for your convenience and to help * you experience uC/TCP-IP. The fact that the source code is provided does * NOT mean that you can use it without paying a licensing fee. * * Knowledge of the source code may NOT be used to develop a similar product. * * Please help us continue to provide the Embedded community with the finest * software available. Your honesty is greatly appreciated. ********************************************************************************************************* */ /* ********************************************************************************************************* * * NETWORK TIMER MANAGEMENT * * Filename : net_tmr.c * Version : V1.89 * Programmer(s) : ITJ ********************************************************************************************************* */ /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ #define NET_TMR_MODULE #include /*$PAGE*/ /* ********************************************************************************************************* * LOCAL DEFINES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL CONSTANTS ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL DATA TYPES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL TABLES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL GLOBAL VARIABLES ********************************************************************************************************* */ /*$PAGE*/ /* ********************************************************************************************************* * LOCAL FUNCTION PROTOTYPES ********************************************************************************************************* */ #if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED) static void NetTmr_Clr (NET_TMR *ptmr); #endif #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) static void NetTmr_Discard (NET_TMR *ptmr); static void NetTmr_DiscardTaskTmr(void); #endif /* ********************************************************************************************************* * LOCAL CONFIGURATION ERRORS ********************************************************************************************************* */ /*$PAGE*/ /* ********************************************************************************************************* * NetTmr_Init() * * Description : (1) Initialize Network Timer Management Module : * * (a) Perform Timer Module/OS initialization * (b) Initialize timer pool * (c) Initialize timer table * (d) Initialize timer task list pointer * (e) Initialize timer error counters * * * Argument(s) : perr Pointer to variable that will receive the return error code from this function : * * NET_TMR_ERR_NONE Network timer module successfully initialized. * * ------- RETURNED BY NetOS_Tmr_Init() : ------- * NET_OS_ERR_INIT_TMR_TASK Network timer task NOT successfully * initialized. * NET_OS_ERR_INIT_TMR_TASK_NAME Network timer task name NOT successfully * configured. * * Return(s) : none. * * Caller(s) : Net_Init(). * * This function is an INTERNAL network protocol suite function & MUST NOT be called by * application function(s). * * Note(s) : (2) Timer pool MUST be initialized PRIOR to initializing the pool with pointers to timers. ********************************************************************************************************* */ /*$PAGE*/ void NetTmr_Init (NET_ERR *perr) { NET_TMR *ptmr; NET_TMR_QTY i; NET_ERR err; /* --------------- PERFORM TMR/OS INIT ---------------- */ NetOS_Tmr_Init(perr); /* Create Tmr Task. */ if (*perr != NET_OS_ERR_NONE) { return; } /* ------------------ INIT TMR POOL ------------------- */ NetTmr_PoolPtr = (NET_TMR *)0; /* Init-clr net tmr pool (see Note #2). */ NetStat_PoolInit((NET_STAT_POOL *)&NetTmr_PoolStat, (NET_STAT_POOL_QTY) NET_TMR_CFG_NBR_TMR, (NET_ERR *)&err); /* ------------------ INIT TMR TBL -------------------- */ ptmr = &NetTmr_Tbl[0]; for (i = 0; i < NET_TMR_CFG_NBR_TMR; i++) { ptmr->Type = NET_TMR_TYPE_TMR; /* Init each tmr type/id--NEVER modify. */ ptmr->ID = (NET_BUF_QTY)i; ptmr->Flags = NET_TMR_FLAG_NONE; /* Init each tmr as NOT used. */ #if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED) NetTmr_Clr(ptmr); #endif ptmr->NextPtr = (void *)NetTmr_PoolPtr; /* Free each tmr to tmr pool (see Note #2). */ NetTmr_PoolPtr = ptmr; ptmr++; } /* -------------- INIT TMR TASK LIST PTR -------------- */ NetTmr_TaskListHead = (NET_TMR *)0; NetTmr_TaskListPtr = (NET_TMR *)0; /* ---------------- INIT TMR ERR CTRS ----------------- */ #if (NET_CTR_CFG_ERR_EN == DEF_ENABLED) NetTmr_ErrNoneAvailCtr = 0; #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) NetTmr_ErrNullPtrCtr = 0; NetTmr_ErrNullObjCtr = 0; NetTmr_ErrNullFnctCtr = 0; NetTmr_ErrNotUsedCtr = 0; NetTmr_ErrInvalidTypeCtr = 0; #endif #endif *perr = NET_TMR_ERR_NONE; } /*$PAGE*/ /* ********************************************************************************************************* * NetTmr_TaskHandler() * * Description : Decrement every timer in Timer Task List & execute timer's expiration function for any * timer that expires. * * (1) (a) Timers are managed in a doubly-linked Timer List. * * (1) 'NetTmr_TaskListHead' points to the head of the Timer List. * * (2) Timers' 'PrevPtr' & 'NextPtr' doubly-link each timer to form the Timer List. * * (b) New timers are added at the head of the Timer List. * * (c) As timers are added into the list, older timers migrate to the tail of the Timer * List. Once a timer expires or is discarded, it is removed from the Timer List. * * * | | * |<-------------- List of Timers --------------->| * | (see Note #1a) | * * New Timers * inserted at head Oldest Timer in List * (see Note #1b) (see Note #1c) * * | NextPtr | * | (see Note #1a2) | * v | v * | * Head of ------- ------- v ------- ------- * Timer List ---->| |------>| |------>| |------>| | * | |<------| |<------| |<------| | * (see Note #1a1) ------- ------- ^ ------- ------- * | * | * PrevPtr * (see Note #1a2) * * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : NetOS_Tmr_Task() [see 'net_os.c']. * * This function is a network protocol suite to operating system (OS) function & SHOULD be * called only by appropriate network-operating system port function(s). * * Note(s) : (2) NetTmr_TaskHandler() blocked until network initialization completes. * * (3) NetTmr_TaskHandler() blocks ALL other network protocol tasks by pending on & acquiring * the global network lock (see 'net.h Note #2'). * * (4) (a) NetTmr_TaskHandler() handles all valid timers in Timer Task List, up to the first * corrupted timer in the Timer Task List, if any. * * (b) #### If ANY timer(s) in Timer Task List are corrupted : * * (1) Discard/unlink current Timer Task timer. * (A) Consequently, any remaining valid timers in Timer Task List are : * (1) Unlinked from Timer Task List, ... * (2) NOT handled. * * (2) Timer Task is aborted. * * (5) Since NetTmr_TaskHandler() is asynchronous to NetTmr_Free() [via execution of certain * timer expiration functions], the Timer Task List timer ('NetTmr_TaskListPtr') MUST be * coordinated with NetTmr_Free() to avoid Timer Task List corruption : * * (a) (1) Timer Task List timer is typically advanced by NetTmr_TaskHandler() to the next * timer in the Timer Task List. * * (2) However, whenever the Timer Task List timer is freed by an asynchronous timer * expiration function, the Timer Task List timer MUST be advanced to the next * valid & available timer in the Timer Task List. * * See also 'NetTmr_Free() Note #3a'. * * (b) Timer Task List timer MUST be cleared after handling the Timer Task List. * * (1) However, Timer Task List timer is implicitly cleared after handling the * Timer Task List. * * See also 'NetTmr_DiscardTaskTmr() Note #1c'. * * (6) Since NetTmr_TaskHandler() is asynchronous to ANY timer Get/Set, one additional tick * is added to each timer's count-down so that the requested timeout is ALWAYS satisfied. * This additional tick is added by NOT checking for zero ticks after decrementing; any * timer that expires is recognized at the next tick. * * (7) When a network timer expires, the timer SHOULD be freed PRIOR to executing the timer * expiration function. This ensures that at least one timer is available if the timer * expiration function requires a timer. ********************************************************************************************************* */ /*$PAGE*/ void NetTmr_TaskHandler (void) { #if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) && \ (NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) CPU_BOOLEAN used; #endif NET_TMR *ptmr; void *obj; CPU_FNCT_PTR fnct; NET_ERR err; if (Net_InitDone != DEF_YES) { /* If init NOT complete, ... */ NetOS_InitWait(&err); /* ... wait on net init (see Note #2). */ if (err != NET_OS_ERR_NONE) { return; } } NetOS_Lock(&err); /* Acquire net lock (see Note #3). */ if (err != NET_OS_ERR_NONE) { return; } NetTmr_TaskListPtr = NetTmr_TaskListHead; /* Start @ Tmr Task List head. */ while (NetTmr_TaskListPtr != (NET_TMR *)0) { /* Handle Tmr Task List tmrs (see Note #4a). */ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* -------------- VALIDATE TYPE --------------- */ if (NetTmr_TaskListPtr->Type != NET_TMR_TYPE_TMR) { /* If tmr type invalid; ... */ NetTmr_DiscardTaskTmr(); /* ... discard tmr task tmr (see Note #4b1) ... */ NET_CTR_ERR_INC(NetTmr_ErrInvalidTypeCtr); NetOS_Unlock(); return; /* ... & abort tmr task (see Note #4b2). */ } /* ------------ VALIDATE TMR USED ------------- */ used = DEF_BIT_IS_SET(NetTmr_TaskListPtr->Flags, NET_TMR_FLAG_USED); if (used != DEF_YES) { /* If tmr NOT used, ... */ NetTmr_DiscardTaskTmr(); /* ... discard tmr task tmr (see Note #4b1) ... */ NET_CTR_ERR_INC(NetTmr_ErrNotUsedCtr); NetOS_Unlock(); return; /* ... & abort tmr task (see Note #4b2). */ } #endif ptmr = (NET_TMR *)NetTmr_TaskListPtr; NetTmr_TaskListPtr = (NET_TMR *)NetTmr_TaskListPtr->NextPtr; /* Set next tmr to update (see Note #5a1). */ if (ptmr->TmrVal > 0) { /* If tmr val > 0, dec tmr val (see Note #6). */ ptmr->TmrVal--; } else { /* Else tmr expired; ... */ obj = ptmr->Obj; /* Get obj for ... */ fnct = ptmr->Fnct; /* ... tmr expiration fnct. */ NetTmr_Free(ptmr); /* ... free tmr (see Note #7); ... */ if (fnct != (CPU_FNCT_PTR)0) { /* ... & if avail, ... */ fnct(obj); /* ... exec tmr expiration fnct. */ } } } #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* Clr tmr task ptr (see Note #5b1). */ NetTmr_TaskListPtr = (NET_TMR *)0; #endif NetOS_Unlock(); /* Release net lock. */ } /*$PAGE*/ /* ********************************************************************************************************* * NetTmr_Get() * * Description : (1) Allocate & initialize a network timer : * * (a) Get timer * (b) Validate timer * (c) Initialize timer * (d) Insert timer at head of Timer Task List * (e) Update timer pool statistics * (f) Return pointer to timer * OR * Null pointer & error code, on failure * * (2) The timer pool is implemented as a stack : * * (a) 'NetTmr_PoolPtr' points to the head of the timer pool. * * (b) Timers' 'NextPtr's link each timer to form the timer pool stack. * * (c) Timers are inserted & removed at the head of the timer pool stack. * * * Timers are * inserted & removed * at the head * (see Note #2c) * * | NextPtr * | (see Note #2b) * v | * | * ------- ------- v ------- ------- * Timer Pool ---->| |------>| |------>| |------>| | * Pointer | | | | | | | | * | | | | | | | | * (see Note #2a) ------- ------- ------- ------- * * | | * |<------------ Pool of Free Timers ------------>| * | (see Note #2) | * * * Argument(s) : obj Pointer to object that requests a timer. * * fnct Pointer to object function to execute when timer expires (see Note #3). * * time Initial timer value (in 'NET_TMR_TICK' ticks) [see Note #4]. * * flags Flags to select timer options; bit-field flags logically OR'd : * * NET_TMR_FLAG_NONE NO timer flags selected. * * perr Pointer to variable that will receive the return error code from this function : * * NET_TMR_ERR_NONE Network timer successfully allocated & initialized. * NET_TMR_ERR_NULL_OBJ Argument 'obj' passed a NULL pointer. * NET_TMR_ERR_NULL_FNCT Argument 'fnct' passed a NULL pointer. * NET_TMR_ERR_NONE_AVAIL NO available timers to allocate. * NET_TMR_ERR_INVALID_TYPE Network timer is NOT a valid timer type. * * Return(s) : Pointer to network timer, if NO errors. * * Pointer to NULL, otherwise. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). *$PAGE* * Note(s) : (3) Ideally, network timer expiration functions could be defined as '[(void) (OBJECT *)]' * type functions -- even though network timer API functions cast expiration functions * to generic 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'). * * (a) (1) Unfortunately, ISO-IEC 9899-1999 ANSI-C, Section 6.3.2.3.7 states that "a * pointer to an object ... may be converted to a pointer to a different object * ... [but] if the resulting pointer is not correctly aligned ... the behavior * is undefined". * * And since compilers may NOT correctly convert 'void' pointers to non-'void' * pointer arguments, network timer expiration functions MUST avoid incorrect * pointer conversion behavior between 'void' pointer parameters & non-'void' * pointer arguments & therefore CANNOT be defined as '[(void) (OBJECT *)]'. * * (2) However, Section 6.3.2.3.1 states that "a pointer to void may be converted * to or from a pointer to any ... object ... A pointer to any ... object ... * may be converted to a pointer to void and back again; the result shall * compare equal to the original pointer". * * (b) Therefore, to correctly convert 'void' pointer objects back to appropriate * network object pointer objects, network timer expiration functions MUST : * * (1) Be defined as 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'); & ... * (2) Explicitly cast 'void' pointer arguments to specific object pointers. * * (4) Timer value of 0 ticks/seconds allowed; next tick will expire timer. * * See also 'NetTmr_TaskHandler() Note #6'. * * (5) #### 'flags' currently unused (remove if unnecessary). ********************************************************************************************************* */ /*$PAGE*/ NET_TMR *NetTmr_Get (void *obj, CPU_FNCT_PTR fnct, NET_TMR_TICK time, CPU_INT16U flags, NET_ERR *perr) { #if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif NET_TMR *ptmr; NET_ERR stat_err; (void)&flags; /* Prevent compiler warning (see Note #5). */ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------------------- VALIDATE PTRS ------------------ */ if (obj == (void *)0) { NET_CTR_ERR_INC(NetTmr_ErrNullObjCtr); *perr = NET_TMR_ERR_NULL_OBJ; return ((NET_TMR *)0); } if (fnct == (CPU_FNCT_PTR)0) { NET_CTR_ERR_INC(NetTmr_ErrNullFnctCtr); *perr = NET_TMR_ERR_NULL_FNCT; return ((NET_TMR *)0); } #endif /* --------------------- GET TMR ---------------------- */ if (NetTmr_PoolPtr != (NET_TMR *)0) { /* If tmr pool NOT empty, get tmr from pool. */ ptmr = (NET_TMR *)NetTmr_PoolPtr; NetTmr_PoolPtr = (NET_TMR *)ptmr->NextPtr; } else { /* If none avail, rtn err. */ NET_CTR_ERR_INC(NetTmr_ErrNoneAvailCtr); *perr = NET_TMR_ERR_NONE_AVAIL; return ((NET_TMR *)0); } #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------------------- VALIDATE TMR ------------------- */ if (ptmr->Type != NET_TMR_TYPE_TMR) { NetTmr_Discard(ptmr); NET_CTR_ERR_INC(NetTmr_ErrInvalidTypeCtr); *perr = NET_TMR_ERR_INVALID_TYPE; return ((NET_TMR *)0); } #endif /* --------------------- INIT TMR --------------------- */ ptmr->PrevPtr = (void *)0; ptmr->NextPtr = (void *)NetTmr_TaskListHead; ptmr->Obj = obj; ptmr->Fnct = fnct; ptmr->TmrVal = time; /* Set tmr val (in ticks). */ ptmr->Flags = NET_TMR_FLAG_NONE; DEF_BIT_SET(ptmr->Flags, NET_TMR_FLAG_USED); /* Set tmr as used. */ /* ---------- INSERT TMR INTO TMR TASK LIST ----------- */ if (NetTmr_TaskListHead != (NET_TMR *)0) { /* If list NOT empty, insert before head. */ NetTmr_TaskListHead->PrevPtr = (void *)ptmr; } NetTmr_TaskListHead = ptmr; /* Insert tmr @ list head. */ /* --------------- UPDATE TMR POOL STATS -------------- */ NetStat_PoolEntryUsedInc(&NetTmr_PoolStat, &stat_err); *perr = NET_TMR_ERR_NONE; return (ptmr); /* --------------------- RTN TMR ---------------------- */ } /*$PAGE*/ /* ********************************************************************************************************* * NetTmr_Free() * * Description : (1) Free a network timer : * * (a) Remove timer from Timer Task List * (b) Clear timer controls * (c) Free timer back to timer pool * (d) Update timer pool statistics * * * Argument(s) : ptmr Pointer to a network timer. * * Return(s) : none. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). * * Note(s) : (2) #### To prevent freeing a timer already freed via previous timer free, NetTmr_Free() * checks the timer's 'USED' flag BEFORE freeing the timer. * * This prevention is only best-effort since any invalid duplicate timer frees MAY be * asynchronous to potentially valid timer gets. Thus the invalid timer free(s) MAY * corrupt the timer's valid operation(s). * * However, since the primary tasks of the network protocol suite are prevented from * running concurrently (see 'net.h Note #2'), it is NOT necessary to protect network * timer resources from possible corruption since no asynchronous access from other * network tasks is possible. * * (3) Since NetTmr_TaskHandler() is asynchronous to NetTmr_Free() [via execution of certain * timer expiration functions], the Timer Task List timer ('NetTmr_TaskListPtr') MUST be * coordinated with NetTmr_Free() to avoid Timer Task List corruption : * * (a) Whenever the Timer Task List timer is freed, the Timer Task List timer MUST be * advanced to the next valid & available timer in the Timer Task List. * * See also 'NetTmr_TaskHandler() Note #5a2'. ********************************************************************************************************* */ /*$PAGE*/ void NetTmr_Free (NET_TMR *ptmr) { #if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) && \ (NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) CPU_BOOLEAN used; #endif NET_TMR *pprev; NET_TMR *pnext; NET_ERR stat_err; /* ------------------ VALIDATE PTR -------------------- */ if (ptmr == (NET_TMR *)0) { return; } #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------------------ VALIDATE TYPE ------------------- */ if (ptmr->Type != NET_TMR_TYPE_TMR) { NetTmr_Discard(ptmr); NET_CTR_ERR_INC(NetTmr_ErrInvalidTypeCtr); return; } /* ---------------- VALIDATE TMR USED ----------------- */ used = DEF_BIT_IS_SET(ptmr->Flags, NET_TMR_FLAG_USED); if (used != DEF_YES) { /* If tmr NOT used, ... */ NET_CTR_ERR_INC(NetTmr_ErrNotUsedCtr); return; /* ... rtn but do NOT free (see Note #2). */ } #endif /* ----------- REMOVE TMR FROM TMR TASK LIST ---------- */ if (ptmr == NetTmr_TaskListPtr) { /* If tmr is next Tmr Task tmr to update, ... */ pnext = (NET_TMR *)NetTmr_TaskListPtr->NextPtr; NetTmr_TaskListPtr = (NET_TMR *)pnext; /* ... adv Tmr Task ptr to skip this tmr (see Note #3a).*/ } pprev = (NET_TMR *)ptmr->PrevPtr; pnext = (NET_TMR *)ptmr->NextPtr; if (pprev != (NET_TMR *)0) { /* If ptmr is NOT the head of Tmr Task List, ... */ pprev->NextPtr = (void *)pnext; /* ... set pprev's NextPtr to skip ptmr. */ } else { /* Else set pnext as head of Tmr Task List. */ NetTmr_TaskListHead = (NET_TMR *)pnext; } if (pnext != (NET_TMR *)0) { /* If ptmr is NOT @ the tail of Tmr Task List, ... */ pnext->PrevPtr = (void *)pprev; /* ... set pnext's PrevPtr to skip ptmr. */ } /* ---------------------- CLR TMR --------------------- */ DEF_BIT_CLR(ptmr->Flags, NET_TMR_FLAG_USED); /* Set tmr as NOT used. */ #if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED) NetTmr_Clr(ptmr); #endif /* --------------------- FREE TMR --------------------- */ ptmr->NextPtr = (void *)NetTmr_PoolPtr; NetTmr_PoolPtr = (NET_TMR *)ptmr; /* -------------- UPDATE TMR POOL STATS --------------- */ NetStat_PoolEntryUsedDec(&NetTmr_PoolStat, &stat_err); } /*$PAGE*/ /* ********************************************************************************************************* * NetTmr_Set() * * Description : Update a network timer with a new expiration function & timer value. * * Argument(s) : ptmr Pointer to a network timer. * * fnct Pointer to object function to execute when timer expires (see Note #2). * * time Update timer value (in seconds expressed in 'NET_TMR_TICK' ticks) * [see also Note #3]. * * perr Pointer to variable that will receive the return error code from this function : * * NET_TMR_ERR_NONE Network timer time successfully updated. * NET_TMR_ERR_NULL_PTR Argument 'ptmr' passed a NULL pointer. * NET_TMR_ERR_NULL_FNCT Argument 'fnct' passed a NULL pointer. * NET_TMR_ERR_INVALID_TYPE Invalid timer type. * * Return(s) : none. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). * * Note(s) : (1) Assumes network timer is ALREADY owned by a valid network object. * * (2) Ideally, network timer expiration functions could be defined as '[(void) (OBJECT *)]' * type functions -- even though network timer API functions cast expiration functions * to generic 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'). * * (a) (1) Unfortunately, ISO-IEC 9899-1999 ANSI-C, Section 6.3.2.3.7 states that "a * pointer to an object ... may be converted to a pointer to a different object * ... [but] if the resulting pointer is not correctly aligned ... the behavior * is undefined". * * And since compilers may NOT correctly convert 'void' pointers to non-'void' * pointer arguments, network timer expiration functions MUST avoid incorrect * pointer conversion behavior between 'void' pointer parameters & non-'void' * pointer arguments & therefore CANNOT be defined as '[(void) (OBJECT *)]'. * * (2) However, Section 6.3.2.3.1 states that "a pointer to void may be converted * to or from a pointer to any ... object ... A pointer to any ... object ... * may be converted to a pointer to void and back again; the result shall * compare equal to the original pointer". * * (b) Therefore, to correctly convert 'void' pointer objects back to appropriate * network object pointer objects, network timer expiration functions MUST : * * (1) Be defined as 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'); & ... * (2) Explicitly cast 'void' pointer arguments to specific object pointers. * * See also 'NetTmr_Get() Note #3'. * * (3) Timer value of 0 ticks/seconds allowed; next tick will expire timer. * * See also 'NetTmr_TaskHandler() Note #6'. ********************************************************************************************************* */ /*$PAGE*/ void NetTmr_Set (NET_TMR *ptmr, CPU_FNCT_PTR fnct, NET_TMR_TICK time, NET_ERR *perr) { #if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) && \ (NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------------------ VALIDATE PTRS ------------------- */ if (ptmr == (NET_TMR *)0) { NET_CTR_ERR_INC(NetTmr_ErrNullPtrCtr); *perr = NET_TMR_ERR_NULL_PTR; return; } if (fnct == (CPU_FNCT_PTR)0) { NET_CTR_ERR_INC(NetTmr_ErrNullFnctCtr); *perr = NET_TMR_ERR_NULL_FNCT; return; } /* ------------------ VALIDATE TYPE ------------------- */ if (ptmr->Type != NET_TMR_TYPE_TMR) { NetTmr_Discard(ptmr); NET_CTR_ERR_INC(NetTmr_ErrInvalidTypeCtr); *perr = NET_TMR_ERR_INVALID_TYPE; return; } #endif ptmr->Fnct = fnct; ptmr->TmrVal = time; *perr = NET_TMR_ERR_NONE; } /*$PAGE*/ /* ********************************************************************************************************* * NetTmr_PoolStatGet() * * Description : Get network timer statistics pool. * * Argument(s) : none. * * Return(s) : Network timer statistics pool, if NO errors. * * NULL statistics pool, otherwise. * * Caller(s) : Application. * * This function is a network protocol suite application interface (API) function & MAY be * called by application function(s). * * Note(s) : (1) NetTmr_PoolStatGet() blocked until network initialization completes; return NULL * statistics pool. ********************************************************************************************************* */ NET_STAT_POOL NetTmr_PoolStatGet (void) { #if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL) CPU_SR cpu_sr; #endif #if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) NET_ERR err; #endif NET_STAT_POOL stat_pool; #if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) if (Net_InitDone != DEF_YES) { /* If init NOT complete, ... */ NetStat_PoolClr(&stat_pool, &err); return (stat_pool); /* ... rtn NULL stat pool (see Note #1). */ } #endif CPU_CRITICAL_ENTER(); stat_pool = NetTmr_PoolStat; CPU_CRITICAL_EXIT(); return (stat_pool); } /*$PAGE*/ /* ********************************************************************************************************* * NetTmr_PoolStatResetMaxUsed() * * Description : Reset network timer statistics pool's maximum number of entries used. * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : Application. * * This function is a network protocol suite application interface (API) function & MAY be * called by application function(s). * * Note(s) : none. ********************************************************************************************************* */ void NetTmr_PoolStatResetMaxUsed (void) { NET_ERR err; NetStat_PoolResetUsedMax(&NetTmr_PoolStat, &err); } /*$PAGE*/ /* ********************************************************************************************************* ********************************************************************************************************* * LOCAL FUNCTIONS ********************************************************************************************************* ********************************************************************************************************* */ /* ********************************************************************************************************* * NetTmr_Clr() * * Description : Clear network timer controls. * * Argument(s) : ptmr Pointer to a network timer. * ---- Argument validated in NetTmr_Init(), * NetTmr_Free(). * * Return(s) : none. * * Caller(s) : NetTmr_Init(), * NetTmr_Free(). * * Note(s) : none. ********************************************************************************************************* */ #if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED) static void NetTmr_Clr (NET_TMR *ptmr) { ptmr->PrevPtr = (void *)0; ptmr->NextPtr = (void *)0; ptmr->Obj = (void *)0; ptmr->Fnct = (CPU_FNCT_PTR)0; ptmr->TmrVal = NET_TMR_TIME_0S; ptmr->Flags = NET_TMR_FLAG_NONE; } #endif /*$PAGE*/ /* ********************************************************************************************************* * NetTmr_Discard() * * Description : (1) Discard an invalid/corrupted network timer : * * (a) Discard timer from available timer pool See Note #2 * (b) Update timer pool statistics * * (2) Assumes timer is invalid/corrupt & MUST be removed. Timer removed simply by NOT * returning the timer back to the timer pool. * * * Argument(s) : ptmr Pointer to an invalid/corrupted network timer. * ---- Argument checked in NetTmr_Get(), * NetTmr_Free(), * NetTmr_Set(). * * Return(s) : none. * * Caller(s) : NetTmr_Get(), * NetTmr_Free(), * NetTmr_Set(). * * Note(s) : none. ********************************************************************************************************* */ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) static void NetTmr_Discard (NET_TMR *ptmr) { NET_ERR stat_err; /* ------------------- DISCARD TMR -------------------- */ (void)&ptmr; /* Prevent compiler warning (see Note #2). */ /* --------------- UPDATE DISCARD STATS --------------- */ NetStat_PoolEntryLostInc(&NetTmr_PoolStat, &stat_err); } #endif /*$PAGE*/ /* ********************************************************************************************************* * NetTmr_DiscardTaskTmr() * * Description : (1) Discard a corrupted Timer Task List timer : * * (a) Unlink Timer Task timer from Timer Task List * * (1) Consequently, any valid or corrupted network timers that may have been linked * following the corrupted Timer Task timer in the Timer Task List are : * * (A) Unlinked from the Timer Task List; ... * (B) Discarded/lost without : * (1) possibility of recovery; ... * (2) measure of the number of network timers lost. * * See also 'NetTmr_TaskHandler() Note #4b1A'. * * (b) Discard Timer Task timer * * (1) Discard the following invalid/corrupted timers : * * (A) Invalid Timer Type * * (2) Do NOT discard the following invalid timers : * * (A) Unused timers * * (c) Clear Timer Task timer pointer * * * (2) (a) Assumes Timer Task List timer ('NetTmr_TaskListPtr') is already corrupted. * * (b) Assumes ALL timers in Timer Task List prior to Timer Task List timer are valid. * * See also 'NetTmr_TaskHandler() Note #4b'. * * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : NetTmr_TaskHandler(). * * Note(s) : none. ********************************************************************************************************* */ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) static void NetTmr_DiscardTaskTmr (void) { NET_TMR *ptmr; NET_TMR *pprev; CPU_BOOLEAN discard; ptmr = (NET_TMR *)NetTmr_TaskListHead; pprev = (NET_TMR *)0; while ((ptmr != (NET_TMR *)0) && /* Srch entire Tmr Task List ... */ (ptmr != (NET_TMR *)NetTmr_TaskListPtr)) { /* ... for corrupted tmr task ptr (see Note #2a). */ pprev = (NET_TMR *)ptmr; ptmr = (NET_TMR *)ptmr->NextPtr; } /* Unlink corrupted tmr task ptr from Tmr Task List : */ if (pprev != (NET_TMR *)0) { /* If NOT @ head of Tmr Task List, ... */ pprev->NextPtr = (void *)0; /* ... clr prev tmr's next tmr. */ } else { /* Else clr Tmr Task List. */ NetTmr_TaskListHead = (NET_TMR *)0; } /* Discard invalid Tmr Task tmr (see Note #1b1). */ discard = (NetTmr_TaskListPtr->Type != NET_TMR_TYPE_TMR) ? DEF_YES : DEF_NO; if (discard == DEF_YES) { NetTmr_Discard(NetTmr_TaskListPtr); } NetTmr_TaskListPtr = (NET_TMR *)0; /* Clr Tmr Task ptr. */ } #endif