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

📄 queue.c

📁 freemodbus-v1-1-1-0.zip v1.1.1版本的代码 支持多个平台
💻 C
📖 第 1 页 / 共 2 页
字号:
	queue since we left the critical section, so it may be that again there	is no space.  This would only happen if a task and ISR post onto the	same queue. */	taskENTER_CRITICAL();	{		if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )		{			/* There is room in the queue, copy the data into the queue. */						prvCopyQueueData( pxQueue, pvItemToQueue );					xReturn = pdPASS;			/* Update the TxLock count so prvUnlockQueue knows to check for			tasks waiting for data to become available in the queue. */			++( pxQueue->xTxLock );		}		else		{			xReturn = errQUEUE_FULL;		}	}	taskEXIT_CRITICAL();	/* We no longer require exclusive access to the queue.  prvUnlockQueue	will remove any tasks suspended on a receive if either this function	or an ISR has posted onto the queue. */	if( prvUnlockQueue( pxQueue ) )	{		/* Resume the scheduler - making ready any tasks that were woken		by an event while the scheduler was locked.  Resuming the		scheduler may cause a yield, in which case there is no point		yielding again here. */		if( !xTaskResumeAll() )		{			taskYIELD();		}	}	else	{		/* Resume the scheduler - making ready any tasks that were woken		by an event while the scheduler was locked. */		xTaskResumeAll();	}	return xReturn;}/*-----------------------------------------------------------*/signed portBASE_TYPE xQueueSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken ){	/* Similar to xQueueSend, 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 )	{		prvCopyQueueData( pxQueue, pvItemToQueue );		/* 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 xQueueReceive( xQueueHandle pxQueue, void *pcBuffer, portTickType xTicksToWait ){signed portBASE_TYPE xReturn;	/* This function is very similar to xQueueSend().  See comments within	xQueueSend() for a more detailed explanation.	Make sure other tasks do not access the queue. */	vTaskSuspendAll();	/* Make sure interrupts do not access the queue. */	prvLockQueue( pxQueue );	/* 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 )		{			vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );			taskENTER_CRITICAL();			{				prvUnlockQueue( pxQueue );				if( !xTaskResumeAll() )				{					taskYIELD();				}				vTaskSuspendAll();				prvLockQueue( pxQueue );			}			taskEXIT_CRITICAL();		}	}	taskENTER_CRITICAL();	{		if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )		{			pxQueue->pcReadFrom += pxQueue->uxItemSize;			if( pxQueue->pcReadFrom >= pxQueue->pcTail )			{				pxQueue->pcReadFrom = pxQueue->pcHead;			}			--( pxQueue->uxMessagesWaiting );			memcpy( ( void * ) pcBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );			/* Increment the lock count so prvUnlockQueue knows to check for			tasks waiting for space to become available on the queue. */			++( pxQueue->xRxLock );			xReturn = pdPASS;		}		else		{			xReturn = pdFAIL;		}	}	taskEXIT_CRITICAL();	/* We no longer require exclusive access to the queue. */	if( prvUnlockQueue( pxQueue ) )	{		if( !xTaskResumeAll() )		{			taskYIELD();		}	}	else	{		xTaskResumeAll();	}	return xReturn;}/*-----------------------------------------------------------*/signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void *pcBuffer, 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 )	{		/* Copy the data from the queue. */		pxQueue->pcReadFrom += pxQueue->uxItemSize;		if( pxQueue->pcReadFrom >= pxQueue->pcTail )		{			pxQueue->pcReadFrom = pxQueue->pcHead;		}		--( pxQueue->uxMessagesWaiting );		memcpy( ( void * ) pcBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );		/* If the queue is locked we will not modify the event list.  Instead		we update the lock count so the task that unlocks the queue will know		that an ISR has removed data while the queue was locked. */		if( pxQueue->xRxLock == queueUNLOCKED )		{			/* We only want to wake one task per ISR, so check that a task has			not already been woken. */			if( !( *pxTaskWoken ) )			{				if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )				{					if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )					{						/* The task waiting has a higher priority than us so						force a context switch. */						*pxTaskWoken = pdTRUE;					}				}			}		}		else		{			/* Increment the lock count so the task that unlocks the queue			knows that data was removed while it was locked. */			++( pxQueue->xRxLock );		}		xReturn = pdPASS;	}	else	{		xReturn = pdFAIL;	}	return xReturn;}/*-----------------------------------------------------------*/unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle pxQueue ){unsigned portBASE_TYPE uxReturn;	taskENTER_CRITICAL();		uxReturn = pxQueue->uxMessagesWaiting;	taskEXIT_CRITICAL();	return uxReturn;}/*-----------------------------------------------------------*/void vQueueDelete( xQueueHandle pxQueue ){	vPortFree( pxQueue->pcHead );	vPortFree( pxQueue );}/*-----------------------------------------------------------*/static signed portBASE_TYPE prvUnlockQueue( xQueueHandle pxQueue ){signed portBASE_TYPE xYieldRequired = pdFALSE;	/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */	/* The lock counts contains the number of extra data items placed or	removed from the queue while the queue was locked.  When a queue is	locked items can be added or removed, but the event lists cannot be	updated. */	taskENTER_CRITICAL();	{		--( pxQueue->xTxLock );		/* See if data was added to the queue while it was locked. */		if( pxQueue->xTxLock > queueUNLOCKED )		{			pxQueue->xTxLock = queueUNLOCKED;			/* Data was posted while the queue was locked.  Are any tasks			blocked waiting for data to become available? */			if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )			{				/* Tasks that are removed from the event list will get added to				the pending ready list as the scheduler is still suspended. */				if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )				{					/* The task waiting has a higher priority so record that a					context	switch is required. */					xYieldRequired = pdTRUE;				}			}					}	}	taskEXIT_CRITICAL();	/* Do the same for the Rx lock. */	taskENTER_CRITICAL();	{		--( pxQueue->xRxLock );		if( pxQueue->xRxLock > queueUNLOCKED )		{			pxQueue->xRxLock = queueUNLOCKED;			if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )			{				if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )				{					xYieldRequired = pdTRUE;				}			}					}	}	taskEXIT_CRITICAL();	return xYieldRequired;}/*-----------------------------------------------------------*/static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ){signed portBASE_TYPE xReturn;	taskENTER_CRITICAL();		xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );	taskEXIT_CRITICAL();	return xReturn;}/*-----------------------------------------------------------*/static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ){signed portBASE_TYPE xReturn;	taskENTER_CRITICAL();		xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );	taskEXIT_CRITICAL();	return xReturn;}

⌨️ 快捷键说明

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