Francisco Paez / freertos-cm3

Dependents:   mbed_lpc1768_freertos_lib

Committer:
fep
Date:
Wed May 31 02:36:43 2017 +0000
Revision:
0:5ff20db10a96
FreeRTOS v9.0.0 for ARM Cortex-M3 based boards.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
fep 0:5ff20db10a96 1 /*
fep 0:5ff20db10a96 2 FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
fep 0:5ff20db10a96 3 All rights reserved
fep 0:5ff20db10a96 4
fep 0:5ff20db10a96 5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
fep 0:5ff20db10a96 6
fep 0:5ff20db10a96 7 This file is part of the FreeRTOS distribution.
fep 0:5ff20db10a96 8
fep 0:5ff20db10a96 9 FreeRTOS is free software; you can redistribute it and/or modify it under
fep 0:5ff20db10a96 10 the terms of the GNU General Public License (version 2) as published by the
fep 0:5ff20db10a96 11 Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
fep 0:5ff20db10a96 12
fep 0:5ff20db10a96 13 ***************************************************************************
fep 0:5ff20db10a96 14 >>! NOTE: The modification to the GPL is included to allow you to !<<
fep 0:5ff20db10a96 15 >>! distribute a combined work that includes FreeRTOS without being !<<
fep 0:5ff20db10a96 16 >>! obliged to provide the source code for proprietary components !<<
fep 0:5ff20db10a96 17 >>! outside of the FreeRTOS kernel. !<<
fep 0:5ff20db10a96 18 ***************************************************************************
fep 0:5ff20db10a96 19
fep 0:5ff20db10a96 20 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
fep 0:5ff20db10a96 21 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
fep 0:5ff20db10a96 22 FOR A PARTICULAR PURPOSE. Full license text is available on the following
fep 0:5ff20db10a96 23 link: http://www.freertos.org/a00114.html
fep 0:5ff20db10a96 24
fep 0:5ff20db10a96 25 ***************************************************************************
fep 0:5ff20db10a96 26 * *
fep 0:5ff20db10a96 27 * FreeRTOS provides completely free yet professionally developed, *
fep 0:5ff20db10a96 28 * robust, strictly quality controlled, supported, and cross *
fep 0:5ff20db10a96 29 * platform software that is more than just the market leader, it *
fep 0:5ff20db10a96 30 * is the industry's de facto standard. *
fep 0:5ff20db10a96 31 * *
fep 0:5ff20db10a96 32 * Help yourself get started quickly while simultaneously helping *
fep 0:5ff20db10a96 33 * to support the FreeRTOS project by purchasing a FreeRTOS *
fep 0:5ff20db10a96 34 * tutorial book, reference manual, or both: *
fep 0:5ff20db10a96 35 * http://www.FreeRTOS.org/Documentation *
fep 0:5ff20db10a96 36 * *
fep 0:5ff20db10a96 37 ***************************************************************************
fep 0:5ff20db10a96 38
fep 0:5ff20db10a96 39 http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
fep 0:5ff20db10a96 40 the FAQ page "My application does not run, what could be wrong?". Have you
fep 0:5ff20db10a96 41 defined configASSERT()?
fep 0:5ff20db10a96 42
fep 0:5ff20db10a96 43 http://www.FreeRTOS.org/support - In return for receiving this top quality
fep 0:5ff20db10a96 44 embedded software for free we request you assist our global community by
fep 0:5ff20db10a96 45 participating in the support forum.
fep 0:5ff20db10a96 46
fep 0:5ff20db10a96 47 http://www.FreeRTOS.org/training - Investing in training allows your team to
fep 0:5ff20db10a96 48 be as productive as possible as early as possible. Now you can receive
fep 0:5ff20db10a96 49 FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
fep 0:5ff20db10a96 50 Ltd, and the world's leading authority on the world's leading RTOS.
fep 0:5ff20db10a96 51
fep 0:5ff20db10a96 52 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
fep 0:5ff20db10a96 53 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
fep 0:5ff20db10a96 54 compatible FAT file system, and our tiny thread aware UDP/IP stack.
fep 0:5ff20db10a96 55
fep 0:5ff20db10a96 56 http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
fep 0:5ff20db10a96 57 Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
fep 0:5ff20db10a96 58
fep 0:5ff20db10a96 59 http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
fep 0:5ff20db10a96 60 Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
fep 0:5ff20db10a96 61 licenses offer ticketed support, indemnification and commercial middleware.
fep 0:5ff20db10a96 62
fep 0:5ff20db10a96 63 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
fep 0:5ff20db10a96 64 engineered and independently SIL3 certified version for use in safety and
fep 0:5ff20db10a96 65 mission critical applications that require provable dependability.
fep 0:5ff20db10a96 66
fep 0:5ff20db10a96 67 1 tab == 4 spaces!
fep 0:5ff20db10a96 68 */
fep 0:5ff20db10a96 69
fep 0:5ff20db10a96 70 /* Standard includes. */
fep 0:5ff20db10a96 71 #include <stdlib.h>
fep 0:5ff20db10a96 72 #include <string.h>
fep 0:5ff20db10a96 73
fep 0:5ff20db10a96 74 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
fep 0:5ff20db10a96 75 all the API functions to use the MPU wrappers. That should only be done when
fep 0:5ff20db10a96 76 task.h is included from an application file. */
fep 0:5ff20db10a96 77 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
fep 0:5ff20db10a96 78
fep 0:5ff20db10a96 79 /* FreeRTOS includes. */
fep 0:5ff20db10a96 80 #include "FreeRTOS.h"
fep 0:5ff20db10a96 81 #include "task.h"
fep 0:5ff20db10a96 82 #include "timers.h"
fep 0:5ff20db10a96 83 #include "StackMacros.h"
fep 0:5ff20db10a96 84
fep 0:5ff20db10a96 85 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
fep 0:5ff20db10a96 86 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
fep 0:5ff20db10a96 87 header files above, but not in this file, in order to generate the correct
fep 0:5ff20db10a96 88 privileged Vs unprivileged linkage and placement. */
fep 0:5ff20db10a96 89 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
fep 0:5ff20db10a96 90
fep 0:5ff20db10a96 91 /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting
fep 0:5ff20db10a96 92 functions but without including stdio.h here. */
fep 0:5ff20db10a96 93 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
fep 0:5ff20db10a96 94 /* At the bottom of this file are two optional functions that can be used
fep 0:5ff20db10a96 95 to generate human readable text from the raw data generated by the
fep 0:5ff20db10a96 96 uxTaskGetSystemState() function. Note the formatting functions are provided
fep 0:5ff20db10a96 97 for convenience only, and are NOT considered part of the kernel. */
fep 0:5ff20db10a96 98 #include <stdio.h>
fep 0:5ff20db10a96 99 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
fep 0:5ff20db10a96 100
fep 0:5ff20db10a96 101 #if( configUSE_PREEMPTION == 0 )
fep 0:5ff20db10a96 102 /* If the cooperative scheduler is being used then a yield should not be
fep 0:5ff20db10a96 103 performed just because a higher priority task has been woken. */
fep 0:5ff20db10a96 104 #define taskYIELD_IF_USING_PREEMPTION()
fep 0:5ff20db10a96 105 #else
fep 0:5ff20db10a96 106 #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
fep 0:5ff20db10a96 107 #endif
fep 0:5ff20db10a96 108
fep 0:5ff20db10a96 109 /* Values that can be assigned to the ucNotifyState member of the TCB. */
fep 0:5ff20db10a96 110 #define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 )
fep 0:5ff20db10a96 111 #define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 )
fep 0:5ff20db10a96 112 #define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 )
fep 0:5ff20db10a96 113
fep 0:5ff20db10a96 114 /*
fep 0:5ff20db10a96 115 * The value used to fill the stack of a task when the task is created. This
fep 0:5ff20db10a96 116 * is used purely for checking the high water mark for tasks.
fep 0:5ff20db10a96 117 */
fep 0:5ff20db10a96 118 #define tskSTACK_FILL_BYTE ( 0xa5U )
fep 0:5ff20db10a96 119
fep 0:5ff20db10a96 120 /* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using
fep 0:5ff20db10a96 121 dynamically allocated RAM, in which case when any task is deleted it is known
fep 0:5ff20db10a96 122 that both the task's stack and TCB need to be freed. Sometimes the
fep 0:5ff20db10a96 123 FreeRTOSConfig.h settings only allow a task to be created using statically
fep 0:5ff20db10a96 124 allocated RAM, in which case when any task is deleted it is known that neither
fep 0:5ff20db10a96 125 the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h
fep 0:5ff20db10a96 126 settings allow a task to be created using either statically or dynamically
fep 0:5ff20db10a96 127 allocated RAM, in which case a member of the TCB is used to record whether the
fep 0:5ff20db10a96 128 stack and/or TCB were allocated statically or dynamically, so when a task is
fep 0:5ff20db10a96 129 deleted the RAM that was allocated dynamically is freed again and no attempt is
fep 0:5ff20db10a96 130 made to free the RAM that was allocated statically.
fep 0:5ff20db10a96 131 tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a
fep 0:5ff20db10a96 132 task to be created using either statically or dynamically allocated RAM. Note
fep 0:5ff20db10a96 133 that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
fep 0:5ff20db10a96 134 a statically allocated stack and a dynamically allocated TCB. */
fep 0:5ff20db10a96 135 #define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
fep 0:5ff20db10a96 136 #define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )
fep 0:5ff20db10a96 137 #define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )
fep 0:5ff20db10a96 138 #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )
fep 0:5ff20db10a96 139
fep 0:5ff20db10a96 140 /*
fep 0:5ff20db10a96 141 * Macros used by vListTask to indicate which state a task is in.
fep 0:5ff20db10a96 142 */
fep 0:5ff20db10a96 143 #define tskBLOCKED_CHAR ( 'B' )
fep 0:5ff20db10a96 144 #define tskREADY_CHAR ( 'R' )
fep 0:5ff20db10a96 145 #define tskDELETED_CHAR ( 'D' )
fep 0:5ff20db10a96 146 #define tskSUSPENDED_CHAR ( 'S' )
fep 0:5ff20db10a96 147
fep 0:5ff20db10a96 148 /*
fep 0:5ff20db10a96 149 * Some kernel aware debuggers require the data the debugger needs access to be
fep 0:5ff20db10a96 150 * global, rather than file scope.
fep 0:5ff20db10a96 151 */
fep 0:5ff20db10a96 152 #ifdef portREMOVE_STATIC_QUALIFIER
fep 0:5ff20db10a96 153 #define static
fep 0:5ff20db10a96 154 #endif
fep 0:5ff20db10a96 155
fep 0:5ff20db10a96 156 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
fep 0:5ff20db10a96 157
fep 0:5ff20db10a96 158 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
fep 0:5ff20db10a96 159 performed in a generic way that is not optimised to any particular
fep 0:5ff20db10a96 160 microcontroller architecture. */
fep 0:5ff20db10a96 161
fep 0:5ff20db10a96 162 /* uxTopReadyPriority holds the priority of the highest priority ready
fep 0:5ff20db10a96 163 state task. */
fep 0:5ff20db10a96 164 #define taskRECORD_READY_PRIORITY( uxPriority ) \
fep 0:5ff20db10a96 165 { \
fep 0:5ff20db10a96 166 if( ( uxPriority ) > uxTopReadyPriority ) \
fep 0:5ff20db10a96 167 { \
fep 0:5ff20db10a96 168 uxTopReadyPriority = ( uxPriority ); \
fep 0:5ff20db10a96 169 } \
fep 0:5ff20db10a96 170 } /* taskRECORD_READY_PRIORITY */
fep 0:5ff20db10a96 171
fep 0:5ff20db10a96 172 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 173
fep 0:5ff20db10a96 174 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
fep 0:5ff20db10a96 175 { \
fep 0:5ff20db10a96 176 UBaseType_t uxTopPriority = uxTopReadyPriority; \
fep 0:5ff20db10a96 177 \
fep 0:5ff20db10a96 178 /* Find the highest priority queue that contains ready tasks. */ \
fep 0:5ff20db10a96 179 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
fep 0:5ff20db10a96 180 { \
fep 0:5ff20db10a96 181 configASSERT( uxTopPriority ); \
fep 0:5ff20db10a96 182 --uxTopPriority; \
fep 0:5ff20db10a96 183 } \
fep 0:5ff20db10a96 184 \
fep 0:5ff20db10a96 185 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
fep 0:5ff20db10a96 186 the same priority get an equal share of the processor time. */ \
fep 0:5ff20db10a96 187 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
fep 0:5ff20db10a96 188 uxTopReadyPriority = uxTopPriority; \
fep 0:5ff20db10a96 189 } /* taskSELECT_HIGHEST_PRIORITY_TASK */
fep 0:5ff20db10a96 190
fep 0:5ff20db10a96 191 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 192
fep 0:5ff20db10a96 193 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
fep 0:5ff20db10a96 194 they are only required when a port optimised method of task selection is
fep 0:5ff20db10a96 195 being used. */
fep 0:5ff20db10a96 196 #define taskRESET_READY_PRIORITY( uxPriority )
fep 0:5ff20db10a96 197 #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
fep 0:5ff20db10a96 198
fep 0:5ff20db10a96 199 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
fep 0:5ff20db10a96 200
fep 0:5ff20db10a96 201 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
fep 0:5ff20db10a96 202 performed in a way that is tailored to the particular microcontroller
fep 0:5ff20db10a96 203 architecture being used. */
fep 0:5ff20db10a96 204
fep 0:5ff20db10a96 205 /* A port optimised version is provided. Call the port defined macros. */
fep 0:5ff20db10a96 206 #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
fep 0:5ff20db10a96 207
fep 0:5ff20db10a96 208 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 209
fep 0:5ff20db10a96 210 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
fep 0:5ff20db10a96 211 { \
fep 0:5ff20db10a96 212 UBaseType_t uxTopPriority; \
fep 0:5ff20db10a96 213 \
fep 0:5ff20db10a96 214 /* Find the highest priority list that contains ready tasks. */ \
fep 0:5ff20db10a96 215 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
fep 0:5ff20db10a96 216 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
fep 0:5ff20db10a96 217 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
fep 0:5ff20db10a96 218 } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
fep 0:5ff20db10a96 219
fep 0:5ff20db10a96 220 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 221
fep 0:5ff20db10a96 222 /* A port optimised version is provided, call it only if the TCB being reset
fep 0:5ff20db10a96 223 is being referenced from a ready list. If it is referenced from a delayed
fep 0:5ff20db10a96 224 or suspended list then it won't be in a ready list. */
fep 0:5ff20db10a96 225 #define taskRESET_READY_PRIORITY( uxPriority ) \
fep 0:5ff20db10a96 226 { \
fep 0:5ff20db10a96 227 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
fep 0:5ff20db10a96 228 { \
fep 0:5ff20db10a96 229 portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
fep 0:5ff20db10a96 230 } \
fep 0:5ff20db10a96 231 }
fep 0:5ff20db10a96 232
fep 0:5ff20db10a96 233 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
fep 0:5ff20db10a96 234
fep 0:5ff20db10a96 235 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 236
fep 0:5ff20db10a96 237 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
fep 0:5ff20db10a96 238 count overflows. */
fep 0:5ff20db10a96 239 #define taskSWITCH_DELAYED_LISTS() \
fep 0:5ff20db10a96 240 { \
fep 0:5ff20db10a96 241 List_t *pxTemp; \
fep 0:5ff20db10a96 242 \
fep 0:5ff20db10a96 243 /* The delayed tasks list should be empty when the lists are switched. */ \
fep 0:5ff20db10a96 244 configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
fep 0:5ff20db10a96 245 \
fep 0:5ff20db10a96 246 pxTemp = pxDelayedTaskList; \
fep 0:5ff20db10a96 247 pxDelayedTaskList = pxOverflowDelayedTaskList; \
fep 0:5ff20db10a96 248 pxOverflowDelayedTaskList = pxTemp; \
fep 0:5ff20db10a96 249 xNumOfOverflows++; \
fep 0:5ff20db10a96 250 prvResetNextTaskUnblockTime(); \
fep 0:5ff20db10a96 251 }
fep 0:5ff20db10a96 252
fep 0:5ff20db10a96 253 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 254
fep 0:5ff20db10a96 255 /*
fep 0:5ff20db10a96 256 * Place the task represented by pxTCB into the appropriate ready list for
fep 0:5ff20db10a96 257 * the task. It is inserted at the end of the list.
fep 0:5ff20db10a96 258 */
fep 0:5ff20db10a96 259 #define prvAddTaskToReadyList( pxTCB ) \
fep 0:5ff20db10a96 260 traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
fep 0:5ff20db10a96 261 taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
fep 0:5ff20db10a96 262 vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
fep 0:5ff20db10a96 263 tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
fep 0:5ff20db10a96 264 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 265
fep 0:5ff20db10a96 266 /*
fep 0:5ff20db10a96 267 * Several functions take an TaskHandle_t parameter that can optionally be NULL,
fep 0:5ff20db10a96 268 * where NULL is used to indicate that the handle of the currently executing
fep 0:5ff20db10a96 269 * task should be used in place of the parameter. This macro simply checks to
fep 0:5ff20db10a96 270 * see if the parameter is NULL and returns a pointer to the appropriate TCB.
fep 0:5ff20db10a96 271 */
fep 0:5ff20db10a96 272 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) )
fep 0:5ff20db10a96 273
fep 0:5ff20db10a96 274 /* The item value of the event list item is normally used to hold the priority
fep 0:5ff20db10a96 275 of the task to which it belongs (coded to allow it to be held in reverse
fep 0:5ff20db10a96 276 priority order). However, it is occasionally borrowed for other purposes. It
fep 0:5ff20db10a96 277 is important its value is not updated due to a task priority change while it is
fep 0:5ff20db10a96 278 being used for another purpose. The following bit definition is used to inform
fep 0:5ff20db10a96 279 the scheduler that the value should not be changed - in which case it is the
fep 0:5ff20db10a96 280 responsibility of whichever module is using the value to ensure it gets set back
fep 0:5ff20db10a96 281 to its original value when it is released. */
fep 0:5ff20db10a96 282 #if( configUSE_16_BIT_TICKS == 1 )
fep 0:5ff20db10a96 283 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
fep 0:5ff20db10a96 284 #else
fep 0:5ff20db10a96 285 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
fep 0:5ff20db10a96 286 #endif
fep 0:5ff20db10a96 287
fep 0:5ff20db10a96 288 /*
fep 0:5ff20db10a96 289 * Task control block. A task control block (TCB) is allocated for each task,
fep 0:5ff20db10a96 290 * and stores task state information, including a pointer to the task's context
fep 0:5ff20db10a96 291 * (the task's run time environment, including register values)
fep 0:5ff20db10a96 292 */
fep 0:5ff20db10a96 293 typedef struct tskTaskControlBlock
fep 0:5ff20db10a96 294 {
fep 0:5ff20db10a96 295 volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
fep 0:5ff20db10a96 296
fep 0:5ff20db10a96 297 #if ( portUSING_MPU_WRAPPERS == 1 )
fep 0:5ff20db10a96 298 xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
fep 0:5ff20db10a96 299 #endif
fep 0:5ff20db10a96 300
fep 0:5ff20db10a96 301 ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
fep 0:5ff20db10a96 302 ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
fep 0:5ff20db10a96 303 UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
fep 0:5ff20db10a96 304 StackType_t *pxStack; /*< Points to the start of the stack. */
fep 0:5ff20db10a96 305 char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
fep 0:5ff20db10a96 306
fep 0:5ff20db10a96 307 #if ( portSTACK_GROWTH > 0 )
fep 0:5ff20db10a96 308 StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
fep 0:5ff20db10a96 309 #endif
fep 0:5ff20db10a96 310
fep 0:5ff20db10a96 311 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
fep 0:5ff20db10a96 312 UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
fep 0:5ff20db10a96 313 #endif
fep 0:5ff20db10a96 314
fep 0:5ff20db10a96 315 #if ( configUSE_TRACE_FACILITY == 1 )
fep 0:5ff20db10a96 316 UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
fep 0:5ff20db10a96 317 UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
fep 0:5ff20db10a96 318 #endif
fep 0:5ff20db10a96 319
fep 0:5ff20db10a96 320 #if ( configUSE_MUTEXES == 1 )
fep 0:5ff20db10a96 321 UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
fep 0:5ff20db10a96 322 UBaseType_t uxMutexesHeld;
fep 0:5ff20db10a96 323 #endif
fep 0:5ff20db10a96 324
fep 0:5ff20db10a96 325 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
fep 0:5ff20db10a96 326 TaskHookFunction_t pxTaskTag;
fep 0:5ff20db10a96 327 #endif
fep 0:5ff20db10a96 328
fep 0:5ff20db10a96 329 #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
fep 0:5ff20db10a96 330 void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
fep 0:5ff20db10a96 331 #endif
fep 0:5ff20db10a96 332
fep 0:5ff20db10a96 333 #if( configGENERATE_RUN_TIME_STATS == 1 )
fep 0:5ff20db10a96 334 uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
fep 0:5ff20db10a96 335 #endif
fep 0:5ff20db10a96 336
fep 0:5ff20db10a96 337 #if ( configUSE_NEWLIB_REENTRANT == 1 )
fep 0:5ff20db10a96 338 /* Allocate a Newlib reent structure that is specific to this task.
fep 0:5ff20db10a96 339 Note Newlib support has been included by popular demand, but is not
fep 0:5ff20db10a96 340 used by the FreeRTOS maintainers themselves. FreeRTOS is not
fep 0:5ff20db10a96 341 responsible for resulting newlib operation. User must be familiar with
fep 0:5ff20db10a96 342 newlib and must provide system-wide implementations of the necessary
fep 0:5ff20db10a96 343 stubs. Be warned that (at the time of writing) the current newlib design
fep 0:5ff20db10a96 344 implements a system-wide malloc() that must be provided with locks. */
fep 0:5ff20db10a96 345 struct _reent xNewLib_reent;
fep 0:5ff20db10a96 346 #endif
fep 0:5ff20db10a96 347
fep 0:5ff20db10a96 348 #if( configUSE_TASK_NOTIFICATIONS == 1 )
fep 0:5ff20db10a96 349 volatile uint32_t ulNotifiedValue;
fep 0:5ff20db10a96 350 volatile uint8_t ucNotifyState;
fep 0:5ff20db10a96 351 #endif
fep 0:5ff20db10a96 352
fep 0:5ff20db10a96 353 /* See the comments above the definition of
fep 0:5ff20db10a96 354 tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
fep 0:5ff20db10a96 355 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
fep 0:5ff20db10a96 356 uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
fep 0:5ff20db10a96 357 #endif
fep 0:5ff20db10a96 358
fep 0:5ff20db10a96 359 #if( INCLUDE_xTaskAbortDelay == 1 )
fep 0:5ff20db10a96 360 uint8_t ucDelayAborted;
fep 0:5ff20db10a96 361 #endif
fep 0:5ff20db10a96 362
fep 0:5ff20db10a96 363 } tskTCB;
fep 0:5ff20db10a96 364
fep 0:5ff20db10a96 365 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
fep 0:5ff20db10a96 366 below to enable the use of older kernel aware debuggers. */
fep 0:5ff20db10a96 367 typedef tskTCB TCB_t;
fep 0:5ff20db10a96 368
fep 0:5ff20db10a96 369 /*lint -e956 A manual analysis and inspection has been used to determine which
fep 0:5ff20db10a96 370 static variables must be declared volatile. */
fep 0:5ff20db10a96 371
fep 0:5ff20db10a96 372 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
fep 0:5ff20db10a96 373
fep 0:5ff20db10a96 374 /* Lists for ready and blocked tasks. --------------------*/
fep 0:5ff20db10a96 375 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */
fep 0:5ff20db10a96 376 PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
fep 0:5ff20db10a96 377 PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
fep 0:5ff20db10a96 378 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
fep 0:5ff20db10a96 379 PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
fep 0:5ff20db10a96 380 PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */
fep 0:5ff20db10a96 381
fep 0:5ff20db10a96 382 #if( INCLUDE_vTaskDelete == 1 )
fep 0:5ff20db10a96 383
fep 0:5ff20db10a96 384 PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
fep 0:5ff20db10a96 385 PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
fep 0:5ff20db10a96 386
fep 0:5ff20db10a96 387 #endif
fep 0:5ff20db10a96 388
fep 0:5ff20db10a96 389 #if ( INCLUDE_vTaskSuspend == 1 )
fep 0:5ff20db10a96 390
fep 0:5ff20db10a96 391 PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
fep 0:5ff20db10a96 392
fep 0:5ff20db10a96 393 #endif
fep 0:5ff20db10a96 394
fep 0:5ff20db10a96 395 /* Other file private variables. --------------------------------*/
fep 0:5ff20db10a96 396 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
fep 0:5ff20db10a96 397 PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;
fep 0:5ff20db10a96 398 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
fep 0:5ff20db10a96 399 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
fep 0:5ff20db10a96 400 PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
fep 0:5ff20db10a96 401 PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
fep 0:5ff20db10a96 402 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
fep 0:5ff20db10a96 403 PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
fep 0:5ff20db10a96 404 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
fep 0:5ff20db10a96 405 PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */
fep 0:5ff20db10a96 406
fep 0:5ff20db10a96 407 /* Context switches are held pending while the scheduler is suspended. Also,
fep 0:5ff20db10a96 408 interrupts must not manipulate the xStateListItem of a TCB, or any of the
fep 0:5ff20db10a96 409 lists the xStateListItem can be referenced from, if the scheduler is suspended.
fep 0:5ff20db10a96 410 If an interrupt needs to unblock a task while the scheduler is suspended then it
fep 0:5ff20db10a96 411 moves the task's event list item into the xPendingReadyList, ready for the
fep 0:5ff20db10a96 412 kernel to move the task from the pending ready list into the real ready list
fep 0:5ff20db10a96 413 when the scheduler is unsuspended. The pending ready list itself can only be
fep 0:5ff20db10a96 414 accessed from a critical section. */
fep 0:5ff20db10a96 415 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
fep 0:5ff20db10a96 416
fep 0:5ff20db10a96 417 #if ( configGENERATE_RUN_TIME_STATS == 1 )
fep 0:5ff20db10a96 418
fep 0:5ff20db10a96 419 PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
fep 0:5ff20db10a96 420 PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
fep 0:5ff20db10a96 421
fep 0:5ff20db10a96 422 #endif
fep 0:5ff20db10a96 423
fep 0:5ff20db10a96 424 /*lint +e956 */
fep 0:5ff20db10a96 425
fep 0:5ff20db10a96 426 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 427
fep 0:5ff20db10a96 428 /* Callback function prototypes. --------------------------*/
fep 0:5ff20db10a96 429 #if( configCHECK_FOR_STACK_OVERFLOW > 0 )
fep 0:5ff20db10a96 430 extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
fep 0:5ff20db10a96 431 #endif
fep 0:5ff20db10a96 432
fep 0:5ff20db10a96 433 #if( configUSE_TICK_HOOK > 0 )
fep 0:5ff20db10a96 434 extern void vApplicationTickHook( void );
fep 0:5ff20db10a96 435 #endif
fep 0:5ff20db10a96 436
fep 0:5ff20db10a96 437 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
fep 0:5ff20db10a96 438 extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
fep 0:5ff20db10a96 439 #endif
fep 0:5ff20db10a96 440
fep 0:5ff20db10a96 441 /* File private functions. --------------------------------*/
fep 0:5ff20db10a96 442
fep 0:5ff20db10a96 443 /**
fep 0:5ff20db10a96 444 * Utility task that simply returns pdTRUE if the task referenced by xTask is
fep 0:5ff20db10a96 445 * currently in the Suspended state, or pdFALSE if the task referenced by xTask
fep 0:5ff20db10a96 446 * is in any other state.
fep 0:5ff20db10a96 447 */
fep 0:5ff20db10a96 448 #if ( INCLUDE_vTaskSuspend == 1 )
fep 0:5ff20db10a96 449 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
fep 0:5ff20db10a96 450 #endif /* INCLUDE_vTaskSuspend */
fep 0:5ff20db10a96 451
fep 0:5ff20db10a96 452 /*
fep 0:5ff20db10a96 453 * Utility to ready all the lists used by the scheduler. This is called
fep 0:5ff20db10a96 454 * automatically upon the creation of the first task.
fep 0:5ff20db10a96 455 */
fep 0:5ff20db10a96 456 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
fep 0:5ff20db10a96 457
fep 0:5ff20db10a96 458 /*
fep 0:5ff20db10a96 459 * The idle task, which as all tasks is implemented as a never ending loop.
fep 0:5ff20db10a96 460 * The idle task is automatically created and added to the ready lists upon
fep 0:5ff20db10a96 461 * creation of the first user task.
fep 0:5ff20db10a96 462 *
fep 0:5ff20db10a96 463 * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
fep 0:5ff20db10a96 464 * language extensions. The equivalent prototype for this function is:
fep 0:5ff20db10a96 465 *
fep 0:5ff20db10a96 466 * void prvIdleTask( void *pvParameters );
fep 0:5ff20db10a96 467 *
fep 0:5ff20db10a96 468 */
fep 0:5ff20db10a96 469 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
fep 0:5ff20db10a96 470
fep 0:5ff20db10a96 471 /*
fep 0:5ff20db10a96 472 * Utility to free all memory allocated by the scheduler to hold a TCB,
fep 0:5ff20db10a96 473 * including the stack pointed to by the TCB.
fep 0:5ff20db10a96 474 *
fep 0:5ff20db10a96 475 * This does not free memory allocated by the task itself (i.e. memory
fep 0:5ff20db10a96 476 * allocated by calls to pvPortMalloc from within the tasks application code).
fep 0:5ff20db10a96 477 */
fep 0:5ff20db10a96 478 #if ( INCLUDE_vTaskDelete == 1 )
fep 0:5ff20db10a96 479
fep 0:5ff20db10a96 480 static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION;
fep 0:5ff20db10a96 481
fep 0:5ff20db10a96 482 #endif
fep 0:5ff20db10a96 483
fep 0:5ff20db10a96 484 /*
fep 0:5ff20db10a96 485 * Used only by the idle task. This checks to see if anything has been placed
fep 0:5ff20db10a96 486 * in the list of tasks waiting to be deleted. If so the task is cleaned up
fep 0:5ff20db10a96 487 * and its TCB deleted.
fep 0:5ff20db10a96 488 */
fep 0:5ff20db10a96 489 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
fep 0:5ff20db10a96 490
fep 0:5ff20db10a96 491 /*
fep 0:5ff20db10a96 492 * The currently executing task is entering the Blocked state. Add the task to
fep 0:5ff20db10a96 493 * either the current or the overflow delayed task list.
fep 0:5ff20db10a96 494 */
fep 0:5ff20db10a96 495 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
fep 0:5ff20db10a96 496
fep 0:5ff20db10a96 497 /*
fep 0:5ff20db10a96 498 * Fills an TaskStatus_t structure with information on each task that is
fep 0:5ff20db10a96 499 * referenced from the pxList list (which may be a ready list, a delayed list,
fep 0:5ff20db10a96 500 * a suspended list, etc.).
fep 0:5ff20db10a96 501 *
fep 0:5ff20db10a96 502 * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
fep 0:5ff20db10a96 503 * NORMAL APPLICATION CODE.
fep 0:5ff20db10a96 504 */
fep 0:5ff20db10a96 505 #if ( configUSE_TRACE_FACILITY == 1 )
fep 0:5ff20db10a96 506
fep 0:5ff20db10a96 507 static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
fep 0:5ff20db10a96 508
fep 0:5ff20db10a96 509 #endif
fep 0:5ff20db10a96 510
fep 0:5ff20db10a96 511 /*
fep 0:5ff20db10a96 512 * Searches pxList for a task with name pcNameToQuery - returning a handle to
fep 0:5ff20db10a96 513 * the task if it is found, or NULL if the task is not found.
fep 0:5ff20db10a96 514 */
fep 0:5ff20db10a96 515 #if ( INCLUDE_xTaskGetHandle == 1 )
fep 0:5ff20db10a96 516
fep 0:5ff20db10a96 517 static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;
fep 0:5ff20db10a96 518
fep 0:5ff20db10a96 519 #endif
fep 0:5ff20db10a96 520
fep 0:5ff20db10a96 521 /*
fep 0:5ff20db10a96 522 * When a task is created, the stack of the task is filled with a known value.
fep 0:5ff20db10a96 523 * This function determines the 'high water mark' of the task stack by
fep 0:5ff20db10a96 524 * determining how much of the stack remains at the original preset value.
fep 0:5ff20db10a96 525 */
fep 0:5ff20db10a96 526 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
fep 0:5ff20db10a96 527
fep 0:5ff20db10a96 528 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
fep 0:5ff20db10a96 529
fep 0:5ff20db10a96 530 #endif
fep 0:5ff20db10a96 531
fep 0:5ff20db10a96 532 /*
fep 0:5ff20db10a96 533 * Return the amount of time, in ticks, that will pass before the kernel will
fep 0:5ff20db10a96 534 * next move a task from the Blocked state to the Running state.
fep 0:5ff20db10a96 535 *
fep 0:5ff20db10a96 536 * This conditional compilation should use inequality to 0, not equality to 1.
fep 0:5ff20db10a96 537 * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
fep 0:5ff20db10a96 538 * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
fep 0:5ff20db10a96 539 * set to a value other than 1.
fep 0:5ff20db10a96 540 */
fep 0:5ff20db10a96 541 #if ( configUSE_TICKLESS_IDLE != 0 )
fep 0:5ff20db10a96 542
fep 0:5ff20db10a96 543 static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
fep 0:5ff20db10a96 544
fep 0:5ff20db10a96 545 #endif
fep 0:5ff20db10a96 546
fep 0:5ff20db10a96 547 /*
fep 0:5ff20db10a96 548 * Set xNextTaskUnblockTime to the time at which the next Blocked state task
fep 0:5ff20db10a96 549 * will exit the Blocked state.
fep 0:5ff20db10a96 550 */
fep 0:5ff20db10a96 551 static void prvResetNextTaskUnblockTime( void );
fep 0:5ff20db10a96 552
fep 0:5ff20db10a96 553 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
fep 0:5ff20db10a96 554
fep 0:5ff20db10a96 555 /*
fep 0:5ff20db10a96 556 * Helper function used to pad task names with spaces when printing out
fep 0:5ff20db10a96 557 * human readable tables of task information.
fep 0:5ff20db10a96 558 */
fep 0:5ff20db10a96 559 static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) PRIVILEGED_FUNCTION;
fep 0:5ff20db10a96 560
fep 0:5ff20db10a96 561 #endif
fep 0:5ff20db10a96 562
fep 0:5ff20db10a96 563 /*
fep 0:5ff20db10a96 564 * Called after a Task_t structure has been allocated either statically or
fep 0:5ff20db10a96 565 * dynamically to fill in the structure's members.
fep 0:5ff20db10a96 566 */
fep 0:5ff20db10a96 567 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
fep 0:5ff20db10a96 568 const char * const pcName,
fep 0:5ff20db10a96 569 const uint32_t ulStackDepth,
fep 0:5ff20db10a96 570 void * const pvParameters,
fep 0:5ff20db10a96 571 UBaseType_t uxPriority,
fep 0:5ff20db10a96 572 TaskHandle_t * const pxCreatedTask,
fep 0:5ff20db10a96 573 TCB_t *pxNewTCB,
fep 0:5ff20db10a96 574 const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
fep 0:5ff20db10a96 575
fep 0:5ff20db10a96 576 /*
fep 0:5ff20db10a96 577 * Called after a new task has been created and initialised to place the task
fep 0:5ff20db10a96 578 * under the control of the scheduler.
fep 0:5ff20db10a96 579 */
fep 0:5ff20db10a96 580 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
fep 0:5ff20db10a96 581
fep 0:5ff20db10a96 582 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 583
fep 0:5ff20db10a96 584 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
fep 0:5ff20db10a96 585
fep 0:5ff20db10a96 586 TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
fep 0:5ff20db10a96 587 const char * const pcName,
fep 0:5ff20db10a96 588 const uint32_t ulStackDepth,
fep 0:5ff20db10a96 589 void * const pvParameters,
fep 0:5ff20db10a96 590 UBaseType_t uxPriority,
fep 0:5ff20db10a96 591 StackType_t * const puxStackBuffer,
fep 0:5ff20db10a96 592 StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
fep 0:5ff20db10a96 593 {
fep 0:5ff20db10a96 594 TCB_t *pxNewTCB;
fep 0:5ff20db10a96 595 TaskHandle_t xReturn;
fep 0:5ff20db10a96 596
fep 0:5ff20db10a96 597 configASSERT( puxStackBuffer != NULL );
fep 0:5ff20db10a96 598 configASSERT( pxTaskBuffer != NULL );
fep 0:5ff20db10a96 599
fep 0:5ff20db10a96 600 if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
fep 0:5ff20db10a96 601 {
fep 0:5ff20db10a96 602 /* The memory used for the task's TCB and stack are passed into this
fep 0:5ff20db10a96 603 function - use them. */
fep 0:5ff20db10a96 604 pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
fep 0:5ff20db10a96 605 pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
fep 0:5ff20db10a96 606
fep 0:5ff20db10a96 607 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
fep 0:5ff20db10a96 608 {
fep 0:5ff20db10a96 609 /* Tasks can be created statically or dynamically, so note this
fep 0:5ff20db10a96 610 task was created statically in case the task is later deleted. */
fep 0:5ff20db10a96 611 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
fep 0:5ff20db10a96 612 }
fep 0:5ff20db10a96 613 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
fep 0:5ff20db10a96 614
fep 0:5ff20db10a96 615 prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
fep 0:5ff20db10a96 616 prvAddNewTaskToReadyList( pxNewTCB );
fep 0:5ff20db10a96 617 }
fep 0:5ff20db10a96 618 else
fep 0:5ff20db10a96 619 {
fep 0:5ff20db10a96 620 xReturn = NULL;
fep 0:5ff20db10a96 621 }
fep 0:5ff20db10a96 622
fep 0:5ff20db10a96 623 return xReturn;
fep 0:5ff20db10a96 624 }
fep 0:5ff20db10a96 625
fep 0:5ff20db10a96 626 #endif /* SUPPORT_STATIC_ALLOCATION */
fep 0:5ff20db10a96 627 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 628
fep 0:5ff20db10a96 629 #if( portUSING_MPU_WRAPPERS == 1 )
fep 0:5ff20db10a96 630
fep 0:5ff20db10a96 631 BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
fep 0:5ff20db10a96 632 {
fep 0:5ff20db10a96 633 TCB_t *pxNewTCB;
fep 0:5ff20db10a96 634 BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
fep 0:5ff20db10a96 635
fep 0:5ff20db10a96 636 configASSERT( pxTaskDefinition->puxStackBuffer );
fep 0:5ff20db10a96 637
fep 0:5ff20db10a96 638 if( pxTaskDefinition->puxStackBuffer != NULL )
fep 0:5ff20db10a96 639 {
fep 0:5ff20db10a96 640 /* Allocate space for the TCB. Where the memory comes from depends
fep 0:5ff20db10a96 641 on the implementation of the port malloc function and whether or
fep 0:5ff20db10a96 642 not static allocation is being used. */
fep 0:5ff20db10a96 643 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
fep 0:5ff20db10a96 644
fep 0:5ff20db10a96 645 if( pxNewTCB != NULL )
fep 0:5ff20db10a96 646 {
fep 0:5ff20db10a96 647 /* Store the stack location in the TCB. */
fep 0:5ff20db10a96 648 pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
fep 0:5ff20db10a96 649
fep 0:5ff20db10a96 650 /* Tasks can be created statically or dynamically, so note
fep 0:5ff20db10a96 651 this task had a statically allocated stack in case it is
fep 0:5ff20db10a96 652 later deleted. The TCB was allocated dynamically. */
fep 0:5ff20db10a96 653 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;
fep 0:5ff20db10a96 654
fep 0:5ff20db10a96 655 prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
fep 0:5ff20db10a96 656 pxTaskDefinition->pcName,
fep 0:5ff20db10a96 657 ( uint32_t ) pxTaskDefinition->usStackDepth,
fep 0:5ff20db10a96 658 pxTaskDefinition->pvParameters,
fep 0:5ff20db10a96 659 pxTaskDefinition->uxPriority,
fep 0:5ff20db10a96 660 pxCreatedTask, pxNewTCB,
fep 0:5ff20db10a96 661 pxTaskDefinition->xRegions );
fep 0:5ff20db10a96 662
fep 0:5ff20db10a96 663 prvAddNewTaskToReadyList( pxNewTCB );
fep 0:5ff20db10a96 664 xReturn = pdPASS;
fep 0:5ff20db10a96 665 }
fep 0:5ff20db10a96 666 }
fep 0:5ff20db10a96 667
fep 0:5ff20db10a96 668 return xReturn;
fep 0:5ff20db10a96 669 }
fep 0:5ff20db10a96 670
fep 0:5ff20db10a96 671 #endif /* portUSING_MPU_WRAPPERS */
fep 0:5ff20db10a96 672 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 673
fep 0:5ff20db10a96 674 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
fep 0:5ff20db10a96 675
fep 0:5ff20db10a96 676 BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
fep 0:5ff20db10a96 677 const char * const pcName,
fep 0:5ff20db10a96 678 const uint16_t usStackDepth,
fep 0:5ff20db10a96 679 void * const pvParameters,
fep 0:5ff20db10a96 680 UBaseType_t uxPriority,
fep 0:5ff20db10a96 681 TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
fep 0:5ff20db10a96 682 {
fep 0:5ff20db10a96 683 TCB_t *pxNewTCB;
fep 0:5ff20db10a96 684 BaseType_t xReturn;
fep 0:5ff20db10a96 685
fep 0:5ff20db10a96 686 /* If the stack grows down then allocate the stack then the TCB so the stack
fep 0:5ff20db10a96 687 does not grow into the TCB. Likewise if the stack grows up then allocate
fep 0:5ff20db10a96 688 the TCB then the stack. */
fep 0:5ff20db10a96 689 #if( portSTACK_GROWTH > 0 )
fep 0:5ff20db10a96 690 {
fep 0:5ff20db10a96 691 /* Allocate space for the TCB. Where the memory comes from depends on
fep 0:5ff20db10a96 692 the implementation of the port malloc function and whether or not static
fep 0:5ff20db10a96 693 allocation is being used. */
fep 0:5ff20db10a96 694 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
fep 0:5ff20db10a96 695
fep 0:5ff20db10a96 696 if( pxNewTCB != NULL )
fep 0:5ff20db10a96 697 {
fep 0:5ff20db10a96 698 /* Allocate space for the stack used by the task being created.
fep 0:5ff20db10a96 699 The base of the stack memory stored in the TCB so the task can
fep 0:5ff20db10a96 700 be deleted later if required. */
fep 0:5ff20db10a96 701 pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
fep 0:5ff20db10a96 702
fep 0:5ff20db10a96 703 if( pxNewTCB->pxStack == NULL )
fep 0:5ff20db10a96 704 {
fep 0:5ff20db10a96 705 /* Could not allocate the stack. Delete the allocated TCB. */
fep 0:5ff20db10a96 706 vPortFree( pxNewTCB );
fep 0:5ff20db10a96 707 pxNewTCB = NULL;
fep 0:5ff20db10a96 708 }
fep 0:5ff20db10a96 709 }
fep 0:5ff20db10a96 710 }
fep 0:5ff20db10a96 711 #else /* portSTACK_GROWTH */
fep 0:5ff20db10a96 712 {
fep 0:5ff20db10a96 713 StackType_t *pxStack;
fep 0:5ff20db10a96 714
fep 0:5ff20db10a96 715 /* Allocate space for the stack used by the task being created. */
fep 0:5ff20db10a96 716 pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
fep 0:5ff20db10a96 717
fep 0:5ff20db10a96 718 if( pxStack != NULL )
fep 0:5ff20db10a96 719 {
fep 0:5ff20db10a96 720 /* Allocate space for the TCB. */
fep 0:5ff20db10a96 721 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */
fep 0:5ff20db10a96 722
fep 0:5ff20db10a96 723 if( pxNewTCB != NULL )
fep 0:5ff20db10a96 724 {
fep 0:5ff20db10a96 725 /* Store the stack location in the TCB. */
fep 0:5ff20db10a96 726 pxNewTCB->pxStack = pxStack;
fep 0:5ff20db10a96 727 }
fep 0:5ff20db10a96 728 else
fep 0:5ff20db10a96 729 {
fep 0:5ff20db10a96 730 /* The stack cannot be used as the TCB was not created. Free
fep 0:5ff20db10a96 731 it again. */
fep 0:5ff20db10a96 732 vPortFree( pxStack );
fep 0:5ff20db10a96 733 }
fep 0:5ff20db10a96 734 }
fep 0:5ff20db10a96 735 else
fep 0:5ff20db10a96 736 {
fep 0:5ff20db10a96 737 pxNewTCB = NULL;
fep 0:5ff20db10a96 738 }
fep 0:5ff20db10a96 739 }
fep 0:5ff20db10a96 740 #endif /* portSTACK_GROWTH */
fep 0:5ff20db10a96 741
fep 0:5ff20db10a96 742 if( pxNewTCB != NULL )
fep 0:5ff20db10a96 743 {
fep 0:5ff20db10a96 744 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
fep 0:5ff20db10a96 745 {
fep 0:5ff20db10a96 746 /* Tasks can be created statically or dynamically, so note this
fep 0:5ff20db10a96 747 task was created dynamically in case it is later deleted. */
fep 0:5ff20db10a96 748 pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
fep 0:5ff20db10a96 749 }
fep 0:5ff20db10a96 750 #endif /* configSUPPORT_STATIC_ALLOCATION */
fep 0:5ff20db10a96 751
fep 0:5ff20db10a96 752 prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
fep 0:5ff20db10a96 753 prvAddNewTaskToReadyList( pxNewTCB );
fep 0:5ff20db10a96 754 xReturn = pdPASS;
fep 0:5ff20db10a96 755 }
fep 0:5ff20db10a96 756 else
fep 0:5ff20db10a96 757 {
fep 0:5ff20db10a96 758 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
fep 0:5ff20db10a96 759 }
fep 0:5ff20db10a96 760
fep 0:5ff20db10a96 761 return xReturn;
fep 0:5ff20db10a96 762 }
fep 0:5ff20db10a96 763
fep 0:5ff20db10a96 764 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
fep 0:5ff20db10a96 765 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 766
fep 0:5ff20db10a96 767 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
fep 0:5ff20db10a96 768 const char * const pcName,
fep 0:5ff20db10a96 769 const uint32_t ulStackDepth,
fep 0:5ff20db10a96 770 void * const pvParameters,
fep 0:5ff20db10a96 771 UBaseType_t uxPriority,
fep 0:5ff20db10a96 772 TaskHandle_t * const pxCreatedTask,
fep 0:5ff20db10a96 773 TCB_t *pxNewTCB,
fep 0:5ff20db10a96 774 const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
fep 0:5ff20db10a96 775 {
fep 0:5ff20db10a96 776 StackType_t *pxTopOfStack;
fep 0:5ff20db10a96 777 UBaseType_t x;
fep 0:5ff20db10a96 778
fep 0:5ff20db10a96 779 #if( portUSING_MPU_WRAPPERS == 1 )
fep 0:5ff20db10a96 780 /* Should the task be created in privileged mode? */
fep 0:5ff20db10a96 781 BaseType_t xRunPrivileged;
fep 0:5ff20db10a96 782 if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
fep 0:5ff20db10a96 783 {
fep 0:5ff20db10a96 784 xRunPrivileged = pdTRUE;
fep 0:5ff20db10a96 785 }
fep 0:5ff20db10a96 786 else
fep 0:5ff20db10a96 787 {
fep 0:5ff20db10a96 788 xRunPrivileged = pdFALSE;
fep 0:5ff20db10a96 789 }
fep 0:5ff20db10a96 790 uxPriority &= ~portPRIVILEGE_BIT;
fep 0:5ff20db10a96 791 #endif /* portUSING_MPU_WRAPPERS == 1 */
fep 0:5ff20db10a96 792
fep 0:5ff20db10a96 793 /* Avoid dependency on memset() if it is not required. */
fep 0:5ff20db10a96 794 #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
fep 0:5ff20db10a96 795 {
fep 0:5ff20db10a96 796 /* Fill the stack with a known value to assist debugging. */
fep 0:5ff20db10a96 797 ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
fep 0:5ff20db10a96 798 }
fep 0:5ff20db10a96 799 #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
fep 0:5ff20db10a96 800
fep 0:5ff20db10a96 801 /* Calculate the top of stack address. This depends on whether the stack
fep 0:5ff20db10a96 802 grows from high memory to low (as per the 80x86) or vice versa.
fep 0:5ff20db10a96 803 portSTACK_GROWTH is used to make the result positive or negative as required
fep 0:5ff20db10a96 804 by the port. */
fep 0:5ff20db10a96 805 #if( portSTACK_GROWTH < 0 )
fep 0:5ff20db10a96 806 {
fep 0:5ff20db10a96 807 pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
fep 0:5ff20db10a96 808 pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */
fep 0:5ff20db10a96 809
fep 0:5ff20db10a96 810 /* Check the alignment of the calculated top of stack is correct. */
fep 0:5ff20db10a96 811 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
fep 0:5ff20db10a96 812 }
fep 0:5ff20db10a96 813 #else /* portSTACK_GROWTH */
fep 0:5ff20db10a96 814 {
fep 0:5ff20db10a96 815 pxTopOfStack = pxNewTCB->pxStack;
fep 0:5ff20db10a96 816
fep 0:5ff20db10a96 817 /* Check the alignment of the stack buffer is correct. */
fep 0:5ff20db10a96 818 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
fep 0:5ff20db10a96 819
fep 0:5ff20db10a96 820 /* The other extreme of the stack space is required if stack checking is
fep 0:5ff20db10a96 821 performed. */
fep 0:5ff20db10a96 822 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
fep 0:5ff20db10a96 823 }
fep 0:5ff20db10a96 824 #endif /* portSTACK_GROWTH */
fep 0:5ff20db10a96 825
fep 0:5ff20db10a96 826 /* Store the task name in the TCB. */
fep 0:5ff20db10a96 827 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
fep 0:5ff20db10a96 828 {
fep 0:5ff20db10a96 829 pxNewTCB->pcTaskName[ x ] = pcName[ x ];
fep 0:5ff20db10a96 830
fep 0:5ff20db10a96 831 /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
fep 0:5ff20db10a96 832 configMAX_TASK_NAME_LEN characters just in case the memory after the
fep 0:5ff20db10a96 833 string is not accessible (extremely unlikely). */
fep 0:5ff20db10a96 834 if( pcName[ x ] == 0x00 )
fep 0:5ff20db10a96 835 {
fep 0:5ff20db10a96 836 break;
fep 0:5ff20db10a96 837 }
fep 0:5ff20db10a96 838 else
fep 0:5ff20db10a96 839 {
fep 0:5ff20db10a96 840 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 841 }
fep 0:5ff20db10a96 842 }
fep 0:5ff20db10a96 843
fep 0:5ff20db10a96 844 /* Ensure the name string is terminated in the case that the string length
fep 0:5ff20db10a96 845 was greater or equal to configMAX_TASK_NAME_LEN. */
fep 0:5ff20db10a96 846 pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
fep 0:5ff20db10a96 847
fep 0:5ff20db10a96 848 /* This is used as an array index so must ensure it's not too large. First
fep 0:5ff20db10a96 849 remove the privilege bit if one is present. */
fep 0:5ff20db10a96 850 if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
fep 0:5ff20db10a96 851 {
fep 0:5ff20db10a96 852 uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
fep 0:5ff20db10a96 853 }
fep 0:5ff20db10a96 854 else
fep 0:5ff20db10a96 855 {
fep 0:5ff20db10a96 856 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 857 }
fep 0:5ff20db10a96 858
fep 0:5ff20db10a96 859 pxNewTCB->uxPriority = uxPriority;
fep 0:5ff20db10a96 860 #if ( configUSE_MUTEXES == 1 )
fep 0:5ff20db10a96 861 {
fep 0:5ff20db10a96 862 pxNewTCB->uxBasePriority = uxPriority;
fep 0:5ff20db10a96 863 pxNewTCB->uxMutexesHeld = 0;
fep 0:5ff20db10a96 864 }
fep 0:5ff20db10a96 865 #endif /* configUSE_MUTEXES */
fep 0:5ff20db10a96 866
fep 0:5ff20db10a96 867 vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
fep 0:5ff20db10a96 868 vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
fep 0:5ff20db10a96 869
fep 0:5ff20db10a96 870 /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get
fep 0:5ff20db10a96 871 back to the containing TCB from a generic item in a list. */
fep 0:5ff20db10a96 872 listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
fep 0:5ff20db10a96 873
fep 0:5ff20db10a96 874 /* Event lists are always in priority order. */
fep 0:5ff20db10a96 875 listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
fep 0:5ff20db10a96 876 listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
fep 0:5ff20db10a96 877
fep 0:5ff20db10a96 878 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
fep 0:5ff20db10a96 879 {
fep 0:5ff20db10a96 880 pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
fep 0:5ff20db10a96 881 }
fep 0:5ff20db10a96 882 #endif /* portCRITICAL_NESTING_IN_TCB */
fep 0:5ff20db10a96 883
fep 0:5ff20db10a96 884 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
fep 0:5ff20db10a96 885 {
fep 0:5ff20db10a96 886 pxNewTCB->pxTaskTag = NULL;
fep 0:5ff20db10a96 887 }
fep 0:5ff20db10a96 888 #endif /* configUSE_APPLICATION_TASK_TAG */
fep 0:5ff20db10a96 889
fep 0:5ff20db10a96 890 #if ( configGENERATE_RUN_TIME_STATS == 1 )
fep 0:5ff20db10a96 891 {
fep 0:5ff20db10a96 892 pxNewTCB->ulRunTimeCounter = 0UL;
fep 0:5ff20db10a96 893 }
fep 0:5ff20db10a96 894 #endif /* configGENERATE_RUN_TIME_STATS */
fep 0:5ff20db10a96 895
fep 0:5ff20db10a96 896 #if ( portUSING_MPU_WRAPPERS == 1 )
fep 0:5ff20db10a96 897 {
fep 0:5ff20db10a96 898 vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );
fep 0:5ff20db10a96 899 }
fep 0:5ff20db10a96 900 #else
fep 0:5ff20db10a96 901 {
fep 0:5ff20db10a96 902 /* Avoid compiler warning about unreferenced parameter. */
fep 0:5ff20db10a96 903 ( void ) xRegions;
fep 0:5ff20db10a96 904 }
fep 0:5ff20db10a96 905 #endif
fep 0:5ff20db10a96 906
fep 0:5ff20db10a96 907 #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
fep 0:5ff20db10a96 908 {
fep 0:5ff20db10a96 909 for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
fep 0:5ff20db10a96 910 {
fep 0:5ff20db10a96 911 pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL;
fep 0:5ff20db10a96 912 }
fep 0:5ff20db10a96 913 }
fep 0:5ff20db10a96 914 #endif
fep 0:5ff20db10a96 915
fep 0:5ff20db10a96 916 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
fep 0:5ff20db10a96 917 {
fep 0:5ff20db10a96 918 pxNewTCB->ulNotifiedValue = 0;
fep 0:5ff20db10a96 919 pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
fep 0:5ff20db10a96 920 }
fep 0:5ff20db10a96 921 #endif
fep 0:5ff20db10a96 922
fep 0:5ff20db10a96 923 #if ( configUSE_NEWLIB_REENTRANT == 1 )
fep 0:5ff20db10a96 924 {
fep 0:5ff20db10a96 925 /* Initialise this task's Newlib reent structure. */
fep 0:5ff20db10a96 926 _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) );
fep 0:5ff20db10a96 927 }
fep 0:5ff20db10a96 928 #endif
fep 0:5ff20db10a96 929
fep 0:5ff20db10a96 930 #if( INCLUDE_xTaskAbortDelay == 1 )
fep 0:5ff20db10a96 931 {
fep 0:5ff20db10a96 932 pxNewTCB->ucDelayAborted = pdFALSE;
fep 0:5ff20db10a96 933 }
fep 0:5ff20db10a96 934 #endif
fep 0:5ff20db10a96 935
fep 0:5ff20db10a96 936 /* Initialize the TCB stack to look as if the task was already running,
fep 0:5ff20db10a96 937 but had been interrupted by the scheduler. The return address is set
fep 0:5ff20db10a96 938 to the start of the task function. Once the stack has been initialised
fep 0:5ff20db10a96 939 the top of stack variable is updated. */
fep 0:5ff20db10a96 940 #if( portUSING_MPU_WRAPPERS == 1 )
fep 0:5ff20db10a96 941 {
fep 0:5ff20db10a96 942 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
fep 0:5ff20db10a96 943 }
fep 0:5ff20db10a96 944 #else /* portUSING_MPU_WRAPPERS */
fep 0:5ff20db10a96 945 {
fep 0:5ff20db10a96 946 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
fep 0:5ff20db10a96 947 }
fep 0:5ff20db10a96 948 #endif /* portUSING_MPU_WRAPPERS */
fep 0:5ff20db10a96 949
fep 0:5ff20db10a96 950 if( ( void * ) pxCreatedTask != NULL )
fep 0:5ff20db10a96 951 {
fep 0:5ff20db10a96 952 /* Pass the handle out in an anonymous way. The handle can be used to
fep 0:5ff20db10a96 953 change the created task's priority, delete the created task, etc.*/
fep 0:5ff20db10a96 954 *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
fep 0:5ff20db10a96 955 }
fep 0:5ff20db10a96 956 else
fep 0:5ff20db10a96 957 {
fep 0:5ff20db10a96 958 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 959 }
fep 0:5ff20db10a96 960 }
fep 0:5ff20db10a96 961 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 962
fep 0:5ff20db10a96 963 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
fep 0:5ff20db10a96 964 {
fep 0:5ff20db10a96 965 /* Ensure interrupts don't access the task lists while the lists are being
fep 0:5ff20db10a96 966 updated. */
fep 0:5ff20db10a96 967 taskENTER_CRITICAL();
fep 0:5ff20db10a96 968 {
fep 0:5ff20db10a96 969 uxCurrentNumberOfTasks++;
fep 0:5ff20db10a96 970 if( pxCurrentTCB == NULL )
fep 0:5ff20db10a96 971 {
fep 0:5ff20db10a96 972 /* There are no other tasks, or all the other tasks are in
fep 0:5ff20db10a96 973 the suspended state - make this the current task. */
fep 0:5ff20db10a96 974 pxCurrentTCB = pxNewTCB;
fep 0:5ff20db10a96 975
fep 0:5ff20db10a96 976 if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
fep 0:5ff20db10a96 977 {
fep 0:5ff20db10a96 978 /* This is the first task to be created so do the preliminary
fep 0:5ff20db10a96 979 initialisation required. We will not recover if this call
fep 0:5ff20db10a96 980 fails, but we will report the failure. */
fep 0:5ff20db10a96 981 prvInitialiseTaskLists();
fep 0:5ff20db10a96 982 }
fep 0:5ff20db10a96 983 else
fep 0:5ff20db10a96 984 {
fep 0:5ff20db10a96 985 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 986 }
fep 0:5ff20db10a96 987 }
fep 0:5ff20db10a96 988 else
fep 0:5ff20db10a96 989 {
fep 0:5ff20db10a96 990 /* If the scheduler is not already running, make this task the
fep 0:5ff20db10a96 991 current task if it is the highest priority task to be created
fep 0:5ff20db10a96 992 so far. */
fep 0:5ff20db10a96 993 if( xSchedulerRunning == pdFALSE )
fep 0:5ff20db10a96 994 {
fep 0:5ff20db10a96 995 if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
fep 0:5ff20db10a96 996 {
fep 0:5ff20db10a96 997 pxCurrentTCB = pxNewTCB;
fep 0:5ff20db10a96 998 }
fep 0:5ff20db10a96 999 else
fep 0:5ff20db10a96 1000 {
fep 0:5ff20db10a96 1001 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1002 }
fep 0:5ff20db10a96 1003 }
fep 0:5ff20db10a96 1004 else
fep 0:5ff20db10a96 1005 {
fep 0:5ff20db10a96 1006 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1007 }
fep 0:5ff20db10a96 1008 }
fep 0:5ff20db10a96 1009
fep 0:5ff20db10a96 1010 uxTaskNumber++;
fep 0:5ff20db10a96 1011
fep 0:5ff20db10a96 1012 #if ( configUSE_TRACE_FACILITY == 1 )
fep 0:5ff20db10a96 1013 {
fep 0:5ff20db10a96 1014 /* Add a counter into the TCB for tracing only. */
fep 0:5ff20db10a96 1015 pxNewTCB->uxTCBNumber = uxTaskNumber;
fep 0:5ff20db10a96 1016 }
fep 0:5ff20db10a96 1017 #endif /* configUSE_TRACE_FACILITY */
fep 0:5ff20db10a96 1018 traceTASK_CREATE( pxNewTCB );
fep 0:5ff20db10a96 1019
fep 0:5ff20db10a96 1020 prvAddTaskToReadyList( pxNewTCB );
fep 0:5ff20db10a96 1021
fep 0:5ff20db10a96 1022 portSETUP_TCB( pxNewTCB );
fep 0:5ff20db10a96 1023 }
fep 0:5ff20db10a96 1024 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 1025
fep 0:5ff20db10a96 1026 if( xSchedulerRunning != pdFALSE )
fep 0:5ff20db10a96 1027 {
fep 0:5ff20db10a96 1028 /* If the created task is of a higher priority than the current task
fep 0:5ff20db10a96 1029 then it should run now. */
fep 0:5ff20db10a96 1030 if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
fep 0:5ff20db10a96 1031 {
fep 0:5ff20db10a96 1032 taskYIELD_IF_USING_PREEMPTION();
fep 0:5ff20db10a96 1033 }
fep 0:5ff20db10a96 1034 else
fep 0:5ff20db10a96 1035 {
fep 0:5ff20db10a96 1036 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1037 }
fep 0:5ff20db10a96 1038 }
fep 0:5ff20db10a96 1039 else
fep 0:5ff20db10a96 1040 {
fep 0:5ff20db10a96 1041 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1042 }
fep 0:5ff20db10a96 1043 }
fep 0:5ff20db10a96 1044 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1045
fep 0:5ff20db10a96 1046 #if ( INCLUDE_vTaskDelete == 1 )
fep 0:5ff20db10a96 1047
fep 0:5ff20db10a96 1048 void vTaskDelete( TaskHandle_t xTaskToDelete )
fep 0:5ff20db10a96 1049 {
fep 0:5ff20db10a96 1050 TCB_t *pxTCB;
fep 0:5ff20db10a96 1051
fep 0:5ff20db10a96 1052 taskENTER_CRITICAL();
fep 0:5ff20db10a96 1053 {
fep 0:5ff20db10a96 1054 /* If null is passed in here then it is the calling task that is
fep 0:5ff20db10a96 1055 being deleted. */
fep 0:5ff20db10a96 1056 pxTCB = prvGetTCBFromHandle( xTaskToDelete );
fep 0:5ff20db10a96 1057
fep 0:5ff20db10a96 1058 /* Remove task from the ready list. */
fep 0:5ff20db10a96 1059 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
fep 0:5ff20db10a96 1060 {
fep 0:5ff20db10a96 1061 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
fep 0:5ff20db10a96 1062 }
fep 0:5ff20db10a96 1063 else
fep 0:5ff20db10a96 1064 {
fep 0:5ff20db10a96 1065 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1066 }
fep 0:5ff20db10a96 1067
fep 0:5ff20db10a96 1068 /* Is the task waiting on an event also? */
fep 0:5ff20db10a96 1069 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
fep 0:5ff20db10a96 1070 {
fep 0:5ff20db10a96 1071 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
fep 0:5ff20db10a96 1072 }
fep 0:5ff20db10a96 1073 else
fep 0:5ff20db10a96 1074 {
fep 0:5ff20db10a96 1075 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1076 }
fep 0:5ff20db10a96 1077
fep 0:5ff20db10a96 1078 /* Increment the uxTaskNumber also so kernel aware debuggers can
fep 0:5ff20db10a96 1079 detect that the task lists need re-generating. This is done before
fep 0:5ff20db10a96 1080 portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
fep 0:5ff20db10a96 1081 not return. */
fep 0:5ff20db10a96 1082 uxTaskNumber++;
fep 0:5ff20db10a96 1083
fep 0:5ff20db10a96 1084 if( pxTCB == pxCurrentTCB )
fep 0:5ff20db10a96 1085 {
fep 0:5ff20db10a96 1086 /* A task is deleting itself. This cannot complete within the
fep 0:5ff20db10a96 1087 task itself, as a context switch to another task is required.
fep 0:5ff20db10a96 1088 Place the task in the termination list. The idle task will
fep 0:5ff20db10a96 1089 check the termination list and free up any memory allocated by
fep 0:5ff20db10a96 1090 the scheduler for the TCB and stack of the deleted task. */
fep 0:5ff20db10a96 1091 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 1092
fep 0:5ff20db10a96 1093 /* Increment the ucTasksDeleted variable so the idle task knows
fep 0:5ff20db10a96 1094 there is a task that has been deleted and that it should therefore
fep 0:5ff20db10a96 1095 check the xTasksWaitingTermination list. */
fep 0:5ff20db10a96 1096 ++uxDeletedTasksWaitingCleanUp;
fep 0:5ff20db10a96 1097
fep 0:5ff20db10a96 1098 /* The pre-delete hook is primarily for the Windows simulator,
fep 0:5ff20db10a96 1099 in which Windows specific clean up operations are performed,
fep 0:5ff20db10a96 1100 after which it is not possible to yield away from this task -
fep 0:5ff20db10a96 1101 hence xYieldPending is used to latch that a context switch is
fep 0:5ff20db10a96 1102 required. */
fep 0:5ff20db10a96 1103 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
fep 0:5ff20db10a96 1104 }
fep 0:5ff20db10a96 1105 else
fep 0:5ff20db10a96 1106 {
fep 0:5ff20db10a96 1107 --uxCurrentNumberOfTasks;
fep 0:5ff20db10a96 1108 prvDeleteTCB( pxTCB );
fep 0:5ff20db10a96 1109
fep 0:5ff20db10a96 1110 /* Reset the next expected unblock time in case it referred to
fep 0:5ff20db10a96 1111 the task that has just been deleted. */
fep 0:5ff20db10a96 1112 prvResetNextTaskUnblockTime();
fep 0:5ff20db10a96 1113 }
fep 0:5ff20db10a96 1114
fep 0:5ff20db10a96 1115 traceTASK_DELETE( pxTCB );
fep 0:5ff20db10a96 1116 }
fep 0:5ff20db10a96 1117 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 1118
fep 0:5ff20db10a96 1119 /* Force a reschedule if it is the currently running task that has just
fep 0:5ff20db10a96 1120 been deleted. */
fep 0:5ff20db10a96 1121 if( xSchedulerRunning != pdFALSE )
fep 0:5ff20db10a96 1122 {
fep 0:5ff20db10a96 1123 if( pxTCB == pxCurrentTCB )
fep 0:5ff20db10a96 1124 {
fep 0:5ff20db10a96 1125 configASSERT( uxSchedulerSuspended == 0 );
fep 0:5ff20db10a96 1126 portYIELD_WITHIN_API();
fep 0:5ff20db10a96 1127 }
fep 0:5ff20db10a96 1128 else
fep 0:5ff20db10a96 1129 {
fep 0:5ff20db10a96 1130 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1131 }
fep 0:5ff20db10a96 1132 }
fep 0:5ff20db10a96 1133 }
fep 0:5ff20db10a96 1134
fep 0:5ff20db10a96 1135 #endif /* INCLUDE_vTaskDelete */
fep 0:5ff20db10a96 1136 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1137
fep 0:5ff20db10a96 1138 #if ( INCLUDE_vTaskDelayUntil == 1 )
fep 0:5ff20db10a96 1139
fep 0:5ff20db10a96 1140 void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
fep 0:5ff20db10a96 1141 {
fep 0:5ff20db10a96 1142 TickType_t xTimeToWake;
fep 0:5ff20db10a96 1143 BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
fep 0:5ff20db10a96 1144
fep 0:5ff20db10a96 1145 configASSERT( pxPreviousWakeTime );
fep 0:5ff20db10a96 1146 configASSERT( ( xTimeIncrement > 0U ) );
fep 0:5ff20db10a96 1147 configASSERT( uxSchedulerSuspended == 0 );
fep 0:5ff20db10a96 1148
fep 0:5ff20db10a96 1149 vTaskSuspendAll();
fep 0:5ff20db10a96 1150 {
fep 0:5ff20db10a96 1151 /* Minor optimisation. The tick count cannot change in this
fep 0:5ff20db10a96 1152 block. */
fep 0:5ff20db10a96 1153 const TickType_t xConstTickCount = xTickCount;
fep 0:5ff20db10a96 1154
fep 0:5ff20db10a96 1155 /* Generate the tick time at which the task wants to wake. */
fep 0:5ff20db10a96 1156 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
fep 0:5ff20db10a96 1157
fep 0:5ff20db10a96 1158 if( xConstTickCount < *pxPreviousWakeTime )
fep 0:5ff20db10a96 1159 {
fep 0:5ff20db10a96 1160 /* The tick count has overflowed since this function was
fep 0:5ff20db10a96 1161 lasted called. In this case the only time we should ever
fep 0:5ff20db10a96 1162 actually delay is if the wake time has also overflowed,
fep 0:5ff20db10a96 1163 and the wake time is greater than the tick time. When this
fep 0:5ff20db10a96 1164 is the case it is as if neither time had overflowed. */
fep 0:5ff20db10a96 1165 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
fep 0:5ff20db10a96 1166 {
fep 0:5ff20db10a96 1167 xShouldDelay = pdTRUE;
fep 0:5ff20db10a96 1168 }
fep 0:5ff20db10a96 1169 else
fep 0:5ff20db10a96 1170 {
fep 0:5ff20db10a96 1171 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1172 }
fep 0:5ff20db10a96 1173 }
fep 0:5ff20db10a96 1174 else
fep 0:5ff20db10a96 1175 {
fep 0:5ff20db10a96 1176 /* The tick time has not overflowed. In this case we will
fep 0:5ff20db10a96 1177 delay if either the wake time has overflowed, and/or the
fep 0:5ff20db10a96 1178 tick time is less than the wake time. */
fep 0:5ff20db10a96 1179 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
fep 0:5ff20db10a96 1180 {
fep 0:5ff20db10a96 1181 xShouldDelay = pdTRUE;
fep 0:5ff20db10a96 1182 }
fep 0:5ff20db10a96 1183 else
fep 0:5ff20db10a96 1184 {
fep 0:5ff20db10a96 1185 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1186 }
fep 0:5ff20db10a96 1187 }
fep 0:5ff20db10a96 1188
fep 0:5ff20db10a96 1189 /* Update the wake time ready for the next call. */
fep 0:5ff20db10a96 1190 *pxPreviousWakeTime = xTimeToWake;
fep 0:5ff20db10a96 1191
fep 0:5ff20db10a96 1192 if( xShouldDelay != pdFALSE )
fep 0:5ff20db10a96 1193 {
fep 0:5ff20db10a96 1194 traceTASK_DELAY_UNTIL( xTimeToWake );
fep 0:5ff20db10a96 1195
fep 0:5ff20db10a96 1196 /* prvAddCurrentTaskToDelayedList() needs the block time, not
fep 0:5ff20db10a96 1197 the time to wake, so subtract the current tick count. */
fep 0:5ff20db10a96 1198 prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
fep 0:5ff20db10a96 1199 }
fep 0:5ff20db10a96 1200 else
fep 0:5ff20db10a96 1201 {
fep 0:5ff20db10a96 1202 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1203 }
fep 0:5ff20db10a96 1204 }
fep 0:5ff20db10a96 1205 xAlreadyYielded = xTaskResumeAll();
fep 0:5ff20db10a96 1206
fep 0:5ff20db10a96 1207 /* Force a reschedule if xTaskResumeAll has not already done so, we may
fep 0:5ff20db10a96 1208 have put ourselves to sleep. */
fep 0:5ff20db10a96 1209 if( xAlreadyYielded == pdFALSE )
fep 0:5ff20db10a96 1210 {
fep 0:5ff20db10a96 1211 portYIELD_WITHIN_API();
fep 0:5ff20db10a96 1212 }
fep 0:5ff20db10a96 1213 else
fep 0:5ff20db10a96 1214 {
fep 0:5ff20db10a96 1215 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1216 }
fep 0:5ff20db10a96 1217 }
fep 0:5ff20db10a96 1218
fep 0:5ff20db10a96 1219 #endif /* INCLUDE_vTaskDelayUntil */
fep 0:5ff20db10a96 1220 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1221
fep 0:5ff20db10a96 1222 #if ( INCLUDE_vTaskDelay == 1 )
fep 0:5ff20db10a96 1223
fep 0:5ff20db10a96 1224 void vTaskDelay( const TickType_t xTicksToDelay )
fep 0:5ff20db10a96 1225 {
fep 0:5ff20db10a96 1226 BaseType_t xAlreadyYielded = pdFALSE;
fep 0:5ff20db10a96 1227
fep 0:5ff20db10a96 1228 /* A delay time of zero just forces a reschedule. */
fep 0:5ff20db10a96 1229 if( xTicksToDelay > ( TickType_t ) 0U )
fep 0:5ff20db10a96 1230 {
fep 0:5ff20db10a96 1231 configASSERT( uxSchedulerSuspended == 0 );
fep 0:5ff20db10a96 1232 vTaskSuspendAll();
fep 0:5ff20db10a96 1233 {
fep 0:5ff20db10a96 1234 traceTASK_DELAY();
fep 0:5ff20db10a96 1235
fep 0:5ff20db10a96 1236 /* A task that is removed from the event list while the
fep 0:5ff20db10a96 1237 scheduler is suspended will not get placed in the ready
fep 0:5ff20db10a96 1238 list or removed from the blocked list until the scheduler
fep 0:5ff20db10a96 1239 is resumed.
fep 0:5ff20db10a96 1240
fep 0:5ff20db10a96 1241 This task cannot be in an event list as it is the currently
fep 0:5ff20db10a96 1242 executing task. */
fep 0:5ff20db10a96 1243 prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
fep 0:5ff20db10a96 1244 }
fep 0:5ff20db10a96 1245 xAlreadyYielded = xTaskResumeAll();
fep 0:5ff20db10a96 1246 }
fep 0:5ff20db10a96 1247 else
fep 0:5ff20db10a96 1248 {
fep 0:5ff20db10a96 1249 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1250 }
fep 0:5ff20db10a96 1251
fep 0:5ff20db10a96 1252 /* Force a reschedule if xTaskResumeAll has not already done so, we may
fep 0:5ff20db10a96 1253 have put ourselves to sleep. */
fep 0:5ff20db10a96 1254 if( xAlreadyYielded == pdFALSE )
fep 0:5ff20db10a96 1255 {
fep 0:5ff20db10a96 1256 portYIELD_WITHIN_API();
fep 0:5ff20db10a96 1257 }
fep 0:5ff20db10a96 1258 else
fep 0:5ff20db10a96 1259 {
fep 0:5ff20db10a96 1260 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1261 }
fep 0:5ff20db10a96 1262 }
fep 0:5ff20db10a96 1263
fep 0:5ff20db10a96 1264 #endif /* INCLUDE_vTaskDelay */
fep 0:5ff20db10a96 1265 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1266
fep 0:5ff20db10a96 1267 #if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) )
fep 0:5ff20db10a96 1268
fep 0:5ff20db10a96 1269 eTaskState eTaskGetState( TaskHandle_t xTask )
fep 0:5ff20db10a96 1270 {
fep 0:5ff20db10a96 1271 eTaskState eReturn;
fep 0:5ff20db10a96 1272 List_t *pxStateList;
fep 0:5ff20db10a96 1273 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
fep 0:5ff20db10a96 1274
fep 0:5ff20db10a96 1275 configASSERT( pxTCB );
fep 0:5ff20db10a96 1276
fep 0:5ff20db10a96 1277 if( pxTCB == pxCurrentTCB )
fep 0:5ff20db10a96 1278 {
fep 0:5ff20db10a96 1279 /* The task calling this function is querying its own state. */
fep 0:5ff20db10a96 1280 eReturn = eRunning;
fep 0:5ff20db10a96 1281 }
fep 0:5ff20db10a96 1282 else
fep 0:5ff20db10a96 1283 {
fep 0:5ff20db10a96 1284 taskENTER_CRITICAL();
fep 0:5ff20db10a96 1285 {
fep 0:5ff20db10a96 1286 pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 1287 }
fep 0:5ff20db10a96 1288 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 1289
fep 0:5ff20db10a96 1290 if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
fep 0:5ff20db10a96 1291 {
fep 0:5ff20db10a96 1292 /* The task being queried is referenced from one of the Blocked
fep 0:5ff20db10a96 1293 lists. */
fep 0:5ff20db10a96 1294 eReturn = eBlocked;
fep 0:5ff20db10a96 1295 }
fep 0:5ff20db10a96 1296
fep 0:5ff20db10a96 1297 #if ( INCLUDE_vTaskSuspend == 1 )
fep 0:5ff20db10a96 1298 else if( pxStateList == &xSuspendedTaskList )
fep 0:5ff20db10a96 1299 {
fep 0:5ff20db10a96 1300 /* The task being queried is referenced from the suspended
fep 0:5ff20db10a96 1301 list. Is it genuinely suspended or is it block
fep 0:5ff20db10a96 1302 indefinitely? */
fep 0:5ff20db10a96 1303 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
fep 0:5ff20db10a96 1304 {
fep 0:5ff20db10a96 1305 eReturn = eSuspended;
fep 0:5ff20db10a96 1306 }
fep 0:5ff20db10a96 1307 else
fep 0:5ff20db10a96 1308 {
fep 0:5ff20db10a96 1309 eReturn = eBlocked;
fep 0:5ff20db10a96 1310 }
fep 0:5ff20db10a96 1311 }
fep 0:5ff20db10a96 1312 #endif
fep 0:5ff20db10a96 1313
fep 0:5ff20db10a96 1314 #if ( INCLUDE_vTaskDelete == 1 )
fep 0:5ff20db10a96 1315 else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )
fep 0:5ff20db10a96 1316 {
fep 0:5ff20db10a96 1317 /* The task being queried is referenced from the deleted
fep 0:5ff20db10a96 1318 tasks list, or it is not referenced from any lists at
fep 0:5ff20db10a96 1319 all. */
fep 0:5ff20db10a96 1320 eReturn = eDeleted;
fep 0:5ff20db10a96 1321 }
fep 0:5ff20db10a96 1322 #endif
fep 0:5ff20db10a96 1323
fep 0:5ff20db10a96 1324 else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */
fep 0:5ff20db10a96 1325 {
fep 0:5ff20db10a96 1326 /* If the task is not in any other state, it must be in the
fep 0:5ff20db10a96 1327 Ready (including pending ready) state. */
fep 0:5ff20db10a96 1328 eReturn = eReady;
fep 0:5ff20db10a96 1329 }
fep 0:5ff20db10a96 1330 }
fep 0:5ff20db10a96 1331
fep 0:5ff20db10a96 1332 return eReturn;
fep 0:5ff20db10a96 1333 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
fep 0:5ff20db10a96 1334
fep 0:5ff20db10a96 1335 #endif /* INCLUDE_eTaskGetState */
fep 0:5ff20db10a96 1336 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1337
fep 0:5ff20db10a96 1338 #if ( INCLUDE_uxTaskPriorityGet == 1 )
fep 0:5ff20db10a96 1339
fep 0:5ff20db10a96 1340 UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )
fep 0:5ff20db10a96 1341 {
fep 0:5ff20db10a96 1342 TCB_t *pxTCB;
fep 0:5ff20db10a96 1343 UBaseType_t uxReturn;
fep 0:5ff20db10a96 1344
fep 0:5ff20db10a96 1345 taskENTER_CRITICAL();
fep 0:5ff20db10a96 1346 {
fep 0:5ff20db10a96 1347 /* If null is passed in here then it is the priority of the that
fep 0:5ff20db10a96 1348 called uxTaskPriorityGet() that is being queried. */
fep 0:5ff20db10a96 1349 pxTCB = prvGetTCBFromHandle( xTask );
fep 0:5ff20db10a96 1350 uxReturn = pxTCB->uxPriority;
fep 0:5ff20db10a96 1351 }
fep 0:5ff20db10a96 1352 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 1353
fep 0:5ff20db10a96 1354 return uxReturn;
fep 0:5ff20db10a96 1355 }
fep 0:5ff20db10a96 1356
fep 0:5ff20db10a96 1357 #endif /* INCLUDE_uxTaskPriorityGet */
fep 0:5ff20db10a96 1358 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1359
fep 0:5ff20db10a96 1360 #if ( INCLUDE_uxTaskPriorityGet == 1 )
fep 0:5ff20db10a96 1361
fep 0:5ff20db10a96 1362 UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask )
fep 0:5ff20db10a96 1363 {
fep 0:5ff20db10a96 1364 TCB_t *pxTCB;
fep 0:5ff20db10a96 1365 UBaseType_t uxReturn, uxSavedInterruptState;
fep 0:5ff20db10a96 1366
fep 0:5ff20db10a96 1367 /* RTOS ports that support interrupt nesting have the concept of a
fep 0:5ff20db10a96 1368 maximum system call (or maximum API call) interrupt priority.
fep 0:5ff20db10a96 1369 Interrupts that are above the maximum system call priority are keep
fep 0:5ff20db10a96 1370 permanently enabled, even when the RTOS kernel is in a critical section,
fep 0:5ff20db10a96 1371 but cannot make any calls to FreeRTOS API functions. If configASSERT()
fep 0:5ff20db10a96 1372 is defined in FreeRTOSConfig.h then
fep 0:5ff20db10a96 1373 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
fep 0:5ff20db10a96 1374 failure if a FreeRTOS API function is called from an interrupt that has
fep 0:5ff20db10a96 1375 been assigned a priority above the configured maximum system call
fep 0:5ff20db10a96 1376 priority. Only FreeRTOS functions that end in FromISR can be called
fep 0:5ff20db10a96 1377 from interrupts that have been assigned a priority at or (logically)
fep 0:5ff20db10a96 1378 below the maximum system call interrupt priority. FreeRTOS maintains a
fep 0:5ff20db10a96 1379 separate interrupt safe API to ensure interrupt entry is as fast and as
fep 0:5ff20db10a96 1380 simple as possible. More information (albeit Cortex-M specific) is
fep 0:5ff20db10a96 1381 provided on the following link:
fep 0:5ff20db10a96 1382 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
fep 0:5ff20db10a96 1383 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
fep 0:5ff20db10a96 1384
fep 0:5ff20db10a96 1385 uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR();
fep 0:5ff20db10a96 1386 {
fep 0:5ff20db10a96 1387 /* If null is passed in here then it is the priority of the calling
fep 0:5ff20db10a96 1388 task that is being queried. */
fep 0:5ff20db10a96 1389 pxTCB = prvGetTCBFromHandle( xTask );
fep 0:5ff20db10a96 1390 uxReturn = pxTCB->uxPriority;
fep 0:5ff20db10a96 1391 }
fep 0:5ff20db10a96 1392 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState );
fep 0:5ff20db10a96 1393
fep 0:5ff20db10a96 1394 return uxReturn;
fep 0:5ff20db10a96 1395 }
fep 0:5ff20db10a96 1396
fep 0:5ff20db10a96 1397 #endif /* INCLUDE_uxTaskPriorityGet */
fep 0:5ff20db10a96 1398 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1399
fep 0:5ff20db10a96 1400 #if ( INCLUDE_vTaskPrioritySet == 1 )
fep 0:5ff20db10a96 1401
fep 0:5ff20db10a96 1402 void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
fep 0:5ff20db10a96 1403 {
fep 0:5ff20db10a96 1404 TCB_t *pxTCB;
fep 0:5ff20db10a96 1405 UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
fep 0:5ff20db10a96 1406 BaseType_t xYieldRequired = pdFALSE;
fep 0:5ff20db10a96 1407
fep 0:5ff20db10a96 1408 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
fep 0:5ff20db10a96 1409
fep 0:5ff20db10a96 1410 /* Ensure the new priority is valid. */
fep 0:5ff20db10a96 1411 if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
fep 0:5ff20db10a96 1412 {
fep 0:5ff20db10a96 1413 uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
fep 0:5ff20db10a96 1414 }
fep 0:5ff20db10a96 1415 else
fep 0:5ff20db10a96 1416 {
fep 0:5ff20db10a96 1417 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1418 }
fep 0:5ff20db10a96 1419
fep 0:5ff20db10a96 1420 taskENTER_CRITICAL();
fep 0:5ff20db10a96 1421 {
fep 0:5ff20db10a96 1422 /* If null is passed in here then it is the priority of the calling
fep 0:5ff20db10a96 1423 task that is being changed. */
fep 0:5ff20db10a96 1424 pxTCB = prvGetTCBFromHandle( xTask );
fep 0:5ff20db10a96 1425
fep 0:5ff20db10a96 1426 traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
fep 0:5ff20db10a96 1427
fep 0:5ff20db10a96 1428 #if ( configUSE_MUTEXES == 1 )
fep 0:5ff20db10a96 1429 {
fep 0:5ff20db10a96 1430 uxCurrentBasePriority = pxTCB->uxBasePriority;
fep 0:5ff20db10a96 1431 }
fep 0:5ff20db10a96 1432 #else
fep 0:5ff20db10a96 1433 {
fep 0:5ff20db10a96 1434 uxCurrentBasePriority = pxTCB->uxPriority;
fep 0:5ff20db10a96 1435 }
fep 0:5ff20db10a96 1436 #endif
fep 0:5ff20db10a96 1437
fep 0:5ff20db10a96 1438 if( uxCurrentBasePriority != uxNewPriority )
fep 0:5ff20db10a96 1439 {
fep 0:5ff20db10a96 1440 /* The priority change may have readied a task of higher
fep 0:5ff20db10a96 1441 priority than the calling task. */
fep 0:5ff20db10a96 1442 if( uxNewPriority > uxCurrentBasePriority )
fep 0:5ff20db10a96 1443 {
fep 0:5ff20db10a96 1444 if( pxTCB != pxCurrentTCB )
fep 0:5ff20db10a96 1445 {
fep 0:5ff20db10a96 1446 /* The priority of a task other than the currently
fep 0:5ff20db10a96 1447 running task is being raised. Is the priority being
fep 0:5ff20db10a96 1448 raised above that of the running task? */
fep 0:5ff20db10a96 1449 if( uxNewPriority >= pxCurrentTCB->uxPriority )
fep 0:5ff20db10a96 1450 {
fep 0:5ff20db10a96 1451 xYieldRequired = pdTRUE;
fep 0:5ff20db10a96 1452 }
fep 0:5ff20db10a96 1453 else
fep 0:5ff20db10a96 1454 {
fep 0:5ff20db10a96 1455 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1456 }
fep 0:5ff20db10a96 1457 }
fep 0:5ff20db10a96 1458 else
fep 0:5ff20db10a96 1459 {
fep 0:5ff20db10a96 1460 /* The priority of the running task is being raised,
fep 0:5ff20db10a96 1461 but the running task must already be the highest
fep 0:5ff20db10a96 1462 priority task able to run so no yield is required. */
fep 0:5ff20db10a96 1463 }
fep 0:5ff20db10a96 1464 }
fep 0:5ff20db10a96 1465 else if( pxTCB == pxCurrentTCB )
fep 0:5ff20db10a96 1466 {
fep 0:5ff20db10a96 1467 /* Setting the priority of the running task down means
fep 0:5ff20db10a96 1468 there may now be another task of higher priority that
fep 0:5ff20db10a96 1469 is ready to execute. */
fep 0:5ff20db10a96 1470 xYieldRequired = pdTRUE;
fep 0:5ff20db10a96 1471 }
fep 0:5ff20db10a96 1472 else
fep 0:5ff20db10a96 1473 {
fep 0:5ff20db10a96 1474 /* Setting the priority of any other task down does not
fep 0:5ff20db10a96 1475 require a yield as the running task must be above the
fep 0:5ff20db10a96 1476 new priority of the task being modified. */
fep 0:5ff20db10a96 1477 }
fep 0:5ff20db10a96 1478
fep 0:5ff20db10a96 1479 /* Remember the ready list the task might be referenced from
fep 0:5ff20db10a96 1480 before its uxPriority member is changed so the
fep 0:5ff20db10a96 1481 taskRESET_READY_PRIORITY() macro can function correctly. */
fep 0:5ff20db10a96 1482 uxPriorityUsedOnEntry = pxTCB->uxPriority;
fep 0:5ff20db10a96 1483
fep 0:5ff20db10a96 1484 #if ( configUSE_MUTEXES == 1 )
fep 0:5ff20db10a96 1485 {
fep 0:5ff20db10a96 1486 /* Only change the priority being used if the task is not
fep 0:5ff20db10a96 1487 currently using an inherited priority. */
fep 0:5ff20db10a96 1488 if( pxTCB->uxBasePriority == pxTCB->uxPriority )
fep 0:5ff20db10a96 1489 {
fep 0:5ff20db10a96 1490 pxTCB->uxPriority = uxNewPriority;
fep 0:5ff20db10a96 1491 }
fep 0:5ff20db10a96 1492 else
fep 0:5ff20db10a96 1493 {
fep 0:5ff20db10a96 1494 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1495 }
fep 0:5ff20db10a96 1496
fep 0:5ff20db10a96 1497 /* The base priority gets set whatever. */
fep 0:5ff20db10a96 1498 pxTCB->uxBasePriority = uxNewPriority;
fep 0:5ff20db10a96 1499 }
fep 0:5ff20db10a96 1500 #else
fep 0:5ff20db10a96 1501 {
fep 0:5ff20db10a96 1502 pxTCB->uxPriority = uxNewPriority;
fep 0:5ff20db10a96 1503 }
fep 0:5ff20db10a96 1504 #endif
fep 0:5ff20db10a96 1505
fep 0:5ff20db10a96 1506 /* Only reset the event list item value if the value is not
fep 0:5ff20db10a96 1507 being used for anything else. */
fep 0:5ff20db10a96 1508 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
fep 0:5ff20db10a96 1509 {
fep 0:5ff20db10a96 1510 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
fep 0:5ff20db10a96 1511 }
fep 0:5ff20db10a96 1512 else
fep 0:5ff20db10a96 1513 {
fep 0:5ff20db10a96 1514 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1515 }
fep 0:5ff20db10a96 1516
fep 0:5ff20db10a96 1517 /* If the task is in the blocked or suspended list we need do
fep 0:5ff20db10a96 1518 nothing more than change it's priority variable. However, if
fep 0:5ff20db10a96 1519 the task is in a ready list it needs to be removed and placed
fep 0:5ff20db10a96 1520 in the list appropriate to its new priority. */
fep 0:5ff20db10a96 1521 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
fep 0:5ff20db10a96 1522 {
fep 0:5ff20db10a96 1523 /* The task is currently in its ready list - remove before adding
fep 0:5ff20db10a96 1524 it to it's new ready list. As we are in a critical section we
fep 0:5ff20db10a96 1525 can do this even if the scheduler is suspended. */
fep 0:5ff20db10a96 1526 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
fep 0:5ff20db10a96 1527 {
fep 0:5ff20db10a96 1528 /* It is known that the task is in its ready list so
fep 0:5ff20db10a96 1529 there is no need to check again and the port level
fep 0:5ff20db10a96 1530 reset macro can be called directly. */
fep 0:5ff20db10a96 1531 portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
fep 0:5ff20db10a96 1532 }
fep 0:5ff20db10a96 1533 else
fep 0:5ff20db10a96 1534 {
fep 0:5ff20db10a96 1535 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1536 }
fep 0:5ff20db10a96 1537 prvAddTaskToReadyList( pxTCB );
fep 0:5ff20db10a96 1538 }
fep 0:5ff20db10a96 1539 else
fep 0:5ff20db10a96 1540 {
fep 0:5ff20db10a96 1541 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1542 }
fep 0:5ff20db10a96 1543
fep 0:5ff20db10a96 1544 if( xYieldRequired != pdFALSE )
fep 0:5ff20db10a96 1545 {
fep 0:5ff20db10a96 1546 taskYIELD_IF_USING_PREEMPTION();
fep 0:5ff20db10a96 1547 }
fep 0:5ff20db10a96 1548 else
fep 0:5ff20db10a96 1549 {
fep 0:5ff20db10a96 1550 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1551 }
fep 0:5ff20db10a96 1552
fep 0:5ff20db10a96 1553 /* Remove compiler warning about unused variables when the port
fep 0:5ff20db10a96 1554 optimised task selection is not being used. */
fep 0:5ff20db10a96 1555 ( void ) uxPriorityUsedOnEntry;
fep 0:5ff20db10a96 1556 }
fep 0:5ff20db10a96 1557 }
fep 0:5ff20db10a96 1558 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 1559 }
fep 0:5ff20db10a96 1560
fep 0:5ff20db10a96 1561 #endif /* INCLUDE_vTaskPrioritySet */
fep 0:5ff20db10a96 1562 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1563
fep 0:5ff20db10a96 1564 #if ( INCLUDE_vTaskSuspend == 1 )
fep 0:5ff20db10a96 1565
fep 0:5ff20db10a96 1566 void vTaskSuspend( TaskHandle_t xTaskToSuspend )
fep 0:5ff20db10a96 1567 {
fep 0:5ff20db10a96 1568 TCB_t *pxTCB;
fep 0:5ff20db10a96 1569
fep 0:5ff20db10a96 1570 taskENTER_CRITICAL();
fep 0:5ff20db10a96 1571 {
fep 0:5ff20db10a96 1572 /* If null is passed in here then it is the running task that is
fep 0:5ff20db10a96 1573 being suspended. */
fep 0:5ff20db10a96 1574 pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
fep 0:5ff20db10a96 1575
fep 0:5ff20db10a96 1576 traceTASK_SUSPEND( pxTCB );
fep 0:5ff20db10a96 1577
fep 0:5ff20db10a96 1578 /* Remove task from the ready/delayed list and place in the
fep 0:5ff20db10a96 1579 suspended list. */
fep 0:5ff20db10a96 1580 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
fep 0:5ff20db10a96 1581 {
fep 0:5ff20db10a96 1582 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
fep 0:5ff20db10a96 1583 }
fep 0:5ff20db10a96 1584 else
fep 0:5ff20db10a96 1585 {
fep 0:5ff20db10a96 1586 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1587 }
fep 0:5ff20db10a96 1588
fep 0:5ff20db10a96 1589 /* Is the task waiting on an event also? */
fep 0:5ff20db10a96 1590 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
fep 0:5ff20db10a96 1591 {
fep 0:5ff20db10a96 1592 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
fep 0:5ff20db10a96 1593 }
fep 0:5ff20db10a96 1594 else
fep 0:5ff20db10a96 1595 {
fep 0:5ff20db10a96 1596 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1597 }
fep 0:5ff20db10a96 1598
fep 0:5ff20db10a96 1599 vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 1600 }
fep 0:5ff20db10a96 1601 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 1602
fep 0:5ff20db10a96 1603 if( xSchedulerRunning != pdFALSE )
fep 0:5ff20db10a96 1604 {
fep 0:5ff20db10a96 1605 /* Reset the next expected unblock time in case it referred to the
fep 0:5ff20db10a96 1606 task that is now in the Suspended state. */
fep 0:5ff20db10a96 1607 taskENTER_CRITICAL();
fep 0:5ff20db10a96 1608 {
fep 0:5ff20db10a96 1609 prvResetNextTaskUnblockTime();
fep 0:5ff20db10a96 1610 }
fep 0:5ff20db10a96 1611 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 1612 }
fep 0:5ff20db10a96 1613 else
fep 0:5ff20db10a96 1614 {
fep 0:5ff20db10a96 1615 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1616 }
fep 0:5ff20db10a96 1617
fep 0:5ff20db10a96 1618 if( pxTCB == pxCurrentTCB )
fep 0:5ff20db10a96 1619 {
fep 0:5ff20db10a96 1620 if( xSchedulerRunning != pdFALSE )
fep 0:5ff20db10a96 1621 {
fep 0:5ff20db10a96 1622 /* The current task has just been suspended. */
fep 0:5ff20db10a96 1623 configASSERT( uxSchedulerSuspended == 0 );
fep 0:5ff20db10a96 1624 portYIELD_WITHIN_API();
fep 0:5ff20db10a96 1625 }
fep 0:5ff20db10a96 1626 else
fep 0:5ff20db10a96 1627 {
fep 0:5ff20db10a96 1628 /* The scheduler is not running, but the task that was pointed
fep 0:5ff20db10a96 1629 to by pxCurrentTCB has just been suspended and pxCurrentTCB
fep 0:5ff20db10a96 1630 must be adjusted to point to a different task. */
fep 0:5ff20db10a96 1631 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
fep 0:5ff20db10a96 1632 {
fep 0:5ff20db10a96 1633 /* No other tasks are ready, so set pxCurrentTCB back to
fep 0:5ff20db10a96 1634 NULL so when the next task is created pxCurrentTCB will
fep 0:5ff20db10a96 1635 be set to point to it no matter what its relative priority
fep 0:5ff20db10a96 1636 is. */
fep 0:5ff20db10a96 1637 pxCurrentTCB = NULL;
fep 0:5ff20db10a96 1638 }
fep 0:5ff20db10a96 1639 else
fep 0:5ff20db10a96 1640 {
fep 0:5ff20db10a96 1641 vTaskSwitchContext();
fep 0:5ff20db10a96 1642 }
fep 0:5ff20db10a96 1643 }
fep 0:5ff20db10a96 1644 }
fep 0:5ff20db10a96 1645 else
fep 0:5ff20db10a96 1646 {
fep 0:5ff20db10a96 1647 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1648 }
fep 0:5ff20db10a96 1649 }
fep 0:5ff20db10a96 1650
fep 0:5ff20db10a96 1651 #endif /* INCLUDE_vTaskSuspend */
fep 0:5ff20db10a96 1652 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1653
fep 0:5ff20db10a96 1654 #if ( INCLUDE_vTaskSuspend == 1 )
fep 0:5ff20db10a96 1655
fep 0:5ff20db10a96 1656 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
fep 0:5ff20db10a96 1657 {
fep 0:5ff20db10a96 1658 BaseType_t xReturn = pdFALSE;
fep 0:5ff20db10a96 1659 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
fep 0:5ff20db10a96 1660
fep 0:5ff20db10a96 1661 /* Accesses xPendingReadyList so must be called from a critical
fep 0:5ff20db10a96 1662 section. */
fep 0:5ff20db10a96 1663
fep 0:5ff20db10a96 1664 /* It does not make sense to check if the calling task is suspended. */
fep 0:5ff20db10a96 1665 configASSERT( xTask );
fep 0:5ff20db10a96 1666
fep 0:5ff20db10a96 1667 /* Is the task being resumed actually in the suspended list? */
fep 0:5ff20db10a96 1668 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
fep 0:5ff20db10a96 1669 {
fep 0:5ff20db10a96 1670 /* Has the task already been resumed from within an ISR? */
fep 0:5ff20db10a96 1671 if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
fep 0:5ff20db10a96 1672 {
fep 0:5ff20db10a96 1673 /* Is it in the suspended list because it is in the Suspended
fep 0:5ff20db10a96 1674 state, or because is is blocked with no timeout? */
fep 0:5ff20db10a96 1675 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
fep 0:5ff20db10a96 1676 {
fep 0:5ff20db10a96 1677 xReturn = pdTRUE;
fep 0:5ff20db10a96 1678 }
fep 0:5ff20db10a96 1679 else
fep 0:5ff20db10a96 1680 {
fep 0:5ff20db10a96 1681 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1682 }
fep 0:5ff20db10a96 1683 }
fep 0:5ff20db10a96 1684 else
fep 0:5ff20db10a96 1685 {
fep 0:5ff20db10a96 1686 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1687 }
fep 0:5ff20db10a96 1688 }
fep 0:5ff20db10a96 1689 else
fep 0:5ff20db10a96 1690 {
fep 0:5ff20db10a96 1691 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1692 }
fep 0:5ff20db10a96 1693
fep 0:5ff20db10a96 1694 return xReturn;
fep 0:5ff20db10a96 1695 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
fep 0:5ff20db10a96 1696
fep 0:5ff20db10a96 1697 #endif /* INCLUDE_vTaskSuspend */
fep 0:5ff20db10a96 1698 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1699
fep 0:5ff20db10a96 1700 #if ( INCLUDE_vTaskSuspend == 1 )
fep 0:5ff20db10a96 1701
fep 0:5ff20db10a96 1702 void vTaskResume( TaskHandle_t xTaskToResume )
fep 0:5ff20db10a96 1703 {
fep 0:5ff20db10a96 1704 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
fep 0:5ff20db10a96 1705
fep 0:5ff20db10a96 1706 /* It does not make sense to resume the calling task. */
fep 0:5ff20db10a96 1707 configASSERT( xTaskToResume );
fep 0:5ff20db10a96 1708
fep 0:5ff20db10a96 1709 /* The parameter cannot be NULL as it is impossible to resume the
fep 0:5ff20db10a96 1710 currently executing task. */
fep 0:5ff20db10a96 1711 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
fep 0:5ff20db10a96 1712 {
fep 0:5ff20db10a96 1713 taskENTER_CRITICAL();
fep 0:5ff20db10a96 1714 {
fep 0:5ff20db10a96 1715 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
fep 0:5ff20db10a96 1716 {
fep 0:5ff20db10a96 1717 traceTASK_RESUME( pxTCB );
fep 0:5ff20db10a96 1718
fep 0:5ff20db10a96 1719 /* As we are in a critical section we can access the ready
fep 0:5ff20db10a96 1720 lists even if the scheduler is suspended. */
fep 0:5ff20db10a96 1721 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 1722 prvAddTaskToReadyList( pxTCB );
fep 0:5ff20db10a96 1723
fep 0:5ff20db10a96 1724 /* We may have just resumed a higher priority task. */
fep 0:5ff20db10a96 1725 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
fep 0:5ff20db10a96 1726 {
fep 0:5ff20db10a96 1727 /* This yield may not cause the task just resumed to run,
fep 0:5ff20db10a96 1728 but will leave the lists in the correct state for the
fep 0:5ff20db10a96 1729 next yield. */
fep 0:5ff20db10a96 1730 taskYIELD_IF_USING_PREEMPTION();
fep 0:5ff20db10a96 1731 }
fep 0:5ff20db10a96 1732 else
fep 0:5ff20db10a96 1733 {
fep 0:5ff20db10a96 1734 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1735 }
fep 0:5ff20db10a96 1736 }
fep 0:5ff20db10a96 1737 else
fep 0:5ff20db10a96 1738 {
fep 0:5ff20db10a96 1739 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1740 }
fep 0:5ff20db10a96 1741 }
fep 0:5ff20db10a96 1742 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 1743 }
fep 0:5ff20db10a96 1744 else
fep 0:5ff20db10a96 1745 {
fep 0:5ff20db10a96 1746 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1747 }
fep 0:5ff20db10a96 1748 }
fep 0:5ff20db10a96 1749
fep 0:5ff20db10a96 1750 #endif /* INCLUDE_vTaskSuspend */
fep 0:5ff20db10a96 1751
fep 0:5ff20db10a96 1752 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1753
fep 0:5ff20db10a96 1754 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
fep 0:5ff20db10a96 1755
fep 0:5ff20db10a96 1756 BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
fep 0:5ff20db10a96 1757 {
fep 0:5ff20db10a96 1758 BaseType_t xYieldRequired = pdFALSE;
fep 0:5ff20db10a96 1759 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
fep 0:5ff20db10a96 1760 UBaseType_t uxSavedInterruptStatus;
fep 0:5ff20db10a96 1761
fep 0:5ff20db10a96 1762 configASSERT( xTaskToResume );
fep 0:5ff20db10a96 1763
fep 0:5ff20db10a96 1764 /* RTOS ports that support interrupt nesting have the concept of a
fep 0:5ff20db10a96 1765 maximum system call (or maximum API call) interrupt priority.
fep 0:5ff20db10a96 1766 Interrupts that are above the maximum system call priority are keep
fep 0:5ff20db10a96 1767 permanently enabled, even when the RTOS kernel is in a critical section,
fep 0:5ff20db10a96 1768 but cannot make any calls to FreeRTOS API functions. If configASSERT()
fep 0:5ff20db10a96 1769 is defined in FreeRTOSConfig.h then
fep 0:5ff20db10a96 1770 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
fep 0:5ff20db10a96 1771 failure if a FreeRTOS API function is called from an interrupt that has
fep 0:5ff20db10a96 1772 been assigned a priority above the configured maximum system call
fep 0:5ff20db10a96 1773 priority. Only FreeRTOS functions that end in FromISR can be called
fep 0:5ff20db10a96 1774 from interrupts that have been assigned a priority at or (logically)
fep 0:5ff20db10a96 1775 below the maximum system call interrupt priority. FreeRTOS maintains a
fep 0:5ff20db10a96 1776 separate interrupt safe API to ensure interrupt entry is as fast and as
fep 0:5ff20db10a96 1777 simple as possible. More information (albeit Cortex-M specific) is
fep 0:5ff20db10a96 1778 provided on the following link:
fep 0:5ff20db10a96 1779 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
fep 0:5ff20db10a96 1780 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
fep 0:5ff20db10a96 1781
fep 0:5ff20db10a96 1782 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
fep 0:5ff20db10a96 1783 {
fep 0:5ff20db10a96 1784 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
fep 0:5ff20db10a96 1785 {
fep 0:5ff20db10a96 1786 traceTASK_RESUME_FROM_ISR( pxTCB );
fep 0:5ff20db10a96 1787
fep 0:5ff20db10a96 1788 /* Check the ready lists can be accessed. */
fep 0:5ff20db10a96 1789 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
fep 0:5ff20db10a96 1790 {
fep 0:5ff20db10a96 1791 /* Ready lists can be accessed so move the task from the
fep 0:5ff20db10a96 1792 suspended list to the ready list directly. */
fep 0:5ff20db10a96 1793 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
fep 0:5ff20db10a96 1794 {
fep 0:5ff20db10a96 1795 xYieldRequired = pdTRUE;
fep 0:5ff20db10a96 1796 }
fep 0:5ff20db10a96 1797 else
fep 0:5ff20db10a96 1798 {
fep 0:5ff20db10a96 1799 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1800 }
fep 0:5ff20db10a96 1801
fep 0:5ff20db10a96 1802 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 1803 prvAddTaskToReadyList( pxTCB );
fep 0:5ff20db10a96 1804 }
fep 0:5ff20db10a96 1805 else
fep 0:5ff20db10a96 1806 {
fep 0:5ff20db10a96 1807 /* The delayed or ready lists cannot be accessed so the task
fep 0:5ff20db10a96 1808 is held in the pending ready list until the scheduler is
fep 0:5ff20db10a96 1809 unsuspended. */
fep 0:5ff20db10a96 1810 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
fep 0:5ff20db10a96 1811 }
fep 0:5ff20db10a96 1812 }
fep 0:5ff20db10a96 1813 else
fep 0:5ff20db10a96 1814 {
fep 0:5ff20db10a96 1815 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1816 }
fep 0:5ff20db10a96 1817 }
fep 0:5ff20db10a96 1818 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
fep 0:5ff20db10a96 1819
fep 0:5ff20db10a96 1820 return xYieldRequired;
fep 0:5ff20db10a96 1821 }
fep 0:5ff20db10a96 1822
fep 0:5ff20db10a96 1823 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
fep 0:5ff20db10a96 1824 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1825
fep 0:5ff20db10a96 1826 void vTaskStartScheduler( void )
fep 0:5ff20db10a96 1827 {
fep 0:5ff20db10a96 1828 BaseType_t xReturn;
fep 0:5ff20db10a96 1829
fep 0:5ff20db10a96 1830 /* Add the idle task at the lowest priority. */
fep 0:5ff20db10a96 1831 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
fep 0:5ff20db10a96 1832 {
fep 0:5ff20db10a96 1833 StaticTask_t *pxIdleTaskTCBBuffer = NULL;
fep 0:5ff20db10a96 1834 StackType_t *pxIdleTaskStackBuffer = NULL;
fep 0:5ff20db10a96 1835 uint32_t ulIdleTaskStackSize;
fep 0:5ff20db10a96 1836
fep 0:5ff20db10a96 1837 /* The Idle task is created using user provided RAM - obtain the
fep 0:5ff20db10a96 1838 address of the RAM then create the idle task. */
fep 0:5ff20db10a96 1839 vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
fep 0:5ff20db10a96 1840 xIdleTaskHandle = xTaskCreateStatic( prvIdleTask,
fep 0:5ff20db10a96 1841 "IDLE",
fep 0:5ff20db10a96 1842 ulIdleTaskStackSize,
fep 0:5ff20db10a96 1843 ( void * ) NULL,
fep 0:5ff20db10a96 1844 ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
fep 0:5ff20db10a96 1845 pxIdleTaskStackBuffer,
fep 0:5ff20db10a96 1846 pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
fep 0:5ff20db10a96 1847
fep 0:5ff20db10a96 1848 if( xIdleTaskHandle != NULL )
fep 0:5ff20db10a96 1849 {
fep 0:5ff20db10a96 1850 xReturn = pdPASS;
fep 0:5ff20db10a96 1851 }
fep 0:5ff20db10a96 1852 else
fep 0:5ff20db10a96 1853 {
fep 0:5ff20db10a96 1854 xReturn = pdFAIL;
fep 0:5ff20db10a96 1855 }
fep 0:5ff20db10a96 1856 }
fep 0:5ff20db10a96 1857 #else
fep 0:5ff20db10a96 1858 {
fep 0:5ff20db10a96 1859 /* The Idle task is being created using dynamically allocated RAM. */
fep 0:5ff20db10a96 1860 xReturn = xTaskCreate( prvIdleTask,
fep 0:5ff20db10a96 1861 "IDLE", configMINIMAL_STACK_SIZE,
fep 0:5ff20db10a96 1862 ( void * ) NULL,
fep 0:5ff20db10a96 1863 ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
fep 0:5ff20db10a96 1864 &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
fep 0:5ff20db10a96 1865 }
fep 0:5ff20db10a96 1866 #endif /* configSUPPORT_STATIC_ALLOCATION */
fep 0:5ff20db10a96 1867
fep 0:5ff20db10a96 1868 #if ( configUSE_TIMERS == 1 )
fep 0:5ff20db10a96 1869 {
fep 0:5ff20db10a96 1870 if( xReturn == pdPASS )
fep 0:5ff20db10a96 1871 {
fep 0:5ff20db10a96 1872 xReturn = xTimerCreateTimerTask();
fep 0:5ff20db10a96 1873 }
fep 0:5ff20db10a96 1874 else
fep 0:5ff20db10a96 1875 {
fep 0:5ff20db10a96 1876 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 1877 }
fep 0:5ff20db10a96 1878 }
fep 0:5ff20db10a96 1879 #endif /* configUSE_TIMERS */
fep 0:5ff20db10a96 1880
fep 0:5ff20db10a96 1881 if( xReturn == pdPASS )
fep 0:5ff20db10a96 1882 {
fep 0:5ff20db10a96 1883 /* Interrupts are turned off here, to ensure a tick does not occur
fep 0:5ff20db10a96 1884 before or during the call to xPortStartScheduler(). The stacks of
fep 0:5ff20db10a96 1885 the created tasks contain a status word with interrupts switched on
fep 0:5ff20db10a96 1886 so interrupts will automatically get re-enabled when the first task
fep 0:5ff20db10a96 1887 starts to run. */
fep 0:5ff20db10a96 1888 portDISABLE_INTERRUPTS();
fep 0:5ff20db10a96 1889
fep 0:5ff20db10a96 1890 #if ( configUSE_NEWLIB_REENTRANT == 1 )
fep 0:5ff20db10a96 1891 {
fep 0:5ff20db10a96 1892 /* Switch Newlib's _impure_ptr variable to point to the _reent
fep 0:5ff20db10a96 1893 structure specific to the task that will run first. */
fep 0:5ff20db10a96 1894 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
fep 0:5ff20db10a96 1895 }
fep 0:5ff20db10a96 1896 #endif /* configUSE_NEWLIB_REENTRANT */
fep 0:5ff20db10a96 1897
fep 0:5ff20db10a96 1898 xNextTaskUnblockTime = portMAX_DELAY;
fep 0:5ff20db10a96 1899 xSchedulerRunning = pdTRUE;
fep 0:5ff20db10a96 1900 xTickCount = ( TickType_t ) 0U;
fep 0:5ff20db10a96 1901
fep 0:5ff20db10a96 1902 /* If configGENERATE_RUN_TIME_STATS is defined then the following
fep 0:5ff20db10a96 1903 macro must be defined to configure the timer/counter used to generate
fep 0:5ff20db10a96 1904 the run time counter time base. */
fep 0:5ff20db10a96 1905 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
fep 0:5ff20db10a96 1906
fep 0:5ff20db10a96 1907 /* Setting up the timer tick is hardware specific and thus in the
fep 0:5ff20db10a96 1908 portable interface. */
fep 0:5ff20db10a96 1909 if( xPortStartScheduler() != pdFALSE )
fep 0:5ff20db10a96 1910 {
fep 0:5ff20db10a96 1911 /* Should not reach here as if the scheduler is running the
fep 0:5ff20db10a96 1912 function will not return. */
fep 0:5ff20db10a96 1913 }
fep 0:5ff20db10a96 1914 else
fep 0:5ff20db10a96 1915 {
fep 0:5ff20db10a96 1916 /* Should only reach here if a task calls xTaskEndScheduler(). */
fep 0:5ff20db10a96 1917 }
fep 0:5ff20db10a96 1918 }
fep 0:5ff20db10a96 1919 else
fep 0:5ff20db10a96 1920 {
fep 0:5ff20db10a96 1921 /* This line will only be reached if the kernel could not be started,
fep 0:5ff20db10a96 1922 because there was not enough FreeRTOS heap to create the idle task
fep 0:5ff20db10a96 1923 or the timer task. */
fep 0:5ff20db10a96 1924 configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
fep 0:5ff20db10a96 1925 }
fep 0:5ff20db10a96 1926
fep 0:5ff20db10a96 1927 /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
fep 0:5ff20db10a96 1928 meaning xIdleTaskHandle is not used anywhere else. */
fep 0:5ff20db10a96 1929 ( void ) xIdleTaskHandle;
fep 0:5ff20db10a96 1930 }
fep 0:5ff20db10a96 1931 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 1932
fep 0:5ff20db10a96 1933 void vTaskEndScheduler( void )
fep 0:5ff20db10a96 1934 {
fep 0:5ff20db10a96 1935 /* Stop the scheduler interrupts and call the portable scheduler end
fep 0:5ff20db10a96 1936 routine so the original ISRs can be restored if necessary. The port
fep 0:5ff20db10a96 1937 layer must ensure interrupts enable bit is left in the correct state. */
fep 0:5ff20db10a96 1938 portDISABLE_INTERRUPTS();
fep 0:5ff20db10a96 1939 xSchedulerRunning = pdFALSE;
fep 0:5ff20db10a96 1940 vPortEndScheduler();
fep 0:5ff20db10a96 1941 }
fep 0:5ff20db10a96 1942 /*----------------------------------------------------------*/
fep 0:5ff20db10a96 1943
fep 0:5ff20db10a96 1944 void vTaskSuspendAll( void )
fep 0:5ff20db10a96 1945 {
fep 0:5ff20db10a96 1946 /* A critical section is not required as the variable is of type
fep 0:5ff20db10a96 1947 BaseType_t. Please read Richard Barry's reply in the following link to a
fep 0:5ff20db10a96 1948 post in the FreeRTOS support forum before reporting this as a bug! -
fep 0:5ff20db10a96 1949 http://goo.gl/wu4acr */
fep 0:5ff20db10a96 1950 ++uxSchedulerSuspended;
fep 0:5ff20db10a96 1951 }
fep 0:5ff20db10a96 1952 /*----------------------------------------------------------*/
fep 0:5ff20db10a96 1953
fep 0:5ff20db10a96 1954 #if ( configUSE_TICKLESS_IDLE != 0 )
fep 0:5ff20db10a96 1955
fep 0:5ff20db10a96 1956 static TickType_t prvGetExpectedIdleTime( void )
fep 0:5ff20db10a96 1957 {
fep 0:5ff20db10a96 1958 TickType_t xReturn;
fep 0:5ff20db10a96 1959 UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
fep 0:5ff20db10a96 1960
fep 0:5ff20db10a96 1961 /* uxHigherPriorityReadyTasks takes care of the case where
fep 0:5ff20db10a96 1962 configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
fep 0:5ff20db10a96 1963 task that are in the Ready state, even though the idle task is
fep 0:5ff20db10a96 1964 running. */
fep 0:5ff20db10a96 1965 #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
fep 0:5ff20db10a96 1966 {
fep 0:5ff20db10a96 1967 if( uxTopReadyPriority > tskIDLE_PRIORITY )
fep 0:5ff20db10a96 1968 {
fep 0:5ff20db10a96 1969 uxHigherPriorityReadyTasks = pdTRUE;
fep 0:5ff20db10a96 1970 }
fep 0:5ff20db10a96 1971 }
fep 0:5ff20db10a96 1972 #else
fep 0:5ff20db10a96 1973 {
fep 0:5ff20db10a96 1974 const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
fep 0:5ff20db10a96 1975
fep 0:5ff20db10a96 1976 /* When port optimised task selection is used the uxTopReadyPriority
fep 0:5ff20db10a96 1977 variable is used as a bit map. If bits other than the least
fep 0:5ff20db10a96 1978 significant bit are set then there are tasks that have a priority
fep 0:5ff20db10a96 1979 above the idle priority that are in the Ready state. This takes
fep 0:5ff20db10a96 1980 care of the case where the co-operative scheduler is in use. */
fep 0:5ff20db10a96 1981 if( uxTopReadyPriority > uxLeastSignificantBit )
fep 0:5ff20db10a96 1982 {
fep 0:5ff20db10a96 1983 uxHigherPriorityReadyTasks = pdTRUE;
fep 0:5ff20db10a96 1984 }
fep 0:5ff20db10a96 1985 }
fep 0:5ff20db10a96 1986 #endif
fep 0:5ff20db10a96 1987
fep 0:5ff20db10a96 1988 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
fep 0:5ff20db10a96 1989 {
fep 0:5ff20db10a96 1990 xReturn = 0;
fep 0:5ff20db10a96 1991 }
fep 0:5ff20db10a96 1992 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
fep 0:5ff20db10a96 1993 {
fep 0:5ff20db10a96 1994 /* There are other idle priority tasks in the ready state. If
fep 0:5ff20db10a96 1995 time slicing is used then the very next tick interrupt must be
fep 0:5ff20db10a96 1996 processed. */
fep 0:5ff20db10a96 1997 xReturn = 0;
fep 0:5ff20db10a96 1998 }
fep 0:5ff20db10a96 1999 else if( uxHigherPriorityReadyTasks != pdFALSE )
fep 0:5ff20db10a96 2000 {
fep 0:5ff20db10a96 2001 /* There are tasks in the Ready state that have a priority above the
fep 0:5ff20db10a96 2002 idle priority. This path can only be reached if
fep 0:5ff20db10a96 2003 configUSE_PREEMPTION is 0. */
fep 0:5ff20db10a96 2004 xReturn = 0;
fep 0:5ff20db10a96 2005 }
fep 0:5ff20db10a96 2006 else
fep 0:5ff20db10a96 2007 {
fep 0:5ff20db10a96 2008 xReturn = xNextTaskUnblockTime - xTickCount;
fep 0:5ff20db10a96 2009 }
fep 0:5ff20db10a96 2010
fep 0:5ff20db10a96 2011 return xReturn;
fep 0:5ff20db10a96 2012 }
fep 0:5ff20db10a96 2013
fep 0:5ff20db10a96 2014 #endif /* configUSE_TICKLESS_IDLE */
fep 0:5ff20db10a96 2015 /*----------------------------------------------------------*/
fep 0:5ff20db10a96 2016
fep 0:5ff20db10a96 2017 BaseType_t xTaskResumeAll( void )
fep 0:5ff20db10a96 2018 {
fep 0:5ff20db10a96 2019 TCB_t *pxTCB = NULL;
fep 0:5ff20db10a96 2020 BaseType_t xAlreadyYielded = pdFALSE;
fep 0:5ff20db10a96 2021
fep 0:5ff20db10a96 2022 /* If uxSchedulerSuspended is zero then this function does not match a
fep 0:5ff20db10a96 2023 previous call to vTaskSuspendAll(). */
fep 0:5ff20db10a96 2024 configASSERT( uxSchedulerSuspended );
fep 0:5ff20db10a96 2025
fep 0:5ff20db10a96 2026 /* It is possible that an ISR caused a task to be removed from an event
fep 0:5ff20db10a96 2027 list while the scheduler was suspended. If this was the case then the
fep 0:5ff20db10a96 2028 removed task will have been added to the xPendingReadyList. Once the
fep 0:5ff20db10a96 2029 scheduler has been resumed it is safe to move all the pending ready
fep 0:5ff20db10a96 2030 tasks from this list into their appropriate ready list. */
fep 0:5ff20db10a96 2031 taskENTER_CRITICAL();
fep 0:5ff20db10a96 2032 {
fep 0:5ff20db10a96 2033 --uxSchedulerSuspended;
fep 0:5ff20db10a96 2034
fep 0:5ff20db10a96 2035 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
fep 0:5ff20db10a96 2036 {
fep 0:5ff20db10a96 2037 if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
fep 0:5ff20db10a96 2038 {
fep 0:5ff20db10a96 2039 /* Move any readied tasks from the pending list into the
fep 0:5ff20db10a96 2040 appropriate ready list. */
fep 0:5ff20db10a96 2041 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
fep 0:5ff20db10a96 2042 {
fep 0:5ff20db10a96 2043 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
fep 0:5ff20db10a96 2044 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
fep 0:5ff20db10a96 2045 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 2046 prvAddTaskToReadyList( pxTCB );
fep 0:5ff20db10a96 2047
fep 0:5ff20db10a96 2048 /* If the moved task has a priority higher than the current
fep 0:5ff20db10a96 2049 task then a yield must be performed. */
fep 0:5ff20db10a96 2050 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
fep 0:5ff20db10a96 2051 {
fep 0:5ff20db10a96 2052 xYieldPending = pdTRUE;
fep 0:5ff20db10a96 2053 }
fep 0:5ff20db10a96 2054 else
fep 0:5ff20db10a96 2055 {
fep 0:5ff20db10a96 2056 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2057 }
fep 0:5ff20db10a96 2058 }
fep 0:5ff20db10a96 2059
fep 0:5ff20db10a96 2060 if( pxTCB != NULL )
fep 0:5ff20db10a96 2061 {
fep 0:5ff20db10a96 2062 /* A task was unblocked while the scheduler was suspended,
fep 0:5ff20db10a96 2063 which may have prevented the next unblock time from being
fep 0:5ff20db10a96 2064 re-calculated, in which case re-calculate it now. Mainly
fep 0:5ff20db10a96 2065 important for low power tickless implementations, where
fep 0:5ff20db10a96 2066 this can prevent an unnecessary exit from low power
fep 0:5ff20db10a96 2067 state. */
fep 0:5ff20db10a96 2068 prvResetNextTaskUnblockTime();
fep 0:5ff20db10a96 2069 }
fep 0:5ff20db10a96 2070
fep 0:5ff20db10a96 2071 /* If any ticks occurred while the scheduler was suspended then
fep 0:5ff20db10a96 2072 they should be processed now. This ensures the tick count does
fep 0:5ff20db10a96 2073 not slip, and that any delayed tasks are resumed at the correct
fep 0:5ff20db10a96 2074 time. */
fep 0:5ff20db10a96 2075 {
fep 0:5ff20db10a96 2076 UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */
fep 0:5ff20db10a96 2077
fep 0:5ff20db10a96 2078 if( uxPendedCounts > ( UBaseType_t ) 0U )
fep 0:5ff20db10a96 2079 {
fep 0:5ff20db10a96 2080 do
fep 0:5ff20db10a96 2081 {
fep 0:5ff20db10a96 2082 if( xTaskIncrementTick() != pdFALSE )
fep 0:5ff20db10a96 2083 {
fep 0:5ff20db10a96 2084 xYieldPending = pdTRUE;
fep 0:5ff20db10a96 2085 }
fep 0:5ff20db10a96 2086 else
fep 0:5ff20db10a96 2087 {
fep 0:5ff20db10a96 2088 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2089 }
fep 0:5ff20db10a96 2090 --uxPendedCounts;
fep 0:5ff20db10a96 2091 } while( uxPendedCounts > ( UBaseType_t ) 0U );
fep 0:5ff20db10a96 2092
fep 0:5ff20db10a96 2093 uxPendedTicks = 0;
fep 0:5ff20db10a96 2094 }
fep 0:5ff20db10a96 2095 else
fep 0:5ff20db10a96 2096 {
fep 0:5ff20db10a96 2097 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2098 }
fep 0:5ff20db10a96 2099 }
fep 0:5ff20db10a96 2100
fep 0:5ff20db10a96 2101 if( xYieldPending != pdFALSE )
fep 0:5ff20db10a96 2102 {
fep 0:5ff20db10a96 2103 #if( configUSE_PREEMPTION != 0 )
fep 0:5ff20db10a96 2104 {
fep 0:5ff20db10a96 2105 xAlreadyYielded = pdTRUE;
fep 0:5ff20db10a96 2106 }
fep 0:5ff20db10a96 2107 #endif
fep 0:5ff20db10a96 2108 taskYIELD_IF_USING_PREEMPTION();
fep 0:5ff20db10a96 2109 }
fep 0:5ff20db10a96 2110 else
fep 0:5ff20db10a96 2111 {
fep 0:5ff20db10a96 2112 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2113 }
fep 0:5ff20db10a96 2114 }
fep 0:5ff20db10a96 2115 }
fep 0:5ff20db10a96 2116 else
fep 0:5ff20db10a96 2117 {
fep 0:5ff20db10a96 2118 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2119 }
fep 0:5ff20db10a96 2120 }
fep 0:5ff20db10a96 2121 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 2122
fep 0:5ff20db10a96 2123 return xAlreadyYielded;
fep 0:5ff20db10a96 2124 }
fep 0:5ff20db10a96 2125 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2126
fep 0:5ff20db10a96 2127 TickType_t xTaskGetTickCount( void )
fep 0:5ff20db10a96 2128 {
fep 0:5ff20db10a96 2129 TickType_t xTicks;
fep 0:5ff20db10a96 2130
fep 0:5ff20db10a96 2131 /* Critical section required if running on a 16 bit processor. */
fep 0:5ff20db10a96 2132 portTICK_TYPE_ENTER_CRITICAL();
fep 0:5ff20db10a96 2133 {
fep 0:5ff20db10a96 2134 xTicks = xTickCount;
fep 0:5ff20db10a96 2135 }
fep 0:5ff20db10a96 2136 portTICK_TYPE_EXIT_CRITICAL();
fep 0:5ff20db10a96 2137
fep 0:5ff20db10a96 2138 return xTicks;
fep 0:5ff20db10a96 2139 }
fep 0:5ff20db10a96 2140 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2141
fep 0:5ff20db10a96 2142 TickType_t xTaskGetTickCountFromISR( void )
fep 0:5ff20db10a96 2143 {
fep 0:5ff20db10a96 2144 TickType_t xReturn;
fep 0:5ff20db10a96 2145 UBaseType_t uxSavedInterruptStatus;
fep 0:5ff20db10a96 2146
fep 0:5ff20db10a96 2147 /* RTOS ports that support interrupt nesting have the concept of a maximum
fep 0:5ff20db10a96 2148 system call (or maximum API call) interrupt priority. Interrupts that are
fep 0:5ff20db10a96 2149 above the maximum system call priority are kept permanently enabled, even
fep 0:5ff20db10a96 2150 when the RTOS kernel is in a critical section, but cannot make any calls to
fep 0:5ff20db10a96 2151 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
fep 0:5ff20db10a96 2152 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
fep 0:5ff20db10a96 2153 failure if a FreeRTOS API function is called from an interrupt that has been
fep 0:5ff20db10a96 2154 assigned a priority above the configured maximum system call priority.
fep 0:5ff20db10a96 2155 Only FreeRTOS functions that end in FromISR can be called from interrupts
fep 0:5ff20db10a96 2156 that have been assigned a priority at or (logically) below the maximum
fep 0:5ff20db10a96 2157 system call interrupt priority. FreeRTOS maintains a separate interrupt
fep 0:5ff20db10a96 2158 safe API to ensure interrupt entry is as fast and as simple as possible.
fep 0:5ff20db10a96 2159 More information (albeit Cortex-M specific) is provided on the following
fep 0:5ff20db10a96 2160 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
fep 0:5ff20db10a96 2161 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
fep 0:5ff20db10a96 2162
fep 0:5ff20db10a96 2163 uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();
fep 0:5ff20db10a96 2164 {
fep 0:5ff20db10a96 2165 xReturn = xTickCount;
fep 0:5ff20db10a96 2166 }
fep 0:5ff20db10a96 2167 portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
fep 0:5ff20db10a96 2168
fep 0:5ff20db10a96 2169 return xReturn;
fep 0:5ff20db10a96 2170 }
fep 0:5ff20db10a96 2171 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2172
fep 0:5ff20db10a96 2173 UBaseType_t uxTaskGetNumberOfTasks( void )
fep 0:5ff20db10a96 2174 {
fep 0:5ff20db10a96 2175 /* A critical section is not required because the variables are of type
fep 0:5ff20db10a96 2176 BaseType_t. */
fep 0:5ff20db10a96 2177 return uxCurrentNumberOfTasks;
fep 0:5ff20db10a96 2178 }
fep 0:5ff20db10a96 2179 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2180
fep 0:5ff20db10a96 2181 char *pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
fep 0:5ff20db10a96 2182 {
fep 0:5ff20db10a96 2183 TCB_t *pxTCB;
fep 0:5ff20db10a96 2184
fep 0:5ff20db10a96 2185 /* If null is passed in here then the name of the calling task is being
fep 0:5ff20db10a96 2186 queried. */
fep 0:5ff20db10a96 2187 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
fep 0:5ff20db10a96 2188 configASSERT( pxTCB );
fep 0:5ff20db10a96 2189 return &( pxTCB->pcTaskName[ 0 ] );
fep 0:5ff20db10a96 2190 }
fep 0:5ff20db10a96 2191 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2192
fep 0:5ff20db10a96 2193 #if ( INCLUDE_xTaskGetHandle == 1 )
fep 0:5ff20db10a96 2194
fep 0:5ff20db10a96 2195 static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] )
fep 0:5ff20db10a96 2196 {
fep 0:5ff20db10a96 2197 TCB_t *pxNextTCB, *pxFirstTCB, *pxReturn = NULL;
fep 0:5ff20db10a96 2198 UBaseType_t x;
fep 0:5ff20db10a96 2199 char cNextChar;
fep 0:5ff20db10a96 2200
fep 0:5ff20db10a96 2201 /* This function is called with the scheduler suspended. */
fep 0:5ff20db10a96 2202
fep 0:5ff20db10a96 2203 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
fep 0:5ff20db10a96 2204 {
fep 0:5ff20db10a96 2205 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
fep 0:5ff20db10a96 2206
fep 0:5ff20db10a96 2207 do
fep 0:5ff20db10a96 2208 {
fep 0:5ff20db10a96 2209 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
fep 0:5ff20db10a96 2210
fep 0:5ff20db10a96 2211 /* Check each character in the name looking for a match or
fep 0:5ff20db10a96 2212 mismatch. */
fep 0:5ff20db10a96 2213 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
fep 0:5ff20db10a96 2214 {
fep 0:5ff20db10a96 2215 cNextChar = pxNextTCB->pcTaskName[ x ];
fep 0:5ff20db10a96 2216
fep 0:5ff20db10a96 2217 if( cNextChar != pcNameToQuery[ x ] )
fep 0:5ff20db10a96 2218 {
fep 0:5ff20db10a96 2219 /* Characters didn't match. */
fep 0:5ff20db10a96 2220 break;
fep 0:5ff20db10a96 2221 }
fep 0:5ff20db10a96 2222 else if( cNextChar == 0x00 )
fep 0:5ff20db10a96 2223 {
fep 0:5ff20db10a96 2224 /* Both strings terminated, a match must have been
fep 0:5ff20db10a96 2225 found. */
fep 0:5ff20db10a96 2226 pxReturn = pxNextTCB;
fep 0:5ff20db10a96 2227 break;
fep 0:5ff20db10a96 2228 }
fep 0:5ff20db10a96 2229 else
fep 0:5ff20db10a96 2230 {
fep 0:5ff20db10a96 2231 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2232 }
fep 0:5ff20db10a96 2233 }
fep 0:5ff20db10a96 2234
fep 0:5ff20db10a96 2235 if( pxReturn != NULL )
fep 0:5ff20db10a96 2236 {
fep 0:5ff20db10a96 2237 /* The handle has been found. */
fep 0:5ff20db10a96 2238 break;
fep 0:5ff20db10a96 2239 }
fep 0:5ff20db10a96 2240
fep 0:5ff20db10a96 2241 } while( pxNextTCB != pxFirstTCB );
fep 0:5ff20db10a96 2242 }
fep 0:5ff20db10a96 2243 else
fep 0:5ff20db10a96 2244 {
fep 0:5ff20db10a96 2245 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2246 }
fep 0:5ff20db10a96 2247
fep 0:5ff20db10a96 2248 return pxReturn;
fep 0:5ff20db10a96 2249 }
fep 0:5ff20db10a96 2250
fep 0:5ff20db10a96 2251 #endif /* INCLUDE_xTaskGetHandle */
fep 0:5ff20db10a96 2252 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2253
fep 0:5ff20db10a96 2254 #if ( INCLUDE_xTaskGetHandle == 1 )
fep 0:5ff20db10a96 2255
fep 0:5ff20db10a96 2256 TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
fep 0:5ff20db10a96 2257 {
fep 0:5ff20db10a96 2258 UBaseType_t uxQueue = configMAX_PRIORITIES;
fep 0:5ff20db10a96 2259 TCB_t* pxTCB;
fep 0:5ff20db10a96 2260
fep 0:5ff20db10a96 2261 /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
fep 0:5ff20db10a96 2262 configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
fep 0:5ff20db10a96 2263
fep 0:5ff20db10a96 2264 vTaskSuspendAll();
fep 0:5ff20db10a96 2265 {
fep 0:5ff20db10a96 2266 /* Search the ready lists. */
fep 0:5ff20db10a96 2267 do
fep 0:5ff20db10a96 2268 {
fep 0:5ff20db10a96 2269 uxQueue--;
fep 0:5ff20db10a96 2270 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );
fep 0:5ff20db10a96 2271
fep 0:5ff20db10a96 2272 if( pxTCB != NULL )
fep 0:5ff20db10a96 2273 {
fep 0:5ff20db10a96 2274 /* Found the handle. */
fep 0:5ff20db10a96 2275 break;
fep 0:5ff20db10a96 2276 }
fep 0:5ff20db10a96 2277
fep 0:5ff20db10a96 2278 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
fep 0:5ff20db10a96 2279
fep 0:5ff20db10a96 2280 /* Search the delayed lists. */
fep 0:5ff20db10a96 2281 if( pxTCB == NULL )
fep 0:5ff20db10a96 2282 {
fep 0:5ff20db10a96 2283 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );
fep 0:5ff20db10a96 2284 }
fep 0:5ff20db10a96 2285
fep 0:5ff20db10a96 2286 if( pxTCB == NULL )
fep 0:5ff20db10a96 2287 {
fep 0:5ff20db10a96 2288 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );
fep 0:5ff20db10a96 2289 }
fep 0:5ff20db10a96 2290
fep 0:5ff20db10a96 2291 #if ( INCLUDE_vTaskSuspend == 1 )
fep 0:5ff20db10a96 2292 {
fep 0:5ff20db10a96 2293 if( pxTCB == NULL )
fep 0:5ff20db10a96 2294 {
fep 0:5ff20db10a96 2295 /* Search the suspended list. */
fep 0:5ff20db10a96 2296 pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );
fep 0:5ff20db10a96 2297 }
fep 0:5ff20db10a96 2298 }
fep 0:5ff20db10a96 2299 #endif
fep 0:5ff20db10a96 2300
fep 0:5ff20db10a96 2301 #if( INCLUDE_vTaskDelete == 1 )
fep 0:5ff20db10a96 2302 {
fep 0:5ff20db10a96 2303 if( pxTCB == NULL )
fep 0:5ff20db10a96 2304 {
fep 0:5ff20db10a96 2305 /* Search the deleted list. */
fep 0:5ff20db10a96 2306 pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );
fep 0:5ff20db10a96 2307 }
fep 0:5ff20db10a96 2308 }
fep 0:5ff20db10a96 2309 #endif
fep 0:5ff20db10a96 2310 }
fep 0:5ff20db10a96 2311 ( void ) xTaskResumeAll();
fep 0:5ff20db10a96 2312
fep 0:5ff20db10a96 2313 return ( TaskHandle_t ) pxTCB;
fep 0:5ff20db10a96 2314 }
fep 0:5ff20db10a96 2315
fep 0:5ff20db10a96 2316 #endif /* INCLUDE_xTaskGetHandle */
fep 0:5ff20db10a96 2317 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2318
fep 0:5ff20db10a96 2319 #if ( configUSE_TRACE_FACILITY == 1 )
fep 0:5ff20db10a96 2320
fep 0:5ff20db10a96 2321 UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )
fep 0:5ff20db10a96 2322 {
fep 0:5ff20db10a96 2323 UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
fep 0:5ff20db10a96 2324
fep 0:5ff20db10a96 2325 vTaskSuspendAll();
fep 0:5ff20db10a96 2326 {
fep 0:5ff20db10a96 2327 /* Is there a space in the array for each task in the system? */
fep 0:5ff20db10a96 2328 if( uxArraySize >= uxCurrentNumberOfTasks )
fep 0:5ff20db10a96 2329 {
fep 0:5ff20db10a96 2330 /* Fill in an TaskStatus_t structure with information on each
fep 0:5ff20db10a96 2331 task in the Ready state. */
fep 0:5ff20db10a96 2332 do
fep 0:5ff20db10a96 2333 {
fep 0:5ff20db10a96 2334 uxQueue--;
fep 0:5ff20db10a96 2335 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
fep 0:5ff20db10a96 2336
fep 0:5ff20db10a96 2337 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
fep 0:5ff20db10a96 2338
fep 0:5ff20db10a96 2339 /* Fill in an TaskStatus_t structure with information on each
fep 0:5ff20db10a96 2340 task in the Blocked state. */
fep 0:5ff20db10a96 2341 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
fep 0:5ff20db10a96 2342 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
fep 0:5ff20db10a96 2343
fep 0:5ff20db10a96 2344 #if( INCLUDE_vTaskDelete == 1 )
fep 0:5ff20db10a96 2345 {
fep 0:5ff20db10a96 2346 /* Fill in an TaskStatus_t structure with information on
fep 0:5ff20db10a96 2347 each task that has been deleted but not yet cleaned up. */
fep 0:5ff20db10a96 2348 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
fep 0:5ff20db10a96 2349 }
fep 0:5ff20db10a96 2350 #endif
fep 0:5ff20db10a96 2351
fep 0:5ff20db10a96 2352 #if ( INCLUDE_vTaskSuspend == 1 )
fep 0:5ff20db10a96 2353 {
fep 0:5ff20db10a96 2354 /* Fill in an TaskStatus_t structure with information on
fep 0:5ff20db10a96 2355 each task in the Suspended state. */
fep 0:5ff20db10a96 2356 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
fep 0:5ff20db10a96 2357 }
fep 0:5ff20db10a96 2358 #endif
fep 0:5ff20db10a96 2359
fep 0:5ff20db10a96 2360 #if ( configGENERATE_RUN_TIME_STATS == 1)
fep 0:5ff20db10a96 2361 {
fep 0:5ff20db10a96 2362 if( pulTotalRunTime != NULL )
fep 0:5ff20db10a96 2363 {
fep 0:5ff20db10a96 2364 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
fep 0:5ff20db10a96 2365 portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
fep 0:5ff20db10a96 2366 #else
fep 0:5ff20db10a96 2367 *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
fep 0:5ff20db10a96 2368 #endif
fep 0:5ff20db10a96 2369 }
fep 0:5ff20db10a96 2370 }
fep 0:5ff20db10a96 2371 #else
fep 0:5ff20db10a96 2372 {
fep 0:5ff20db10a96 2373 if( pulTotalRunTime != NULL )
fep 0:5ff20db10a96 2374 {
fep 0:5ff20db10a96 2375 *pulTotalRunTime = 0;
fep 0:5ff20db10a96 2376 }
fep 0:5ff20db10a96 2377 }
fep 0:5ff20db10a96 2378 #endif
fep 0:5ff20db10a96 2379 }
fep 0:5ff20db10a96 2380 else
fep 0:5ff20db10a96 2381 {
fep 0:5ff20db10a96 2382 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2383 }
fep 0:5ff20db10a96 2384 }
fep 0:5ff20db10a96 2385 ( void ) xTaskResumeAll();
fep 0:5ff20db10a96 2386
fep 0:5ff20db10a96 2387 return uxTask;
fep 0:5ff20db10a96 2388 }
fep 0:5ff20db10a96 2389
fep 0:5ff20db10a96 2390 #endif /* configUSE_TRACE_FACILITY */
fep 0:5ff20db10a96 2391 /*----------------------------------------------------------*/
fep 0:5ff20db10a96 2392
fep 0:5ff20db10a96 2393 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
fep 0:5ff20db10a96 2394
fep 0:5ff20db10a96 2395 TaskHandle_t xTaskGetIdleTaskHandle( void )
fep 0:5ff20db10a96 2396 {
fep 0:5ff20db10a96 2397 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
fep 0:5ff20db10a96 2398 started, then xIdleTaskHandle will be NULL. */
fep 0:5ff20db10a96 2399 configASSERT( ( xIdleTaskHandle != NULL ) );
fep 0:5ff20db10a96 2400 return xIdleTaskHandle;
fep 0:5ff20db10a96 2401 }
fep 0:5ff20db10a96 2402
fep 0:5ff20db10a96 2403 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
fep 0:5ff20db10a96 2404 /*----------------------------------------------------------*/
fep 0:5ff20db10a96 2405
fep 0:5ff20db10a96 2406 /* This conditional compilation should use inequality to 0, not equality to 1.
fep 0:5ff20db10a96 2407 This is to ensure vTaskStepTick() is available when user defined low power mode
fep 0:5ff20db10a96 2408 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
fep 0:5ff20db10a96 2409 1. */
fep 0:5ff20db10a96 2410 #if ( configUSE_TICKLESS_IDLE != 0 )
fep 0:5ff20db10a96 2411
fep 0:5ff20db10a96 2412 void vTaskStepTick( const TickType_t xTicksToJump )
fep 0:5ff20db10a96 2413 {
fep 0:5ff20db10a96 2414 /* Correct the tick count value after a period during which the tick
fep 0:5ff20db10a96 2415 was suppressed. Note this does *not* call the tick hook function for
fep 0:5ff20db10a96 2416 each stepped tick. */
fep 0:5ff20db10a96 2417 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
fep 0:5ff20db10a96 2418 xTickCount += xTicksToJump;
fep 0:5ff20db10a96 2419 traceINCREASE_TICK_COUNT( xTicksToJump );
fep 0:5ff20db10a96 2420 }
fep 0:5ff20db10a96 2421
fep 0:5ff20db10a96 2422 #endif /* configUSE_TICKLESS_IDLE */
fep 0:5ff20db10a96 2423 /*----------------------------------------------------------*/
fep 0:5ff20db10a96 2424
fep 0:5ff20db10a96 2425 #if ( INCLUDE_xTaskAbortDelay == 1 )
fep 0:5ff20db10a96 2426
fep 0:5ff20db10a96 2427 BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
fep 0:5ff20db10a96 2428 {
fep 0:5ff20db10a96 2429 TCB_t *pxTCB = ( TCB_t * ) xTask;
fep 0:5ff20db10a96 2430 BaseType_t xReturn = pdFALSE;
fep 0:5ff20db10a96 2431
fep 0:5ff20db10a96 2432 configASSERT( pxTCB );
fep 0:5ff20db10a96 2433
fep 0:5ff20db10a96 2434 vTaskSuspendAll();
fep 0:5ff20db10a96 2435 {
fep 0:5ff20db10a96 2436 /* A task can only be prematurely removed from the Blocked state if
fep 0:5ff20db10a96 2437 it is actually in the Blocked state. */
fep 0:5ff20db10a96 2438 if( eTaskGetState( xTask ) == eBlocked )
fep 0:5ff20db10a96 2439 {
fep 0:5ff20db10a96 2440 /* Remove the reference to the task from the blocked list. An
fep 0:5ff20db10a96 2441 interrupt won't touch the xStateListItem because the
fep 0:5ff20db10a96 2442 scheduler is suspended. */
fep 0:5ff20db10a96 2443 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 2444
fep 0:5ff20db10a96 2445 /* Is the task waiting on an event also? If so remove it from
fep 0:5ff20db10a96 2446 the event list too. Interrupts can touch the event list item,
fep 0:5ff20db10a96 2447 even though the scheduler is suspended, so a critical section
fep 0:5ff20db10a96 2448 is used. */
fep 0:5ff20db10a96 2449 taskENTER_CRITICAL();
fep 0:5ff20db10a96 2450 {
fep 0:5ff20db10a96 2451 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
fep 0:5ff20db10a96 2452 {
fep 0:5ff20db10a96 2453 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
fep 0:5ff20db10a96 2454 pxTCB->ucDelayAborted = pdTRUE;
fep 0:5ff20db10a96 2455 }
fep 0:5ff20db10a96 2456 else
fep 0:5ff20db10a96 2457 {
fep 0:5ff20db10a96 2458 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2459 }
fep 0:5ff20db10a96 2460 }
fep 0:5ff20db10a96 2461 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 2462
fep 0:5ff20db10a96 2463 /* Place the unblocked task into the appropriate ready list. */
fep 0:5ff20db10a96 2464 prvAddTaskToReadyList( pxTCB );
fep 0:5ff20db10a96 2465
fep 0:5ff20db10a96 2466 /* A task being unblocked cannot cause an immediate context
fep 0:5ff20db10a96 2467 switch if preemption is turned off. */
fep 0:5ff20db10a96 2468 #if ( configUSE_PREEMPTION == 1 )
fep 0:5ff20db10a96 2469 {
fep 0:5ff20db10a96 2470 /* Preemption is on, but a context switch should only be
fep 0:5ff20db10a96 2471 performed if the unblocked task has a priority that is
fep 0:5ff20db10a96 2472 equal to or higher than the currently executing task. */
fep 0:5ff20db10a96 2473 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
fep 0:5ff20db10a96 2474 {
fep 0:5ff20db10a96 2475 /* Pend the yield to be performed when the scheduler
fep 0:5ff20db10a96 2476 is unsuspended. */
fep 0:5ff20db10a96 2477 xYieldPending = pdTRUE;
fep 0:5ff20db10a96 2478 }
fep 0:5ff20db10a96 2479 else
fep 0:5ff20db10a96 2480 {
fep 0:5ff20db10a96 2481 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2482 }
fep 0:5ff20db10a96 2483 }
fep 0:5ff20db10a96 2484 #endif /* configUSE_PREEMPTION */
fep 0:5ff20db10a96 2485 }
fep 0:5ff20db10a96 2486 else
fep 0:5ff20db10a96 2487 {
fep 0:5ff20db10a96 2488 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2489 }
fep 0:5ff20db10a96 2490 }
fep 0:5ff20db10a96 2491 xTaskResumeAll();
fep 0:5ff20db10a96 2492
fep 0:5ff20db10a96 2493 return xReturn;
fep 0:5ff20db10a96 2494 }
fep 0:5ff20db10a96 2495
fep 0:5ff20db10a96 2496 #endif /* INCLUDE_xTaskAbortDelay */
fep 0:5ff20db10a96 2497 /*----------------------------------------------------------*/
fep 0:5ff20db10a96 2498
fep 0:5ff20db10a96 2499 BaseType_t xTaskIncrementTick( void )
fep 0:5ff20db10a96 2500 {
fep 0:5ff20db10a96 2501 TCB_t * pxTCB;
fep 0:5ff20db10a96 2502 TickType_t xItemValue;
fep 0:5ff20db10a96 2503 BaseType_t xSwitchRequired = pdFALSE;
fep 0:5ff20db10a96 2504
fep 0:5ff20db10a96 2505 /* Called by the portable layer each time a tick interrupt occurs.
fep 0:5ff20db10a96 2506 Increments the tick then checks to see if the new tick value will cause any
fep 0:5ff20db10a96 2507 tasks to be unblocked. */
fep 0:5ff20db10a96 2508 traceTASK_INCREMENT_TICK( xTickCount );
fep 0:5ff20db10a96 2509 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
fep 0:5ff20db10a96 2510 {
fep 0:5ff20db10a96 2511 /* Minor optimisation. The tick count cannot change in this
fep 0:5ff20db10a96 2512 block. */
fep 0:5ff20db10a96 2513 const TickType_t xConstTickCount = xTickCount + 1;
fep 0:5ff20db10a96 2514
fep 0:5ff20db10a96 2515 /* Increment the RTOS tick, switching the delayed and overflowed
fep 0:5ff20db10a96 2516 delayed lists if it wraps to 0. */
fep 0:5ff20db10a96 2517 xTickCount = xConstTickCount;
fep 0:5ff20db10a96 2518
fep 0:5ff20db10a96 2519 if( xConstTickCount == ( TickType_t ) 0U )
fep 0:5ff20db10a96 2520 {
fep 0:5ff20db10a96 2521 taskSWITCH_DELAYED_LISTS();
fep 0:5ff20db10a96 2522 }
fep 0:5ff20db10a96 2523 else
fep 0:5ff20db10a96 2524 {
fep 0:5ff20db10a96 2525 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2526 }
fep 0:5ff20db10a96 2527
fep 0:5ff20db10a96 2528 /* See if this tick has made a timeout expire. Tasks are stored in
fep 0:5ff20db10a96 2529 the queue in the order of their wake time - meaning once one task
fep 0:5ff20db10a96 2530 has been found whose block time has not expired there is no need to
fep 0:5ff20db10a96 2531 look any further down the list. */
fep 0:5ff20db10a96 2532 if( xConstTickCount >= xNextTaskUnblockTime )
fep 0:5ff20db10a96 2533 {
fep 0:5ff20db10a96 2534 for( ;; )
fep 0:5ff20db10a96 2535 {
fep 0:5ff20db10a96 2536 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
fep 0:5ff20db10a96 2537 {
fep 0:5ff20db10a96 2538 /* The delayed list is empty. Set xNextTaskUnblockTime
fep 0:5ff20db10a96 2539 to the maximum possible value so it is extremely
fep 0:5ff20db10a96 2540 unlikely that the
fep 0:5ff20db10a96 2541 if( xTickCount >= xNextTaskUnblockTime ) test will pass
fep 0:5ff20db10a96 2542 next time through. */
fep 0:5ff20db10a96 2543 xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
fep 0:5ff20db10a96 2544 break;
fep 0:5ff20db10a96 2545 }
fep 0:5ff20db10a96 2546 else
fep 0:5ff20db10a96 2547 {
fep 0:5ff20db10a96 2548 /* The delayed list is not empty, get the value of the
fep 0:5ff20db10a96 2549 item at the head of the delayed list. This is the time
fep 0:5ff20db10a96 2550 at which the task at the head of the delayed list must
fep 0:5ff20db10a96 2551 be removed from the Blocked state. */
fep 0:5ff20db10a96 2552 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
fep 0:5ff20db10a96 2553 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 2554
fep 0:5ff20db10a96 2555 if( xConstTickCount < xItemValue )
fep 0:5ff20db10a96 2556 {
fep 0:5ff20db10a96 2557 /* It is not time to unblock this item yet, but the
fep 0:5ff20db10a96 2558 item value is the time at which the task at the head
fep 0:5ff20db10a96 2559 of the blocked list must be removed from the Blocked
fep 0:5ff20db10a96 2560 state - so record the item value in
fep 0:5ff20db10a96 2561 xNextTaskUnblockTime. */
fep 0:5ff20db10a96 2562 xNextTaskUnblockTime = xItemValue;
fep 0:5ff20db10a96 2563 break;
fep 0:5ff20db10a96 2564 }
fep 0:5ff20db10a96 2565 else
fep 0:5ff20db10a96 2566 {
fep 0:5ff20db10a96 2567 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2568 }
fep 0:5ff20db10a96 2569
fep 0:5ff20db10a96 2570 /* It is time to remove the item from the Blocked state. */
fep 0:5ff20db10a96 2571 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 2572
fep 0:5ff20db10a96 2573 /* Is the task waiting on an event also? If so remove
fep 0:5ff20db10a96 2574 it from the event list. */
fep 0:5ff20db10a96 2575 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
fep 0:5ff20db10a96 2576 {
fep 0:5ff20db10a96 2577 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
fep 0:5ff20db10a96 2578 }
fep 0:5ff20db10a96 2579 else
fep 0:5ff20db10a96 2580 {
fep 0:5ff20db10a96 2581 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2582 }
fep 0:5ff20db10a96 2583
fep 0:5ff20db10a96 2584 /* Place the unblocked task into the appropriate ready
fep 0:5ff20db10a96 2585 list. */
fep 0:5ff20db10a96 2586 prvAddTaskToReadyList( pxTCB );
fep 0:5ff20db10a96 2587
fep 0:5ff20db10a96 2588 /* A task being unblocked cannot cause an immediate
fep 0:5ff20db10a96 2589 context switch if preemption is turned off. */
fep 0:5ff20db10a96 2590 #if ( configUSE_PREEMPTION == 1 )
fep 0:5ff20db10a96 2591 {
fep 0:5ff20db10a96 2592 /* Preemption is on, but a context switch should
fep 0:5ff20db10a96 2593 only be performed if the unblocked task has a
fep 0:5ff20db10a96 2594 priority that is equal to or higher than the
fep 0:5ff20db10a96 2595 currently executing task. */
fep 0:5ff20db10a96 2596 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
fep 0:5ff20db10a96 2597 {
fep 0:5ff20db10a96 2598 xSwitchRequired = pdTRUE;
fep 0:5ff20db10a96 2599 }
fep 0:5ff20db10a96 2600 else
fep 0:5ff20db10a96 2601 {
fep 0:5ff20db10a96 2602 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2603 }
fep 0:5ff20db10a96 2604 }
fep 0:5ff20db10a96 2605 #endif /* configUSE_PREEMPTION */
fep 0:5ff20db10a96 2606 }
fep 0:5ff20db10a96 2607 }
fep 0:5ff20db10a96 2608 }
fep 0:5ff20db10a96 2609
fep 0:5ff20db10a96 2610 /* Tasks of equal priority to the currently running task will share
fep 0:5ff20db10a96 2611 processing time (time slice) if preemption is on, and the application
fep 0:5ff20db10a96 2612 writer has not explicitly turned time slicing off. */
fep 0:5ff20db10a96 2613 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
fep 0:5ff20db10a96 2614 {
fep 0:5ff20db10a96 2615 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
fep 0:5ff20db10a96 2616 {
fep 0:5ff20db10a96 2617 xSwitchRequired = pdTRUE;
fep 0:5ff20db10a96 2618 }
fep 0:5ff20db10a96 2619 else
fep 0:5ff20db10a96 2620 {
fep 0:5ff20db10a96 2621 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2622 }
fep 0:5ff20db10a96 2623 }
fep 0:5ff20db10a96 2624 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
fep 0:5ff20db10a96 2625
fep 0:5ff20db10a96 2626 #if ( configUSE_TICK_HOOK == 1 )
fep 0:5ff20db10a96 2627 {
fep 0:5ff20db10a96 2628 /* Guard against the tick hook being called when the pended tick
fep 0:5ff20db10a96 2629 count is being unwound (when the scheduler is being unlocked). */
fep 0:5ff20db10a96 2630 if( uxPendedTicks == ( UBaseType_t ) 0U )
fep 0:5ff20db10a96 2631 {
fep 0:5ff20db10a96 2632 vApplicationTickHook();
fep 0:5ff20db10a96 2633 }
fep 0:5ff20db10a96 2634 else
fep 0:5ff20db10a96 2635 {
fep 0:5ff20db10a96 2636 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2637 }
fep 0:5ff20db10a96 2638 }
fep 0:5ff20db10a96 2639 #endif /* configUSE_TICK_HOOK */
fep 0:5ff20db10a96 2640 }
fep 0:5ff20db10a96 2641 else
fep 0:5ff20db10a96 2642 {
fep 0:5ff20db10a96 2643 ++uxPendedTicks;
fep 0:5ff20db10a96 2644
fep 0:5ff20db10a96 2645 /* The tick hook gets called at regular intervals, even if the
fep 0:5ff20db10a96 2646 scheduler is locked. */
fep 0:5ff20db10a96 2647 #if ( configUSE_TICK_HOOK == 1 )
fep 0:5ff20db10a96 2648 {
fep 0:5ff20db10a96 2649 vApplicationTickHook();
fep 0:5ff20db10a96 2650 }
fep 0:5ff20db10a96 2651 #endif
fep 0:5ff20db10a96 2652 }
fep 0:5ff20db10a96 2653
fep 0:5ff20db10a96 2654 #if ( configUSE_PREEMPTION == 1 )
fep 0:5ff20db10a96 2655 {
fep 0:5ff20db10a96 2656 if( xYieldPending != pdFALSE )
fep 0:5ff20db10a96 2657 {
fep 0:5ff20db10a96 2658 xSwitchRequired = pdTRUE;
fep 0:5ff20db10a96 2659 }
fep 0:5ff20db10a96 2660 else
fep 0:5ff20db10a96 2661 {
fep 0:5ff20db10a96 2662 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2663 }
fep 0:5ff20db10a96 2664 }
fep 0:5ff20db10a96 2665 #endif /* configUSE_PREEMPTION */
fep 0:5ff20db10a96 2666
fep 0:5ff20db10a96 2667 return xSwitchRequired;
fep 0:5ff20db10a96 2668 }
fep 0:5ff20db10a96 2669 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2670
fep 0:5ff20db10a96 2671 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
fep 0:5ff20db10a96 2672
fep 0:5ff20db10a96 2673 void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction )
fep 0:5ff20db10a96 2674 {
fep 0:5ff20db10a96 2675 TCB_t *xTCB;
fep 0:5ff20db10a96 2676
fep 0:5ff20db10a96 2677 /* If xTask is NULL then it is the task hook of the calling task that is
fep 0:5ff20db10a96 2678 getting set. */
fep 0:5ff20db10a96 2679 if( xTask == NULL )
fep 0:5ff20db10a96 2680 {
fep 0:5ff20db10a96 2681 xTCB = ( TCB_t * ) pxCurrentTCB;
fep 0:5ff20db10a96 2682 }
fep 0:5ff20db10a96 2683 else
fep 0:5ff20db10a96 2684 {
fep 0:5ff20db10a96 2685 xTCB = ( TCB_t * ) xTask;
fep 0:5ff20db10a96 2686 }
fep 0:5ff20db10a96 2687
fep 0:5ff20db10a96 2688 /* Save the hook function in the TCB. A critical section is required as
fep 0:5ff20db10a96 2689 the value can be accessed from an interrupt. */
fep 0:5ff20db10a96 2690 taskENTER_CRITICAL();
fep 0:5ff20db10a96 2691 xTCB->pxTaskTag = pxHookFunction;
fep 0:5ff20db10a96 2692 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 2693 }
fep 0:5ff20db10a96 2694
fep 0:5ff20db10a96 2695 #endif /* configUSE_APPLICATION_TASK_TAG */
fep 0:5ff20db10a96 2696 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2697
fep 0:5ff20db10a96 2698 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
fep 0:5ff20db10a96 2699
fep 0:5ff20db10a96 2700 TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
fep 0:5ff20db10a96 2701 {
fep 0:5ff20db10a96 2702 TCB_t *xTCB;
fep 0:5ff20db10a96 2703 TaskHookFunction_t xReturn;
fep 0:5ff20db10a96 2704
fep 0:5ff20db10a96 2705 /* If xTask is NULL then we are setting our own task hook. */
fep 0:5ff20db10a96 2706 if( xTask == NULL )
fep 0:5ff20db10a96 2707 {
fep 0:5ff20db10a96 2708 xTCB = ( TCB_t * ) pxCurrentTCB;
fep 0:5ff20db10a96 2709 }
fep 0:5ff20db10a96 2710 else
fep 0:5ff20db10a96 2711 {
fep 0:5ff20db10a96 2712 xTCB = ( TCB_t * ) xTask;
fep 0:5ff20db10a96 2713 }
fep 0:5ff20db10a96 2714
fep 0:5ff20db10a96 2715 /* Save the hook function in the TCB. A critical section is required as
fep 0:5ff20db10a96 2716 the value can be accessed from an interrupt. */
fep 0:5ff20db10a96 2717 taskENTER_CRITICAL();
fep 0:5ff20db10a96 2718 {
fep 0:5ff20db10a96 2719 xReturn = xTCB->pxTaskTag;
fep 0:5ff20db10a96 2720 }
fep 0:5ff20db10a96 2721 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 2722
fep 0:5ff20db10a96 2723 return xReturn;
fep 0:5ff20db10a96 2724 }
fep 0:5ff20db10a96 2725
fep 0:5ff20db10a96 2726 #endif /* configUSE_APPLICATION_TASK_TAG */
fep 0:5ff20db10a96 2727 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2728
fep 0:5ff20db10a96 2729 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
fep 0:5ff20db10a96 2730
fep 0:5ff20db10a96 2731 BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )
fep 0:5ff20db10a96 2732 {
fep 0:5ff20db10a96 2733 TCB_t *xTCB;
fep 0:5ff20db10a96 2734 BaseType_t xReturn;
fep 0:5ff20db10a96 2735
fep 0:5ff20db10a96 2736 /* If xTask is NULL then we are calling our own task hook. */
fep 0:5ff20db10a96 2737 if( xTask == NULL )
fep 0:5ff20db10a96 2738 {
fep 0:5ff20db10a96 2739 xTCB = ( TCB_t * ) pxCurrentTCB;
fep 0:5ff20db10a96 2740 }
fep 0:5ff20db10a96 2741 else
fep 0:5ff20db10a96 2742 {
fep 0:5ff20db10a96 2743 xTCB = ( TCB_t * ) xTask;
fep 0:5ff20db10a96 2744 }
fep 0:5ff20db10a96 2745
fep 0:5ff20db10a96 2746 if( xTCB->pxTaskTag != NULL )
fep 0:5ff20db10a96 2747 {
fep 0:5ff20db10a96 2748 xReturn = xTCB->pxTaskTag( pvParameter );
fep 0:5ff20db10a96 2749 }
fep 0:5ff20db10a96 2750 else
fep 0:5ff20db10a96 2751 {
fep 0:5ff20db10a96 2752 xReturn = pdFAIL;
fep 0:5ff20db10a96 2753 }
fep 0:5ff20db10a96 2754
fep 0:5ff20db10a96 2755 return xReturn;
fep 0:5ff20db10a96 2756 }
fep 0:5ff20db10a96 2757
fep 0:5ff20db10a96 2758 #endif /* configUSE_APPLICATION_TASK_TAG */
fep 0:5ff20db10a96 2759 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2760
fep 0:5ff20db10a96 2761 void vTaskSwitchContext( void )
fep 0:5ff20db10a96 2762 {
fep 0:5ff20db10a96 2763 if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
fep 0:5ff20db10a96 2764 {
fep 0:5ff20db10a96 2765 /* The scheduler is currently suspended - do not allow a context
fep 0:5ff20db10a96 2766 switch. */
fep 0:5ff20db10a96 2767 xYieldPending = pdTRUE;
fep 0:5ff20db10a96 2768 }
fep 0:5ff20db10a96 2769 else
fep 0:5ff20db10a96 2770 {
fep 0:5ff20db10a96 2771 xYieldPending = pdFALSE;
fep 0:5ff20db10a96 2772 traceTASK_SWITCHED_OUT();
fep 0:5ff20db10a96 2773
fep 0:5ff20db10a96 2774 #if ( configGENERATE_RUN_TIME_STATS == 1 )
fep 0:5ff20db10a96 2775 {
fep 0:5ff20db10a96 2776 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
fep 0:5ff20db10a96 2777 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
fep 0:5ff20db10a96 2778 #else
fep 0:5ff20db10a96 2779 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
fep 0:5ff20db10a96 2780 #endif
fep 0:5ff20db10a96 2781
fep 0:5ff20db10a96 2782 /* Add the amount of time the task has been running to the
fep 0:5ff20db10a96 2783 accumulated time so far. The time the task started running was
fep 0:5ff20db10a96 2784 stored in ulTaskSwitchedInTime. Note that there is no overflow
fep 0:5ff20db10a96 2785 protection here so count values are only valid until the timer
fep 0:5ff20db10a96 2786 overflows. The guard against negative values is to protect
fep 0:5ff20db10a96 2787 against suspect run time stat counter implementations - which
fep 0:5ff20db10a96 2788 are provided by the application, not the kernel. */
fep 0:5ff20db10a96 2789 if( ulTotalRunTime > ulTaskSwitchedInTime )
fep 0:5ff20db10a96 2790 {
fep 0:5ff20db10a96 2791 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
fep 0:5ff20db10a96 2792 }
fep 0:5ff20db10a96 2793 else
fep 0:5ff20db10a96 2794 {
fep 0:5ff20db10a96 2795 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 2796 }
fep 0:5ff20db10a96 2797 ulTaskSwitchedInTime = ulTotalRunTime;
fep 0:5ff20db10a96 2798 }
fep 0:5ff20db10a96 2799 #endif /* configGENERATE_RUN_TIME_STATS */
fep 0:5ff20db10a96 2800
fep 0:5ff20db10a96 2801 /* Check for stack overflow, if configured. */
fep 0:5ff20db10a96 2802 taskCHECK_FOR_STACK_OVERFLOW();
fep 0:5ff20db10a96 2803
fep 0:5ff20db10a96 2804 /* Select a new task to run using either the generic C or port
fep 0:5ff20db10a96 2805 optimised asm code. */
fep 0:5ff20db10a96 2806 taskSELECT_HIGHEST_PRIORITY_TASK();
fep 0:5ff20db10a96 2807 traceTASK_SWITCHED_IN();
fep 0:5ff20db10a96 2808
fep 0:5ff20db10a96 2809 #if ( configUSE_NEWLIB_REENTRANT == 1 )
fep 0:5ff20db10a96 2810 {
fep 0:5ff20db10a96 2811 /* Switch Newlib's _impure_ptr variable to point to the _reent
fep 0:5ff20db10a96 2812 structure specific to this task. */
fep 0:5ff20db10a96 2813 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
fep 0:5ff20db10a96 2814 }
fep 0:5ff20db10a96 2815 #endif /* configUSE_NEWLIB_REENTRANT */
fep 0:5ff20db10a96 2816 }
fep 0:5ff20db10a96 2817 }
fep 0:5ff20db10a96 2818 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2819
fep 0:5ff20db10a96 2820 void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
fep 0:5ff20db10a96 2821 {
fep 0:5ff20db10a96 2822 configASSERT( pxEventList );
fep 0:5ff20db10a96 2823
fep 0:5ff20db10a96 2824 /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
fep 0:5ff20db10a96 2825 SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
fep 0:5ff20db10a96 2826
fep 0:5ff20db10a96 2827 /* Place the event list item of the TCB in the appropriate event list.
fep 0:5ff20db10a96 2828 This is placed in the list in priority order so the highest priority task
fep 0:5ff20db10a96 2829 is the first to be woken by the event. The queue that contains the event
fep 0:5ff20db10a96 2830 list is locked, preventing simultaneous access from interrupts. */
fep 0:5ff20db10a96 2831 vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
fep 0:5ff20db10a96 2832
fep 0:5ff20db10a96 2833 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
fep 0:5ff20db10a96 2834 }
fep 0:5ff20db10a96 2835 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2836
fep 0:5ff20db10a96 2837 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )
fep 0:5ff20db10a96 2838 {
fep 0:5ff20db10a96 2839 configASSERT( pxEventList );
fep 0:5ff20db10a96 2840
fep 0:5ff20db10a96 2841 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
fep 0:5ff20db10a96 2842 the event groups implementation. */
fep 0:5ff20db10a96 2843 configASSERT( uxSchedulerSuspended != 0 );
fep 0:5ff20db10a96 2844
fep 0:5ff20db10a96 2845 /* Store the item value in the event list item. It is safe to access the
fep 0:5ff20db10a96 2846 event list item here as interrupts won't access the event list item of a
fep 0:5ff20db10a96 2847 task that is not in the Blocked state. */
fep 0:5ff20db10a96 2848 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
fep 0:5ff20db10a96 2849
fep 0:5ff20db10a96 2850 /* Place the event list item of the TCB at the end of the appropriate event
fep 0:5ff20db10a96 2851 list. It is safe to access the event list here because it is part of an
fep 0:5ff20db10a96 2852 event group implementation - and interrupts don't access event groups
fep 0:5ff20db10a96 2853 directly (instead they access them indirectly by pending function calls to
fep 0:5ff20db10a96 2854 the task level). */
fep 0:5ff20db10a96 2855 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
fep 0:5ff20db10a96 2856
fep 0:5ff20db10a96 2857 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
fep 0:5ff20db10a96 2858 }
fep 0:5ff20db10a96 2859 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2860
fep 0:5ff20db10a96 2861 #if( configUSE_TIMERS == 1 )
fep 0:5ff20db10a96 2862
fep 0:5ff20db10a96 2863 void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )
fep 0:5ff20db10a96 2864 {
fep 0:5ff20db10a96 2865 configASSERT( pxEventList );
fep 0:5ff20db10a96 2866
fep 0:5ff20db10a96 2867 /* This function should not be called by application code hence the
fep 0:5ff20db10a96 2868 'Restricted' in its name. It is not part of the public API. It is
fep 0:5ff20db10a96 2869 designed for use by kernel code, and has special calling requirements -
fep 0:5ff20db10a96 2870 it should be called with the scheduler suspended. */
fep 0:5ff20db10a96 2871
fep 0:5ff20db10a96 2872
fep 0:5ff20db10a96 2873 /* Place the event list item of the TCB in the appropriate event list.
fep 0:5ff20db10a96 2874 In this case it is assume that this is the only task that is going to
fep 0:5ff20db10a96 2875 be waiting on this event list, so the faster vListInsertEnd() function
fep 0:5ff20db10a96 2876 can be used in place of vListInsert. */
fep 0:5ff20db10a96 2877 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
fep 0:5ff20db10a96 2878
fep 0:5ff20db10a96 2879 /* If the task should block indefinitely then set the block time to a
fep 0:5ff20db10a96 2880 value that will be recognised as an indefinite delay inside the
fep 0:5ff20db10a96 2881 prvAddCurrentTaskToDelayedList() function. */
fep 0:5ff20db10a96 2882 if( xWaitIndefinitely != pdFALSE )
fep 0:5ff20db10a96 2883 {
fep 0:5ff20db10a96 2884 xTicksToWait = portMAX_DELAY;
fep 0:5ff20db10a96 2885 }
fep 0:5ff20db10a96 2886
fep 0:5ff20db10a96 2887 traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
fep 0:5ff20db10a96 2888 prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
fep 0:5ff20db10a96 2889 }
fep 0:5ff20db10a96 2890
fep 0:5ff20db10a96 2891 #endif /* configUSE_TIMERS */
fep 0:5ff20db10a96 2892 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2893
fep 0:5ff20db10a96 2894 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
fep 0:5ff20db10a96 2895 {
fep 0:5ff20db10a96 2896 TCB_t *pxUnblockedTCB;
fep 0:5ff20db10a96 2897 BaseType_t xReturn;
fep 0:5ff20db10a96 2898
fep 0:5ff20db10a96 2899 /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
fep 0:5ff20db10a96 2900 called from a critical section within an ISR. */
fep 0:5ff20db10a96 2901
fep 0:5ff20db10a96 2902 /* The event list is sorted in priority order, so the first in the list can
fep 0:5ff20db10a96 2903 be removed as it is known to be the highest priority. Remove the TCB from
fep 0:5ff20db10a96 2904 the delayed list, and add it to the ready list.
fep 0:5ff20db10a96 2905
fep 0:5ff20db10a96 2906 If an event is for a queue that is locked then this function will never
fep 0:5ff20db10a96 2907 get called - the lock count on the queue will get modified instead. This
fep 0:5ff20db10a96 2908 means exclusive access to the event list is guaranteed here.
fep 0:5ff20db10a96 2909
fep 0:5ff20db10a96 2910 This function assumes that a check has already been made to ensure that
fep 0:5ff20db10a96 2911 pxEventList is not empty. */
fep 0:5ff20db10a96 2912 pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
fep 0:5ff20db10a96 2913 configASSERT( pxUnblockedTCB );
fep 0:5ff20db10a96 2914 ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
fep 0:5ff20db10a96 2915
fep 0:5ff20db10a96 2916 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
fep 0:5ff20db10a96 2917 {
fep 0:5ff20db10a96 2918 ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
fep 0:5ff20db10a96 2919 prvAddTaskToReadyList( pxUnblockedTCB );
fep 0:5ff20db10a96 2920 }
fep 0:5ff20db10a96 2921 else
fep 0:5ff20db10a96 2922 {
fep 0:5ff20db10a96 2923 /* The delayed and ready lists cannot be accessed, so hold this task
fep 0:5ff20db10a96 2924 pending until the scheduler is resumed. */
fep 0:5ff20db10a96 2925 vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
fep 0:5ff20db10a96 2926 }
fep 0:5ff20db10a96 2927
fep 0:5ff20db10a96 2928 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
fep 0:5ff20db10a96 2929 {
fep 0:5ff20db10a96 2930 /* Return true if the task removed from the event list has a higher
fep 0:5ff20db10a96 2931 priority than the calling task. This allows the calling task to know if
fep 0:5ff20db10a96 2932 it should force a context switch now. */
fep 0:5ff20db10a96 2933 xReturn = pdTRUE;
fep 0:5ff20db10a96 2934
fep 0:5ff20db10a96 2935 /* Mark that a yield is pending in case the user is not using the
fep 0:5ff20db10a96 2936 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
fep 0:5ff20db10a96 2937 xYieldPending = pdTRUE;
fep 0:5ff20db10a96 2938 }
fep 0:5ff20db10a96 2939 else
fep 0:5ff20db10a96 2940 {
fep 0:5ff20db10a96 2941 xReturn = pdFALSE;
fep 0:5ff20db10a96 2942 }
fep 0:5ff20db10a96 2943
fep 0:5ff20db10a96 2944 #if( configUSE_TICKLESS_IDLE != 0 )
fep 0:5ff20db10a96 2945 {
fep 0:5ff20db10a96 2946 /* If a task is blocked on a kernel object then xNextTaskUnblockTime
fep 0:5ff20db10a96 2947 might be set to the blocked task's time out time. If the task is
fep 0:5ff20db10a96 2948 unblocked for a reason other than a timeout xNextTaskUnblockTime is
fep 0:5ff20db10a96 2949 normally left unchanged, because it is automatically reset to a new
fep 0:5ff20db10a96 2950 value when the tick count equals xNextTaskUnblockTime. However if
fep 0:5ff20db10a96 2951 tickless idling is used it might be more important to enter sleep mode
fep 0:5ff20db10a96 2952 at the earliest possible time - so reset xNextTaskUnblockTime here to
fep 0:5ff20db10a96 2953 ensure it is updated at the earliest possible time. */
fep 0:5ff20db10a96 2954 prvResetNextTaskUnblockTime();
fep 0:5ff20db10a96 2955 }
fep 0:5ff20db10a96 2956 #endif
fep 0:5ff20db10a96 2957
fep 0:5ff20db10a96 2958 return xReturn;
fep 0:5ff20db10a96 2959 }
fep 0:5ff20db10a96 2960 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 2961
fep 0:5ff20db10a96 2962 BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
fep 0:5ff20db10a96 2963 {
fep 0:5ff20db10a96 2964 TCB_t *pxUnblockedTCB;
fep 0:5ff20db10a96 2965 BaseType_t xReturn;
fep 0:5ff20db10a96 2966
fep 0:5ff20db10a96 2967 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
fep 0:5ff20db10a96 2968 the event flags implementation. */
fep 0:5ff20db10a96 2969 configASSERT( uxSchedulerSuspended != pdFALSE );
fep 0:5ff20db10a96 2970
fep 0:5ff20db10a96 2971 /* Store the new item value in the event list. */
fep 0:5ff20db10a96 2972 listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
fep 0:5ff20db10a96 2973
fep 0:5ff20db10a96 2974 /* Remove the event list form the event flag. Interrupts do not access
fep 0:5ff20db10a96 2975 event flags. */
fep 0:5ff20db10a96 2976 pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem );
fep 0:5ff20db10a96 2977 configASSERT( pxUnblockedTCB );
fep 0:5ff20db10a96 2978 ( void ) uxListRemove( pxEventListItem );
fep 0:5ff20db10a96 2979
fep 0:5ff20db10a96 2980 /* Remove the task from the delayed list and add it to the ready list. The
fep 0:5ff20db10a96 2981 scheduler is suspended so interrupts will not be accessing the ready
fep 0:5ff20db10a96 2982 lists. */
fep 0:5ff20db10a96 2983 ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
fep 0:5ff20db10a96 2984 prvAddTaskToReadyList( pxUnblockedTCB );
fep 0:5ff20db10a96 2985
fep 0:5ff20db10a96 2986 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
fep 0:5ff20db10a96 2987 {
fep 0:5ff20db10a96 2988 /* Return true if the task removed from the event list has
fep 0:5ff20db10a96 2989 a higher priority than the calling task. This allows
fep 0:5ff20db10a96 2990 the calling task to know if it should force a context
fep 0:5ff20db10a96 2991 switch now. */
fep 0:5ff20db10a96 2992 xReturn = pdTRUE;
fep 0:5ff20db10a96 2993
fep 0:5ff20db10a96 2994 /* Mark that a yield is pending in case the user is not using the
fep 0:5ff20db10a96 2995 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
fep 0:5ff20db10a96 2996 xYieldPending = pdTRUE;
fep 0:5ff20db10a96 2997 }
fep 0:5ff20db10a96 2998 else
fep 0:5ff20db10a96 2999 {
fep 0:5ff20db10a96 3000 xReturn = pdFALSE;
fep 0:5ff20db10a96 3001 }
fep 0:5ff20db10a96 3002
fep 0:5ff20db10a96 3003 return xReturn;
fep 0:5ff20db10a96 3004 }
fep 0:5ff20db10a96 3005 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3006
fep 0:5ff20db10a96 3007 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
fep 0:5ff20db10a96 3008 {
fep 0:5ff20db10a96 3009 configASSERT( pxTimeOut );
fep 0:5ff20db10a96 3010 pxTimeOut->xOverflowCount = xNumOfOverflows;
fep 0:5ff20db10a96 3011 pxTimeOut->xTimeOnEntering = xTickCount;
fep 0:5ff20db10a96 3012 }
fep 0:5ff20db10a96 3013 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3014
fep 0:5ff20db10a96 3015 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait )
fep 0:5ff20db10a96 3016 {
fep 0:5ff20db10a96 3017 BaseType_t xReturn;
fep 0:5ff20db10a96 3018
fep 0:5ff20db10a96 3019 configASSERT( pxTimeOut );
fep 0:5ff20db10a96 3020 configASSERT( pxTicksToWait );
fep 0:5ff20db10a96 3021
fep 0:5ff20db10a96 3022 taskENTER_CRITICAL();
fep 0:5ff20db10a96 3023 {
fep 0:5ff20db10a96 3024 /* Minor optimisation. The tick count cannot change in this block. */
fep 0:5ff20db10a96 3025 const TickType_t xConstTickCount = xTickCount;
fep 0:5ff20db10a96 3026
fep 0:5ff20db10a96 3027 #if( INCLUDE_xTaskAbortDelay == 1 )
fep 0:5ff20db10a96 3028 if( pxCurrentTCB->ucDelayAborted != pdFALSE )
fep 0:5ff20db10a96 3029 {
fep 0:5ff20db10a96 3030 /* The delay was aborted, which is not the same as a time out,
fep 0:5ff20db10a96 3031 but has the same result. */
fep 0:5ff20db10a96 3032 pxCurrentTCB->ucDelayAborted = pdFALSE;
fep 0:5ff20db10a96 3033 xReturn = pdTRUE;
fep 0:5ff20db10a96 3034 }
fep 0:5ff20db10a96 3035 else
fep 0:5ff20db10a96 3036 #endif
fep 0:5ff20db10a96 3037
fep 0:5ff20db10a96 3038 #if ( INCLUDE_vTaskSuspend == 1 )
fep 0:5ff20db10a96 3039 if( *pxTicksToWait == portMAX_DELAY )
fep 0:5ff20db10a96 3040 {
fep 0:5ff20db10a96 3041 /* If INCLUDE_vTaskSuspend is set to 1 and the block time
fep 0:5ff20db10a96 3042 specified is the maximum block time then the task should block
fep 0:5ff20db10a96 3043 indefinitely, and therefore never time out. */
fep 0:5ff20db10a96 3044 xReturn = pdFALSE;
fep 0:5ff20db10a96 3045 }
fep 0:5ff20db10a96 3046 else
fep 0:5ff20db10a96 3047 #endif
fep 0:5ff20db10a96 3048
fep 0:5ff20db10a96 3049 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
fep 0:5ff20db10a96 3050 {
fep 0:5ff20db10a96 3051 /* The tick count is greater than the time at which
fep 0:5ff20db10a96 3052 vTaskSetTimeout() was called, but has also overflowed since
fep 0:5ff20db10a96 3053 vTaskSetTimeOut() was called. It must have wrapped all the way
fep 0:5ff20db10a96 3054 around and gone past again. This passed since vTaskSetTimeout()
fep 0:5ff20db10a96 3055 was called. */
fep 0:5ff20db10a96 3056 xReturn = pdTRUE;
fep 0:5ff20db10a96 3057 }
fep 0:5ff20db10a96 3058 else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
fep 0:5ff20db10a96 3059 {
fep 0:5ff20db10a96 3060 /* Not a genuine timeout. Adjust parameters for time remaining. */
fep 0:5ff20db10a96 3061 *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
fep 0:5ff20db10a96 3062 vTaskSetTimeOutState( pxTimeOut );
fep 0:5ff20db10a96 3063 xReturn = pdFALSE;
fep 0:5ff20db10a96 3064 }
fep 0:5ff20db10a96 3065 else
fep 0:5ff20db10a96 3066 {
fep 0:5ff20db10a96 3067 xReturn = pdTRUE;
fep 0:5ff20db10a96 3068 }
fep 0:5ff20db10a96 3069 }
fep 0:5ff20db10a96 3070 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 3071
fep 0:5ff20db10a96 3072 return xReturn;
fep 0:5ff20db10a96 3073 }
fep 0:5ff20db10a96 3074 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3075
fep 0:5ff20db10a96 3076 void vTaskMissedYield( void )
fep 0:5ff20db10a96 3077 {
fep 0:5ff20db10a96 3078 xYieldPending = pdTRUE;
fep 0:5ff20db10a96 3079 }
fep 0:5ff20db10a96 3080 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3081
fep 0:5ff20db10a96 3082 #if ( configUSE_TRACE_FACILITY == 1 )
fep 0:5ff20db10a96 3083
fep 0:5ff20db10a96 3084 UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
fep 0:5ff20db10a96 3085 {
fep 0:5ff20db10a96 3086 UBaseType_t uxReturn;
fep 0:5ff20db10a96 3087 TCB_t *pxTCB;
fep 0:5ff20db10a96 3088
fep 0:5ff20db10a96 3089 if( xTask != NULL )
fep 0:5ff20db10a96 3090 {
fep 0:5ff20db10a96 3091 pxTCB = ( TCB_t * ) xTask;
fep 0:5ff20db10a96 3092 uxReturn = pxTCB->uxTaskNumber;
fep 0:5ff20db10a96 3093 }
fep 0:5ff20db10a96 3094 else
fep 0:5ff20db10a96 3095 {
fep 0:5ff20db10a96 3096 uxReturn = 0U;
fep 0:5ff20db10a96 3097 }
fep 0:5ff20db10a96 3098
fep 0:5ff20db10a96 3099 return uxReturn;
fep 0:5ff20db10a96 3100 }
fep 0:5ff20db10a96 3101
fep 0:5ff20db10a96 3102 #endif /* configUSE_TRACE_FACILITY */
fep 0:5ff20db10a96 3103 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3104
fep 0:5ff20db10a96 3105 #if ( configUSE_TRACE_FACILITY == 1 )
fep 0:5ff20db10a96 3106
fep 0:5ff20db10a96 3107 void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle )
fep 0:5ff20db10a96 3108 {
fep 0:5ff20db10a96 3109 TCB_t *pxTCB;
fep 0:5ff20db10a96 3110
fep 0:5ff20db10a96 3111 if( xTask != NULL )
fep 0:5ff20db10a96 3112 {
fep 0:5ff20db10a96 3113 pxTCB = ( TCB_t * ) xTask;
fep 0:5ff20db10a96 3114 pxTCB->uxTaskNumber = uxHandle;
fep 0:5ff20db10a96 3115 }
fep 0:5ff20db10a96 3116 }
fep 0:5ff20db10a96 3117
fep 0:5ff20db10a96 3118 #endif /* configUSE_TRACE_FACILITY */
fep 0:5ff20db10a96 3119
fep 0:5ff20db10a96 3120 /*
fep 0:5ff20db10a96 3121 * -----------------------------------------------------------
fep 0:5ff20db10a96 3122 * The Idle task.
fep 0:5ff20db10a96 3123 * ----------------------------------------------------------
fep 0:5ff20db10a96 3124 *
fep 0:5ff20db10a96 3125 * The portTASK_FUNCTION() macro is used to allow port/compiler specific
fep 0:5ff20db10a96 3126 * language extensions. The equivalent prototype for this function is:
fep 0:5ff20db10a96 3127 *
fep 0:5ff20db10a96 3128 * void prvIdleTask( void *pvParameters );
fep 0:5ff20db10a96 3129 *
fep 0:5ff20db10a96 3130 */
fep 0:5ff20db10a96 3131 static portTASK_FUNCTION( prvIdleTask, pvParameters )
fep 0:5ff20db10a96 3132 {
fep 0:5ff20db10a96 3133 /* Stop warnings. */
fep 0:5ff20db10a96 3134 ( void ) pvParameters;
fep 0:5ff20db10a96 3135
fep 0:5ff20db10a96 3136 /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
fep 0:5ff20db10a96 3137 SCHEDULER IS STARTED. **/
fep 0:5ff20db10a96 3138
fep 0:5ff20db10a96 3139 for( ;; )
fep 0:5ff20db10a96 3140 {
fep 0:5ff20db10a96 3141 /* See if any tasks have deleted themselves - if so then the idle task
fep 0:5ff20db10a96 3142 is responsible for freeing the deleted task's TCB and stack. */
fep 0:5ff20db10a96 3143 prvCheckTasksWaitingTermination();
fep 0:5ff20db10a96 3144
fep 0:5ff20db10a96 3145 #if ( configUSE_PREEMPTION == 0 )
fep 0:5ff20db10a96 3146 {
fep 0:5ff20db10a96 3147 /* If we are not using preemption we keep forcing a task switch to
fep 0:5ff20db10a96 3148 see if any other task has become available. If we are using
fep 0:5ff20db10a96 3149 preemption we don't need to do this as any task becoming available
fep 0:5ff20db10a96 3150 will automatically get the processor anyway. */
fep 0:5ff20db10a96 3151 taskYIELD();
fep 0:5ff20db10a96 3152 }
fep 0:5ff20db10a96 3153 #endif /* configUSE_PREEMPTION */
fep 0:5ff20db10a96 3154
fep 0:5ff20db10a96 3155 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
fep 0:5ff20db10a96 3156 {
fep 0:5ff20db10a96 3157 /* When using preemption tasks of equal priority will be
fep 0:5ff20db10a96 3158 timesliced. If a task that is sharing the idle priority is ready
fep 0:5ff20db10a96 3159 to run then the idle task should yield before the end of the
fep 0:5ff20db10a96 3160 timeslice.
fep 0:5ff20db10a96 3161
fep 0:5ff20db10a96 3162 A critical region is not required here as we are just reading from
fep 0:5ff20db10a96 3163 the list, and an occasional incorrect value will not matter. If
fep 0:5ff20db10a96 3164 the ready list at the idle priority contains more than one task
fep 0:5ff20db10a96 3165 then a task other than the idle task is ready to execute. */
fep 0:5ff20db10a96 3166 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
fep 0:5ff20db10a96 3167 {
fep 0:5ff20db10a96 3168 taskYIELD();
fep 0:5ff20db10a96 3169 }
fep 0:5ff20db10a96 3170 else
fep 0:5ff20db10a96 3171 {
fep 0:5ff20db10a96 3172 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3173 }
fep 0:5ff20db10a96 3174 }
fep 0:5ff20db10a96 3175 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
fep 0:5ff20db10a96 3176
fep 0:5ff20db10a96 3177 #if ( configUSE_IDLE_HOOK == 1 )
fep 0:5ff20db10a96 3178 {
fep 0:5ff20db10a96 3179 extern void vApplicationIdleHook( void );
fep 0:5ff20db10a96 3180
fep 0:5ff20db10a96 3181 /* Call the user defined function from within the idle task. This
fep 0:5ff20db10a96 3182 allows the application designer to add background functionality
fep 0:5ff20db10a96 3183 without the overhead of a separate task.
fep 0:5ff20db10a96 3184 NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
fep 0:5ff20db10a96 3185 CALL A FUNCTION THAT MIGHT BLOCK. */
fep 0:5ff20db10a96 3186 vApplicationIdleHook();
fep 0:5ff20db10a96 3187 }
fep 0:5ff20db10a96 3188 #endif /* configUSE_IDLE_HOOK */
fep 0:5ff20db10a96 3189
fep 0:5ff20db10a96 3190 /* This conditional compilation should use inequality to 0, not equality
fep 0:5ff20db10a96 3191 to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
fep 0:5ff20db10a96 3192 user defined low power mode implementations require
fep 0:5ff20db10a96 3193 configUSE_TICKLESS_IDLE to be set to a value other than 1. */
fep 0:5ff20db10a96 3194 #if ( configUSE_TICKLESS_IDLE != 0 )
fep 0:5ff20db10a96 3195 {
fep 0:5ff20db10a96 3196 TickType_t xExpectedIdleTime;
fep 0:5ff20db10a96 3197
fep 0:5ff20db10a96 3198 /* It is not desirable to suspend then resume the scheduler on
fep 0:5ff20db10a96 3199 each iteration of the idle task. Therefore, a preliminary
fep 0:5ff20db10a96 3200 test of the expected idle time is performed without the
fep 0:5ff20db10a96 3201 scheduler suspended. The result here is not necessarily
fep 0:5ff20db10a96 3202 valid. */
fep 0:5ff20db10a96 3203 xExpectedIdleTime = prvGetExpectedIdleTime();
fep 0:5ff20db10a96 3204
fep 0:5ff20db10a96 3205 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
fep 0:5ff20db10a96 3206 {
fep 0:5ff20db10a96 3207 vTaskSuspendAll();
fep 0:5ff20db10a96 3208 {
fep 0:5ff20db10a96 3209 /* Now the scheduler is suspended, the expected idle
fep 0:5ff20db10a96 3210 time can be sampled again, and this time its value can
fep 0:5ff20db10a96 3211 be used. */
fep 0:5ff20db10a96 3212 configASSERT( xNextTaskUnblockTime >= xTickCount );
fep 0:5ff20db10a96 3213 xExpectedIdleTime = prvGetExpectedIdleTime();
fep 0:5ff20db10a96 3214
fep 0:5ff20db10a96 3215 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
fep 0:5ff20db10a96 3216 {
fep 0:5ff20db10a96 3217 traceLOW_POWER_IDLE_BEGIN();
fep 0:5ff20db10a96 3218 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
fep 0:5ff20db10a96 3219 traceLOW_POWER_IDLE_END();
fep 0:5ff20db10a96 3220 }
fep 0:5ff20db10a96 3221 else
fep 0:5ff20db10a96 3222 {
fep 0:5ff20db10a96 3223 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3224 }
fep 0:5ff20db10a96 3225 }
fep 0:5ff20db10a96 3226 ( void ) xTaskResumeAll();
fep 0:5ff20db10a96 3227 }
fep 0:5ff20db10a96 3228 else
fep 0:5ff20db10a96 3229 {
fep 0:5ff20db10a96 3230 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3231 }
fep 0:5ff20db10a96 3232 }
fep 0:5ff20db10a96 3233 #endif /* configUSE_TICKLESS_IDLE */
fep 0:5ff20db10a96 3234 }
fep 0:5ff20db10a96 3235 }
fep 0:5ff20db10a96 3236 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3237
fep 0:5ff20db10a96 3238 #if( configUSE_TICKLESS_IDLE != 0 )
fep 0:5ff20db10a96 3239
fep 0:5ff20db10a96 3240 eSleepModeStatus eTaskConfirmSleepModeStatus( void )
fep 0:5ff20db10a96 3241 {
fep 0:5ff20db10a96 3242 /* The idle task exists in addition to the application tasks. */
fep 0:5ff20db10a96 3243 const UBaseType_t uxNonApplicationTasks = 1;
fep 0:5ff20db10a96 3244 eSleepModeStatus eReturn = eStandardSleep;
fep 0:5ff20db10a96 3245
fep 0:5ff20db10a96 3246 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
fep 0:5ff20db10a96 3247 {
fep 0:5ff20db10a96 3248 /* A task was made ready while the scheduler was suspended. */
fep 0:5ff20db10a96 3249 eReturn = eAbortSleep;
fep 0:5ff20db10a96 3250 }
fep 0:5ff20db10a96 3251 else if( xYieldPending != pdFALSE )
fep 0:5ff20db10a96 3252 {
fep 0:5ff20db10a96 3253 /* A yield was pended while the scheduler was suspended. */
fep 0:5ff20db10a96 3254 eReturn = eAbortSleep;
fep 0:5ff20db10a96 3255 }
fep 0:5ff20db10a96 3256 else
fep 0:5ff20db10a96 3257 {
fep 0:5ff20db10a96 3258 /* If all the tasks are in the suspended list (which might mean they
fep 0:5ff20db10a96 3259 have an infinite block time rather than actually being suspended)
fep 0:5ff20db10a96 3260 then it is safe to turn all clocks off and just wait for external
fep 0:5ff20db10a96 3261 interrupts. */
fep 0:5ff20db10a96 3262 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
fep 0:5ff20db10a96 3263 {
fep 0:5ff20db10a96 3264 eReturn = eNoTasksWaitingTimeout;
fep 0:5ff20db10a96 3265 }
fep 0:5ff20db10a96 3266 else
fep 0:5ff20db10a96 3267 {
fep 0:5ff20db10a96 3268 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3269 }
fep 0:5ff20db10a96 3270 }
fep 0:5ff20db10a96 3271
fep 0:5ff20db10a96 3272 return eReturn;
fep 0:5ff20db10a96 3273 }
fep 0:5ff20db10a96 3274
fep 0:5ff20db10a96 3275 #endif /* configUSE_TICKLESS_IDLE */
fep 0:5ff20db10a96 3276 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3277
fep 0:5ff20db10a96 3278 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
fep 0:5ff20db10a96 3279
fep 0:5ff20db10a96 3280 void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue )
fep 0:5ff20db10a96 3281 {
fep 0:5ff20db10a96 3282 TCB_t *pxTCB;
fep 0:5ff20db10a96 3283
fep 0:5ff20db10a96 3284 if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
fep 0:5ff20db10a96 3285 {
fep 0:5ff20db10a96 3286 pxTCB = prvGetTCBFromHandle( xTaskToSet );
fep 0:5ff20db10a96 3287 pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
fep 0:5ff20db10a96 3288 }
fep 0:5ff20db10a96 3289 }
fep 0:5ff20db10a96 3290
fep 0:5ff20db10a96 3291 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
fep 0:5ff20db10a96 3292 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3293
fep 0:5ff20db10a96 3294 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
fep 0:5ff20db10a96 3295
fep 0:5ff20db10a96 3296 void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex )
fep 0:5ff20db10a96 3297 {
fep 0:5ff20db10a96 3298 void *pvReturn = NULL;
fep 0:5ff20db10a96 3299 TCB_t *pxTCB;
fep 0:5ff20db10a96 3300
fep 0:5ff20db10a96 3301 if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
fep 0:5ff20db10a96 3302 {
fep 0:5ff20db10a96 3303 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
fep 0:5ff20db10a96 3304 pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];
fep 0:5ff20db10a96 3305 }
fep 0:5ff20db10a96 3306 else
fep 0:5ff20db10a96 3307 {
fep 0:5ff20db10a96 3308 pvReturn = NULL;
fep 0:5ff20db10a96 3309 }
fep 0:5ff20db10a96 3310
fep 0:5ff20db10a96 3311 return pvReturn;
fep 0:5ff20db10a96 3312 }
fep 0:5ff20db10a96 3313
fep 0:5ff20db10a96 3314 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
fep 0:5ff20db10a96 3315 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3316
fep 0:5ff20db10a96 3317 #if ( portUSING_MPU_WRAPPERS == 1 )
fep 0:5ff20db10a96 3318
fep 0:5ff20db10a96 3319 void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )
fep 0:5ff20db10a96 3320 {
fep 0:5ff20db10a96 3321 TCB_t *pxTCB;
fep 0:5ff20db10a96 3322
fep 0:5ff20db10a96 3323 /* If null is passed in here then we are modifying the MPU settings of
fep 0:5ff20db10a96 3324 the calling task. */
fep 0:5ff20db10a96 3325 pxTCB = prvGetTCBFromHandle( xTaskToModify );
fep 0:5ff20db10a96 3326
fep 0:5ff20db10a96 3327 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
fep 0:5ff20db10a96 3328 }
fep 0:5ff20db10a96 3329
fep 0:5ff20db10a96 3330 #endif /* portUSING_MPU_WRAPPERS */
fep 0:5ff20db10a96 3331 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3332
fep 0:5ff20db10a96 3333 static void prvInitialiseTaskLists( void )
fep 0:5ff20db10a96 3334 {
fep 0:5ff20db10a96 3335 UBaseType_t uxPriority;
fep 0:5ff20db10a96 3336
fep 0:5ff20db10a96 3337 for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
fep 0:5ff20db10a96 3338 {
fep 0:5ff20db10a96 3339 vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
fep 0:5ff20db10a96 3340 }
fep 0:5ff20db10a96 3341
fep 0:5ff20db10a96 3342 vListInitialise( &xDelayedTaskList1 );
fep 0:5ff20db10a96 3343 vListInitialise( &xDelayedTaskList2 );
fep 0:5ff20db10a96 3344 vListInitialise( &xPendingReadyList );
fep 0:5ff20db10a96 3345
fep 0:5ff20db10a96 3346 #if ( INCLUDE_vTaskDelete == 1 )
fep 0:5ff20db10a96 3347 {
fep 0:5ff20db10a96 3348 vListInitialise( &xTasksWaitingTermination );
fep 0:5ff20db10a96 3349 }
fep 0:5ff20db10a96 3350 #endif /* INCLUDE_vTaskDelete */
fep 0:5ff20db10a96 3351
fep 0:5ff20db10a96 3352 #if ( INCLUDE_vTaskSuspend == 1 )
fep 0:5ff20db10a96 3353 {
fep 0:5ff20db10a96 3354 vListInitialise( &xSuspendedTaskList );
fep 0:5ff20db10a96 3355 }
fep 0:5ff20db10a96 3356 #endif /* INCLUDE_vTaskSuspend */
fep 0:5ff20db10a96 3357
fep 0:5ff20db10a96 3358 /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
fep 0:5ff20db10a96 3359 using list2. */
fep 0:5ff20db10a96 3360 pxDelayedTaskList = &xDelayedTaskList1;
fep 0:5ff20db10a96 3361 pxOverflowDelayedTaskList = &xDelayedTaskList2;
fep 0:5ff20db10a96 3362 }
fep 0:5ff20db10a96 3363 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3364
fep 0:5ff20db10a96 3365 static void prvCheckTasksWaitingTermination( void )
fep 0:5ff20db10a96 3366 {
fep 0:5ff20db10a96 3367
fep 0:5ff20db10a96 3368 /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
fep 0:5ff20db10a96 3369
fep 0:5ff20db10a96 3370 #if ( INCLUDE_vTaskDelete == 1 )
fep 0:5ff20db10a96 3371 {
fep 0:5ff20db10a96 3372 BaseType_t xListIsEmpty;
fep 0:5ff20db10a96 3373
fep 0:5ff20db10a96 3374 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
fep 0:5ff20db10a96 3375 too often in the idle task. */
fep 0:5ff20db10a96 3376 while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
fep 0:5ff20db10a96 3377 {
fep 0:5ff20db10a96 3378 vTaskSuspendAll();
fep 0:5ff20db10a96 3379 {
fep 0:5ff20db10a96 3380 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
fep 0:5ff20db10a96 3381 }
fep 0:5ff20db10a96 3382 ( void ) xTaskResumeAll();
fep 0:5ff20db10a96 3383
fep 0:5ff20db10a96 3384 if( xListIsEmpty == pdFALSE )
fep 0:5ff20db10a96 3385 {
fep 0:5ff20db10a96 3386 TCB_t *pxTCB;
fep 0:5ff20db10a96 3387
fep 0:5ff20db10a96 3388 taskENTER_CRITICAL();
fep 0:5ff20db10a96 3389 {
fep 0:5ff20db10a96 3390 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
fep 0:5ff20db10a96 3391 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 3392 --uxCurrentNumberOfTasks;
fep 0:5ff20db10a96 3393 --uxDeletedTasksWaitingCleanUp;
fep 0:5ff20db10a96 3394 }
fep 0:5ff20db10a96 3395 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 3396
fep 0:5ff20db10a96 3397 prvDeleteTCB( pxTCB );
fep 0:5ff20db10a96 3398 }
fep 0:5ff20db10a96 3399 else
fep 0:5ff20db10a96 3400 {
fep 0:5ff20db10a96 3401 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3402 }
fep 0:5ff20db10a96 3403 }
fep 0:5ff20db10a96 3404 }
fep 0:5ff20db10a96 3405 #endif /* INCLUDE_vTaskDelete */
fep 0:5ff20db10a96 3406 }
fep 0:5ff20db10a96 3407 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3408
fep 0:5ff20db10a96 3409 #if( configUSE_TRACE_FACILITY == 1 )
fep 0:5ff20db10a96 3410
fep 0:5ff20db10a96 3411 void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState )
fep 0:5ff20db10a96 3412 {
fep 0:5ff20db10a96 3413 TCB_t *pxTCB;
fep 0:5ff20db10a96 3414
fep 0:5ff20db10a96 3415 /* xTask is NULL then get the state of the calling task. */
fep 0:5ff20db10a96 3416 pxTCB = prvGetTCBFromHandle( xTask );
fep 0:5ff20db10a96 3417
fep 0:5ff20db10a96 3418 pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB;
fep 0:5ff20db10a96 3419 pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName [ 0 ] );
fep 0:5ff20db10a96 3420 pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;
fep 0:5ff20db10a96 3421 pxTaskStatus->pxStackBase = pxTCB->pxStack;
fep 0:5ff20db10a96 3422 pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
fep 0:5ff20db10a96 3423
fep 0:5ff20db10a96 3424 #if ( INCLUDE_vTaskSuspend == 1 )
fep 0:5ff20db10a96 3425 {
fep 0:5ff20db10a96 3426 /* If the task is in the suspended list then there is a chance it is
fep 0:5ff20db10a96 3427 actually just blocked indefinitely - so really it should be reported as
fep 0:5ff20db10a96 3428 being in the Blocked state. */
fep 0:5ff20db10a96 3429 if( pxTaskStatus->eCurrentState == eSuspended )
fep 0:5ff20db10a96 3430 {
fep 0:5ff20db10a96 3431 vTaskSuspendAll();
fep 0:5ff20db10a96 3432 {
fep 0:5ff20db10a96 3433 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
fep 0:5ff20db10a96 3434 {
fep 0:5ff20db10a96 3435 pxTaskStatus->eCurrentState = eBlocked;
fep 0:5ff20db10a96 3436 }
fep 0:5ff20db10a96 3437 }
fep 0:5ff20db10a96 3438 xTaskResumeAll();
fep 0:5ff20db10a96 3439 }
fep 0:5ff20db10a96 3440 }
fep 0:5ff20db10a96 3441 #endif /* INCLUDE_vTaskSuspend */
fep 0:5ff20db10a96 3442
fep 0:5ff20db10a96 3443 #if ( configUSE_MUTEXES == 1 )
fep 0:5ff20db10a96 3444 {
fep 0:5ff20db10a96 3445 pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
fep 0:5ff20db10a96 3446 }
fep 0:5ff20db10a96 3447 #else
fep 0:5ff20db10a96 3448 {
fep 0:5ff20db10a96 3449 pxTaskStatus->uxBasePriority = 0;
fep 0:5ff20db10a96 3450 }
fep 0:5ff20db10a96 3451 #endif
fep 0:5ff20db10a96 3452
fep 0:5ff20db10a96 3453 #if ( configGENERATE_RUN_TIME_STATS == 1 )
fep 0:5ff20db10a96 3454 {
fep 0:5ff20db10a96 3455 pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
fep 0:5ff20db10a96 3456 }
fep 0:5ff20db10a96 3457 #else
fep 0:5ff20db10a96 3458 {
fep 0:5ff20db10a96 3459 pxTaskStatus->ulRunTimeCounter = 0;
fep 0:5ff20db10a96 3460 }
fep 0:5ff20db10a96 3461 #endif
fep 0:5ff20db10a96 3462
fep 0:5ff20db10a96 3463 /* Obtaining the task state is a little fiddly, so is only done if the value
fep 0:5ff20db10a96 3464 of eState passed into this function is eInvalid - otherwise the state is
fep 0:5ff20db10a96 3465 just set to whatever is passed in. */
fep 0:5ff20db10a96 3466 if( eState != eInvalid )
fep 0:5ff20db10a96 3467 {
fep 0:5ff20db10a96 3468 pxTaskStatus->eCurrentState = eState;
fep 0:5ff20db10a96 3469 }
fep 0:5ff20db10a96 3470 else
fep 0:5ff20db10a96 3471 {
fep 0:5ff20db10a96 3472 pxTaskStatus->eCurrentState = eTaskGetState( xTask );
fep 0:5ff20db10a96 3473 }
fep 0:5ff20db10a96 3474
fep 0:5ff20db10a96 3475 /* Obtaining the stack space takes some time, so the xGetFreeStackSpace
fep 0:5ff20db10a96 3476 parameter is provided to allow it to be skipped. */
fep 0:5ff20db10a96 3477 if( xGetFreeStackSpace != pdFALSE )
fep 0:5ff20db10a96 3478 {
fep 0:5ff20db10a96 3479 #if ( portSTACK_GROWTH > 0 )
fep 0:5ff20db10a96 3480 {
fep 0:5ff20db10a96 3481 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
fep 0:5ff20db10a96 3482 }
fep 0:5ff20db10a96 3483 #else
fep 0:5ff20db10a96 3484 {
fep 0:5ff20db10a96 3485 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
fep 0:5ff20db10a96 3486 }
fep 0:5ff20db10a96 3487 #endif
fep 0:5ff20db10a96 3488 }
fep 0:5ff20db10a96 3489 else
fep 0:5ff20db10a96 3490 {
fep 0:5ff20db10a96 3491 pxTaskStatus->usStackHighWaterMark = 0;
fep 0:5ff20db10a96 3492 }
fep 0:5ff20db10a96 3493 }
fep 0:5ff20db10a96 3494
fep 0:5ff20db10a96 3495 #endif /* configUSE_TRACE_FACILITY */
fep 0:5ff20db10a96 3496 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3497
fep 0:5ff20db10a96 3498 #if ( configUSE_TRACE_FACILITY == 1 )
fep 0:5ff20db10a96 3499
fep 0:5ff20db10a96 3500 static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
fep 0:5ff20db10a96 3501 {
fep 0:5ff20db10a96 3502 volatile TCB_t *pxNextTCB, *pxFirstTCB;
fep 0:5ff20db10a96 3503 UBaseType_t uxTask = 0;
fep 0:5ff20db10a96 3504
fep 0:5ff20db10a96 3505 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
fep 0:5ff20db10a96 3506 {
fep 0:5ff20db10a96 3507 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
fep 0:5ff20db10a96 3508
fep 0:5ff20db10a96 3509 /* Populate an TaskStatus_t structure within the
fep 0:5ff20db10a96 3510 pxTaskStatusArray array for each task that is referenced from
fep 0:5ff20db10a96 3511 pxList. See the definition of TaskStatus_t in task.h for the
fep 0:5ff20db10a96 3512 meaning of each TaskStatus_t structure member. */
fep 0:5ff20db10a96 3513 do
fep 0:5ff20db10a96 3514 {
fep 0:5ff20db10a96 3515 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
fep 0:5ff20db10a96 3516 vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
fep 0:5ff20db10a96 3517 uxTask++;
fep 0:5ff20db10a96 3518 } while( pxNextTCB != pxFirstTCB );
fep 0:5ff20db10a96 3519 }
fep 0:5ff20db10a96 3520 else
fep 0:5ff20db10a96 3521 {
fep 0:5ff20db10a96 3522 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3523 }
fep 0:5ff20db10a96 3524
fep 0:5ff20db10a96 3525 return uxTask;
fep 0:5ff20db10a96 3526 }
fep 0:5ff20db10a96 3527
fep 0:5ff20db10a96 3528 #endif /* configUSE_TRACE_FACILITY */
fep 0:5ff20db10a96 3529 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3530
fep 0:5ff20db10a96 3531 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
fep 0:5ff20db10a96 3532
fep 0:5ff20db10a96 3533 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
fep 0:5ff20db10a96 3534 {
fep 0:5ff20db10a96 3535 uint32_t ulCount = 0U;
fep 0:5ff20db10a96 3536
fep 0:5ff20db10a96 3537 while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
fep 0:5ff20db10a96 3538 {
fep 0:5ff20db10a96 3539 pucStackByte -= portSTACK_GROWTH;
fep 0:5ff20db10a96 3540 ulCount++;
fep 0:5ff20db10a96 3541 }
fep 0:5ff20db10a96 3542
fep 0:5ff20db10a96 3543 ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
fep 0:5ff20db10a96 3544
fep 0:5ff20db10a96 3545 return ( uint16_t ) ulCount;
fep 0:5ff20db10a96 3546 }
fep 0:5ff20db10a96 3547
fep 0:5ff20db10a96 3548 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
fep 0:5ff20db10a96 3549 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3550
fep 0:5ff20db10a96 3551 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
fep 0:5ff20db10a96 3552
fep 0:5ff20db10a96 3553 UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
fep 0:5ff20db10a96 3554 {
fep 0:5ff20db10a96 3555 TCB_t *pxTCB;
fep 0:5ff20db10a96 3556 uint8_t *pucEndOfStack;
fep 0:5ff20db10a96 3557 UBaseType_t uxReturn;
fep 0:5ff20db10a96 3558
fep 0:5ff20db10a96 3559 pxTCB = prvGetTCBFromHandle( xTask );
fep 0:5ff20db10a96 3560
fep 0:5ff20db10a96 3561 #if portSTACK_GROWTH < 0
fep 0:5ff20db10a96 3562 {
fep 0:5ff20db10a96 3563 pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
fep 0:5ff20db10a96 3564 }
fep 0:5ff20db10a96 3565 #else
fep 0:5ff20db10a96 3566 {
fep 0:5ff20db10a96 3567 pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
fep 0:5ff20db10a96 3568 }
fep 0:5ff20db10a96 3569 #endif
fep 0:5ff20db10a96 3570
fep 0:5ff20db10a96 3571 uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
fep 0:5ff20db10a96 3572
fep 0:5ff20db10a96 3573 return uxReturn;
fep 0:5ff20db10a96 3574 }
fep 0:5ff20db10a96 3575
fep 0:5ff20db10a96 3576 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
fep 0:5ff20db10a96 3577 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3578
fep 0:5ff20db10a96 3579 #if ( INCLUDE_vTaskDelete == 1 )
fep 0:5ff20db10a96 3580
fep 0:5ff20db10a96 3581 static void prvDeleteTCB( TCB_t *pxTCB )
fep 0:5ff20db10a96 3582 {
fep 0:5ff20db10a96 3583 /* This call is required specifically for the TriCore port. It must be
fep 0:5ff20db10a96 3584 above the vPortFree() calls. The call is also used by ports/demos that
fep 0:5ff20db10a96 3585 want to allocate and clean RAM statically. */
fep 0:5ff20db10a96 3586 portCLEAN_UP_TCB( pxTCB );
fep 0:5ff20db10a96 3587
fep 0:5ff20db10a96 3588 /* Free up the memory allocated by the scheduler for the task. It is up
fep 0:5ff20db10a96 3589 to the task to free any memory allocated at the application level. */
fep 0:5ff20db10a96 3590 #if ( configUSE_NEWLIB_REENTRANT == 1 )
fep 0:5ff20db10a96 3591 {
fep 0:5ff20db10a96 3592 _reclaim_reent( &( pxTCB->xNewLib_reent ) );
fep 0:5ff20db10a96 3593 }
fep 0:5ff20db10a96 3594 #endif /* configUSE_NEWLIB_REENTRANT */
fep 0:5ff20db10a96 3595
fep 0:5ff20db10a96 3596 #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
fep 0:5ff20db10a96 3597 {
fep 0:5ff20db10a96 3598 /* The task can only have been allocated dynamically - free both
fep 0:5ff20db10a96 3599 the stack and TCB. */
fep 0:5ff20db10a96 3600 vPortFree( pxTCB->pxStack );
fep 0:5ff20db10a96 3601 vPortFree( pxTCB );
fep 0:5ff20db10a96 3602 }
fep 0:5ff20db10a96 3603 #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )
fep 0:5ff20db10a96 3604 {
fep 0:5ff20db10a96 3605 /* The task could have been allocated statically or dynamically, so
fep 0:5ff20db10a96 3606 check what was statically allocated before trying to free the
fep 0:5ff20db10a96 3607 memory. */
fep 0:5ff20db10a96 3608 if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
fep 0:5ff20db10a96 3609 {
fep 0:5ff20db10a96 3610 /* Both the stack and TCB were allocated dynamically, so both
fep 0:5ff20db10a96 3611 must be freed. */
fep 0:5ff20db10a96 3612 vPortFree( pxTCB->pxStack );
fep 0:5ff20db10a96 3613 vPortFree( pxTCB );
fep 0:5ff20db10a96 3614 }
fep 0:5ff20db10a96 3615 else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
fep 0:5ff20db10a96 3616 {
fep 0:5ff20db10a96 3617 /* Only the stack was statically allocated, so the TCB is the
fep 0:5ff20db10a96 3618 only memory that must be freed. */
fep 0:5ff20db10a96 3619 vPortFree( pxTCB );
fep 0:5ff20db10a96 3620 }
fep 0:5ff20db10a96 3621 else
fep 0:5ff20db10a96 3622 {
fep 0:5ff20db10a96 3623 /* Neither the stack nor the TCB were allocated dynamically, so
fep 0:5ff20db10a96 3624 nothing needs to be freed. */
fep 0:5ff20db10a96 3625 configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )
fep 0:5ff20db10a96 3626 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3627 }
fep 0:5ff20db10a96 3628 }
fep 0:5ff20db10a96 3629 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
fep 0:5ff20db10a96 3630 }
fep 0:5ff20db10a96 3631
fep 0:5ff20db10a96 3632 #endif /* INCLUDE_vTaskDelete */
fep 0:5ff20db10a96 3633 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3634
fep 0:5ff20db10a96 3635 static void prvResetNextTaskUnblockTime( void )
fep 0:5ff20db10a96 3636 {
fep 0:5ff20db10a96 3637 TCB_t *pxTCB;
fep 0:5ff20db10a96 3638
fep 0:5ff20db10a96 3639 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
fep 0:5ff20db10a96 3640 {
fep 0:5ff20db10a96 3641 /* The new current delayed list is empty. Set xNextTaskUnblockTime to
fep 0:5ff20db10a96 3642 the maximum possible value so it is extremely unlikely that the
fep 0:5ff20db10a96 3643 if( xTickCount >= xNextTaskUnblockTime ) test will pass until
fep 0:5ff20db10a96 3644 there is an item in the delayed list. */
fep 0:5ff20db10a96 3645 xNextTaskUnblockTime = portMAX_DELAY;
fep 0:5ff20db10a96 3646 }
fep 0:5ff20db10a96 3647 else
fep 0:5ff20db10a96 3648 {
fep 0:5ff20db10a96 3649 /* The new current delayed list is not empty, get the value of
fep 0:5ff20db10a96 3650 the item at the head of the delayed list. This is the time at
fep 0:5ff20db10a96 3651 which the task at the head of the delayed list should be removed
fep 0:5ff20db10a96 3652 from the Blocked state. */
fep 0:5ff20db10a96 3653 ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
fep 0:5ff20db10a96 3654 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) );
fep 0:5ff20db10a96 3655 }
fep 0:5ff20db10a96 3656 }
fep 0:5ff20db10a96 3657 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3658
fep 0:5ff20db10a96 3659 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
fep 0:5ff20db10a96 3660
fep 0:5ff20db10a96 3661 TaskHandle_t xTaskGetCurrentTaskHandle( void )
fep 0:5ff20db10a96 3662 {
fep 0:5ff20db10a96 3663 TaskHandle_t xReturn;
fep 0:5ff20db10a96 3664
fep 0:5ff20db10a96 3665 /* A critical section is not required as this is not called from
fep 0:5ff20db10a96 3666 an interrupt and the current TCB will always be the same for any
fep 0:5ff20db10a96 3667 individual execution thread. */
fep 0:5ff20db10a96 3668 xReturn = pxCurrentTCB;
fep 0:5ff20db10a96 3669
fep 0:5ff20db10a96 3670 return xReturn;
fep 0:5ff20db10a96 3671 }
fep 0:5ff20db10a96 3672
fep 0:5ff20db10a96 3673 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
fep 0:5ff20db10a96 3674 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3675
fep 0:5ff20db10a96 3676 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
fep 0:5ff20db10a96 3677
fep 0:5ff20db10a96 3678 BaseType_t xTaskGetSchedulerState( void )
fep 0:5ff20db10a96 3679 {
fep 0:5ff20db10a96 3680 BaseType_t xReturn;
fep 0:5ff20db10a96 3681
fep 0:5ff20db10a96 3682 if( xSchedulerRunning == pdFALSE )
fep 0:5ff20db10a96 3683 {
fep 0:5ff20db10a96 3684 xReturn = taskSCHEDULER_NOT_STARTED;
fep 0:5ff20db10a96 3685 }
fep 0:5ff20db10a96 3686 else
fep 0:5ff20db10a96 3687 {
fep 0:5ff20db10a96 3688 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
fep 0:5ff20db10a96 3689 {
fep 0:5ff20db10a96 3690 xReturn = taskSCHEDULER_RUNNING;
fep 0:5ff20db10a96 3691 }
fep 0:5ff20db10a96 3692 else
fep 0:5ff20db10a96 3693 {
fep 0:5ff20db10a96 3694 xReturn = taskSCHEDULER_SUSPENDED;
fep 0:5ff20db10a96 3695 }
fep 0:5ff20db10a96 3696 }
fep 0:5ff20db10a96 3697
fep 0:5ff20db10a96 3698 return xReturn;
fep 0:5ff20db10a96 3699 }
fep 0:5ff20db10a96 3700
fep 0:5ff20db10a96 3701 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
fep 0:5ff20db10a96 3702 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3703
fep 0:5ff20db10a96 3704 #if ( configUSE_MUTEXES == 1 )
fep 0:5ff20db10a96 3705
fep 0:5ff20db10a96 3706 void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
fep 0:5ff20db10a96 3707 {
fep 0:5ff20db10a96 3708 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
fep 0:5ff20db10a96 3709
fep 0:5ff20db10a96 3710 /* If the mutex was given back by an interrupt while the queue was
fep 0:5ff20db10a96 3711 locked then the mutex holder might now be NULL. */
fep 0:5ff20db10a96 3712 if( pxMutexHolder != NULL )
fep 0:5ff20db10a96 3713 {
fep 0:5ff20db10a96 3714 /* If the holder of the mutex has a priority below the priority of
fep 0:5ff20db10a96 3715 the task attempting to obtain the mutex then it will temporarily
fep 0:5ff20db10a96 3716 inherit the priority of the task attempting to obtain the mutex. */
fep 0:5ff20db10a96 3717 if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
fep 0:5ff20db10a96 3718 {
fep 0:5ff20db10a96 3719 /* Adjust the mutex holder state to account for its new
fep 0:5ff20db10a96 3720 priority. Only reset the event list item value if the value is
fep 0:5ff20db10a96 3721 not being used for anything else. */
fep 0:5ff20db10a96 3722 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
fep 0:5ff20db10a96 3723 {
fep 0:5ff20db10a96 3724 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
fep 0:5ff20db10a96 3725 }
fep 0:5ff20db10a96 3726 else
fep 0:5ff20db10a96 3727 {
fep 0:5ff20db10a96 3728 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3729 }
fep 0:5ff20db10a96 3730
fep 0:5ff20db10a96 3731 /* If the task being modified is in the ready state it will need
fep 0:5ff20db10a96 3732 to be moved into a new list. */
fep 0:5ff20db10a96 3733 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
fep 0:5ff20db10a96 3734 {
fep 0:5ff20db10a96 3735 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
fep 0:5ff20db10a96 3736 {
fep 0:5ff20db10a96 3737 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
fep 0:5ff20db10a96 3738 }
fep 0:5ff20db10a96 3739 else
fep 0:5ff20db10a96 3740 {
fep 0:5ff20db10a96 3741 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3742 }
fep 0:5ff20db10a96 3743
fep 0:5ff20db10a96 3744 /* Inherit the priority before being moved into the new list. */
fep 0:5ff20db10a96 3745 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
fep 0:5ff20db10a96 3746 prvAddTaskToReadyList( pxTCB );
fep 0:5ff20db10a96 3747 }
fep 0:5ff20db10a96 3748 else
fep 0:5ff20db10a96 3749 {
fep 0:5ff20db10a96 3750 /* Just inherit the priority. */
fep 0:5ff20db10a96 3751 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
fep 0:5ff20db10a96 3752 }
fep 0:5ff20db10a96 3753
fep 0:5ff20db10a96 3754 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
fep 0:5ff20db10a96 3755 }
fep 0:5ff20db10a96 3756 else
fep 0:5ff20db10a96 3757 {
fep 0:5ff20db10a96 3758 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3759 }
fep 0:5ff20db10a96 3760 }
fep 0:5ff20db10a96 3761 else
fep 0:5ff20db10a96 3762 {
fep 0:5ff20db10a96 3763 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3764 }
fep 0:5ff20db10a96 3765 }
fep 0:5ff20db10a96 3766
fep 0:5ff20db10a96 3767 #endif /* configUSE_MUTEXES */
fep 0:5ff20db10a96 3768 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3769
fep 0:5ff20db10a96 3770 #if ( configUSE_MUTEXES == 1 )
fep 0:5ff20db10a96 3771
fep 0:5ff20db10a96 3772 BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
fep 0:5ff20db10a96 3773 {
fep 0:5ff20db10a96 3774 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
fep 0:5ff20db10a96 3775 BaseType_t xReturn = pdFALSE;
fep 0:5ff20db10a96 3776
fep 0:5ff20db10a96 3777 if( pxMutexHolder != NULL )
fep 0:5ff20db10a96 3778 {
fep 0:5ff20db10a96 3779 /* A task can only have an inherited priority if it holds the mutex.
fep 0:5ff20db10a96 3780 If the mutex is held by a task then it cannot be given from an
fep 0:5ff20db10a96 3781 interrupt, and if a mutex is given by the holding task then it must
fep 0:5ff20db10a96 3782 be the running state task. */
fep 0:5ff20db10a96 3783 configASSERT( pxTCB == pxCurrentTCB );
fep 0:5ff20db10a96 3784
fep 0:5ff20db10a96 3785 configASSERT( pxTCB->uxMutexesHeld );
fep 0:5ff20db10a96 3786 ( pxTCB->uxMutexesHeld )--;
fep 0:5ff20db10a96 3787
fep 0:5ff20db10a96 3788 /* Has the holder of the mutex inherited the priority of another
fep 0:5ff20db10a96 3789 task? */
fep 0:5ff20db10a96 3790 if( pxTCB->uxPriority != pxTCB->uxBasePriority )
fep 0:5ff20db10a96 3791 {
fep 0:5ff20db10a96 3792 /* Only disinherit if no other mutexes are held. */
fep 0:5ff20db10a96 3793 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
fep 0:5ff20db10a96 3794 {
fep 0:5ff20db10a96 3795 /* A task can only have an inherited priority if it holds
fep 0:5ff20db10a96 3796 the mutex. If the mutex is held by a task then it cannot be
fep 0:5ff20db10a96 3797 given from an interrupt, and if a mutex is given by the
fep 0:5ff20db10a96 3798 holding task then it must be the running state task. Remove
fep 0:5ff20db10a96 3799 the holding task from the ready list. */
fep 0:5ff20db10a96 3800 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
fep 0:5ff20db10a96 3801 {
fep 0:5ff20db10a96 3802 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
fep 0:5ff20db10a96 3803 }
fep 0:5ff20db10a96 3804 else
fep 0:5ff20db10a96 3805 {
fep 0:5ff20db10a96 3806 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3807 }
fep 0:5ff20db10a96 3808
fep 0:5ff20db10a96 3809 /* Disinherit the priority before adding the task into the
fep 0:5ff20db10a96 3810 new ready list. */
fep 0:5ff20db10a96 3811 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
fep 0:5ff20db10a96 3812 pxTCB->uxPriority = pxTCB->uxBasePriority;
fep 0:5ff20db10a96 3813
fep 0:5ff20db10a96 3814 /* Reset the event list item value. It cannot be in use for
fep 0:5ff20db10a96 3815 any other purpose if this task is running, and it must be
fep 0:5ff20db10a96 3816 running to give back the mutex. */
fep 0:5ff20db10a96 3817 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
fep 0:5ff20db10a96 3818 prvAddTaskToReadyList( pxTCB );
fep 0:5ff20db10a96 3819
fep 0:5ff20db10a96 3820 /* Return true to indicate that a context switch is required.
fep 0:5ff20db10a96 3821 This is only actually required in the corner case whereby
fep 0:5ff20db10a96 3822 multiple mutexes were held and the mutexes were given back
fep 0:5ff20db10a96 3823 in an order different to that in which they were taken.
fep 0:5ff20db10a96 3824 If a context switch did not occur when the first mutex was
fep 0:5ff20db10a96 3825 returned, even if a task was waiting on it, then a context
fep 0:5ff20db10a96 3826 switch should occur when the last mutex is returned whether
fep 0:5ff20db10a96 3827 a task is waiting on it or not. */
fep 0:5ff20db10a96 3828 xReturn = pdTRUE;
fep 0:5ff20db10a96 3829 }
fep 0:5ff20db10a96 3830 else
fep 0:5ff20db10a96 3831 {
fep 0:5ff20db10a96 3832 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3833 }
fep 0:5ff20db10a96 3834 }
fep 0:5ff20db10a96 3835 else
fep 0:5ff20db10a96 3836 {
fep 0:5ff20db10a96 3837 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3838 }
fep 0:5ff20db10a96 3839 }
fep 0:5ff20db10a96 3840 else
fep 0:5ff20db10a96 3841 {
fep 0:5ff20db10a96 3842 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3843 }
fep 0:5ff20db10a96 3844
fep 0:5ff20db10a96 3845 return xReturn;
fep 0:5ff20db10a96 3846 }
fep 0:5ff20db10a96 3847
fep 0:5ff20db10a96 3848 #endif /* configUSE_MUTEXES */
fep 0:5ff20db10a96 3849 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3850
fep 0:5ff20db10a96 3851 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
fep 0:5ff20db10a96 3852
fep 0:5ff20db10a96 3853 void vTaskEnterCritical( void )
fep 0:5ff20db10a96 3854 {
fep 0:5ff20db10a96 3855 portDISABLE_INTERRUPTS();
fep 0:5ff20db10a96 3856
fep 0:5ff20db10a96 3857 if( xSchedulerRunning != pdFALSE )
fep 0:5ff20db10a96 3858 {
fep 0:5ff20db10a96 3859 ( pxCurrentTCB->uxCriticalNesting )++;
fep 0:5ff20db10a96 3860
fep 0:5ff20db10a96 3861 /* This is not the interrupt safe version of the enter critical
fep 0:5ff20db10a96 3862 function so assert() if it is being called from an interrupt
fep 0:5ff20db10a96 3863 context. Only API functions that end in "FromISR" can be used in an
fep 0:5ff20db10a96 3864 interrupt. Only assert if the critical nesting count is 1 to
fep 0:5ff20db10a96 3865 protect against recursive calls if the assert function also uses a
fep 0:5ff20db10a96 3866 critical section. */
fep 0:5ff20db10a96 3867 if( pxCurrentTCB->uxCriticalNesting == 1 )
fep 0:5ff20db10a96 3868 {
fep 0:5ff20db10a96 3869 portASSERT_IF_IN_ISR();
fep 0:5ff20db10a96 3870 }
fep 0:5ff20db10a96 3871 }
fep 0:5ff20db10a96 3872 else
fep 0:5ff20db10a96 3873 {
fep 0:5ff20db10a96 3874 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3875 }
fep 0:5ff20db10a96 3876 }
fep 0:5ff20db10a96 3877
fep 0:5ff20db10a96 3878 #endif /* portCRITICAL_NESTING_IN_TCB */
fep 0:5ff20db10a96 3879 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3880
fep 0:5ff20db10a96 3881 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
fep 0:5ff20db10a96 3882
fep 0:5ff20db10a96 3883 void vTaskExitCritical( void )
fep 0:5ff20db10a96 3884 {
fep 0:5ff20db10a96 3885 if( xSchedulerRunning != pdFALSE )
fep 0:5ff20db10a96 3886 {
fep 0:5ff20db10a96 3887 if( pxCurrentTCB->uxCriticalNesting > 0U )
fep 0:5ff20db10a96 3888 {
fep 0:5ff20db10a96 3889 ( pxCurrentTCB->uxCriticalNesting )--;
fep 0:5ff20db10a96 3890
fep 0:5ff20db10a96 3891 if( pxCurrentTCB->uxCriticalNesting == 0U )
fep 0:5ff20db10a96 3892 {
fep 0:5ff20db10a96 3893 portENABLE_INTERRUPTS();
fep 0:5ff20db10a96 3894 }
fep 0:5ff20db10a96 3895 else
fep 0:5ff20db10a96 3896 {
fep 0:5ff20db10a96 3897 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3898 }
fep 0:5ff20db10a96 3899 }
fep 0:5ff20db10a96 3900 else
fep 0:5ff20db10a96 3901 {
fep 0:5ff20db10a96 3902 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3903 }
fep 0:5ff20db10a96 3904 }
fep 0:5ff20db10a96 3905 else
fep 0:5ff20db10a96 3906 {
fep 0:5ff20db10a96 3907 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 3908 }
fep 0:5ff20db10a96 3909 }
fep 0:5ff20db10a96 3910
fep 0:5ff20db10a96 3911 #endif /* portCRITICAL_NESTING_IN_TCB */
fep 0:5ff20db10a96 3912 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3913
fep 0:5ff20db10a96 3914 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
fep 0:5ff20db10a96 3915
fep 0:5ff20db10a96 3916 static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName )
fep 0:5ff20db10a96 3917 {
fep 0:5ff20db10a96 3918 size_t x;
fep 0:5ff20db10a96 3919
fep 0:5ff20db10a96 3920 /* Start by copying the entire string. */
fep 0:5ff20db10a96 3921 strcpy( pcBuffer, pcTaskName );
fep 0:5ff20db10a96 3922
fep 0:5ff20db10a96 3923 /* Pad the end of the string with spaces to ensure columns line up when
fep 0:5ff20db10a96 3924 printed out. */
fep 0:5ff20db10a96 3925 for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ )
fep 0:5ff20db10a96 3926 {
fep 0:5ff20db10a96 3927 pcBuffer[ x ] = ' ';
fep 0:5ff20db10a96 3928 }
fep 0:5ff20db10a96 3929
fep 0:5ff20db10a96 3930 /* Terminate. */
fep 0:5ff20db10a96 3931 pcBuffer[ x ] = 0x00;
fep 0:5ff20db10a96 3932
fep 0:5ff20db10a96 3933 /* Return the new end of string. */
fep 0:5ff20db10a96 3934 return &( pcBuffer[ x ] );
fep 0:5ff20db10a96 3935 }
fep 0:5ff20db10a96 3936
fep 0:5ff20db10a96 3937 #endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
fep 0:5ff20db10a96 3938 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 3939
fep 0:5ff20db10a96 3940 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
fep 0:5ff20db10a96 3941
fep 0:5ff20db10a96 3942 void vTaskList( char * pcWriteBuffer )
fep 0:5ff20db10a96 3943 {
fep 0:5ff20db10a96 3944 TaskStatus_t *pxTaskStatusArray;
fep 0:5ff20db10a96 3945 volatile UBaseType_t uxArraySize, x;
fep 0:5ff20db10a96 3946 char cStatus;
fep 0:5ff20db10a96 3947
fep 0:5ff20db10a96 3948 /*
fep 0:5ff20db10a96 3949 * PLEASE NOTE:
fep 0:5ff20db10a96 3950 *
fep 0:5ff20db10a96 3951 * This function is provided for convenience only, and is used by many
fep 0:5ff20db10a96 3952 * of the demo applications. Do not consider it to be part of the
fep 0:5ff20db10a96 3953 * scheduler.
fep 0:5ff20db10a96 3954 *
fep 0:5ff20db10a96 3955 * vTaskList() calls uxTaskGetSystemState(), then formats part of the
fep 0:5ff20db10a96 3956 * uxTaskGetSystemState() output into a human readable table that
fep 0:5ff20db10a96 3957 * displays task names, states and stack usage.
fep 0:5ff20db10a96 3958 *
fep 0:5ff20db10a96 3959 * vTaskList() has a dependency on the sprintf() C library function that
fep 0:5ff20db10a96 3960 * might bloat the code size, use a lot of stack, and provide different
fep 0:5ff20db10a96 3961 * results on different platforms. An alternative, tiny, third party,
fep 0:5ff20db10a96 3962 * and limited functionality implementation of sprintf() is provided in
fep 0:5ff20db10a96 3963 * many of the FreeRTOS/Demo sub-directories in a file called
fep 0:5ff20db10a96 3964 * printf-stdarg.c (note printf-stdarg.c does not provide a full
fep 0:5ff20db10a96 3965 * snprintf() implementation!).
fep 0:5ff20db10a96 3966 *
fep 0:5ff20db10a96 3967 * It is recommended that production systems call uxTaskGetSystemState()
fep 0:5ff20db10a96 3968 * directly to get access to raw stats data, rather than indirectly
fep 0:5ff20db10a96 3969 * through a call to vTaskList().
fep 0:5ff20db10a96 3970 */
fep 0:5ff20db10a96 3971
fep 0:5ff20db10a96 3972
fep 0:5ff20db10a96 3973 /* Make sure the write buffer does not contain a string. */
fep 0:5ff20db10a96 3974 *pcWriteBuffer = 0x00;
fep 0:5ff20db10a96 3975
fep 0:5ff20db10a96 3976 /* Take a snapshot of the number of tasks in case it changes while this
fep 0:5ff20db10a96 3977 function is executing. */
fep 0:5ff20db10a96 3978 uxArraySize = uxCurrentNumberOfTasks;
fep 0:5ff20db10a96 3979
fep 0:5ff20db10a96 3980 /* Allocate an array index for each task. NOTE! if
fep 0:5ff20db10a96 3981 configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
fep 0:5ff20db10a96 3982 equate to NULL. */
fep 0:5ff20db10a96 3983 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
fep 0:5ff20db10a96 3984
fep 0:5ff20db10a96 3985 if( pxTaskStatusArray != NULL )
fep 0:5ff20db10a96 3986 {
fep 0:5ff20db10a96 3987 /* Generate the (binary) data. */
fep 0:5ff20db10a96 3988 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
fep 0:5ff20db10a96 3989
fep 0:5ff20db10a96 3990 /* Create a human readable table from the binary data. */
fep 0:5ff20db10a96 3991 for( x = 0; x < uxArraySize; x++ )
fep 0:5ff20db10a96 3992 {
fep 0:5ff20db10a96 3993 switch( pxTaskStatusArray[ x ].eCurrentState )
fep 0:5ff20db10a96 3994 {
fep 0:5ff20db10a96 3995 case eReady: cStatus = tskREADY_CHAR;
fep 0:5ff20db10a96 3996 break;
fep 0:5ff20db10a96 3997
fep 0:5ff20db10a96 3998 case eBlocked: cStatus = tskBLOCKED_CHAR;
fep 0:5ff20db10a96 3999 break;
fep 0:5ff20db10a96 4000
fep 0:5ff20db10a96 4001 case eSuspended: cStatus = tskSUSPENDED_CHAR;
fep 0:5ff20db10a96 4002 break;
fep 0:5ff20db10a96 4003
fep 0:5ff20db10a96 4004 case eDeleted: cStatus = tskDELETED_CHAR;
fep 0:5ff20db10a96 4005 break;
fep 0:5ff20db10a96 4006
fep 0:5ff20db10a96 4007 default: /* Should not get here, but it is included
fep 0:5ff20db10a96 4008 to prevent static checking errors. */
fep 0:5ff20db10a96 4009 cStatus = 0x00;
fep 0:5ff20db10a96 4010 break;
fep 0:5ff20db10a96 4011 }
fep 0:5ff20db10a96 4012
fep 0:5ff20db10a96 4013 /* Write the task name to the string, padding with spaces so it
fep 0:5ff20db10a96 4014 can be printed in tabular form more easily. */
fep 0:5ff20db10a96 4015 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
fep 0:5ff20db10a96 4016
fep 0:5ff20db10a96 4017 /* Write the rest of the string. */
fep 0:5ff20db10a96 4018 sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );
fep 0:5ff20db10a96 4019 pcWriteBuffer += strlen( pcWriteBuffer );
fep 0:5ff20db10a96 4020 }
fep 0:5ff20db10a96 4021
fep 0:5ff20db10a96 4022 /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
fep 0:5ff20db10a96 4023 is 0 then vPortFree() will be #defined to nothing. */
fep 0:5ff20db10a96 4024 vPortFree( pxTaskStatusArray );
fep 0:5ff20db10a96 4025 }
fep 0:5ff20db10a96 4026 else
fep 0:5ff20db10a96 4027 {
fep 0:5ff20db10a96 4028 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4029 }
fep 0:5ff20db10a96 4030 }
fep 0:5ff20db10a96 4031
fep 0:5ff20db10a96 4032 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
fep 0:5ff20db10a96 4033 /*----------------------------------------------------------*/
fep 0:5ff20db10a96 4034
fep 0:5ff20db10a96 4035 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
fep 0:5ff20db10a96 4036
fep 0:5ff20db10a96 4037 void vTaskGetRunTimeStats( char *pcWriteBuffer )
fep 0:5ff20db10a96 4038 {
fep 0:5ff20db10a96 4039 TaskStatus_t *pxTaskStatusArray;
fep 0:5ff20db10a96 4040 volatile UBaseType_t uxArraySize, x;
fep 0:5ff20db10a96 4041 uint32_t ulTotalTime, ulStatsAsPercentage;
fep 0:5ff20db10a96 4042
fep 0:5ff20db10a96 4043 #if( configUSE_TRACE_FACILITY != 1 )
fep 0:5ff20db10a96 4044 {
fep 0:5ff20db10a96 4045 #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
fep 0:5ff20db10a96 4046 }
fep 0:5ff20db10a96 4047 #endif
fep 0:5ff20db10a96 4048
fep 0:5ff20db10a96 4049 /*
fep 0:5ff20db10a96 4050 * PLEASE NOTE:
fep 0:5ff20db10a96 4051 *
fep 0:5ff20db10a96 4052 * This function is provided for convenience only, and is used by many
fep 0:5ff20db10a96 4053 * of the demo applications. Do not consider it to be part of the
fep 0:5ff20db10a96 4054 * scheduler.
fep 0:5ff20db10a96 4055 *
fep 0:5ff20db10a96 4056 * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
fep 0:5ff20db10a96 4057 * of the uxTaskGetSystemState() output into a human readable table that
fep 0:5ff20db10a96 4058 * displays the amount of time each task has spent in the Running state
fep 0:5ff20db10a96 4059 * in both absolute and percentage terms.
fep 0:5ff20db10a96 4060 *
fep 0:5ff20db10a96 4061 * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
fep 0:5ff20db10a96 4062 * function that might bloat the code size, use a lot of stack, and
fep 0:5ff20db10a96 4063 * provide different results on different platforms. An alternative,
fep 0:5ff20db10a96 4064 * tiny, third party, and limited functionality implementation of
fep 0:5ff20db10a96 4065 * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
fep 0:5ff20db10a96 4066 * a file called printf-stdarg.c (note printf-stdarg.c does not provide
fep 0:5ff20db10a96 4067 * a full snprintf() implementation!).
fep 0:5ff20db10a96 4068 *
fep 0:5ff20db10a96 4069 * It is recommended that production systems call uxTaskGetSystemState()
fep 0:5ff20db10a96 4070 * directly to get access to raw stats data, rather than indirectly
fep 0:5ff20db10a96 4071 * through a call to vTaskGetRunTimeStats().
fep 0:5ff20db10a96 4072 */
fep 0:5ff20db10a96 4073
fep 0:5ff20db10a96 4074 /* Make sure the write buffer does not contain a string. */
fep 0:5ff20db10a96 4075 *pcWriteBuffer = 0x00;
fep 0:5ff20db10a96 4076
fep 0:5ff20db10a96 4077 /* Take a snapshot of the number of tasks in case it changes while this
fep 0:5ff20db10a96 4078 function is executing. */
fep 0:5ff20db10a96 4079 uxArraySize = uxCurrentNumberOfTasks;
fep 0:5ff20db10a96 4080
fep 0:5ff20db10a96 4081 /* Allocate an array index for each task. NOTE! If
fep 0:5ff20db10a96 4082 configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
fep 0:5ff20db10a96 4083 equate to NULL. */
fep 0:5ff20db10a96 4084 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
fep 0:5ff20db10a96 4085
fep 0:5ff20db10a96 4086 if( pxTaskStatusArray != NULL )
fep 0:5ff20db10a96 4087 {
fep 0:5ff20db10a96 4088 /* Generate the (binary) data. */
fep 0:5ff20db10a96 4089 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
fep 0:5ff20db10a96 4090
fep 0:5ff20db10a96 4091 /* For percentage calculations. */
fep 0:5ff20db10a96 4092 ulTotalTime /= 100UL;
fep 0:5ff20db10a96 4093
fep 0:5ff20db10a96 4094 /* Avoid divide by zero errors. */
fep 0:5ff20db10a96 4095 if( ulTotalTime > 0 )
fep 0:5ff20db10a96 4096 {
fep 0:5ff20db10a96 4097 /* Create a human readable table from the binary data. */
fep 0:5ff20db10a96 4098 for( x = 0; x < uxArraySize; x++ )
fep 0:5ff20db10a96 4099 {
fep 0:5ff20db10a96 4100 /* What percentage of the total run time has the task used?
fep 0:5ff20db10a96 4101 This will always be rounded down to the nearest integer.
fep 0:5ff20db10a96 4102 ulTotalRunTimeDiv100 has already been divided by 100. */
fep 0:5ff20db10a96 4103 ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
fep 0:5ff20db10a96 4104
fep 0:5ff20db10a96 4105 /* Write the task name to the string, padding with
fep 0:5ff20db10a96 4106 spaces so it can be printed in tabular form more
fep 0:5ff20db10a96 4107 easily. */
fep 0:5ff20db10a96 4108 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
fep 0:5ff20db10a96 4109
fep 0:5ff20db10a96 4110 if( ulStatsAsPercentage > 0UL )
fep 0:5ff20db10a96 4111 {
fep 0:5ff20db10a96 4112 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
fep 0:5ff20db10a96 4113 {
fep 0:5ff20db10a96 4114 sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
fep 0:5ff20db10a96 4115 }
fep 0:5ff20db10a96 4116 #else
fep 0:5ff20db10a96 4117 {
fep 0:5ff20db10a96 4118 /* sizeof( int ) == sizeof( long ) so a smaller
fep 0:5ff20db10a96 4119 printf() library can be used. */
fep 0:5ff20db10a96 4120 sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
fep 0:5ff20db10a96 4121 }
fep 0:5ff20db10a96 4122 #endif
fep 0:5ff20db10a96 4123 }
fep 0:5ff20db10a96 4124 else
fep 0:5ff20db10a96 4125 {
fep 0:5ff20db10a96 4126 /* If the percentage is zero here then the task has
fep 0:5ff20db10a96 4127 consumed less than 1% of the total run time. */
fep 0:5ff20db10a96 4128 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
fep 0:5ff20db10a96 4129 {
fep 0:5ff20db10a96 4130 sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter );
fep 0:5ff20db10a96 4131 }
fep 0:5ff20db10a96 4132 #else
fep 0:5ff20db10a96 4133 {
fep 0:5ff20db10a96 4134 /* sizeof( int ) == sizeof( long ) so a smaller
fep 0:5ff20db10a96 4135 printf() library can be used. */
fep 0:5ff20db10a96 4136 sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
fep 0:5ff20db10a96 4137 }
fep 0:5ff20db10a96 4138 #endif
fep 0:5ff20db10a96 4139 }
fep 0:5ff20db10a96 4140
fep 0:5ff20db10a96 4141 pcWriteBuffer += strlen( pcWriteBuffer );
fep 0:5ff20db10a96 4142 }
fep 0:5ff20db10a96 4143 }
fep 0:5ff20db10a96 4144 else
fep 0:5ff20db10a96 4145 {
fep 0:5ff20db10a96 4146 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4147 }
fep 0:5ff20db10a96 4148
fep 0:5ff20db10a96 4149 /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
fep 0:5ff20db10a96 4150 is 0 then vPortFree() will be #defined to nothing. */
fep 0:5ff20db10a96 4151 vPortFree( pxTaskStatusArray );
fep 0:5ff20db10a96 4152 }
fep 0:5ff20db10a96 4153 else
fep 0:5ff20db10a96 4154 {
fep 0:5ff20db10a96 4155 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4156 }
fep 0:5ff20db10a96 4157 }
fep 0:5ff20db10a96 4158
fep 0:5ff20db10a96 4159 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
fep 0:5ff20db10a96 4160 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 4161
fep 0:5ff20db10a96 4162 TickType_t uxTaskResetEventItemValue( void )
fep 0:5ff20db10a96 4163 {
fep 0:5ff20db10a96 4164 TickType_t uxReturn;
fep 0:5ff20db10a96 4165
fep 0:5ff20db10a96 4166 uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
fep 0:5ff20db10a96 4167
fep 0:5ff20db10a96 4168 /* Reset the event list item to its normal value - so it can be used with
fep 0:5ff20db10a96 4169 queues and semaphores. */
fep 0:5ff20db10a96 4170 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
fep 0:5ff20db10a96 4171
fep 0:5ff20db10a96 4172 return uxReturn;
fep 0:5ff20db10a96 4173 }
fep 0:5ff20db10a96 4174 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 4175
fep 0:5ff20db10a96 4176 #if ( configUSE_MUTEXES == 1 )
fep 0:5ff20db10a96 4177
fep 0:5ff20db10a96 4178 void *pvTaskIncrementMutexHeldCount( void )
fep 0:5ff20db10a96 4179 {
fep 0:5ff20db10a96 4180 /* If xSemaphoreCreateMutex() is called before any tasks have been created
fep 0:5ff20db10a96 4181 then pxCurrentTCB will be NULL. */
fep 0:5ff20db10a96 4182 if( pxCurrentTCB != NULL )
fep 0:5ff20db10a96 4183 {
fep 0:5ff20db10a96 4184 ( pxCurrentTCB->uxMutexesHeld )++;
fep 0:5ff20db10a96 4185 }
fep 0:5ff20db10a96 4186
fep 0:5ff20db10a96 4187 return pxCurrentTCB;
fep 0:5ff20db10a96 4188 }
fep 0:5ff20db10a96 4189
fep 0:5ff20db10a96 4190 #endif /* configUSE_MUTEXES */
fep 0:5ff20db10a96 4191 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 4192
fep 0:5ff20db10a96 4193 #if( configUSE_TASK_NOTIFICATIONS == 1 )
fep 0:5ff20db10a96 4194
fep 0:5ff20db10a96 4195 uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
fep 0:5ff20db10a96 4196 {
fep 0:5ff20db10a96 4197 uint32_t ulReturn;
fep 0:5ff20db10a96 4198
fep 0:5ff20db10a96 4199 taskENTER_CRITICAL();
fep 0:5ff20db10a96 4200 {
fep 0:5ff20db10a96 4201 /* Only block if the notification count is not already non-zero. */
fep 0:5ff20db10a96 4202 if( pxCurrentTCB->ulNotifiedValue == 0UL )
fep 0:5ff20db10a96 4203 {
fep 0:5ff20db10a96 4204 /* Mark this task as waiting for a notification. */
fep 0:5ff20db10a96 4205 pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
fep 0:5ff20db10a96 4206
fep 0:5ff20db10a96 4207 if( xTicksToWait > ( TickType_t ) 0 )
fep 0:5ff20db10a96 4208 {
fep 0:5ff20db10a96 4209 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
fep 0:5ff20db10a96 4210 traceTASK_NOTIFY_TAKE_BLOCK();
fep 0:5ff20db10a96 4211
fep 0:5ff20db10a96 4212 /* All ports are written to allow a yield in a critical
fep 0:5ff20db10a96 4213 section (some will yield immediately, others wait until the
fep 0:5ff20db10a96 4214 critical section exits) - but it is not something that
fep 0:5ff20db10a96 4215 application code should ever do. */
fep 0:5ff20db10a96 4216 portYIELD_WITHIN_API();
fep 0:5ff20db10a96 4217 }
fep 0:5ff20db10a96 4218 else
fep 0:5ff20db10a96 4219 {
fep 0:5ff20db10a96 4220 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4221 }
fep 0:5ff20db10a96 4222 }
fep 0:5ff20db10a96 4223 else
fep 0:5ff20db10a96 4224 {
fep 0:5ff20db10a96 4225 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4226 }
fep 0:5ff20db10a96 4227 }
fep 0:5ff20db10a96 4228 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 4229
fep 0:5ff20db10a96 4230 taskENTER_CRITICAL();
fep 0:5ff20db10a96 4231 {
fep 0:5ff20db10a96 4232 traceTASK_NOTIFY_TAKE();
fep 0:5ff20db10a96 4233 ulReturn = pxCurrentTCB->ulNotifiedValue;
fep 0:5ff20db10a96 4234
fep 0:5ff20db10a96 4235 if( ulReturn != 0UL )
fep 0:5ff20db10a96 4236 {
fep 0:5ff20db10a96 4237 if( xClearCountOnExit != pdFALSE )
fep 0:5ff20db10a96 4238 {
fep 0:5ff20db10a96 4239 pxCurrentTCB->ulNotifiedValue = 0UL;
fep 0:5ff20db10a96 4240 }
fep 0:5ff20db10a96 4241 else
fep 0:5ff20db10a96 4242 {
fep 0:5ff20db10a96 4243 pxCurrentTCB->ulNotifiedValue = ulReturn - 1;
fep 0:5ff20db10a96 4244 }
fep 0:5ff20db10a96 4245 }
fep 0:5ff20db10a96 4246 else
fep 0:5ff20db10a96 4247 {
fep 0:5ff20db10a96 4248 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4249 }
fep 0:5ff20db10a96 4250
fep 0:5ff20db10a96 4251 pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
fep 0:5ff20db10a96 4252 }
fep 0:5ff20db10a96 4253 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 4254
fep 0:5ff20db10a96 4255 return ulReturn;
fep 0:5ff20db10a96 4256 }
fep 0:5ff20db10a96 4257
fep 0:5ff20db10a96 4258 #endif /* configUSE_TASK_NOTIFICATIONS */
fep 0:5ff20db10a96 4259 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 4260
fep 0:5ff20db10a96 4261 #if( configUSE_TASK_NOTIFICATIONS == 1 )
fep 0:5ff20db10a96 4262
fep 0:5ff20db10a96 4263 BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
fep 0:5ff20db10a96 4264 {
fep 0:5ff20db10a96 4265 BaseType_t xReturn;
fep 0:5ff20db10a96 4266
fep 0:5ff20db10a96 4267 taskENTER_CRITICAL();
fep 0:5ff20db10a96 4268 {
fep 0:5ff20db10a96 4269 /* Only block if a notification is not already pending. */
fep 0:5ff20db10a96 4270 if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
fep 0:5ff20db10a96 4271 {
fep 0:5ff20db10a96 4272 /* Clear bits in the task's notification value as bits may get
fep 0:5ff20db10a96 4273 set by the notifying task or interrupt. This can be used to
fep 0:5ff20db10a96 4274 clear the value to zero. */
fep 0:5ff20db10a96 4275 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;
fep 0:5ff20db10a96 4276
fep 0:5ff20db10a96 4277 /* Mark this task as waiting for a notification. */
fep 0:5ff20db10a96 4278 pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
fep 0:5ff20db10a96 4279
fep 0:5ff20db10a96 4280 if( xTicksToWait > ( TickType_t ) 0 )
fep 0:5ff20db10a96 4281 {
fep 0:5ff20db10a96 4282 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
fep 0:5ff20db10a96 4283 traceTASK_NOTIFY_WAIT_BLOCK();
fep 0:5ff20db10a96 4284
fep 0:5ff20db10a96 4285 /* All ports are written to allow a yield in a critical
fep 0:5ff20db10a96 4286 section (some will yield immediately, others wait until the
fep 0:5ff20db10a96 4287 critical section exits) - but it is not something that
fep 0:5ff20db10a96 4288 application code should ever do. */
fep 0:5ff20db10a96 4289 portYIELD_WITHIN_API();
fep 0:5ff20db10a96 4290 }
fep 0:5ff20db10a96 4291 else
fep 0:5ff20db10a96 4292 {
fep 0:5ff20db10a96 4293 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4294 }
fep 0:5ff20db10a96 4295 }
fep 0:5ff20db10a96 4296 else
fep 0:5ff20db10a96 4297 {
fep 0:5ff20db10a96 4298 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4299 }
fep 0:5ff20db10a96 4300 }
fep 0:5ff20db10a96 4301 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 4302
fep 0:5ff20db10a96 4303 taskENTER_CRITICAL();
fep 0:5ff20db10a96 4304 {
fep 0:5ff20db10a96 4305 traceTASK_NOTIFY_WAIT();
fep 0:5ff20db10a96 4306
fep 0:5ff20db10a96 4307 if( pulNotificationValue != NULL )
fep 0:5ff20db10a96 4308 {
fep 0:5ff20db10a96 4309 /* Output the current notification value, which may or may not
fep 0:5ff20db10a96 4310 have changed. */
fep 0:5ff20db10a96 4311 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
fep 0:5ff20db10a96 4312 }
fep 0:5ff20db10a96 4313
fep 0:5ff20db10a96 4314 /* If ucNotifyValue is set then either the task never entered the
fep 0:5ff20db10a96 4315 blocked state (because a notification was already pending) or the
fep 0:5ff20db10a96 4316 task unblocked because of a notification. Otherwise the task
fep 0:5ff20db10a96 4317 unblocked because of a timeout. */
fep 0:5ff20db10a96 4318 if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION )
fep 0:5ff20db10a96 4319 {
fep 0:5ff20db10a96 4320 /* A notification was not received. */
fep 0:5ff20db10a96 4321 xReturn = pdFALSE;
fep 0:5ff20db10a96 4322 }
fep 0:5ff20db10a96 4323 else
fep 0:5ff20db10a96 4324 {
fep 0:5ff20db10a96 4325 /* A notification was already pending or a notification was
fep 0:5ff20db10a96 4326 received while the task was waiting. */
fep 0:5ff20db10a96 4327 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;
fep 0:5ff20db10a96 4328 xReturn = pdTRUE;
fep 0:5ff20db10a96 4329 }
fep 0:5ff20db10a96 4330
fep 0:5ff20db10a96 4331 pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
fep 0:5ff20db10a96 4332 }
fep 0:5ff20db10a96 4333 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 4334
fep 0:5ff20db10a96 4335 return xReturn;
fep 0:5ff20db10a96 4336 }
fep 0:5ff20db10a96 4337
fep 0:5ff20db10a96 4338 #endif /* configUSE_TASK_NOTIFICATIONS */
fep 0:5ff20db10a96 4339 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 4340
fep 0:5ff20db10a96 4341 #if( configUSE_TASK_NOTIFICATIONS == 1 )
fep 0:5ff20db10a96 4342
fep 0:5ff20db10a96 4343 BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
fep 0:5ff20db10a96 4344 {
fep 0:5ff20db10a96 4345 TCB_t * pxTCB;
fep 0:5ff20db10a96 4346 BaseType_t xReturn = pdPASS;
fep 0:5ff20db10a96 4347 uint8_t ucOriginalNotifyState;
fep 0:5ff20db10a96 4348
fep 0:5ff20db10a96 4349 configASSERT( xTaskToNotify );
fep 0:5ff20db10a96 4350 pxTCB = ( TCB_t * ) xTaskToNotify;
fep 0:5ff20db10a96 4351
fep 0:5ff20db10a96 4352 taskENTER_CRITICAL();
fep 0:5ff20db10a96 4353 {
fep 0:5ff20db10a96 4354 if( pulPreviousNotificationValue != NULL )
fep 0:5ff20db10a96 4355 {
fep 0:5ff20db10a96 4356 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
fep 0:5ff20db10a96 4357 }
fep 0:5ff20db10a96 4358
fep 0:5ff20db10a96 4359 ucOriginalNotifyState = pxTCB->ucNotifyState;
fep 0:5ff20db10a96 4360
fep 0:5ff20db10a96 4361 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
fep 0:5ff20db10a96 4362
fep 0:5ff20db10a96 4363 switch( eAction )
fep 0:5ff20db10a96 4364 {
fep 0:5ff20db10a96 4365 case eSetBits :
fep 0:5ff20db10a96 4366 pxTCB->ulNotifiedValue |= ulValue;
fep 0:5ff20db10a96 4367 break;
fep 0:5ff20db10a96 4368
fep 0:5ff20db10a96 4369 case eIncrement :
fep 0:5ff20db10a96 4370 ( pxTCB->ulNotifiedValue )++;
fep 0:5ff20db10a96 4371 break;
fep 0:5ff20db10a96 4372
fep 0:5ff20db10a96 4373 case eSetValueWithOverwrite :
fep 0:5ff20db10a96 4374 pxTCB->ulNotifiedValue = ulValue;
fep 0:5ff20db10a96 4375 break;
fep 0:5ff20db10a96 4376
fep 0:5ff20db10a96 4377 case eSetValueWithoutOverwrite :
fep 0:5ff20db10a96 4378 if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
fep 0:5ff20db10a96 4379 {
fep 0:5ff20db10a96 4380 pxTCB->ulNotifiedValue = ulValue;
fep 0:5ff20db10a96 4381 }
fep 0:5ff20db10a96 4382 else
fep 0:5ff20db10a96 4383 {
fep 0:5ff20db10a96 4384 /* The value could not be written to the task. */
fep 0:5ff20db10a96 4385 xReturn = pdFAIL;
fep 0:5ff20db10a96 4386 }
fep 0:5ff20db10a96 4387 break;
fep 0:5ff20db10a96 4388
fep 0:5ff20db10a96 4389 case eNoAction:
fep 0:5ff20db10a96 4390 /* The task is being notified without its notify value being
fep 0:5ff20db10a96 4391 updated. */
fep 0:5ff20db10a96 4392 break;
fep 0:5ff20db10a96 4393 }
fep 0:5ff20db10a96 4394
fep 0:5ff20db10a96 4395 traceTASK_NOTIFY();
fep 0:5ff20db10a96 4396
fep 0:5ff20db10a96 4397 /* If the task is in the blocked state specifically to wait for a
fep 0:5ff20db10a96 4398 notification then unblock it now. */
fep 0:5ff20db10a96 4399 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
fep 0:5ff20db10a96 4400 {
fep 0:5ff20db10a96 4401 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 4402 prvAddTaskToReadyList( pxTCB );
fep 0:5ff20db10a96 4403
fep 0:5ff20db10a96 4404 /* The task should not have been on an event list. */
fep 0:5ff20db10a96 4405 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
fep 0:5ff20db10a96 4406
fep 0:5ff20db10a96 4407 #if( configUSE_TICKLESS_IDLE != 0 )
fep 0:5ff20db10a96 4408 {
fep 0:5ff20db10a96 4409 /* If a task is blocked waiting for a notification then
fep 0:5ff20db10a96 4410 xNextTaskUnblockTime might be set to the blocked task's time
fep 0:5ff20db10a96 4411 out time. If the task is unblocked for a reason other than
fep 0:5ff20db10a96 4412 a timeout xNextTaskUnblockTime is normally left unchanged,
fep 0:5ff20db10a96 4413 because it will automatically get reset to a new value when
fep 0:5ff20db10a96 4414 the tick count equals xNextTaskUnblockTime. However if
fep 0:5ff20db10a96 4415 tickless idling is used it might be more important to enter
fep 0:5ff20db10a96 4416 sleep mode at the earliest possible time - so reset
fep 0:5ff20db10a96 4417 xNextTaskUnblockTime here to ensure it is updated at the
fep 0:5ff20db10a96 4418 earliest possible time. */
fep 0:5ff20db10a96 4419 prvResetNextTaskUnblockTime();
fep 0:5ff20db10a96 4420 }
fep 0:5ff20db10a96 4421 #endif
fep 0:5ff20db10a96 4422
fep 0:5ff20db10a96 4423 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
fep 0:5ff20db10a96 4424 {
fep 0:5ff20db10a96 4425 /* The notified task has a priority above the currently
fep 0:5ff20db10a96 4426 executing task so a yield is required. */
fep 0:5ff20db10a96 4427 taskYIELD_IF_USING_PREEMPTION();
fep 0:5ff20db10a96 4428 }
fep 0:5ff20db10a96 4429 else
fep 0:5ff20db10a96 4430 {
fep 0:5ff20db10a96 4431 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4432 }
fep 0:5ff20db10a96 4433 }
fep 0:5ff20db10a96 4434 else
fep 0:5ff20db10a96 4435 {
fep 0:5ff20db10a96 4436 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4437 }
fep 0:5ff20db10a96 4438 }
fep 0:5ff20db10a96 4439 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 4440
fep 0:5ff20db10a96 4441 return xReturn;
fep 0:5ff20db10a96 4442 }
fep 0:5ff20db10a96 4443
fep 0:5ff20db10a96 4444 #endif /* configUSE_TASK_NOTIFICATIONS */
fep 0:5ff20db10a96 4445 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 4446
fep 0:5ff20db10a96 4447 #if( configUSE_TASK_NOTIFICATIONS == 1 )
fep 0:5ff20db10a96 4448
fep 0:5ff20db10a96 4449 BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )
fep 0:5ff20db10a96 4450 {
fep 0:5ff20db10a96 4451 TCB_t * pxTCB;
fep 0:5ff20db10a96 4452 uint8_t ucOriginalNotifyState;
fep 0:5ff20db10a96 4453 BaseType_t xReturn = pdPASS;
fep 0:5ff20db10a96 4454 UBaseType_t uxSavedInterruptStatus;
fep 0:5ff20db10a96 4455
fep 0:5ff20db10a96 4456 configASSERT( xTaskToNotify );
fep 0:5ff20db10a96 4457
fep 0:5ff20db10a96 4458 /* RTOS ports that support interrupt nesting have the concept of a
fep 0:5ff20db10a96 4459 maximum system call (or maximum API call) interrupt priority.
fep 0:5ff20db10a96 4460 Interrupts that are above the maximum system call priority are keep
fep 0:5ff20db10a96 4461 permanently enabled, even when the RTOS kernel is in a critical section,
fep 0:5ff20db10a96 4462 but cannot make any calls to FreeRTOS API functions. If configASSERT()
fep 0:5ff20db10a96 4463 is defined in FreeRTOSConfig.h then
fep 0:5ff20db10a96 4464 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
fep 0:5ff20db10a96 4465 failure if a FreeRTOS API function is called from an interrupt that has
fep 0:5ff20db10a96 4466 been assigned a priority above the configured maximum system call
fep 0:5ff20db10a96 4467 priority. Only FreeRTOS functions that end in FromISR can be called
fep 0:5ff20db10a96 4468 from interrupts that have been assigned a priority at or (logically)
fep 0:5ff20db10a96 4469 below the maximum system call interrupt priority. FreeRTOS maintains a
fep 0:5ff20db10a96 4470 separate interrupt safe API to ensure interrupt entry is as fast and as
fep 0:5ff20db10a96 4471 simple as possible. More information (albeit Cortex-M specific) is
fep 0:5ff20db10a96 4472 provided on the following link:
fep 0:5ff20db10a96 4473 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
fep 0:5ff20db10a96 4474 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
fep 0:5ff20db10a96 4475
fep 0:5ff20db10a96 4476 pxTCB = ( TCB_t * ) xTaskToNotify;
fep 0:5ff20db10a96 4477
fep 0:5ff20db10a96 4478 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
fep 0:5ff20db10a96 4479 {
fep 0:5ff20db10a96 4480 if( pulPreviousNotificationValue != NULL )
fep 0:5ff20db10a96 4481 {
fep 0:5ff20db10a96 4482 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
fep 0:5ff20db10a96 4483 }
fep 0:5ff20db10a96 4484
fep 0:5ff20db10a96 4485 ucOriginalNotifyState = pxTCB->ucNotifyState;
fep 0:5ff20db10a96 4486 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
fep 0:5ff20db10a96 4487
fep 0:5ff20db10a96 4488 switch( eAction )
fep 0:5ff20db10a96 4489 {
fep 0:5ff20db10a96 4490 case eSetBits :
fep 0:5ff20db10a96 4491 pxTCB->ulNotifiedValue |= ulValue;
fep 0:5ff20db10a96 4492 break;
fep 0:5ff20db10a96 4493
fep 0:5ff20db10a96 4494 case eIncrement :
fep 0:5ff20db10a96 4495 ( pxTCB->ulNotifiedValue )++;
fep 0:5ff20db10a96 4496 break;
fep 0:5ff20db10a96 4497
fep 0:5ff20db10a96 4498 case eSetValueWithOverwrite :
fep 0:5ff20db10a96 4499 pxTCB->ulNotifiedValue = ulValue;
fep 0:5ff20db10a96 4500 break;
fep 0:5ff20db10a96 4501
fep 0:5ff20db10a96 4502 case eSetValueWithoutOverwrite :
fep 0:5ff20db10a96 4503 if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
fep 0:5ff20db10a96 4504 {
fep 0:5ff20db10a96 4505 pxTCB->ulNotifiedValue = ulValue;
fep 0:5ff20db10a96 4506 }
fep 0:5ff20db10a96 4507 else
fep 0:5ff20db10a96 4508 {
fep 0:5ff20db10a96 4509 /* The value could not be written to the task. */
fep 0:5ff20db10a96 4510 xReturn = pdFAIL;
fep 0:5ff20db10a96 4511 }
fep 0:5ff20db10a96 4512 break;
fep 0:5ff20db10a96 4513
fep 0:5ff20db10a96 4514 case eNoAction :
fep 0:5ff20db10a96 4515 /* The task is being notified without its notify value being
fep 0:5ff20db10a96 4516 updated. */
fep 0:5ff20db10a96 4517 break;
fep 0:5ff20db10a96 4518 }
fep 0:5ff20db10a96 4519
fep 0:5ff20db10a96 4520 traceTASK_NOTIFY_FROM_ISR();
fep 0:5ff20db10a96 4521
fep 0:5ff20db10a96 4522 /* If the task is in the blocked state specifically to wait for a
fep 0:5ff20db10a96 4523 notification then unblock it now. */
fep 0:5ff20db10a96 4524 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
fep 0:5ff20db10a96 4525 {
fep 0:5ff20db10a96 4526 /* The task should not have been on an event list. */
fep 0:5ff20db10a96 4527 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
fep 0:5ff20db10a96 4528
fep 0:5ff20db10a96 4529 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
fep 0:5ff20db10a96 4530 {
fep 0:5ff20db10a96 4531 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 4532 prvAddTaskToReadyList( pxTCB );
fep 0:5ff20db10a96 4533 }
fep 0:5ff20db10a96 4534 else
fep 0:5ff20db10a96 4535 {
fep 0:5ff20db10a96 4536 /* The delayed and ready lists cannot be accessed, so hold
fep 0:5ff20db10a96 4537 this task pending until the scheduler is resumed. */
fep 0:5ff20db10a96 4538 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
fep 0:5ff20db10a96 4539 }
fep 0:5ff20db10a96 4540
fep 0:5ff20db10a96 4541 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
fep 0:5ff20db10a96 4542 {
fep 0:5ff20db10a96 4543 /* The notified task has a priority above the currently
fep 0:5ff20db10a96 4544 executing task so a yield is required. */
fep 0:5ff20db10a96 4545 if( pxHigherPriorityTaskWoken != NULL )
fep 0:5ff20db10a96 4546 {
fep 0:5ff20db10a96 4547 *pxHigherPriorityTaskWoken = pdTRUE;
fep 0:5ff20db10a96 4548 }
fep 0:5ff20db10a96 4549 else
fep 0:5ff20db10a96 4550 {
fep 0:5ff20db10a96 4551 /* Mark that a yield is pending in case the user is not
fep 0:5ff20db10a96 4552 using the "xHigherPriorityTaskWoken" parameter to an ISR
fep 0:5ff20db10a96 4553 safe FreeRTOS function. */
fep 0:5ff20db10a96 4554 xYieldPending = pdTRUE;
fep 0:5ff20db10a96 4555 }
fep 0:5ff20db10a96 4556 }
fep 0:5ff20db10a96 4557 else
fep 0:5ff20db10a96 4558 {
fep 0:5ff20db10a96 4559 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4560 }
fep 0:5ff20db10a96 4561 }
fep 0:5ff20db10a96 4562 }
fep 0:5ff20db10a96 4563 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
fep 0:5ff20db10a96 4564
fep 0:5ff20db10a96 4565 return xReturn;
fep 0:5ff20db10a96 4566 }
fep 0:5ff20db10a96 4567
fep 0:5ff20db10a96 4568 #endif /* configUSE_TASK_NOTIFICATIONS */
fep 0:5ff20db10a96 4569 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 4570
fep 0:5ff20db10a96 4571 #if( configUSE_TASK_NOTIFICATIONS == 1 )
fep 0:5ff20db10a96 4572
fep 0:5ff20db10a96 4573 void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )
fep 0:5ff20db10a96 4574 {
fep 0:5ff20db10a96 4575 TCB_t * pxTCB;
fep 0:5ff20db10a96 4576 uint8_t ucOriginalNotifyState;
fep 0:5ff20db10a96 4577 UBaseType_t uxSavedInterruptStatus;
fep 0:5ff20db10a96 4578
fep 0:5ff20db10a96 4579 configASSERT( xTaskToNotify );
fep 0:5ff20db10a96 4580
fep 0:5ff20db10a96 4581 /* RTOS ports that support interrupt nesting have the concept of a
fep 0:5ff20db10a96 4582 maximum system call (or maximum API call) interrupt priority.
fep 0:5ff20db10a96 4583 Interrupts that are above the maximum system call priority are keep
fep 0:5ff20db10a96 4584 permanently enabled, even when the RTOS kernel is in a critical section,
fep 0:5ff20db10a96 4585 but cannot make any calls to FreeRTOS API functions. If configASSERT()
fep 0:5ff20db10a96 4586 is defined in FreeRTOSConfig.h then
fep 0:5ff20db10a96 4587 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
fep 0:5ff20db10a96 4588 failure if a FreeRTOS API function is called from an interrupt that has
fep 0:5ff20db10a96 4589 been assigned a priority above the configured maximum system call
fep 0:5ff20db10a96 4590 priority. Only FreeRTOS functions that end in FromISR can be called
fep 0:5ff20db10a96 4591 from interrupts that have been assigned a priority at or (logically)
fep 0:5ff20db10a96 4592 below the maximum system call interrupt priority. FreeRTOS maintains a
fep 0:5ff20db10a96 4593 separate interrupt safe API to ensure interrupt entry is as fast and as
fep 0:5ff20db10a96 4594 simple as possible. More information (albeit Cortex-M specific) is
fep 0:5ff20db10a96 4595 provided on the following link:
fep 0:5ff20db10a96 4596 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
fep 0:5ff20db10a96 4597 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
fep 0:5ff20db10a96 4598
fep 0:5ff20db10a96 4599 pxTCB = ( TCB_t * ) xTaskToNotify;
fep 0:5ff20db10a96 4600
fep 0:5ff20db10a96 4601 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
fep 0:5ff20db10a96 4602 {
fep 0:5ff20db10a96 4603 ucOriginalNotifyState = pxTCB->ucNotifyState;
fep 0:5ff20db10a96 4604 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
fep 0:5ff20db10a96 4605
fep 0:5ff20db10a96 4606 /* 'Giving' is equivalent to incrementing a count in a counting
fep 0:5ff20db10a96 4607 semaphore. */
fep 0:5ff20db10a96 4608 ( pxTCB->ulNotifiedValue )++;
fep 0:5ff20db10a96 4609
fep 0:5ff20db10a96 4610 traceTASK_NOTIFY_GIVE_FROM_ISR();
fep 0:5ff20db10a96 4611
fep 0:5ff20db10a96 4612 /* If the task is in the blocked state specifically to wait for a
fep 0:5ff20db10a96 4613 notification then unblock it now. */
fep 0:5ff20db10a96 4614 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
fep 0:5ff20db10a96 4615 {
fep 0:5ff20db10a96 4616 /* The task should not have been on an event list. */
fep 0:5ff20db10a96 4617 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
fep 0:5ff20db10a96 4618
fep 0:5ff20db10a96 4619 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
fep 0:5ff20db10a96 4620 {
fep 0:5ff20db10a96 4621 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
fep 0:5ff20db10a96 4622 prvAddTaskToReadyList( pxTCB );
fep 0:5ff20db10a96 4623 }
fep 0:5ff20db10a96 4624 else
fep 0:5ff20db10a96 4625 {
fep 0:5ff20db10a96 4626 /* The delayed and ready lists cannot be accessed, so hold
fep 0:5ff20db10a96 4627 this task pending until the scheduler is resumed. */
fep 0:5ff20db10a96 4628 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
fep 0:5ff20db10a96 4629 }
fep 0:5ff20db10a96 4630
fep 0:5ff20db10a96 4631 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
fep 0:5ff20db10a96 4632 {
fep 0:5ff20db10a96 4633 /* The notified task has a priority above the currently
fep 0:5ff20db10a96 4634 executing task so a yield is required. */
fep 0:5ff20db10a96 4635 if( pxHigherPriorityTaskWoken != NULL )
fep 0:5ff20db10a96 4636 {
fep 0:5ff20db10a96 4637 *pxHigherPriorityTaskWoken = pdTRUE;
fep 0:5ff20db10a96 4638 }
fep 0:5ff20db10a96 4639 else
fep 0:5ff20db10a96 4640 {
fep 0:5ff20db10a96 4641 /* Mark that a yield is pending in case the user is not
fep 0:5ff20db10a96 4642 using the "xHigherPriorityTaskWoken" parameter in an ISR
fep 0:5ff20db10a96 4643 safe FreeRTOS function. */
fep 0:5ff20db10a96 4644 xYieldPending = pdTRUE;
fep 0:5ff20db10a96 4645 }
fep 0:5ff20db10a96 4646 }
fep 0:5ff20db10a96 4647 else
fep 0:5ff20db10a96 4648 {
fep 0:5ff20db10a96 4649 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4650 }
fep 0:5ff20db10a96 4651 }
fep 0:5ff20db10a96 4652 }
fep 0:5ff20db10a96 4653 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
fep 0:5ff20db10a96 4654 }
fep 0:5ff20db10a96 4655
fep 0:5ff20db10a96 4656 #endif /* configUSE_TASK_NOTIFICATIONS */
fep 0:5ff20db10a96 4657
fep 0:5ff20db10a96 4658 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 4659
fep 0:5ff20db10a96 4660 #if( configUSE_TASK_NOTIFICATIONS == 1 )
fep 0:5ff20db10a96 4661
fep 0:5ff20db10a96 4662 BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask )
fep 0:5ff20db10a96 4663 {
fep 0:5ff20db10a96 4664 TCB_t *pxTCB;
fep 0:5ff20db10a96 4665 BaseType_t xReturn;
fep 0:5ff20db10a96 4666
fep 0:5ff20db10a96 4667 /* If null is passed in here then it is the calling task that is having
fep 0:5ff20db10a96 4668 its notification state cleared. */
fep 0:5ff20db10a96 4669 pxTCB = prvGetTCBFromHandle( xTask );
fep 0:5ff20db10a96 4670
fep 0:5ff20db10a96 4671 taskENTER_CRITICAL();
fep 0:5ff20db10a96 4672 {
fep 0:5ff20db10a96 4673 if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED )
fep 0:5ff20db10a96 4674 {
fep 0:5ff20db10a96 4675 pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
fep 0:5ff20db10a96 4676 xReturn = pdPASS;
fep 0:5ff20db10a96 4677 }
fep 0:5ff20db10a96 4678 else
fep 0:5ff20db10a96 4679 {
fep 0:5ff20db10a96 4680 xReturn = pdFAIL;
fep 0:5ff20db10a96 4681 }
fep 0:5ff20db10a96 4682 }
fep 0:5ff20db10a96 4683 taskEXIT_CRITICAL();
fep 0:5ff20db10a96 4684
fep 0:5ff20db10a96 4685 return xReturn;
fep 0:5ff20db10a96 4686 }
fep 0:5ff20db10a96 4687
fep 0:5ff20db10a96 4688 #endif /* configUSE_TASK_NOTIFICATIONS */
fep 0:5ff20db10a96 4689 /*-----------------------------------------------------------*/
fep 0:5ff20db10a96 4690
fep 0:5ff20db10a96 4691
fep 0:5ff20db10a96 4692 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
fep 0:5ff20db10a96 4693 {
fep 0:5ff20db10a96 4694 TickType_t xTimeToWake;
fep 0:5ff20db10a96 4695 const TickType_t xConstTickCount = xTickCount;
fep 0:5ff20db10a96 4696
fep 0:5ff20db10a96 4697 #if( INCLUDE_xTaskAbortDelay == 1 )
fep 0:5ff20db10a96 4698 {
fep 0:5ff20db10a96 4699 /* About to enter a delayed list, so ensure the ucDelayAborted flag is
fep 0:5ff20db10a96 4700 reset to pdFALSE so it can be detected as having been set to pdTRUE
fep 0:5ff20db10a96 4701 when the task leaves the Blocked state. */
fep 0:5ff20db10a96 4702 pxCurrentTCB->ucDelayAborted = pdFALSE;
fep 0:5ff20db10a96 4703 }
fep 0:5ff20db10a96 4704 #endif
fep 0:5ff20db10a96 4705
fep 0:5ff20db10a96 4706 /* Remove the task from the ready list before adding it to the blocked list
fep 0:5ff20db10a96 4707 as the same list item is used for both lists. */
fep 0:5ff20db10a96 4708 if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
fep 0:5ff20db10a96 4709 {
fep 0:5ff20db10a96 4710 /* The current task must be in a ready list, so there is no need to
fep 0:5ff20db10a96 4711 check, and the port reset macro can be called directly. */
fep 0:5ff20db10a96 4712 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
fep 0:5ff20db10a96 4713 }
fep 0:5ff20db10a96 4714 else
fep 0:5ff20db10a96 4715 {
fep 0:5ff20db10a96 4716 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4717 }
fep 0:5ff20db10a96 4718
fep 0:5ff20db10a96 4719 #if ( INCLUDE_vTaskSuspend == 1 )
fep 0:5ff20db10a96 4720 {
fep 0:5ff20db10a96 4721 if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
fep 0:5ff20db10a96 4722 {
fep 0:5ff20db10a96 4723 /* Add the task to the suspended task list instead of a delayed task
fep 0:5ff20db10a96 4724 list to ensure it is not woken by a timing event. It will block
fep 0:5ff20db10a96 4725 indefinitely. */
fep 0:5ff20db10a96 4726 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
fep 0:5ff20db10a96 4727 }
fep 0:5ff20db10a96 4728 else
fep 0:5ff20db10a96 4729 {
fep 0:5ff20db10a96 4730 /* Calculate the time at which the task should be woken if the event
fep 0:5ff20db10a96 4731 does not occur. This may overflow but this doesn't matter, the
fep 0:5ff20db10a96 4732 kernel will manage it correctly. */
fep 0:5ff20db10a96 4733 xTimeToWake = xConstTickCount + xTicksToWait;
fep 0:5ff20db10a96 4734
fep 0:5ff20db10a96 4735 /* The list item will be inserted in wake time order. */
fep 0:5ff20db10a96 4736 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
fep 0:5ff20db10a96 4737
fep 0:5ff20db10a96 4738 if( xTimeToWake < xConstTickCount )
fep 0:5ff20db10a96 4739 {
fep 0:5ff20db10a96 4740 /* Wake time has overflowed. Place this item in the overflow
fep 0:5ff20db10a96 4741 list. */
fep 0:5ff20db10a96 4742 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
fep 0:5ff20db10a96 4743 }
fep 0:5ff20db10a96 4744 else
fep 0:5ff20db10a96 4745 {
fep 0:5ff20db10a96 4746 /* The wake time has not overflowed, so the current block list
fep 0:5ff20db10a96 4747 is used. */
fep 0:5ff20db10a96 4748 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
fep 0:5ff20db10a96 4749
fep 0:5ff20db10a96 4750 /* If the task entering the blocked state was placed at the
fep 0:5ff20db10a96 4751 head of the list of blocked tasks then xNextTaskUnblockTime
fep 0:5ff20db10a96 4752 needs to be updated too. */
fep 0:5ff20db10a96 4753 if( xTimeToWake < xNextTaskUnblockTime )
fep 0:5ff20db10a96 4754 {
fep 0:5ff20db10a96 4755 xNextTaskUnblockTime = xTimeToWake;
fep 0:5ff20db10a96 4756 }
fep 0:5ff20db10a96 4757 else
fep 0:5ff20db10a96 4758 {
fep 0:5ff20db10a96 4759 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4760 }
fep 0:5ff20db10a96 4761 }
fep 0:5ff20db10a96 4762 }
fep 0:5ff20db10a96 4763 }
fep 0:5ff20db10a96 4764 #else /* INCLUDE_vTaskSuspend */
fep 0:5ff20db10a96 4765 {
fep 0:5ff20db10a96 4766 /* Calculate the time at which the task should be woken if the event
fep 0:5ff20db10a96 4767 does not occur. This may overflow but this doesn't matter, the kernel
fep 0:5ff20db10a96 4768 will manage it correctly. */
fep 0:5ff20db10a96 4769 xTimeToWake = xConstTickCount + xTicksToWait;
fep 0:5ff20db10a96 4770
fep 0:5ff20db10a96 4771 /* The list item will be inserted in wake time order. */
fep 0:5ff20db10a96 4772 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
fep 0:5ff20db10a96 4773
fep 0:5ff20db10a96 4774 if( xTimeToWake < xConstTickCount )
fep 0:5ff20db10a96 4775 {
fep 0:5ff20db10a96 4776 /* Wake time has overflowed. Place this item in the overflow list. */
fep 0:5ff20db10a96 4777 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
fep 0:5ff20db10a96 4778 }
fep 0:5ff20db10a96 4779 else
fep 0:5ff20db10a96 4780 {
fep 0:5ff20db10a96 4781 /* The wake time has not overflowed, so the current block list is used. */
fep 0:5ff20db10a96 4782 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
fep 0:5ff20db10a96 4783
fep 0:5ff20db10a96 4784 /* If the task entering the blocked state was placed at the head of the
fep 0:5ff20db10a96 4785 list of blocked tasks then xNextTaskUnblockTime needs to be updated
fep 0:5ff20db10a96 4786 too. */
fep 0:5ff20db10a96 4787 if( xTimeToWake < xNextTaskUnblockTime )
fep 0:5ff20db10a96 4788 {
fep 0:5ff20db10a96 4789 xNextTaskUnblockTime = xTimeToWake;
fep 0:5ff20db10a96 4790 }
fep 0:5ff20db10a96 4791 else
fep 0:5ff20db10a96 4792 {
fep 0:5ff20db10a96 4793 mtCOVERAGE_TEST_MARKER();
fep 0:5ff20db10a96 4794 }
fep 0:5ff20db10a96 4795 }
fep 0:5ff20db10a96 4796
fep 0:5ff20db10a96 4797 /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
fep 0:5ff20db10a96 4798 ( void ) xCanBlockIndefinitely;
fep 0:5ff20db10a96 4799 }
fep 0:5ff20db10a96 4800 #endif /* INCLUDE_vTaskSuspend */
fep 0:5ff20db10a96 4801 }
fep 0:5ff20db10a96 4802
fep 0:5ff20db10a96 4803
fep 0:5ff20db10a96 4804 #ifdef FREERTOS_MODULE_TEST
fep 0:5ff20db10a96 4805 #include "tasks_test_access_functions.h"
fep 0:5ff20db10a96 4806 #endif
fep 0:5ff20db10a96 4807
fep 0:5ff20db10a96 4808