task.c 35 KB

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