tasks.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  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 <string.h>
  31. /* FreeRTOS includes. */
  32. #include "FreeRTOS.h"
  33. #include "task.h"
  34. #define FREERTOS_PRIORITY_TO_RTTHREAD(priority) ( configMAX_PRIORITIES - 1 - ( priority ) )
  35. #define RTTHREAD_PRIORITY_TO_FREERTOS(priority) ( RT_THREAD_PRIORITY_MAX - 1 - ( priority ) )
  36. /* Values that can be assigned to the ucNotifyState member of the TCB. */
  37. #define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) /* Must be zero as it is the initialised value. */
  38. #define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 )
  39. #define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 )
  40. /*
  41. * Several functions take a TaskHandle_t parameter that can optionally be NULL,
  42. * where NULL is used to indicate that the handle of the currently executing
  43. * task should be used in place of the parameter. This macro simply checks to
  44. * see if the parameter is NULL and returns a pointer to the appropriate TCB.
  45. */
  46. #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( xTaskGetCurrentTaskHandle() ) : ( pxHandle ) )
  47. /*
  48. * Task control block. A task control block (TCB) is allocated for each task,
  49. * and stores task state information, including a pointer to the task's context
  50. * (the task's run time environment, including register values)
  51. */
  52. typedef struct tskTaskControlBlock
  53. {
  54. struct rt_thread thread;
  55. #if ( configUSE_APPLICATION_TASK_TAG == 1 )
  56. TaskHookFunction_t pxTaskTag;
  57. #endif
  58. #if ( configUSE_TASK_NOTIFICATIONS == 1 )
  59. volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
  60. volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
  61. #endif
  62. #if ( INCLUDE_xTaskAbortDelay == 1 )
  63. uint8_t ucDelayAborted;
  64. #endif
  65. } tskTCB;
  66. typedef tskTCB TCB_t;
  67. /* Other file private variables. --------------------------------*/
  68. static volatile BaseType_t xSchedulerRunning = pdFALSE;
  69. /*-----------------------------------------------------------*/
  70. /*
  71. * Called after a Task_t structure has been allocated either statically or
  72. * dynamically to fill in the structure's members.
  73. */
  74. static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
  75. const char * const pcName,
  76. const uint32_t ulStackDepth,
  77. void * const pvParameters,
  78. UBaseType_t uxPriority,
  79. TaskHandle_t * const pxCreatedTask,
  80. TCB_t * pxNewTCB,
  81. StackType_t * const puxStackBuffer );
  82. #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
  83. TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
  84. const char * const pcName,
  85. const uint32_t ulStackDepth,
  86. void * const pvParameters,
  87. UBaseType_t uxPriority,
  88. StackType_t * const puxStackBuffer,
  89. StaticTask_t * const pxTaskBuffer )
  90. {
  91. TCB_t * pxNewTCB;
  92. TaskHandle_t xReturn = NULL;
  93. configASSERT( puxStackBuffer != NULL );
  94. configASSERT( pxTaskBuffer != NULL );
  95. #if ( configASSERT_DEFINED == 1 )
  96. {
  97. /* Sanity check that the size of the structure used to declare a
  98. * variable of type StaticTask_t equals the size of the real task
  99. * structure. */
  100. volatile size_t xSize = sizeof( StaticTask_t );
  101. configASSERT( xSize == sizeof( TCB_t ) );
  102. ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
  103. }
  104. #endif /* configASSERT_DEFINED */
  105. if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
  106. {
  107. pxNewTCB = ( TCB_t * ) pxTaskBuffer;
  108. prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, puxStackBuffer );
  109. rt_thread_startup( ( rt_thread_t ) pxNewTCB );
  110. }
  111. return xReturn;
  112. }
  113. #endif /* SUPPORT_STATIC_ALLOCATION */
  114. #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  115. BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
  116. const char * const pcName,
  117. const configSTACK_DEPTH_TYPE usStackDepth,
  118. void * const pvParameters,
  119. UBaseType_t uxPriority,
  120. TaskHandle_t * const pxCreatedTask )
  121. {
  122. TCB_t * pxNewTCB;
  123. BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
  124. void * stack_start = RT_NULL;
  125. pxNewTCB = ( TCB_t * ) RT_KERNEL_MALLOC( sizeof( TCB_t ) );
  126. if ( pxNewTCB != NULL )
  127. {
  128. stack_start = RT_KERNEL_MALLOC( usStackDepth * sizeof( StackType_t ) );
  129. if ( stack_start != RT_NULL )
  130. {
  131. prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, ( StackType_t * ) stack_start );
  132. xReturn = pdPASS;
  133. /* Mark as dynamic */
  134. ( ( struct rt_thread * ) pxNewTCB )->type &= ~RT_Object_Class_Static;
  135. rt_thread_startup( ( rt_thread_t ) pxNewTCB );
  136. }
  137. else
  138. {
  139. RT_KERNEL_FREE( pxNewTCB );
  140. }
  141. }
  142. return xReturn;
  143. }
  144. #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
  145. /*-----------------------------------------------------------*/
  146. static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
  147. const char * const pcName,
  148. const uint32_t ulStackDepth,
  149. void * const pvParameters,
  150. UBaseType_t uxPriority,
  151. TaskHandle_t * const pxCreatedTask,
  152. TCB_t * pxNewTCB,
  153. StackType_t * const puxStackBuffer )
  154. {
  155. /* This is used as an array index so must ensure it's not too large. */
  156. configASSERT( uxPriority < configMAX_PRIORITIES );
  157. if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
  158. {
  159. uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
  160. }
  161. rt_thread_init( ( struct rt_thread * ) pxNewTCB, pcName, pxTaskCode, pvParameters,
  162. puxStackBuffer, ulStackDepth * sizeof( StackType_t ), FREERTOS_PRIORITY_TO_RTTHREAD( uxPriority ), 1 );
  163. #if ( configUSE_APPLICATION_TASK_TAG == 1 )
  164. pxNewTCB->pxTaskTag = NULL;
  165. #endif
  166. #if ( configUSE_TASK_NOTIFICATIONS == 1 )
  167. rt_memset( ( void * ) &( pxNewTCB->ulNotifiedValue[ 0 ] ), 0x00, sizeof( pxNewTCB->ulNotifiedValue ) );
  168. rt_memset( ( void * ) &( pxNewTCB->ucNotifyState[ 0 ] ), 0x00, sizeof( pxNewTCB->ucNotifyState ) );
  169. #endif
  170. #if ( INCLUDE_xTaskAbortDelay == 1 )
  171. pxNewTCB->ucDelayAborted = pdFALSE;
  172. #endif
  173. if ( pxCreatedTask != NULL )
  174. {
  175. *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
  176. }
  177. }
  178. /*-----------------------------------------------------------*/
  179. #if ( INCLUDE_vTaskDelete == 1 )
  180. void vTaskDelete( TaskHandle_t xTaskToDelete )
  181. {
  182. rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTaskToDelete );
  183. if ( thread == RT_NULL )
  184. {
  185. thread = rt_thread_self();
  186. }
  187. #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
  188. if ( rt_object_is_systemobject( ( rt_object_t ) thread ) )
  189. #endif
  190. {
  191. #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
  192. rt_thread_detach( thread );
  193. #endif
  194. #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
  195. }
  196. else
  197. {
  198. #endif
  199. #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  200. rt_thread_delete( thread );
  201. #endif
  202. }
  203. if ( thread == rt_thread_self() )
  204. {
  205. rt_schedule();
  206. }
  207. }
  208. #endif /* INCLUDE_vTaskDelete */
  209. /*-----------------------------------------------------------*/
  210. #if ( INCLUDE_xTaskDelayUntil == 1 )
  211. BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
  212. const TickType_t xTimeIncrement )
  213. {
  214. BaseType_t xShouldDelay = pdFALSE;
  215. rt_base_t level;
  216. rt_tick_t cur_tick;
  217. RT_ASSERT( pxPreviousWakeTime != RT_NULL );
  218. RT_ASSERT( xTimeIncrement > 0U );
  219. level = rt_hw_interrupt_disable();
  220. cur_tick = rt_tick_get();
  221. if (cur_tick - *pxPreviousWakeTime < xTimeIncrement)
  222. {
  223. rt_thread_delay_until( pxPreviousWakeTime, xTimeIncrement );
  224. xShouldDelay = pdTRUE;
  225. }
  226. rt_hw_interrupt_enable( level );
  227. return xShouldDelay;
  228. }
  229. #endif /* INCLUDE_xTaskDelayUntil */
  230. /*-----------------------------------------------------------*/
  231. #if ( INCLUDE_vTaskDelay == 1 )
  232. void vTaskDelay( const TickType_t xTicksToDelay )
  233. {
  234. rt_thread_delay( xTicksToDelay );
  235. }
  236. #endif /* INCLUDE_vTaskDelay */
  237. /*-----------------------------------------------------------*/
  238. #if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) )
  239. eTaskState eTaskGetState( TaskHandle_t xTask )
  240. {
  241. eTaskState eReturn;
  242. rt_thread_t thread = ( rt_thread_t ) xTask;
  243. rt_base_t level;
  244. configASSERT( xTask );
  245. level = rt_hw_interrupt_disable();
  246. switch ( thread->stat & RT_THREAD_STAT_MASK )
  247. {
  248. case RT_THREAD_READY:
  249. {
  250. eReturn = eReady;
  251. break;
  252. }
  253. case RT_THREAD_SUSPEND:
  254. {
  255. /* If thread timer is activated it is blocked with a timeout */
  256. if ( thread->thread_timer.parent.flag & RT_TIMER_FLAG_ACTIVATED )
  257. {
  258. eReturn = eBlocked;
  259. }
  260. /* Otherwise it is suspended or blocked with an infinite timeout */
  261. else
  262. {
  263. eReturn = eSuspended;
  264. }
  265. break;
  266. }
  267. case RT_THREAD_RUNNING:
  268. {
  269. eReturn = eRunning;
  270. break;
  271. }
  272. case RT_THREAD_CLOSE:
  273. {
  274. eReturn = eDeleted;
  275. break;
  276. }
  277. default:
  278. eReturn = eInvalid;
  279. }
  280. rt_hw_interrupt_enable( level );
  281. return eReturn;
  282. }
  283. #endif /* INCLUDE_eTaskGetState */
  284. /*-----------------------------------------------------------*/
  285. #if ( INCLUDE_uxTaskPriorityGet == 1 )
  286. UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
  287. {
  288. UBaseType_t uxReturn;
  289. rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTask );
  290. rt_base_t level;
  291. level = rt_hw_interrupt_disable();
  292. uxReturn = thread->current_priority;
  293. rt_hw_interrupt_enable( level );
  294. return RTTHREAD_PRIORITY_TO_FREERTOS( uxReturn );
  295. }
  296. #endif /* INCLUDE_uxTaskPriorityGet */
  297. /*-----------------------------------------------------------*/
  298. #if ( INCLUDE_uxTaskPriorityGet == 1 )
  299. UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask )
  300. {
  301. return uxTaskPriorityGet( xTask );
  302. }
  303. #endif /* INCLUDE_uxTaskPriorityGet */
  304. /*-----------------------------------------------------------*/
  305. #if ( INCLUDE_vTaskPrioritySet == 1 )
  306. void vTaskPrioritySet( TaskHandle_t xTask,
  307. UBaseType_t uxNewPriority )
  308. {
  309. extern rt_thread_t rt_current_thread;
  310. rt_thread_t thread;
  311. rt_uint8_t current_priority;
  312. rt_bool_t need_schedule = RT_FALSE;
  313. rt_base_t level;
  314. configASSERT( uxNewPriority < configMAX_PRIORITIES );
  315. /* Ensure the new priority is valid. */
  316. if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
  317. {
  318. uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
  319. }
  320. uxNewPriority = FREERTOS_PRIORITY_TO_RTTHREAD( uxNewPriority );
  321. level = rt_hw_interrupt_disable();
  322. thread = ( rt_thread_t ) prvGetTCBFromHandle( xTask );
  323. current_priority = thread->current_priority;
  324. if ( current_priority != uxNewPriority )
  325. {
  326. rt_thread_control( thread, RT_THREAD_CTRL_CHANGE_PRIORITY, &uxNewPriority);
  327. if ( uxNewPriority < current_priority )
  328. {
  329. /* The priority of a task other than the currently running task is being raised.
  330. * Need to schedule if the priority is raised above that of the running task */
  331. if ( thread != rt_current_thread && uxNewPriority <= rt_current_thread->current_priority )
  332. {
  333. need_schedule = RT_TRUE;
  334. }
  335. }
  336. /* Setting the priority of the running task down means
  337. * there may now be another task of higher priority that
  338. * is ready to execute. */
  339. else if ( thread == rt_current_thread )
  340. {
  341. need_schedule = RT_TRUE;
  342. }
  343. }
  344. rt_hw_interrupt_enable( level );
  345. if ( need_schedule == RT_TRUE )
  346. {
  347. rt_schedule();
  348. }
  349. }
  350. #endif /* INCLUDE_vTaskPrioritySet */
  351. /*-----------------------------------------------------------*/
  352. #if ( INCLUDE_vTaskSuspend == 1 )
  353. void vTaskSuspend( TaskHandle_t xTaskToSuspend )
  354. {
  355. rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTaskToSuspend );
  356. if ( rt_thread_suspend( thread ) == RT_EOK )
  357. {
  358. rt_schedule();
  359. }
  360. }
  361. #endif /* INCLUDE_vTaskSuspend */
  362. /*-----------------------------------------------------------*/
  363. #if ( INCLUDE_vTaskSuspend == 1 )
  364. void vTaskResume( TaskHandle_t xTaskToResume )
  365. {
  366. rt_thread_t thread = ( rt_thread_t ) xTaskToResume;
  367. rt_bool_t need_schedule = RT_FALSE;
  368. rt_base_t level;
  369. /* It does not make sense to resume the calling task. */
  370. configASSERT( xTaskToResume );
  371. if ( thread != NULL && thread != rt_thread_self() )
  372. {
  373. level = rt_hw_interrupt_disable();
  374. /* A task with higher priority than the current running task is ready */
  375. if ( rt_thread_resume( thread ) == RT_EOK && thread->current_priority <= rt_thread_self()->current_priority )
  376. {
  377. need_schedule = RT_TRUE;
  378. }
  379. rt_hw_interrupt_enable( level );
  380. }
  381. if (need_schedule == RT_TRUE)
  382. {
  383. rt_schedule();
  384. }
  385. }
  386. #endif /* INCLUDE_vTaskSuspend */
  387. /*-----------------------------------------------------------*/
  388. #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
  389. BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
  390. {
  391. vTaskResume( xTaskToResume );
  392. return pdFALSE;
  393. }
  394. #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
  395. /*-----------------------------------------------------------*/
  396. void vTaskStartScheduler( void )
  397. {
  398. xSchedulerRunning = pdTRUE;
  399. }
  400. /*-----------------------------------------------------------*/
  401. void vTaskEndScheduler( void )
  402. {
  403. xSchedulerRunning = pdFALSE;
  404. vPortEndScheduler();
  405. }
  406. /*----------------------------------------------------------*/
  407. void vTaskSuspendAll( void )
  408. {
  409. rt_enter_critical();
  410. }
  411. /*----------------------------------------------------------*/
  412. BaseType_t xTaskResumeAll( void )
  413. {
  414. rt_exit_critical();
  415. return pdFALSE;
  416. }
  417. /*-----------------------------------------------------------*/
  418. TickType_t xTaskGetTickCount( void )
  419. {
  420. return rt_tick_get();
  421. }
  422. /*-----------------------------------------------------------*/
  423. TickType_t xTaskGetTickCountFromISR( void )
  424. {
  425. return rt_tick_get();
  426. }
  427. /*-----------------------------------------------------------*/
  428. UBaseType_t uxTaskGetNumberOfTasks( void )
  429. {
  430. UBaseType_t uxReturn = 0;
  431. rt_base_t level;
  432. struct rt_object_information *information;
  433. struct rt_list_node *node = RT_NULL;
  434. information = rt_object_get_information( RT_Object_Class_Thread );
  435. RT_ASSERT( information != RT_NULL );
  436. level = rt_hw_interrupt_disable();
  437. rt_list_for_each( node, &( information->object_list ) )
  438. {
  439. uxReturn += 1;
  440. }
  441. rt_hw_interrupt_enable( level );
  442. return uxReturn;
  443. }
  444. /*-----------------------------------------------------------*/
  445. char * pcTaskGetName( TaskHandle_t xTaskToQuery )
  446. {
  447. rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTaskToQuery );
  448. return &( thread->name[ 0 ] );
  449. }
  450. /*-----------------------------------------------------------*/
  451. #if ( INCLUDE_xTaskGetHandle == 1 )
  452. TaskHandle_t xTaskGetHandle( const char * pcNameToQuery )
  453. {
  454. return ( TaskHandle_t ) rt_thread_find( ( char * ) pcNameToQuery );
  455. }
  456. #endif /* INCLUDE_xTaskGetHandle */
  457. /*-----------------------------------------------------------*/
  458. #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
  459. TaskHandle_t xTaskGetIdleTaskHandle( void )
  460. {
  461. return ( TaskHandle_t ) rt_thread_find( "tidle0" );
  462. }
  463. #endif /* INCLUDE_xTaskGetIdleTaskHandle */
  464. /*----------------------------------------------------------*/
  465. #if ( INCLUDE_xTaskAbortDelay == 1 )
  466. BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
  467. {
  468. TCB_t * pxTCB = xTask;
  469. BaseType_t xReturn;
  470. rt_thread_t thread = ( rt_thread_t ) xTask;
  471. rt_bool_t need_schedule = RT_FALSE;
  472. rt_base_t level;
  473. configASSERT( pxTCB );
  474. level = rt_hw_interrupt_disable();
  475. if ( eTaskGetState( xTask ) == eBlocked )
  476. {
  477. rt_thread_resume( thread );
  478. thread->error = -RT_ETIMEOUT;
  479. pxTCB->ucDelayAborted = pdTRUE;
  480. if ( thread->current_priority < rt_thread_self()->current_priority ){
  481. need_schedule = RT_TRUE;
  482. }
  483. xReturn = pdPASS;
  484. }
  485. else
  486. {
  487. xReturn = pdFAIL;
  488. }
  489. rt_hw_interrupt_enable( level );
  490. if ( need_schedule == RT_TRUE )
  491. {
  492. rt_schedule();
  493. }
  494. return xReturn;
  495. }
  496. #endif /* INCLUDE_xTaskAbortDelay */
  497. /*----------------------------------------------------------*/
  498. #if ( configUSE_APPLICATION_TASK_TAG == 1 )
  499. void vTaskSetApplicationTaskTag( TaskHandle_t xTask,
  500. TaskHookFunction_t pxHookFunction )
  501. {
  502. TCB_t * xTCB = prvGetTCBFromHandle( xTask );
  503. rt_base_t level;
  504. level = rt_hw_interrupt_disable();
  505. xTCB->pxTaskTag = pxHookFunction;
  506. rt_hw_interrupt_enable( level );
  507. }
  508. #endif /* configUSE_APPLICATION_TASK_TAG */
  509. /*-----------------------------------------------------------*/
  510. #if ( configUSE_APPLICATION_TASK_TAG == 1 )
  511. TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
  512. {
  513. TaskHookFunction_t xReturn;
  514. TCB_t * xTCB = prvGetTCBFromHandle( xTask );
  515. rt_base_t level;
  516. level = rt_hw_interrupt_disable();
  517. xReturn = xTCB->pxTaskTag;
  518. rt_hw_interrupt_enable( level );
  519. return xReturn;
  520. }
  521. #endif /* configUSE_APPLICATION_TASK_TAG */
  522. /*-----------------------------------------------------------*/
  523. #if ( configUSE_APPLICATION_TASK_TAG == 1 )
  524. TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask )
  525. {
  526. return xTaskGetApplicationTaskTag( xTask );
  527. }
  528. #endif /* configUSE_APPLICATION_TASK_TAG */
  529. /*-----------------------------------------------------------*/
  530. #if ( configUSE_APPLICATION_TASK_TAG == 1 )
  531. BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
  532. void * pvParameter )
  533. {
  534. BaseType_t xReturn;
  535. TCB_t * xTCB = prvGetTCBFromHandle( xTask );
  536. if( xTCB->pxTaskTag != NULL )
  537. {
  538. xReturn = xTCB->pxTaskTag( pvParameter );
  539. }
  540. else
  541. {
  542. xReturn = pdFAIL;
  543. }
  544. return xReturn;
  545. }
  546. #endif /* configUSE_APPLICATION_TASK_TAG */
  547. /*-----------------------------------------------------------*/
  548. void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
  549. {
  550. rt_base_t level;
  551. configASSERT( pxTimeOut );
  552. level = rt_hw_interrupt_disable();
  553. pxTimeOut->xOverflowCount = 0;
  554. pxTimeOut->xTimeOnEntering = ( TickType_t ) rt_tick_get();
  555. rt_hw_interrupt_enable( level );
  556. }
  557. /*-----------------------------------------------------------*/
  558. void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )
  559. {
  560. /* For internal use only as it does not use a critical section. */
  561. pxTimeOut->xOverflowCount = 0;
  562. pxTimeOut->xTimeOnEntering = ( TickType_t ) rt_tick_get();;
  563. }
  564. /*-----------------------------------------------------------*/
  565. BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
  566. TickType_t * const pxTicksToWait )
  567. {
  568. TCB_t * pxCurrentTCB = ( TCB_t * ) rt_thread_self();
  569. BaseType_t xReturn;
  570. rt_base_t level;
  571. configASSERT( pxTimeOut );
  572. configASSERT( pxTicksToWait );
  573. level = rt_hw_interrupt_disable();
  574. /* Minor optimisation. The tick count cannot change in this block. */
  575. const TickType_t xConstTickCount = ( TickType_t ) rt_tick_get();
  576. const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;
  577. #if ( INCLUDE_xTaskAbortDelay == 1 )
  578. if( pxCurrentTCB->ucDelayAborted != ( uint8_t ) pdFALSE )
  579. {
  580. /* The delay was aborted, which is not the same as a time out,
  581. * but has the same result. */
  582. pxCurrentTCB->ucDelayAborted = pdFALSE;
  583. xReturn = pdTRUE;
  584. }
  585. else
  586. #endif
  587. #if ( INCLUDE_vTaskSuspend == 1 )
  588. if( *pxTicksToWait == portMAX_DELAY )
  589. {
  590. /* If INCLUDE_vTaskSuspend is set to 1 and the block time
  591. * specified is the maximum block time then the task should block
  592. * indefinitely, and therefore never time out. */
  593. xReturn = pdFALSE;
  594. }
  595. else
  596. #endif
  597. if( xElapsedTime < *pxTicksToWait )
  598. {
  599. /* Not a genuine timeout. Adjust parameters for time remaining. */
  600. *pxTicksToWait -= xElapsedTime;
  601. vTaskInternalSetTimeOutState( pxTimeOut );
  602. xReturn = pdFALSE;
  603. }
  604. else
  605. {
  606. *pxTicksToWait = ( TickType_t ) 0;
  607. xReturn = pdTRUE;
  608. }
  609. rt_hw_interrupt_enable( level );
  610. return xReturn;
  611. }
  612. /*-----------------------------------------------------------*/
  613. #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) )
  614. TaskHandle_t xTaskGetCurrentTaskHandle( void )
  615. {
  616. TaskHandle_t xReturn;
  617. /* A critical section is not required as this is not called from
  618. * an interrupt and the current TCB will always be the same for any
  619. * individual execution thread. */
  620. xReturn = ( TaskHandle_t ) rt_thread_self();
  621. return xReturn;
  622. }
  623. #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
  624. /*-----------------------------------------------------------*/
  625. #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) )
  626. BaseType_t xTaskGetSchedulerState( void )
  627. {
  628. BaseType_t xReturn;
  629. if( xSchedulerRunning == pdFALSE )
  630. {
  631. xReturn = taskSCHEDULER_NOT_STARTED;
  632. }
  633. else
  634. {
  635. if( rt_critical_level() == 0 )
  636. {
  637. xReturn = taskSCHEDULER_RUNNING;
  638. }
  639. else
  640. {
  641. xReturn = taskSCHEDULER_SUSPENDED;
  642. }
  643. }
  644. return xReturn;
  645. }
  646. #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) ) */
  647. /*-----------------------------------------------------------*/
  648. #if ( configUSE_TASK_NOTIFICATIONS == 1 )
  649. uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait,
  650. BaseType_t xClearCountOnExit,
  651. TickType_t xTicksToWait )
  652. {
  653. uint32_t ulReturn;
  654. TCB_t * pxCurrentTCB = ( TCB_t * ) rt_thread_self();
  655. rt_thread_t thread = ( rt_thread_t ) pxCurrentTCB;
  656. rt_base_t level;
  657. configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
  658. level = rt_hw_interrupt_disable();
  659. /* Only block if the notification count is not already non-zero. */
  660. if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL )
  661. {
  662. /* Mark this task as waiting for a notification. */
  663. pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
  664. if( xTicksToWait > ( TickType_t ) 0 )
  665. {
  666. rt_thread_suspend( thread );
  667. if ( ( rt_int32_t ) xTicksToWait > 0 )
  668. {
  669. rt_timer_control(&(thread->thread_timer),
  670. RT_TIMER_CTRL_SET_TIME,
  671. &xTicksToWait);
  672. rt_timer_start(&(thread->thread_timer));
  673. }
  674. rt_hw_interrupt_enable(level);
  675. rt_schedule();
  676. /* Clear thread error. */
  677. thread->error = RT_EOK;
  678. }
  679. }
  680. rt_hw_interrupt_enable( level );
  681. level = rt_hw_interrupt_disable();
  682. ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
  683. if( ulReturn != 0UL )
  684. {
  685. if( xClearCountOnExit != pdFALSE )
  686. {
  687. pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL;
  688. }
  689. else
  690. {
  691. pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1;
  692. }
  693. }
  694. pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
  695. rt_hw_interrupt_enable( level );
  696. return ulReturn;
  697. }
  698. #endif /* configUSE_TASK_NOTIFICATIONS */
  699. /*-----------------------------------------------------------*/
  700. #if ( configUSE_TASK_NOTIFICATIONS == 1 )
  701. BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait,
  702. uint32_t ulBitsToClearOnEntry,
  703. uint32_t ulBitsToClearOnExit,
  704. uint32_t * pulNotificationValue,
  705. TickType_t xTicksToWait )
  706. {
  707. BaseType_t xReturn;
  708. TCB_t * pxCurrentTCB = ( TCB_t * ) rt_thread_self();
  709. rt_thread_t thread = ( rt_thread_t ) pxCurrentTCB;
  710. rt_base_t level;
  711. configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
  712. level = rt_hw_interrupt_disable();
  713. /* Only block if a notification is not already pending. */
  714. if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
  715. {
  716. /* Clear bits in the task's notification value as bits may get
  717. * set by the notifying task or interrupt. This can be used to
  718. * clear the value to zero. */
  719. pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry;
  720. /* Mark this task as waiting for a notification. */
  721. pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
  722. if( xTicksToWait > ( TickType_t ) 0 )
  723. {
  724. rt_thread_suspend( thread );
  725. if ( ( rt_int32_t ) xTicksToWait > 0 )
  726. {
  727. rt_timer_control(&(thread->thread_timer),
  728. RT_TIMER_CTRL_SET_TIME,
  729. &xTicksToWait);
  730. rt_timer_start(&(thread->thread_timer));
  731. }
  732. rt_hw_interrupt_enable(level);
  733. rt_schedule();
  734. /* Clear thread error. It is not used to determine the function return value. */
  735. thread->error = RT_EOK;
  736. }
  737. else
  738. {
  739. rt_hw_interrupt_enable( level );
  740. }
  741. }
  742. else
  743. {
  744. rt_hw_interrupt_enable( level );
  745. }
  746. level = rt_hw_interrupt_disable();
  747. if( pulNotificationValue != NULL )
  748. {
  749. /* Output the current notification value, which may or may not
  750. * have changed. */
  751. *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
  752. }
  753. /* If ucNotifyValue is set then either the task never entered the
  754. * blocked state (because a notification was already pending) or the
  755. * task unblocked because of a notification. Otherwise the task
  756. * unblocked because of a timeout. */
  757. if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
  758. {
  759. /* A notification was not received. */
  760. xReturn = pdFALSE;
  761. }
  762. else
  763. {
  764. /* A notification was already pending or a notification was
  765. * received while the task was waiting. */
  766. pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnExit;
  767. xReturn = pdTRUE;
  768. }
  769. pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
  770. rt_hw_interrupt_enable( level );
  771. return xReturn;
  772. }
  773. #endif /* configUSE_TASK_NOTIFICATIONS */
  774. /*-----------------------------------------------------------*/
  775. #if ( configUSE_TASK_NOTIFICATIONS == 1 )
  776. BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
  777. UBaseType_t uxIndexToNotify,
  778. uint32_t ulValue,
  779. eNotifyAction eAction,
  780. uint32_t * pulPreviousNotificationValue )
  781. {
  782. TCB_t * pxTCB;
  783. BaseType_t xReturn = pdPASS;
  784. uint8_t ucOriginalNotifyState;
  785. rt_base_t level;
  786. configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
  787. configASSERT( xTaskToNotify );
  788. pxTCB = xTaskToNotify;
  789. level = rt_hw_interrupt_disable();
  790. if( pulPreviousNotificationValue != NULL )
  791. {
  792. *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
  793. }
  794. ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
  795. pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
  796. switch( eAction )
  797. {
  798. case eSetBits:
  799. pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
  800. break;
  801. case eIncrement:
  802. ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
  803. break;
  804. case eSetValueWithOverwrite:
  805. pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
  806. break;
  807. case eSetValueWithoutOverwrite:
  808. if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
  809. {
  810. pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
  811. }
  812. else
  813. {
  814. /* The value could not be written to the task. */
  815. xReturn = pdFAIL;
  816. }
  817. break;
  818. case eNoAction:
  819. /* The task is being notified without its notify value being
  820. * updated. */
  821. break;
  822. default:
  823. /* Should not get here if all enums are handled.
  824. * Artificially force an assert by testing a value the
  825. * compiler can't assume is const. */
  826. configASSERT( xTaskToNotify == NULL );
  827. break;
  828. }
  829. /* If the task is in the blocked state specifically to wait for a
  830. * notification then unblock it now. */
  831. if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
  832. {
  833. rt_thread_resume( ( rt_thread_t ) pxTCB );
  834. if( ( ( rt_thread_t ) pxTCB )->current_priority < rt_thread_self()->current_priority )
  835. {
  836. /* The notified task has a priority above the currently
  837. * executing task so a schedule is required. */
  838. rt_schedule();
  839. }
  840. }
  841. rt_hw_interrupt_enable( level );
  842. return xReturn;
  843. }
  844. #endif /* configUSE_TASK_NOTIFICATIONS */
  845. /*-----------------------------------------------------------*/
  846. #if ( configUSE_TASK_NOTIFICATIONS == 1 )
  847. BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
  848. UBaseType_t uxIndexToNotify,
  849. uint32_t ulValue,
  850. eNotifyAction eAction,
  851. uint32_t * pulPreviousNotificationValue,
  852. BaseType_t * pxHigherPriorityTaskWoken )
  853. {
  854. BaseType_t xReturn;
  855. xReturn = xTaskGenericNotify( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue );
  856. if ( pxHigherPriorityTaskWoken != NULL )
  857. {
  858. *pxHigherPriorityTaskWoken = pdFALSE;
  859. }
  860. return xReturn;
  861. }
  862. #endif /* configUSE_TASK_NOTIFICATIONS */
  863. /*-----------------------------------------------------------*/
  864. #if ( configUSE_TASK_NOTIFICATIONS == 1 )
  865. void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
  866. UBaseType_t uxIndexToNotify,
  867. BaseType_t * pxHigherPriorityTaskWoken )
  868. {
  869. xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify );
  870. if ( pxHigherPriorityTaskWoken != NULL )
  871. {
  872. *pxHigherPriorityTaskWoken = pdFALSE;
  873. }
  874. }
  875. #endif /* configUSE_TASK_NOTIFICATIONS */
  876. /*-----------------------------------------------------------*/
  877. #if ( configUSE_TASK_NOTIFICATIONS == 1 )
  878. BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
  879. UBaseType_t uxIndexToClear )
  880. {
  881. TCB_t * pxTCB;
  882. BaseType_t xReturn;
  883. rt_base_t level;
  884. configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES );
  885. /* If null is passed in here then it is the calling task that is having
  886. * its notification state cleared. */
  887. pxTCB = prvGetTCBFromHandle( xTask );
  888. level = rt_hw_interrupt_disable();
  889. if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED )
  890. {
  891. pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION;
  892. xReturn = pdPASS;
  893. }
  894. else
  895. {
  896. xReturn = pdFAIL;
  897. }
  898. rt_hw_interrupt_enable( level );
  899. return xReturn;
  900. }
  901. #endif /* configUSE_TASK_NOTIFICATIONS */
  902. /*-----------------------------------------------------------*/
  903. #if ( configUSE_TASK_NOTIFICATIONS == 1 )
  904. uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
  905. UBaseType_t uxIndexToClear,
  906. uint32_t ulBitsToClear )
  907. {
  908. TCB_t * pxTCB;
  909. uint32_t ulReturn;
  910. rt_base_t level;
  911. /* If null is passed in here then it is the calling task that is having
  912. * its notification state cleared. */
  913. pxTCB = prvGetTCBFromHandle( xTask );
  914. level = rt_hw_interrupt_disable();
  915. /* Return the notification as it was before the bits were cleared,
  916. * then clear the bit mask. */
  917. ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ];
  918. pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear;
  919. rt_hw_interrupt_enable( level );
  920. return ulReturn;
  921. }
  922. #endif /* configUSE_TASK_NOTIFICATIONS */
  923. /*-----------------------------------------------------------*/
  924. #if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
  925. /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the
  926. * same except for their return type. Using configSTACK_DEPTH_TYPE allows the
  927. * user to determine the return type. It gets around the problem of the value
  928. * overflowing on 8-bit types without breaking backward compatibility for
  929. * applications that expect an 8-bit return type. */
  930. configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask )
  931. {
  932. uint32_t ulCount = 0U;
  933. rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTask );
  934. rt_uint8_t * stack_addr = thread->stack_addr;
  935. #ifdef ARCH_CPU_STACK_GROWS_UPWARD
  936. stack_addr = stack_addr + thread->stack_size - 1;
  937. while ( *stack_addr == '#' )
  938. {
  939. ulCount += 1;
  940. stack_addr -= 1;
  941. }
  942. #else
  943. while ( *stack_addr == '#' )
  944. {
  945. ulCount += 1;
  946. stack_addr += 1;
  947. }
  948. #endif
  949. ulCount /= ( uint32_t ) sizeof( StackType_t );
  950. return ( configSTACK_DEPTH_TYPE ) ulCount;
  951. }
  952. #endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */
  953. /*-----------------------------------------------------------*/
  954. #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
  955. UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
  956. {
  957. return ( UBaseType_t ) uxTaskGetStackHighWaterMark2( xTask );
  958. }
  959. #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
  960. /*-----------------------------------------------------------*/