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

📄 queue.c

📁 关于 modbus tcp 的一些源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
static void prvUnlockQueue( xQueueHandle pxQueue )

{

	/* 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. */

					vTaskMissedYield();

				}

			}			

		}

	}

	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 )

				{

					vTaskMissedYield();

				}

			}			

		}

	}

	taskEXIT_CRITICAL();

}

/*-----------------------------------------------------------*/



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;

}

/*-----------------------------------------------------------*/



#if configUSE_CO_ROUTINES == 1

signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )

{

signed portBASE_TYPE xReturn;

		

	/* If the queue is already full we may have to block.  A critical section

	is required to prevent an interrupt removing something from the queue 

	between the check to see if the queue is full and blocking on the queue. */

	portDISABLE_INTERRUPTS();

	{

		if( prvIsQueueFull( pxQueue ) )

		{

			/* The queue is full - do we want to block or just leave without

			posting? */

			if( xTicksToWait > ( portTickType ) 0 )

			{

				/* As this is called from a coroutine we cannot block directly, but

				return indicating that we need to block. */

				vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );				

				portENABLE_INTERRUPTS();

				return errQUEUE_BLOCKED;

			}

			else

			{

				portENABLE_INTERRUPTS();

				return errQUEUE_FULL;

			}

		}

	}

	portENABLE_INTERRUPTS();

		

	portNOP();



	portDISABLE_INTERRUPTS();

	{

		if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )

		{

			/* There is room in the queue, copy the data into the queue. */			

			prvCopyQueueData( pxQueue, pvItemToQueue );		

			xReturn = pdPASS;



			/* Were any co-routines waiting for data to become available? */

			if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )

			{

				/* In this instance the co-routine could be placed directly 

				into the ready list as we are within a critical section.  

				Instead the same pending ready list mechansim is used as if

				the event were caused from within an interrupt. */

				if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )

				{

					/* The co-routine waiting has a higher priority so record 

					that a yield might be appropriate. */

					xReturn = errQUEUE_YIELD;

				}

			}

		}

		else

		{

			xReturn = errQUEUE_FULL;

		}

	}

	portENABLE_INTERRUPTS();



	return xReturn;

}

#endif

/*-----------------------------------------------------------*/



#if configUSE_CO_ROUTINES == 1

signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )

{

signed portBASE_TYPE xReturn;



	/* If the queue is already empty we may have to block.  A critical section

	is required to prevent an interrupt adding something to the queue 

	between the check to see if the queue is empty and blocking on the queue. */

	portDISABLE_INTERRUPTS();

	{

		if( prvIsQueueEmpty( pxQueue ) )

		{

			/* There are no messages in the queue, do we want to block or just

			leave with nothing? */			

			if( xTicksToWait > ( portTickType ) 0 )

			{

				/* As this is a co-routine we cannot block directly, but return

				indicating that we need to block. */

				vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );

				portENABLE_INTERRUPTS();

				return errQUEUE_BLOCKED;

			}

			else

			{

				portENABLE_INTERRUPTS();

				return errQUEUE_FULL;

			}

		}

	}

	portENABLE_INTERRUPTS();



	portNOP();



	portDISABLE_INTERRUPTS();

	{

		if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )

		{

			/* Data is available from the queue. */

			pxQueue->pcReadFrom += pxQueue->uxItemSize;

			if( pxQueue->pcReadFrom >= pxQueue->pcTail )

			{

				pxQueue->pcReadFrom = pxQueue->pcHead;

			}

			--( pxQueue->uxMessagesWaiting );

			memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );



			xReturn = pdPASS;



			/* Were any co-routines waiting for space to become available? */

			if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )

			{

				/* In this instance the co-routine could be placed directly 

				into the ready list as we are within a critical section.  

				Instead the same pending ready list mechansim is used as if

				the event were caused from within an interrupt. */

				if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )

				{

					xReturn = errQUEUE_YIELD;

				}

			}	

		}

		else

		{

			xReturn = pdFAIL;

		}

	}

	portENABLE_INTERRUPTS();



	return xReturn;

}

#endif

/*-----------------------------------------------------------*/







#if configUSE_CO_ROUTINES == 1

signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )

{

	/* Cannot block within an ISR so if there is no space on the queue then

	exit without doing anything. */

	if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )

	{

		prvCopyQueueData( pxQueue, pvItemToQueue );



		/* We only want to wake one co-routine per ISR, so check that a 

		co-routine has not already been woken. */

		if( !xCoRoutinePreviouslyWoken )		

		{

			if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )

			{

				if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )

				{

					return pdTRUE;

				}

			}

		}

	}



	return xCoRoutinePreviouslyWoken;

}

#endif

/*-----------------------------------------------------------*/



#if configUSE_CO_ROUTINES == 1

signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )

{

signed portBASE_TYPE xReturn;



	/* We cannot block from an ISR, so check there is data available. If

	not then just leave without doing anything. */

	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 * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );



		if( !( *pxCoRoutineWoken ) )

		{

			if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )

			{

				if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )

				{

					*pxCoRoutineWoken = pdTRUE;

				}

			}

		}



		xReturn = pdPASS;

	}

	else

	{

		xReturn = pdFAIL;

	}



	return xReturn;

}

#endif

/*-----------------------------------------------------------*/



⌨️ 快捷键说明

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