Freertos for LPC CM3 tested on LPC1768

Committer:
dflet
Date:
Sat Jun 06 13:27:43 2015 +0000
Revision:
0:91ad48ad5687
Setup for LPC CM3 but may work with LPC CM4

Who changed what in which revision?

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