Port of TI's CC3100 Websock camera demo. Using FreeRTOS, mbedTLS, also parts of Arducam for cams ov5642 and 0v2640. Can also use MT9D111. Work in progress. Be warned some parts maybe a bit flacky. This is for Seeed Arch max only, for an M3, see the demo for CM3 using the 0v5642 aducam mini.

Dependencies:   mbed

Committer:
dflet
Date:
Tue Sep 15 16:45:04 2015 +0000
Revision:
22:f9b5e0b80bf2
Parent:
0:50cedd586816
Removed some debug.

Who changed what in which revision?

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