mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-19 09:38:32 -04:00
Add first version of alternative API.
This commit is contained in:
parent
b6d2b739f3
commit
8603259d40
17 changed files with 2308 additions and 120 deletions
|
@ -112,12 +112,16 @@
|
|||
#error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_MUTEXES
|
||||
#define configUSE_MUTEXES 0
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_COUNTING_SEMAPHORES
|
||||
#define configUSE_COUNTING_SEMAPHORES 0
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_MUTEXES
|
||||
#define configUSE_MUTEXES 0
|
||||
#ifndef configUSE_ALTERNATIVE_API
|
||||
#define configUSE_ALTERNATIVE_API 0
|
||||
#endif
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
|
|
|
@ -1159,6 +1159,30 @@ signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void
|
|||
*/
|
||||
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, const void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );
|
||||
|
||||
/*
|
||||
* xQueueAltGenericSend() is a light weight version of xQueueGenericSend().
|
||||
* Likewise xQueueAltGenericReceive() is a light weight version of
|
||||
* xQueueGenericReceive().
|
||||
*
|
||||
* The source code that implements the light weight (fast) 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
|
||||
* fully featured API as an alternative. The fully featured API has more
|
||||
* complex code that takes longer to execute, but makes much less use of
|
||||
* critical sections. Therefore the light weight API sacrifices interrupt
|
||||
* responsiveness to gain execution speed, whereas the fully featured API
|
||||
* sacrifices execution speed to ensure better interrupt responsiveness.
|
||||
*/
|
||||
signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
|
||||
signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );
|
||||
|
||||
/*
|
||||
* The light weight versions of the fully featured macros.
|
||||
*/
|
||||
#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_FRONT )
|
||||
#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK )
|
||||
#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( xQueue, pvBuffer, xTicksToWait, pdFALSE )
|
||||
#define xQueueAltPeek( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( xQueue, pvBuffer, xTicksToWait, pdTRUE )
|
||||
|
||||
/*
|
||||
* The functions defined above are for passing data to and from tasks. The
|
||||
|
|
|
@ -154,7 +154,8 @@ typedef xQueueHandle xSemaphoreHandle;
|
|||
* \defgroup xSemaphoreTake xSemaphoreTake
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime )
|
||||
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime, pdFALSE )
|
||||
#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime, pdFALSE )
|
||||
|
||||
/**
|
||||
* semphr. h
|
||||
|
@ -213,7 +214,8 @@ typedef xQueueHandle xSemaphoreHandle;
|
|||
* \defgroup xSemaphoreGive xSemaphoreGive
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
|
||||
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
|
||||
#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
|
||||
|
||||
/**
|
||||
* semphr. h
|
||||
|
|
|
@ -77,6 +77,11 @@ is being used. */
|
|||
/* Trap routine used by taskYIELD() to manually cause a context switch. */
|
||||
static void __interrupt __far prvYieldProcessor( void );
|
||||
|
||||
/* The timer initialisation functions leave interrupts enabled,
|
||||
which is not what we want. This ISR is installed temporarily in case
|
||||
the timer fires before we get a change to disable interrupts again. */
|
||||
static void __interrupt __far prvDummyISR( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/* See header file for description. */
|
||||
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
|
||||
|
@ -162,6 +167,15 @@ portBASE_TYPE xPortStartScheduler( void )
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void __interrupt __far prvDummyISR( void )
|
||||
{
|
||||
/* The timer initialisation functions leave interrupts enabled,
|
||||
which is not what we want. This ISR is installed temporarily in case
|
||||
the timer fires before we get a change to disable interrupts again. */
|
||||
outport( portEIO_REGISTER, portCLEAR_INTERRUPT );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The ISR used depends on whether the preemptive or cooperative scheduler
|
||||
is being used. */
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
|
@ -204,15 +218,23 @@ void vPortEndScheduler( void )
|
|||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
const unsigned portSHORT usTimerACompare = portTIMER_COMPARE, usTimerAMode = portENABLE_TIMER_AND_INTERRUPT;
|
||||
const unsigned portSHORT usT2_IRQ = 0x13;
|
||||
|
||||
/* Configure the timer, the dummy handler is used here as the init
|
||||
function leaves interrupts enabled. */
|
||||
t2_init( usTimerAMode, usTimerACompare, prvDummyISR );
|
||||
|
||||
/* Disable interrupts again before installing the real handlers. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
/* Tick service routine used by the scheduler when preemptive scheduling is
|
||||
being used. */
|
||||
t2_init( usTimerAMode, usTimerACompare, prvPreemptiveTick );
|
||||
setvect( usT2_IRQ, prvPreemptiveTick );
|
||||
#else
|
||||
/* Tick service routine used by the scheduler when cooperative scheduling is
|
||||
being used. */
|
||||
t2_init( usTimerAMode, usTimerACompare, prvNonPreemptiveTick );
|
||||
setvect( usT2_IRQ, prvNonPreemptiveTick );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
200
Source/queue.c
200
Source/queue.c
|
@ -77,7 +77,7 @@ typedef struct QueueDefinition
|
|||
xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
|
||||
xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
|
||||
|
||||
unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
|
||||
volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
|
||||
unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
|
||||
unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
|
||||
|
||||
|
@ -107,6 +107,8 @@ signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, const void * co
|
|||
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, const void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );
|
||||
xQueueHandle xQueueCreateMutex( void );
|
||||
xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount );
|
||||
signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
|
||||
signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );
|
||||
|
||||
#if configUSE_CO_ROUTINES == 1
|
||||
signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );
|
||||
|
@ -455,6 +457,202 @@ xTimeOutType xTimeOut;
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#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 light weight (fast) 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
|
||||
fully featured API as an alternative. The fully featured API has more
|
||||
complex code that takes longer to execute, but makes much less use of
|
||||
critical sections. Therefore the light weight 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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
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 light weight (fast) 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
|
||||
fully featured API as an alternative. The fully featured API has more
|
||||
complex code that takes longer to execute, but makes much less use of
|
||||
critical sections. Therefore the light weight 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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue