Prepare for a FreeRTOS V9 release candidate:
- Remove the standard demo files that used the [long since deprecated] alternative API. - Add standard demo task that tests the new xTaskAbortDelay() function. - Update the Win32 Visual Studio project to use Visual Studio 2015 Community Edition. - Rename the xGenericListItem TCB member to xStateListItem as it better describes the member's purpose.pull/1/head
parent
c7b7b90cc9
commit
d7253324cd
@ -0,0 +1,650 @@
|
|||||||
|
/*
|
||||||
|
FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
This file is part of the FreeRTOS distribution.
|
||||||
|
|
||||||
|
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License (version 2) as published by the
|
||||||
|
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||||
|
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||||
|
>>! obliged to provide the source code for proprietary components !<<
|
||||||
|
>>! outside of the FreeRTOS kernel. !<<
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that is more than just the market leader, it *
|
||||||
|
* is the industry's de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly while simultaneously helping *
|
||||||
|
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||||
|
* tutorial book, reference manual, or both: *
|
||||||
|
* http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||||
|
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||||
|
defined configASSERT()?
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||||
|
embedded software for free we request you assist our global community by
|
||||||
|
participating in the support forum.
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||||
|
be as productive as possible as early as possible. Now you can receive
|
||||||
|
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||||
|
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||||
|
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||||
|
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||||
|
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||||
|
|
||||||
|
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||||
|
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and commercial middleware.
|
||||||
|
|
||||||
|
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||||
|
engineered and independently SIL3 certified version for use in safety and
|
||||||
|
mission critical applications that require provable dependability.
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains some test scenarios that ensure tasks respond correctly
|
||||||
|
* to xTaskAbortDelay() calls.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include "limits.h"
|
||||||
|
|
||||||
|
/* Kernel includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "queue.h"
|
||||||
|
#include "semphr.h"
|
||||||
|
#include "event_groups.h"
|
||||||
|
|
||||||
|
/* Demo includes. */
|
||||||
|
#include "AbortDelay.h"
|
||||||
|
|
||||||
|
/* This file can only be used if the functionality it tests is included in the
|
||||||
|
build. Remove the whole file if this is not the case. */
|
||||||
|
#if( INCLUDE_xTaskAbortDelay == 1 )
|
||||||
|
|
||||||
|
#if( INCLUDE_xTaskGetTaskHandle != 1 )
|
||||||
|
#error This test file uses the xTaskGetTaskHandle() API function so INCLUDE_xTaskGetTaskHandle must be set to 1 in FreeRTOSConfig.h.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Task priorities. Allow these to be overridden. */
|
||||||
|
#ifndef abtCONTROLLING_PRIORITY
|
||||||
|
#define abtCONTROLLING_PRIORITY ( configMAX_PRIORITIES - 3 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef abtBLOCKING_PRIORITY
|
||||||
|
#define abtBLOCKING_PRIORITY ( configMAX_PRIORITIES - 2 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The tests that are performed. */
|
||||||
|
#define abtNOTIFY_WAIT_ABORTS 0
|
||||||
|
#define abtNOTIFY_TAKE_ABORTS 1
|
||||||
|
#define abtDELAY_ABORTS 2
|
||||||
|
#define abtDELAY_UNTIL_ABORTS 3
|
||||||
|
#define abtSEMAPHORE_TAKE_ABORTS 4
|
||||||
|
#define abtEVENT_GROUP_ABORTS 5
|
||||||
|
#define abtQUEUE_SEND_ABORTS 6
|
||||||
|
#define abtMAX_TESTS 7
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The two test tasks. The controlling task specifies which test to executed.
|
||||||
|
* More information is provided in the comments within the tasks.
|
||||||
|
*/
|
||||||
|
static void prvControllingTask( void *pvParameters );
|
||||||
|
static void prvBlockingTask( void *pvParameters );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test functions called by the blocking task. Each function follows the same
|
||||||
|
* pattern, but the way the task blocks is different in each case.
|
||||||
|
*
|
||||||
|
* In each function three blocking calls are made. The first and third
|
||||||
|
* blocking call is expected to time out, while the middle blocking call is
|
||||||
|
* expected to be aborted by the controlling task half way through the block
|
||||||
|
* time.
|
||||||
|
*/
|
||||||
|
static void prvTestAbortingTaskNotifyWait( void );
|
||||||
|
static void prvTestAbortingTaskNotifyTake( void );
|
||||||
|
static void prvTestAbortingTaskDelay( void );
|
||||||
|
static void prvTestAbortingTaskDelayUntil( void );
|
||||||
|
static void prvTestAbortingSemaphoreTake( void );
|
||||||
|
static void prvTestAbortingEventGroupWait( void );
|
||||||
|
static void prvTestAbortingQueueSend( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checks the amount of time a task spent in the Blocked state is within the
|
||||||
|
* expected bounds.
|
||||||
|
*/
|
||||||
|
static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Used to ensure that tasks are still executing without error. */
|
||||||
|
static volatile BaseType_t xControllingCycles = 0, xBlockingCycles = 0;
|
||||||
|
static volatile BaseType_t xErrorOccurred = pdFALSE;
|
||||||
|
|
||||||
|
/* Each task needs to know the other tasks handle so they can send signals to
|
||||||
|
each other. The handle is obtained from the task's name. */
|
||||||
|
static const char *pcControllingTaskName = "AbtCtrl", *pcBlockingTaskName = "AbtBlk";
|
||||||
|
|
||||||
|
/* The maximum amount of time a task will block for. */
|
||||||
|
const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 100 );
|
||||||
|
const TickType_t xHalfMaxBlockTime = pdMS_TO_TICKS( 50 );
|
||||||
|
|
||||||
|
/* The actual block time is dependent on the priority of other tasks in the
|
||||||
|
system so the actual block time might be greater than that expected, but it
|
||||||
|
should be within an acceptable upper bound. */
|
||||||
|
const TickType_t xAllowableMargin = pdMS_TO_TICKS( 7 );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vCreateAbortDelayTasks( void )
|
||||||
|
{
|
||||||
|
/* Create the two test tasks described above. */
|
||||||
|
xTaskCreate( prvControllingTask, pcControllingTaskName, configMINIMAL_STACK_SIZE, NULL, abtCONTROLLING_PRIORITY, NULL );
|
||||||
|
xTaskCreate( prvBlockingTask, pcBlockingTaskName, configMINIMAL_STACK_SIZE, NULL, abtBLOCKING_PRIORITY, NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvControllingTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
TaskHandle_t xBlockingTask;
|
||||||
|
uint32_t ulTestToPerform = abtNOTIFY_WAIT_ABORTS;
|
||||||
|
TickType_t xTimeAtStart;
|
||||||
|
const TickType_t xStartMargin = 2UL;
|
||||||
|
|
||||||
|
/* Just to remove compiler warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
xBlockingTask = xTaskGetTaskHandle( pcBlockingTaskName );
|
||||||
|
configASSERT( xBlockingTask );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Tell the secondary task to perform the next test. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
xTaskNotify( xBlockingTask, ulTestToPerform, eSetValueWithOverwrite );
|
||||||
|
|
||||||
|
/* The secondary task has a higher priority, so will now be in the
|
||||||
|
Blocked state to wait for a maximum of xMaxBlockTime. It expects that
|
||||||
|
period to complete with a timeout. It will then block for
|
||||||
|
xMaxBlockTimeAgain, but this time it expects to the block time to abort
|
||||||
|
half way through. Block until it is time to send the abort to the
|
||||||
|
secondary task. xStartMargin is used because this task takes timing
|
||||||
|
from the beginning of the test, whereas the blocking task takes timing
|
||||||
|
from the entry into the Blocked state - and as the tasks run at
|
||||||
|
different priorities, there may be some discrepancy. Also, temporarily
|
||||||
|
raise the priority of the controlling task to that of the blocking
|
||||||
|
task to minimise discrepancies. */
|
||||||
|
vTaskPrioritySet( NULL, abtBLOCKING_PRIORITY );
|
||||||
|
vTaskDelay( xMaxBlockTime + xHalfMaxBlockTime + xStartMargin );
|
||||||
|
xTaskAbortDelay( xBlockingTask );
|
||||||
|
|
||||||
|
/* Reset the priority to the normal controlling priority. */
|
||||||
|
vTaskPrioritySet( NULL, abtCONTROLLING_PRIORITY );
|
||||||
|
|
||||||
|
/* Now wait to be notified that the secondary task has completed its
|
||||||
|
test. */
|
||||||
|
ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
|
||||||
|
|
||||||
|
/* Did the entire test run for the expected time, which is two full
|
||||||
|
block times plus the half block time caused by calling
|
||||||
|
xTaskAbortDelay()? */
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, ( xMaxBlockTime + xMaxBlockTime + xHalfMaxBlockTime ) );
|
||||||
|
|
||||||
|
/* Move onto the next test. */
|
||||||
|
ulTestToPerform++;
|
||||||
|
|
||||||
|
if( ulTestToPerform >= abtMAX_TESTS )
|
||||||
|
{
|
||||||
|
ulTestToPerform = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To indicate this task is still executing. */
|
||||||
|
xControllingCycles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvBlockingTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
TaskHandle_t xControllingTask;
|
||||||
|
uint32_t ulNotificationValue;
|
||||||
|
|
||||||
|
/* Just to remove compiler warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
xControllingTask = xTaskGetTaskHandle( pcControllingTaskName );
|
||||||
|
configASSERT( xControllingTask );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Wait to be notified of the test that is to be performed next. */
|
||||||
|
xTaskNotifyWait( 0, ULONG_MAX, &ulNotificationValue, portMAX_DELAY );
|
||||||
|
|
||||||
|
switch( ulNotificationValue )
|
||||||
|
{
|
||||||
|
case abtNOTIFY_WAIT_ABORTS:
|
||||||
|
prvTestAbortingTaskNotifyWait();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case abtNOTIFY_TAKE_ABORTS:
|
||||||
|
prvTestAbortingTaskNotifyTake();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case abtDELAY_ABORTS:
|
||||||
|
prvTestAbortingTaskDelay();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case abtDELAY_UNTIL_ABORTS:
|
||||||
|
prvTestAbortingTaskDelayUntil();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case abtSEMAPHORE_TAKE_ABORTS:
|
||||||
|
prvTestAbortingSemaphoreTake();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case abtEVENT_GROUP_ABORTS:
|
||||||
|
prvTestAbortingEventGroupWait();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case abtQUEUE_SEND_ABORTS:
|
||||||
|
prvTestAbortingQueueSend();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Should not get here. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let the primary task know the test is complete. */
|
||||||
|
xTaskNotifyGive( xControllingTask );
|
||||||
|
|
||||||
|
/* To indicate this task is still executing. */
|
||||||
|
xBlockingCycles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTestAbortingTaskDelayUntil( void )
|
||||||
|
{
|
||||||
|
TickType_t xTimeAtStart, xLastBlockTime;
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* Take a copy of the time as it is updated in the call to
|
||||||
|
vTaskDelayUntil() but its original value is needed to determine the actual
|
||||||
|
time spend in the Blocked state. */
|
||||||
|
xLastBlockTime = xTimeAtStart;
|
||||||
|
|
||||||
|
/* This first delay should just time out. */
|
||||||
|
vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
|
/* This second delay should be aborted by the primary task half way
|
||||||
|
through. Again take a copy of the time as it is updated in the call to
|
||||||
|
vTaskDelayUntil() buts its original value is needed to determine the amount
|
||||||
|
of time actually spent in the Blocked state. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
xLastBlockTime = xTimeAtStart;
|
||||||
|
vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
|
/* As with the other tests, the third block period should not time out. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
xLastBlockTime = xTimeAtStart;
|
||||||
|
vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTestAbortingTaskDelay( void )
|
||||||
|
{
|
||||||
|
TickType_t xTimeAtStart;
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This first delay should just time out. */
|
||||||
|
vTaskDelay( xMaxBlockTime );
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This second delay should be aborted by the primary task half way
|
||||||
|
through. */
|
||||||
|
vTaskDelay( xMaxBlockTime );
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This third delay should just time out again. */
|
||||||
|
vTaskDelay( xMaxBlockTime );
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTestAbortingTaskNotifyTake( void )
|
||||||
|
{
|
||||||
|
TickType_t xTimeAtStart;
|
||||||
|
uint32_t ulReturn;
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This first delay should just time out. */
|
||||||
|
ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
|
||||||
|
if( ulReturn != 0 )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This second delay should be aborted by the primary task half way
|
||||||
|
through. */
|
||||||
|
ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
|
||||||
|
if( ulReturn != 0 )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This third delay should just time out again. */
|
||||||
|
ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
|
||||||
|
if( ulReturn != 0 )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTestAbortingEventGroupWait( void )
|
||||||
|
{
|
||||||
|
TickType_t xTimeAtStart;
|
||||||
|
static StaticEventGroup_t xEventGroupBuffer;
|
||||||
|
EventGroupHandle_t xEventGroup;
|
||||||
|
EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;
|
||||||
|
|
||||||
|
/* Create the event group. Statically allocated memory is used so the
|
||||||
|
creation cannot fail. */
|
||||||
|
xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This first delay should just time out. */
|
||||||
|
xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
|
||||||
|
if( xReturn != 0x00 )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This second delay should be aborted by the primary task half way
|
||||||
|
through. */
|
||||||
|
xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
|
||||||
|
if( xReturn != 0x00 )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This third delay should just time out again. */
|
||||||
|
xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
|
||||||
|
if( xReturn != 0x00 )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
|
/* Not really necessary in this case, but for completeness. */
|
||||||
|
vEventGroupDelete( xEventGroup );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTestAbortingQueueSend( void )
|
||||||
|
{
|
||||||
|
TickType_t xTimeAtStart;
|
||||||
|
BaseType_t xReturn;
|
||||||
|
static StaticQueue_t xQueueBuffer;
|
||||||
|
static uint8_t ucQueueStorage[ sizeof( uint8_t ) ], ucItemToQueue;
|
||||||
|
const UBaseType_t xQueueLength = ( UBaseType_t ) 1;
|
||||||
|
QueueHandle_t xQueue;
|
||||||
|
|
||||||
|
/* Create the queue. Statically allocated memory is used so the
|
||||||
|
creation cannot fail. */
|
||||||
|
xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer );
|
||||||
|
|
||||||
|
/* This function tests aborting when in the blocked state waiting to send,
|
||||||
|
so the queue must be full. There is only one space in the queue. */
|
||||||
|
xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
|
||||||
|
if( xReturn != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This first delay should just time out. */
|
||||||
|
xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
|
||||||
|
if( xReturn != pdFALSE )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This second delay should be aborted by the primary task half way
|
||||||
|
through. */
|
||||||
|
xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
|
||||||
|
if( xReturn != pdFALSE )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This third delay should just time out again. */
|
||||||
|
xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
|
||||||
|
if( xReturn != pdFALSE )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
|
/* Not really necessary in this case, but for completeness. */
|
||||||
|
vQueueDelete( xQueue );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTestAbortingSemaphoreTake( void )
|
||||||
|
{
|
||||||
|
TickType_t xTimeAtStart;
|
||||||
|
BaseType_t xReturn;
|
||||||
|
static StaticSemaphore_t xSemaphoreBuffer;
|
||||||
|
SemaphoreHandle_t xSemaphore;
|
||||||
|
|
||||||
|
/* Create the semaphore. Statically allocated memory is used so the
|
||||||
|
creation cannot fail. */
|
||||||
|
xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This first delay should just time out. */
|
||||||
|
xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
|
||||||
|
if( xReturn != pdFALSE )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This second delay should be aborted by the primary task half way
|
||||||
|
through. */
|
||||||
|
xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
|
||||||
|
if( xReturn != pdFALSE )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This third delay should just time out again. */
|
||||||
|
xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
|
||||||
|
if( xReturn != pdFALSE )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
|
/* Not really necessary in this case, but for completeness. */
|
||||||
|
vSemaphoreDelete( xSemaphore );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTestAbortingTaskNotifyWait( void )
|
||||||
|
{
|
||||||
|
TickType_t xTimeAtStart;
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This first delay should just time out. */
|
||||||
|
xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
|
||||||
|
if( xReturn != pdFALSE )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This second delay should be aborted by the primary task half way
|
||||||
|
through. */
|
||||||
|
xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
|
||||||
|
if( xReturn != pdFALSE )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* This third delay should just time out again. */
|
||||||
|
xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
|
||||||
|
if( xReturn != pdFALSE )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )
|
||||||
|
{
|
||||||
|
TickType_t xTimeNow, xActualBlockTime;
|
||||||
|
|
||||||
|
xTimeNow = xTaskGetTickCount();
|
||||||
|
xActualBlockTime = xTimeNow - xStartTime;
|
||||||
|
|
||||||
|
/* The actual block time should not be less than the expected block time. */
|
||||||
|
if( xActualBlockTime < xExpectedBlockTime )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d, actual block time %d, expected %d", __LINE__, xActualBlockTime, xExpectedBlockTime );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The actual block time can be greater than the expected block time, as it
|
||||||
|
depends on the priority of the other tasks, but it should be within an
|
||||||
|
acceptable margin. */
|
||||||
|
if( xActualBlockTime > ( xExpectedBlockTime + xAllowableMargin ) )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE; printf( "Line %d", __LINE__ );taskDISABLE_INTERRUPTS();for(;;){Sleep( 1000 );}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xAreAbortDelayTestTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;
|
||||||
|
BaseType_t xReturn = pdPASS;
|
||||||
|
|
||||||
|
/* Have both tasks performed at least one cycle since this function was
|
||||||
|
last called? */
|
||||||
|
if( xControllingCycles == xLastControllingCycleCount )
|
||||||
|
{
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xBlockingCycles == xLastBlockingCycleCount )
|
||||||
|
{
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xErrorOccurred == pdTRUE )
|
||||||
|
{
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
xLastBlockingCycleCount = xBlockingCycles;
|
||||||
|
xLastControllingCycleCount = xControllingCycles;
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* INCLUDE_xTaskAbortDelay == 1 */
|
@ -1,336 +0,0 @@
|
|||||||
/*
|
|
||||||
FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
|
|
||||||
All rights reserved
|
|
||||||
|
|
||||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
|
||||||
|
|
||||||
This file is part of the FreeRTOS distribution.
|
|
||||||
|
|
||||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License (version 2) as published by the
|
|
||||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
|
||||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
|
||||||
>>! obliged to provide the source code for proprietary components !<<
|
|
||||||
>>! outside of the FreeRTOS kernel. !<<
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
|
||||||
link: http://www.freertos.org/a00114.html
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
* *
|
|
||||||
* FreeRTOS provides completely free yet professionally developed, *
|
|
||||||
* robust, strictly quality controlled, supported, and cross *
|
|
||||||
* platform software that is more than just the market leader, it *
|
|
||||||
* is the industry's de facto standard. *
|
|
||||||
* *
|
|
||||||
* Help yourself get started quickly while simultaneously helping *
|
|
||||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
|
||||||
* tutorial book, reference manual, or both: *
|
|
||||||
* http://www.FreeRTOS.org/Documentation *
|
|
||||||
* *
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
|
||||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
|
||||||
defined configASSERT()?
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
|
||||||
embedded software for free we request you assist our global community by
|
|
||||||
participating in the support forum.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
|
||||||
be as productive as possible as early as possible. Now you can receive
|
|
||||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
|
||||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
|
||||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
|
||||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
|
||||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
|
||||||
|
|
||||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
|
||||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
|
||||||
licenses offer ticketed support, indemnification and commercial middleware.
|
|
||||||
|
|
||||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
|
||||||
engineered and independently SIL3 certified version for use in safety and
|
|
||||||
mission critical applications that require provable dependability.
|
|
||||||
|
|
||||||
1 tab == 4 spaces!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is a version of BlockQ.c that uses the alternative (Alt) API.
|
|
||||||
*
|
|
||||||
* Creates six tasks that operate on three queues as follows:
|
|
||||||
*
|
|
||||||
* The first two tasks send and receive an incrementing number to/from a queue.
|
|
||||||
* One task acts as a producer and the other as the consumer. The consumer is a
|
|
||||||
* higher priority than the producer and is set to block on queue reads. The queue
|
|
||||||
* only has space for one item - as soon as the producer posts a message on the
|
|
||||||
* queue the consumer will unblock, pre-empt the producer, and remove the item.
|
|
||||||
*
|
|
||||||
* The second two tasks work the other way around. Again the queue used only has
|
|
||||||
* enough space for one item. This time the consumer has a lower priority than the
|
|
||||||
* producer. The producer will try to post on the queue blocking when the queue is
|
|
||||||
* full. When the consumer wakes it will remove the item from the queue, causing
|
|
||||||
* the producer to unblock, pre-empt the consumer, and immediately re-fill the
|
|
||||||
* queue.
|
|
||||||
*
|
|
||||||
* The last two tasks use the same queue producer and consumer functions. This time the queue has
|
|
||||||
* enough space for lots of items and the tasks operate at the same priority. The
|
|
||||||
* producer will execute, placing items into the queue. The consumer will start
|
|
||||||
* executing when either the queue becomes full (causing the producer to block) or
|
|
||||||
* a context switch occurs (tasks of the same priority will time slice).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/* Scheduler include files. */
|
|
||||||
#include "FreeRTOS.h"
|
|
||||||
#include "task.h"
|
|
||||||
#include "queue.h"
|
|
||||||
|
|
||||||
/* Demo program include files. */
|
|
||||||
#include "AltBlckQ.h"
|
|
||||||
|
|
||||||
#define blckqSTACK_SIZE configMINIMAL_STACK_SIZE
|
|
||||||
#define blckqNUM_TASK_SETS ( 3 )
|
|
||||||
|
|
||||||
/* Structure used to pass parameters to the blocking queue tasks. */
|
|
||||||
typedef struct BLOCKING_QUEUE_PARAMETERS
|
|
||||||
{
|
|
||||||
QueueHandle_t xQueue; /*< The queue to be used by the task. */
|
|
||||||
TickType_t xBlockTime; /*< The block time to use on queue reads/writes. */
|
|
||||||
volatile short *psCheckVariable; /*< Incremented on each successful cycle to check the task is still running. */
|
|
||||||
} xBlockingQueueParameters;
|
|
||||||
|
|
||||||
/* Task function that creates an incrementing number and posts it on a queue. */
|
|
||||||
static portTASK_FUNCTION_PROTO( vBlockingQueueProducer, pvParameters );
|
|
||||||
|
|
||||||
/* Task function that removes the incrementing number from a queue and checks that
|
|
||||||
it is the expected number. */
|
|
||||||
static portTASK_FUNCTION_PROTO( vBlockingQueueConsumer, pvParameters );
|
|
||||||
|
|
||||||
/* Variables which are incremented each time an item is removed from a queue, and
|
|
||||||
found to be the expected value.
|
|
||||||
These are used to check that the tasks are still running. */
|
|
||||||
static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 };
|
|
||||||
|
|
||||||
/* Variable which are incremented each time an item is posted on a queue. These
|
|
||||||
are used to check that the tasks are still running. */
|
|
||||||
static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 };
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
void vStartAltBlockingQueueTasks( UBaseType_t uxPriority )
|
|
||||||
{
|
|
||||||
xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2;
|
|
||||||
xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4;
|
|
||||||
xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6;
|
|
||||||
const UBaseType_t uxQueueSize1 = 1, uxQueueSize5 = 5;
|
|
||||||
const TickType_t xBlockTime = ( TickType_t ) 1000 / portTICK_PERIOD_MS;
|
|
||||||
const TickType_t xDontBlock = ( TickType_t ) 0;
|
|
||||||
|
|
||||||
/* Create the first two tasks as described at the top of the file. */
|
|
||||||
|
|
||||||
/* First create the structure used to pass parameters to the consumer tasks. */
|
|
||||||
pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
|
||||||
|
|
||||||
/* Create the queue used by the first two tasks to pass the incrementing number.
|
|
||||||
Pass a pointer to the queue in the parameter structure. */
|
|
||||||
pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) );
|
|
||||||
|
|
||||||
/* The consumer is created first so gets a block time as described above. */
|
|
||||||
pxQueueParameters1->xBlockTime = xBlockTime;
|
|
||||||
|
|
||||||
/* Pass in the variable that this task is going to increment so we can check it
|
|
||||||
is still running. */
|
|
||||||
pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] );
|
|
||||||
|
|
||||||
/* Create the structure used to pass parameters to the producer task. */
|
|
||||||
pxQueueParameters2 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
|
||||||
|
|
||||||
/* Pass the queue to this task also, using the parameter structure. */
|
|
||||||
pxQueueParameters2->xQueue = pxQueueParameters1->xQueue;
|
|
||||||
|
|
||||||
/* The producer is not going to block - as soon as it posts the consumer will
|
|
||||||
wake and remove the item so the producer should always have room to post. */
|
|
||||||
pxQueueParameters2->xBlockTime = xDontBlock;
|
|
||||||
|
|
||||||
/* Pass in the variable that this task is going to increment so we can check
|
|
||||||
it is still running. */
|
|
||||||
pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] );
|
|
||||||
|
|
||||||
|
|
||||||
/* Note the producer has a lower priority than the consumer when the tasks are
|
|
||||||
spawned. */
|
|
||||||
xTaskCreate( vBlockingQueueConsumer, "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL );
|
|
||||||
xTaskCreate( vBlockingQueueProducer, "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Create the second two tasks as described at the top of the file. This uses
|
|
||||||
the same mechanism but reverses the task priorities. */
|
|
||||||
|
|
||||||
pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
|
||||||
pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) );
|
|
||||||
pxQueueParameters3->xBlockTime = xDontBlock;
|
|
||||||
pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] );
|
|
||||||
|
|
||||||
pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
|
||||||
pxQueueParameters4->xQueue = pxQueueParameters3->xQueue;
|
|
||||||
pxQueueParameters4->xBlockTime = xBlockTime;
|
|
||||||
pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] );
|
|
||||||
|
|
||||||
xTaskCreate( vBlockingQueueConsumer, "QProdB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL );
|
|
||||||
xTaskCreate( vBlockingQueueProducer, "QConsB4", blckqSTACK_SIZE, ( void * ) pxQueueParameters4, uxPriority, NULL );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Create the last two tasks as described above. The mechanism is again just
|
|
||||||
the same. This time both parameter structures are given a block time. */
|
|
||||||
pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
|
||||||
pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( UBaseType_t ) sizeof( uint16_t ) );
|
|
||||||
pxQueueParameters5->xBlockTime = xBlockTime;
|
|
||||||
pxQueueParameters5->psCheckVariable = &( sBlockingProducerCount[ 2 ] );
|
|
||||||
|
|
||||||
pxQueueParameters6 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
|
||||||
pxQueueParameters6->xQueue = pxQueueParameters5->xQueue;
|
|
||||||
pxQueueParameters6->xBlockTime = xBlockTime;
|
|
||||||
pxQueueParameters6->psCheckVariable = &( sBlockingConsumerCount[ 2 ] );
|
|
||||||
|
|
||||||
xTaskCreate( vBlockingQueueProducer, "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL );
|
|
||||||
xTaskCreate( vBlockingQueueConsumer, "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL );
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
static portTASK_FUNCTION( vBlockingQueueProducer, pvParameters )
|
|
||||||
{
|
|
||||||
uint16_t usValue = 0;
|
|
||||||
xBlockingQueueParameters *pxQueueParameters;
|
|
||||||
short sErrorEverOccurred = pdFALSE;
|
|
||||||
|
|
||||||
#ifdef USE_STDIO
|
|
||||||
void vPrintDisplayMessage( const char * const * ppcMessageToSend );
|
|
||||||
|
|
||||||
const char * const pcTaskStartMsg = "Alt blocking queue producer task started.\r\n";
|
|
||||||
|
|
||||||
/* Queue a message for printing to say the task has started. */
|
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters;
|
|
||||||
|
|
||||||
for( ;; )
|
|
||||||
{
|
|
||||||
if( xQueueAltSendToBack( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS )
|
|
||||||
{
|
|
||||||
sErrorEverOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* We have successfully posted a message, so increment the variable
|
|
||||||
used to check we are still running. */
|
|
||||||
if( sErrorEverOccurred == pdFALSE )
|
|
||||||
{
|
|
||||||
( *pxQueueParameters->psCheckVariable )++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Increment the variable we are going to post next time round. The
|
|
||||||
consumer will expect the numbers to follow in numerical order. */
|
|
||||||
++usValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
static portTASK_FUNCTION( vBlockingQueueConsumer, pvParameters )
|
|
||||||
{
|
|
||||||
uint16_t usData, usExpectedValue = 0;
|
|
||||||
xBlockingQueueParameters *pxQueueParameters;
|
|
||||||
short sErrorEverOccurred = pdFALSE;
|
|
||||||
|
|
||||||
#ifdef USE_STDIO
|
|
||||||
void vPrintDisplayMessage( const char * const * ppcMessageToSend );
|
|
||||||
|
|
||||||
const char * const pcTaskStartMsg = "Alt blocking queue consumer task started.\r\n";
|
|
||||||
|
|
||||||
/* Queue a message for printing to say the task has started. */
|
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters;
|
|
||||||
|
|
||||||
for( ;; )
|
|
||||||
{
|
|
||||||
if( xQueueAltReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS )
|
|
||||||
{
|
|
||||||
if( usData != usExpectedValue )
|
|
||||||
{
|
|
||||||
/* Catch-up. */
|
|
||||||
usExpectedValue = usData;
|
|
||||||
|
|
||||||
sErrorEverOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* We have successfully received a message, so increment the
|
|
||||||
variable used to check we are still running. */
|
|
||||||
if( sErrorEverOccurred == pdFALSE )
|
|
||||||
{
|
|
||||||
( *pxQueueParameters->psCheckVariable )++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Increment the value we expect to remove from the queue next time
|
|
||||||
round. */
|
|
||||||
++usExpectedValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* This is called to check that all the created tasks are still running. */
|
|
||||||
BaseType_t xAreAltBlockingQueuesStillRunning( void )
|
|
||||||
{
|
|
||||||
static short sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 };
|
|
||||||
static short sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 };
|
|
||||||
BaseType_t xReturn = pdPASS, xTasks;
|
|
||||||
|
|
||||||
/* Not too worried about mutual exclusion on these variables as they are 16
|
|
||||||
bits and we are only reading them. We also only care to see if they have
|
|
||||||
changed or not.
|
|
||||||
|
|
||||||
Loop through each check variable to and return pdFALSE if any are found not
|
|
||||||
to have changed since the last call. */
|
|
||||||
|
|
||||||
for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ )
|
|
||||||
{
|
|
||||||
if( sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ] )
|
|
||||||
{
|
|
||||||
xReturn = pdFALSE;
|
|
||||||
}
|
|
||||||
sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ];
|
|
||||||
|
|
||||||
|
|
||||||
if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] )
|
|
||||||
{
|
|
||||||
xReturn = pdFALSE;
|
|
||||||
}
|
|
||||||
sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ];
|
|
||||||
}
|
|
||||||
|
|
||||||
return xReturn;
|
|
||||||
}
|
|
||||||
|
|
@ -1,553 +0,0 @@
|
|||||||
/*
|
|
||||||
FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
|
|
||||||
All rights reserved
|
|
||||||
|
|
||||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
|
||||||
|
|
||||||
This file is part of the FreeRTOS distribution.
|
|
||||||
|
|
||||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License (version 2) as published by the
|
|
||||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
|
||||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
|
||||||
>>! obliged to provide the source code for proprietary components !<<
|
|
||||||
>>! outside of the FreeRTOS kernel. !<<
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
|
||||||
link: http://www.freertos.org/a00114.html
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
* *
|
|
||||||
* FreeRTOS provides completely free yet professionally developed, *
|
|
||||||
* robust, strictly quality controlled, supported, and cross *
|
|
||||||
* platform software that is more than just the market leader, it *
|
|
||||||
* is the industry's de facto standard. *
|
|
||||||
* *
|
|
||||||
* Help yourself get started quickly while simultaneously helping *
|
|
||||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
|
||||||
* tutorial book, reference manual, or both: *
|
|
||||||
* http://www.FreeRTOS.org/Documentation *
|
|
||||||
* *
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
|
||||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
|
||||||
defined configASSERT()?
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
|
||||||
embedded software for free we request you assist our global community by
|
|
||||||
participating in the support forum.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
|
||||||
be as productive as possible as early as possible. Now you can receive
|
|
||||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
|
||||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
|
||||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
|
||||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
|
||||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
|
||||||
|
|
||||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
|
||||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
|
||||||
licenses offer ticketed support, indemnification and commercial middleware.
|
|
||||||
|
|
||||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
|
||||||
engineered and independently SIL3 certified version for use in safety and
|
|
||||||
mission critical applications that require provable dependability.
|
|
||||||
|
|
||||||
1 tab == 4 spaces!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is a version of BlockTim.c that uses the light weight API.
|
|
||||||
*
|
|
||||||
* This file contains some test scenarios that ensure tasks do not exit queue
|
|
||||||
* send or receive functions prematurely. A description of the tests is
|
|
||||||
* included within the code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Kernel includes. */
|
|
||||||
#include "FreeRTOS.h"
|
|
||||||
#include "task.h"
|
|
||||||
#include "queue.h"
|
|
||||||
|
|
||||||
/* Demo includes. */
|
|
||||||
#include "AltBlock.h"
|
|
||||||
|
|
||||||
/* Task priorities. */
|
|
||||||
#define bktPRIMARY_PRIORITY ( 3 )
|
|
||||||
#define bktSECONDARY_PRIORITY ( 2 )
|
|
||||||
|
|
||||||
/* Task behaviour. */
|
|
||||||
#define bktQUEUE_LENGTH ( 5 )
|
|
||||||
#define bktSHORT_WAIT ( ( ( TickType_t ) 20 ) / portTICK_PERIOD_MS )
|
|
||||||
#define bktPRIMARY_BLOCK_TIME ( 10 )
|
|
||||||
#define bktALLOWABLE_MARGIN ( 12 )
|
|
||||||
#define bktTIME_TO_BLOCK ( 175 )
|
|
||||||
#define bktDONT_BLOCK ( ( TickType_t ) 0 )
|
|
||||||
#define bktRUN_INDICATOR ( ( UBaseType_t ) 0x55 )
|
|
||||||
|
|
||||||
/* The queue on which the tasks block. */
|
|
||||||
static QueueHandle_t xTestQueue;
|
|
||||||
|
|
||||||
/* Handle to the secondary task is required by the primary task for calls
|
|
||||||
to vTaskSuspend/Resume(). */
|
|
||||||
static TaskHandle_t xSecondary;
|
|
||||||
|
|
||||||
/* Used to ensure that tasks are still executing without error. */
|
|
||||||
static BaseType_t xPrimaryCycles = 0, xSecondaryCycles = 0;
|
|
||||||
static BaseType_t xErrorOccurred = pdFALSE;
|
|
||||||
|
|
||||||
/* Provides a simple mechanism for the primary task to know when the
|
|
||||||
secondary task has executed. */
|
|
||||||
static volatile UBaseType_t xRunIndicator;
|
|
||||||
|
|
||||||
/* The two test tasks. Their behaviour is commented within the files. */
|
|
||||||
static void vPrimaryBlockTimeTestTask( void *pvParameters );
|
|
||||||
static void vSecondaryBlockTimeTestTask( void *pvParameters );
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
void vCreateAltBlockTimeTasks( void )
|
|
||||||
{
|
|
||||||
/* Create the queue on which the two tasks block. */
|
|
||||||
xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( BaseType_t ) );
|
|
||||||
|
|
||||||
/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
|
|
||||||
in use. The queue registry is provided as a means for kernel aware
|
|
||||||
debuggers to locate queues and has no purpose if a kernel aware debugger
|
|
||||||
is not being used. The call to vQueueAddToRegistry() will be removed
|
|
||||||
by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
|
||||||
defined to be less than 1. */
|
|
||||||
vQueueAddToRegistry( xTestQueue, "AltBlockQueue" );
|
|
||||||
|
|
||||||
|
|
||||||
/* Create the two test tasks. */
|
|
||||||
xTaskCreate( vPrimaryBlockTimeTestTask, "FBTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );
|
|
||||||
xTaskCreate( vSecondaryBlockTimeTestTask, "FBTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary );
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
static void vPrimaryBlockTimeTestTask( void *pvParameters )
|
|
||||||
{
|
|
||||||
BaseType_t xItem, xData;
|
|
||||||
TickType_t xTimeWhenBlocking;
|
|
||||||
TickType_t xTimeToBlock, xBlockedTime;
|
|
||||||
|
|
||||||
#ifdef USE_STDIO
|
|
||||||
void vPrintDisplayMessage( const char * const * ppcMessageToSend );
|
|
||||||
|
|
||||||
const char * const pcTaskStartMsg = "Alt primary block time test started.\r\n";
|
|
||||||
|
|
||||||
/* Queue a message for printing to say the task has started. */
|
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
( void ) pvParameters;
|
|
||||||
|
|
||||||
for( ;; )
|
|
||||||
{
|
|
||||||
/*********************************************************************
|
|
||||||
Test 1
|
|
||||||
|
|
||||||
Simple block time wakeup test on queue receives. */
|
|
||||||
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
|
||||||
{
|
|
||||||
/* The queue is empty. Attempt to read from the queue using a block
|
|
||||||
time. When we wake, ensure the delta in time is as expected. */
|
|
||||||
xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;
|
|
||||||
|
|
||||||
/* A critical section is used to minimise the jitter in the time
|
|
||||||
measurements. */
|
|
||||||
portENTER_CRITICAL();
|
|
||||||
{
|
|
||||||
xTimeWhenBlocking = xTaskGetTickCount();
|
|
||||||
|
|
||||||
/* We should unblock after xTimeToBlock having not received
|
|
||||||
anything on the queue. */
|
|
||||||
if( xQueueAltReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* How long were we blocked for? */
|
|
||||||
xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
|
|
||||||
}
|
|
||||||
portEXIT_CRITICAL();
|
|
||||||
|
|
||||||
if( xBlockedTime < xTimeToBlock )
|
|
||||||
{
|
|
||||||
/* Should not have blocked for less than we requested. */
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
|
|
||||||
{
|
|
||||||
/* Should not have blocked for longer than we requested,
|
|
||||||
although we would not necessarily run as soon as we were
|
|
||||||
unblocked so a margin is allowed. */
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
|
||||||
taskYIELD();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
Test 2
|
|
||||||
|
|
||||||
Simple block time wakeup test on queue sends.
|
|
||||||
|
|
||||||
First fill the queue. It should be empty so all sends should pass. */
|
|
||||||
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
|
||||||
{
|
|
||||||
if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
|
||||||
{
|
|
||||||
/* The queue is full. Attempt to write to the queue using a block
|
|
||||||
time. When we wake, ensure the delta in time is as expected. */
|
|
||||||
xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;
|
|
||||||
|
|
||||||
portENTER_CRITICAL();
|
|
||||||
{
|
|
||||||
xTimeWhenBlocking = xTaskGetTickCount();
|
|
||||||
|
|
||||||
/* We should unblock after xTimeToBlock having not received
|
|
||||||
anything on the queue. */
|
|
||||||
if( xQueueAltSendToBack( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* How long were we blocked for? */
|
|
||||||
xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
|
|
||||||
}
|
|
||||||
portEXIT_CRITICAL();
|
|
||||||
|
|
||||||
if( xBlockedTime < xTimeToBlock )
|
|
||||||
{
|
|
||||||
/* Should not have blocked for less than we requested. */
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
|
|
||||||
{
|
|
||||||
/* Should not have blocked for longer than we requested,
|
|
||||||
although we would not necessarily run as soon as we were
|
|
||||||
unblocked so a margin is allowed. */
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
|
||||||
taskYIELD();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
Test 3
|
|
||||||
|
|
||||||
Wake the other task, it will block attempting to post to the queue.
|
|
||||||
When we read from the queue the other task will wake, but before it
|
|
||||||
can run we will post to the queue again. When the other task runs it
|
|
||||||
will find the queue still full, even though it was woken. It should
|
|
||||||
recognise that its block time has not expired and return to block for
|
|
||||||
the remains of its block time.
|
|
||||||
|
|
||||||
Wake the other task so it blocks attempting to post to the already
|
|
||||||
full queue. */
|
|
||||||
xRunIndicator = 0;
|
|
||||||
vTaskResume( xSecondary );
|
|
||||||
|
|
||||||
/* We need to wait a little to ensure the other task executes. */
|
|
||||||
while( xRunIndicator != bktRUN_INDICATOR )
|
|
||||||
{
|
|
||||||
/* The other task has not yet executed. */
|
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
|
||||||
}
|
|
||||||
/* Make sure the other task is blocked on the queue. */
|
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
|
||||||
xRunIndicator = 0;
|
|
||||||
|
|
||||||
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
|
||||||
{
|
|
||||||
/* Now when we make space on the queue the other task should wake
|
|
||||||
but not execute as this task has higher priority. */
|
|
||||||
if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now fill the queue again before the other task gets a chance to
|
|
||||||
execute. If the other task had executed we would find the queue
|
|
||||||
full ourselves, and the other task have set xRunIndicator. */
|
|
||||||
if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xRunIndicator == bktRUN_INDICATOR )
|
|
||||||
{
|
|
||||||
/* The other task should not have executed. */
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Raise the priority of the other task so it executes and blocks
|
|
||||||
on the queue again. */
|
|
||||||
vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
|
|
||||||
|
|
||||||
/* The other task should now have re-blocked without exiting the
|
|
||||||
queue function. */
|
|
||||||
if( xRunIndicator == bktRUN_INDICATOR )
|
|
||||||
{
|
|
||||||
/* The other task should not have executed outside of the
|
|
||||||
queue function. */
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the priority back down. */
|
|
||||||
vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Let the other task timeout. When it unblockes it will check that it
|
|
||||||
unblocked at the correct time, then suspend itself. */
|
|
||||||
while( xRunIndicator != bktRUN_INDICATOR )
|
|
||||||
{
|
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
|
||||||
}
|
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
|
||||||
xRunIndicator = 0;
|
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
|
||||||
taskYIELD();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
Test 4
|
|
||||||
|
|
||||||
As per test 3 - but with the send and receive the other way around.
|
|
||||||
The other task blocks attempting to read from the queue.
|
|
||||||
|
|
||||||
Empty the queue. We should find that it is full. */
|
|
||||||
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
|
||||||
{
|
|
||||||
if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wake the other task so it blocks attempting to read from the
|
|
||||||
already empty queue. */
|
|
||||||
vTaskResume( xSecondary );
|
|
||||||
|
|
||||||
/* We need to wait a little to ensure the other task executes. */
|
|
||||||
while( xRunIndicator != bktRUN_INDICATOR )
|
|
||||||
{
|
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
|
||||||
}
|
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
|
||||||
xRunIndicator = 0;
|
|
||||||
|
|
||||||
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
|
||||||
{
|
|
||||||
/* Now when we place an item on the queue the other task should
|
|
||||||
wake but not execute as this task has higher priority. */
|
|
||||||
if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now empty the queue again before the other task gets a chance to
|
|
||||||
execute. If the other task had executed we would find the queue
|
|
||||||
empty ourselves, and the other task would be suspended. */
|
|
||||||
if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xRunIndicator == bktRUN_INDICATOR )
|
|
||||||
{
|
|
||||||
/* The other task should not have executed. */
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Raise the priority of the other task so it executes and blocks
|
|
||||||
on the queue again. */
|
|
||||||
vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
|
|
||||||
|
|
||||||
/* The other task should now have re-blocked without exiting the
|
|
||||||
queue function. */
|
|
||||||
if( xRunIndicator == bktRUN_INDICATOR )
|
|
||||||
{
|
|
||||||
/* The other task should not have executed outside of the
|
|
||||||
queue function. */
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Let the other task timeout. When it unblockes it will check that it
|
|
||||||
unblocked at the correct time, then suspend itself. */
|
|
||||||
while( xRunIndicator != bktRUN_INDICATOR )
|
|
||||||
{
|
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
|
||||||
}
|
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
|
||||||
|
|
||||||
xPrimaryCycles++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
static void vSecondaryBlockTimeTestTask( void *pvParameters )
|
|
||||||
{
|
|
||||||
TickType_t xTimeWhenBlocking, xBlockedTime;
|
|
||||||
BaseType_t xData;
|
|
||||||
|
|
||||||
#ifdef USE_STDIO
|
|
||||||
void vPrintDisplayMessage( const char * const * ppcMessageToSend );
|
|
||||||
|
|
||||||
const char * const pcTaskStartMsg = "Alt secondary block time test started.\r\n";
|
|
||||||
|
|
||||||
/* Queue a message for printing to say the task has started. */
|
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
( void ) pvParameters;
|
|
||||||
|
|
||||||
for( ;; )
|
|
||||||
{
|
|
||||||
/*********************************************************************
|
|
||||||
Test 1 and 2
|
|
||||||
|
|
||||||
This task does does not participate in these tests. */
|
|
||||||
vTaskSuspend( NULL );
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
Test 3
|
|
||||||
|
|
||||||
The first thing we do is attempt to read from the queue. It should be
|
|
||||||
full so we block. Note the time before we block so we can check the
|
|
||||||
wake time is as per that expected. */
|
|
||||||
portENTER_CRITICAL();
|
|
||||||
{
|
|
||||||
xTimeWhenBlocking = xTaskGetTickCount();
|
|
||||||
|
|
||||||
/* We should unblock after bktTIME_TO_BLOCK having not received
|
|
||||||
anything on the queue. */
|
|
||||||
xData = 0;
|
|
||||||
xRunIndicator = bktRUN_INDICATOR;
|
|
||||||
if( xQueueAltSendToBack( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* How long were we inside the send function? */
|
|
||||||
xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
|
|
||||||
}
|
|
||||||
portEXIT_CRITICAL();
|
|
||||||
|
|
||||||
/* We should not have blocked for less time than bktTIME_TO_BLOCK. */
|
|
||||||
if( xBlockedTime < bktTIME_TO_BLOCK )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We should of not blocked for much longer than bktALLOWABLE_MARGIN
|
|
||||||
either. A margin is permitted as we would not necessarily run as
|
|
||||||
soon as we unblocked. */
|
|
||||||
if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Suspend ready for test 3. */
|
|
||||||
xRunIndicator = bktRUN_INDICATOR;
|
|
||||||
vTaskSuspend( NULL );
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
Test 4
|
|
||||||
|
|
||||||
As per test three, but with the send and receive reversed. */
|
|
||||||
portENTER_CRITICAL();
|
|
||||||
{
|
|
||||||
xTimeWhenBlocking = xTaskGetTickCount();
|
|
||||||
|
|
||||||
/* We should unblock after bktTIME_TO_BLOCK having not received
|
|
||||||
anything on the queue. */
|
|
||||||
xRunIndicator = bktRUN_INDICATOR;
|
|
||||||
if( xQueueAltReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
|
|
||||||
}
|
|
||||||
portEXIT_CRITICAL();
|
|
||||||
|
|
||||||
/* We should not have blocked for less time than bktTIME_TO_BLOCK. */
|
|
||||||
if( xBlockedTime < bktTIME_TO_BLOCK )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We should of not blocked for much longer than bktALLOWABLE_MARGIN
|
|
||||||
either. A margin is permitted as we would not necessarily run as soon
|
|
||||||
as we unblocked. */
|
|
||||||
if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
|
|
||||||
{
|
|
||||||
xErrorOccurred = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
xRunIndicator = bktRUN_INDICATOR;
|
|
||||||
|
|
||||||
xSecondaryCycles++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
BaseType_t xAreAltBlockTimeTestTasksStillRunning( void )
|
|
||||||
{
|
|
||||||
static BaseType_t xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;
|
|
||||||
BaseType_t xReturn = pdPASS;
|
|
||||||
|
|
||||||
/* Have both tasks performed at least one cycle since this function was
|
|
||||||
last called? */
|
|
||||||
if( xPrimaryCycles == xLastPrimaryCycleCount )
|
|
||||||
{
|
|
||||||
xReturn = pdFAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xSecondaryCycles == xLastSecondaryCycleCount )
|
|
||||||
{
|
|
||||||
xReturn = pdFAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xErrorOccurred == pdTRUE )
|
|
||||||
{
|
|
||||||
xReturn = pdFAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
xLastSecondaryCycleCount = xSecondaryCycles;
|
|
||||||
xLastPrimaryCycleCount = xPrimaryCycles;
|
|
||||||
|
|
||||||
return xReturn;
|
|
||||||
}
|
|
@ -1,279 +0,0 @@
|
|||||||
/*
|
|
||||||
FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
|
|
||||||
All rights reserved
|
|
||||||
|
|
||||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
|
||||||
|
|
||||||
This file is part of the FreeRTOS distribution.
|
|
||||||
|
|
||||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License (version 2) as published by the
|
|
||||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
|
||||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
|
||||||
>>! obliged to provide the source code for proprietary components !<<
|
|
||||||
>>! outside of the FreeRTOS kernel. !<<
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
|
||||||
link: http://www.freertos.org/a00114.html
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
* *
|
|
||||||
* FreeRTOS provides completely free yet professionally developed, *
|
|
||||||
* robust, strictly quality controlled, supported, and cross *
|
|
||||||
* platform software that is more than just the market leader, it *
|
|
||||||
* is the industry's de facto standard. *
|
|
||||||
* *
|
|
||||||
* Help yourself get started quickly while simultaneously helping *
|
|
||||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
|
||||||
* tutorial book, reference manual, or both: *
|
|
||||||
* http://www.FreeRTOS.org/Documentation *
|
|
||||||
* *
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
|
||||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
|
||||||
defined configASSERT()?
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
|
||||||
embedded software for free we request you assist our global community by
|
|
||||||
participating in the support forum.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
|
||||||
be as productive as possible as early as possible. Now you can receive
|
|
||||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
|
||||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
|
||||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
|
||||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
|
||||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
|
||||||
|
|
||||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
|
||||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
|
||||||
licenses offer ticketed support, indemnification and commercial middleware.
|
|
||||||
|
|
||||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
|
||||||
engineered and independently SIL3 certified version for use in safety and
|
|
||||||
mission critical applications that require provable dependability.
|
|
||||||
|
|
||||||
1 tab == 4 spaces!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is a version of PollQ.c that uses the alternative (Alt) API.
|
|
||||||
*
|
|
||||||
* Creates two tasks that communicate over a single queue. One task acts as a
|
|
||||||
* producer, the other a consumer.
|
|
||||||
*
|
|
||||||
* The producer loops for three iteration, posting an incrementing number onto the
|
|
||||||
* queue each cycle. It then delays for a fixed period before doing exactly the
|
|
||||||
* same again.
|
|
||||||
*
|
|
||||||
* The consumer loops emptying the queue. Each item removed from the queue is
|
|
||||||
* checked to ensure it contains the expected value. When the queue is empty it
|
|
||||||
* blocks for a fixed period, then does the same again.
|
|
||||||
*
|
|
||||||
* All queue access is performed without blocking. The consumer completely empties
|
|
||||||
* the queue each time it runs so the producer should never find the queue full.
|
|
||||||
*
|
|
||||||
* An error is flagged if the consumer obtains an unexpected value or the producer
|
|
||||||
* find the queue is full.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Changes from V2.0.0
|
|
||||||
|
|
||||||
+ Delay periods are now specified using variables and constants of
|
|
||||||
TickType_t rather than uint32_t.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/* Scheduler include files. */
|
|
||||||
#include "FreeRTOS.h"
|
|
||||||
#include "task.h"
|
|
||||||
#include "queue.h"
|
|
||||||
|
|
||||||
/* Demo program include files. */
|
|
||||||
#include "AltPollQ.h"
|
|
||||||
|
|
||||||
#define pollqSTACK_SIZE configMINIMAL_STACK_SIZE
|
|
||||||
#define pollqQUEUE_SIZE ( 10 )
|
|
||||||
#define pollqPRODUCER_DELAY ( ( TickType_t ) 200 / portTICK_PERIOD_MS )
|
|
||||||
#define pollqCONSUMER_DELAY ( pollqPRODUCER_DELAY - ( TickType_t ) ( 20 / portTICK_PERIOD_MS ) )
|
|
||||||
#define pollqNO_DELAY ( ( TickType_t ) 0 )
|
|
||||||
#define pollqVALUES_TO_PRODUCE ( ( BaseType_t ) 3 )
|
|
||||||
#define pollqINITIAL_VALUE ( ( BaseType_t ) 0 )
|
|
||||||
|
|
||||||
/* The task that posts the incrementing number onto the queue. */
|
|
||||||
static portTASK_FUNCTION_PROTO( vPolledQueueProducer, pvParameters );
|
|
||||||
|
|
||||||
/* The task that empties the queue. */
|
|
||||||
static portTASK_FUNCTION_PROTO( vPolledQueueConsumer, pvParameters );
|
|
||||||
|
|
||||||
/* Variables that are used to check that the tasks are still running with no
|
|
||||||
errors. */
|
|
||||||
static volatile BaseType_t xPollingConsumerCount = pollqINITIAL_VALUE, xPollingProducerCount = pollqINITIAL_VALUE;
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
void vStartAltPolledQueueTasks( UBaseType_t uxPriority )
|
|
||||||
{
|
|
||||||
static QueueHandle_t xPolledQueue;
|
|
||||||
|
|
||||||
/* Create the queue used by the producer and consumer. */
|
|
||||||
xPolledQueue = xQueueCreate( pollqQUEUE_SIZE, ( UBaseType_t ) sizeof( uint16_t ) );
|
|
||||||
|
|
||||||
/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
|
|
||||||
in use. The queue registry is provided as a means for kernel aware
|
|
||||||
debuggers to locate queues and has no purpose if a kernel aware debugger
|
|
||||||
is not being used. The call to vQueueAddToRegistry() will be removed
|
|
||||||
by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
|
||||||
defined to be less than 1. */
|
|
||||||
vQueueAddToRegistry( xPolledQueue, "AltPollQueue" );
|
|
||||||
|
|
||||||
|
|
||||||
/* Spawn the producer and consumer. */
|
|
||||||
xTaskCreate( vPolledQueueConsumer, "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( TaskHandle_t * ) NULL );
|
|
||||||
xTaskCreate( vPolledQueueProducer, "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( TaskHandle_t * ) NULL );
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
static portTASK_FUNCTION( vPolledQueueProducer, pvParameters )
|
|
||||||
{
|
|
||||||
uint16_t usValue = ( uint16_t ) 0;
|
|
||||||
BaseType_t xError = pdFALSE, xLoop;
|
|
||||||
|
|
||||||
#ifdef USE_STDIO
|
|
||||||
void vPrintDisplayMessage( const char * const * ppcMessageToSend );
|
|
||||||
|
|
||||||
const char * const pcTaskStartMsg = "Alt polling queue producer task started.\r\n";
|
|
||||||
|
|
||||||
/* Queue a message for printing to say the task has started. */
|
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for( ;; )
|
|
||||||
{
|
|
||||||
for( xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++ )
|
|
||||||
{
|
|
||||||
/* Send an incrementing number on the queue without blocking. */
|
|
||||||
if( xQueueAltSendToBack( *( ( QueueHandle_t * ) pvParameters ), ( void * ) &usValue, pollqNO_DELAY ) != pdPASS )
|
|
||||||
{
|
|
||||||
/* We should never find the queue full so if we get here there
|
|
||||||
has been an error. */
|
|
||||||
xError = pdTRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( xError == pdFALSE )
|
|
||||||
{
|
|
||||||
/* If an error has ever been recorded we stop incrementing the
|
|
||||||
check variable. */
|
|
||||||
portENTER_CRITICAL();
|
|
||||||
xPollingProducerCount++;
|
|
||||||
portEXIT_CRITICAL();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the value we are going to post next time around. */
|
|
||||||
usValue++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait before we start posting again to ensure the consumer runs and
|
|
||||||
empties the queue. */
|
|
||||||
vTaskDelay( pollqPRODUCER_DELAY );
|
|
||||||
}
|
|
||||||
} /*lint !e818 Function prototype must conform to API. */
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
static portTASK_FUNCTION( vPolledQueueConsumer, pvParameters )
|
|
||||||
{
|
|
||||||
uint16_t usData, usExpectedValue = ( uint16_t ) 0;
|
|
||||||
BaseType_t xError = pdFALSE;
|
|
||||||
|
|
||||||
#ifdef USE_STDIO
|
|
||||||
void vPrintDisplayMessage( const char * const * ppcMessageToSend );
|
|
||||||
|
|
||||||
const char * const pcTaskStartMsg = "Alt blocking queue consumer task started.\r\n";
|
|
||||||
|
|
||||||
/* Queue a message for printing to say the task has started. */
|
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for( ;; )
|
|
||||||
{
|
|
||||||
/* Loop until the queue is empty. */
|
|
||||||
while( uxQueueMessagesWaiting( *( ( QueueHandle_t * ) pvParameters ) ) )
|
|
||||||
{
|
|
||||||
if( xQueueAltReceive( *( ( QueueHandle_t * ) pvParameters ), &usData, pollqNO_DELAY ) == pdPASS )
|
|
||||||
{
|
|
||||||
if( usData != usExpectedValue )
|
|
||||||
{
|
|
||||||
/* This is not what we expected to receive so an error has
|
|
||||||
occurred. */
|
|
||||||
xError = pdTRUE;
|
|
||||||
|
|
||||||
/* Catch-up to the value we received so our next expected
|
|
||||||
value should again be correct. */
|
|
||||||
usExpectedValue = usData;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( xError == pdFALSE )
|
|
||||||
{
|
|
||||||
/* Only increment the check variable if no errors have
|
|
||||||
occurred. */
|
|
||||||
portENTER_CRITICAL();
|
|
||||||
xPollingConsumerCount++;
|
|
||||||
portEXIT_CRITICAL();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Next time round we would expect the number to be one higher. */
|
|
||||||
usExpectedValue++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now the queue is empty we block, allowing the producer to place more
|
|
||||||
items in the queue. */
|
|
||||||
vTaskDelay( pollqCONSUMER_DELAY );
|
|
||||||
}
|
|
||||||
} /*lint !e818 Function prototype must conform to API. */
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* This is called to check that all the created tasks are still running with no errors. */
|
|
||||||
BaseType_t xAreAltPollingQueuesStillRunning( void )
|
|
||||||
{
|
|
||||||
BaseType_t xReturn;
|
|
||||||
|
|
||||||
/* Check both the consumer and producer poll count to check they have both
|
|
||||||
been changed since out last trip round. We do not need a critical section
|
|
||||||
around the check variables as this is called from a higher priority than
|
|
||||||
the other tasks that access the same variables. */
|
|
||||||
if( ( xPollingConsumerCount == pollqINITIAL_VALUE ) ||
|
|
||||||
( xPollingProducerCount == pollqINITIAL_VALUE )
|
|
||||||
)
|
|
||||||
{
|
|
||||||
xReturn = pdFALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xReturn = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the check variables back down so we know if they have been
|
|
||||||
incremented the next time around. */
|
|
||||||
xPollingConsumerCount = pollqINITIAL_VALUE;
|
|
||||||
xPollingProducerCount = pollqINITIAL_VALUE;
|
|
||||||
|
|
||||||
return xReturn;
|
|
||||||
}
|
|
@ -1,591 +0,0 @@
|
|||||||
/*
|
|
||||||
FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
|
|
||||||
All rights reserved
|
|
||||||
|
|
||||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
|
||||||
|
|
||||||
This file is part of the FreeRTOS distribution.
|
|
||||||
|
|
||||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License (version 2) as published by the
|
|
||||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
|
||||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
|
||||||
>>! obliged to provide the source code for proprietary components !<<
|
|
||||||
>>! outside of the FreeRTOS kernel. !<<
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
|
||||||
link: http://www.freertos.org/a00114.html
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
* *
|
|
||||||
* FreeRTOS provides completely free yet professionally developed, *
|
|
||||||
* robust, strictly quality controlled, supported, and cross *
|
|
||||||
* platform software that is more than just the market leader, it *
|
|
||||||
* is the industry's de facto standard. *
|
|
||||||
* *
|
|
||||||
* Help yourself get started quickly while simultaneously helping *
|
|
||||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
|
||||||
* tutorial book, reference manual, or both: *
|
|
||||||
* http://www.FreeRTOS.org/Documentation *
|
|
||||||
* *
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
|
||||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
|
||||||
defined configASSERT()?
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
|
||||||
embedded software for free we request you assist our global community by
|
|
||||||
participating in the support forum.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
|
||||||
be as productive as possible as early as possible. Now you can receive
|
|
||||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
|
||||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
|
||||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
|
||||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
|
||||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
|
||||||
|
|
||||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
|
||||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
|
||||||
licenses offer ticketed support, indemnification and commercial middleware.
|
|
||||||
|
|
||||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
|
||||||
engineered and independently SIL3 certified version for use in safety and
|
|
||||||
mission critical applications that require provable dependability.
|
|
||||||
|
|
||||||
1 tab == 4 spaces!
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file implements the same demo and test as GenQTest.c, but uses the
|
|
||||||
* light weight API in place of the fully featured API.
|
|
||||||
*
|
|
||||||
* See the comments at the top of GenQTest.c for a description.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/* Scheduler include files. */
|
|
||||||
#include "FreeRTOS.h"
|
|
||||||
#include "task.h"
|
|
||||||
#include "queue.h"
|
|
||||||
#include "semphr.h"
|
|
||||||
|
|
||||||
/* Demo program include files. */
|
|
||||||
#include "AltQTest.h"
|
|
||||||
|
|
||||||
#define genqQUEUE_LENGTH ( 5 )
|
|
||||||
#define genqNO_BLOCK ( 0 )
|
|
||||||
|
|
||||||
#define genqMUTEX_LOW_PRIORITY ( tskIDLE_PRIORITY )
|
|
||||||
#define genqMUTEX_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
|
||||||
#define genqMUTEX_MEDIUM_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
|
||||||
#define genqMUTEX_HIGH_PRIORITY ( tskIDLE_PRIORITY + 3 )
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tests the behaviour of the xQueueAltSendToFront() and xQueueAltSendToBack()
|
|
||||||
* macros by using both to fill a queue, then reading from the queue to
|
|
||||||
* check the resultant queue order is as expected. Queue data is also
|
|
||||||
* peeked.
|
|
||||||
*/
|
|
||||||
static void prvSendFrontAndBackTest( void *pvParameters );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following three tasks are used to demonstrate the mutex behaviour.
|
|
||||||
* Each task is given a different priority to demonstrate the priority
|
|
||||||
* inheritance mechanism.
|
|
||||||
*
|
|
||||||
* The low priority task obtains a mutex. After this a high priority task
|
|
||||||
* attempts to obtain the same mutex, causing its priority to be inherited
|
|
||||||
* by the low priority task. The task with the inherited high priority then
|
|
||||||
* resumes a medium priority task to ensure it is not blocked by the medium
|
|
||||||
* priority task while it holds the inherited high priority. Once the mutex
|
|
||||||
* is returned the task with the inherited priority returns to its original
|
|
||||||
* low priority, and is therefore immediately preempted by first the high
|
|
||||||
* priority task and then the medium prioroity task before it can continue.
|
|
||||||
*/
|
|
||||||
static void prvLowPriorityMutexTask( void *pvParameters );
|
|
||||||
static void prvMediumPriorityMutexTask( void *pvParameters );
|
|
||||||
static void prvHighPriorityMutexTask( void *pvParameters );
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
|
||||||
detected in any of the tasks. */
|
|
||||||
static BaseType_t xErrorDetected = pdFALSE;
|
|
||||||
|
|
||||||
/* Counters that are incremented on each cycle of a test. This is used to
|
|
||||||
detect a stalled task - a test that is no longer running. */
|
|
||||||
static volatile uint32_t ulLoopCounter = 0;
|
|
||||||
static volatile uint32_t ulLoopCounter2 = 0;
|
|
||||||
|
|
||||||
/* The variable that is guarded by the mutex in the mutex demo tasks. */
|
|
||||||
static volatile uint32_t ulGuardedVariable = 0;
|
|
||||||
|
|
||||||
/* Handles used in the mutext test to suspend and resume the high and medium
|
|
||||||
priority mutex test tasks. */
|
|
||||||
static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask;
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
void vStartAltGenericQueueTasks( UBaseType_t uxPriority )
|
|
||||||
{
|
|
||||||
QueueHandle_t xQueue;
|
|
||||||
SemaphoreHandle_t xMutex;
|
|
||||||
|
|
||||||
/* Create the queue that we are going to use for the
|
|
||||||
prvSendFrontAndBackTest demo. */
|
|
||||||
xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( uint32_t ) );
|
|
||||||
|
|
||||||
/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
|
|
||||||
in use. The queue registry is provided as a means for kernel aware
|
|
||||||
debuggers to locate queues and has no purpose if a kernel aware debugger
|
|
||||||
is not being used. The call to vQueueAddToRegistry() will be removed
|
|
||||||
by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
|
||||||
defined to be less than 1. */
|
|
||||||
vQueueAddToRegistry( xQueue, "Alt_Gen_Test_Queue" );
|
|
||||||
|
|
||||||
/* Create the demo task and pass it the queue just created. We are
|
|
||||||
passing the queue handle by value so it does not matter that it is
|
|
||||||
declared on the stack here. */
|
|
||||||
xTaskCreate( prvSendFrontAndBackTest, "FGenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL );
|
|
||||||
|
|
||||||
/* Create the mutex used by the prvMutexTest task. */
|
|
||||||
xMutex = xSemaphoreCreateMutex();
|
|
||||||
|
|
||||||
/* vQueueAddToRegistry() adds the mutex to the registry, if one is
|
|
||||||
in use. The registry is provided as a means for kernel aware
|
|
||||||
debuggers to locate mutex and has no purpose if a kernel aware debugger
|
|
||||||
is not being used. The call to vQueueAddToRegistry() will be removed
|
|
||||||
by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
|
||||||
defined to be less than 1. */
|
|
||||||
vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Alt_Q_Mutex" );
|
|
||||||
|
|
||||||
/* Create the mutex demo tasks and pass it the mutex just created. We are
|
|
||||||
passing the mutex handle by value so it does not matter that it is declared
|
|
||||||
on the stack here. */
|
|
||||||
xTaskCreate( prvLowPriorityMutexTask, "FMuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );
|
|
||||||
xTaskCreate( prvMediumPriorityMutexTask, "FMuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );
|
|
||||||
xTaskCreate( prvHighPriorityMutexTask, "FMuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
static void prvSendFrontAndBackTest( void *pvParameters )
|
|
||||||
{
|
|
||||||
uint32_t ulData, ulData2;
|
|
||||||
QueueHandle_t xQueue;
|
|
||||||
|
|
||||||
#ifdef USE_STDIO
|
|
||||||
void vPrintDisplayMessage( const char * const * ppcMessageToSend );
|
|
||||||
|
|
||||||
const char * const pcTaskStartMsg = "Alt queue SendToFront/SendToBack/Peek test started.\r\n";
|
|
||||||
|
|
||||||
/* Queue a message for printing to say the task has started. */
|
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
xQueue = ( QueueHandle_t ) pvParameters;
|
|
||||||
|
|
||||||
for( ;; )
|
|
||||||
{
|
|
||||||
/* The queue is empty, so sending an item to the back of the queue
|
|
||||||
should have the same efect as sending it to the front of the queue.
|
|
||||||
|
|
||||||
First send to the front and check everything is as expected. */
|
|
||||||
xQueueAltSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );
|
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 1 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xQueueAltReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The data we sent to the queue should equal the data we just received
|
|
||||||
from the queue. */
|
|
||||||
if( ulLoopCounter != ulData )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Then do the same, sending the data to the back, checking everything
|
|
||||||
is as expected. */
|
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 0 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
xQueueAltSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );
|
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 1 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xQueueAltReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 0 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The data we sent to the queue should equal the data we just received
|
|
||||||
from the queue. */
|
|
||||||
if( ulLoopCounter != ulData )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
|
||||||
taskYIELD();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Place 2, 3, 4 into the queue, adding items to the back of the queue. */
|
|
||||||
for( ulData = 2; ulData < 5; ulData++ )
|
|
||||||
{
|
|
||||||
xQueueAltSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now the order in the queue should be 2, 3, 4, with 2 being the first
|
|
||||||
thing to be read out. Now add 1 then 0 to the front of the queue. */
|
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 3 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
ulData = 1;
|
|
||||||
xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );
|
|
||||||
ulData = 0;
|
|
||||||
xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );
|
|
||||||
|
|
||||||
/* Now the queue should be full, and when we read the data out we
|
|
||||||
should receive 0, 1, 2, 3, 4. */
|
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 5 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xQueueAltSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
|
||||||
taskYIELD();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check the data we read out is in the expected order. */
|
|
||||||
for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ )
|
|
||||||
{
|
|
||||||
/* Try peeking the data first. */
|
|
||||||
if( xQueueAltPeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ulData != ulData2 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Now try receiving the data for real. The value should be the
|
|
||||||
same. Clobber the value first so we know we really received it. */
|
|
||||||
ulData2 = ~ulData2;
|
|
||||||
if( xQueueAltReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ulData != ulData2 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The queue should now be empty again. */
|
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 0 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
|
||||||
taskYIELD();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Our queue is empty once more, add 10, 11 to the back. */
|
|
||||||
ulData = 10;
|
|
||||||
if( xQueueAltSendToBack( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
ulData = 11;
|
|
||||||
if( xQueueAltSendToBack( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 2 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now we should have 10, 11 in the queue. Add 7, 8, 9 to the
|
|
||||||
front. */
|
|
||||||
for( ulData = 9; ulData >= 7; ulData-- )
|
|
||||||
{
|
|
||||||
if( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now check that the queue is full, and that receiving data provides
|
|
||||||
the expected sequence of 7, 8, 9, 10, 11. */
|
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 5 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( xQueueAltSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
|
||||||
taskYIELD();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check the data we read out is in the expected order. */
|
|
||||||
for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ )
|
|
||||||
{
|
|
||||||
if( xQueueAltReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ulData != ulData2 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 0 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulLoopCounter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
static void prvLowPriorityMutexTask( void *pvParameters )
|
|
||||||
{
|
|
||||||
SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters;
|
|
||||||
|
|
||||||
#ifdef USE_STDIO
|
|
||||||
void vPrintDisplayMessage( const char * const * ppcMessageToSend );
|
|
||||||
|
|
||||||
const char * const pcTaskStartMsg = "Fast mutex with priority inheritance test started.\r\n";
|
|
||||||
|
|
||||||
/* Queue a message for printing to say the task has started. */
|
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
( void ) pvParameters;
|
|
||||||
|
|
||||||
|
|
||||||
for( ;; )
|
|
||||||
{
|
|
||||||
/* Take the mutex. It should be available now. */
|
|
||||||
if( xSemaphoreAltTake( xMutex, genqNO_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set our guarded variable to a known start value. */
|
|
||||||
ulGuardedVariable = 0;
|
|
||||||
|
|
||||||
/* Our priority should be as per that assigned when the task was
|
|
||||||
created. */
|
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now unsuspend the high priority task. This will attempt to take the
|
|
||||||
mutex, and block when it finds it cannot obtain it. */
|
|
||||||
vTaskResume( xHighPriorityMutexTask );
|
|
||||||
|
|
||||||
/* We should now have inherited the prioritoy of the high priority task,
|
|
||||||
as by now it will have attempted to get the mutex. */
|
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We can attempt to set our priority to the test priority - between the
|
|
||||||
idle priority and the medium/high test priorities, but our actual
|
|
||||||
prioroity should remain at the high priority. */
|
|
||||||
vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );
|
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now unsuspend the medium priority task. This should not run as our
|
|
||||||
inherited priority is above that of the medium priority task. */
|
|
||||||
vTaskResume( xMediumPriorityMutexTask );
|
|
||||||
|
|
||||||
/* If the did run then it will have incremented our guarded variable. */
|
|
||||||
if( ulGuardedVariable != 0 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When we give back the semaphore our priority should be disinherited
|
|
||||||
back to the priority to which we attempted to set ourselves. This means
|
|
||||||
that when the high priority task next blocks, the medium priority task
|
|
||||||
should execute and increment the guarded variable. When we next run
|
|
||||||
both the high and medium priority tasks will have been suspended again. */
|
|
||||||
if( xSemaphoreAltGive( xMutex ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that the guarded variable did indeed increment... */
|
|
||||||
if( ulGuardedVariable != 1 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ... and that our priority has been disinherited to
|
|
||||||
genqMUTEX_TEST_PRIORITY. */
|
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set our priority back to our original priority ready for the next
|
|
||||||
loop around this test. */
|
|
||||||
vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );
|
|
||||||
|
|
||||||
/* Just to show we are still running. */
|
|
||||||
ulLoopCounter2++;
|
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
|
||||||
taskYIELD();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
static void prvMediumPriorityMutexTask( void *pvParameters )
|
|
||||||
{
|
|
||||||
( void ) pvParameters;
|
|
||||||
|
|
||||||
for( ;; )
|
|
||||||
{
|
|
||||||
/* The medium priority task starts by suspending itself. The low
|
|
||||||
priority task will unsuspend this task when required. */
|
|
||||||
vTaskSuspend( NULL );
|
|
||||||
|
|
||||||
/* When this task unsuspends all it does is increment the guarded
|
|
||||||
variable, this is so the low priority task knows that it has
|
|
||||||
executed. */
|
|
||||||
ulGuardedVariable++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
static void prvHighPriorityMutexTask( void *pvParameters )
|
|
||||||
{
|
|
||||||
SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters;
|
|
||||||
|
|
||||||
( void ) pvParameters;
|
|
||||||
|
|
||||||
for( ;; )
|
|
||||||
{
|
|
||||||
/* The high priority task starts by suspending itself. The low
|
|
||||||
priority task will unsuspend this task when required. */
|
|
||||||
vTaskSuspend( NULL );
|
|
||||||
|
|
||||||
/* When this task unsuspends all it does is attempt to obtain
|
|
||||||
the mutex. It should find the mutex is not available so a
|
|
||||||
block time is specified. */
|
|
||||||
if( xSemaphoreAltTake( xMutex, portMAX_DELAY ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When we eventually obtain the mutex we just give it back then
|
|
||||||
return to suspend ready for the next test. */
|
|
||||||
if( xSemaphoreAltGive( xMutex ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* This is called to check that all the created tasks are still running. */
|
|
||||||
BaseType_t xAreAltGenericQueueTasksStillRunning( void )
|
|
||||||
{
|
|
||||||
static uint32_t ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;
|
|
||||||
|
|
||||||
/* If the demo task is still running then we expect the loopcounters to
|
|
||||||
have incremented since this function was last called. */
|
|
||||||
if( ulLastLoopCounter == ulLoopCounter )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ulLastLoopCounter2 == ulLoopCounter2 )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulLastLoopCounter = ulLoopCounter;
|
|
||||||
ulLastLoopCounter2 = ulLoopCounter2;
|
|
||||||
|
|
||||||
/* Errors detected in the task itself will have latched xErrorDetected
|
|
||||||
to true. */
|
|
||||||
|
|
||||||
return !xErrorDetected;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
|||||||
|
This directory contains the implementation of the "common demo tasks". These
|
||||||
|
are test tasks and demo tasks that are used by nearly all the demo applications.
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
|
|
||||||
All rights reserved
|
|
||||||
|
|
||||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
|
||||||
|
|
||||||
This file is part of the FreeRTOS distribution.
|
|
||||||
|
|
||||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License (version 2) as published by the
|
|
||||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
|
||||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
|
||||||
>>! obliged to provide the source code for proprietary components !<<
|
|
||||||
>>! outside of the FreeRTOS kernel. !<<
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
|
||||||
link: http://www.freertos.org/a00114.html
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
* *
|
|
||||||
* FreeRTOS provides completely free yet professionally developed, *
|
|
||||||
* robust, strictly quality controlled, supported, and cross *
|
|
||||||
* platform software that is more than just the market leader, it *
|
|
||||||
* is the industry's de facto standard. *
|
|
||||||
* *
|
|
||||||
* Help yourself get started quickly while simultaneously helping *
|
|
||||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
|
||||||
* tutorial book, reference manual, or both: *
|
|
||||||
* http://www.FreeRTOS.org/Documentation *
|
|
||||||
* *
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
|
||||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
|
||||||
defined configASSERT()?
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
|
||||||
embedded software for free we request you assist our global community by
|
|
||||||
participating in the support forum.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
|
||||||
be as productive as possible as early as possible. Now you can receive
|
|
||||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
|
||||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
|
||||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
|
||||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
|
||||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
|
||||||
|
|
||||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
|
||||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
|
||||||
licenses offer ticketed support, indemnification and commercial middleware.
|
|
||||||
|
|
||||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
|
||||||
engineered and independently SIL3 certified version for use in safety and
|
|
||||||
mission critical applications that require provable dependability.
|
|
||||||
|
|
||||||
1 tab == 4 spaces!
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ALT_BLOCK_Q_H
|
|
||||||
#define ALT_BLOCK_Q_H
|
|
||||||
|
|
||||||
void vStartAltBlockingQueueTasks( UBaseType_t uxPriority );
|
|
||||||
BaseType_t xAreAltBlockingQueuesStillRunning( void );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
|
|
||||||
All rights reserved
|
|
||||||
|
|
||||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
|
||||||
|
|
||||||
This file is part of the FreeRTOS distribution.
|
|
||||||
|
|
||||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License (version 2) as published by the
|
|
||||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
|
||||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
|
||||||
>>! obliged to provide the source code for proprietary components !<<
|
|
||||||
>>! outside of the FreeRTOS kernel. !<<
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
|
||||||
link: http://www.freertos.org/a00114.html
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
* *
|
|
||||||
* FreeRTOS provides completely free yet professionally developed, *
|
|
||||||
* robust, strictly quality controlled, supported, and cross *
|
|
||||||
* platform software that is more than just the market leader, it *
|
|
||||||
* is the industry's de facto standard. *
|
|
||||||
* *
|
|
||||||
* Help yourself get started quickly while simultaneously helping *
|
|
||||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
|
||||||
* tutorial book, reference manual, or both: *
|
|
||||||
* http://www.FreeRTOS.org/Documentation *
|
|
||||||
* *
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
|
||||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
|
||||||
defined configASSERT()?
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
|
||||||
embedded software for free we request you assist our global community by
|
|
||||||
participating in the support forum.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
|
||||||
be as productive as possible as early as possible. Now you can receive
|
|
||||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
|
||||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
|
||||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
|
||||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
|
||||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
|
||||||
|
|
||||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
|
||||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
|
||||||
licenses offer ticketed support, indemnification and commercial middleware.
|
|
||||||
|
|
||||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
|
||||||
engineered and independently SIL3 certified version for use in safety and
|
|
||||||
mission critical applications that require provable dependability.
|
|
||||||
|
|
||||||
1 tab == 4 spaces!
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FAST_BLOCK_TIME_TEST_H
|
|
||||||
#define FAST_BLOCK_TIME_TEST_H
|
|
||||||
|
|
||||||
void vCreateAltBlockTimeTasks( void );
|
|
||||||
BaseType_t xAreAltBlockTimeTestTasksStillRunning( void );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
|
|
||||||
All rights reserved
|
|
||||||
|
|
||||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
|
||||||
|
|
||||||
This file is part of the FreeRTOS distribution.
|
|
||||||
|
|
||||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License (version 2) as published by the
|
|
||||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
|
||||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
|
||||||
>>! obliged to provide the source code for proprietary components !<<
|
|
||||||
>>! outside of the FreeRTOS kernel. !<<
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
|
||||||
link: http://www.freertos.org/a00114.html
|
|
||||||
|
|
||||||
***************************************************************************
|
|
||||||
* *
|
|
||||||
* FreeRTOS provides completely free yet professionally developed, *
|
|
||||||
* robust, strictly quality controlled, supported, and cross *
|
|
||||||
* platform software that is more than just the market leader, it *
|
|
||||||
* is the industry's de facto standard. *
|
|
||||||
* *
|
|
||||||
* Help yourself get started quickly while simultaneously helping *
|
|
||||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
|
||||||
* tutorial book, reference manual, or both: *
|
|
||||||
* http://www.FreeRTOS.org/Documentation *
|
|
||||||
* *
|
|
||||||
***************************************************************************
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
|
||||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
|
||||||
defined configASSERT()?
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
|
||||||
embedded software for free we request you assist our global community by
|
|
||||||
participating in the support forum.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
|
||||||
be as productive as possible as early as possible. Now you can receive
|
|
||||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
|
||||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
|
||||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
|
||||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
|
||||||
|
|
||||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
|
||||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
|
||||||
|
|
||||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
|
||||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
|
||||||
licenses offer ticketed support, indemnification and commercial middleware.
|
|
||||||
|
|
||||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
|
||||||
engineered and independently SIL3 certified version for use in safety and
|
|
||||||
mission critical applications that require provable dependability.
|
|
||||||
|
|
||||||
1 tab == 4 spaces!
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FAST_GEN_Q_TEST_H
|
|
||||||
#define FAST_GEN_Q_TEST_H
|
|
||||||
|
|
||||||
void vStartAltGenericQueueTasks( UBaseType_t uxPriority );
|
|
||||||
BaseType_t xAreAltGenericQueueTasksStillRunning( void );
|
|
||||||
|
|
||||||
#endif /* GEN_Q_TEST_H */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue