David Fletcher / Mbed 2 deprecated cc3100_Test_mqtt_CM4F

Dependencies:   mbed

Committer:
dflet
Date:
Thu Sep 03 14:07:01 2015 +0000
Revision:
0:1e7b5dd9edb4
First commit, it's been hanging around for a while. Updated SPI mode change 1 to 0.

Who changed what in which revision?

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