os_tmr.c
上传用户:zbk8730
上传日期:2017-08-10
资源大小:12168k
文件大小:45k
源码类别:

uCOS

开发平台:

C/C++

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