www.freertos.org

Dependents:   Nucleo freertos_test FreeRTOS_test freertos_bluetooth ... more

Committer:
rgrover1
Date:
Fri Jan 24 14:56:04 2014 +0000
Revision:
0:8e57f3e9cc89
Making FreeRTOS available as a library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 0:8e57f3e9cc89 1 /*
rgrover1 0:8e57f3e9cc89 2 FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
rgrover1 0:8e57f3e9cc89 3 All rights reserved
rgrover1 0:8e57f3e9cc89 4
rgrover1 0:8e57f3e9cc89 5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
rgrover1 0:8e57f3e9cc89 6
rgrover1 0:8e57f3e9cc89 7 ***************************************************************************
rgrover1 0:8e57f3e9cc89 8 * *
rgrover1 0:8e57f3e9cc89 9 * FreeRTOS provides completely free yet professionally developed, *
rgrover1 0:8e57f3e9cc89 10 * robust, strictly quality controlled, supported, and cross *
rgrover1 0:8e57f3e9cc89 11 * platform software that has become a de facto standard. *
rgrover1 0:8e57f3e9cc89 12 * *
rgrover1 0:8e57f3e9cc89 13 * Help yourself get started quickly and support the FreeRTOS *
rgrover1 0:8e57f3e9cc89 14 * project by purchasing a FreeRTOS tutorial book, reference *
rgrover1 0:8e57f3e9cc89 15 * manual, or both from: http://www.FreeRTOS.org/Documentation *
rgrover1 0:8e57f3e9cc89 16 * *
rgrover1 0:8e57f3e9cc89 17 * Thank you! *
rgrover1 0:8e57f3e9cc89 18 * *
rgrover1 0:8e57f3e9cc89 19 ***************************************************************************
rgrover1 0:8e57f3e9cc89 20
rgrover1 0:8e57f3e9cc89 21 This file is part of the FreeRTOS distribution.
rgrover1 0:8e57f3e9cc89 22
rgrover1 0:8e57f3e9cc89 23 FreeRTOS is free software; you can redistribute it and/or modify it under
rgrover1 0:8e57f3e9cc89 24 the terms of the GNU General Public License (version 2) as published by the
rgrover1 0:8e57f3e9cc89 25 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
rgrover1 0:8e57f3e9cc89 26
rgrover1 0:8e57f3e9cc89 27 >>! NOTE: The modification to the GPL is included to allow you to distribute
rgrover1 0:8e57f3e9cc89 28 >>! a combined work that includes FreeRTOS without being obliged to provide
rgrover1 0:8e57f3e9cc89 29 >>! the source code for proprietary components outside of the FreeRTOS
rgrover1 0:8e57f3e9cc89 30 >>! kernel.
rgrover1 0:8e57f3e9cc89 31
rgrover1 0:8e57f3e9cc89 32 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
rgrover1 0:8e57f3e9cc89 33 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
rgrover1 0:8e57f3e9cc89 34 FOR A PARTICULAR PURPOSE. Full license text is available from the following
rgrover1 0:8e57f3e9cc89 35 link: http://www.freertos.org/a00114.html
rgrover1 0:8e57f3e9cc89 36
rgrover1 0:8e57f3e9cc89 37 1 tab == 4 spaces!
rgrover1 0:8e57f3e9cc89 38
rgrover1 0:8e57f3e9cc89 39 ***************************************************************************
rgrover1 0:8e57f3e9cc89 40 * *
rgrover1 0:8e57f3e9cc89 41 * Having a problem? Start by reading the FAQ "My application does *
rgrover1 0:8e57f3e9cc89 42 * not run, what could be wrong?" *
rgrover1 0:8e57f3e9cc89 43 * *
rgrover1 0:8e57f3e9cc89 44 * http://www.FreeRTOS.org/FAQHelp.html *
rgrover1 0:8e57f3e9cc89 45 * *
rgrover1 0:8e57f3e9cc89 46 ***************************************************************************
rgrover1 0:8e57f3e9cc89 47
rgrover1 0:8e57f3e9cc89 48 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
rgrover1 0:8e57f3e9cc89 49 license and Real Time Engineers Ltd. contact details.
rgrover1 0:8e57f3e9cc89 50
rgrover1 0:8e57f3e9cc89 51 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
rgrover1 0:8e57f3e9cc89 52 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
rgrover1 0:8e57f3e9cc89 53 compatible FAT file system, and our tiny thread aware UDP/IP stack.
rgrover1 0:8e57f3e9cc89 54
rgrover1 0:8e57f3e9cc89 55 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
rgrover1 0:8e57f3e9cc89 56 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
rgrover1 0:8e57f3e9cc89 57 licenses offer ticketed support, indemnification and middleware.
rgrover1 0:8e57f3e9cc89 58
rgrover1 0:8e57f3e9cc89 59 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
rgrover1 0:8e57f3e9cc89 60 engineered and independently SIL3 certified version for use in safety and
rgrover1 0:8e57f3e9cc89 61 mission critical applications that require provable dependability.
rgrover1 0:8e57f3e9cc89 62
rgrover1 0:8e57f3e9cc89 63 1 tab == 4 spaces!
rgrover1 0:8e57f3e9cc89 64 */
rgrover1 0:8e57f3e9cc89 65
rgrover1 0:8e57f3e9cc89 66 #include <stdlib.h>
rgrover1 0:8e57f3e9cc89 67 #include <string.h>
rgrover1 0:8e57f3e9cc89 68
rgrover1 0:8e57f3e9cc89 69 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
rgrover1 0:8e57f3e9cc89 70 all the API functions to use the MPU wrappers. That should only be done when
rgrover1 0:8e57f3e9cc89 71 task.h is included from an application file. */
rgrover1 0:8e57f3e9cc89 72 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
rgrover1 0:8e57f3e9cc89 73
rgrover1 0:8e57f3e9cc89 74 #include "FreeRTOS.h"
rgrover1 0:8e57f3e9cc89 75 #include "task.h"
rgrover1 0:8e57f3e9cc89 76 #include "queue.h"
rgrover1 0:8e57f3e9cc89 77
rgrover1 0:8e57f3e9cc89 78 #if ( configUSE_CO_ROUTINES == 1 )
rgrover1 0:8e57f3e9cc89 79 #include "croutine.h"
rgrover1 0:8e57f3e9cc89 80 #endif
rgrover1 0:8e57f3e9cc89 81
rgrover1 0:8e57f3e9cc89 82 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
rgrover1 0:8e57f3e9cc89 83 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
rgrover1 0:8e57f3e9cc89 84 header files above, but not in this file, in order to generate the correct
rgrover1 0:8e57f3e9cc89 85 privileged Vs unprivileged linkage and placement. */
rgrover1 0:8e57f3e9cc89 86 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
rgrover1 0:8e57f3e9cc89 87
rgrover1 0:8e57f3e9cc89 88
rgrover1 0:8e57f3e9cc89 89 /* Constants used with the cRxLock and xTxLock structure members. */
rgrover1 0:8e57f3e9cc89 90 #define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
rgrover1 0:8e57f3e9cc89 91 #define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 92
rgrover1 0:8e57f3e9cc89 93 /* When the xQUEUE structure is used to represent a base queue its pcHead and
rgrover1 0:8e57f3e9cc89 94 pcTail members are used as pointers into the queue storage area. When the
rgrover1 0:8e57f3e9cc89 95 xQUEUE structure is used to represent a mutex pcHead and pcTail pointers are
rgrover1 0:8e57f3e9cc89 96 not necessary, and the pcHead pointer is set to NULL to indicate that the
rgrover1 0:8e57f3e9cc89 97 pcTail pointer actually points to the mutex holder (if any). Map alternative
rgrover1 0:8e57f3e9cc89 98 names to the pcHead and pcTail structure members to ensure the readability of
rgrover1 0:8e57f3e9cc89 99 the code is maintained despite this dual use of two structure members. An
rgrover1 0:8e57f3e9cc89 100 alternative implementation would be to use a union, but use of a union is
rgrover1 0:8e57f3e9cc89 101 against the coding standard (although an exception to the standard has been
rgrover1 0:8e57f3e9cc89 102 permitted where the dual use also significantly changes the type of the
rgrover1 0:8e57f3e9cc89 103 structure member). */
rgrover1 0:8e57f3e9cc89 104 #define pxMutexHolder pcTail
rgrover1 0:8e57f3e9cc89 105 #define uxQueueType pcHead
rgrover1 0:8e57f3e9cc89 106 #define queueQUEUE_IS_MUTEX NULL
rgrover1 0:8e57f3e9cc89 107
rgrover1 0:8e57f3e9cc89 108 /* Semaphores do not actually store or copy data, so have an item size of
rgrover1 0:8e57f3e9cc89 109 zero. */
rgrover1 0:8e57f3e9cc89 110 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 111 #define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U )
rgrover1 0:8e57f3e9cc89 112
rgrover1 0:8e57f3e9cc89 113 #if( configUSE_PREEMPTION == 0 )
rgrover1 0:8e57f3e9cc89 114 /* If the cooperative scheduler is being used then a yield should not be
rgrover1 0:8e57f3e9cc89 115 performed just because a higher priority task has been woken. */
rgrover1 0:8e57f3e9cc89 116 #define queueYIELD_IF_USING_PREEMPTION()
rgrover1 0:8e57f3e9cc89 117 #else
rgrover1 0:8e57f3e9cc89 118 #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
rgrover1 0:8e57f3e9cc89 119 #endif
rgrover1 0:8e57f3e9cc89 120
rgrover1 0:8e57f3e9cc89 121 /*
rgrover1 0:8e57f3e9cc89 122 * Definition of the queue used by the scheduler.
rgrover1 0:8e57f3e9cc89 123 * Items are queued by copy, not reference.
rgrover1 0:8e57f3e9cc89 124 */
rgrover1 0:8e57f3e9cc89 125 typedef struct QueueDefinition
rgrover1 0:8e57f3e9cc89 126 {
rgrover1 0:8e57f3e9cc89 127 signed char *pcHead; /*< Points to the beginning of the queue storage area. */
rgrover1 0:8e57f3e9cc89 128 signed char *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */
rgrover1 0:8e57f3e9cc89 129
rgrover1 0:8e57f3e9cc89 130 signed char *pcWriteTo; /*< Points to the free next place in the storage area. */
rgrover1 0:8e57f3e9cc89 131
rgrover1 0:8e57f3e9cc89 132 union /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */
rgrover1 0:8e57f3e9cc89 133 {
rgrover1 0:8e57f3e9cc89 134 signed char *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */
rgrover1 0:8e57f3e9cc89 135 unsigned portBASE_TYPE uxRecursiveCallCount;/*< Maintains a count of the numebr of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */
rgrover1 0:8e57f3e9cc89 136 } u;
rgrover1 0:8e57f3e9cc89 137
rgrover1 0:8e57f3e9cc89 138 xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
rgrover1 0:8e57f3e9cc89 139 xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
rgrover1 0:8e57f3e9cc89 140
rgrover1 0:8e57f3e9cc89 141 volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
rgrover1 0:8e57f3e9cc89 142 unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
rgrover1 0:8e57f3e9cc89 143 unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
rgrover1 0:8e57f3e9cc89 144
rgrover1 0:8e57f3e9cc89 145 volatile signed portBASE_TYPE xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
rgrover1 0:8e57f3e9cc89 146 volatile signed portBASE_TYPE xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
rgrover1 0:8e57f3e9cc89 147
rgrover1 0:8e57f3e9cc89 148 #if ( configUSE_TRACE_FACILITY == 1 )
rgrover1 0:8e57f3e9cc89 149 unsigned char ucQueueNumber;
rgrover1 0:8e57f3e9cc89 150 unsigned char ucQueueType;
rgrover1 0:8e57f3e9cc89 151 #endif
rgrover1 0:8e57f3e9cc89 152
rgrover1 0:8e57f3e9cc89 153 #if ( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 154 struct QueueDefinition *pxQueueSetContainer;
rgrover1 0:8e57f3e9cc89 155 #endif
rgrover1 0:8e57f3e9cc89 156
rgrover1 0:8e57f3e9cc89 157 } xQUEUE;
rgrover1 0:8e57f3e9cc89 158 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 159
rgrover1 0:8e57f3e9cc89 160 /*
rgrover1 0:8e57f3e9cc89 161 * The queue registry is just a means for kernel aware debuggers to locate
rgrover1 0:8e57f3e9cc89 162 * queue structures. It has no other purpose so is an optional component.
rgrover1 0:8e57f3e9cc89 163 */
rgrover1 0:8e57f3e9cc89 164 #if ( configQUEUE_REGISTRY_SIZE > 0 )
rgrover1 0:8e57f3e9cc89 165
rgrover1 0:8e57f3e9cc89 166 /* The type stored within the queue registry array. This allows a name
rgrover1 0:8e57f3e9cc89 167 to be assigned to each queue making kernel aware debugging a little
rgrover1 0:8e57f3e9cc89 168 more user friendly. */
rgrover1 0:8e57f3e9cc89 169 typedef struct QUEUE_REGISTRY_ITEM
rgrover1 0:8e57f3e9cc89 170 {
rgrover1 0:8e57f3e9cc89 171 signed char *pcQueueName;
rgrover1 0:8e57f3e9cc89 172 xQueueHandle xHandle;
rgrover1 0:8e57f3e9cc89 173 } xQueueRegistryItem;
rgrover1 0:8e57f3e9cc89 174
rgrover1 0:8e57f3e9cc89 175 /* The queue registry is simply an array of xQueueRegistryItem structures.
rgrover1 0:8e57f3e9cc89 176 The pcQueueName member of a structure being NULL is indicative of the
rgrover1 0:8e57f3e9cc89 177 array position being vacant. */
rgrover1 0:8e57f3e9cc89 178 xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
rgrover1 0:8e57f3e9cc89 179
rgrover1 0:8e57f3e9cc89 180 #endif /* configQUEUE_REGISTRY_SIZE */
rgrover1 0:8e57f3e9cc89 181
rgrover1 0:8e57f3e9cc89 182 /*
rgrover1 0:8e57f3e9cc89 183 * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
rgrover1 0:8e57f3e9cc89 184 * prevent an ISR from adding or removing items to the queue, but does prevent
rgrover1 0:8e57f3e9cc89 185 * an ISR from removing tasks from the queue event lists. If an ISR finds a
rgrover1 0:8e57f3e9cc89 186 * queue is locked it will instead increment the appropriate queue lock count
rgrover1 0:8e57f3e9cc89 187 * to indicate that a task may require unblocking. When the queue in unlocked
rgrover1 0:8e57f3e9cc89 188 * these lock counts are inspected, and the appropriate action taken.
rgrover1 0:8e57f3e9cc89 189 */
rgrover1 0:8e57f3e9cc89 190 static void prvUnlockQueue( xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
rgrover1 0:8e57f3e9cc89 191
rgrover1 0:8e57f3e9cc89 192 /*
rgrover1 0:8e57f3e9cc89 193 * Uses a critical section to determine if there is any data in a queue.
rgrover1 0:8e57f3e9cc89 194 *
rgrover1 0:8e57f3e9cc89 195 * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
rgrover1 0:8e57f3e9cc89 196 */
rgrover1 0:8e57f3e9cc89 197 static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
rgrover1 0:8e57f3e9cc89 198
rgrover1 0:8e57f3e9cc89 199 /*
rgrover1 0:8e57f3e9cc89 200 * Uses a critical section to determine if there is any space in a queue.
rgrover1 0:8e57f3e9cc89 201 *
rgrover1 0:8e57f3e9cc89 202 * @return pdTRUE if there is no space, otherwise pdFALSE;
rgrover1 0:8e57f3e9cc89 203 */
rgrover1 0:8e57f3e9cc89 204 static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
rgrover1 0:8e57f3e9cc89 205
rgrover1 0:8e57f3e9cc89 206 /*
rgrover1 0:8e57f3e9cc89 207 * Copies an item into the queue, either at the front of the queue or the
rgrover1 0:8e57f3e9cc89 208 * back of the queue.
rgrover1 0:8e57f3e9cc89 209 */
rgrover1 0:8e57f3e9cc89 210 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
rgrover1 0:8e57f3e9cc89 211
rgrover1 0:8e57f3e9cc89 212 /*
rgrover1 0:8e57f3e9cc89 213 * Copies an item out of a queue.
rgrover1 0:8e57f3e9cc89 214 */
rgrover1 0:8e57f3e9cc89 215 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION;
rgrover1 0:8e57f3e9cc89 216
rgrover1 0:8e57f3e9cc89 217 #if ( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 218 /*
rgrover1 0:8e57f3e9cc89 219 * Checks to see if a queue is a member of a queue set, and if so, notifies
rgrover1 0:8e57f3e9cc89 220 * the queue set that the queue contains data.
rgrover1 0:8e57f3e9cc89 221 */
rgrover1 0:8e57f3e9cc89 222 static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
rgrover1 0:8e57f3e9cc89 223 #endif
rgrover1 0:8e57f3e9cc89 224
rgrover1 0:8e57f3e9cc89 225 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 226
rgrover1 0:8e57f3e9cc89 227 /*
rgrover1 0:8e57f3e9cc89 228 * Macro to mark a queue as locked. Locking a queue prevents an ISR from
rgrover1 0:8e57f3e9cc89 229 * accessing the queue event lists.
rgrover1 0:8e57f3e9cc89 230 */
rgrover1 0:8e57f3e9cc89 231 #define prvLockQueue( pxQueue ) \
rgrover1 0:8e57f3e9cc89 232 taskENTER_CRITICAL(); \
rgrover1 0:8e57f3e9cc89 233 { \
rgrover1 0:8e57f3e9cc89 234 if( ( pxQueue )->xRxLock == queueUNLOCKED ) \
rgrover1 0:8e57f3e9cc89 235 { \
rgrover1 0:8e57f3e9cc89 236 ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \
rgrover1 0:8e57f3e9cc89 237 } \
rgrover1 0:8e57f3e9cc89 238 if( ( pxQueue )->xTxLock == queueUNLOCKED ) \
rgrover1 0:8e57f3e9cc89 239 { \
rgrover1 0:8e57f3e9cc89 240 ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \
rgrover1 0:8e57f3e9cc89 241 } \
rgrover1 0:8e57f3e9cc89 242 } \
rgrover1 0:8e57f3e9cc89 243 taskEXIT_CRITICAL()
rgrover1 0:8e57f3e9cc89 244 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 245
rgrover1 0:8e57f3e9cc89 246 portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue )
rgrover1 0:8e57f3e9cc89 247 {
rgrover1 0:8e57f3e9cc89 248 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 249
rgrover1 0:8e57f3e9cc89 250 configASSERT( pxQueue );
rgrover1 0:8e57f3e9cc89 251
rgrover1 0:8e57f3e9cc89 252 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 253 {
rgrover1 0:8e57f3e9cc89 254 pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );
rgrover1 0:8e57f3e9cc89 255 pxQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
rgrover1 0:8e57f3e9cc89 256 pxQueue->pcWriteTo = pxQueue->pcHead;
rgrover1 0:8e57f3e9cc89 257 pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( unsigned portBASE_TYPE ) 1U ) * pxQueue->uxItemSize );
rgrover1 0:8e57f3e9cc89 258 pxQueue->xRxLock = queueUNLOCKED;
rgrover1 0:8e57f3e9cc89 259 pxQueue->xTxLock = queueUNLOCKED;
rgrover1 0:8e57f3e9cc89 260
rgrover1 0:8e57f3e9cc89 261 if( xNewQueue == pdFALSE )
rgrover1 0:8e57f3e9cc89 262 {
rgrover1 0:8e57f3e9cc89 263 /* If there are tasks blocked waiting to read from the queue, then
rgrover1 0:8e57f3e9cc89 264 the tasks will remain blocked as after this function exits the queue
rgrover1 0:8e57f3e9cc89 265 will still be empty. If there are tasks blocked waiting to write to
rgrover1 0:8e57f3e9cc89 266 the queue, then one should be unblocked as after this function exits
rgrover1 0:8e57f3e9cc89 267 it will be possible to write to it. */
rgrover1 0:8e57f3e9cc89 268 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 269 {
rgrover1 0:8e57f3e9cc89 270 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
rgrover1 0:8e57f3e9cc89 271 {
rgrover1 0:8e57f3e9cc89 272 queueYIELD_IF_USING_PREEMPTION();
rgrover1 0:8e57f3e9cc89 273 }
rgrover1 0:8e57f3e9cc89 274 }
rgrover1 0:8e57f3e9cc89 275 }
rgrover1 0:8e57f3e9cc89 276 else
rgrover1 0:8e57f3e9cc89 277 {
rgrover1 0:8e57f3e9cc89 278 /* Ensure the event queues start in the correct state. */
rgrover1 0:8e57f3e9cc89 279 vListInitialise( &( pxQueue->xTasksWaitingToSend ) );
rgrover1 0:8e57f3e9cc89 280 vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );
rgrover1 0:8e57f3e9cc89 281 }
rgrover1 0:8e57f3e9cc89 282 }
rgrover1 0:8e57f3e9cc89 283 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 284
rgrover1 0:8e57f3e9cc89 285 /* A value is returned for calling semantic consistency with previous
rgrover1 0:8e57f3e9cc89 286 versions. */
rgrover1 0:8e57f3e9cc89 287 return pdPASS;
rgrover1 0:8e57f3e9cc89 288 }
rgrover1 0:8e57f3e9cc89 289 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 290
rgrover1 0:8e57f3e9cc89 291 xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType )
rgrover1 0:8e57f3e9cc89 292 {
rgrover1 0:8e57f3e9cc89 293 xQUEUE *pxNewQueue;
rgrover1 0:8e57f3e9cc89 294 size_t xQueueSizeInBytes;
rgrover1 0:8e57f3e9cc89 295 xQueueHandle xReturn = NULL;
rgrover1 0:8e57f3e9cc89 296
rgrover1 0:8e57f3e9cc89 297 /* Remove compiler warnings about unused parameters should
rgrover1 0:8e57f3e9cc89 298 configUSE_TRACE_FACILITY not be set to 1. */
rgrover1 0:8e57f3e9cc89 299 ( void ) ucQueueType;
rgrover1 0:8e57f3e9cc89 300
rgrover1 0:8e57f3e9cc89 301 /* Allocate the new queue structure. */
rgrover1 0:8e57f3e9cc89 302 if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 303 {
rgrover1 0:8e57f3e9cc89 304 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
rgrover1 0:8e57f3e9cc89 305 if( pxNewQueue != NULL )
rgrover1 0:8e57f3e9cc89 306 {
rgrover1 0:8e57f3e9cc89 307 /* Create the list of pointers to queue items. The queue is one byte
rgrover1 0:8e57f3e9cc89 308 longer than asked for to make wrap checking easier/faster. */
rgrover1 0:8e57f3e9cc89 309 xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
rgrover1 0:8e57f3e9cc89 310
rgrover1 0:8e57f3e9cc89 311 pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
rgrover1 0:8e57f3e9cc89 312 if( pxNewQueue->pcHead != NULL )
rgrover1 0:8e57f3e9cc89 313 {
rgrover1 0:8e57f3e9cc89 314 /* Initialise the queue members as described above where the
rgrover1 0:8e57f3e9cc89 315 queue type is defined. */
rgrover1 0:8e57f3e9cc89 316 pxNewQueue->uxLength = uxQueueLength;
rgrover1 0:8e57f3e9cc89 317 pxNewQueue->uxItemSize = uxItemSize;
rgrover1 0:8e57f3e9cc89 318 ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
rgrover1 0:8e57f3e9cc89 319
rgrover1 0:8e57f3e9cc89 320 #if ( configUSE_TRACE_FACILITY == 1 )
rgrover1 0:8e57f3e9cc89 321 {
rgrover1 0:8e57f3e9cc89 322 pxNewQueue->ucQueueType = ucQueueType;
rgrover1 0:8e57f3e9cc89 323 }
rgrover1 0:8e57f3e9cc89 324 #endif /* configUSE_TRACE_FACILITY */
rgrover1 0:8e57f3e9cc89 325
rgrover1 0:8e57f3e9cc89 326 #if( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 327 {
rgrover1 0:8e57f3e9cc89 328 pxNewQueue->pxQueueSetContainer = NULL;
rgrover1 0:8e57f3e9cc89 329 }
rgrover1 0:8e57f3e9cc89 330 #endif /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 331
rgrover1 0:8e57f3e9cc89 332 traceQUEUE_CREATE( pxNewQueue );
rgrover1 0:8e57f3e9cc89 333 xReturn = pxNewQueue;
rgrover1 0:8e57f3e9cc89 334 }
rgrover1 0:8e57f3e9cc89 335 else
rgrover1 0:8e57f3e9cc89 336 {
rgrover1 0:8e57f3e9cc89 337 traceQUEUE_CREATE_FAILED( ucQueueType );
rgrover1 0:8e57f3e9cc89 338 vPortFree( pxNewQueue );
rgrover1 0:8e57f3e9cc89 339 }
rgrover1 0:8e57f3e9cc89 340 }
rgrover1 0:8e57f3e9cc89 341 }
rgrover1 0:8e57f3e9cc89 342
rgrover1 0:8e57f3e9cc89 343 configASSERT( xReturn );
rgrover1 0:8e57f3e9cc89 344
rgrover1 0:8e57f3e9cc89 345 return xReturn;
rgrover1 0:8e57f3e9cc89 346 }
rgrover1 0:8e57f3e9cc89 347 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 348
rgrover1 0:8e57f3e9cc89 349 #if ( configUSE_MUTEXES == 1 )
rgrover1 0:8e57f3e9cc89 350
rgrover1 0:8e57f3e9cc89 351 xQueueHandle xQueueCreateMutex( unsigned char ucQueueType )
rgrover1 0:8e57f3e9cc89 352 {
rgrover1 0:8e57f3e9cc89 353 xQUEUE *pxNewQueue;
rgrover1 0:8e57f3e9cc89 354
rgrover1 0:8e57f3e9cc89 355 /* Prevent compiler warnings about unused parameters if
rgrover1 0:8e57f3e9cc89 356 configUSE_TRACE_FACILITY does not equal 1. */
rgrover1 0:8e57f3e9cc89 357 ( void ) ucQueueType;
rgrover1 0:8e57f3e9cc89 358
rgrover1 0:8e57f3e9cc89 359 /* Allocate the new queue structure. */
rgrover1 0:8e57f3e9cc89 360 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
rgrover1 0:8e57f3e9cc89 361 if( pxNewQueue != NULL )
rgrover1 0:8e57f3e9cc89 362 {
rgrover1 0:8e57f3e9cc89 363 /* Information required for priority inheritance. */
rgrover1 0:8e57f3e9cc89 364 pxNewQueue->pxMutexHolder = NULL;
rgrover1 0:8e57f3e9cc89 365 pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
rgrover1 0:8e57f3e9cc89 366
rgrover1 0:8e57f3e9cc89 367 /* Queues used as a mutex no data is actually copied into or out
rgrover1 0:8e57f3e9cc89 368 of the queue. */
rgrover1 0:8e57f3e9cc89 369 pxNewQueue->pcWriteTo = NULL;
rgrover1 0:8e57f3e9cc89 370 pxNewQueue->u.pcReadFrom = NULL;
rgrover1 0:8e57f3e9cc89 371
rgrover1 0:8e57f3e9cc89 372 /* Each mutex has a length of 1 (like a binary semaphore) and
rgrover1 0:8e57f3e9cc89 373 an item size of 0 as nothing is actually copied into or out
rgrover1 0:8e57f3e9cc89 374 of the mutex. */
rgrover1 0:8e57f3e9cc89 375 pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
rgrover1 0:8e57f3e9cc89 376 pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;
rgrover1 0:8e57f3e9cc89 377 pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;
rgrover1 0:8e57f3e9cc89 378 pxNewQueue->xRxLock = queueUNLOCKED;
rgrover1 0:8e57f3e9cc89 379 pxNewQueue->xTxLock = queueUNLOCKED;
rgrover1 0:8e57f3e9cc89 380
rgrover1 0:8e57f3e9cc89 381 #if ( configUSE_TRACE_FACILITY == 1 )
rgrover1 0:8e57f3e9cc89 382 {
rgrover1 0:8e57f3e9cc89 383 pxNewQueue->ucQueueType = ucQueueType;
rgrover1 0:8e57f3e9cc89 384 }
rgrover1 0:8e57f3e9cc89 385 #endif
rgrover1 0:8e57f3e9cc89 386
rgrover1 0:8e57f3e9cc89 387 #if ( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 388 {
rgrover1 0:8e57f3e9cc89 389 pxNewQueue->pxQueueSetContainer = NULL;
rgrover1 0:8e57f3e9cc89 390 }
rgrover1 0:8e57f3e9cc89 391 #endif
rgrover1 0:8e57f3e9cc89 392
rgrover1 0:8e57f3e9cc89 393 /* Ensure the event queues start with the correct state. */
rgrover1 0:8e57f3e9cc89 394 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
rgrover1 0:8e57f3e9cc89 395 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
rgrover1 0:8e57f3e9cc89 396
rgrover1 0:8e57f3e9cc89 397 traceCREATE_MUTEX( pxNewQueue );
rgrover1 0:8e57f3e9cc89 398
rgrover1 0:8e57f3e9cc89 399 /* Start with the semaphore in the expected state. */
rgrover1 0:8e57f3e9cc89 400 ( void ) xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );
rgrover1 0:8e57f3e9cc89 401 }
rgrover1 0:8e57f3e9cc89 402 else
rgrover1 0:8e57f3e9cc89 403 {
rgrover1 0:8e57f3e9cc89 404 traceCREATE_MUTEX_FAILED();
rgrover1 0:8e57f3e9cc89 405 }
rgrover1 0:8e57f3e9cc89 406
rgrover1 0:8e57f3e9cc89 407 configASSERT( pxNewQueue );
rgrover1 0:8e57f3e9cc89 408 return pxNewQueue;
rgrover1 0:8e57f3e9cc89 409 }
rgrover1 0:8e57f3e9cc89 410
rgrover1 0:8e57f3e9cc89 411 #endif /* configUSE_MUTEXES */
rgrover1 0:8e57f3e9cc89 412 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 413
rgrover1 0:8e57f3e9cc89 414 #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
rgrover1 0:8e57f3e9cc89 415
rgrover1 0:8e57f3e9cc89 416 void* xQueueGetMutexHolder( xQueueHandle xSemaphore )
rgrover1 0:8e57f3e9cc89 417 {
rgrover1 0:8e57f3e9cc89 418 void *pxReturn;
rgrover1 0:8e57f3e9cc89 419
rgrover1 0:8e57f3e9cc89 420 /* This function is called by xSemaphoreGetMutexHolder(), and should not
rgrover1 0:8e57f3e9cc89 421 be called directly. Note: This is is a good way of determining if the
rgrover1 0:8e57f3e9cc89 422 calling task is the mutex holder, but not a good way of determining the
rgrover1 0:8e57f3e9cc89 423 identity of the mutex holder, as the holder may change between the
rgrover1 0:8e57f3e9cc89 424 following critical section exiting and the function returning. */
rgrover1 0:8e57f3e9cc89 425 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 426 {
rgrover1 0:8e57f3e9cc89 427 if( ( ( xQUEUE * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )
rgrover1 0:8e57f3e9cc89 428 {
rgrover1 0:8e57f3e9cc89 429 pxReturn = ( void * ) ( ( xQUEUE * ) xSemaphore )->pxMutexHolder;
rgrover1 0:8e57f3e9cc89 430 }
rgrover1 0:8e57f3e9cc89 431 else
rgrover1 0:8e57f3e9cc89 432 {
rgrover1 0:8e57f3e9cc89 433 pxReturn = NULL;
rgrover1 0:8e57f3e9cc89 434 }
rgrover1 0:8e57f3e9cc89 435 }
rgrover1 0:8e57f3e9cc89 436 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 437
rgrover1 0:8e57f3e9cc89 438 return pxReturn;
rgrover1 0:8e57f3e9cc89 439 }
rgrover1 0:8e57f3e9cc89 440
rgrover1 0:8e57f3e9cc89 441 #endif
rgrover1 0:8e57f3e9cc89 442 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 443
rgrover1 0:8e57f3e9cc89 444 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
rgrover1 0:8e57f3e9cc89 445
rgrover1 0:8e57f3e9cc89 446 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex )
rgrover1 0:8e57f3e9cc89 447 {
rgrover1 0:8e57f3e9cc89 448 portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 449 xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
rgrover1 0:8e57f3e9cc89 450
rgrover1 0:8e57f3e9cc89 451 configASSERT( pxMutex );
rgrover1 0:8e57f3e9cc89 452
rgrover1 0:8e57f3e9cc89 453 /* If this is the task that holds the mutex then pxMutexHolder will not
rgrover1 0:8e57f3e9cc89 454 change outside of this task. If this task does not hold the mutex then
rgrover1 0:8e57f3e9cc89 455 pxMutexHolder can never coincidentally equal the tasks handle, and as
rgrover1 0:8e57f3e9cc89 456 this is the only condition we are interested in it does not matter if
rgrover1 0:8e57f3e9cc89 457 pxMutexHolder is accessed simultaneously by another task. Therefore no
rgrover1 0:8e57f3e9cc89 458 mutual exclusion is required to test the pxMutexHolder variable. */
rgrover1 0:8e57f3e9cc89 459 if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as xTaskHandle is a typedef. */
rgrover1 0:8e57f3e9cc89 460 {
rgrover1 0:8e57f3e9cc89 461 traceGIVE_MUTEX_RECURSIVE( pxMutex );
rgrover1 0:8e57f3e9cc89 462
rgrover1 0:8e57f3e9cc89 463 /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
rgrover1 0:8e57f3e9cc89 464 the task handle, therefore no underflow check is required. Also,
rgrover1 0:8e57f3e9cc89 465 uxRecursiveCallCount is only modified by the mutex holder, and as
rgrover1 0:8e57f3e9cc89 466 there can only be one, no mutual exclusion is required to modify the
rgrover1 0:8e57f3e9cc89 467 uxRecursiveCallCount member. */
rgrover1 0:8e57f3e9cc89 468 ( pxMutex->u.uxRecursiveCallCount )--;
rgrover1 0:8e57f3e9cc89 469
rgrover1 0:8e57f3e9cc89 470 /* Have we unwound the call count? */
rgrover1 0:8e57f3e9cc89 471 if( pxMutex->u.uxRecursiveCallCount == ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 472 {
rgrover1 0:8e57f3e9cc89 473 /* Return the mutex. This will automatically unblock any other
rgrover1 0:8e57f3e9cc89 474 task that might be waiting to access the mutex. */
rgrover1 0:8e57f3e9cc89 475 ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
rgrover1 0:8e57f3e9cc89 476 }
rgrover1 0:8e57f3e9cc89 477
rgrover1 0:8e57f3e9cc89 478 xReturn = pdPASS;
rgrover1 0:8e57f3e9cc89 479 }
rgrover1 0:8e57f3e9cc89 480 else
rgrover1 0:8e57f3e9cc89 481 {
rgrover1 0:8e57f3e9cc89 482 /* We cannot give the mutex because we are not the holder. */
rgrover1 0:8e57f3e9cc89 483 xReturn = pdFAIL;
rgrover1 0:8e57f3e9cc89 484
rgrover1 0:8e57f3e9cc89 485 traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
rgrover1 0:8e57f3e9cc89 486 }
rgrover1 0:8e57f3e9cc89 487
rgrover1 0:8e57f3e9cc89 488 return xReturn;
rgrover1 0:8e57f3e9cc89 489 }
rgrover1 0:8e57f3e9cc89 490
rgrover1 0:8e57f3e9cc89 491 #endif /* configUSE_RECURSIVE_MUTEXES */
rgrover1 0:8e57f3e9cc89 492 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 493
rgrover1 0:8e57f3e9cc89 494 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
rgrover1 0:8e57f3e9cc89 495
rgrover1 0:8e57f3e9cc89 496 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime )
rgrover1 0:8e57f3e9cc89 497 {
rgrover1 0:8e57f3e9cc89 498 portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 499 xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
rgrover1 0:8e57f3e9cc89 500
rgrover1 0:8e57f3e9cc89 501 configASSERT( pxMutex );
rgrover1 0:8e57f3e9cc89 502
rgrover1 0:8e57f3e9cc89 503 /* Comments regarding mutual exclusion as per those within
rgrover1 0:8e57f3e9cc89 504 xQueueGiveMutexRecursive(). */
rgrover1 0:8e57f3e9cc89 505
rgrover1 0:8e57f3e9cc89 506 traceTAKE_MUTEX_RECURSIVE( pxMutex );
rgrover1 0:8e57f3e9cc89 507
rgrover1 0:8e57f3e9cc89 508 if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */
rgrover1 0:8e57f3e9cc89 509 {
rgrover1 0:8e57f3e9cc89 510 ( pxMutex->u.uxRecursiveCallCount )++;
rgrover1 0:8e57f3e9cc89 511 xReturn = pdPASS;
rgrover1 0:8e57f3e9cc89 512 }
rgrover1 0:8e57f3e9cc89 513 else
rgrover1 0:8e57f3e9cc89 514 {
rgrover1 0:8e57f3e9cc89 515 xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
rgrover1 0:8e57f3e9cc89 516
rgrover1 0:8e57f3e9cc89 517 /* pdPASS will only be returned if we successfully obtained the mutex,
rgrover1 0:8e57f3e9cc89 518 we may have blocked to reach here. */
rgrover1 0:8e57f3e9cc89 519 if( xReturn == pdPASS )
rgrover1 0:8e57f3e9cc89 520 {
rgrover1 0:8e57f3e9cc89 521 ( pxMutex->u.uxRecursiveCallCount )++;
rgrover1 0:8e57f3e9cc89 522 }
rgrover1 0:8e57f3e9cc89 523 else
rgrover1 0:8e57f3e9cc89 524 {
rgrover1 0:8e57f3e9cc89 525 traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
rgrover1 0:8e57f3e9cc89 526 }
rgrover1 0:8e57f3e9cc89 527 }
rgrover1 0:8e57f3e9cc89 528
rgrover1 0:8e57f3e9cc89 529 return xReturn;
rgrover1 0:8e57f3e9cc89 530 }
rgrover1 0:8e57f3e9cc89 531
rgrover1 0:8e57f3e9cc89 532 #endif /* configUSE_RECURSIVE_MUTEXES */
rgrover1 0:8e57f3e9cc89 533 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 534
rgrover1 0:8e57f3e9cc89 535 #if ( configUSE_COUNTING_SEMAPHORES == 1 )
rgrover1 0:8e57f3e9cc89 536
rgrover1 0:8e57f3e9cc89 537 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )
rgrover1 0:8e57f3e9cc89 538 {
rgrover1 0:8e57f3e9cc89 539 xQueueHandle xHandle;
rgrover1 0:8e57f3e9cc89 540
rgrover1 0:8e57f3e9cc89 541 configASSERT( uxMaxCount != 0 );
rgrover1 0:8e57f3e9cc89 542 configASSERT( uxInitialCount <= uxMaxCount );
rgrover1 0:8e57f3e9cc89 543
rgrover1 0:8e57f3e9cc89 544 xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
rgrover1 0:8e57f3e9cc89 545
rgrover1 0:8e57f3e9cc89 546 if( xHandle != NULL )
rgrover1 0:8e57f3e9cc89 547 {
rgrover1 0:8e57f3e9cc89 548 ( ( xQUEUE * ) xHandle )->uxMessagesWaiting = uxInitialCount;
rgrover1 0:8e57f3e9cc89 549
rgrover1 0:8e57f3e9cc89 550 traceCREATE_COUNTING_SEMAPHORE();
rgrover1 0:8e57f3e9cc89 551 }
rgrover1 0:8e57f3e9cc89 552 else
rgrover1 0:8e57f3e9cc89 553 {
rgrover1 0:8e57f3e9cc89 554 traceCREATE_COUNTING_SEMAPHORE_FAILED();
rgrover1 0:8e57f3e9cc89 555 }
rgrover1 0:8e57f3e9cc89 556
rgrover1 0:8e57f3e9cc89 557 configASSERT( xHandle );
rgrover1 0:8e57f3e9cc89 558 return xHandle;
rgrover1 0:8e57f3e9cc89 559 }
rgrover1 0:8e57f3e9cc89 560
rgrover1 0:8e57f3e9cc89 561 #endif /* configUSE_COUNTING_SEMAPHORES */
rgrover1 0:8e57f3e9cc89 562 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 563
rgrover1 0:8e57f3e9cc89 564 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
rgrover1 0:8e57f3e9cc89 565 {
rgrover1 0:8e57f3e9cc89 566 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
rgrover1 0:8e57f3e9cc89 567 xTimeOutType xTimeOut;
rgrover1 0:8e57f3e9cc89 568 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 569
rgrover1 0:8e57f3e9cc89 570 configASSERT( pxQueue );
rgrover1 0:8e57f3e9cc89 571 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
rgrover1 0:8e57f3e9cc89 572 configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
rgrover1 0:8e57f3e9cc89 573
rgrover1 0:8e57f3e9cc89 574 /* This function relaxes the coding standard somewhat to allow return
rgrover1 0:8e57f3e9cc89 575 statements within the function itself. This is done in the interest
rgrover1 0:8e57f3e9cc89 576 of execution time efficiency. */
rgrover1 0:8e57f3e9cc89 577 for( ;; )
rgrover1 0:8e57f3e9cc89 578 {
rgrover1 0:8e57f3e9cc89 579 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 580 {
rgrover1 0:8e57f3e9cc89 581 /* Is there room on the queue now? The running task must be
rgrover1 0:8e57f3e9cc89 582 the highest priority task wanting to access the queue. If
rgrover1 0:8e57f3e9cc89 583 the head item in the queue is to be overwritten then it does
rgrover1 0:8e57f3e9cc89 584 not matter if the queue is full. */
rgrover1 0:8e57f3e9cc89 585 if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
rgrover1 0:8e57f3e9cc89 586 {
rgrover1 0:8e57f3e9cc89 587 traceQUEUE_SEND( pxQueue );
rgrover1 0:8e57f3e9cc89 588 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
rgrover1 0:8e57f3e9cc89 589
rgrover1 0:8e57f3e9cc89 590 #if ( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 591 {
rgrover1 0:8e57f3e9cc89 592 if( pxQueue->pxQueueSetContainer != NULL )
rgrover1 0:8e57f3e9cc89 593 {
rgrover1 0:8e57f3e9cc89 594 if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
rgrover1 0:8e57f3e9cc89 595 {
rgrover1 0:8e57f3e9cc89 596 /* The queue is a member of a queue set, and posting
rgrover1 0:8e57f3e9cc89 597 to the queue set caused a higher priority task to
rgrover1 0:8e57f3e9cc89 598 unblock. A context switch is required. */
rgrover1 0:8e57f3e9cc89 599 queueYIELD_IF_USING_PREEMPTION();
rgrover1 0:8e57f3e9cc89 600 }
rgrover1 0:8e57f3e9cc89 601 }
rgrover1 0:8e57f3e9cc89 602 else
rgrover1 0:8e57f3e9cc89 603 {
rgrover1 0:8e57f3e9cc89 604 /* If there was a task waiting for data to arrive on the
rgrover1 0:8e57f3e9cc89 605 queue then unblock it now. */
rgrover1 0:8e57f3e9cc89 606 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 607 {
rgrover1 0:8e57f3e9cc89 608 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
rgrover1 0:8e57f3e9cc89 609 {
rgrover1 0:8e57f3e9cc89 610 /* The unblocked task has a priority higher than
rgrover1 0:8e57f3e9cc89 611 our own so yield immediately. Yes it is ok to
rgrover1 0:8e57f3e9cc89 612 do this from within the critical section - the
rgrover1 0:8e57f3e9cc89 613 kernel takes care of that. */
rgrover1 0:8e57f3e9cc89 614 queueYIELD_IF_USING_PREEMPTION();
rgrover1 0:8e57f3e9cc89 615 }
rgrover1 0:8e57f3e9cc89 616 }
rgrover1 0:8e57f3e9cc89 617 }
rgrover1 0:8e57f3e9cc89 618 }
rgrover1 0:8e57f3e9cc89 619 #else /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 620 {
rgrover1 0:8e57f3e9cc89 621 /* If there was a task waiting for data to arrive on the
rgrover1 0:8e57f3e9cc89 622 queue then unblock it now. */
rgrover1 0:8e57f3e9cc89 623 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 624 {
rgrover1 0:8e57f3e9cc89 625 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
rgrover1 0:8e57f3e9cc89 626 {
rgrover1 0:8e57f3e9cc89 627 /* The unblocked task has a priority higher than
rgrover1 0:8e57f3e9cc89 628 our own so yield immediately. Yes it is ok to do
rgrover1 0:8e57f3e9cc89 629 this from within the critical section - the kernel
rgrover1 0:8e57f3e9cc89 630 takes care of that. */
rgrover1 0:8e57f3e9cc89 631 queueYIELD_IF_USING_PREEMPTION();
rgrover1 0:8e57f3e9cc89 632 }
rgrover1 0:8e57f3e9cc89 633 }
rgrover1 0:8e57f3e9cc89 634 }
rgrover1 0:8e57f3e9cc89 635 #endif /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 636
rgrover1 0:8e57f3e9cc89 637 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 638
rgrover1 0:8e57f3e9cc89 639 /* Return to the original privilege level before exiting the
rgrover1 0:8e57f3e9cc89 640 function. */
rgrover1 0:8e57f3e9cc89 641 return pdPASS;
rgrover1 0:8e57f3e9cc89 642 }
rgrover1 0:8e57f3e9cc89 643 else
rgrover1 0:8e57f3e9cc89 644 {
rgrover1 0:8e57f3e9cc89 645 if( xTicksToWait == ( portTickType ) 0 )
rgrover1 0:8e57f3e9cc89 646 {
rgrover1 0:8e57f3e9cc89 647 /* The queue was full and no block time is specified (or
rgrover1 0:8e57f3e9cc89 648 the block time has expired) so leave now. */
rgrover1 0:8e57f3e9cc89 649 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 650
rgrover1 0:8e57f3e9cc89 651 /* Return to the original privilege level before exiting
rgrover1 0:8e57f3e9cc89 652 the function. */
rgrover1 0:8e57f3e9cc89 653 traceQUEUE_SEND_FAILED( pxQueue );
rgrover1 0:8e57f3e9cc89 654 return errQUEUE_FULL;
rgrover1 0:8e57f3e9cc89 655 }
rgrover1 0:8e57f3e9cc89 656 else if( xEntryTimeSet == pdFALSE )
rgrover1 0:8e57f3e9cc89 657 {
rgrover1 0:8e57f3e9cc89 658 /* The queue was full and a block time was specified so
rgrover1 0:8e57f3e9cc89 659 configure the timeout structure. */
rgrover1 0:8e57f3e9cc89 660 vTaskSetTimeOutState( &xTimeOut );
rgrover1 0:8e57f3e9cc89 661 xEntryTimeSet = pdTRUE;
rgrover1 0:8e57f3e9cc89 662 }
rgrover1 0:8e57f3e9cc89 663 else
rgrover1 0:8e57f3e9cc89 664 {
rgrover1 0:8e57f3e9cc89 665 /* Entry time was already set. */
rgrover1 0:8e57f3e9cc89 666 }
rgrover1 0:8e57f3e9cc89 667 }
rgrover1 0:8e57f3e9cc89 668 }
rgrover1 0:8e57f3e9cc89 669 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 670
rgrover1 0:8e57f3e9cc89 671 /* Interrupts and other tasks can send to and receive from the queue
rgrover1 0:8e57f3e9cc89 672 now the critical section has been exited. */
rgrover1 0:8e57f3e9cc89 673
rgrover1 0:8e57f3e9cc89 674 vTaskSuspendAll();
rgrover1 0:8e57f3e9cc89 675 prvLockQueue( pxQueue );
rgrover1 0:8e57f3e9cc89 676
rgrover1 0:8e57f3e9cc89 677 /* Update the timeout state to see if it has expired yet. */
rgrover1 0:8e57f3e9cc89 678 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 679 {
rgrover1 0:8e57f3e9cc89 680 if( prvIsQueueFull( pxQueue ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 681 {
rgrover1 0:8e57f3e9cc89 682 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
rgrover1 0:8e57f3e9cc89 683 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
rgrover1 0:8e57f3e9cc89 684
rgrover1 0:8e57f3e9cc89 685 /* Unlocking the queue means queue events can effect the
rgrover1 0:8e57f3e9cc89 686 event list. It is possible that interrupts occurring now
rgrover1 0:8e57f3e9cc89 687 remove this task from the event list again - but as the
rgrover1 0:8e57f3e9cc89 688 scheduler is suspended the task will go onto the pending
rgrover1 0:8e57f3e9cc89 689 ready last instead of the actual ready list. */
rgrover1 0:8e57f3e9cc89 690 prvUnlockQueue( pxQueue );
rgrover1 0:8e57f3e9cc89 691
rgrover1 0:8e57f3e9cc89 692 /* Resuming the scheduler will move tasks from the pending
rgrover1 0:8e57f3e9cc89 693 ready list into the ready list - so it is feasible that this
rgrover1 0:8e57f3e9cc89 694 task is already in a ready list before it yields - in which
rgrover1 0:8e57f3e9cc89 695 case the yield will not cause a context switch unless there
rgrover1 0:8e57f3e9cc89 696 is also a higher priority task in the pending ready list. */
rgrover1 0:8e57f3e9cc89 697 if( xTaskResumeAll() == pdFALSE )
rgrover1 0:8e57f3e9cc89 698 {
rgrover1 0:8e57f3e9cc89 699 portYIELD_WITHIN_API();
rgrover1 0:8e57f3e9cc89 700 }
rgrover1 0:8e57f3e9cc89 701 }
rgrover1 0:8e57f3e9cc89 702 else
rgrover1 0:8e57f3e9cc89 703 {
rgrover1 0:8e57f3e9cc89 704 /* Try again. */
rgrover1 0:8e57f3e9cc89 705 prvUnlockQueue( pxQueue );
rgrover1 0:8e57f3e9cc89 706 ( void ) xTaskResumeAll();
rgrover1 0:8e57f3e9cc89 707 }
rgrover1 0:8e57f3e9cc89 708 }
rgrover1 0:8e57f3e9cc89 709 else
rgrover1 0:8e57f3e9cc89 710 {
rgrover1 0:8e57f3e9cc89 711 /* The timeout has expired. */
rgrover1 0:8e57f3e9cc89 712 prvUnlockQueue( pxQueue );
rgrover1 0:8e57f3e9cc89 713 ( void ) xTaskResumeAll();
rgrover1 0:8e57f3e9cc89 714
rgrover1 0:8e57f3e9cc89 715 /* Return to the original privilege level before exiting the
rgrover1 0:8e57f3e9cc89 716 function. */
rgrover1 0:8e57f3e9cc89 717 traceQUEUE_SEND_FAILED( pxQueue );
rgrover1 0:8e57f3e9cc89 718 return errQUEUE_FULL;
rgrover1 0:8e57f3e9cc89 719 }
rgrover1 0:8e57f3e9cc89 720 }
rgrover1 0:8e57f3e9cc89 721 }
rgrover1 0:8e57f3e9cc89 722 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 723
rgrover1 0:8e57f3e9cc89 724 #if ( configUSE_ALTERNATIVE_API == 1 )
rgrover1 0:8e57f3e9cc89 725
rgrover1 0:8e57f3e9cc89 726 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
rgrover1 0:8e57f3e9cc89 727 {
rgrover1 0:8e57f3e9cc89 728 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
rgrover1 0:8e57f3e9cc89 729 xTimeOutType xTimeOut;
rgrover1 0:8e57f3e9cc89 730 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 731
rgrover1 0:8e57f3e9cc89 732 configASSERT( pxQueue );
rgrover1 0:8e57f3e9cc89 733 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
rgrover1 0:8e57f3e9cc89 734
rgrover1 0:8e57f3e9cc89 735 for( ;; )
rgrover1 0:8e57f3e9cc89 736 {
rgrover1 0:8e57f3e9cc89 737 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 738 {
rgrover1 0:8e57f3e9cc89 739 /* Is there room on the queue now? To be running we must be
rgrover1 0:8e57f3e9cc89 740 the highest priority task wanting to access the queue. */
rgrover1 0:8e57f3e9cc89 741 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
rgrover1 0:8e57f3e9cc89 742 {
rgrover1 0:8e57f3e9cc89 743 traceQUEUE_SEND( pxQueue );
rgrover1 0:8e57f3e9cc89 744 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
rgrover1 0:8e57f3e9cc89 745
rgrover1 0:8e57f3e9cc89 746 /* If there was a task waiting for data to arrive on the
rgrover1 0:8e57f3e9cc89 747 queue then unblock it now. */
rgrover1 0:8e57f3e9cc89 748 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 749 {
rgrover1 0:8e57f3e9cc89 750 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
rgrover1 0:8e57f3e9cc89 751 {
rgrover1 0:8e57f3e9cc89 752 /* The unblocked task has a priority higher than
rgrover1 0:8e57f3e9cc89 753 our own so yield immediately. */
rgrover1 0:8e57f3e9cc89 754 portYIELD_WITHIN_API();
rgrover1 0:8e57f3e9cc89 755 }
rgrover1 0:8e57f3e9cc89 756 }
rgrover1 0:8e57f3e9cc89 757
rgrover1 0:8e57f3e9cc89 758 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 759 return pdPASS;
rgrover1 0:8e57f3e9cc89 760 }
rgrover1 0:8e57f3e9cc89 761 else
rgrover1 0:8e57f3e9cc89 762 {
rgrover1 0:8e57f3e9cc89 763 if( xTicksToWait == ( portTickType ) 0 )
rgrover1 0:8e57f3e9cc89 764 {
rgrover1 0:8e57f3e9cc89 765 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 766 return errQUEUE_FULL;
rgrover1 0:8e57f3e9cc89 767 }
rgrover1 0:8e57f3e9cc89 768 else if( xEntryTimeSet == pdFALSE )
rgrover1 0:8e57f3e9cc89 769 {
rgrover1 0:8e57f3e9cc89 770 vTaskSetTimeOutState( &xTimeOut );
rgrover1 0:8e57f3e9cc89 771 xEntryTimeSet = pdTRUE;
rgrover1 0:8e57f3e9cc89 772 }
rgrover1 0:8e57f3e9cc89 773 }
rgrover1 0:8e57f3e9cc89 774 }
rgrover1 0:8e57f3e9cc89 775 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 776
rgrover1 0:8e57f3e9cc89 777 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 778 {
rgrover1 0:8e57f3e9cc89 779 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 780 {
rgrover1 0:8e57f3e9cc89 781 if( prvIsQueueFull( pxQueue ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 782 {
rgrover1 0:8e57f3e9cc89 783 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
rgrover1 0:8e57f3e9cc89 784 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
rgrover1 0:8e57f3e9cc89 785 portYIELD_WITHIN_API();
rgrover1 0:8e57f3e9cc89 786 }
rgrover1 0:8e57f3e9cc89 787 }
rgrover1 0:8e57f3e9cc89 788 else
rgrover1 0:8e57f3e9cc89 789 {
rgrover1 0:8e57f3e9cc89 790 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 791 traceQUEUE_SEND_FAILED( pxQueue );
rgrover1 0:8e57f3e9cc89 792 return errQUEUE_FULL;
rgrover1 0:8e57f3e9cc89 793 }
rgrover1 0:8e57f3e9cc89 794 }
rgrover1 0:8e57f3e9cc89 795 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 796 }
rgrover1 0:8e57f3e9cc89 797 }
rgrover1 0:8e57f3e9cc89 798
rgrover1 0:8e57f3e9cc89 799 #endif /* configUSE_ALTERNATIVE_API */
rgrover1 0:8e57f3e9cc89 800 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 801
rgrover1 0:8e57f3e9cc89 802 #if ( configUSE_ALTERNATIVE_API == 1 )
rgrover1 0:8e57f3e9cc89 803
rgrover1 0:8e57f3e9cc89 804 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
rgrover1 0:8e57f3e9cc89 805 {
rgrover1 0:8e57f3e9cc89 806 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
rgrover1 0:8e57f3e9cc89 807 xTimeOutType xTimeOut;
rgrover1 0:8e57f3e9cc89 808 signed char *pcOriginalReadPosition;
rgrover1 0:8e57f3e9cc89 809 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 810
rgrover1 0:8e57f3e9cc89 811 configASSERT( pxQueue );
rgrover1 0:8e57f3e9cc89 812 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
rgrover1 0:8e57f3e9cc89 813
rgrover1 0:8e57f3e9cc89 814 for( ;; )
rgrover1 0:8e57f3e9cc89 815 {
rgrover1 0:8e57f3e9cc89 816 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 817 {
rgrover1 0:8e57f3e9cc89 818 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 819 {
rgrover1 0:8e57f3e9cc89 820 /* Remember our read position in case we are just peeking. */
rgrover1 0:8e57f3e9cc89 821 pcOriginalReadPosition = pxQueue->u.pcReadFrom;
rgrover1 0:8e57f3e9cc89 822
rgrover1 0:8e57f3e9cc89 823 prvCopyDataFromQueue( pxQueue, pvBuffer );
rgrover1 0:8e57f3e9cc89 824
rgrover1 0:8e57f3e9cc89 825 if( xJustPeeking == pdFALSE )
rgrover1 0:8e57f3e9cc89 826 {
rgrover1 0:8e57f3e9cc89 827 traceQUEUE_RECEIVE( pxQueue );
rgrover1 0:8e57f3e9cc89 828
rgrover1 0:8e57f3e9cc89 829 /* Data is actually being removed (not just peeked). */
rgrover1 0:8e57f3e9cc89 830 --( pxQueue->uxMessagesWaiting );
rgrover1 0:8e57f3e9cc89 831
rgrover1 0:8e57f3e9cc89 832 #if ( configUSE_MUTEXES == 1 )
rgrover1 0:8e57f3e9cc89 833 {
rgrover1 0:8e57f3e9cc89 834 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
rgrover1 0:8e57f3e9cc89 835 {
rgrover1 0:8e57f3e9cc89 836 /* Record the information required to implement
rgrover1 0:8e57f3e9cc89 837 priority inheritance should it become necessary. */
rgrover1 0:8e57f3e9cc89 838 pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle();
rgrover1 0:8e57f3e9cc89 839 }
rgrover1 0:8e57f3e9cc89 840 }
rgrover1 0:8e57f3e9cc89 841 #endif
rgrover1 0:8e57f3e9cc89 842
rgrover1 0:8e57f3e9cc89 843 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 844 {
rgrover1 0:8e57f3e9cc89 845 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
rgrover1 0:8e57f3e9cc89 846 {
rgrover1 0:8e57f3e9cc89 847 portYIELD_WITHIN_API();
rgrover1 0:8e57f3e9cc89 848 }
rgrover1 0:8e57f3e9cc89 849 }
rgrover1 0:8e57f3e9cc89 850 }
rgrover1 0:8e57f3e9cc89 851 else
rgrover1 0:8e57f3e9cc89 852 {
rgrover1 0:8e57f3e9cc89 853 traceQUEUE_PEEK( pxQueue );
rgrover1 0:8e57f3e9cc89 854
rgrover1 0:8e57f3e9cc89 855 /* We are not removing the data, so reset our read
rgrover1 0:8e57f3e9cc89 856 pointer. */
rgrover1 0:8e57f3e9cc89 857 pxQueue->u.pcReadFrom = pcOriginalReadPosition;
rgrover1 0:8e57f3e9cc89 858
rgrover1 0:8e57f3e9cc89 859 /* The data is being left in the queue, so see if there are
rgrover1 0:8e57f3e9cc89 860 any other tasks waiting for the data. */
rgrover1 0:8e57f3e9cc89 861 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 862 {
rgrover1 0:8e57f3e9cc89 863 /* Tasks that are removed from the event list will get added to
rgrover1 0:8e57f3e9cc89 864 the pending ready list as the scheduler is still suspended. */
rgrover1 0:8e57f3e9cc89 865 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 866 {
rgrover1 0:8e57f3e9cc89 867 /* The task waiting has a higher priority than this task. */
rgrover1 0:8e57f3e9cc89 868 portYIELD_WITHIN_API();
rgrover1 0:8e57f3e9cc89 869 }
rgrover1 0:8e57f3e9cc89 870 }
rgrover1 0:8e57f3e9cc89 871
rgrover1 0:8e57f3e9cc89 872 }
rgrover1 0:8e57f3e9cc89 873
rgrover1 0:8e57f3e9cc89 874 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 875 return pdPASS;
rgrover1 0:8e57f3e9cc89 876 }
rgrover1 0:8e57f3e9cc89 877 else
rgrover1 0:8e57f3e9cc89 878 {
rgrover1 0:8e57f3e9cc89 879 if( xTicksToWait == ( portTickType ) 0 )
rgrover1 0:8e57f3e9cc89 880 {
rgrover1 0:8e57f3e9cc89 881 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 882 traceQUEUE_RECEIVE_FAILED( pxQueue );
rgrover1 0:8e57f3e9cc89 883 return errQUEUE_EMPTY;
rgrover1 0:8e57f3e9cc89 884 }
rgrover1 0:8e57f3e9cc89 885 else if( xEntryTimeSet == pdFALSE )
rgrover1 0:8e57f3e9cc89 886 {
rgrover1 0:8e57f3e9cc89 887 vTaskSetTimeOutState( &xTimeOut );
rgrover1 0:8e57f3e9cc89 888 xEntryTimeSet = pdTRUE;
rgrover1 0:8e57f3e9cc89 889 }
rgrover1 0:8e57f3e9cc89 890 }
rgrover1 0:8e57f3e9cc89 891 }
rgrover1 0:8e57f3e9cc89 892 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 893
rgrover1 0:8e57f3e9cc89 894 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 895 {
rgrover1 0:8e57f3e9cc89 896 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 897 {
rgrover1 0:8e57f3e9cc89 898 if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 899 {
rgrover1 0:8e57f3e9cc89 900 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
rgrover1 0:8e57f3e9cc89 901
rgrover1 0:8e57f3e9cc89 902 #if ( configUSE_MUTEXES == 1 )
rgrover1 0:8e57f3e9cc89 903 {
rgrover1 0:8e57f3e9cc89 904 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
rgrover1 0:8e57f3e9cc89 905 {
rgrover1 0:8e57f3e9cc89 906 portENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 907 {
rgrover1 0:8e57f3e9cc89 908 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
rgrover1 0:8e57f3e9cc89 909 }
rgrover1 0:8e57f3e9cc89 910 portEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 911 }
rgrover1 0:8e57f3e9cc89 912 }
rgrover1 0:8e57f3e9cc89 913 #endif
rgrover1 0:8e57f3e9cc89 914
rgrover1 0:8e57f3e9cc89 915 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
rgrover1 0:8e57f3e9cc89 916 portYIELD_WITHIN_API();
rgrover1 0:8e57f3e9cc89 917 }
rgrover1 0:8e57f3e9cc89 918 }
rgrover1 0:8e57f3e9cc89 919 else
rgrover1 0:8e57f3e9cc89 920 {
rgrover1 0:8e57f3e9cc89 921 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 922 traceQUEUE_RECEIVE_FAILED( pxQueue );
rgrover1 0:8e57f3e9cc89 923 return errQUEUE_EMPTY;
rgrover1 0:8e57f3e9cc89 924 }
rgrover1 0:8e57f3e9cc89 925 }
rgrover1 0:8e57f3e9cc89 926 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 927 }
rgrover1 0:8e57f3e9cc89 928 }
rgrover1 0:8e57f3e9cc89 929
rgrover1 0:8e57f3e9cc89 930
rgrover1 0:8e57f3e9cc89 931 #endif /* configUSE_ALTERNATIVE_API */
rgrover1 0:8e57f3e9cc89 932 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 933
rgrover1 0:8e57f3e9cc89 934 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
rgrover1 0:8e57f3e9cc89 935 {
rgrover1 0:8e57f3e9cc89 936 signed portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 937 unsigned portBASE_TYPE uxSavedInterruptStatus;
rgrover1 0:8e57f3e9cc89 938 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 939
rgrover1 0:8e57f3e9cc89 940 configASSERT( pxQueue );
rgrover1 0:8e57f3e9cc89 941 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
rgrover1 0:8e57f3e9cc89 942 configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
rgrover1 0:8e57f3e9cc89 943
rgrover1 0:8e57f3e9cc89 944 /* RTOS ports that support interrupt nesting have the concept of a maximum
rgrover1 0:8e57f3e9cc89 945 system call (or maximum API call) interrupt priority. Interrupts that are
rgrover1 0:8e57f3e9cc89 946 above the maximum system call priority are keep permanently enabled, even
rgrover1 0:8e57f3e9cc89 947 when the RTOS kernel is in a critical section, but cannot make any calls to
rgrover1 0:8e57f3e9cc89 948 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
rgrover1 0:8e57f3e9cc89 949 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
rgrover1 0:8e57f3e9cc89 950 failure if a FreeRTOS API function is called from an interrupt that has been
rgrover1 0:8e57f3e9cc89 951 assigned a priority above the configured maximum system call priority.
rgrover1 0:8e57f3e9cc89 952 Only FreeRTOS functions that end in FromISR can be called from interrupts
rgrover1 0:8e57f3e9cc89 953 that have been assigned a priority at or (logically) below the maximum
rgrover1 0:8e57f3e9cc89 954 system call interrupt priority. FreeRTOS maintains a separate interrupt
rgrover1 0:8e57f3e9cc89 955 safe API to ensure interrupt entry is as fast and as simple as possible.
rgrover1 0:8e57f3e9cc89 956 More information (albeit Cortex-M specific) is provided on the following
rgrover1 0:8e57f3e9cc89 957 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
rgrover1 0:8e57f3e9cc89 958 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
rgrover1 0:8e57f3e9cc89 959
rgrover1 0:8e57f3e9cc89 960 /* Similar to xQueueGenericSend, except we don't block if there is no room
rgrover1 0:8e57f3e9cc89 961 in the queue. Also we don't directly wake a task that was blocked on a
rgrover1 0:8e57f3e9cc89 962 queue read, instead we return a flag to say whether a context switch is
rgrover1 0:8e57f3e9cc89 963 required or not (i.e. has a task with a higher priority than us been woken
rgrover1 0:8e57f3e9cc89 964 by this post). */
rgrover1 0:8e57f3e9cc89 965 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
rgrover1 0:8e57f3e9cc89 966 {
rgrover1 0:8e57f3e9cc89 967 if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
rgrover1 0:8e57f3e9cc89 968 {
rgrover1 0:8e57f3e9cc89 969 traceQUEUE_SEND_FROM_ISR( pxQueue );
rgrover1 0:8e57f3e9cc89 970
rgrover1 0:8e57f3e9cc89 971 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
rgrover1 0:8e57f3e9cc89 972
rgrover1 0:8e57f3e9cc89 973 /* If the queue is locked we do not alter the event list. This will
rgrover1 0:8e57f3e9cc89 974 be done when the queue is unlocked later. */
rgrover1 0:8e57f3e9cc89 975 if( pxQueue->xTxLock == queueUNLOCKED )
rgrover1 0:8e57f3e9cc89 976 {
rgrover1 0:8e57f3e9cc89 977 #if ( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 978 {
rgrover1 0:8e57f3e9cc89 979 if( pxQueue->pxQueueSetContainer != NULL )
rgrover1 0:8e57f3e9cc89 980 {
rgrover1 0:8e57f3e9cc89 981 if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
rgrover1 0:8e57f3e9cc89 982 {
rgrover1 0:8e57f3e9cc89 983 /* The queue is a member of a queue set, and posting
rgrover1 0:8e57f3e9cc89 984 to the queue set caused a higher priority task to
rgrover1 0:8e57f3e9cc89 985 unblock. A context switch is required. */
rgrover1 0:8e57f3e9cc89 986 if( pxHigherPriorityTaskWoken != NULL )
rgrover1 0:8e57f3e9cc89 987 {
rgrover1 0:8e57f3e9cc89 988 *pxHigherPriorityTaskWoken = pdTRUE;
rgrover1 0:8e57f3e9cc89 989 }
rgrover1 0:8e57f3e9cc89 990 }
rgrover1 0:8e57f3e9cc89 991 }
rgrover1 0:8e57f3e9cc89 992 else
rgrover1 0:8e57f3e9cc89 993 {
rgrover1 0:8e57f3e9cc89 994 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 995 {
rgrover1 0:8e57f3e9cc89 996 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 997 {
rgrover1 0:8e57f3e9cc89 998 /* The task waiting has a higher priority so record that a
rgrover1 0:8e57f3e9cc89 999 context switch is required. */
rgrover1 0:8e57f3e9cc89 1000 if( pxHigherPriorityTaskWoken != NULL )
rgrover1 0:8e57f3e9cc89 1001 {
rgrover1 0:8e57f3e9cc89 1002 *pxHigherPriorityTaskWoken = pdTRUE;
rgrover1 0:8e57f3e9cc89 1003 }
rgrover1 0:8e57f3e9cc89 1004 }
rgrover1 0:8e57f3e9cc89 1005 }
rgrover1 0:8e57f3e9cc89 1006 }
rgrover1 0:8e57f3e9cc89 1007 }
rgrover1 0:8e57f3e9cc89 1008 #else /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 1009 {
rgrover1 0:8e57f3e9cc89 1010 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1011 {
rgrover1 0:8e57f3e9cc89 1012 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 1013 {
rgrover1 0:8e57f3e9cc89 1014 /* The task waiting has a higher priority so record that a
rgrover1 0:8e57f3e9cc89 1015 context switch is required. */
rgrover1 0:8e57f3e9cc89 1016 if( pxHigherPriorityTaskWoken != NULL )
rgrover1 0:8e57f3e9cc89 1017 {
rgrover1 0:8e57f3e9cc89 1018 *pxHigherPriorityTaskWoken = pdTRUE;
rgrover1 0:8e57f3e9cc89 1019 }
rgrover1 0:8e57f3e9cc89 1020 }
rgrover1 0:8e57f3e9cc89 1021 }
rgrover1 0:8e57f3e9cc89 1022 }
rgrover1 0:8e57f3e9cc89 1023 #endif /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 1024 }
rgrover1 0:8e57f3e9cc89 1025 else
rgrover1 0:8e57f3e9cc89 1026 {
rgrover1 0:8e57f3e9cc89 1027 /* Increment the lock count so the task that unlocks the queue
rgrover1 0:8e57f3e9cc89 1028 knows that data was posted while it was locked. */
rgrover1 0:8e57f3e9cc89 1029 ++( pxQueue->xTxLock );
rgrover1 0:8e57f3e9cc89 1030 }
rgrover1 0:8e57f3e9cc89 1031
rgrover1 0:8e57f3e9cc89 1032 xReturn = pdPASS;
rgrover1 0:8e57f3e9cc89 1033 }
rgrover1 0:8e57f3e9cc89 1034 else
rgrover1 0:8e57f3e9cc89 1035 {
rgrover1 0:8e57f3e9cc89 1036 traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
rgrover1 0:8e57f3e9cc89 1037 xReturn = errQUEUE_FULL;
rgrover1 0:8e57f3e9cc89 1038 }
rgrover1 0:8e57f3e9cc89 1039 }
rgrover1 0:8e57f3e9cc89 1040 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
rgrover1 0:8e57f3e9cc89 1041
rgrover1 0:8e57f3e9cc89 1042 return xReturn;
rgrover1 0:8e57f3e9cc89 1043 }
rgrover1 0:8e57f3e9cc89 1044 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1045
rgrover1 0:8e57f3e9cc89 1046 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
rgrover1 0:8e57f3e9cc89 1047 {
rgrover1 0:8e57f3e9cc89 1048 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
rgrover1 0:8e57f3e9cc89 1049 xTimeOutType xTimeOut;
rgrover1 0:8e57f3e9cc89 1050 signed char *pcOriginalReadPosition;
rgrover1 0:8e57f3e9cc89 1051 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 1052
rgrover1 0:8e57f3e9cc89 1053 configASSERT( pxQueue );
rgrover1 0:8e57f3e9cc89 1054 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
rgrover1 0:8e57f3e9cc89 1055
rgrover1 0:8e57f3e9cc89 1056 /* This function relaxes the coding standard somewhat to allow return
rgrover1 0:8e57f3e9cc89 1057 statements within the function itself. This is done in the interest
rgrover1 0:8e57f3e9cc89 1058 of execution time efficiency. */
rgrover1 0:8e57f3e9cc89 1059
rgrover1 0:8e57f3e9cc89 1060 for( ;; )
rgrover1 0:8e57f3e9cc89 1061 {
rgrover1 0:8e57f3e9cc89 1062 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 1063 {
rgrover1 0:8e57f3e9cc89 1064 /* Is there data in the queue now? To be running we must be
rgrover1 0:8e57f3e9cc89 1065 the highest priority task wanting to access the queue. */
rgrover1 0:8e57f3e9cc89 1066 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 1067 {
rgrover1 0:8e57f3e9cc89 1068 /* Remember the read position in case the queue is only being
rgrover1 0:8e57f3e9cc89 1069 peeked. */
rgrover1 0:8e57f3e9cc89 1070 pcOriginalReadPosition = pxQueue->u.pcReadFrom;
rgrover1 0:8e57f3e9cc89 1071
rgrover1 0:8e57f3e9cc89 1072 prvCopyDataFromQueue( pxQueue, pvBuffer );
rgrover1 0:8e57f3e9cc89 1073
rgrover1 0:8e57f3e9cc89 1074 if( xJustPeeking == pdFALSE )
rgrover1 0:8e57f3e9cc89 1075 {
rgrover1 0:8e57f3e9cc89 1076 traceQUEUE_RECEIVE( pxQueue );
rgrover1 0:8e57f3e9cc89 1077
rgrover1 0:8e57f3e9cc89 1078 /* Actually removing data, not just peeking. */
rgrover1 0:8e57f3e9cc89 1079 --( pxQueue->uxMessagesWaiting );
rgrover1 0:8e57f3e9cc89 1080
rgrover1 0:8e57f3e9cc89 1081 #if ( configUSE_MUTEXES == 1 )
rgrover1 0:8e57f3e9cc89 1082 {
rgrover1 0:8e57f3e9cc89 1083 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
rgrover1 0:8e57f3e9cc89 1084 {
rgrover1 0:8e57f3e9cc89 1085 /* Record the information required to implement
rgrover1 0:8e57f3e9cc89 1086 priority inheritance should it become necessary. */
rgrover1 0:8e57f3e9cc89 1087 pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */
rgrover1 0:8e57f3e9cc89 1088 }
rgrover1 0:8e57f3e9cc89 1089 }
rgrover1 0:8e57f3e9cc89 1090 #endif
rgrover1 0:8e57f3e9cc89 1091
rgrover1 0:8e57f3e9cc89 1092 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1093 {
rgrover1 0:8e57f3e9cc89 1094 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
rgrover1 0:8e57f3e9cc89 1095 {
rgrover1 0:8e57f3e9cc89 1096 queueYIELD_IF_USING_PREEMPTION();
rgrover1 0:8e57f3e9cc89 1097 }
rgrover1 0:8e57f3e9cc89 1098 }
rgrover1 0:8e57f3e9cc89 1099 }
rgrover1 0:8e57f3e9cc89 1100 else
rgrover1 0:8e57f3e9cc89 1101 {
rgrover1 0:8e57f3e9cc89 1102 traceQUEUE_PEEK( pxQueue );
rgrover1 0:8e57f3e9cc89 1103
rgrover1 0:8e57f3e9cc89 1104 /* The data is not being removed, so reset the read
rgrover1 0:8e57f3e9cc89 1105 pointer. */
rgrover1 0:8e57f3e9cc89 1106 pxQueue->u.pcReadFrom = pcOriginalReadPosition;
rgrover1 0:8e57f3e9cc89 1107
rgrover1 0:8e57f3e9cc89 1108 /* The data is being left in the queue, so see if there are
rgrover1 0:8e57f3e9cc89 1109 any other tasks waiting for the data. */
rgrover1 0:8e57f3e9cc89 1110 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1111 {
rgrover1 0:8e57f3e9cc89 1112 /* Tasks that are removed from the event list will get added to
rgrover1 0:8e57f3e9cc89 1113 the pending ready list as the scheduler is still suspended. */
rgrover1 0:8e57f3e9cc89 1114 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 1115 {
rgrover1 0:8e57f3e9cc89 1116 /* The task waiting has a higher priority than this task. */
rgrover1 0:8e57f3e9cc89 1117 queueYIELD_IF_USING_PREEMPTION();
rgrover1 0:8e57f3e9cc89 1118 }
rgrover1 0:8e57f3e9cc89 1119 }
rgrover1 0:8e57f3e9cc89 1120 }
rgrover1 0:8e57f3e9cc89 1121
rgrover1 0:8e57f3e9cc89 1122 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 1123 return pdPASS;
rgrover1 0:8e57f3e9cc89 1124 }
rgrover1 0:8e57f3e9cc89 1125 else
rgrover1 0:8e57f3e9cc89 1126 {
rgrover1 0:8e57f3e9cc89 1127 if( xTicksToWait == ( portTickType ) 0 )
rgrover1 0:8e57f3e9cc89 1128 {
rgrover1 0:8e57f3e9cc89 1129 /* The queue was empty and no block time is specified (or
rgrover1 0:8e57f3e9cc89 1130 the block time has expired) so leave now. */
rgrover1 0:8e57f3e9cc89 1131 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 1132 traceQUEUE_RECEIVE_FAILED( pxQueue );
rgrover1 0:8e57f3e9cc89 1133 return errQUEUE_EMPTY;
rgrover1 0:8e57f3e9cc89 1134 }
rgrover1 0:8e57f3e9cc89 1135 else if( xEntryTimeSet == pdFALSE )
rgrover1 0:8e57f3e9cc89 1136 {
rgrover1 0:8e57f3e9cc89 1137 /* The queue was empty and a block time was specified so
rgrover1 0:8e57f3e9cc89 1138 configure the timeout structure. */
rgrover1 0:8e57f3e9cc89 1139 vTaskSetTimeOutState( &xTimeOut );
rgrover1 0:8e57f3e9cc89 1140 xEntryTimeSet = pdTRUE;
rgrover1 0:8e57f3e9cc89 1141 }
rgrover1 0:8e57f3e9cc89 1142 else
rgrover1 0:8e57f3e9cc89 1143 {
rgrover1 0:8e57f3e9cc89 1144 /* Entry time was already set. */
rgrover1 0:8e57f3e9cc89 1145 }
rgrover1 0:8e57f3e9cc89 1146 }
rgrover1 0:8e57f3e9cc89 1147 }
rgrover1 0:8e57f3e9cc89 1148 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 1149
rgrover1 0:8e57f3e9cc89 1150 /* Interrupts and other tasks can send to and receive from the queue
rgrover1 0:8e57f3e9cc89 1151 now the critical section has been exited. */
rgrover1 0:8e57f3e9cc89 1152
rgrover1 0:8e57f3e9cc89 1153 vTaskSuspendAll();
rgrover1 0:8e57f3e9cc89 1154 prvLockQueue( pxQueue );
rgrover1 0:8e57f3e9cc89 1155
rgrover1 0:8e57f3e9cc89 1156 /* Update the timeout state to see if it has expired yet. */
rgrover1 0:8e57f3e9cc89 1157 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1158 {
rgrover1 0:8e57f3e9cc89 1159 if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 1160 {
rgrover1 0:8e57f3e9cc89 1161 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
rgrover1 0:8e57f3e9cc89 1162
rgrover1 0:8e57f3e9cc89 1163 #if ( configUSE_MUTEXES == 1 )
rgrover1 0:8e57f3e9cc89 1164 {
rgrover1 0:8e57f3e9cc89 1165 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
rgrover1 0:8e57f3e9cc89 1166 {
rgrover1 0:8e57f3e9cc89 1167 portENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 1168 {
rgrover1 0:8e57f3e9cc89 1169 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
rgrover1 0:8e57f3e9cc89 1170 }
rgrover1 0:8e57f3e9cc89 1171 portEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 1172 }
rgrover1 0:8e57f3e9cc89 1173 }
rgrover1 0:8e57f3e9cc89 1174 #endif
rgrover1 0:8e57f3e9cc89 1175
rgrover1 0:8e57f3e9cc89 1176 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
rgrover1 0:8e57f3e9cc89 1177 prvUnlockQueue( pxQueue );
rgrover1 0:8e57f3e9cc89 1178 if( xTaskResumeAll() == pdFALSE )
rgrover1 0:8e57f3e9cc89 1179 {
rgrover1 0:8e57f3e9cc89 1180 portYIELD_WITHIN_API();
rgrover1 0:8e57f3e9cc89 1181 }
rgrover1 0:8e57f3e9cc89 1182 }
rgrover1 0:8e57f3e9cc89 1183 else
rgrover1 0:8e57f3e9cc89 1184 {
rgrover1 0:8e57f3e9cc89 1185 /* Try again. */
rgrover1 0:8e57f3e9cc89 1186 prvUnlockQueue( pxQueue );
rgrover1 0:8e57f3e9cc89 1187 ( void ) xTaskResumeAll();
rgrover1 0:8e57f3e9cc89 1188 }
rgrover1 0:8e57f3e9cc89 1189 }
rgrover1 0:8e57f3e9cc89 1190 else
rgrover1 0:8e57f3e9cc89 1191 {
rgrover1 0:8e57f3e9cc89 1192 prvUnlockQueue( pxQueue );
rgrover1 0:8e57f3e9cc89 1193 ( void ) xTaskResumeAll();
rgrover1 0:8e57f3e9cc89 1194 traceQUEUE_RECEIVE_FAILED( pxQueue );
rgrover1 0:8e57f3e9cc89 1195 return errQUEUE_EMPTY;
rgrover1 0:8e57f3e9cc89 1196 }
rgrover1 0:8e57f3e9cc89 1197 }
rgrover1 0:8e57f3e9cc89 1198 }
rgrover1 0:8e57f3e9cc89 1199 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1200
rgrover1 0:8e57f3e9cc89 1201 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken )
rgrover1 0:8e57f3e9cc89 1202 {
rgrover1 0:8e57f3e9cc89 1203 signed portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 1204 unsigned portBASE_TYPE uxSavedInterruptStatus;
rgrover1 0:8e57f3e9cc89 1205 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 1206
rgrover1 0:8e57f3e9cc89 1207 configASSERT( pxQueue );
rgrover1 0:8e57f3e9cc89 1208 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
rgrover1 0:8e57f3e9cc89 1209
rgrover1 0:8e57f3e9cc89 1210 /* RTOS ports that support interrupt nesting have the concept of a maximum
rgrover1 0:8e57f3e9cc89 1211 system call (or maximum API call) interrupt priority. Interrupts that are
rgrover1 0:8e57f3e9cc89 1212 above the maximum system call priority are keep permanently enabled, even
rgrover1 0:8e57f3e9cc89 1213 when the RTOS kernel is in a critical section, but cannot make any calls to
rgrover1 0:8e57f3e9cc89 1214 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
rgrover1 0:8e57f3e9cc89 1215 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
rgrover1 0:8e57f3e9cc89 1216 failure if a FreeRTOS API function is called from an interrupt that has been
rgrover1 0:8e57f3e9cc89 1217 assigned a priority above the configured maximum system call priority.
rgrover1 0:8e57f3e9cc89 1218 Only FreeRTOS functions that end in FromISR can be called from interrupts
rgrover1 0:8e57f3e9cc89 1219 that have been assigned a priority at or (logically) below the maximum
rgrover1 0:8e57f3e9cc89 1220 system call interrupt priority. FreeRTOS maintains a separate interrupt
rgrover1 0:8e57f3e9cc89 1221 safe API to ensure interrupt entry is as fast and as simple as possible.
rgrover1 0:8e57f3e9cc89 1222 More information (albeit Cortex-M specific) is provided on the following
rgrover1 0:8e57f3e9cc89 1223 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
rgrover1 0:8e57f3e9cc89 1224 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
rgrover1 0:8e57f3e9cc89 1225
rgrover1 0:8e57f3e9cc89 1226 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
rgrover1 0:8e57f3e9cc89 1227 {
rgrover1 0:8e57f3e9cc89 1228 /* Cannot block in an ISR, so check there is data available. */
rgrover1 0:8e57f3e9cc89 1229 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 1230 {
rgrover1 0:8e57f3e9cc89 1231 traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
rgrover1 0:8e57f3e9cc89 1232
rgrover1 0:8e57f3e9cc89 1233 prvCopyDataFromQueue( pxQueue, pvBuffer );
rgrover1 0:8e57f3e9cc89 1234 --( pxQueue->uxMessagesWaiting );
rgrover1 0:8e57f3e9cc89 1235
rgrover1 0:8e57f3e9cc89 1236 /* If the queue is locked the event list will not be modified.
rgrover1 0:8e57f3e9cc89 1237 Instead update the lock count so the task that unlocks the queue
rgrover1 0:8e57f3e9cc89 1238 will know that an ISR has removed data while the queue was
rgrover1 0:8e57f3e9cc89 1239 locked. */
rgrover1 0:8e57f3e9cc89 1240 if( pxQueue->xRxLock == queueUNLOCKED )
rgrover1 0:8e57f3e9cc89 1241 {
rgrover1 0:8e57f3e9cc89 1242 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1243 {
rgrover1 0:8e57f3e9cc89 1244 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 1245 {
rgrover1 0:8e57f3e9cc89 1246 /* The task waiting has a higher priority than us so
rgrover1 0:8e57f3e9cc89 1247 force a context switch. */
rgrover1 0:8e57f3e9cc89 1248 if( pxHigherPriorityTaskWoken != NULL )
rgrover1 0:8e57f3e9cc89 1249 {
rgrover1 0:8e57f3e9cc89 1250 *pxHigherPriorityTaskWoken = pdTRUE;
rgrover1 0:8e57f3e9cc89 1251 }
rgrover1 0:8e57f3e9cc89 1252 }
rgrover1 0:8e57f3e9cc89 1253 }
rgrover1 0:8e57f3e9cc89 1254 }
rgrover1 0:8e57f3e9cc89 1255 else
rgrover1 0:8e57f3e9cc89 1256 {
rgrover1 0:8e57f3e9cc89 1257 /* Increment the lock count so the task that unlocks the queue
rgrover1 0:8e57f3e9cc89 1258 knows that data was removed while it was locked. */
rgrover1 0:8e57f3e9cc89 1259 ++( pxQueue->xRxLock );
rgrover1 0:8e57f3e9cc89 1260 }
rgrover1 0:8e57f3e9cc89 1261
rgrover1 0:8e57f3e9cc89 1262 xReturn = pdPASS;
rgrover1 0:8e57f3e9cc89 1263 }
rgrover1 0:8e57f3e9cc89 1264 else
rgrover1 0:8e57f3e9cc89 1265 {
rgrover1 0:8e57f3e9cc89 1266 xReturn = pdFAIL;
rgrover1 0:8e57f3e9cc89 1267 traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
rgrover1 0:8e57f3e9cc89 1268 }
rgrover1 0:8e57f3e9cc89 1269 }
rgrover1 0:8e57f3e9cc89 1270 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
rgrover1 0:8e57f3e9cc89 1271
rgrover1 0:8e57f3e9cc89 1272 return xReturn;
rgrover1 0:8e57f3e9cc89 1273 }
rgrover1 0:8e57f3e9cc89 1274 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1275
rgrover1 0:8e57f3e9cc89 1276 signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, void * const pvBuffer )
rgrover1 0:8e57f3e9cc89 1277 {
rgrover1 0:8e57f3e9cc89 1278 signed portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 1279 unsigned portBASE_TYPE uxSavedInterruptStatus;
rgrover1 0:8e57f3e9cc89 1280 signed char *pcOriginalReadPosition;
rgrover1 0:8e57f3e9cc89 1281 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 1282
rgrover1 0:8e57f3e9cc89 1283 configASSERT( pxQueue );
rgrover1 0:8e57f3e9cc89 1284 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
rgrover1 0:8e57f3e9cc89 1285
rgrover1 0:8e57f3e9cc89 1286 /* RTOS ports that support interrupt nesting have the concept of a maximum
rgrover1 0:8e57f3e9cc89 1287 system call (or maximum API call) interrupt priority. Interrupts that are
rgrover1 0:8e57f3e9cc89 1288 above the maximum system call priority are keep permanently enabled, even
rgrover1 0:8e57f3e9cc89 1289 when the RTOS kernel is in a critical section, but cannot make any calls to
rgrover1 0:8e57f3e9cc89 1290 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
rgrover1 0:8e57f3e9cc89 1291 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
rgrover1 0:8e57f3e9cc89 1292 failure if a FreeRTOS API function is called from an interrupt that has been
rgrover1 0:8e57f3e9cc89 1293 assigned a priority above the configured maximum system call priority.
rgrover1 0:8e57f3e9cc89 1294 Only FreeRTOS functions that end in FromISR can be called from interrupts
rgrover1 0:8e57f3e9cc89 1295 that have been assigned a priority at or (logically) below the maximum
rgrover1 0:8e57f3e9cc89 1296 system call interrupt priority. FreeRTOS maintains a separate interrupt
rgrover1 0:8e57f3e9cc89 1297 safe API to ensure interrupt entry is as fast and as simple as possible.
rgrover1 0:8e57f3e9cc89 1298 More information (albeit Cortex-M specific) is provided on the following
rgrover1 0:8e57f3e9cc89 1299 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
rgrover1 0:8e57f3e9cc89 1300 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
rgrover1 0:8e57f3e9cc89 1301
rgrover1 0:8e57f3e9cc89 1302 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
rgrover1 0:8e57f3e9cc89 1303 {
rgrover1 0:8e57f3e9cc89 1304 /* Cannot block in an ISR, so check there is data available. */
rgrover1 0:8e57f3e9cc89 1305 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 1306 {
rgrover1 0:8e57f3e9cc89 1307 traceQUEUE_PEEK_FROM_ISR( pxQueue );
rgrover1 0:8e57f3e9cc89 1308
rgrover1 0:8e57f3e9cc89 1309 /* Remember the read position so it can be reset as nothing is
rgrover1 0:8e57f3e9cc89 1310 actually being removed from the queue. */
rgrover1 0:8e57f3e9cc89 1311 pcOriginalReadPosition = pxQueue->u.pcReadFrom;
rgrover1 0:8e57f3e9cc89 1312 prvCopyDataFromQueue( pxQueue, pvBuffer );
rgrover1 0:8e57f3e9cc89 1313 pxQueue->u.pcReadFrom = pcOriginalReadPosition;
rgrover1 0:8e57f3e9cc89 1314
rgrover1 0:8e57f3e9cc89 1315 xReturn = pdPASS;
rgrover1 0:8e57f3e9cc89 1316 }
rgrover1 0:8e57f3e9cc89 1317 else
rgrover1 0:8e57f3e9cc89 1318 {
rgrover1 0:8e57f3e9cc89 1319 xReturn = pdFAIL;
rgrover1 0:8e57f3e9cc89 1320 traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue );
rgrover1 0:8e57f3e9cc89 1321 }
rgrover1 0:8e57f3e9cc89 1322 }
rgrover1 0:8e57f3e9cc89 1323 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
rgrover1 0:8e57f3e9cc89 1324
rgrover1 0:8e57f3e9cc89 1325 return xReturn;
rgrover1 0:8e57f3e9cc89 1326 }
rgrover1 0:8e57f3e9cc89 1327 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1328
rgrover1 0:8e57f3e9cc89 1329 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue )
rgrover1 0:8e57f3e9cc89 1330 {
rgrover1 0:8e57f3e9cc89 1331 unsigned portBASE_TYPE uxReturn;
rgrover1 0:8e57f3e9cc89 1332
rgrover1 0:8e57f3e9cc89 1333 configASSERT( xQueue );
rgrover1 0:8e57f3e9cc89 1334
rgrover1 0:8e57f3e9cc89 1335 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 1336 uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
rgrover1 0:8e57f3e9cc89 1337 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 1338
rgrover1 0:8e57f3e9cc89 1339 return uxReturn;
rgrover1 0:8e57f3e9cc89 1340 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
rgrover1 0:8e57f3e9cc89 1341 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1342
rgrover1 0:8e57f3e9cc89 1343 unsigned portBASE_TYPE uxQueueSpacesAvailable( const xQueueHandle xQueue )
rgrover1 0:8e57f3e9cc89 1344 {
rgrover1 0:8e57f3e9cc89 1345 unsigned portBASE_TYPE uxReturn;
rgrover1 0:8e57f3e9cc89 1346 xQUEUE *pxQueue;
rgrover1 0:8e57f3e9cc89 1347
rgrover1 0:8e57f3e9cc89 1348 pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 1349 configASSERT( pxQueue );
rgrover1 0:8e57f3e9cc89 1350
rgrover1 0:8e57f3e9cc89 1351 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 1352 uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting;
rgrover1 0:8e57f3e9cc89 1353 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 1354
rgrover1 0:8e57f3e9cc89 1355 return uxReturn;
rgrover1 0:8e57f3e9cc89 1356 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
rgrover1 0:8e57f3e9cc89 1357 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1358
rgrover1 0:8e57f3e9cc89 1359 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue )
rgrover1 0:8e57f3e9cc89 1360 {
rgrover1 0:8e57f3e9cc89 1361 unsigned portBASE_TYPE uxReturn;
rgrover1 0:8e57f3e9cc89 1362
rgrover1 0:8e57f3e9cc89 1363 configASSERT( xQueue );
rgrover1 0:8e57f3e9cc89 1364
rgrover1 0:8e57f3e9cc89 1365 uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
rgrover1 0:8e57f3e9cc89 1366
rgrover1 0:8e57f3e9cc89 1367 return uxReturn;
rgrover1 0:8e57f3e9cc89 1368 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
rgrover1 0:8e57f3e9cc89 1369 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1370
rgrover1 0:8e57f3e9cc89 1371 void vQueueDelete( xQueueHandle xQueue )
rgrover1 0:8e57f3e9cc89 1372 {
rgrover1 0:8e57f3e9cc89 1373 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 1374
rgrover1 0:8e57f3e9cc89 1375 configASSERT( pxQueue );
rgrover1 0:8e57f3e9cc89 1376
rgrover1 0:8e57f3e9cc89 1377 traceQUEUE_DELETE( pxQueue );
rgrover1 0:8e57f3e9cc89 1378 #if ( configQUEUE_REGISTRY_SIZE > 0 )
rgrover1 0:8e57f3e9cc89 1379 {
rgrover1 0:8e57f3e9cc89 1380 vQueueUnregisterQueue( pxQueue );
rgrover1 0:8e57f3e9cc89 1381 }
rgrover1 0:8e57f3e9cc89 1382 #endif
rgrover1 0:8e57f3e9cc89 1383 vPortFree( pxQueue->pcHead );
rgrover1 0:8e57f3e9cc89 1384 vPortFree( pxQueue );
rgrover1 0:8e57f3e9cc89 1385 }
rgrover1 0:8e57f3e9cc89 1386 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1387
rgrover1 0:8e57f3e9cc89 1388 #if ( configUSE_TRACE_FACILITY == 1 )
rgrover1 0:8e57f3e9cc89 1389
rgrover1 0:8e57f3e9cc89 1390 unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue )
rgrover1 0:8e57f3e9cc89 1391 {
rgrover1 0:8e57f3e9cc89 1392 return ( ( xQUEUE * ) xQueue )->ucQueueNumber;
rgrover1 0:8e57f3e9cc89 1393 }
rgrover1 0:8e57f3e9cc89 1394
rgrover1 0:8e57f3e9cc89 1395 #endif /* configUSE_TRACE_FACILITY */
rgrover1 0:8e57f3e9cc89 1396 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1397
rgrover1 0:8e57f3e9cc89 1398 #if ( configUSE_TRACE_FACILITY == 1 )
rgrover1 0:8e57f3e9cc89 1399
rgrover1 0:8e57f3e9cc89 1400 void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber )
rgrover1 0:8e57f3e9cc89 1401 {
rgrover1 0:8e57f3e9cc89 1402 ( ( xQUEUE * ) xQueue )->ucQueueNumber = ucQueueNumber;
rgrover1 0:8e57f3e9cc89 1403 }
rgrover1 0:8e57f3e9cc89 1404
rgrover1 0:8e57f3e9cc89 1405 #endif /* configUSE_TRACE_FACILITY */
rgrover1 0:8e57f3e9cc89 1406 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1407
rgrover1 0:8e57f3e9cc89 1408 #if ( configUSE_TRACE_FACILITY == 1 )
rgrover1 0:8e57f3e9cc89 1409
rgrover1 0:8e57f3e9cc89 1410 unsigned char ucQueueGetQueueType( xQueueHandle xQueue )
rgrover1 0:8e57f3e9cc89 1411 {
rgrover1 0:8e57f3e9cc89 1412 return ( ( xQUEUE * ) xQueue )->ucQueueType;
rgrover1 0:8e57f3e9cc89 1413 }
rgrover1 0:8e57f3e9cc89 1414
rgrover1 0:8e57f3e9cc89 1415 #endif /* configUSE_TRACE_FACILITY */
rgrover1 0:8e57f3e9cc89 1416 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1417
rgrover1 0:8e57f3e9cc89 1418 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
rgrover1 0:8e57f3e9cc89 1419 {
rgrover1 0:8e57f3e9cc89 1420 if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 1421 {
rgrover1 0:8e57f3e9cc89 1422 #if ( configUSE_MUTEXES == 1 )
rgrover1 0:8e57f3e9cc89 1423 {
rgrover1 0:8e57f3e9cc89 1424 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
rgrover1 0:8e57f3e9cc89 1425 {
rgrover1 0:8e57f3e9cc89 1426 /* The mutex is no longer being held. */
rgrover1 0:8e57f3e9cc89 1427 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
rgrover1 0:8e57f3e9cc89 1428 pxQueue->pxMutexHolder = NULL;
rgrover1 0:8e57f3e9cc89 1429 }
rgrover1 0:8e57f3e9cc89 1430 }
rgrover1 0:8e57f3e9cc89 1431 #endif /* configUSE_MUTEXES */
rgrover1 0:8e57f3e9cc89 1432 }
rgrover1 0:8e57f3e9cc89 1433 else if( xPosition == queueSEND_TO_BACK )
rgrover1 0:8e57f3e9cc89 1434 {
rgrover1 0:8e57f3e9cc89 1435 ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. */
rgrover1 0:8e57f3e9cc89 1436 pxQueue->pcWriteTo += pxQueue->uxItemSize;
rgrover1 0:8e57f3e9cc89 1437 if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
rgrover1 0:8e57f3e9cc89 1438 {
rgrover1 0:8e57f3e9cc89 1439 pxQueue->pcWriteTo = pxQueue->pcHead;
rgrover1 0:8e57f3e9cc89 1440 }
rgrover1 0:8e57f3e9cc89 1441 }
rgrover1 0:8e57f3e9cc89 1442 else
rgrover1 0:8e57f3e9cc89 1443 {
rgrover1 0:8e57f3e9cc89 1444 ( void ) memcpy( ( void * ) pxQueue->u.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
rgrover1 0:8e57f3e9cc89 1445 pxQueue->u.pcReadFrom -= pxQueue->uxItemSize;
rgrover1 0:8e57f3e9cc89 1446 if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
rgrover1 0:8e57f3e9cc89 1447 {
rgrover1 0:8e57f3e9cc89 1448 pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
rgrover1 0:8e57f3e9cc89 1449 }
rgrover1 0:8e57f3e9cc89 1450
rgrover1 0:8e57f3e9cc89 1451 if( xPosition == queueOVERWRITE )
rgrover1 0:8e57f3e9cc89 1452 {
rgrover1 0:8e57f3e9cc89 1453 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 1454 {
rgrover1 0:8e57f3e9cc89 1455 /* An item is not being added but overwritten, so subtract
rgrover1 0:8e57f3e9cc89 1456 one from the recorded number of items in the queue so when
rgrover1 0:8e57f3e9cc89 1457 one is added again below the number of recorded items remains
rgrover1 0:8e57f3e9cc89 1458 correct. */
rgrover1 0:8e57f3e9cc89 1459 --( pxQueue->uxMessagesWaiting );
rgrover1 0:8e57f3e9cc89 1460 }
rgrover1 0:8e57f3e9cc89 1461 }
rgrover1 0:8e57f3e9cc89 1462 }
rgrover1 0:8e57f3e9cc89 1463
rgrover1 0:8e57f3e9cc89 1464 ++( pxQueue->uxMessagesWaiting );
rgrover1 0:8e57f3e9cc89 1465 }
rgrover1 0:8e57f3e9cc89 1466 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1467
rgrover1 0:8e57f3e9cc89 1468 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, void * const pvBuffer )
rgrover1 0:8e57f3e9cc89 1469 {
rgrover1 0:8e57f3e9cc89 1470 if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
rgrover1 0:8e57f3e9cc89 1471 {
rgrover1 0:8e57f3e9cc89 1472 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
rgrover1 0:8e57f3e9cc89 1473 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */
rgrover1 0:8e57f3e9cc89 1474 {
rgrover1 0:8e57f3e9cc89 1475 pxQueue->u.pcReadFrom = pxQueue->pcHead;
rgrover1 0:8e57f3e9cc89 1476 }
rgrover1 0:8e57f3e9cc89 1477 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */
rgrover1 0:8e57f3e9cc89 1478 }
rgrover1 0:8e57f3e9cc89 1479 }
rgrover1 0:8e57f3e9cc89 1480 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1481
rgrover1 0:8e57f3e9cc89 1482 static void prvUnlockQueue( xQUEUE *pxQueue )
rgrover1 0:8e57f3e9cc89 1483 {
rgrover1 0:8e57f3e9cc89 1484 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
rgrover1 0:8e57f3e9cc89 1485
rgrover1 0:8e57f3e9cc89 1486 /* The lock counts contains the number of extra data items placed or
rgrover1 0:8e57f3e9cc89 1487 removed from the queue while the queue was locked. When a queue is
rgrover1 0:8e57f3e9cc89 1488 locked items can be added or removed, but the event lists cannot be
rgrover1 0:8e57f3e9cc89 1489 updated. */
rgrover1 0:8e57f3e9cc89 1490 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 1491 {
rgrover1 0:8e57f3e9cc89 1492 /* See if data was added to the queue while it was locked. */
rgrover1 0:8e57f3e9cc89 1493 while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
rgrover1 0:8e57f3e9cc89 1494 {
rgrover1 0:8e57f3e9cc89 1495 /* Data was posted while the queue was locked. Are any tasks
rgrover1 0:8e57f3e9cc89 1496 blocked waiting for data to become available? */
rgrover1 0:8e57f3e9cc89 1497 #if ( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 1498 {
rgrover1 0:8e57f3e9cc89 1499 if( pxQueue->pxQueueSetContainer != NULL )
rgrover1 0:8e57f3e9cc89 1500 {
rgrover1 0:8e57f3e9cc89 1501 if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE )
rgrover1 0:8e57f3e9cc89 1502 {
rgrover1 0:8e57f3e9cc89 1503 /* The queue is a member of a queue set, and posting to
rgrover1 0:8e57f3e9cc89 1504 the queue set caused a higher priority task to unblock.
rgrover1 0:8e57f3e9cc89 1505 A context switch is required. */
rgrover1 0:8e57f3e9cc89 1506 vTaskMissedYield();
rgrover1 0:8e57f3e9cc89 1507 }
rgrover1 0:8e57f3e9cc89 1508 }
rgrover1 0:8e57f3e9cc89 1509 else
rgrover1 0:8e57f3e9cc89 1510 {
rgrover1 0:8e57f3e9cc89 1511 /* Tasks that are removed from the event list will get added to
rgrover1 0:8e57f3e9cc89 1512 the pending ready list as the scheduler is still suspended. */
rgrover1 0:8e57f3e9cc89 1513 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1514 {
rgrover1 0:8e57f3e9cc89 1515 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 1516 {
rgrover1 0:8e57f3e9cc89 1517 /* The task waiting has a higher priority so record that a
rgrover1 0:8e57f3e9cc89 1518 context switch is required. */
rgrover1 0:8e57f3e9cc89 1519 vTaskMissedYield();
rgrover1 0:8e57f3e9cc89 1520 }
rgrover1 0:8e57f3e9cc89 1521 }
rgrover1 0:8e57f3e9cc89 1522 else
rgrover1 0:8e57f3e9cc89 1523 {
rgrover1 0:8e57f3e9cc89 1524 break;
rgrover1 0:8e57f3e9cc89 1525 }
rgrover1 0:8e57f3e9cc89 1526 }
rgrover1 0:8e57f3e9cc89 1527 }
rgrover1 0:8e57f3e9cc89 1528 #else /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 1529 {
rgrover1 0:8e57f3e9cc89 1530 /* Tasks that are removed from the event list will get added to
rgrover1 0:8e57f3e9cc89 1531 the pending ready list as the scheduler is still suspended. */
rgrover1 0:8e57f3e9cc89 1532 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1533 {
rgrover1 0:8e57f3e9cc89 1534 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 1535 {
rgrover1 0:8e57f3e9cc89 1536 /* The task waiting has a higher priority so record that a
rgrover1 0:8e57f3e9cc89 1537 context switch is required. */
rgrover1 0:8e57f3e9cc89 1538 vTaskMissedYield();
rgrover1 0:8e57f3e9cc89 1539 }
rgrover1 0:8e57f3e9cc89 1540 }
rgrover1 0:8e57f3e9cc89 1541 else
rgrover1 0:8e57f3e9cc89 1542 {
rgrover1 0:8e57f3e9cc89 1543 break;
rgrover1 0:8e57f3e9cc89 1544 }
rgrover1 0:8e57f3e9cc89 1545 }
rgrover1 0:8e57f3e9cc89 1546 #endif /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 1547
rgrover1 0:8e57f3e9cc89 1548 --( pxQueue->xTxLock );
rgrover1 0:8e57f3e9cc89 1549 }
rgrover1 0:8e57f3e9cc89 1550
rgrover1 0:8e57f3e9cc89 1551 pxQueue->xTxLock = queueUNLOCKED;
rgrover1 0:8e57f3e9cc89 1552 }
rgrover1 0:8e57f3e9cc89 1553 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 1554
rgrover1 0:8e57f3e9cc89 1555 /* Do the same for the Rx lock. */
rgrover1 0:8e57f3e9cc89 1556 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 1557 {
rgrover1 0:8e57f3e9cc89 1558 while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
rgrover1 0:8e57f3e9cc89 1559 {
rgrover1 0:8e57f3e9cc89 1560 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1561 {
rgrover1 0:8e57f3e9cc89 1562 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 1563 {
rgrover1 0:8e57f3e9cc89 1564 vTaskMissedYield();
rgrover1 0:8e57f3e9cc89 1565 }
rgrover1 0:8e57f3e9cc89 1566
rgrover1 0:8e57f3e9cc89 1567 --( pxQueue->xRxLock );
rgrover1 0:8e57f3e9cc89 1568 }
rgrover1 0:8e57f3e9cc89 1569 else
rgrover1 0:8e57f3e9cc89 1570 {
rgrover1 0:8e57f3e9cc89 1571 break;
rgrover1 0:8e57f3e9cc89 1572 }
rgrover1 0:8e57f3e9cc89 1573 }
rgrover1 0:8e57f3e9cc89 1574
rgrover1 0:8e57f3e9cc89 1575 pxQueue->xRxLock = queueUNLOCKED;
rgrover1 0:8e57f3e9cc89 1576 }
rgrover1 0:8e57f3e9cc89 1577 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 1578 }
rgrover1 0:8e57f3e9cc89 1579 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1580
rgrover1 0:8e57f3e9cc89 1581 static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue )
rgrover1 0:8e57f3e9cc89 1582 {
rgrover1 0:8e57f3e9cc89 1583 signed portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 1584
rgrover1 0:8e57f3e9cc89 1585 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 1586 {
rgrover1 0:8e57f3e9cc89 1587 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 1588 {
rgrover1 0:8e57f3e9cc89 1589 xReturn = pdTRUE;
rgrover1 0:8e57f3e9cc89 1590 }
rgrover1 0:8e57f3e9cc89 1591 else
rgrover1 0:8e57f3e9cc89 1592 {
rgrover1 0:8e57f3e9cc89 1593 xReturn = pdFALSE;
rgrover1 0:8e57f3e9cc89 1594 }
rgrover1 0:8e57f3e9cc89 1595 }
rgrover1 0:8e57f3e9cc89 1596 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 1597
rgrover1 0:8e57f3e9cc89 1598 return xReturn;
rgrover1 0:8e57f3e9cc89 1599 }
rgrover1 0:8e57f3e9cc89 1600 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1601
rgrover1 0:8e57f3e9cc89 1602 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue )
rgrover1 0:8e57f3e9cc89 1603 {
rgrover1 0:8e57f3e9cc89 1604 signed portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 1605
rgrover1 0:8e57f3e9cc89 1606 configASSERT( xQueue );
rgrover1 0:8e57f3e9cc89 1607 if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 1608 {
rgrover1 0:8e57f3e9cc89 1609 xReturn = pdTRUE;
rgrover1 0:8e57f3e9cc89 1610 }
rgrover1 0:8e57f3e9cc89 1611 else
rgrover1 0:8e57f3e9cc89 1612 {
rgrover1 0:8e57f3e9cc89 1613 xReturn = pdFALSE;
rgrover1 0:8e57f3e9cc89 1614 }
rgrover1 0:8e57f3e9cc89 1615
rgrover1 0:8e57f3e9cc89 1616 return xReturn;
rgrover1 0:8e57f3e9cc89 1617 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
rgrover1 0:8e57f3e9cc89 1618 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1619
rgrover1 0:8e57f3e9cc89 1620 static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue )
rgrover1 0:8e57f3e9cc89 1621 {
rgrover1 0:8e57f3e9cc89 1622 signed portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 1623
rgrover1 0:8e57f3e9cc89 1624 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 1625 {
rgrover1 0:8e57f3e9cc89 1626 if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )
rgrover1 0:8e57f3e9cc89 1627 {
rgrover1 0:8e57f3e9cc89 1628 xReturn = pdTRUE;
rgrover1 0:8e57f3e9cc89 1629 }
rgrover1 0:8e57f3e9cc89 1630 else
rgrover1 0:8e57f3e9cc89 1631 {
rgrover1 0:8e57f3e9cc89 1632 xReturn = pdFALSE;
rgrover1 0:8e57f3e9cc89 1633 }
rgrover1 0:8e57f3e9cc89 1634 }
rgrover1 0:8e57f3e9cc89 1635 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 1636
rgrover1 0:8e57f3e9cc89 1637 return xReturn;
rgrover1 0:8e57f3e9cc89 1638 }
rgrover1 0:8e57f3e9cc89 1639 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1640
rgrover1 0:8e57f3e9cc89 1641 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue )
rgrover1 0:8e57f3e9cc89 1642 {
rgrover1 0:8e57f3e9cc89 1643 signed portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 1644
rgrover1 0:8e57f3e9cc89 1645 configASSERT( xQueue );
rgrover1 0:8e57f3e9cc89 1646 if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( ( xQUEUE * ) xQueue )->uxLength )
rgrover1 0:8e57f3e9cc89 1647 {
rgrover1 0:8e57f3e9cc89 1648 xReturn = pdTRUE;
rgrover1 0:8e57f3e9cc89 1649 }
rgrover1 0:8e57f3e9cc89 1650 else
rgrover1 0:8e57f3e9cc89 1651 {
rgrover1 0:8e57f3e9cc89 1652 xReturn = pdFALSE;
rgrover1 0:8e57f3e9cc89 1653 }
rgrover1 0:8e57f3e9cc89 1654
rgrover1 0:8e57f3e9cc89 1655 return xReturn;
rgrover1 0:8e57f3e9cc89 1656 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
rgrover1 0:8e57f3e9cc89 1657 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1658
rgrover1 0:8e57f3e9cc89 1659 #if ( configUSE_CO_ROUTINES == 1 )
rgrover1 0:8e57f3e9cc89 1660
rgrover1 0:8e57f3e9cc89 1661 signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait )
rgrover1 0:8e57f3e9cc89 1662 {
rgrover1 0:8e57f3e9cc89 1663 signed portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 1664 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 1665
rgrover1 0:8e57f3e9cc89 1666 /* If the queue is already full we may have to block. A critical section
rgrover1 0:8e57f3e9cc89 1667 is required to prevent an interrupt removing something from the queue
rgrover1 0:8e57f3e9cc89 1668 between the check to see if the queue is full and blocking on the queue. */
rgrover1 0:8e57f3e9cc89 1669 portDISABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 1670 {
rgrover1 0:8e57f3e9cc89 1671 if( prvIsQueueFull( pxQueue ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 1672 {
rgrover1 0:8e57f3e9cc89 1673 /* The queue is full - do we want to block or just leave without
rgrover1 0:8e57f3e9cc89 1674 posting? */
rgrover1 0:8e57f3e9cc89 1675 if( xTicksToWait > ( portTickType ) 0 )
rgrover1 0:8e57f3e9cc89 1676 {
rgrover1 0:8e57f3e9cc89 1677 /* As this is called from a coroutine we cannot block directly, but
rgrover1 0:8e57f3e9cc89 1678 return indicating that we need to block. */
rgrover1 0:8e57f3e9cc89 1679 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
rgrover1 0:8e57f3e9cc89 1680 portENABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 1681 return errQUEUE_BLOCKED;
rgrover1 0:8e57f3e9cc89 1682 }
rgrover1 0:8e57f3e9cc89 1683 else
rgrover1 0:8e57f3e9cc89 1684 {
rgrover1 0:8e57f3e9cc89 1685 portENABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 1686 return errQUEUE_FULL;
rgrover1 0:8e57f3e9cc89 1687 }
rgrover1 0:8e57f3e9cc89 1688 }
rgrover1 0:8e57f3e9cc89 1689 }
rgrover1 0:8e57f3e9cc89 1690 portENABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 1691
rgrover1 0:8e57f3e9cc89 1692 portDISABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 1693 {
rgrover1 0:8e57f3e9cc89 1694 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
rgrover1 0:8e57f3e9cc89 1695 {
rgrover1 0:8e57f3e9cc89 1696 /* There is room in the queue, copy the data into the queue. */
rgrover1 0:8e57f3e9cc89 1697 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
rgrover1 0:8e57f3e9cc89 1698 xReturn = pdPASS;
rgrover1 0:8e57f3e9cc89 1699
rgrover1 0:8e57f3e9cc89 1700 /* Were any co-routines waiting for data to become available? */
rgrover1 0:8e57f3e9cc89 1701 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1702 {
rgrover1 0:8e57f3e9cc89 1703 /* In this instance the co-routine could be placed directly
rgrover1 0:8e57f3e9cc89 1704 into the ready list as we are within a critical section.
rgrover1 0:8e57f3e9cc89 1705 Instead the same pending ready list mechanism is used as if
rgrover1 0:8e57f3e9cc89 1706 the event were caused from within an interrupt. */
rgrover1 0:8e57f3e9cc89 1707 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 1708 {
rgrover1 0:8e57f3e9cc89 1709 /* The co-routine waiting has a higher priority so record
rgrover1 0:8e57f3e9cc89 1710 that a yield might be appropriate. */
rgrover1 0:8e57f3e9cc89 1711 xReturn = errQUEUE_YIELD;
rgrover1 0:8e57f3e9cc89 1712 }
rgrover1 0:8e57f3e9cc89 1713 }
rgrover1 0:8e57f3e9cc89 1714 }
rgrover1 0:8e57f3e9cc89 1715 else
rgrover1 0:8e57f3e9cc89 1716 {
rgrover1 0:8e57f3e9cc89 1717 xReturn = errQUEUE_FULL;
rgrover1 0:8e57f3e9cc89 1718 }
rgrover1 0:8e57f3e9cc89 1719 }
rgrover1 0:8e57f3e9cc89 1720 portENABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 1721
rgrover1 0:8e57f3e9cc89 1722 return xReturn;
rgrover1 0:8e57f3e9cc89 1723 }
rgrover1 0:8e57f3e9cc89 1724
rgrover1 0:8e57f3e9cc89 1725 #endif /* configUSE_CO_ROUTINES */
rgrover1 0:8e57f3e9cc89 1726 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1727
rgrover1 0:8e57f3e9cc89 1728 #if ( configUSE_CO_ROUTINES == 1 )
rgrover1 0:8e57f3e9cc89 1729
rgrover1 0:8e57f3e9cc89 1730 signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait )
rgrover1 0:8e57f3e9cc89 1731 {
rgrover1 0:8e57f3e9cc89 1732 signed portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 1733 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 1734
rgrover1 0:8e57f3e9cc89 1735 /* If the queue is already empty we may have to block. A critical section
rgrover1 0:8e57f3e9cc89 1736 is required to prevent an interrupt adding something to the queue
rgrover1 0:8e57f3e9cc89 1737 between the check to see if the queue is empty and blocking on the queue. */
rgrover1 0:8e57f3e9cc89 1738 portDISABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 1739 {
rgrover1 0:8e57f3e9cc89 1740 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 1741 {
rgrover1 0:8e57f3e9cc89 1742 /* There are no messages in the queue, do we want to block or just
rgrover1 0:8e57f3e9cc89 1743 leave with nothing? */
rgrover1 0:8e57f3e9cc89 1744 if( xTicksToWait > ( portTickType ) 0 )
rgrover1 0:8e57f3e9cc89 1745 {
rgrover1 0:8e57f3e9cc89 1746 /* As this is a co-routine we cannot block directly, but return
rgrover1 0:8e57f3e9cc89 1747 indicating that we need to block. */
rgrover1 0:8e57f3e9cc89 1748 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
rgrover1 0:8e57f3e9cc89 1749 portENABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 1750 return errQUEUE_BLOCKED;
rgrover1 0:8e57f3e9cc89 1751 }
rgrover1 0:8e57f3e9cc89 1752 else
rgrover1 0:8e57f3e9cc89 1753 {
rgrover1 0:8e57f3e9cc89 1754 portENABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 1755 return errQUEUE_FULL;
rgrover1 0:8e57f3e9cc89 1756 }
rgrover1 0:8e57f3e9cc89 1757 }
rgrover1 0:8e57f3e9cc89 1758 }
rgrover1 0:8e57f3e9cc89 1759 portENABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 1760
rgrover1 0:8e57f3e9cc89 1761 portDISABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 1762 {
rgrover1 0:8e57f3e9cc89 1763 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 1764 {
rgrover1 0:8e57f3e9cc89 1765 /* Data is available from the queue. */
rgrover1 0:8e57f3e9cc89 1766 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
rgrover1 0:8e57f3e9cc89 1767 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )
rgrover1 0:8e57f3e9cc89 1768 {
rgrover1 0:8e57f3e9cc89 1769 pxQueue->u.pcReadFrom = pxQueue->pcHead;
rgrover1 0:8e57f3e9cc89 1770 }
rgrover1 0:8e57f3e9cc89 1771 --( pxQueue->uxMessagesWaiting );
rgrover1 0:8e57f3e9cc89 1772 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
rgrover1 0:8e57f3e9cc89 1773
rgrover1 0:8e57f3e9cc89 1774 xReturn = pdPASS;
rgrover1 0:8e57f3e9cc89 1775
rgrover1 0:8e57f3e9cc89 1776 /* Were any co-routines waiting for space to become available? */
rgrover1 0:8e57f3e9cc89 1777 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1778 {
rgrover1 0:8e57f3e9cc89 1779 /* In this instance the co-routine could be placed directly
rgrover1 0:8e57f3e9cc89 1780 into the ready list as we are within a critical section.
rgrover1 0:8e57f3e9cc89 1781 Instead the same pending ready list mechanism is used as if
rgrover1 0:8e57f3e9cc89 1782 the event were caused from within an interrupt. */
rgrover1 0:8e57f3e9cc89 1783 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 1784 {
rgrover1 0:8e57f3e9cc89 1785 xReturn = errQUEUE_YIELD;
rgrover1 0:8e57f3e9cc89 1786 }
rgrover1 0:8e57f3e9cc89 1787 }
rgrover1 0:8e57f3e9cc89 1788 }
rgrover1 0:8e57f3e9cc89 1789 else
rgrover1 0:8e57f3e9cc89 1790 {
rgrover1 0:8e57f3e9cc89 1791 xReturn = pdFAIL;
rgrover1 0:8e57f3e9cc89 1792 }
rgrover1 0:8e57f3e9cc89 1793 }
rgrover1 0:8e57f3e9cc89 1794 portENABLE_INTERRUPTS();
rgrover1 0:8e57f3e9cc89 1795
rgrover1 0:8e57f3e9cc89 1796 return xReturn;
rgrover1 0:8e57f3e9cc89 1797 }
rgrover1 0:8e57f3e9cc89 1798
rgrover1 0:8e57f3e9cc89 1799 #endif /* configUSE_CO_ROUTINES */
rgrover1 0:8e57f3e9cc89 1800 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1801
rgrover1 0:8e57f3e9cc89 1802 #if ( configUSE_CO_ROUTINES == 1 )
rgrover1 0:8e57f3e9cc89 1803
rgrover1 0:8e57f3e9cc89 1804 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
rgrover1 0:8e57f3e9cc89 1805 {
rgrover1 0:8e57f3e9cc89 1806 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 1807
rgrover1 0:8e57f3e9cc89 1808 /* Cannot block within an ISR so if there is no space on the queue then
rgrover1 0:8e57f3e9cc89 1809 exit without doing anything. */
rgrover1 0:8e57f3e9cc89 1810 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
rgrover1 0:8e57f3e9cc89 1811 {
rgrover1 0:8e57f3e9cc89 1812 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
rgrover1 0:8e57f3e9cc89 1813
rgrover1 0:8e57f3e9cc89 1814 /* We only want to wake one co-routine per ISR, so check that a
rgrover1 0:8e57f3e9cc89 1815 co-routine has not already been woken. */
rgrover1 0:8e57f3e9cc89 1816 if( xCoRoutinePreviouslyWoken == pdFALSE )
rgrover1 0:8e57f3e9cc89 1817 {
rgrover1 0:8e57f3e9cc89 1818 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1819 {
rgrover1 0:8e57f3e9cc89 1820 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 1821 {
rgrover1 0:8e57f3e9cc89 1822 return pdTRUE;
rgrover1 0:8e57f3e9cc89 1823 }
rgrover1 0:8e57f3e9cc89 1824 }
rgrover1 0:8e57f3e9cc89 1825 }
rgrover1 0:8e57f3e9cc89 1826 }
rgrover1 0:8e57f3e9cc89 1827
rgrover1 0:8e57f3e9cc89 1828 return xCoRoutinePreviouslyWoken;
rgrover1 0:8e57f3e9cc89 1829 }
rgrover1 0:8e57f3e9cc89 1830
rgrover1 0:8e57f3e9cc89 1831 #endif /* configUSE_CO_ROUTINES */
rgrover1 0:8e57f3e9cc89 1832 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1833
rgrover1 0:8e57f3e9cc89 1834 #if ( configUSE_CO_ROUTINES == 1 )
rgrover1 0:8e57f3e9cc89 1835
rgrover1 0:8e57f3e9cc89 1836 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
rgrover1 0:8e57f3e9cc89 1837 {
rgrover1 0:8e57f3e9cc89 1838 signed portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 1839 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 1840
rgrover1 0:8e57f3e9cc89 1841 /* We cannot block from an ISR, so check there is data available. If
rgrover1 0:8e57f3e9cc89 1842 not then just leave without doing anything. */
rgrover1 0:8e57f3e9cc89 1843 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 1844 {
rgrover1 0:8e57f3e9cc89 1845 /* Copy the data from the queue. */
rgrover1 0:8e57f3e9cc89 1846 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
rgrover1 0:8e57f3e9cc89 1847 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )
rgrover1 0:8e57f3e9cc89 1848 {
rgrover1 0:8e57f3e9cc89 1849 pxQueue->u.pcReadFrom = pxQueue->pcHead;
rgrover1 0:8e57f3e9cc89 1850 }
rgrover1 0:8e57f3e9cc89 1851 --( pxQueue->uxMessagesWaiting );
rgrover1 0:8e57f3e9cc89 1852 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
rgrover1 0:8e57f3e9cc89 1853
rgrover1 0:8e57f3e9cc89 1854 if( ( *pxCoRoutineWoken ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1855 {
rgrover1 0:8e57f3e9cc89 1856 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 1857 {
rgrover1 0:8e57f3e9cc89 1858 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 1859 {
rgrover1 0:8e57f3e9cc89 1860 *pxCoRoutineWoken = pdTRUE;
rgrover1 0:8e57f3e9cc89 1861 }
rgrover1 0:8e57f3e9cc89 1862 }
rgrover1 0:8e57f3e9cc89 1863 }
rgrover1 0:8e57f3e9cc89 1864
rgrover1 0:8e57f3e9cc89 1865 xReturn = pdPASS;
rgrover1 0:8e57f3e9cc89 1866 }
rgrover1 0:8e57f3e9cc89 1867 else
rgrover1 0:8e57f3e9cc89 1868 {
rgrover1 0:8e57f3e9cc89 1869 xReturn = pdFAIL;
rgrover1 0:8e57f3e9cc89 1870 }
rgrover1 0:8e57f3e9cc89 1871
rgrover1 0:8e57f3e9cc89 1872 return xReturn;
rgrover1 0:8e57f3e9cc89 1873 }
rgrover1 0:8e57f3e9cc89 1874
rgrover1 0:8e57f3e9cc89 1875 #endif /* configUSE_CO_ROUTINES */
rgrover1 0:8e57f3e9cc89 1876 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1877
rgrover1 0:8e57f3e9cc89 1878 #if ( configQUEUE_REGISTRY_SIZE > 0 )
rgrover1 0:8e57f3e9cc89 1879
rgrover1 0:8e57f3e9cc89 1880 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
rgrover1 0:8e57f3e9cc89 1881 {
rgrover1 0:8e57f3e9cc89 1882 unsigned portBASE_TYPE ux;
rgrover1 0:8e57f3e9cc89 1883
rgrover1 0:8e57f3e9cc89 1884 /* See if there is an empty space in the registry. A NULL name denotes
rgrover1 0:8e57f3e9cc89 1885 a free slot. */
rgrover1 0:8e57f3e9cc89 1886 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
rgrover1 0:8e57f3e9cc89 1887 {
rgrover1 0:8e57f3e9cc89 1888 if( xQueueRegistry[ ux ].pcQueueName == NULL )
rgrover1 0:8e57f3e9cc89 1889 {
rgrover1 0:8e57f3e9cc89 1890 /* Store the information on this queue. */
rgrover1 0:8e57f3e9cc89 1891 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
rgrover1 0:8e57f3e9cc89 1892 xQueueRegistry[ ux ].xHandle = xQueue;
rgrover1 0:8e57f3e9cc89 1893 break;
rgrover1 0:8e57f3e9cc89 1894 }
rgrover1 0:8e57f3e9cc89 1895 }
rgrover1 0:8e57f3e9cc89 1896 }
rgrover1 0:8e57f3e9cc89 1897
rgrover1 0:8e57f3e9cc89 1898 #endif /* configQUEUE_REGISTRY_SIZE */
rgrover1 0:8e57f3e9cc89 1899 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1900
rgrover1 0:8e57f3e9cc89 1901 #if ( configQUEUE_REGISTRY_SIZE > 0 )
rgrover1 0:8e57f3e9cc89 1902
rgrover1 0:8e57f3e9cc89 1903 void vQueueUnregisterQueue( xQueueHandle xQueue )
rgrover1 0:8e57f3e9cc89 1904 {
rgrover1 0:8e57f3e9cc89 1905 unsigned portBASE_TYPE ux;
rgrover1 0:8e57f3e9cc89 1906
rgrover1 0:8e57f3e9cc89 1907 /* See if the handle of the queue being unregistered in actually in the
rgrover1 0:8e57f3e9cc89 1908 registry. */
rgrover1 0:8e57f3e9cc89 1909 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
rgrover1 0:8e57f3e9cc89 1910 {
rgrover1 0:8e57f3e9cc89 1911 if( xQueueRegistry[ ux ].xHandle == xQueue )
rgrover1 0:8e57f3e9cc89 1912 {
rgrover1 0:8e57f3e9cc89 1913 /* Set the name to NULL to show that this slot if free again. */
rgrover1 0:8e57f3e9cc89 1914 xQueueRegistry[ ux ].pcQueueName = NULL;
rgrover1 0:8e57f3e9cc89 1915 break;
rgrover1 0:8e57f3e9cc89 1916 }
rgrover1 0:8e57f3e9cc89 1917 }
rgrover1 0:8e57f3e9cc89 1918
rgrover1 0:8e57f3e9cc89 1919 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
rgrover1 0:8e57f3e9cc89 1920
rgrover1 0:8e57f3e9cc89 1921 #endif /* configQUEUE_REGISTRY_SIZE */
rgrover1 0:8e57f3e9cc89 1922 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1923
rgrover1 0:8e57f3e9cc89 1924 #if ( configUSE_TIMERS == 1 )
rgrover1 0:8e57f3e9cc89 1925
rgrover1 0:8e57f3e9cc89 1926 void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait )
rgrover1 0:8e57f3e9cc89 1927 {
rgrover1 0:8e57f3e9cc89 1928 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
rgrover1 0:8e57f3e9cc89 1929
rgrover1 0:8e57f3e9cc89 1930 /* This function should not be called by application code hence the
rgrover1 0:8e57f3e9cc89 1931 'Restricted' in its name. It is not part of the public API. It is
rgrover1 0:8e57f3e9cc89 1932 designed for use by kernel code, and has special calling requirements.
rgrover1 0:8e57f3e9cc89 1933 It can result in vListInsert() being called on a list that can only
rgrover1 0:8e57f3e9cc89 1934 possibly ever have one item in it, so the list will be fast, but even
rgrover1 0:8e57f3e9cc89 1935 so it should be called with the scheduler locked and not from a critical
rgrover1 0:8e57f3e9cc89 1936 section. */
rgrover1 0:8e57f3e9cc89 1937
rgrover1 0:8e57f3e9cc89 1938 /* Only do anything if there are no messages in the queue. This function
rgrover1 0:8e57f3e9cc89 1939 will not actually cause the task to block, just place it on a blocked
rgrover1 0:8e57f3e9cc89 1940 list. It will not block until the scheduler is unlocked - at which
rgrover1 0:8e57f3e9cc89 1941 time a yield will be performed. If an item is added to the queue while
rgrover1 0:8e57f3e9cc89 1942 the queue is locked, and the calling task blocks on the queue, then the
rgrover1 0:8e57f3e9cc89 1943 calling task will be immediately unblocked when the queue is unlocked. */
rgrover1 0:8e57f3e9cc89 1944 prvLockQueue( pxQueue );
rgrover1 0:8e57f3e9cc89 1945 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )
rgrover1 0:8e57f3e9cc89 1946 {
rgrover1 0:8e57f3e9cc89 1947 /* There is nothing in the queue, block for the specified period. */
rgrover1 0:8e57f3e9cc89 1948 vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
rgrover1 0:8e57f3e9cc89 1949 }
rgrover1 0:8e57f3e9cc89 1950 prvUnlockQueue( pxQueue );
rgrover1 0:8e57f3e9cc89 1951 }
rgrover1 0:8e57f3e9cc89 1952
rgrover1 0:8e57f3e9cc89 1953 #endif /* configUSE_TIMERS */
rgrover1 0:8e57f3e9cc89 1954 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1955
rgrover1 0:8e57f3e9cc89 1956 #if ( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 1957
rgrover1 0:8e57f3e9cc89 1958 xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength )
rgrover1 0:8e57f3e9cc89 1959 {
rgrover1 0:8e57f3e9cc89 1960 xQueueSetHandle pxQueue;
rgrover1 0:8e57f3e9cc89 1961
rgrover1 0:8e57f3e9cc89 1962 pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( xQUEUE * ), queueQUEUE_TYPE_SET );
rgrover1 0:8e57f3e9cc89 1963
rgrover1 0:8e57f3e9cc89 1964 return pxQueue;
rgrover1 0:8e57f3e9cc89 1965 }
rgrover1 0:8e57f3e9cc89 1966
rgrover1 0:8e57f3e9cc89 1967 #endif /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 1968 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 1969
rgrover1 0:8e57f3e9cc89 1970 #if ( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 1971
rgrover1 0:8e57f3e9cc89 1972 portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
rgrover1 0:8e57f3e9cc89 1973 {
rgrover1 0:8e57f3e9cc89 1974 portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 1975
rgrover1 0:8e57f3e9cc89 1976 if( ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
rgrover1 0:8e57f3e9cc89 1977 {
rgrover1 0:8e57f3e9cc89 1978 /* Cannot add a queue/semaphore to more than one queue set. */
rgrover1 0:8e57f3e9cc89 1979 xReturn = pdFAIL;
rgrover1 0:8e57f3e9cc89 1980 }
rgrover1 0:8e57f3e9cc89 1981 else if( ( ( xQUEUE * ) xQueueOrSemaphore )->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 1982 {
rgrover1 0:8e57f3e9cc89 1983 /* Cannot add a queue/semaphore to a queue set if there are already
rgrover1 0:8e57f3e9cc89 1984 items in the queue/semaphore. */
rgrover1 0:8e57f3e9cc89 1985 xReturn = pdFAIL;
rgrover1 0:8e57f3e9cc89 1986 }
rgrover1 0:8e57f3e9cc89 1987 else
rgrover1 0:8e57f3e9cc89 1988 {
rgrover1 0:8e57f3e9cc89 1989 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 1990 {
rgrover1 0:8e57f3e9cc89 1991 ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;
rgrover1 0:8e57f3e9cc89 1992 }
rgrover1 0:8e57f3e9cc89 1993 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 1994 xReturn = pdPASS;
rgrover1 0:8e57f3e9cc89 1995 }
rgrover1 0:8e57f3e9cc89 1996
rgrover1 0:8e57f3e9cc89 1997 return xReturn;
rgrover1 0:8e57f3e9cc89 1998 }
rgrover1 0:8e57f3e9cc89 1999
rgrover1 0:8e57f3e9cc89 2000 #endif /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 2001 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 2002
rgrover1 0:8e57f3e9cc89 2003 #if ( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 2004
rgrover1 0:8e57f3e9cc89 2005 portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
rgrover1 0:8e57f3e9cc89 2006 {
rgrover1 0:8e57f3e9cc89 2007 portBASE_TYPE xReturn;
rgrover1 0:8e57f3e9cc89 2008 xQUEUE * const pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore;
rgrover1 0:8e57f3e9cc89 2009
rgrover1 0:8e57f3e9cc89 2010 if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
rgrover1 0:8e57f3e9cc89 2011 {
rgrover1 0:8e57f3e9cc89 2012 /* The queue was not a member of the set. */
rgrover1 0:8e57f3e9cc89 2013 xReturn = pdFAIL;
rgrover1 0:8e57f3e9cc89 2014 }
rgrover1 0:8e57f3e9cc89 2015 else if( pxQueueOrSemaphore->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
rgrover1 0:8e57f3e9cc89 2016 {
rgrover1 0:8e57f3e9cc89 2017 /* It is dangerous to remove a queue from a set when the queue is
rgrover1 0:8e57f3e9cc89 2018 not empty because the queue set will still hold pending events for
rgrover1 0:8e57f3e9cc89 2019 the queue. */
rgrover1 0:8e57f3e9cc89 2020 xReturn = pdFAIL;
rgrover1 0:8e57f3e9cc89 2021 }
rgrover1 0:8e57f3e9cc89 2022 else
rgrover1 0:8e57f3e9cc89 2023 {
rgrover1 0:8e57f3e9cc89 2024 taskENTER_CRITICAL();
rgrover1 0:8e57f3e9cc89 2025 {
rgrover1 0:8e57f3e9cc89 2026 /* The queue is no longer contained in the set. */
rgrover1 0:8e57f3e9cc89 2027 pxQueueOrSemaphore->pxQueueSetContainer = NULL;
rgrover1 0:8e57f3e9cc89 2028 }
rgrover1 0:8e57f3e9cc89 2029 taskEXIT_CRITICAL();
rgrover1 0:8e57f3e9cc89 2030 xReturn = pdPASS;
rgrover1 0:8e57f3e9cc89 2031 }
rgrover1 0:8e57f3e9cc89 2032
rgrover1 0:8e57f3e9cc89 2033 return xReturn;
rgrover1 0:8e57f3e9cc89 2034 } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */
rgrover1 0:8e57f3e9cc89 2035
rgrover1 0:8e57f3e9cc89 2036 #endif /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 2037 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 2038
rgrover1 0:8e57f3e9cc89 2039 #if ( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 2040
rgrover1 0:8e57f3e9cc89 2041 xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks )
rgrover1 0:8e57f3e9cc89 2042 {
rgrover1 0:8e57f3e9cc89 2043 xQueueSetMemberHandle xReturn = NULL;
rgrover1 0:8e57f3e9cc89 2044
rgrover1 0:8e57f3e9cc89 2045 ( void ) xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */
rgrover1 0:8e57f3e9cc89 2046 return xReturn;
rgrover1 0:8e57f3e9cc89 2047 }
rgrover1 0:8e57f3e9cc89 2048
rgrover1 0:8e57f3e9cc89 2049 #endif /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 2050 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 2051
rgrover1 0:8e57f3e9cc89 2052 #if ( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 2053
rgrover1 0:8e57f3e9cc89 2054 xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet )
rgrover1 0:8e57f3e9cc89 2055 {
rgrover1 0:8e57f3e9cc89 2056 xQueueSetMemberHandle xReturn = NULL;
rgrover1 0:8e57f3e9cc89 2057
rgrover1 0:8e57f3e9cc89 2058 ( void ) xQueueReceiveFromISR( ( xQueueHandle ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */
rgrover1 0:8e57f3e9cc89 2059 return xReturn;
rgrover1 0:8e57f3e9cc89 2060 }
rgrover1 0:8e57f3e9cc89 2061
rgrover1 0:8e57f3e9cc89 2062 #endif /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 2063 /*-----------------------------------------------------------*/
rgrover1 0:8e57f3e9cc89 2064
rgrover1 0:8e57f3e9cc89 2065 #if ( configUSE_QUEUE_SETS == 1 )
rgrover1 0:8e57f3e9cc89 2066
rgrover1 0:8e57f3e9cc89 2067 static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition )
rgrover1 0:8e57f3e9cc89 2068 {
rgrover1 0:8e57f3e9cc89 2069 xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
rgrover1 0:8e57f3e9cc89 2070 portBASE_TYPE xReturn = pdFALSE;
rgrover1 0:8e57f3e9cc89 2071
rgrover1 0:8e57f3e9cc89 2072 configASSERT( pxQueueSetContainer );
rgrover1 0:8e57f3e9cc89 2073 configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
rgrover1 0:8e57f3e9cc89 2074
rgrover1 0:8e57f3e9cc89 2075 if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
rgrover1 0:8e57f3e9cc89 2076 {
rgrover1 0:8e57f3e9cc89 2077 traceQUEUE_SEND( pxQueueSetContainer );
rgrover1 0:8e57f3e9cc89 2078 /* The data copies is the handle of the queue that contains data. */
rgrover1 0:8e57f3e9cc89 2079 prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );
rgrover1 0:8e57f3e9cc89 2080 if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
rgrover1 0:8e57f3e9cc89 2081 {
rgrover1 0:8e57f3e9cc89 2082 if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
rgrover1 0:8e57f3e9cc89 2083 {
rgrover1 0:8e57f3e9cc89 2084 /* The task waiting has a higher priority */
rgrover1 0:8e57f3e9cc89 2085 xReturn = pdTRUE;
rgrover1 0:8e57f3e9cc89 2086 }
rgrover1 0:8e57f3e9cc89 2087 }
rgrover1 0:8e57f3e9cc89 2088 }
rgrover1 0:8e57f3e9cc89 2089
rgrover1 0:8e57f3e9cc89 2090 return xReturn;
rgrover1 0:8e57f3e9cc89 2091 }
rgrover1 0:8e57f3e9cc89 2092
rgrover1 0:8e57f3e9cc89 2093 #endif /* configUSE_QUEUE_SETS */
rgrover1 0:8e57f3e9cc89 2094
rgrover1 0:8e57f3e9cc89 2095
rgrover1 0:8e57f3e9cc89 2096
rgrover1 0:8e57f3e9cc89 2097
rgrover1 0:8e57f3e9cc89 2098
rgrover1 0:8e57f3e9cc89 2099
rgrover1 0:8e57f3e9cc89 2100
rgrover1 0:8e57f3e9cc89 2101
rgrover1 0:8e57f3e9cc89 2102
rgrover1 0:8e57f3e9cc89 2103
rgrover1 0:8e57f3e9cc89 2104
rgrover1 0:8e57f3e9cc89 2105