timers.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /*
  2. * FreeRTOS Kernel V10.4.6
  3. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * SPDX-License-Identifier: MIT
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  8. * this software and associated documentation files (the "Software"), to deal in
  9. * the Software without restriction, including without limitation the rights to
  10. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  11. * the Software, and to permit persons to whom the Software is furnished to do so,
  12. * subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in all
  15. * copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  19. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  20. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  21. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. *
  24. * https://www.FreeRTOS.org
  25. * https://github.com/FreeRTOS
  26. *
  27. */
  28. /* Standard includes. */
  29. #include <stdlib.h>
  30. #include "FreeRTOS.h"
  31. #include "task.h"
  32. #include "queue.h"
  33. #include "timers.h"
  34. /* This entire source file will be skipped if the application is not configured
  35. * to include software timer functionality. This #if is closed at the very bottom
  36. * of this file. If you want to include software timer functionality then ensure
  37. * configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
  38. #if ( configUSE_TIMERS == 1 )
  39. typedef void (* rt_timer_callback_t)(void *);
  40. /* The definition of the timers themselves. */
  41. typedef struct tmrTimerControl
  42. {
  43. struct rt_timer timer;
  44. void * pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */
  45. } xTIMER;
  46. typedef xTIMER Timer_t;
  47. /*-----------------------------------------------------------*/
  48. #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  49. TimerHandle_t xTimerCreate( const char * const pcTimerName,
  50. const TickType_t xTimerPeriodInTicks,
  51. const UBaseType_t uxAutoReload,
  52. void * const pvTimerID,
  53. TimerCallbackFunction_t pxCallbackFunction )
  54. {
  55. Timer_t * pxNewTimer;
  56. rt_uint8_t flag = RT_TIMER_FLAG_SOFT_TIMER;
  57. pxNewTimer = ( Timer_t * ) RT_KERNEL_MALLOC( sizeof( Timer_t ) );
  58. if( pxNewTimer != RT_NULL )
  59. {
  60. if ( uxAutoReload != pdFALSE )
  61. {
  62. flag |= RT_TIMER_FLAG_PERIODIC;
  63. }
  64. else
  65. {
  66. flag |= RT_TIMER_FLAG_ONE_SHOT;
  67. }
  68. rt_timer_init( ( rt_timer_t ) pxNewTimer, pcTimerName, ( rt_timer_callback_t ) pxCallbackFunction, pxNewTimer, xTimerPeriodInTicks, flag );
  69. pxNewTimer->pvTimerID = pvTimerID;
  70. /* Mark as dynamic so we can distinguish when deleting */
  71. ( ( rt_timer_t ) pxNewTimer )->parent.type &= ~RT_Object_Class_Static;
  72. }
  73. return pxNewTimer;
  74. }
  75. #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
  76. /*-----------------------------------------------------------*/
  77. #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
  78. TimerHandle_t xTimerCreateStatic( const char * const pcTimerName,
  79. const TickType_t xTimerPeriodInTicks,
  80. const UBaseType_t uxAutoReload,
  81. void * const pvTimerID,
  82. TimerCallbackFunction_t pxCallbackFunction,
  83. StaticTimer_t * pxTimerBuffer )
  84. {
  85. Timer_t * pxNewTimer;
  86. rt_uint8_t flag = RT_TIMER_FLAG_SOFT_TIMER;
  87. #if ( configASSERT_DEFINED == 1 )
  88. {
  89. /* Sanity check that the size of the structure used to declare a
  90. * variable of type StaticTimer_t equals the size of the real timer
  91. * structure. */
  92. volatile size_t xSize = sizeof( StaticTimer_t );
  93. configASSERT( xSize == sizeof( Timer_t ) );
  94. ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */
  95. }
  96. #endif /* configASSERT_DEFINED */
  97. /* A pointer to a StaticTimer_t structure MUST be provided, use it. */
  98. configASSERT( pxTimerBuffer );
  99. pxNewTimer = ( Timer_t * ) pxTimerBuffer;
  100. if( pxNewTimer != NULL )
  101. {
  102. if ( uxAutoReload != pdFALSE )
  103. {
  104. flag |= RT_TIMER_FLAG_PERIODIC;
  105. }
  106. else
  107. {
  108. flag |= RT_TIMER_FLAG_ONE_SHOT;
  109. }
  110. rt_timer_init( ( rt_timer_t ) pxNewTimer, pcTimerName, ( rt_timer_callback_t ) pxCallbackFunction, pxNewTimer, xTimerPeriodInTicks, flag );
  111. pxNewTimer->pvTimerID = pvTimerID;
  112. }
  113. return pxNewTimer;
  114. }
  115. #endif /* configSUPPORT_STATIC_ALLOCATION */
  116. /*-----------------------------------------------------------*/
  117. BaseType_t xTimerGenericCommand( TimerHandle_t xTimer,
  118. const BaseType_t xCommandID,
  119. const TickType_t xOptionalValue,
  120. BaseType_t * const pxHigherPriorityTaskWoken,
  121. const TickType_t xTicksToWait )
  122. {
  123. rt_err_t err = -RT_ERROR;
  124. configASSERT( xTimer );
  125. if ( ( xCommandID == tmrCOMMAND_START ) || ( xCommandID == tmrCOMMAND_START_FROM_ISR )
  126. || ( xCommandID == tmrCOMMAND_RESET ) || ( xCommandID == tmrCOMMAND_RESET_FROM_ISR ) )
  127. {
  128. err = rt_timer_start( ( rt_timer_t ) xTimer );
  129. }
  130. else if ( ( xCommandID == tmrCOMMAND_STOP ) || ( xCommandID == tmrCOMMAND_STOP_FROM_ISR ) )
  131. {
  132. err = rt_timer_stop( ( rt_timer_t ) xTimer );
  133. }
  134. else if ( ( xCommandID == tmrCOMMAND_CHANGE_PERIOD ) || ( xCommandID == tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ) )
  135. {
  136. if ( rt_timer_stop( ( rt_timer_t ) xTimer ) == RT_EOK )
  137. {
  138. if ( rt_timer_control( ( rt_timer_t ) xTimer, RT_TIMER_CTRL_SET_TIME, ( void * ) &xOptionalValue ) == RT_EOK )
  139. {
  140. err = rt_timer_start( ( rt_timer_t ) xTimer );
  141. }
  142. }
  143. }
  144. else if ( xCommandID == tmrCOMMAND_DELETE )
  145. {
  146. #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
  147. if ( rt_object_is_systemobject( ( rt_object_t ) xTimer ) )
  148. #endif
  149. {
  150. #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
  151. err = rt_timer_detach( ( rt_timer_t ) xTimer );
  152. #endif
  153. #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
  154. }
  155. else
  156. {
  157. #endif
  158. #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  159. ( ( rt_timer_t ) xTimer )->parent.type |= RT_Object_Class_Static;
  160. err = rt_timer_detach( ( rt_timer_t ) xTimer );
  161. RT_KERNEL_FREE( xTimer );
  162. #endif
  163. }
  164. }
  165. if ( ( xCommandID >= tmrFIRST_FROM_ISR_COMMAND ) && ( xCommandID <= tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ) && ( pxHigherPriorityTaskWoken != NULL ) )
  166. {
  167. *pxHigherPriorityTaskWoken = pdFALSE;
  168. }
  169. return rt_err_to_freertos( err );
  170. }
  171. /*-----------------------------------------------------------*/
  172. TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )
  173. {
  174. return ( TaskHandle_t ) rt_thread_find( "timer" );
  175. }
  176. /*-----------------------------------------------------------*/
  177. TickType_t xTimerGetPeriod( TimerHandle_t xTimer )
  178. {
  179. Timer_t * pxTimer = xTimer;
  180. rt_tick_t arg;
  181. configASSERT( xTimer );
  182. rt_timer_control( ( rt_timer_t ) pxTimer, RT_TIMER_CTRL_GET_TIME, &arg );
  183. return ( TickType_t ) arg;
  184. }
  185. /*-----------------------------------------------------------*/
  186. void vTimerSetReloadMode( TimerHandle_t xTimer,
  187. const UBaseType_t uxAutoReload )
  188. {
  189. Timer_t * pxTimer = xTimer;
  190. configASSERT( xTimer );
  191. if ( uxAutoReload != pdFALSE )
  192. {
  193. rt_timer_control( ( rt_timer_t ) pxTimer, RT_TIMER_CTRL_SET_PERIODIC, RT_NULL );
  194. }
  195. else
  196. {
  197. rt_timer_control( ( rt_timer_t ) pxTimer, RT_TIMER_CTRL_SET_ONESHOT, RT_NULL );
  198. }
  199. }
  200. /*-----------------------------------------------------------*/
  201. UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer )
  202. {
  203. Timer_t * pxTimer = xTimer;
  204. UBaseType_t uxReturn;
  205. rt_base_t level;
  206. configASSERT( xTimer );
  207. level = rt_hw_interrupt_disable();
  208. if ( ( ( rt_timer_t ) pxTimer )->parent.flag & RT_TIMER_FLAG_PERIODIC )
  209. {
  210. uxReturn = ( UBaseType_t ) pdTRUE;
  211. }
  212. else
  213. {
  214. uxReturn = ( UBaseType_t ) pdFALSE;
  215. }
  216. rt_hw_interrupt_enable( level );
  217. return uxReturn;
  218. }
  219. /*-----------------------------------------------------------*/
  220. TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )
  221. {
  222. Timer_t * pxTimer = xTimer;
  223. TickType_t xReturn;
  224. configASSERT( xTimer );
  225. rt_timer_control( ( rt_timer_t ) pxTimer, RT_TIMER_CTRL_GET_REMAIN_TIME, &xReturn );
  226. return xReturn;
  227. }
  228. /*-----------------------------------------------------------*/
  229. const char * pcTimerGetName( TimerHandle_t xTimer )
  230. {
  231. Timer_t * pxTimer = xTimer;
  232. configASSERT( xTimer );
  233. return ( ( rt_timer_t ) pxTimer )->parent.name;
  234. }
  235. /*-----------------------------------------------------------*/
  236. BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )
  237. {
  238. BaseType_t xReturn;
  239. Timer_t * pxTimer = xTimer;
  240. rt_uint32_t arg;
  241. configASSERT( xTimer );
  242. rt_timer_control( ( rt_timer_t ) pxTimer, RT_TIMER_CTRL_GET_STATE, &arg );
  243. if ( arg == RT_TIMER_FLAG_ACTIVATED )
  244. {
  245. xReturn = pdTRUE;
  246. }
  247. else
  248. {
  249. xReturn = pdFALSE;
  250. }
  251. return xReturn;
  252. }
  253. /*-----------------------------------------------------------*/
  254. void * pvTimerGetTimerID( const TimerHandle_t xTimer )
  255. {
  256. Timer_t * const pxTimer = xTimer;
  257. void * pvReturn;
  258. rt_base_t level;
  259. configASSERT( xTimer );
  260. level = rt_hw_interrupt_disable();
  261. pvReturn = pxTimer->pvTimerID;
  262. rt_hw_interrupt_enable( level );
  263. return pvReturn;
  264. }
  265. /*-----------------------------------------------------------*/
  266. void vTimerSetTimerID( TimerHandle_t xTimer,
  267. void * pvNewID )
  268. {
  269. Timer_t * const pxTimer = xTimer;
  270. rt_base_t level;
  271. configASSERT( xTimer );
  272. level = rt_hw_interrupt_disable();
  273. pxTimer->pvTimerID = pvNewID;
  274. rt_hw_interrupt_enable( level );
  275. }
  276. /*-----------------------------------------------------------*/
  277. #endif /* configUSE_TIMERS == 1 */