task.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  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. /*
  38. * Several functions take a TaskHandle_t parameter that can optionally be NULL,
  39. * where NULL is used to indicate that the handle of the currently executing
  40. * task should be used in place of the parameter. This macro simply checks to
  41. * see if the parameter is NULL and returns a pointer to the appropriate TCB.
  42. */
  43. #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( xTaskGetCurrentTaskHandle() ) : ( pxHandle ) )
  44. /*
  45. * Task control block. A task control block (TCB) is allocated for each task,
  46. * and stores task state information, including a pointer to the task's context
  47. * (the task's run time environment, including register values)
  48. */
  49. typedef struct tskTaskControlBlock
  50. {
  51. struct rt_thread thread;
  52. #if ( configUSE_APPLICATION_TASK_TAG == 1 )
  53. TaskHookFunction_t pxTaskTag;
  54. #endif
  55. } tskTCB;
  56. typedef tskTCB TCB_t;
  57. /*-----------------------------------------------------------*/
  58. #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
  59. TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
  60. const char * const pcName,
  61. const uint32_t ulStackDepth,
  62. void * const pvParameters,
  63. UBaseType_t uxPriority,
  64. StackType_t * const puxStackBuffer,
  65. StaticTask_t * const pxTaskBuffer )
  66. {
  67. TaskHandle_t xReturn = NULL;
  68. configASSERT( puxStackBuffer != NULL );
  69. configASSERT( pxTaskBuffer != NULL );
  70. #if ( configASSERT_DEFINED == 1 )
  71. {
  72. /* Sanity check that the size of the structure used to declare a
  73. * variable of type StaticTask_t equals the size of the real task
  74. * structure. */
  75. volatile size_t xSize = sizeof( StaticTask_t );
  76. configASSERT( xSize == sizeof( TCB_t ) );
  77. ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
  78. }
  79. #endif /* configASSERT_DEFINED */
  80. if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
  81. {
  82. rt_thread_init( ( struct rt_thread * ) pxTaskBuffer, pcName, pxTaskCode, pvParameters,
  83. ( void * ) puxStackBuffer, ulStackDepth * sizeof( StackType_t ), FREERTOS_PRIORITY_TO_RTTHREAD( uxPriority ), 1 );
  84. rt_thread_startup( ( rt_thread_t ) pxTaskBuffer );
  85. xReturn = ( TaskHandle_t ) pxTaskBuffer;
  86. }
  87. return xReturn;
  88. }
  89. #endif /* SUPPORT_STATIC_ALLOCATION */
  90. #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  91. BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
  92. const char * const pcName,
  93. const configSTACK_DEPTH_TYPE usStackDepth,
  94. void * const pvParameters,
  95. UBaseType_t uxPriority,
  96. TaskHandle_t * const pxCreatedTask )
  97. {
  98. TCB_t * pxNewTCB;
  99. BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
  100. void * stack_start = RT_NULL;
  101. pxNewTCB = ( TCB_t * ) RT_KERNEL_MALLOC( sizeof( TCB_t ) );
  102. if ( pxNewTCB != NULL )
  103. {
  104. stack_start = RT_KERNEL_MALLOC( usStackDepth * sizeof( StackType_t ) );
  105. if ( stack_start != RT_NULL )
  106. {
  107. rt_thread_init( ( struct rt_thread * ) pxNewTCB, pcName, pxTaskCode, pvParameters,
  108. stack_start, usStackDepth * sizeof( StackType_t ), FREERTOS_PRIORITY_TO_RTTHREAD( uxPriority ), 1 );
  109. xReturn = pdPASS;
  110. if ( pxCreatedTask != NULL )
  111. {
  112. *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
  113. }
  114. /* Mark as dynamic */
  115. ( ( struct rt_thread * ) pxNewTCB )->type &= ~RT_Object_Class_Static;
  116. rt_thread_startup( ( rt_thread_t ) pxNewTCB );
  117. }
  118. else
  119. {
  120. RT_KERNEL_FREE( pxNewTCB );
  121. }
  122. }
  123. return xReturn;
  124. }
  125. #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
  126. /*-----------------------------------------------------------*/
  127. #if ( INCLUDE_vTaskDelete == 1 )
  128. void vTaskDelete( TaskHandle_t xTaskToDelete )
  129. {
  130. rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTaskToDelete );
  131. if ( thread == RT_NULL )
  132. {
  133. thread = rt_thread_self();
  134. }
  135. #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
  136. if ( rt_object_is_systemobject( ( rt_object_t ) thread ) )
  137. #endif
  138. {
  139. #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
  140. rt_thread_detach( thread );
  141. #endif
  142. #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
  143. }
  144. else
  145. {
  146. #endif
  147. #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  148. rt_thread_delete( thread );
  149. #endif
  150. }
  151. if ( thread == rt_thread_self() )
  152. {
  153. rt_schedule();
  154. }
  155. }
  156. #endif /* INCLUDE_vTaskDelete */
  157. /*-----------------------------------------------------------*/
  158. #if ( INCLUDE_xTaskDelayUntil == 1 )
  159. BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
  160. const TickType_t xTimeIncrement )
  161. {
  162. BaseType_t xShouldDelay = pdFALSE;
  163. rt_base_t level;
  164. rt_tick_t cur_tick;
  165. RT_ASSERT( pxPreviousWakeTime != RT_NULL );
  166. RT_ASSERT( xTimeIncrement > 0U );
  167. level = rt_hw_interrupt_disable();
  168. cur_tick = rt_tick_get();
  169. if (cur_tick - *pxPreviousWakeTime < xTimeIncrement)
  170. {
  171. rt_thread_delay_until( pxPreviousWakeTime, xTimeIncrement );
  172. xShouldDelay = pdTRUE;
  173. }
  174. rt_hw_interrupt_enable( level );
  175. return xShouldDelay;
  176. }
  177. #endif /* INCLUDE_xTaskDelayUntil */
  178. /*-----------------------------------------------------------*/
  179. #if ( INCLUDE_vTaskDelay == 1 )
  180. void vTaskDelay( const TickType_t xTicksToDelay )
  181. {
  182. rt_thread_delay( xTicksToDelay );
  183. }
  184. #endif /* INCLUDE_vTaskDelay */
  185. /*-----------------------------------------------------------*/
  186. #if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) )
  187. eTaskState eTaskGetState( TaskHandle_t xTask )
  188. {
  189. eTaskState eReturn;
  190. rt_thread_t thread = ( rt_thread_t ) xTask;
  191. rt_base_t level;
  192. configASSERT( pxTCB );
  193. level = rt_hw_interrupt_disable();
  194. switch ( thread->stat & RT_THREAD_STAT_MASK )
  195. {
  196. case RT_THREAD_READY:
  197. {
  198. eReturn = eReady;
  199. break;
  200. }
  201. case RT_THREAD_SUSPEND:
  202. {
  203. /* If thread timer is activated it is blocked with a timeout */
  204. if ( thread->thread_timer.parent.flag & RT_TIMER_FLAG_ACTIVATED )
  205. {
  206. eReturn = eBlocked;
  207. }
  208. /* Otherwise it is suspended or blocked with an infinite timeout */
  209. else
  210. {
  211. eReturn = eSuspended;
  212. }
  213. break;
  214. }
  215. case RT_THREAD_RUNNING:
  216. {
  217. eReturn = eRunning;
  218. break;
  219. }
  220. case RT_THREAD_CLOSE:
  221. {
  222. eReturn = eDeleted;
  223. break;
  224. }
  225. default:
  226. eReturn = eInvalid;
  227. }
  228. rt_hw_interrupt_enable( level );
  229. return eReturn;
  230. }
  231. #endif /* INCLUDE_eTaskGetState */
  232. /*-----------------------------------------------------------*/
  233. #if ( INCLUDE_uxTaskPriorityGet == 1 )
  234. UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
  235. {
  236. UBaseType_t uxReturn;
  237. rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTask );
  238. rt_base_t level;
  239. level = rt_hw_interrupt_disable();
  240. uxReturn = thread->current_priority;
  241. rt_hw_interrupt_enable( level );
  242. return RTTHREAD_PRIORITY_TO_FREERTOS( uxReturn );
  243. }
  244. #endif /* INCLUDE_uxTaskPriorityGet */
  245. /*-----------------------------------------------------------*/
  246. #if ( INCLUDE_uxTaskPriorityGet == 1 )
  247. UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask )
  248. {
  249. return uxTaskPriorityGet( xTask );
  250. }
  251. #endif /* INCLUDE_uxTaskPriorityGet */
  252. /*-----------------------------------------------------------*/
  253. #if ( INCLUDE_vTaskPrioritySet == 1 )
  254. void vTaskPrioritySet( TaskHandle_t xTask,
  255. UBaseType_t uxNewPriority )
  256. {
  257. extern rt_thread_t rt_current_thread;
  258. rt_thread_t thread;
  259. rt_uint8_t current_priority;
  260. rt_bool_t need_schedule = RT_FALSE;
  261. rt_base_t level;
  262. configASSERT( uxNewPriority < configMAX_PRIORITIES );
  263. /* Ensure the new priority is valid. */
  264. if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
  265. {
  266. uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
  267. }
  268. uxNewPriority = FREERTOS_PRIORITY_TO_RTTHREAD( uxNewPriority );
  269. level = rt_hw_interrupt_disable();
  270. thread = ( rt_thread_t ) prvGetTCBFromHandle( xTask );
  271. current_priority = thread->current_priority;
  272. if ( current_priority != uxNewPriority )
  273. {
  274. rt_thread_control( thread, RT_THREAD_CTRL_CHANGE_PRIORITY, &uxNewPriority);
  275. if ( uxNewPriority < current_priority )
  276. {
  277. /* The priority of a task other than the currently running task is being raised.
  278. * Need to schedule if the priority is raised above that of the running task */
  279. if ( thread != rt_current_thread && uxNewPriority <= rt_current_thread->current_priority )
  280. {
  281. need_schedule = RT_TRUE;
  282. }
  283. }
  284. /* Setting the priority of the running task down means
  285. * there may now be another task of higher priority that
  286. * is ready to execute. */
  287. else if ( thread == rt_current_thread )
  288. {
  289. need_schedule = RT_TRUE;
  290. }
  291. }
  292. rt_hw_interrupt_enable( level );
  293. if ( need_schedule == RT_TRUE )
  294. {
  295. rt_schedule();
  296. }
  297. }
  298. #endif /* INCLUDE_vTaskPrioritySet */
  299. /*-----------------------------------------------------------*/
  300. #if ( INCLUDE_vTaskSuspend == 1 )
  301. void vTaskSuspend( TaskHandle_t xTaskToSuspend )
  302. {
  303. rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTaskToSuspend );
  304. if ( rt_thread_suspend( thread ) == RT_EOK )
  305. {
  306. rt_schedule();
  307. }
  308. }
  309. #endif /* INCLUDE_vTaskSuspend */
  310. /*-----------------------------------------------------------*/
  311. #if ( INCLUDE_vTaskSuspend == 1 )
  312. void vTaskResume( TaskHandle_t xTaskToResume )
  313. {
  314. rt_thread_t thread = ( rt_thread_t ) xTaskToResume;
  315. rt_bool_t need_schedule = RT_FALSE;
  316. rt_base_t level;
  317. /* It does not make sense to resume the calling task. */
  318. configASSERT( xTaskToResume );
  319. if ( thread != NULL && thread != rt_thread_self() )
  320. {
  321. level = rt_hw_interrupt_disable();
  322. /* A task with higher priority than the current running task is ready */
  323. if ( rt_thread_resume( thread ) == RT_EOK && thread->current_priority <= rt_thread_self()->current_priority )
  324. {
  325. need_schedule = RT_TRUE;
  326. }
  327. rt_hw_interrupt_enable(level);
  328. }
  329. if (need_schedule == RT_TRUE)
  330. {
  331. rt_schedule();
  332. }
  333. }
  334. #endif /* INCLUDE_vTaskSuspend */
  335. /*-----------------------------------------------------------*/
  336. #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
  337. BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
  338. {
  339. vTaskResume( xTaskToResume );
  340. return pdFALSE;
  341. }
  342. #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
  343. /*-----------------------------------------------------------*/
  344. void vTaskSuspendAll( void )
  345. {
  346. rt_enter_critical();
  347. }
  348. /*----------------------------------------------------------*/
  349. BaseType_t xTaskResumeAll( void )
  350. {
  351. rt_exit_critical();
  352. return pdFALSE;
  353. }
  354. /*-----------------------------------------------------------*/
  355. TickType_t xTaskGetTickCount( void )
  356. {
  357. return rt_tick_get();
  358. }
  359. /*-----------------------------------------------------------*/
  360. TickType_t xTaskGetTickCountFromISR( void )
  361. {
  362. return rt_tick_get();
  363. }
  364. /*-----------------------------------------------------------*/
  365. UBaseType_t uxTaskGetNumberOfTasks( void )
  366. {
  367. UBaseType_t uxReturn = 0;
  368. rt_base_t level;
  369. struct rt_object_information *information;
  370. struct rt_list_node *node = RT_NULL;
  371. information = rt_object_get_information( RT_Object_Class_Thread );
  372. RT_ASSERT( information != RT_NULL );
  373. level = rt_hw_interrupt_disable();
  374. rt_list_for_each( node, &( information->object_list ) )
  375. {
  376. uxReturn += 1;
  377. }
  378. rt_hw_interrupt_enable( level );
  379. return uxReturn;
  380. }
  381. /*-----------------------------------------------------------*/
  382. char * pcTaskGetName( TaskHandle_t xTaskToQuery )
  383. {
  384. rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTaskToQuery );
  385. return &( thread->name[ 0 ] );
  386. }
  387. /*-----------------------------------------------------------*/
  388. #if ( INCLUDE_xTaskGetHandle == 1 )
  389. TaskHandle_t xTaskGetHandle( const char * pcNameToQuery )
  390. {
  391. return ( TaskHandle_t ) rt_thread_find( ( char * ) pcNameToQuery );
  392. }
  393. #endif /* INCLUDE_xTaskGetHandle */
  394. /*-----------------------------------------------------------*/
  395. #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
  396. TaskHandle_t xTaskGetIdleTaskHandle( void )
  397. {
  398. return ( TaskHandle_t ) rt_thread_find( "tidle0" );
  399. }
  400. #endif /* INCLUDE_xTaskGetIdleTaskHandle */
  401. /*----------------------------------------------------------*/
  402. #if ( INCLUDE_xTaskAbortDelay == 1 )
  403. BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
  404. {
  405. BaseType_t xReturn;
  406. rt_thread_t thread = ( rt_thread_t ) xTask;
  407. rt_bool_t need_schedule = RT_FALSE;
  408. rt_base_t level;
  409. configASSERT( pxTCB );
  410. level = rt_hw_interrupt_disable();
  411. if ( eTaskGetState( xTask ) == eBlocked )
  412. {
  413. rt_thread_resume( thread );
  414. thread->error = -RT_ETIMEOUT;
  415. if ( thread->current_priority < rt_thread_self()->current_priority ){
  416. need_schedule = RT_TRUE;
  417. }
  418. xReturn = pdPASS;
  419. }
  420. else
  421. {
  422. xReturn = pdFAIL;
  423. }
  424. rt_hw_interrupt_enable( level );
  425. if ( need_schedule == RT_TRUE )
  426. {
  427. rt_schedule();
  428. }
  429. return xReturn;
  430. }
  431. #endif /* INCLUDE_xTaskAbortDelay */
  432. /*----------------------------------------------------------*/
  433. #if ( configUSE_APPLICATION_TASK_TAG == 1 )
  434. void vTaskSetApplicationTaskTag( TaskHandle_t xTask,
  435. TaskHookFunction_t pxHookFunction )
  436. {
  437. TCB_t * xTCB = prvGetTCBFromHandle( xTask );
  438. rt_base_t level;
  439. level = rt_hw_interrupt_disable();
  440. xTCB->pxTaskTag = pxHookFunction;
  441. rt_hw_interrupt_enable( level );
  442. }
  443. #endif /* configUSE_APPLICATION_TASK_TAG */
  444. /*-----------------------------------------------------------*/
  445. #if ( configUSE_APPLICATION_TASK_TAG == 1 )
  446. TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
  447. {
  448. TaskHookFunction_t xReturn;
  449. TCB_t * xTCB = prvGetTCBFromHandle( xTask );
  450. rt_base_t level;
  451. level = rt_hw_interrupt_disable();
  452. xReturn = xTCB->pxTaskTag;
  453. rt_hw_interrupt_enable( level );
  454. return xReturn;
  455. }
  456. #endif /* configUSE_APPLICATION_TASK_TAG */
  457. /*-----------------------------------------------------------*/
  458. #if ( configUSE_APPLICATION_TASK_TAG == 1 )
  459. TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask )
  460. {
  461. return xTaskGetApplicationTaskTag( xTask );
  462. }
  463. #endif /* configUSE_APPLICATION_TASK_TAG */
  464. /*-----------------------------------------------------------*/
  465. #if ( configUSE_APPLICATION_TASK_TAG == 1 )
  466. BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
  467. void * pvParameter )
  468. {
  469. BaseType_t xReturn;
  470. TCB_t * xTCB = prvGetTCBFromHandle( xTask );
  471. if( xTCB->pxTaskTag != NULL )
  472. {
  473. xReturn = xTCB->pxTaskTag( pvParameter );
  474. }
  475. else
  476. {
  477. xReturn = pdFAIL;
  478. }
  479. return xReturn;
  480. }
  481. #endif /* configUSE_APPLICATION_TASK_TAG */
  482. /*-----------------------------------------------------------*/
  483. #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) )
  484. TaskHandle_t xTaskGetCurrentTaskHandle( void )
  485. {
  486. TaskHandle_t xReturn;
  487. /* A critical section is not required as this is not called from
  488. * an interrupt and the current TCB will always be the same for any
  489. * individual execution thread. */
  490. xReturn = ( TaskHandle_t ) rt_thread_self();
  491. return xReturn;
  492. }
  493. #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
  494. /*-----------------------------------------------------------*/
  495. #if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
  496. /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the
  497. * same except for their return type. Using configSTACK_DEPTH_TYPE allows the
  498. * user to determine the return type. It gets around the problem of the value
  499. * overflowing on 8-bit types without breaking backward compatibility for
  500. * applications that expect an 8-bit return type. */
  501. configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask )
  502. {
  503. uint32_t ulCount = 0U;
  504. rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTask );
  505. rt_uint8_t * stack_addr = thread->stack_addr;
  506. #ifdef ARCH_CPU_STACK_GROWS_UPWARD
  507. stack_addr = stack_addr + thread->stack_size - 1;
  508. while ( *stack_addr == '#' )
  509. {
  510. ulCount += 1;
  511. stack_addr -= 1;
  512. }
  513. #else
  514. while ( *stack_addr == '#' )
  515. {
  516. ulCount += 1;
  517. stack_addr += 1;
  518. }
  519. #endif
  520. ulCount /= ( uint32_t ) sizeof( StackType_t );
  521. return ( configSTACK_DEPTH_TYPE ) ulCount;
  522. }
  523. #endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */
  524. /*-----------------------------------------------------------*/
  525. #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
  526. UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
  527. {
  528. return ( UBaseType_t ) uxTaskGetStackHighWaterMark2( xTask );
  529. }
  530. #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
  531. /*-----------------------------------------------------------*/