os_tmr.c
上传用户:yj_qqy
上传日期:2017-01-28
资源大小:2911k
文件大小:46k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. ************************************************************************************************************************
  3. *                                                uC/OS-II
  4. *                                          The Real-Time Kernel
  5. *                                            TIMER MANAGEMENT
  6. *
  7. *                              (c) Copyright 1992-2007, Micrium, Weston, FL
  8. *                                           All Rights Reserved
  9. *
  10. *
  11. * File    : OS_TMR.C
  12. * By      : Jean J. Labrosse
  13. * Version : V2.86
  14. *
  15. * LICENSING TERMS:
  16. * ---------------
  17. *   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.  
  18. * If you plan on using  uC/OS-II  in a commercial product you need to contact Micri祄 to properly license 
  19. * its use in your product. We provide ALL the source code for your convenience and to help you experience 
  20. * uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a 
  21. * licensing fee.
  22. ************************************************************************************************************************
  23. */
  24. #include <ucos_ii.h>
  25. /*
  26. ************************************************************************************************************************
  27. *                                                        NOTES
  28. *
  29. * 1) Your application MUST define the following #define constants:
  30. *
  31. *    OS_TASK_TMR_PRIO          The priority of the Timer management task
  32. *    OS_TASK_TMR_STK_SIZE      The size     of the Timer management task's stack
  33. *
  34. * 2) You must call OSTmrSignal() to notify the Timer management task that it's time to update the timers.
  35. ************************************************************************************************************************
  36. */
  37. /*
  38. ************************************************************************************************************************
  39. *                                                     CONSTANTS
  40. ************************************************************************************************************************
  41. */
  42. #define  OS_TMR_LINK_DLY       0
  43. #define  OS_TMR_LINK_PERIODIC  1
  44. /*
  45. ************************************************************************************************************************
  46. *                                                  LOCAL PROTOTYPES
  47. ************************************************************************************************************************
  48. */
  49. #if OS_TMR_EN > 0
  50. static  OS_TMR  *OSTmr_Alloc         (void);
  51. static  void     OSTmr_Free          (OS_TMR *ptmr);
  52. static  void     OSTmr_InitTask      (void);
  53. static  void     OSTmr_Link          (OS_TMR *ptmr, INT8U type);
  54. static  void     OSTmr_Unlink        (OS_TMR *ptmr);
  55. static  void     OSTmr_Lock          (void);
  56. static  void     OSTmr_Unlock        (void);
  57. static  void     OSTmr_Task          (void   *p_arg);
  58. #endif
  59. /*$PAGE*/
  60. /*
  61. ************************************************************************************************************************
  62. *                                                   CREATE A TIMER
  63. *
  64. * Description: This function is called by your application code to create a timer.
  65. *
  66. * Arguments  : dly           Initial delay.
  67. *                            If the timer is configured for ONE-SHOT mode, this is the timeout used
  68. *                            If the timer is configured for PERIODIC mode, this is the first timeout to wait for
  69. *                               before the timer starts entering periodic mode
  70. *
  71. *              period        The 'period' being repeated for the timer.
  72. *                               If you specified 'OS_TMR_OPT_PERIODIC' as an option, when the timer expires, it will
  73. *                               automatically restart with the same period.
  74. *
  75. *              opt           Specifies either:
  76. *                               OS_TMR_OPT_ONE_SHOT       The timer counts down only once
  77. *                               OS_TMR_OPT_PERIODIC       The timer counts down and then reloads itself
  78. *
  79. *              callback      Is a pointer to a callback function that will be called when the timer expires.  The
  80. *                               callback function must be declared as follows:
  81. *
  82. *                               void MyCallback (OS_TMR *ptmr, void *p_arg);
  83. *
  84. *              callback_arg  Is an argument (a pointer) that is passed to the callback function when it is called.
  85. *
  86. *              pname         Is a pointer to an ASCII string that is used to name the timer.  Names are useful for
  87. *                               debugging.  The length of the ASCII string for the name can be as big as:
  88. *
  89. *                               OS_TMR_CFG_NAME_SIZE and should be found in OS_CFG.H
  90. *
  91. *              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
  92. *                               OS_ERR_NONE
  93. *                               OS_ERR_TMR_INVALID_DLY     you specified an invalid delay
  94. *                               OS_ERR_TMR_INVALID_PERIOD  you specified an invalid period
  95. *                               OS_ERR_TMR_INVALID_OPT     you specified an invalid option
  96. *                               OS_ERR_TMR_ISR             if the call was made from an ISR
  97. *                               OS_ERR_TMR_NON_AVAIL       if there are no free timers from the timer pool
  98. *                               OS_ERR_TMR_NAME_TOO_LONG   if the timer name is too long to fit
  99. *
  100. * Returns    : A pointer to an OS_TMR data structure.  
  101. *              This is the 'handle' that your application will use to reference the timer created.
  102. ************************************************************************************************************************
  103. */
  104. #if OS_TMR_EN > 0
  105. OS_TMR  *OSTmrCreate (INT32U           dly,
  106.                       INT32U           period,
  107.                       INT8U            opt,
  108.                       OS_TMR_CALLBACK  callback,
  109.                       void            *callback_arg,
  110.                       INT8U           *pname,
  111.                       INT8U           *perr)
  112. {
  113.     OS_TMR   *ptmr;
  114. #if OS_TMR_CFG_NAME_SIZE > 0
  115.     INT8U     len;
  116. #endif
  117. #if OS_ARG_CHK_EN > 0
  118.     if (perr == (INT8U *)0) {                               /* Validate arguments                                     */
  119.         return ((OS_TMR *)0);
  120.     }
  121.     switch (opt) {
  122.         case OS_TMR_OPT_PERIODIC:
  123.              if (period == 0) {
  124.                  *perr = OS_ERR_TMR_INVALID_PERIOD;
  125.                  return ((OS_TMR *)0);
  126.              }
  127.              break;
  128.         case OS_TMR_OPT_ONE_SHOT:
  129.              if (dly == 0) {
  130.                  *perr = OS_ERR_TMR_INVALID_DLY;
  131.                  return ((OS_TMR *)0);
  132.              }
  133.              break;
  134.         default:
  135.              *perr = OS_ERR_TMR_INVALID_OPT;
  136.              return ((OS_TMR *)0);
  137.     }
  138. #endif
  139.     if (OSIntNesting > 0) {                                 /* See if trying to call from an ISR                      */
  140.         *perr  = OS_ERR_TMR_ISR;
  141.         return ((OS_TMR *)0);
  142.     }
  143.     OSTmr_Lock();
  144.     ptmr = OSTmr_Alloc();                                   /* Obtain a timer from the free pool                      */
  145.     if (ptmr == (OS_TMR *)0) {
  146.         OSTmr_Unlock();
  147.         *perr = OS_ERR_TMR_NON_AVAIL;
  148.         return ((OS_TMR *)0);
  149.     }
  150.     ptmr->OSTmrState       = OS_TMR_STATE_STOPPED;          /* Indicate that timer is not running yet                 */
  151.     ptmr->OSTmrDly         = dly;
  152.     ptmr->OSTmrPeriod      = period;
  153.     ptmr->OSTmrOpt         = opt;
  154.     ptmr->OSTmrCallback    = callback;
  155.     ptmr->OSTmrCallbackArg = callback_arg;
  156. #if OS_TMR_CFG_NAME_SIZE > 0
  157.     if (pname !=(INT8U *)0) {
  158.         len = OS_StrLen(pname);                             /* Copy timer name                                        */
  159.         if (len < OS_TMR_CFG_NAME_SIZE) {
  160.             (void)OS_StrCopy(ptmr->OSTmrName, pname);
  161.         } else {
  162. #if OS_TMR_CFG_NAME_SIZE > 1
  163.             ptmr->OSTmrName[0] = '#';                       /* Invalid size specified                                 */
  164.             ptmr->OSTmrName[1] = OS_ASCII_NUL;
  165. #endif
  166.             *perr              = OS_ERR_TMR_NAME_TOO_LONG;
  167.             OSTmr_Unlock();
  168.             return (ptmr);
  169.         }
  170.     }
  171. #endif
  172.     OSTmr_Unlock();
  173.     *perr = OS_ERR_NONE;
  174.     return (ptmr);
  175. }
  176. #endif
  177. /*$PAGE*/
  178. /*
  179. ************************************************************************************************************************
  180. *                                                   DELETE A TIMER
  181. *
  182. * Description: This function is called by your application code to delete a timer.
  183. *
  184. * Arguments  : ptmr          Is a pointer to the timer to stop and delete.
  185. *
  186. *              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
  187. *                               OS_ERR_NONE
  188. *                               OS_ERR_TMR_INVALID        'ptmr'  is a NULL pointer
  189. *                               OS_ERR_TMR_INVALID_TYPE   'ptmr'  is not pointing to an OS_TMR
  190. *                               OS_ERR_TMR_ISR            if the function was called from an ISR
  191. *                               OS_ERR_TMR_INACTIVE       if the timer was not created
  192. *                               OS_ERR_TMR_INVALID_STATE  the timer is in an invalid state
  193. *
  194. * Returns    : OS_TRUE       If the call was successful
  195. *              OS_FALSE      If not
  196. ************************************************************************************************************************
  197. */
  198. #if OS_TMR_EN > 0
  199. BOOLEAN  OSTmrDel (OS_TMR  *ptmr,
  200.                    INT8U   *perr)
  201. {
  202. #if OS_ARG_CHK_EN > 0
  203.     if (perr == (INT8U *)0) {                               /* Validate arguments                                     */
  204.         return (OS_FALSE);
  205.     }
  206.     if (ptmr == (OS_TMR *)0) {
  207.         *perr = OS_ERR_TMR_INVALID;
  208.         return (OS_FALSE);
  209.     }
  210. #endif
  211.     if (ptmr->OSTmrType != OS_TMR_TYPE) {                   /* Validate timer structure                               */
  212.         *perr = OS_ERR_TMR_INVALID_TYPE;
  213.         return (OS_FALSE);
  214.     }
  215.     if (OSIntNesting > 0) {                                 /* See if trying to call from an ISR                      */
  216.         *perr  = OS_ERR_TMR_ISR;
  217.         return (OS_FALSE);
  218.     }
  219.     OSTmr_Lock();
  220.     switch (ptmr->OSTmrState) {
  221.         case OS_TMR_STATE_RUNNING:
  222.              OSTmr_Unlink(ptmr);                            /* Remove from current wheel spoke                        */
  223.              OSTmr_Free(ptmr);                              /* Return timer to free list of timers                    */
  224.              OSTmr_Unlock();
  225.              *perr = OS_ERR_NONE;
  226.              return (OS_TRUE);
  227.         case OS_TMR_STATE_STOPPED:                          /* Timer has not started or ...                           */
  228.         case OS_TMR_STATE_COMPLETED:                        /* ... timer has completed the ONE-SHOT time              */
  229.              OSTmr_Free(ptmr);                              /* Return timer to free list of timers                    */
  230.              OSTmr_Unlock();
  231.              *perr = OS_ERR_NONE;
  232.              return (OS_TRUE);
  233.         case OS_TMR_STATE_UNUSED:                           /* Already deleted                                        */
  234.              OSTmr_Unlock();
  235.              *perr = OS_ERR_TMR_INACTIVE;
  236.              return (OS_FALSE);
  237.         default:
  238.              OSTmr_Unlock();
  239.              *perr = OS_ERR_TMR_INVALID_STATE;
  240.              return (OS_FALSE);
  241.     }
  242. }
  243. #endif
  244. /*$PAGE*/
  245. /*
  246. ************************************************************************************************************************
  247. *                                             GET THE NAME OF A TIMER
  248. *
  249. * Description: This function is called to obtain the name of a timer.
  250. *
  251. * Arguments  : ptmr          Is a pointer to the timer to obtain the name for
  252. *
  253. *              pdest         Is a pointer to where the name of the timer will be placed.  It is the caller's responsibility
  254. *                            to ensure that he has sufficient storage in the destination, i.e. at least OS_TMR_CFG_NAME_SIZE
  255. *
  256. *              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
  257. *                               OS_ERR_NONE               The call was successful
  258. *                               OS_ERR_TMR_INVALID_DEST   'pdest' is a NULL pointer
  259. *                               OS_ERR_TMR_INVALID        'ptmr'  is a NULL pointer
  260. *                               OS_ERR_TMR_INVALID_TYPE   'ptmr'  is not pointing to an OS_TMR
  261. *                               OS_ERR_NAME_GET_ISR       if the call was made from an ISR
  262. *                               OS_ERR_TMR_INACTIVE       'ptmr'  points to a timer that is not active
  263. *                               OS_ERR_TMR_INVALID_STATE  the timer is in an invalid state
  264. *
  265. * Returns    : The length of the string or 0 if the timer does not exist.
  266. ************************************************************************************************************************
  267. */
  268. #if OS_TMR_EN > 0 && OS_TMR_CFG_NAME_SIZE > 0
  269. INT8U  OSTmrNameGet (OS_TMR  *ptmr,
  270.                      INT8U   *pdest,
  271.                      INT8U   *perr)
  272. {
  273.     INT8U  len;
  274. #if OS_ARG_CHK_EN > 0
  275.     if (perr == (INT8U *)0) {
  276.         return (0);
  277.     }
  278.     if (pdest == (INT8U *)0) {
  279.         *perr = OS_ERR_TMR_INVALID_DEST;
  280.         return (0);
  281.     }
  282.     if (ptmr == (OS_TMR *)0) {
  283.         *perr = OS_ERR_TMR_INVALID;
  284.         return (0);
  285.     }
  286. #endif
  287.     if (ptmr->OSTmrType != OS_TMR_TYPE) {              /* Validate timer structure                                    */
  288.         *perr = OS_ERR_TMR_INVALID_TYPE;
  289.         return (0);
  290.     }
  291.     if (OSIntNesting > 0) {                            /* See if trying to call from an ISR                           */
  292.         *perr = OS_ERR_NAME_GET_ISR;
  293.         return (0);
  294.     }
  295.     OSTmr_Lock();
  296.     switch (ptmr->OSTmrState) {
  297.         case OS_TMR_STATE_RUNNING:
  298.         case OS_TMR_STATE_STOPPED:
  299.         case OS_TMR_STATE_COMPLETED:
  300.              len   = OS_StrCopy(pdest, ptmr->OSTmrName);
  301.              OSTmr_Unlock();
  302.              *perr = OS_ERR_NONE;
  303.              return (len);
  304.         case OS_TMR_STATE_UNUSED:                      /* Timer is not allocated                                      */
  305.              OSTmr_Unlock();
  306.              *perr = OS_ERR_TMR_INACTIVE;
  307.              return (0);
  308.         default:
  309.              OSTmr_Unlock();
  310.              *perr = OS_ERR_TMR_INVALID_STATE;
  311.              return (0);
  312.     }
  313. }
  314. #endif
  315. /*$PAGE*/
  316. /*
  317. ************************************************************************************************************************
  318. *                                    GET HOW MUCH TIME IS LEFT BEFORE A TIMER EXPIRES
  319. *
  320. * Description: This function is called to get the number of ticks before a timer times out.
  321. *
  322. * Arguments  : ptmr          Is a pointer to the timer to obtain the remaining time from.
  323. *
  324. *              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
  325. *                               OS_ERR_NONE
  326. *                               OS_ERR_TMR_INVALID        'ptmr' is a NULL pointer
  327. *                               OS_ERR_TMR_INVALID_TYPE   'ptmr'  is not pointing to an OS_TMR
  328. *                               OS_ERR_TMR_ISR            if the call was made from an ISR
  329. *                               OS_ERR_TMR_INACTIVE       'ptmr' points to a timer that is not active
  330. *                               OS_ERR_TMR_INVALID_STATE  the timer is in an invalid state
  331. *
  332. * Returns    : The time remaining for the timer to expire.  The time represents 'timer' increments.  In other words, if
  333. *              OSTmr_Task() is signaled every 1/10 of a second then the returned value represents the number of 1/10 of
  334. *              a second remaining before the timer expires.
  335. ************************************************************************************************************************
  336. */
  337. #if OS_TMR_EN > 0
  338. INT32U  OSTmrRemainGet (OS_TMR  *ptmr,
  339.                         INT8U   *perr)
  340. {
  341.     INT32U  remain;
  342. #if OS_ARG_CHK_EN > 0
  343.     if (perr == (INT8U *)0) {
  344.         return (0);
  345.     }
  346.     if (ptmr == (OS_TMR *)0) {
  347.         *perr = OS_ERR_TMR_INVALID;
  348.         return (0);
  349.     }
  350. #endif
  351.     if (ptmr->OSTmrType != OS_TMR_TYPE) {              /* Validate timer structure                                    */
  352.         *perr = OS_ERR_TMR_INVALID_TYPE;
  353.         return (0);
  354.     }
  355.     if (OSIntNesting > 0) {                            /* See if trying to call from an ISR                           */
  356.         *perr = OS_ERR_TMR_ISR;
  357.         return (0);
  358.     }
  359.     OSTmr_Lock();
  360.     switch (ptmr->OSTmrState) {
  361.         case OS_TMR_STATE_RUNNING:
  362.              remain = ptmr->OSTmrMatch - OSTmrTime;    /* Determine how much time is left to timeout                  */
  363.              OSTmr_Unlock();
  364.              *perr  = OS_ERR_NONE;
  365.              return (remain);
  366.         case OS_TMR_STATE_STOPPED:                     /* It's assumed that the timer has not started yet             */
  367.              switch (ptmr->OSTmrOpt) {
  368.                  case OS_TMR_OPT_PERIODIC:
  369.                       if (ptmr->OSTmrDly == 0) {
  370.                           remain = ptmr->OSTmrPeriod;
  371.                       } else {
  372.                           remain = ptmr->OSTmrDly;
  373.                       }
  374.                       OSTmr_Unlock();
  375.                       *perr  = OS_ERR_NONE;
  376.                       break;
  377.                  case OS_TMR_OPT_ONE_SHOT:
  378.                  default:
  379.                       remain = ptmr->OSTmrDly;
  380.                       OSTmr_Unlock();
  381.                       *perr  = OS_ERR_NONE;
  382.                       break;
  383.              }
  384.              return (remain);
  385.         case OS_TMR_STATE_COMPLETED:                   /* Only ONE-SHOT that timed out can be in this state           */
  386.              OSTmr_Unlock();
  387.              *perr = OS_ERR_NONE;
  388.              return (0);
  389.         case OS_TMR_STATE_UNUSED:
  390.              OSTmr_Unlock();
  391.              *perr = OS_ERR_TMR_INACTIVE;
  392.              return (0);
  393.         default:
  394.              OSTmr_Unlock();
  395.              *perr = OS_ERR_TMR_INVALID_STATE;
  396.              return (0);
  397.     }
  398. }
  399. #endif
  400. /*$PAGE*/
  401. /*
  402. ************************************************************************************************************************
  403. *                                    FIND OUT WHAT STATE A TIMER IS IN
  404. *
  405. * Description: This function is called to determine what state the timer is in:
  406. *
  407. *                  OS_TMR_STATE_UNUSED     the timer has not been created
  408. *                  OS_TMR_STATE_STOPPED    the timer has been created but has not been started or has been stopped
  409. *                  OS_TMR_COMPLETED        the timer is in ONE-SHOT mode and has completed it's timeout
  410. *                  OS_TMR_RUNNING          the timer is currently running
  411. *
  412. * Arguments  : ptmr          Is a pointer to the desired timer
  413. *
  414. *              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
  415. *                               OS_ERR_NONE
  416. *                               OS_ERR_TMR_INVALID        'ptmr' is a NULL pointer
  417. *                               OS_ERR_TMR_INVALID_TYPE   'ptmr'  is not pointing to an OS_TMR
  418. *                               OS_ERR_TMR_ISR            if the call was made from an ISR
  419. *                               OS_ERR_TMR_INACTIVE       'ptmr' points to a timer that is not active
  420. *                               OS_ERR_TMR_INVALID_STATE  if the timer is not in a valid state
  421. *
  422. * Returns    : The current state of the timer (see description).
  423. ************************************************************************************************************************
  424. */
  425. #if OS_TMR_EN > 0
  426. INT8U  OSTmrStateGet (OS_TMR  *ptmr,
  427.                       INT8U   *perr)
  428. {
  429.     INT8U  state;
  430. #if OS_ARG_CHK_EN > 0
  431.     if (perr == (INT8U *)0) {
  432.         return (0);
  433.     }
  434.     if (ptmr == (OS_TMR *)0) {
  435.         *perr = OS_ERR_TMR_INVALID;
  436.         return (0);
  437.     }
  438. #endif
  439.     if (ptmr->OSTmrType != OS_TMR_TYPE) {              /* Validate timer structure                                    */
  440.         *perr = OS_ERR_TMR_INVALID_TYPE;
  441.         return (0);
  442.     }
  443.     if (OSIntNesting > 0) {                            /* See if trying to call from an ISR                           */
  444.         *perr = OS_ERR_TMR_ISR;
  445.         return (0);
  446.     }
  447.     OSTmr_Lock();
  448.     state = ptmr->OSTmrState;
  449.     switch (state) {
  450.         case OS_TMR_STATE_UNUSED:   
  451.         case OS_TMR_STATE_STOPPED:  
  452.         case OS_TMR_STATE_COMPLETED:
  453.         case OS_TMR_STATE_RUNNING:  
  454.              *perr = OS_ERR_NONE;
  455.              break;
  456.              
  457.         default:
  458.              *perr = OS_ERR_TMR_INVALID_STATE;
  459.              break;
  460.     }
  461.     OSTmr_Unlock();
  462.     return (state);
  463. }
  464. #endif
  465. /*$PAGE*/
  466. /*
  467. ************************************************************************************************************************
  468. *                                                   START A TIMER
  469. *
  470. * Description: This function is called by your application code to start a timer.
  471. *
  472. * Arguments  : ptmr          Is a pointer to an OS_TMR
  473. *
  474. *              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
  475. *                               OS_ERR_NONE
  476. *                               OS_ERR_TMR_INVALID
  477. *                               OS_ERR_TMR_INVALID_TYPE    'ptmr'  is not pointing to an OS_TMR
  478. *                               OS_ERR_TMR_ISR             if the call was made from an ISR
  479. *                               OS_ERR_TMR_INACTIVE        if the timer was not created
  480. *                               OS_ERR_TMR_INVALID_STATE   the timer is in an invalid state
  481. *
  482. * Returns    : OS_TRUE    if the timer was started
  483. *              OS_FALSE   if an error was detected
  484. ************************************************************************************************************************
  485. */
  486. #if OS_TMR_EN > 0
  487. BOOLEAN  OSTmrStart (OS_TMR   *ptmr,
  488.                      INT8U    *perr)
  489. {
  490. #if OS_ARG_CHK_EN > 0
  491.     if (perr == (INT8U *)0) {                               /* Validate arguments                                     */
  492.         return (OS_FALSE);
  493.     }
  494.     if (ptmr == (OS_TMR *)0) {
  495.         *perr = OS_ERR_TMR_INVALID;
  496.         return (OS_FALSE);
  497.     }
  498. #endif
  499.     if (ptmr->OSTmrType != OS_TMR_TYPE) {                   /* Validate timer structure                               */
  500.         *perr = OS_ERR_TMR_INVALID_TYPE;
  501.         return (OS_FALSE);
  502.     }
  503.     if (OSIntNesting > 0) {                                 /* See if trying to call from an ISR                      */
  504.         *perr  = OS_ERR_TMR_ISR;
  505.         return (OS_FALSE);
  506.     }
  507.     OSTmr_Lock();
  508.     switch (ptmr->OSTmrState) {
  509.         case OS_TMR_STATE_RUNNING:                          /* Restart the timer                                      */
  510.              OSTmr_Unlink(ptmr);                            /* ... Stop the timer                                     */
  511.              OSTmr_Link(ptmr, OS_TMR_LINK_DLY);             /* ... Link timer to timer wheel                          */
  512.              OSTmr_Unlock();
  513.              *perr = OS_ERR_NONE;
  514.              return (OS_TRUE);
  515.         case OS_TMR_STATE_STOPPED:                          /* Start the timer                                        */
  516.         case OS_TMR_STATE_COMPLETED:
  517.              OSTmr_Link(ptmr, OS_TMR_LINK_DLY);             /* ... Link timer to timer wheel                          */
  518.              OSTmr_Unlock();
  519.              *perr = OS_ERR_NONE;
  520.              return (OS_TRUE);
  521.         case OS_TMR_STATE_UNUSED:                           /* Timer not created                                      */
  522.              OSTmr_Unlock();
  523.              *perr = OS_ERR_TMR_INACTIVE;
  524.              return (OS_FALSE);
  525.         default:
  526.              OSTmr_Unlock();
  527.              *perr = OS_ERR_TMR_INVALID_STATE;
  528.              return (OS_FALSE);
  529.     }
  530. }
  531. #endif
  532. /*$PAGE*/
  533. /*
  534. ************************************************************************************************************************
  535. *                                                   STOP A TIMER
  536. *
  537. * Description: This function is called by your application code to stop a timer.
  538. *
  539. * Arguments  : ptmr          Is a pointer to the timer to stop.
  540. *
  541. *              opt           Allows you to specify an option to this functions which can be:
  542. *
  543. *                               OS_TMR_OPT_NONE          Do nothing special but stop the timer
  544. *                               OS_TMR_OPT_CALLBACK      Execute the callback function, pass it the callback argument
  545. *                                                        specified when the timer was created.
  546. *                               OS_TMR_OPT_CALLBACK_ARG  Execute the callback function, pass it the callback argument
  547. *                                                        specified in THIS function call
  548. *
  549. *              callback_arg  Is a pointer to a 'new' callback argument that can be passed to the callback function
  550. *                               instead of the timer's callback argument.  In other words, use 'callback_arg' passed in
  551. *                               THIS function INSTEAD of ptmr->OSTmrCallbackArg
  552. *
  553. *              perr          Is a pointer to an error code.  '*perr' will contain one of the following:
  554. *                               OS_ERR_NONE
  555. *                               OS_ERR_TMR_INVALID         'ptmr' is a NULL pointer
  556. *                               OS_ERR_TMR_INVALID_TYPE    'ptmr'  is not pointing to an OS_TMR
  557. *                               OS_ERR_TMR_ISR             if the function was called from an ISR
  558. *                               OS_ERR_TMR_INACTIVE        if the timer was not created
  559. *                               OS_ERR_TMR_INVALID_OPT     if you specified an invalid option for 'opt'
  560. *                               OS_ERR_TMR_STOPPED         if the timer was already stopped
  561. *                               OS_ERR_TMR_INVALID_STATE   the timer is in an invalid state
  562. *                               OS_ERR_TMR_NO_CALLBACK     if the timer does not have a callback function defined
  563. *
  564. * Returns    : OS_TRUE       If we stopped the timer (if the timer is already stopped, we also return OS_TRUE)
  565. *              OS_FALSE      If not
  566. ************************************************************************************************************************
  567. */
  568. #if OS_TMR_EN > 0
  569. BOOLEAN  OSTmrStop (OS_TMR  *ptmr,
  570.                     INT8U    opt,
  571.                     void    *callback_arg,
  572.                     INT8U   *perr)
  573. {
  574.     OS_TMR_CALLBACK  pfnct;
  575. #if OS_ARG_CHK_EN > 0
  576.     if (perr == (INT8U *)0) {                                     /* Validate arguments                               */
  577.         return (OS_FALSE);
  578.     }
  579.     if (ptmr == (OS_TMR *)0) {
  580.         *perr = OS_ERR_TMR_INVALID;
  581.         return (OS_FALSE);
  582.     }
  583. #endif
  584.     if (ptmr->OSTmrType != OS_TMR_TYPE) {                         /* Validate timer structure                         */
  585.         *perr = OS_ERR_TMR_INVALID_TYPE;
  586.         return (OS_FALSE);
  587.     }
  588.     if (OSIntNesting > 0) {                                       /* See if trying to call from an ISR                */
  589.         *perr  = OS_ERR_TMR_ISR;
  590.         return (OS_FALSE);
  591.     }
  592.     OSTmr_Lock();
  593.     switch (ptmr->OSTmrState) {
  594.         case OS_TMR_STATE_RUNNING:
  595.              OSTmr_Unlink(ptmr);                                  /* Remove from current wheel spoke                  */
  596.              *perr = OS_ERR_NONE;
  597.              switch (opt) {
  598.                  case OS_TMR_OPT_CALLBACK:
  599.                       pfnct = ptmr->OSTmrCallback;                /* Execute callback function if available ...       */
  600.                       if (pfnct != (OS_TMR_CALLBACK)0) {
  601.                           (*pfnct)((void *)ptmr, ptmr->OSTmrCallbackArg);  /* Use callback arg when timer was created */
  602.                       } else {
  603.                           *perr = OS_ERR_TMR_NO_CALLBACK;
  604.                       }
  605.                       break;
  606.                  case OS_TMR_OPT_CALLBACK_ARG:
  607.                       pfnct = ptmr->OSTmrCallback;                /* Execute callback function if available ...       */
  608.                       if (pfnct != (OS_TMR_CALLBACK)0) {
  609.                           (*pfnct)((void *)ptmr, callback_arg);   /* ... using the 'callback_arg' provided in call    */
  610.                       } else {
  611.                           *perr = OS_ERR_TMR_NO_CALLBACK;
  612.                       }
  613.                       break;
  614.                  case OS_TMR_OPT_NONE:
  615.                       break;
  616.                  default:
  617.                      *perr = OS_ERR_TMR_INVALID_OPT;
  618.                      break;
  619.              }
  620.              OSTmr_Unlock();
  621.              return (OS_TRUE);
  622.         case OS_TMR_STATE_COMPLETED:                              /* Timer has already completed the ONE-SHOT or ...  */
  623.         case OS_TMR_STATE_STOPPED:                                /* ... timer has not started yet.                   */
  624.              OSTmr_Unlock();
  625.              *perr = OS_ERR_TMR_STOPPED;
  626.              return (OS_TRUE);
  627.         case OS_TMR_STATE_UNUSED:                                 /* Timer was not created                            */
  628.              OSTmr_Unlock();
  629.              *perr = OS_ERR_TMR_INACTIVE;
  630.              return (OS_FALSE);
  631.         default:
  632.              OSTmr_Unlock();
  633.              *perr = OS_ERR_TMR_INVALID_STATE;
  634.              return (OS_FALSE);
  635.     }
  636. }
  637. #endif
  638. /*$PAGE*/
  639. /*
  640. ************************************************************************************************************************
  641. *                                      SIGNAL THAT IT'S TIME TO UPDATE THE TIMERS
  642. *
  643. * Description: This function is typically called by the ISR that occurs at the timer tick rate and is used to signal to
  644. *              OSTmr_Task() that it's time to update the timers.
  645. *
  646. * Arguments  : none
  647. *
  648. * Returns    : OS_ERR_NONE         The call was successful and the timer task was signaled.
  649. *              OS_ERR_SEM_OVF      If OSTmrSignal() was called more often than OSTmr_Task() can handle the timers.  
  650. *                                  This would indicate that your system is heavily loaded.
  651. *              OS_ERR_EVENT_TYPE   Unlikely you would get this error because the semaphore used for signaling is created 
  652. *                                  by uC/OS-II.
  653. *              OS_ERR_PEVENT_NULL  Again, unlikely you would ever get this error because the semaphore used for signaling 
  654. *                                  is created by uC/OS-II.
  655. ************************************************************************************************************************
  656. */
  657. #if OS_TMR_EN > 0
  658. INT8U  OSTmrSignal (void)
  659. {
  660.     INT8U  err;
  661.     err = OSSemPost(OSTmrSemSignal);
  662.     return (err);
  663. }
  664. #endif
  665. /*$PAGE*/
  666. /*
  667. ************************************************************************************************************************
  668. *                                               ALLOCATE AND FREE A TIMER
  669. *
  670. * Description: This function is called to allocate a timer.
  671. *
  672. * Arguments  : none
  673. *
  674. * Returns    : a pointer to a timer if one is available
  675. ************************************************************************************************************************
  676. */
  677. #if OS_TMR_EN > 0
  678. static  OS_TMR  *OSTmr_Alloc (void)
  679. {
  680.     OS_TMR *ptmr;
  681.     if (OSTmrFreeList == (OS_TMR *)0) {
  682.         return ((OS_TMR *)0);
  683.     }
  684.     ptmr            = (OS_TMR *)OSTmrFreeList;
  685.     OSTmrFreeList   = (OS_TMR *)ptmr->OSTmrNext;
  686.     ptmr->OSTmrNext = (OS_TCB *)0;
  687.     ptmr->OSTmrPrev = (OS_TCB *)0;
  688.     OSTmrUsed++;
  689.     OSTmrFree--;
  690.     return (ptmr);
  691. }
  692. #endif
  693. /*
  694. ************************************************************************************************************************
  695. *                                             RETURN A TIMER TO THE FREE LIST
  696. *
  697. * Description: This function is called to return a timer object to the free list of timers.
  698. *
  699. * Arguments  : ptmr     is a pointer to the timer to free
  700. *
  701. * Returns    : none
  702. ************************************************************************************************************************
  703. */
  704. #if OS_TMR_EN > 0
  705. static  void  OSTmr_Free (OS_TMR *ptmr)
  706. {
  707.     ptmr->OSTmrState       = OS_TMR_STATE_UNUSED;      /* Clear timer object fields                                   */
  708.     ptmr->OSTmrOpt         = OS_TMR_OPT_NONE;
  709.     ptmr->OSTmrPeriod      = 0;
  710.     ptmr->OSTmrMatch       = 0;
  711.     ptmr->OSTmrCallback    = (OS_TMR_CALLBACK)0;
  712.     ptmr->OSTmrCallbackArg = (void *)0;
  713. #if OS_TMR_CFG_NAME_SIZE > 1
  714.     ptmr->OSTmrName[0]     = '?';                      /* Unknown name                                                */
  715.     ptmr->OSTmrName[1]     = OS_ASCII_NUL;
  716. #endif
  717.     ptmr->OSTmrPrev        = (OS_TCB *)0;              /* Chain timer to free list                                    */
  718.     ptmr->OSTmrNext        = OSTmrFreeList;
  719.     OSTmrFreeList          = ptmr;
  720.     OSTmrUsed--;                                       /* Update timer object statistics                              */
  721.     OSTmrFree++;
  722. }
  723. #endif
  724. /*$PAGE*/
  725. /*
  726. ************************************************************************************************************************
  727. *                                                    INITIALIZATION
  728. *                                          INITIALIZE THE FREE LIST OF TIMERS
  729. *
  730. * Description: This function is called by OSInit() to initialize the free list of OS_TMRs.
  731. *
  732. * Arguments  : none
  733. *
  734. * Returns    : none
  735. ************************************************************************************************************************
  736. */
  737. #if OS_TMR_EN > 0
  738. void  OSTmr_Init (void)
  739. {
  740. #if OS_EVENT_NAME_SIZE > 10
  741.     INT8U    err;
  742. #endif
  743.     INT16U   i;
  744.     OS_TMR  *ptmr1;
  745.     OS_TMR  *ptmr2;
  746.     OS_MemClr((INT8U *)&OSTmrTbl[0],      sizeof(OSTmrTbl));            /* Clear all the TMRs                         */
  747.     OS_MemClr((INT8U *)&OSTmrWheelTbl[0], sizeof(OSTmrWheelTbl));       /* Clear the timer wheel                      */
  748.     ptmr1 = &OSTmrTbl[0];
  749.     ptmr2 = &OSTmrTbl[1];
  750.     for (i = 0; i < (OS_TMR_CFG_MAX - 1); i++) {                        /* Init. list of free TMRs                    */
  751.         ptmr1->OSTmrType    = OS_TMR_TYPE;
  752.         ptmr1->OSTmrState   = OS_TMR_STATE_UNUSED;                      /* Indicate that timer is inactive            */
  753.         ptmr1->OSTmrNext    = (void *)ptmr2;                            /* Link to next timer                         */
  754. #if OS_TMR_CFG_NAME_SIZE > 1
  755.         ptmr1->OSTmrName[0] = '?';                                      /* Unknown name                               */
  756.         ptmr1->OSTmrName[1] = OS_ASCII_NUL;
  757. #endif
  758.         ptmr1++;
  759.         ptmr2++;
  760.     }
  761.     ptmr1->OSTmrType    = OS_TMR_TYPE;
  762.     ptmr1->OSTmrState   = OS_TMR_STATE_UNUSED;                          /* Indicate that timer is inactive            */
  763.     ptmr1->OSTmrNext    = (void *)0;                                    /* Last OS_TMR                                */
  764. #if OS_TMR_CFG_NAME_SIZE > 1
  765.     ptmr1->OSTmrName[0] = '?';                                          /* Unknown name                               */
  766.     ptmr1->OSTmrName[1] = OS_ASCII_NUL;
  767. #endif
  768.     OSTmrTime           = 0;
  769.     OSTmrUsed           = 0;
  770.     OSTmrFree           = OS_TMR_CFG_MAX;
  771.     OSTmrFreeList       = &OSTmrTbl[0];
  772.     OSTmrSem            = OSSemCreate(1);
  773.     OSTmrSemSignal      = OSSemCreate(0);
  774. #if OS_EVENT_NAME_SIZE > 18
  775.     OSEventNameSet(OSTmrSem,       (INT8U *)"uC/OS-II TmrLock",   &err);/* Assign names to semaphores                 */
  776. #else
  777. #if OS_EVENT_NAME_SIZE > 10
  778.     OSEventNameSet(OSTmrSem,       (INT8U *)"OS-TmrLock",         &err);
  779. #endif
  780. #endif
  781. #if OS_EVENT_NAME_SIZE > 18
  782.     OSEventNameSet(OSTmrSemSignal, (INT8U *)"uC/OS-II TmrSignal", &err);
  783. #else
  784. #if OS_EVENT_NAME_SIZE > 10
  785.     OSEventNameSet(OSTmrSemSignal, (INT8U *)"OS-TmrSig",          &err);
  786. #endif
  787. #endif
  788.     OSTmr_InitTask();
  789. }
  790. #endif
  791. /*$PAGE*/
  792. /*
  793. ************************************************************************************************************************
  794. *                                          INITIALIZE THE TIMER MANAGEMENT TASK
  795. *
  796. * Description: This function is called by OSTmrInit() to create the timer management task.
  797. *
  798. * Arguments  : none
  799. *
  800. * Returns    : none
  801. ************************************************************************************************************************
  802. */
  803. #if OS_TMR_EN > 0
  804. static  void  OSTmr_InitTask (void)
  805. {
  806. #if OS_TASK_NAME_SIZE > 6
  807.     INT8U  err;
  808. #endif
  809. #if OS_TASK_CREATE_EXT_EN > 0
  810.     #if OS_STK_GROWTH == 1
  811.     (void)OSTaskCreateExt(OSTmr_Task,
  812.                           (void *)0,                                       /* No arguments passed to OSTmrTask()      */
  813.                           &OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1],         /* Set Top-Of-Stack                        */
  814.                           OS_TASK_TMR_PRIO,
  815.                           OS_TASK_TMR_ID,
  816.                           &OSTmrTaskStk[0],                                /* Set Bottom-Of-Stack                     */
  817.                           OS_TASK_TMR_STK_SIZE,
  818.                           (void *)0,                                       /* No TCB extension                        */
  819.                           OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);      /* Enable stack checking + clear stack     */
  820.     #else
  821.     (void)OSTaskCreateExt(OSTmr_Task,
  822.                           (void *)0,                                       /* No arguments passed to OSTmrTask()      */
  823.                           &OSTmrTaskStk[0],                                /* Set Top-Of-Stack                        */
  824.                           OS_TASK_TMR_PRIO,
  825.                           OS_TASK_TMR_ID,
  826.                           &OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1],         /* Set Bottom-Of-Stack                     */
  827.                           OS_TASK_TMR_STK_SIZE,
  828.                           (void *)0,                                       /* No TCB extension                        */
  829.                           OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);      /* Enable stack checking + clear stack     */
  830.     #endif
  831. #else
  832.     #if OS_STK_GROWTH == 1
  833.     (void)OSTaskCreate(OSTmr_Task,
  834.                        (void *)0,
  835.                        &OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1],
  836.                        OS_TASK_TMR_PRIO);
  837.     #else
  838.     (void)OSTaskCreate(OSTmr_Task,
  839.                        (void *)0,
  840.                        &OSTmrTaskStk[0],
  841.                        OS_TASK_TMR_PRIO);
  842.     #endif
  843. #endif
  844. #if OS_TASK_NAME_SIZE > 12
  845.     OSTaskNameSet(OS_TASK_TMR_PRIO, (INT8U *)"uC/OS-II Tmr", &err);
  846. #else
  847. #if OS_TASK_NAME_SIZE > 6
  848.     OSTaskNameSet(OS_TASK_TMR_PRIO, (INT8U *)"OS-Tmr", &err);
  849. #endif
  850. #endif
  851. }
  852. #endif
  853. /*$PAGE*/
  854. /*
  855. ************************************************************************************************************************
  856. *                                         INSERT A TIMER INTO THE TIMER WHEEL
  857. *
  858. * Description: This function is called to insert the timer into the timer wheel.  The timer is always inserted at the
  859. *              beginning of the list.
  860. *
  861. * Arguments  : ptmr          Is a pointer to the timer to insert.
  862. *
  863. *              type          Is either:
  864. *                               OS_TMR_LINK_PERIODIC    Means to re-insert the timer after a period expired
  865. *                               OS_TMR_LINK_DLY         Means to insert    the timer the first time
  866. *
  867. * Returns    : none
  868. ************************************************************************************************************************
  869. */
  870. #if OS_TMR_EN > 0
  871. static  void  OSTmr_Link (OS_TMR *ptmr, INT8U type)
  872. {
  873.     OS_TMR       *ptmr1;
  874.     OS_TMR_WHEEL *pspoke;
  875.     INT16U        spoke;
  876.     ptmr->OSTmrState = OS_TMR_STATE_RUNNING;
  877.     if (type == OS_TMR_LINK_PERIODIC) {                            /* Determine when timer will expire                */
  878.         ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime;
  879.     } else {
  880.         if (ptmr->OSTmrDly == 0) {
  881.             ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime;
  882.         } else {
  883.             ptmr->OSTmrMatch = ptmr->OSTmrDly    + OSTmrTime;
  884.         }
  885.     }
  886.     spoke  = (INT16U)(ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE);
  887.     pspoke = &OSTmrWheelTbl[spoke];
  888.     if (pspoke->OSTmrFirst == (OS_TMR *)0) {                       /* Link into timer wheel                           */
  889.         pspoke->OSTmrFirst   = ptmr;
  890.         ptmr->OSTmrNext      = (OS_TMR *)0;
  891.         pspoke->OSTmrEntries = 1;
  892.     } else {
  893.         ptmr1                = pspoke->OSTmrFirst;                 /* Point to first timer in the spoke               */
  894.         pspoke->OSTmrFirst   = ptmr;
  895.         ptmr->OSTmrNext      = (void *)ptmr1;
  896.         ptmr1->OSTmrPrev     = (void *)ptmr;
  897.         pspoke->OSTmrEntries++;
  898.     }
  899.     ptmr->OSTmrPrev = (void *)0;                                   /* Timer always inserted as first node in list     */
  900. }
  901. #endif
  902. /*$PAGE*/
  903. /*
  904. ************************************************************************************************************************
  905. *                                         REMOVE A TIMER FROM THE TIMER WHEEL
  906. *
  907. * Description: This function is called to remove the timer from the timer wheel.
  908. *
  909. * Arguments  : ptmr          Is a pointer to the timer to remove.
  910. *
  911. * Returns    : none
  912. ************************************************************************************************************************
  913. */
  914. #if OS_TMR_EN > 0
  915. static  void  OSTmr_Unlink (OS_TMR *ptmr)
  916. {
  917.     OS_TMR        *ptmr1;
  918.     OS_TMR        *ptmr2;
  919.     OS_TMR_WHEEL  *pspoke;
  920.     INT16U         spoke;
  921.     spoke  = (INT16U)(ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE);
  922.     pspoke = &OSTmrWheelTbl[spoke];
  923.     if (pspoke->OSTmrFirst == ptmr) {                       /* See if timer to remove is at the beginning of list     */
  924.         ptmr1              = (OS_TMR *)ptmr->OSTmrNext;
  925.         pspoke->OSTmrFirst = (OS_TMR *)ptmr1;
  926.         if (ptmr1 != (OS_TMR *)0) {
  927.             ptmr1->OSTmrPrev = (void *)0;
  928.         }
  929.     } else {
  930.         ptmr1            = (OS_TMR *)ptmr->OSTmrPrev;       /* Remove timer from somewhere in the list                */
  931.         ptmr2            = (OS_TMR *)ptmr->OSTmrNext;
  932.         ptmr1->OSTmrNext = ptmr2;
  933.         if (ptmr2 != (OS_TMR *)0) {
  934.             ptmr2->OSTmrPrev = (void *)ptmr1;
  935.         }
  936.     }
  937.     ptmr->OSTmrState = OS_TMR_STATE_STOPPED;
  938.     ptmr->OSTmrNext  = (void *)0;
  939.     ptmr->OSTmrPrev  = (void *)0;
  940.     pspoke->OSTmrEntries--;
  941. }
  942. #endif
  943. /*$PAGE*/
  944. /*
  945. ************************************************************************************************************************
  946. *                                       TIMER MANAGER DATA STRUCTURE LOCKING MECHANISM
  947. *
  948. * Description: These functions are used to gain exclusive access to timer management data structures.
  949. *
  950. * Arguments  : none
  951. *
  952. * Returns    : none
  953. ************************************************************************************************************************
  954. */
  955. #if OS_TMR_EN > 0
  956. static  void  OSTmr_Lock (void)
  957. {
  958.     INT8U  err;
  959.     OSSemPend(OSTmrSem, 0, &err);
  960.     (void)err;
  961. }
  962. #endif
  963. #if OS_TMR_EN > 0
  964. static  void  OSTmr_Unlock (void)
  965. {
  966.     (void)OSSemPost(OSTmrSem);
  967. }
  968. #endif
  969. /*$PAGE*/
  970. /*
  971. ************************************************************************************************************************
  972. *                                                 TIMER MANAGEMENT TASK
  973. *
  974. * Description: This task is created by OSTmrInit().
  975. *
  976. * Arguments  : none
  977. *
  978. * Returns    : none
  979. ************************************************************************************************************************
  980. */
  981. #if OS_TMR_EN > 0
  982. static  void  OSTmr_Task (void *p_arg)
  983. {
  984.     INT8U            err;
  985.     OS_TMR          *ptmr;
  986.     OS_TMR          *ptmr_next;
  987.     OS_TMR_CALLBACK  pfnct;
  988.     OS_TMR_WHEEL    *pspoke;
  989.     INT16U           spoke;
  990.     (void)p_arg;                                                 /* Not using 'p_arg', prevent compiler warning       */
  991.     for (;;) {
  992.         OSSemPend(OSTmrSemSignal, 0, &err);                      /* Wait for signal indicating time to update timers  */
  993.         OSTmr_Lock();
  994.         OSTmrTime++;                                             /* Increment the current time                        */
  995.         spoke  = (INT16U)(OSTmrTime % OS_TMR_CFG_WHEEL_SIZE);    /* Position on current timer wheel entry             */
  996.         pspoke = &OSTmrWheelTbl[spoke];
  997.         ptmr   = pspoke->OSTmrFirst;
  998.         while (ptmr != (OS_TMR *)0) {
  999.             ptmr_next = (OS_TMR *)ptmr->OSTmrNext;               /* Point to next timer to update because current ... */
  1000.                                                                  /* ... timer could get unlinked from the wheel.      */
  1001.             if (OSTmrTime == ptmr->OSTmrMatch) {                 /* Process each timer that expires                   */
  1002.                 pfnct = ptmr->OSTmrCallback;                     /* Execute callback function if available            */
  1003.                 if (pfnct != (OS_TMR_CALLBACK)0) {
  1004.                     (*pfnct)((void *)ptmr, ptmr->OSTmrCallbackArg);
  1005.                 }
  1006.                 OSTmr_Unlink(ptmr);                              /* Remove from current wheel spoke                   */
  1007.                 if (ptmr->OSTmrOpt == OS_TMR_OPT_PERIODIC) {
  1008.                     OSTmr_Link(ptmr, OS_TMR_LINK_PERIODIC);      /* Recalculate new position of timer in wheel        */
  1009.                 } else {
  1010.                     ptmr->OSTmrState = OS_TMR_STATE_COMPLETED;   /* Indicate that the timer has completed             */
  1011.                 }
  1012.             }
  1013.             ptmr = ptmr_next;
  1014.         }
  1015.         OSTmr_Unlock();
  1016.     }
  1017. }
  1018. #endif