| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055 |
- /*
- * FreeRTOS Kernel V10.4.6
- * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * https://www.FreeRTOS.org
- * https://github.com/FreeRTOS
- *
- */
- /* Standard includes. */
- #include <stdlib.h>
- #include <string.h>
- /* FreeRTOS includes. */
- #include "FreeRTOS.h"
- #include "task.h"
- //TODO: check configMAX_PRIORITIES == RT_THREAD_PRIORITY_MAX
- #define FREERTOS_PRIORITY_TO_RTTHREAD(priority) ( configMAX_PRIORITIES - 1 - ( priority ) )
- #define RTTHREAD_PRIORITY_TO_FREERTOS(priority) ( RT_THREAD_PRIORITY_MAX - 1 - ( priority ) )
- /* Values that can be assigned to the ucNotifyState member of the TCB. */
- #define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) /* Must be zero as it is the initialised value. */
- #define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 )
- #define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 )
- /*
- * Several functions take a TaskHandle_t parameter that can optionally be NULL,
- * where NULL is used to indicate that the handle of the currently executing
- * task should be used in place of the parameter. This macro simply checks to
- * see if the parameter is NULL and returns a pointer to the appropriate TCB.
- */
- #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( xTaskGetCurrentTaskHandle() ) : ( pxHandle ) )
- /*
- * Task control block. A task control block (TCB) is allocated for each task,
- * and stores task state information, including a pointer to the task's context
- * (the task's run time environment, including register values)
- */
- typedef struct tskTaskControlBlock
- {
- struct rt_thread thread;
- #if ( configUSE_APPLICATION_TASK_TAG == 1 )
- TaskHookFunction_t pxTaskTag;
- #endif
- #if ( configUSE_TASK_NOTIFICATIONS == 1 )
- volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
- volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
- #endif
- } tskTCB;
- typedef tskTCB TCB_t;
- /*-----------------------------------------------------------*/
- /*
- * Called after a Task_t structure has been allocated either statically or
- * dynamically to fill in the structure's members.
- */
- static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
- const char * const pcName,
- const uint32_t ulStackDepth,
- void * const pvParameters,
- UBaseType_t uxPriority,
- TaskHandle_t * const pxCreatedTask,
- TCB_t * pxNewTCB,
- StackType_t * const puxStackBuffer );
- #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
- TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
- const char * const pcName,
- const uint32_t ulStackDepth,
- void * const pvParameters,
- UBaseType_t uxPriority,
- StackType_t * const puxStackBuffer,
- StaticTask_t * const pxTaskBuffer )
- {
- TCB_t * pxNewTCB;
- TaskHandle_t xReturn = NULL;
- configASSERT( puxStackBuffer != NULL );
- configASSERT( pxTaskBuffer != NULL );
- #if ( configASSERT_DEFINED == 1 )
- {
- /* Sanity check that the size of the structure used to declare a
- * variable of type StaticTask_t equals the size of the real task
- * structure. */
- volatile size_t xSize = sizeof( StaticTask_t );
- configASSERT( xSize == sizeof( TCB_t ) );
- ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
- }
- #endif /* configASSERT_DEFINED */
- if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
- {
- pxNewTCB = ( TCB_t * ) pxTaskBuffer;
- prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, puxStackBuffer );
- rt_thread_startup( ( rt_thread_t ) pxNewTCB );
- }
- return xReturn;
- }
- #endif /* SUPPORT_STATIC_ALLOCATION */
- #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
- BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
- const char * const pcName,
- const configSTACK_DEPTH_TYPE usStackDepth,
- void * const pvParameters,
- UBaseType_t uxPriority,
- TaskHandle_t * const pxCreatedTask )
- {
- TCB_t * pxNewTCB;
- BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
- void * stack_start = RT_NULL;
- pxNewTCB = ( TCB_t * ) RT_KERNEL_MALLOC( sizeof( TCB_t ) );
- if ( pxNewTCB != NULL )
- {
- stack_start = RT_KERNEL_MALLOC( usStackDepth * sizeof( StackType_t ) );
- if ( stack_start != RT_NULL )
- {
- prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, ( StackType_t * ) stack_start );
- xReturn = pdPASS;
- /* Mark as dynamic */
- ( ( struct rt_thread * ) pxNewTCB )->type &= ~RT_Object_Class_Static;
- rt_thread_startup( ( rt_thread_t ) pxNewTCB );
- }
- else
- {
- RT_KERNEL_FREE( pxNewTCB );
- }
- }
- return xReturn;
- }
- #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
- /*-----------------------------------------------------------*/
- static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
- const char * const pcName,
- const uint32_t ulStackDepth,
- void * const pvParameters,
- UBaseType_t uxPriority,
- TaskHandle_t * const pxCreatedTask,
- TCB_t * pxNewTCB,
- StackType_t * const puxStackBuffer )
- {
- /* This is used as an array index so must ensure it's not too large. */
- configASSERT( uxPriority < configMAX_PRIORITIES );
- if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
- {
- uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
- }
- rt_thread_init( ( struct rt_thread * ) pxNewTCB, pcName, pxTaskCode, pvParameters,
- puxStackBuffer, ulStackDepth * sizeof( StackType_t ), FREERTOS_PRIORITY_TO_RTTHREAD( uxPriority ), 1 );
- #if ( configUSE_APPLICATION_TASK_TAG == 1 )
- pxNewTCB->pxTaskTag = NULL;
- #endif
- #if ( configUSE_TASK_NOTIFICATIONS == 1 )
- rt_memset( ( void * ) &( pxNewTCB->ulNotifiedValue[ 0 ] ), 0x00, sizeof( pxNewTCB->ulNotifiedValue ) );
- rt_memset( ( void * ) &( pxNewTCB->ucNotifyState[ 0 ] ), 0x00, sizeof( pxNewTCB->ucNotifyState ) );
- #endif
- if ( pxCreatedTask != NULL )
- {
- *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
- }
- }
- /*-----------------------------------------------------------*/
- #if ( INCLUDE_vTaskDelete == 1 )
- void vTaskDelete( TaskHandle_t xTaskToDelete )
- {
- rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTaskToDelete );
- if ( thread == RT_NULL )
- {
- thread = rt_thread_self();
- }
- #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
- if ( rt_object_is_systemobject( ( rt_object_t ) thread ) )
- #endif
- {
- #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
- rt_thread_detach( thread );
- #endif
- #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
- }
- else
- {
- #endif
- #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
- rt_thread_delete( thread );
- #endif
- }
- if ( thread == rt_thread_self() )
- {
- rt_schedule();
- }
- }
- #endif /* INCLUDE_vTaskDelete */
- /*-----------------------------------------------------------*/
- #if ( INCLUDE_xTaskDelayUntil == 1 )
- BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
- const TickType_t xTimeIncrement )
- {
- BaseType_t xShouldDelay = pdFALSE;
- rt_base_t level;
- rt_tick_t cur_tick;
- RT_ASSERT( pxPreviousWakeTime != RT_NULL );
- RT_ASSERT( xTimeIncrement > 0U );
- level = rt_hw_interrupt_disable();
- cur_tick = rt_tick_get();
- if (cur_tick - *pxPreviousWakeTime < xTimeIncrement)
- {
- rt_thread_delay_until( pxPreviousWakeTime, xTimeIncrement );
- xShouldDelay = pdTRUE;
- }
- rt_hw_interrupt_enable( level );
- return xShouldDelay;
- }
- #endif /* INCLUDE_xTaskDelayUntil */
- /*-----------------------------------------------------------*/
- #if ( INCLUDE_vTaskDelay == 1 )
- void vTaskDelay( const TickType_t xTicksToDelay )
- {
- rt_thread_delay( xTicksToDelay );
- }
- #endif /* INCLUDE_vTaskDelay */
- /*-----------------------------------------------------------*/
- #if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) )
- eTaskState eTaskGetState( TaskHandle_t xTask )
- {
- eTaskState eReturn;
- rt_thread_t thread = ( rt_thread_t ) xTask;
- rt_base_t level;
- configASSERT( pxTCB );
- level = rt_hw_interrupt_disable();
- switch ( thread->stat & RT_THREAD_STAT_MASK )
- {
- case RT_THREAD_READY:
- {
- eReturn = eReady;
- break;
- }
- case RT_THREAD_SUSPEND:
- {
- /* If thread timer is activated it is blocked with a timeout */
- if ( thread->thread_timer.parent.flag & RT_TIMER_FLAG_ACTIVATED )
- {
- eReturn = eBlocked;
- }
- /* Otherwise it is suspended or blocked with an infinite timeout */
- else
- {
- eReturn = eSuspended;
- }
- break;
- }
- case RT_THREAD_RUNNING:
- {
- eReturn = eRunning;
- break;
- }
- case RT_THREAD_CLOSE:
- {
- eReturn = eDeleted;
- break;
- }
- default:
- eReturn = eInvalid;
- }
- rt_hw_interrupt_enable( level );
- return eReturn;
- }
- #endif /* INCLUDE_eTaskGetState */
- /*-----------------------------------------------------------*/
- #if ( INCLUDE_uxTaskPriorityGet == 1 )
- UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
- {
- UBaseType_t uxReturn;
- rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTask );
- rt_base_t level;
- level = rt_hw_interrupt_disable();
- uxReturn = thread->current_priority;
- rt_hw_interrupt_enable( level );
- return RTTHREAD_PRIORITY_TO_FREERTOS( uxReturn );
- }
- #endif /* INCLUDE_uxTaskPriorityGet */
- /*-----------------------------------------------------------*/
- #if ( INCLUDE_uxTaskPriorityGet == 1 )
- UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask )
- {
- return uxTaskPriorityGet( xTask );
- }
- #endif /* INCLUDE_uxTaskPriorityGet */
- /*-----------------------------------------------------------*/
- #if ( INCLUDE_vTaskPrioritySet == 1 )
- void vTaskPrioritySet( TaskHandle_t xTask,
- UBaseType_t uxNewPriority )
- {
- extern rt_thread_t rt_current_thread;
- rt_thread_t thread;
- rt_uint8_t current_priority;
- rt_bool_t need_schedule = RT_FALSE;
- rt_base_t level;
- configASSERT( uxNewPriority < configMAX_PRIORITIES );
- /* Ensure the new priority is valid. */
- if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
- {
- uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
- }
- uxNewPriority = FREERTOS_PRIORITY_TO_RTTHREAD( uxNewPriority );
- level = rt_hw_interrupt_disable();
- thread = ( rt_thread_t ) prvGetTCBFromHandle( xTask );
- current_priority = thread->current_priority;
- if ( current_priority != uxNewPriority )
- {
- rt_thread_control( thread, RT_THREAD_CTRL_CHANGE_PRIORITY, &uxNewPriority);
- if ( uxNewPriority < current_priority )
- {
- /* The priority of a task other than the currently running task is being raised.
- * Need to schedule if the priority is raised above that of the running task */
- if ( thread != rt_current_thread && uxNewPriority <= rt_current_thread->current_priority )
- {
- need_schedule = RT_TRUE;
- }
- }
- /* Setting the priority of the running task down means
- * there may now be another task of higher priority that
- * is ready to execute. */
- else if ( thread == rt_current_thread )
- {
- need_schedule = RT_TRUE;
- }
- }
- rt_hw_interrupt_enable( level );
- if ( need_schedule == RT_TRUE )
- {
- rt_schedule();
- }
- }
- #endif /* INCLUDE_vTaskPrioritySet */
- /*-----------------------------------------------------------*/
- #if ( INCLUDE_vTaskSuspend == 1 )
- void vTaskSuspend( TaskHandle_t xTaskToSuspend )
- {
- rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTaskToSuspend );
- if ( rt_thread_suspend( thread ) == RT_EOK )
- {
- rt_schedule();
- }
- }
- #endif /* INCLUDE_vTaskSuspend */
- /*-----------------------------------------------------------*/
- #if ( INCLUDE_vTaskSuspend == 1 )
- void vTaskResume( TaskHandle_t xTaskToResume )
- {
- rt_thread_t thread = ( rt_thread_t ) xTaskToResume;
- rt_bool_t need_schedule = RT_FALSE;
- rt_base_t level;
- /* It does not make sense to resume the calling task. */
- configASSERT( xTaskToResume );
- if ( thread != NULL && thread != rt_thread_self() )
- {
- level = rt_hw_interrupt_disable();
- /* A task with higher priority than the current running task is ready */
- if ( rt_thread_resume( thread ) == RT_EOK && thread->current_priority <= rt_thread_self()->current_priority )
- {
- need_schedule = RT_TRUE;
- }
- rt_hw_interrupt_enable( level );
- }
- if (need_schedule == RT_TRUE)
- {
- rt_schedule();
- }
- }
- #endif /* INCLUDE_vTaskSuspend */
- /*-----------------------------------------------------------*/
- #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
- BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
- {
- vTaskResume( xTaskToResume );
- return pdFALSE;
- }
- #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
- /*-----------------------------------------------------------*/
- void vTaskSuspendAll( void )
- {
- rt_enter_critical();
- }
- /*----------------------------------------------------------*/
- BaseType_t xTaskResumeAll( void )
- {
- rt_exit_critical();
- return pdFALSE;
- }
- /*-----------------------------------------------------------*/
- TickType_t xTaskGetTickCount( void )
- {
- return rt_tick_get();
- }
- /*-----------------------------------------------------------*/
- TickType_t xTaskGetTickCountFromISR( void )
- {
- return rt_tick_get();
- }
- /*-----------------------------------------------------------*/
- UBaseType_t uxTaskGetNumberOfTasks( void )
- {
- UBaseType_t uxReturn = 0;
- rt_base_t level;
- struct rt_object_information *information;
- struct rt_list_node *node = RT_NULL;
- information = rt_object_get_information( RT_Object_Class_Thread );
- RT_ASSERT( information != RT_NULL );
- level = rt_hw_interrupt_disable();
- rt_list_for_each( node, &( information->object_list ) )
- {
- uxReturn += 1;
- }
- rt_hw_interrupt_enable( level );
- return uxReturn;
- }
- /*-----------------------------------------------------------*/
- char * pcTaskGetName( TaskHandle_t xTaskToQuery )
- {
- rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTaskToQuery );
- return &( thread->name[ 0 ] );
- }
- /*-----------------------------------------------------------*/
- #if ( INCLUDE_xTaskGetHandle == 1 )
- TaskHandle_t xTaskGetHandle( const char * pcNameToQuery )
- {
- return ( TaskHandle_t ) rt_thread_find( ( char * ) pcNameToQuery );
- }
- #endif /* INCLUDE_xTaskGetHandle */
- /*-----------------------------------------------------------*/
- #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
- TaskHandle_t xTaskGetIdleTaskHandle( void )
- {
- return ( TaskHandle_t ) rt_thread_find( "tidle0" );
- }
- #endif /* INCLUDE_xTaskGetIdleTaskHandle */
- /*----------------------------------------------------------*/
- #if ( INCLUDE_xTaskAbortDelay == 1 )
- BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
- {
- BaseType_t xReturn;
- rt_thread_t thread = ( rt_thread_t ) xTask;
- rt_bool_t need_schedule = RT_FALSE;
- rt_base_t level;
- configASSERT( pxTCB );
- level = rt_hw_interrupt_disable();
- if ( eTaskGetState( xTask ) == eBlocked )
- {
- rt_thread_resume( thread );
- thread->error = -RT_ETIMEOUT;
- if ( thread->current_priority < rt_thread_self()->current_priority ){
- need_schedule = RT_TRUE;
- }
- xReturn = pdPASS;
- }
- else
- {
- xReturn = pdFAIL;
- }
- rt_hw_interrupt_enable( level );
- if ( need_schedule == RT_TRUE )
- {
- rt_schedule();
- }
- return xReturn;
- }
- #endif /* INCLUDE_xTaskAbortDelay */
- /*----------------------------------------------------------*/
- #if ( configUSE_APPLICATION_TASK_TAG == 1 )
- void vTaskSetApplicationTaskTag( TaskHandle_t xTask,
- TaskHookFunction_t pxHookFunction )
- {
- TCB_t * xTCB = prvGetTCBFromHandle( xTask );
- rt_base_t level;
- level = rt_hw_interrupt_disable();
- xTCB->pxTaskTag = pxHookFunction;
- rt_hw_interrupt_enable( level );
- }
- #endif /* configUSE_APPLICATION_TASK_TAG */
- /*-----------------------------------------------------------*/
- #if ( configUSE_APPLICATION_TASK_TAG == 1 )
- TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
- {
- TaskHookFunction_t xReturn;
- TCB_t * xTCB = prvGetTCBFromHandle( xTask );
- rt_base_t level;
- level = rt_hw_interrupt_disable();
- xReturn = xTCB->pxTaskTag;
- rt_hw_interrupt_enable( level );
- return xReturn;
- }
- #endif /* configUSE_APPLICATION_TASK_TAG */
- /*-----------------------------------------------------------*/
- #if ( configUSE_APPLICATION_TASK_TAG == 1 )
- TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask )
- {
- return xTaskGetApplicationTaskTag( xTask );
- }
- #endif /* configUSE_APPLICATION_TASK_TAG */
- /*-----------------------------------------------------------*/
- #if ( configUSE_APPLICATION_TASK_TAG == 1 )
- BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
- void * pvParameter )
- {
- BaseType_t xReturn;
- TCB_t * xTCB = prvGetTCBFromHandle( xTask );
- if( xTCB->pxTaskTag != NULL )
- {
- xReturn = xTCB->pxTaskTag( pvParameter );
- }
- else
- {
- xReturn = pdFAIL;
- }
- return xReturn;
- }
- #endif /* configUSE_APPLICATION_TASK_TAG */
- /*-----------------------------------------------------------*/
- #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) )
- TaskHandle_t xTaskGetCurrentTaskHandle( void )
- {
- TaskHandle_t xReturn;
- /* A critical section is not required as this is not called from
- * an interrupt and the current TCB will always be the same for any
- * individual execution thread. */
- xReturn = ( TaskHandle_t ) rt_thread_self();
- return xReturn;
- }
- #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
- /*-----------------------------------------------------------*/
- #if ( configUSE_TASK_NOTIFICATIONS == 1 )
- uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait,
- BaseType_t xClearCountOnExit,
- TickType_t xTicksToWait )
- {
- uint32_t ulReturn;
- TCB_t * pxCurrentTCB = ( TCB_t * ) rt_thread_self();
- rt_thread_t thread = ( rt_thread_t ) pxCurrentTCB;
- rt_base_t level;
- configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
- level = rt_hw_interrupt_disable();
- /* Only block if the notification count is not already non-zero. */
- if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL )
- {
- /* Mark this task as waiting for a notification. */
- pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
- if( xTicksToWait > ( TickType_t ) 0 )
- {
- rt_thread_suspend( thread );
- if ( ( rt_int32_t ) xTicksToWait > 0 )
- {
- rt_timer_control(&(thread->thread_timer),
- RT_TIMER_CTRL_SET_TIME,
- &xTicksToWait);
- rt_timer_start(&(thread->thread_timer));
- }
- rt_hw_interrupt_enable(level);
- rt_schedule();
- /* Clear thread error. */
- thread->error = RT_EOK;
- }
- }
- rt_hw_interrupt_enable( level );
- level = rt_hw_interrupt_disable();
- ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
- if( ulReturn != 0UL )
- {
- if( xClearCountOnExit != pdFALSE )
- {
- pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL;
- }
- else
- {
- pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1;
- }
- }
- pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
- rt_hw_interrupt_enable( level );
- return ulReturn;
- }
- #endif /* configUSE_TASK_NOTIFICATIONS */
- /*-----------------------------------------------------------*/
- #if ( configUSE_TASK_NOTIFICATIONS == 1 )
- BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait,
- uint32_t ulBitsToClearOnEntry,
- uint32_t ulBitsToClearOnExit,
- uint32_t * pulNotificationValue,
- TickType_t xTicksToWait )
- {
- BaseType_t xReturn;
- TCB_t * pxCurrentTCB = ( TCB_t * ) rt_thread_self();
- rt_thread_t thread = ( rt_thread_t ) pxCurrentTCB;
- rt_base_t level;
- configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
- level = rt_hw_interrupt_disable();
- /* Only block if a notification is not already pending. */
- if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
- {
- /* Clear bits in the task's notification value as bits may get
- * set by the notifying task or interrupt. This can be used to
- * clear the value to zero. */
- pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry;
- /* Mark this task as waiting for a notification. */
- pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
- if( xTicksToWait > ( TickType_t ) 0 )
- {
- rt_thread_suspend( thread );
- if ( ( rt_int32_t ) xTicksToWait > 0 )
- {
- rt_timer_control(&(thread->thread_timer),
- RT_TIMER_CTRL_SET_TIME,
- &xTicksToWait);
- rt_timer_start(&(thread->thread_timer));
- }
- rt_hw_interrupt_enable(level);
- rt_schedule();
- /* Clear thread error. It is not used to determine the function return value. */
- thread->error = RT_EOK;
- }
- else
- {
- rt_hw_interrupt_enable( level );
- }
- }
- else
- {
- rt_hw_interrupt_enable( level );
- }
- level = rt_hw_interrupt_disable();
- if( pulNotificationValue != NULL )
- {
- /* Output the current notification value, which may or may not
- * have changed. */
- *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
- }
- /* If ucNotifyValue is set then either the task never entered the
- * blocked state (because a notification was already pending) or the
- * task unblocked because of a notification. Otherwise the task
- * unblocked because of a timeout. */
- if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
- {
- /* A notification was not received. */
- xReturn = pdFALSE;
- }
- else
- {
- /* A notification was already pending or a notification was
- * received while the task was waiting. */
- pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnExit;
- xReturn = pdTRUE;
- }
- pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
- rt_hw_interrupt_enable( level );
- return xReturn;
- }
- #endif /* configUSE_TASK_NOTIFICATIONS */
- /*-----------------------------------------------------------*/
- #if ( configUSE_TASK_NOTIFICATIONS == 1 )
- BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
- UBaseType_t uxIndexToNotify,
- uint32_t ulValue,
- eNotifyAction eAction,
- uint32_t * pulPreviousNotificationValue )
- {
- TCB_t * pxTCB;
- BaseType_t xReturn = pdPASS;
- uint8_t ucOriginalNotifyState;
- rt_base_t level;
- configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
- configASSERT( xTaskToNotify );
- pxTCB = xTaskToNotify;
- level = rt_hw_interrupt_disable();
- if( pulPreviousNotificationValue != NULL )
- {
- *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
- }
- ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
- pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
- switch( eAction )
- {
- case eSetBits:
- pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
- break;
- case eIncrement:
- ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
- break;
- case eSetValueWithOverwrite:
- pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
- break;
- case eSetValueWithoutOverwrite:
- if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
- {
- pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
- }
- else
- {
- /* The value could not be written to the task. */
- xReturn = pdFAIL;
- }
- break;
- case eNoAction:
- /* The task is being notified without its notify value being
- * updated. */
- break;
- default:
- /* Should not get here if all enums are handled.
- * Artificially force an assert by testing a value the
- * compiler can't assume is const. */
- configASSERT( xTaskToNotify == NULL );
- break;
- }
- /* If the task is in the blocked state specifically to wait for a
- * notification then unblock it now. */
- if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
- {
- rt_thread_resume( ( rt_thread_t ) pxTCB );
- if( ( ( rt_thread_t ) pxTCB )->current_priority < rt_thread_self()->current_priority )
- {
- /* The notified task has a priority above the currently
- * executing task so a schedule is required. */
- rt_schedule();
- }
- }
- rt_hw_interrupt_enable( level );
- return xReturn;
- }
- #endif /* configUSE_TASK_NOTIFICATIONS */
- /*-----------------------------------------------------------*/
- #if ( configUSE_TASK_NOTIFICATIONS == 1 )
- BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
- UBaseType_t uxIndexToNotify,
- uint32_t ulValue,
- eNotifyAction eAction,
- uint32_t * pulPreviousNotificationValue,
- BaseType_t * pxHigherPriorityTaskWoken )
- {
- BaseType_t xReturn;
- xReturn = xTaskGenericNotify( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue );
- if ( pxHigherPriorityTaskWoken != NULL )
- {
- *pxHigherPriorityTaskWoken = pdFALSE;
- }
- return xReturn;
- }
- #endif /* configUSE_TASK_NOTIFICATIONS */
- /*-----------------------------------------------------------*/
- #if ( configUSE_TASK_NOTIFICATIONS == 1 )
- void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
- UBaseType_t uxIndexToNotify,
- BaseType_t * pxHigherPriorityTaskWoken )
- {
- xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify );
- if ( pxHigherPriorityTaskWoken != NULL )
- {
- *pxHigherPriorityTaskWoken = pdFALSE;
- }
- }
- #endif /* configUSE_TASK_NOTIFICATIONS */
- /*-----------------------------------------------------------*/
- #if ( configUSE_TASK_NOTIFICATIONS == 1 )
- BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
- UBaseType_t uxIndexToClear )
- {
- TCB_t * pxTCB;
- BaseType_t xReturn;
- rt_base_t level;
- configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES );
- /* If null is passed in here then it is the calling task that is having
- * its notification state cleared. */
- pxTCB = prvGetTCBFromHandle( xTask );
- level = rt_hw_interrupt_disable();
- if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED )
- {
- pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION;
- xReturn = pdPASS;
- }
- else
- {
- xReturn = pdFAIL;
- }
- rt_hw_interrupt_enable( level );
- return xReturn;
- }
- #endif /* configUSE_TASK_NOTIFICATIONS */
- /*-----------------------------------------------------------*/
- #if ( configUSE_TASK_NOTIFICATIONS == 1 )
- uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
- UBaseType_t uxIndexToClear,
- uint32_t ulBitsToClear )
- {
- TCB_t * pxTCB;
- uint32_t ulReturn;
- rt_base_t level;
- /* If null is passed in here then it is the calling task that is having
- * its notification state cleared. */
- pxTCB = prvGetTCBFromHandle( xTask );
- level = rt_hw_interrupt_disable();
- /* Return the notification as it was before the bits were cleared,
- * then clear the bit mask. */
- ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ];
- pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear;
- rt_hw_interrupt_enable( level );
- return ulReturn;
- }
- #endif /* configUSE_TASK_NOTIFICATIONS */
- /*-----------------------------------------------------------*/
- #if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
- /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the
- * same except for their return type. Using configSTACK_DEPTH_TYPE allows the
- * user to determine the return type. It gets around the problem of the value
- * overflowing on 8-bit types without breaking backward compatibility for
- * applications that expect an 8-bit return type. */
- configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask )
- {
- uint32_t ulCount = 0U;
- rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTask );
- rt_uint8_t * stack_addr = thread->stack_addr;
- #ifdef ARCH_CPU_STACK_GROWS_UPWARD
- stack_addr = stack_addr + thread->stack_size - 1;
- while ( *stack_addr == '#' )
- {
- ulCount += 1;
- stack_addr -= 1;
- }
- #else
- while ( *stack_addr == '#' )
- {
- ulCount += 1;
- stack_addr += 1;
- }
- #endif
- ulCount /= ( uint32_t ) sizeof( StackType_t );
- return ( configSTACK_DEPTH_TYPE ) ulCount;
- }
- #endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */
- /*-----------------------------------------------------------*/
- #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
- UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
- {
- return ( UBaseType_t ) uxTaskGetStackHighWaterMark2( xTask );
- }
- #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
- /*-----------------------------------------------------------*/
|