⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 queue.c

📁 An complete pmp solution for mattel juicebox player. Using crossworks for arm.
💻 C
📖 第 1 页 / 共 3 页
字号:
		}

		if( xReturn == errQUEUE_FULL )
		{
			if( xTicksToWait > 0 )
			{
				if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
				{
					xReturn = queueERRONEOUS_UNBLOCK;
				}
			}
		}
	}
	while( xReturn == queueERRONEOUS_UNBLOCK );

	prvUnlockQueue( pxQueue );
	xTaskResumeAll();

	return xReturn;
}
/*-----------------------------------------------------------*/

#if configUSE_ALTERNATIVE_API == 1

	signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
	{
	signed portBASE_TYPE xReturn;
	xTimeOutType xTimeOut;

		/* The source code that implements the alternative (Alt) API is much
		simpler	because it executes everything from within a critical section.
		This is	the approach taken by many other RTOSes, but FreeRTOS.org has the
		preferred fully featured API too.  The fully featured API has more
		complex	code that takes longer to execute, but makes much less use of
		critical sections.  Therefore the alternative API sacrifices interrupt
		responsiveness to gain execution speed, whereas the fully featured API
		sacrifices execution speed to ensure better interrupt responsiveness.  */

		taskENTER_CRITICAL();
		{
			/* Capture the current time status for future reference. */
			vTaskSetTimeOutState( &xTimeOut );

			/* If the queue is already full we may have to block. */
			do
			{
				if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )
				{
					/* The queue is full - do we want to block or just leave without
					posting? */
					if( xTicksToWait > ( portTickType ) 0 )
					{
						/* We are going to place ourselves on the xTasksWaitingToSend
						event list, and will get woken should the delay expire, or
						space become available on the queue. */
						vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
			
						/* Force a context switch now as we are blocked.  We can do
						this from within a critical section as the task we are
						switching to has its own context.  When we return here (i.e.
						we unblock) we will leave the critical section as normal. */
						taskYIELD();
					}
				}
					
				if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
				{
					/* There is room in the queue, copy the data into the queue. */			
					prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
					xReturn = pdPASS;

					if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
					{
						if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
						{
							/* The task waiting has a higher priority. */
							taskYIELD();
						}
					}			
				}
				else
				{
					xReturn = errQUEUE_FULL;

					if( xTicksToWait > 0 )
					{					
						if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
						{
							/* Another task must have accessed the queue between 
							this task unblocking and actually executing. */
							xReturn = queueERRONEOUS_UNBLOCK;
						}
					}
				}
			}
			while( xReturn == queueERRONEOUS_UNBLOCK );
		}
		taskEXIT_CRITICAL();

		return xReturn;
	}

#endif /* configUSE_ALTERNATIVE_API */
/*-----------------------------------------------------------*/

#if configUSE_ALTERNATIVE_API == 1

	signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
	{
	signed portBASE_TYPE xReturn = pdTRUE;
	xTimeOutType xTimeOut;
	signed portCHAR *pcOriginalReadPosition;

		/* The source code that implements the alternative (Alt) API is much
		simpler	because it executes everything from within a critical section.
		This is	the approach taken by many other RTOSes, but FreeRTOS.org has the
		preferred fully featured API too.  The fully featured API has more
		complex	code that takes longer to execute, but makes much less use of
		critical sections.  Therefore the alternative API sacrifices interrupt
		responsiveness to gain execution speed, whereas the fully featured API
		sacrifices execution speed to ensure better interrupt responsiveness.  */

		taskENTER_CRITICAL();
		{
			/* Capture the current time status for future reference. */
			vTaskSetTimeOutState( &xTimeOut );

			do
			{
				/* If there are no messages in the queue we may have to block. */
				if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
				{
					/* There are no messages in the queue, do we want to block or just
					leave with nothing? */			
					if( xTicksToWait > ( portTickType ) 0 )
					{
						#if ( configUSE_MUTEXES == 1 )
						{
							if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
							{
								vTaskPriorityInherit( ( void * const ) pxQueue->pxMutexHolder );
							}
						}
						#endif
						
						vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
						taskYIELD();
					}
				}
			
				if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
				{
					/* Remember our read position in case we are just peeking. */
					pcOriginalReadPosition = pxQueue->pcReadFrom;

					prvCopyDataFromQueue( pxQueue, pvBuffer );

					if( xJustPeeking == pdFALSE )
					{
						/* We are actually removing data. */
						--( pxQueue->uxMessagesWaiting );
							
						#if ( configUSE_MUTEXES == 1 )
						{
							if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
							{
								/* Record the information required to implement
								priority inheritance should it become necessary. */
								pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
							}
						}
						#endif

						if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
						{
							if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
							{
								/* The task waiting has a higher priority. */
								taskYIELD();
							}
						}
					}
					else
					{
						/* We are not removing the data, so reset our read
						pointer. */
						pxQueue->pcReadFrom = pcOriginalReadPosition;
					}
					
					xReturn = pdPASS;					
				}
				else
				{
					xReturn = errQUEUE_EMPTY;

					if( xTicksToWait > 0 )
					{
						if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
						{
							xReturn = queueERRONEOUS_UNBLOCK;
						}
					}
				}

			} while( xReturn == queueERRONEOUS_UNBLOCK );
		}
		taskEXIT_CRITICAL();

		return xReturn;
	}

