Update revision to use TI's mqtt and Freertos.

Dependencies:   mbed client server

Fork of cc3100_Test_mqtt_CM3 by David Fletcher

Committer:
dflet
Date:
Thu Sep 03 14:02:37 2015 +0000
Revision:
3:a8c249046181
SPI Mode change 1 to 0

Who changed what in which revision?

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