osal_vt.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. /**
  14. * @file osal_vt.c
  15. * @brief OSAL Virtual Timers module code.
  16. * @details This module can be used in an OSAL implementation whenever an
  17. * underlying RTOS is unable to provide timeout services or there
  18. * is no underlying RTOS.
  19. *
  20. * @addtogroup OSAL_VT
  21. * @{
  22. */
  23. #include "osal.h"
  24. #include "osal_vt.h"
  25. /*===========================================================================*/
  26. /* Module local definitions. */
  27. /*===========================================================================*/
  28. /*===========================================================================*/
  29. /* Module exported variables. */
  30. /*===========================================================================*/
  31. /**
  32. * @brief Virtual timers delta list header.
  33. */
  34. virtual_timers_list_t vtlist;
  35. /*===========================================================================*/
  36. /* Module local types. */
  37. /*===========================================================================*/
  38. /*===========================================================================*/
  39. /* Module local variables. */
  40. /*===========================================================================*/
  41. /*===========================================================================*/
  42. /* Module local functions. */
  43. /*===========================================================================*/
  44. /*===========================================================================*/
  45. /* Module exported functions. */
  46. /*===========================================================================*/
  47. /**
  48. * @brief Timers initialization.
  49. *
  50. * @init
  51. */
  52. void vtInit(void) {
  53. /* Virtual Timers initialization.*/
  54. vtlist.vt_next = vtlist.vt_prev = (void *)&vtlist;
  55. vtlist.vt_delta = (sysinterval_t)-1;
  56. vtlist.vt_systime = 0;
  57. }
  58. /**
  59. * @brief Returns @p TRUE if the specified timer is armed.
  60. *
  61. * @param[out] vtp the @p virtual_timer_t structure pointer
  62. *
  63. * @iclass
  64. */
  65. bool vtIsArmedI(virtual_timer_t *vtp) {
  66. return vtp->vt_func != NULL;
  67. }
  68. /**
  69. * @brief Virtual timers ticker.
  70. * @note The system lock is released before entering the callback and
  71. * re-acquired immediately after. It is callback's responsibility
  72. * to acquire the lock if needed. This is done in order to reduce
  73. * interrupts jitter when many timers are in use.
  74. *
  75. * @iclass
  76. */
  77. void vtDoTickI(void) {
  78. vtlist.vt_systime++;
  79. if (&vtlist != (virtual_timers_list_t *)vtlist.vt_next) {
  80. virtual_timer_t *vtp;
  81. --vtlist.vt_next->vt_delta;
  82. while (!(vtp = vtlist.vt_next)->vt_delta) {
  83. vtfunc_t fn = vtp->vt_func;
  84. vtp->vt_func = (vtfunc_t)NULL;
  85. vtp->vt_next->vt_prev = (void *)&vtlist;
  86. (&vtlist)->vt_next = vtp->vt_next;
  87. osalSysUnlockFromISR();
  88. fn(vtp->vt_par);
  89. osalSysLockFromISR();
  90. }
  91. }
  92. }
  93. /**
  94. * @brief Enables a virtual timer.
  95. * @note The associated function is invoked from interrupt context.
  96. *
  97. * @param[out] vtp the @p virtual_timer_t structure pointer
  98. * @param[in] timeout the number of ticks before the operation timeouts, the
  99. * special values are handled as follow:
  100. * - @a TIME_INFINITE is allowed but interpreted as a
  101. * normal time specification.
  102. * - @a TIME_IMMEDIATE this value is not allowed.
  103. * .
  104. * @param[in] vtfunc the timer callback function. After invoking the
  105. * callback the timer is disabled and the structure can
  106. * be disposed or reused.
  107. * @param[in] par a parameter that will be passed to the callback
  108. * function
  109. *
  110. * @iclass
  111. */
  112. void vtSetI(virtual_timer_t *vtp, sysinterval_t timeout,
  113. vtfunc_t vtfunc, void *par) {
  114. virtual_timer_t *p;
  115. vtp->vt_par = par;
  116. vtp->vt_func = vtfunc;
  117. p = vtlist.vt_next;
  118. while (p->vt_delta < timeout) {
  119. timeout -= p->vt_delta;
  120. p = p->vt_next;
  121. }
  122. vtp->vt_prev = (vtp->vt_next = p)->vt_prev;
  123. vtp->vt_prev->vt_next = p->vt_prev = vtp;
  124. vtp->vt_delta = timeout;
  125. if (p != (void *)&vtlist)
  126. p->vt_delta -= timeout;
  127. }
  128. /**
  129. * @brief Disables a Virtual Timer.
  130. * @note The timer MUST be active when this function is invoked.
  131. *
  132. * @param[in] vtp the @p virtual_timer_t structure pointer
  133. *
  134. * @iclass
  135. */
  136. void vtResetI(virtual_timer_t *vtp) {
  137. if (vtp->vt_next != (void *)&vtlist)
  138. vtp->vt_next->vt_delta += vtp->vt_delta;
  139. vtp->vt_prev->vt_next = vtp->vt_next;
  140. vtp->vt_next->vt_prev = vtp->vt_prev;
  141. vtp->vt_func = (vtfunc_t)NULL;
  142. }
  143. /** @} */