#endif /* configUSE_ALTERNATIVE_API */
/*-----------------------------------------------------------*/

signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition )
{
	/* Similar to xQueueGenericSend, except we don't block if there is no room
	in the queue.  Also we don't directly wake a task that was blocked on a
	queue read, instead we return a flag to say whether a context switch is
	required or not (i.e. has a task with a higher priority than us been woken
	by this	post). */
	if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
	{
		prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );

		/* If the queue is locked we do not alter the event list.  This will
		be done when the queue is unlocked later. */
		if( pxQueue->xTxLock == queueUNLOCKED )
		{
			/* We only want to wake one task per ISR, so check that a task has
			not already been woken. */
			if( !xTaskPreviouslyWoken )		
			{
				if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
				{
					if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
					{
						/* The task waiting has a higher priority so record that a
						context	switch is required. */
						return pdTRUE;
					}
				}
			}
		}
		else
		{
			/* Increment the lock count so the task that unlocks the queue
			knows that data was posted while it was locked. */
			++( pxQueue->xTxLock );
		}
	}

	return xTaskPreviouslyWoken;
}
/*-----------------------------------------------------------*/

signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
{
signed portBASE_TYPE xReturn = pdTRUE;
xTimeOutType xTimeOut;
signed portCHAR *pcOriginalReadPosition;

	/* This function is very similar to xQueueGenericSend().  See comments
	within xQueueGenericSend() for a more detailed explanation.

	Make sure other tasks do not access the queue. */
	vTaskSuspendAll();

	/* Capture the current time status for future reference. */
	vTaskSetTimeOutState( &xTimeOut );

	/* Make sure interrupts do not access the queue. */
	prvLockQueue( pxQueue );

	do
	{
		/* If there are no messages in the queue we may have to block. */
		if( prvIsQueueEmpty( pxQueue ) )
		{
			/* There are no messages in the queue, do we want to block or just
			leave with nothing? */			
			if( xTicksToWait > ( portTickType ) 0 )
			{
				#if ( configUSE_MUTEXES == 1 )
				{
					if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
					{
						portENTER_CRITICAL();
							vTaskPriorityInherit( ( void * const ) pxQueue->pxMutexHolder );
						portEXIT_CRITICAL();
					}
				}
				#endif
				
				vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
				taskENTER_CRITICAL();
				{
					prvUnlockQueue( pxQueue );
					if( !xTaskResumeAll() )
					{
						taskYIELD();
					}

					if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
					{
						/* We unblocked but the queue is empty.  We probably
						timed out. */
						xReturn = errQUEUE_EMPTY;
					}
	
					vTaskSuspendAll();
					prvLockQueue( pxQueue );
				}
				taskEXIT_CRITICAL();
			}
		}
	
		if( xReturn != errQUEUE_EMPTY )
		{
			taskENTER_CRITICAL();
			{
				if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
				{
					/* Remember our read position in case we are just peeking. */
					pcOriginalReadPosition = pxQueue->pcReadFrom;

					prvCopyDataFromQueue( pxQueue, pvBuffer );

					if( xJustPeeking == pdFALSE )
					{
						/* We are actually removing data. */
						--( pxQueue->uxMessagesWaiting );
							
						/* Increment the lock count so prvUnlockQueue knows to check for
						tasks waiting for space to become available on the queue. */
						++( pxQueue->xRxLock );
						
						#if ( configUSE_MUTEXES == 1 )
						{
							if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
							{
								/* Record the information required to implement
								priority inheritance should it become necessary. */
								pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
							}
						}
						#endif
					}
					else
					{
						/* We are not removing the data, so reset our read
						pointer. */
						pxQueue->pcReadFrom = pcOriginalReadPosition;

						/* The data is being left in the queue, so increment the
						lock count so prvUnlockQueue knows to check for other
						tasks waiting for the data to be available. */
						++( pxQueue->xTxLock );						
					}
					
					xReturn = pdPASS;					
				}
				else
				{
					xReturn = errQUEUE_EMPTY;
				}
			}
			taskEXIT_CRITICAL();
		}

		if( xReturn == errQUEUE_EMPTY )
		{
			if( xTicksToWait > 0 )
			{
				if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
				{
					xReturn = queueERRONEOUS_UNBLOCK;
				}
			}
		}
	} while( xReturn == queueERRONEOUS_UNBLOCK );

	/* We no longer require exclusive access to the queue. */
	prvUnlockQueue( pxQueue );
	xTaskResumeAll();

	return xReturn;
}
/*-----------------------------------------------------------*/

signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, const void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )
{
signed portBASE_TYPE xReturn;

	/* We cannot block from an ISR, so check there is data available. */
	if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
	{
		prvCopyDataFromQueue( pxQueue, pvBuffer );
		--( pxQueue->uxMessagesWaiting );

		/* If the queue is locked we will not modify the event list.  Instead

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -