From ff9dfaa75c6b68af145369198deb6cd8721fe7cb Mon Sep 17 00:00:00 2001 From: rtel Date: Sat, 25 Jan 2014 17:01:41 +0000 Subject: [PATCH] Introduce xTimerPendFunctionCall(). Change INCLUDE_xTimerPendFunctionCallFromISR to INCLUDE_xTimerPendFunctionCall Update event group trace macros to match the new trace recorder code. Ensure parameter name consistency by renaming any occurrences of xBlockTime and xBlockTimeTicks to xTicksToWait. Continue work on GCC/RL78 port - still a work in progress. Adjust how the critical section was used in xQueueAddToSet. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2181 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- FreeRTOS/Source/event_groups.c | 47 +++++++-- FreeRTOS/Source/include/FreeRTOS.h | 32 ++++-- FreeRTOS/Source/include/event_groups.h | 3 + FreeRTOS/Source/include/queue.h | 16 +-- FreeRTOS/Source/include/timers.h | 123 +++++++++++++++-------- FreeRTOS/Source/portable/IAR/RL78/port.c | 51 ++++++++-- FreeRTOS/Source/queue.c | 40 ++++---- FreeRTOS/Source/timers.c | 56 ++++++++--- 8 files changed, 257 insertions(+), 111 deletions(-) diff --git a/FreeRTOS/Source/event_groups.c b/FreeRTOS/Source/event_groups.c index 859a54439..9747e0417 100644 --- a/FreeRTOS/Source/event_groups.c +++ b/FreeRTOS/Source/event_groups.c @@ -87,8 +87,8 @@ privileged Vs unprivileged linkage and placement. */ #error configUSE_TIMERS must be set to 1 to make the xEventGroupSetBitFromISR() function available. #endif -#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( INCLUDE_xTimerPendFunctionCallFromISR == 0 ) - #error INCLUDE_xTimerPendFunctionCallFromISR must also be set to one to make the xEventGroupSetBitFromISR() function available. +#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 0 ) + #error INCLUDE_xTimerPendFunctionCall must also be set to one to make the xEventGroupSetBitFromISR() function available. #endif /* The following bit fields convey control information in a task's event list @@ -110,6 +110,11 @@ typedef struct EVENT_GROUP_DEFINITION { EventBits_t uxEventBits; List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ + + #if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxEventGroupNumber; + #endif + } EventGroup_t; /*-----------------------------------------------------------*/ @@ -151,6 +156,7 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t u EventBits_t uxOriginalBitValue, uxReturn; EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; BaseType_t xAlreadyYielded; +BaseType_t xTimeoutOccurred = pdFALSE; configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( uxBitsToWaitFor != 0 ); @@ -162,8 +168,6 @@ BaseType_t xAlreadyYielded; vTaskSuspendAll(); { - traceEVENT_GROUP_SYNC_START( xEventGroup, uxBitsToSet ); - uxOriginalBitValue = pxEventBits->uxEventBits; ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet ); @@ -183,6 +187,8 @@ BaseType_t xAlreadyYielded; { if( xTicksToWait != ( TickType_t ) 0 ) { + traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); + /* Store the bits that the calling task is waiting for in the task's event list item so the kernel knows when a match is found. Then enter the blocked state. */ @@ -242,6 +248,8 @@ BaseType_t xAlreadyYielded; } } taskEXIT_CRITICAL(); + + xTimeoutOccurred = pdTRUE; } else { @@ -251,7 +259,7 @@ BaseType_t xAlreadyYielded; } } - traceEVENT_GROUP_SYNC_END( xEventGroup, uxReturn ); + traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ); return uxReturn; } /*-----------------------------------------------------------*/ @@ -261,6 +269,7 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; EventBits_t uxReturn, uxControlBits = 0; BaseType_t xWaitConditionMet, xAlreadyYielded; +BaseType_t xTimeoutOccurred = pdFALSE; /* Check the user is not attempting to wait on the bits used by the kernel itself, and that at least one bit is being requested. */ @@ -276,8 +285,6 @@ BaseType_t xWaitConditionMet, xAlreadyYielded; { const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; - traceEVENT_GROUP_WAIT_BITS_START( xEventGroup, uxBitsToWaitFor ); - /* Check to see if the wait condition is already met or not. */ xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits ); @@ -337,6 +344,8 @@ BaseType_t xWaitConditionMet, xAlreadyYielded; some compilers mistakenly generate a warning about the variable being returned without being set if it is not done. */ uxReturn = 0; + + traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); } } xAlreadyYielded = xTaskResumeAll(); @@ -384,6 +393,8 @@ BaseType_t xWaitConditionMet, xAlreadyYielded; } } taskEXIT_CRITICAL(); + + xTimeoutOccurred = pdFALSE; } else { @@ -392,8 +403,7 @@ BaseType_t xWaitConditionMet, xAlreadyYielded; uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; } } - - traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxReturn ); + traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); return uxReturn; } /*-----------------------------------------------------------*/ @@ -608,5 +618,24 @@ BaseType_t xWaitConditionMet = pdFALSE; return xWaitConditionMet; } +/*-----------------------------------------------------------*/ +#if (configUSE_TRACE_FACILITY == 1) + UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) + { + UBaseType_t xReturn; + EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; + + if( xEventGroup == NULL ) + { + xReturn = 0; + } + else + { + xReturn = pxEventBits->uxEventGroupNumber; + } + + return xReturn; + } +#endif diff --git a/FreeRTOS/Source/include/FreeRTOS.h b/FreeRTOS/Source/include/FreeRTOS.h index 43d7f7191..2f1c28534 100644 --- a/FreeRTOS/Source/include/FreeRTOS.h +++ b/FreeRTOS/Source/include/FreeRTOS.h @@ -249,8 +249,8 @@ is included as it is used by the port layer. */ #define INCLUDE_xEventGroupSetBitFromISR 0 #endif -#ifndef INCLUDE_xTimerPendFunctionCallFromISR - #define INCLUDE_xTimerPendFunctionCallFromISR 0 +#ifndef INCLUDE_xTimerPendFunctionCall + #define INCLUDE_xTimerPendFunctionCall 0 #endif #ifndef configASSERT @@ -567,20 +567,20 @@ is included as it is used by the port layer. */ #define traceEVENT_GROUP_CREATE_FAILED() #endif -#ifndef traceEVENT_GROUP_SYNC_START - #define traceEVENT_GROUP_SYNC_START( xEventGroup, uxBitsToSet ) +#ifndef traceEVENT_GROUP_SYNC_BLOCK + #define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ) #endif #ifndef traceEVENT_GROUP_SYNC_END - #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxReturn ) + #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred #endif -#ifndef traceEVENT_GROUP_WAIT_BITS_START - #define traceEVENT_GROUP_WAIT_BITS_START( xEventGroup, uxBitsToWaitFor ) +#ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK + #define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ) #endif #ifndef traceEVENT_GROUP_WAIT_BITS_END - #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxReturn ) + #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred #endif #ifndef traceEVENT_GROUP_CLEAR_BITS @@ -595,10 +595,26 @@ is included as it is used by the port layer. */ #define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ) #endif +#ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR + #define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ) +#endif + #ifndef traceEVENT_GROUP_DELETE #define traceEVENT_GROUP_DELETE( xEventGroup ) #endif +#ifndef tracePEND_FUNC_CALL + #define tracePEND_FUNC_CALL(xFunctionToPend, pvParameter1, ulParameter2, ret) +#endif + +#ifndef tracePEND_FUNC_CALL_FROM_ISR + #define tracePEND_FUNC_CALL_FROM_ISR(xFunctionToPend, pvParameter1, ulParameter2, ret) +#endif + +#ifndef traceQUEUE_REGISTRY_ADD + #define traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName) +#endif + #ifndef configGENERATE_RUN_TIME_STATS #define configGENERATE_RUN_TIME_STATS 0 #endif diff --git a/FreeRTOS/Source/include/event_groups.h b/FreeRTOS/Source/include/event_groups.h index 4407fff65..32cafea7d 100644 --- a/FreeRTOS/Source/include/event_groups.h +++ b/FreeRTOS/Source/include/event_groups.h @@ -663,6 +663,9 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ); /* For internal use only. */ void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ); +#if (configUSE_TRACE_FACILITY == 1) + UBaseType_t uxEventGroupGetNumber( void* xEventGroup ); +#endif #ifdef __cplusplus } diff --git a/FreeRTOS/Source/include/queue.h b/FreeRTOS/Source/include/queue.h index d160a0fcd..8a83ef258 100644 --- a/FreeRTOS/Source/include/queue.h +++ b/FreeRTOS/Source/include/queue.h @@ -1370,7 +1370,7 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pv void vAFunction( void *pvParameters ) { char cValueToPost; - const TickType_t xBlockTime = ( TickType_t )0xff; + const TickType_t xTicksToWait = ( TickType_t )0xff; // Create a queue capable of containing 10 characters. xQueue = xQueueCreate( 10, sizeof( char ) ); @@ -1382,17 +1382,17 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pv // ... // Post some characters that will be used within an ISR. If the queue - // is full then this task will block for xBlockTime ticks. + // is full then this task will block for xTicksToWait ticks. cValueToPost = 'a'; - xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime ); + xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait ); cValueToPost = 'b'; - xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime ); + xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait ); // ... keep posting characters ... this task may block when the queue // becomes full. cValueToPost = 'c'; - xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime ); + xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait ); } // ISR that outputs all the characters received on the queue. @@ -1480,7 +1480,7 @@ void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; * For internal use only. Use xSemaphoreTakeMutexRecursive() or * xSemaphoreGiveMutexRecursive() instead of calling these functions directly. */ -BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xBlockTime ) PRIVILEGED_FUNCTION; +BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION; /* @@ -1653,7 +1653,7 @@ BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueS * * @param xQueueSet The queue set on which the task will (potentially) block. * - * @param xBlockTimeTicks The maximum time, in ticks, that the calling task will + * @param xTicksToWait The maximum time, in ticks, that the calling task will * remain in the Blocked state (with other tasks executing) to wait for a member * of the queue set to be ready for a successful queue read or semaphore take * operation. @@ -1664,7 +1664,7 @@ BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueS * in the queue set that is available, or NULL if no such queue or semaphore * exists before before the specified block time expires. */ -QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xBlockTimeTicks ) PRIVILEGED_FUNCTION; +QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /* * A version of xQueueSelectFromSet() that can be used from an ISR. diff --git a/FreeRTOS/Source/include/timers.h b/FreeRTOS/Source/include/timers.h index 2b9698d36..b25144eb0 100644 --- a/FreeRTOS/Source/include/timers.h +++ b/FreeRTOS/Source/include/timers.h @@ -89,18 +89,19 @@ be used solely through the macros that make up the public software timer API, as defined below. The commands that are sent from interrupts must use the highest numbers as tmrFIRST_FROM_ISR_COMMAND is used to determine if the task or interrupt version of the queue send function should be used. */ -#define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 ) -#define tmrCOMMAND_START ( ( BaseType_t ) 0 ) -#define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 1 ) -#define tmrCOMMAND_RESET ( ( BaseType_t ) 2 ) -#define tmrCOMMAND_STOP ( ( BaseType_t ) 3 ) -#define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 ) -#define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 ) +#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 ) +#define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 ) +#define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 ) +#define tmrCOMMAND_START ( ( BaseType_t ) 1 ) +#define tmrCOMMAND_RESET ( ( BaseType_t ) 2 ) +#define tmrCOMMAND_STOP ( ( BaseType_t ) 3 ) +#define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 ) +#define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 ) -#define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 ) -#define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 7 ) -#define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 8 ) -#define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 9 ) +#define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 ) +#define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 ) +#define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 ) +#define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 ) /** @@ -111,13 +112,13 @@ or interrupt version of the queue send function should be used. */ */ typedef void * TimerHandle_t; -/* - * Defines the prototype to which timer callback functions must conform. +/* + * Defines the prototype to which timer callback functions must conform. */ typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer ); -/* - * Defines the prototype to which functions used with the +/* + * Defines the prototype to which functions used with the * xTimerPendFunctionCallFromISR() function must conform. */ typedef void (*PendedFunction_t)( void *, uint32_t ); @@ -324,7 +325,7 @@ BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); /** - * BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xBlockTime ); + * BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task @@ -353,14 +354,14 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * * @param xTimer The handle of the timer being started/restarted. * - * @param xBlockTime Specifies the time, in ticks, that the calling task should + * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the start command to be successfully * sent to the timer command queue, should the queue already be full when - * xTimerStart() was called. xBlockTime is ignored if xTimerStart() is called + * xTimerStart() was called. xTicksToWait is ignored if xTimerStart() is called * before the scheduler is started. * * @return pdFAIL will be returned if the start command could not be sent to - * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will * be returned if the command was successfully sent to the timer command queue. * When the command is actually processed will depend on the priority of the * timer service/daemon task relative to other tasks in the system, although the @@ -373,10 +374,10 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * See the xTimerCreate() API function example usage scenario. * */ -#define xTimerStart( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) ) +#define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) /** - * BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xBlockTime ); + * BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task @@ -396,14 +397,14 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * * @param xTimer The handle of the timer being stopped. * - * @param xBlockTime Specifies the time, in ticks, that the calling task should + * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the stop command to be successfully * sent to the timer command queue, should the queue already be full when - * xTimerStop() was called. xBlockTime is ignored if xTimerStop() is called + * xTimerStop() was called. xTicksToWait is ignored if xTimerStop() is called * before the scheduler is started. * * @return pdFAIL will be returned if the stop command could not be sent to - * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will * be returned if the command was successfully sent to the timer command queue. * When the command is actually processed will depend on the priority of the * timer service/daemon task relative to other tasks in the system. The timer @@ -415,12 +416,12 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * See the xTimerCreate() API function example usage scenario. * */ -#define xTimerStop( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xBlockTime ) ) +#define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) ) /** * BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, * TickType_t xNewPeriod, - * TickType_t xBlockTime ); + * TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task @@ -448,14 +449,14 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than * or equal to 1000. * - * @param xBlockTime Specifies the time, in ticks, that the calling task should + * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the change period command to be * successfully sent to the timer command queue, should the queue already be - * full when xTimerChangePeriod() was called. xBlockTime is ignored if + * full when xTimerChangePeriod() was called. xTicksToWait is ignored if * xTimerChangePeriod() is called before the scheduler is started. * * @return pdFAIL will be returned if the change period command could not be - * sent to the timer command queue even after xBlockTime ticks had passed. + * sent to the timer command queue even after xTicksToWait ticks had passed. * pdPASS will be returned if the command was successfully sent to the timer * command queue. When the command is actually processed will depend on the * priority of the timer service/daemon task relative to other tasks in the @@ -495,10 +496,10 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * } * @endverbatim */ - #define xTimerChangePeriod( xTimer, xNewPeriod, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xBlockTime ) ) + #define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) ) /** - * BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xBlockTime ); + * BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task @@ -515,14 +516,14 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * * @param xTimer The handle of the timer being deleted. * - * @param xBlockTime Specifies the time, in ticks, that the calling task should + * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the delete command to be * successfully sent to the timer command queue, should the queue already be - * full when xTimerDelete() was called. xBlockTime is ignored if xTimerDelete() + * full when xTimerDelete() was called. xTicksToWait is ignored if xTimerDelete() * is called before the scheduler is started. * * @return pdFAIL will be returned if the delete command could not be sent to - * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will * be returned if the command was successfully sent to the timer command queue. * When the command is actually processed will depend on the priority of the * timer service/daemon task relative to other tasks in the system. The timer @@ -533,10 +534,10 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * * See the xTimerChangePeriod() API function example usage scenario. */ -#define xTimerDelete( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xBlockTime ) ) +#define xTimerDelete( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) ) /** - * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xBlockTime ); + * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait ); * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task @@ -567,14 +568,14 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * * @param xTimer The handle of the timer being reset/started/restarted. * - * @param xBlockTime Specifies the time, in ticks, that the calling task should + * @param xTicksToWait Specifies the time, in ticks, that the calling task should * be held in the Blocked state to wait for the reset command to be successfully * sent to the timer command queue, should the queue already be full when - * xTimerReset() was called. xBlockTime is ignored if xTimerReset() is called + * xTimerReset() was called. xTicksToWait is ignored if xTimerReset() is called * before the scheduler is started. * * @return pdFAIL will be returned if the reset command could not be sent to - * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will * be returned if the command was successfully sent to the timer command queue. * When the command is actually processed will depend on the priority of the * timer service/daemon task relative to other tasks in the system, although the @@ -657,7 +658,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * } * @endverbatim */ -#define xTimerReset( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) ) +#define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) /** * BaseType_t xTimerStartFromISR( TimerHandle_t xTimer, @@ -976,13 +977,13 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); * * * Used from application interrupt service routines to defer the execution of a - * function to the RTOS daemon task (the timer service task, hence this function + * function to the RTOS daemon task (the timer service task, hence this function * is implemented in timers.c and is prefixed with 'Timer'). * * Ideally an interrupt service routine (ISR) is kept as short as possible, but * sometimes an ISR either has a lot of processing to do, or needs to perform - * processing that is not deterministic. In these cases - * xTimerPendFunctionCallFromISR() can be used to defer processing of a function + * processing that is not deterministic. In these cases + * xTimerPendFunctionCallFromISR() can be used to defer processing of a function * to the RTOS daemon task. * * A mechanism is provided that allows the interrupt to return directly to the @@ -1058,12 +1059,46 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); */ BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ); + /** + * BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, + * void *pvParameter1, + * uint32_t ulParameter2, + * TickType_t xTicksToWait ); + * + * + * Used to defer the execution of a function to the RTOS daemon task (the timer + * service task, hence this function is implemented in timers.c and is prefixed + * with 'Timer'). + * + * @param xFunctionToPend The function to execute from the timer service/ + * daemon task. The function must conform to the PendedFunction_t + * prototype. + * + * @param pvParameter1 The value of the callback function's first parameter. + * The parameter has a void * type to allow it to be used to pass any type. + * For example, unsigned longs can be cast to a void *, or the void * can be + * used to point to a structure. + * + * @param ulParameter2 The value of the callback function's second parameter. + * + * @param xTicksToWait Calling this function will result in a message being + * sent to the timer daemon task on a queue. xTicksToWait is the amount of + * time the calling task should remain in the Blocked state (so not using any + * processing time) for space to become available on the timer queue if the + * queue is found to be full. + * + * @return pdPASS is returned if the message was successfully sent to the + * timer daemon task, otherwise pdFALSE is returned. + * + */ +BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ); + /* * Functions beyond this part are not part of the public API and are intended * for use by the kernel only. */ BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; -BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xBlockTime ) PRIVILEGED_FUNCTION; +BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; #ifdef __cplusplus } diff --git a/FreeRTOS/Source/portable/IAR/RL78/port.c b/FreeRTOS/Source/portable/IAR/RL78/port.c index aa352fbc1..24178e9fb 100644 --- a/FreeRTOS/Source/portable/IAR/RL78/port.c +++ b/FreeRTOS/Source/portable/IAR/RL78/port.c @@ -1,5 +1,5 @@ /* - FreeRTOS V8.0.0:rc1 - Copyright (C) 2014 Real Time Engineers Ltd. + FreeRTOS V8.0.0:rc1 - Copyright (C) 2014 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -120,6 +120,11 @@ static void prvSetupTimerInterrupt( void ); */ extern void vPortStartFirstTask( void ); +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + /*-----------------------------------------------------------*/ /* @@ -132,9 +137,13 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px { uint32_t *pulLocal; + /* With large code and large data sizeof( StackType_t ) == 2, and + sizeof( StackType_t * ) == 4. With small code and small data + sizeof( StackType_t ) == 2 and sizeof( StackType_t * ) == 2. */ + #if __DATA_MODEL__ == __DATA_MODEL_FAR__ { - /* Parameters are passed in on the stack, and written using a 32bit value + /* Parameters are passed in on the stack, and written using a 32-bit value hence a space is left for the second two bytes. */ pxTopOfStack--; @@ -143,14 +152,15 @@ uint32_t *pulLocal; *pulLocal = ( uint32_t ) pvParameters; pxTopOfStack--; - /* These values are just spacers. The return address of the function - would normally be written here. */ - *pxTopOfStack = ( StackType_t ) 0xcdcd; + /* The return address, leaving space for the first two bytes of the + 32-bit value. See the comments above the prvTaskExitError() prototype + at the top of this file. */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0xcdcd; + pulLocal = ( uint32_t * ) pxTopOfStack; + *pulLocal = ( uint32_t ) prvTaskExitError; pxTopOfStack--; - /* The start address / PSW value is also written in as a 32bit value, + /* The start address / PSW value is also written in as a 32-bit value, so leave a space for the second two bytes. */ pxTopOfStack--; @@ -165,9 +175,16 @@ uint32_t *pulLocal; } #else { - /* Task function address is written to the stack first. As it is - written as a 32bit value a space is left on the stack for the second - two bytes. */ + /* The return address, leaving space for the first two bytes of the + 32-bit value. See the comments above the prvTaskExitError() prototype + at the top of this file. */ + pxTopOfStack--; + pulLocal = ( uint32_t * ) pxTopOfStack; + *pulLocal = ( uint32_t ) prvTaskExitError; + pxTopOfStack--; + + /* Task function. Again as it is written as a 32-bit value a space is + left on the stack for the second two bytes. */ pxTopOfStack--; /* Task function start address combined with the PSW. */ @@ -205,6 +222,20 @@ uint32_t *pulLocal; } /*-----------------------------------------------------------*/ +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( usCriticalNesting == ~0U ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + BaseType_t xPortStartScheduler( void ) { /* Setup the hardware to generate the tick. Interrupts are disabled when diff --git a/FreeRTOS/Source/queue.c b/FreeRTOS/Source/queue.c index bb391020d..3fb1b6ce5 100644 --- a/FreeRTOS/Source/queue.c +++ b/FreeRTOS/Source/queue.c @@ -512,7 +512,7 @@ QueueHandle_t xReturn = NULL; #if ( configUSE_RECURSIVE_MUTEXES == 1 ) - BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xBlockTime ) + BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) { BaseType_t xReturn; Queue_t * const pxMutex = ( Queue_t * ) xMutex; @@ -531,7 +531,7 @@ QueueHandle_t xReturn = NULL; } else { - xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE ); + xReturn = xQueueGenericReceive( pxMutex, NULL, xTicksToWait, pdFALSE ); /* pdPASS will only be returned if we successfully obtained the mutex, we may have blocked to reach here. */ @@ -2156,6 +2156,8 @@ BaseType_t xReturn; /* Store the information on this queue. */ xQueueRegistry[ ux ].pcQueueName = pcQueueName; xQueueRegistry[ ux ].xHandle = xQueue; + + traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ); break; } else @@ -2251,26 +2253,26 @@ BaseType_t xReturn; { BaseType_t xReturn; - if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) - { - /* Cannot add a queue/semaphore to more than one queue set. */ - xReturn = pdFAIL; - } - else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 ) - { - /* Cannot add a queue/semaphore to a queue set if there are already - items in the queue/semaphore. */ - xReturn = pdFAIL; - } - else + taskENTER_CRITICAL(); { - taskENTER_CRITICAL(); + if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) + { + /* Cannot add a queue/semaphore to more than one queue set. */ + xReturn = pdFAIL; + } + else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 ) + { + /* Cannot add a queue/semaphore to a queue set if there are already + items in the queue/semaphore. */ + xReturn = pdFAIL; + } + else { ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; + xReturn = pdPASS; } - taskEXIT_CRITICAL(); - xReturn = pdPASS; } + taskEXIT_CRITICAL(); return xReturn; } @@ -2316,11 +2318,11 @@ BaseType_t xReturn; #if ( configUSE_QUEUE_SETS == 1 ) - QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xBlockTimeTicks ) + QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait ) { QueueSetMemberHandle_t xReturn = NULL; - ( void ) xQueueGenericReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */ + ( void ) xQueueGenericReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */ return xReturn; } diff --git a/FreeRTOS/Source/timers.c b/FreeRTOS/Source/timers.c index 26f537d72..8f6747a89 100644 --- a/FreeRTOS/Source/timers.c +++ b/FreeRTOS/Source/timers.c @@ -76,8 +76,8 @@ task.h is included from an application file. */ #include "queue.h" #include "timers.h" -#if ( INCLUDE_xTimerPendFunctionCallFromISR == 1 ) && ( configUSE_TIMERS == 0 ) - #error configUSE_TIMERS must be set to 1 to make the INCLUDE_xTimerPendFunctionCallFromISR() function available. +#if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 ) + #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available. #endif /* Lint e961 and e750 are suppressed as a MISRA exception justified because the @@ -140,9 +140,9 @@ typedef struct tmrTimerQueueMessage /* Don't include xCallbackParameters if it is not going to be used as it makes the structure (and therefore the timer queue) larger. */ - #if ( INCLUDE_xTimerPendFunctionCallFromISR == 1 ) + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) CallbackParameters_t xCallbackParameters; - #endif /* INCLUDE_xTimerPendFunctionCallFromISR */ + #endif /* INCLUDE_xTimerPendFunctionCall */ } u; } DaemonTaskMessage_t; @@ -305,7 +305,7 @@ Timer_t *pxNewTimer; } /*-----------------------------------------------------------*/ -BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xBlockTime ) +BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) { BaseType_t xReturn = pdFAIL; DaemonTaskMessage_t xMessage; @@ -323,7 +323,7 @@ DaemonTaskMessage_t xMessage; { if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) { - xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xBlockTime ); + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); } else { @@ -575,9 +575,11 @@ TickType_t xTimeNow; while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */ { - #if ( INCLUDE_xTimerPendFunctionCallFromISR == 1 ) + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) { - if( xMessage.xMessageID == tmrCOMMAND_EXECUTE_CALLBACK ) + /* Negative commands are pended function calls rather than timer + commands. */ + if( xMessage.xMessageID < 0 ) { const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters ); @@ -593,9 +595,11 @@ TickType_t xTimeNow; mtCOVERAGE_TEST_MARKER(); } } - #endif /* INCLUDE_xTimerPendFunctionCallFromISR */ + #endif /* INCLUDE_xTimerPendFunctionCall */ - if( xMessage.xMessageID != tmrCOMMAND_EXECUTE_CALLBACK ) + /* Commands that are positive are timer commands rather than pended + function calls. */ + if( xMessage.xMessageID >= 0 ) { /* The messages uses the xTimerParameters member to work on a software timer. */ @@ -811,7 +815,7 @@ Timer_t * const pxTimer = ( Timer_t * ) xTimer; } /*-----------------------------------------------------------*/ -#if( INCLUDE_xTimerPendFunctionCallFromISR == 1 ) +#if( INCLUDE_xTimerPendFunctionCall == 1 ) BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) { @@ -820,17 +824,43 @@ Timer_t * const pxTimer = ( Timer_t * ) xTimer; /* Complete the message with the function parameters and post it to the daemon task. */ - xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK; + xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR; xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); + + tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + + return xReturn; + } + +#endif /* INCLUDE_xTimerPendFunctionCall */ +/*-----------------------------------------------------------*/ + +#if( INCLUDE_xTimerPendFunctionCall == 1 ) + + BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) + { + DaemonTaskMessage_t xMessage; + BaseType_t xReturn; + + /* Complete the message with the function parameters and post it to the + daemon task. */ + xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK; + xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; + xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; + xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; + + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); + tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + return xReturn; } -#endif /* INCLUDE_xTimerPendFunctionCallFromISR */ +#endif /* INCLUDE_xTimerPendFunctionCall */ /*-----------------------------------------------------------*/ /* This entire source file will be skipped if the application is not configured -- 2.39.5