mirror of
https://github.com/drasko/open-ameba.git
synced 2025-07-31 12:31:04 +00:00
update
This commit is contained in:
parent
0cf6a74c39
commit
020aedc9bb
114 changed files with 28699 additions and 2408 deletions
|
|
@ -978,7 +978,7 @@
|
||||||
<buildTargets>
|
<buildTargets>
|
||||||
<target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
<target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
<buildCommand>mingw32-make.exe</buildCommand>
|
<buildCommand>mingw32-make.exe</buildCommand>
|
||||||
<buildArguments>-s -j</buildArguments>
|
<buildArguments>-s -j 4</buildArguments>
|
||||||
<buildTarget>all</buildTarget>
|
<buildTarget>all</buildTarget>
|
||||||
<stopOnError>true</stopOnError>
|
<stopOnError>true</stopOnError>
|
||||||
<useDefaultCommand>false</useDefaultCommand>
|
<useDefaultCommand>false</useDefaultCommand>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-897121475649177215" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cross ARM" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-899746928891724671" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cross ARM" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||||
</provider>
|
</provider>
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-897121475649177215" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cross ARM" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-899746928891724671" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cross ARM" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||||
</provider>
|
</provider>
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-950027335418731358" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cross ARM" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-952652788661278814" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cross ARM" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||||
</provider>
|
</provider>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,346 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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).
|
||||||
|
*
|
||||||
|
* \page BlockQC blockQ.c
|
||||||
|
* \ingroup DemoFiles
|
||||||
|
* <HR>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V1.00:
|
||||||
|
|
||||||
|
+ Reversed the priority and block times of the second two demo tasks so
|
||||||
|
they operate as per the description above.
|
||||||
|
|
||||||
|
Changes from V2.0.0
|
||||||
|
|
||||||
|
+ Delay periods are now specified using variables and constants of
|
||||||
|
TickType_t rather than unsigned long.
|
||||||
|
|
||||||
|
Changes from V4.0.2
|
||||||
|
|
||||||
|
+ The second set of tasks were created the wrong way around. This has been
|
||||||
|
corrected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "BlockQ.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
#define blckqSTACK_SIZE ( ( unsigned short ) 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 void vBlockingQueueProducer( void *pvParameters );
|
||||||
|
|
||||||
|
/* Task function that removes the incrementing number from a queue and checks that
|
||||||
|
it is the expected number. */
|
||||||
|
static void vBlockingQueueConsumer( void *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 ] = { ( short ) 0, ( short ) 0, ( short ) 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 ] = { ( short ) 0, ( short ) 0, ( short ) 0 };
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartBlockingQueueTasks( unsigned portBASE_TYPE uxPriority )
|
||||||
|
{
|
||||||
|
xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2;
|
||||||
|
xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4;
|
||||||
|
xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6;
|
||||||
|
const unsigned portBASE_TYPE 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, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );
|
||||||
|
|
||||||
|
/* 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, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );
|
||||||
|
pxQueueParameters3->xBlockTime = xDontBlock;
|
||||||
|
pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] );
|
||||||
|
|
||||||
|
pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
||||||
|
pxQueueParameters4->xQueue = pxQueueParameters3->xQueue;
|
||||||
|
pxQueueParameters4->xBlockTime = xBlockTime;
|
||||||
|
pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] );
|
||||||
|
|
||||||
|
xTaskCreate( vBlockingQueueProducer, "QProdB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL );
|
||||||
|
xTaskCreate( vBlockingQueueConsumer, "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, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );
|
||||||
|
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 void vBlockingQueueProducer( void *pvParameters )
|
||||||
|
{
|
||||||
|
unsigned short usValue = 0;
|
||||||
|
xBlockingQueueParameters *pxQueueParameters;
|
||||||
|
const char * const pcTaskStartMsg = "Blocking queue producer started.\r\n";
|
||||||
|
const char * const pcTaskErrorMsg = "Could not post on blocking queue\r\n";
|
||||||
|
short sErrorEverOccurred = pdFALSE;
|
||||||
|
|
||||||
|
pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
if( xQueueSendToBack( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcTaskErrorMsg );
|
||||||
|
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 void vBlockingQueueConsumer( void *pvParameters )
|
||||||
|
{
|
||||||
|
unsigned short usData, usExpectedValue = 0;
|
||||||
|
xBlockingQueueParameters *pxQueueParameters;
|
||||||
|
const char * const pcTaskStartMsg = "Blocking queue consumer started.\r\n";
|
||||||
|
const char * const pcTaskErrorMsg = "Incorrect value received on blocking queue.\r\n";
|
||||||
|
short sErrorEverOccurred = pdFALSE;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
if( xQueueReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS )
|
||||||
|
{
|
||||||
|
if( usData != usExpectedValue )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcTaskErrorMsg );
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
portBASE_TYPE xAreBlockingQueuesStillRunning( void )
|
||||||
|
{
|
||||||
|
static short sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 };
|
||||||
|
static short sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 };
|
||||||
|
portBASE_TYPE 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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,258 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 very simple queue test. See the BlockQ. c documentation for a more
|
||||||
|
* comprehensive version.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* \page PollQC pollQ.c
|
||||||
|
* \ingroup DemoFiles
|
||||||
|
* <HR>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V2.0.0
|
||||||
|
|
||||||
|
+ Delay periods are now specified using variables and constants of
|
||||||
|
TickType_t rather than unsigned long.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "queue.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "PollQ.h"
|
||||||
|
|
||||||
|
#define pollqSTACK_SIZE ( ( unsigned short ) configMINIMAL_STACK_SIZE )
|
||||||
|
|
||||||
|
/* The task that posts the incrementing number onto the queue. */
|
||||||
|
static void vPolledQueueProducer( void *pvParameters );
|
||||||
|
|
||||||
|
/* The task that empties the queue. */
|
||||||
|
static void vPolledQueueConsumer( void *pvParameters );
|
||||||
|
|
||||||
|
/* Variables that are used to check that the tasks are still running with no errors. */
|
||||||
|
static volatile short sPollingConsumerCount = 0, sPollingProducerCount = 0;
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartPolledQueueTasks( unsigned portBASE_TYPE uxPriority )
|
||||||
|
{
|
||||||
|
static QueueHandle_t xPolledQueue;
|
||||||
|
const unsigned portBASE_TYPE uxQueueSize = 10;
|
||||||
|
|
||||||
|
/* Create the queue used by the producer and consumer. */
|
||||||
|
xPolledQueue = xQueueCreate( uxQueueSize, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );
|
||||||
|
|
||||||
|
/* Spawn the producer and consumer. */
|
||||||
|
xTaskCreate( vPolledQueueConsumer, "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, NULL );
|
||||||
|
xTaskCreate( vPolledQueueProducer, "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vPolledQueueProducer( void *pvParameters )
|
||||||
|
{
|
||||||
|
unsigned short usValue = 0, usLoop;
|
||||||
|
QueueHandle_t *pxQueue;
|
||||||
|
const TickType_t xDelay = ( TickType_t ) 200 / portTICK_PERIOD_MS;
|
||||||
|
const unsigned short usNumToProduce = 3;
|
||||||
|
const char * const pcTaskStartMsg = "Polled queue producer started.\r\n";
|
||||||
|
const char * const pcTaskErrorMsg = "Could not post on polled queue.\r\n";
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
/* The queue being used is passed in as the parameter. */
|
||||||
|
pxQueue = ( QueueHandle_t * ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
for( usLoop = 0; usLoop < usNumToProduce; ++usLoop )
|
||||||
|
{
|
||||||
|
/* Send an incrementing number on the queue without blocking. */
|
||||||
|
if( xQueueSendToBack( *pxQueue, ( void * ) &usValue, ( TickType_t ) 0 ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* We should never find the queue full - this is an error. */
|
||||||
|
vPrintDisplayMessage( &pcTaskErrorMsg );
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If an error has ever been recorded we stop incrementing the
|
||||||
|
check variable. */
|
||||||
|
++sPollingProducerCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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( xDelay );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vPolledQueueConsumer( void *pvParameters )
|
||||||
|
{
|
||||||
|
unsigned short usData, usExpectedValue = 0;
|
||||||
|
QueueHandle_t *pxQueue;
|
||||||
|
const TickType_t xDelay = ( TickType_t ) 200 / portTICK_PERIOD_MS;
|
||||||
|
const char * const pcTaskStartMsg = "Polled queue consumer started.\r\n";
|
||||||
|
const char * const pcTaskErrorMsg = "Incorrect value received on polled queue.\r\n";
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
/* The queue being used is passed in as the parameter. */
|
||||||
|
pxQueue = ( QueueHandle_t * ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Loop until the queue is empty. */
|
||||||
|
while( uxQueueMessagesWaiting( *pxQueue ) )
|
||||||
|
{
|
||||||
|
if( xQueueReceive( *pxQueue, &usData, ( TickType_t ) 0 ) == pdPASS )
|
||||||
|
{
|
||||||
|
if( usData != usExpectedValue )
|
||||||
|
{
|
||||||
|
/* This is not what we expected to receive so an error has
|
||||||
|
occurred. */
|
||||||
|
vPrintDisplayMessage( &pcTaskErrorMsg );
|
||||||
|
sError = pdTRUE;
|
||||||
|
/* Catch-up to the value we received so our next expected value
|
||||||
|
should again be correct. */
|
||||||
|
usExpectedValue = usData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* Only increment the check variable if no errors have
|
||||||
|
occurred. */
|
||||||
|
++sPollingConsumerCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++usExpectedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now the queue is empty we block, allowing the producer to place more
|
||||||
|
items in the queue. */
|
||||||
|
vTaskDelay( xDelay );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running with no errors. */
|
||||||
|
portBASE_TYPE xArePollingQueuesStillRunning( void )
|
||||||
|
{
|
||||||
|
static short sLastPollingConsumerCount = 0, sLastPollingProducerCount = 0;
|
||||||
|
portBASE_TYPE xReturn;
|
||||||
|
|
||||||
|
if( ( sLastPollingConsumerCount == sPollingConsumerCount ) ||
|
||||||
|
( sLastPollingProducerCount == sPollingProducerCount )
|
||||||
|
)
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sLastPollingConsumerCount = sPollingConsumerCount;
|
||||||
|
sLastPollingProducerCount = sPollingProducerCount;
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,384 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates two tasks that operate on an interrupt driven serial port. A loopback
|
||||||
|
* connector should be used so that everything that is transmitted is also received.
|
||||||
|
* The serial port does not use any flow control. On a standard 9way 'D' connector
|
||||||
|
* pins two and three should be connected together.
|
||||||
|
*
|
||||||
|
* The first task repeatedly sends a string to a queue, character at a time. The
|
||||||
|
* serial port interrupt will empty the queue and transmit the characters. The
|
||||||
|
* task blocks for a pseudo random period before resending the string.
|
||||||
|
*
|
||||||
|
* The second task blocks on a queue waiting for a character to be received.
|
||||||
|
* Characters received by the serial port interrupt routine are posted onto the
|
||||||
|
* queue - unblocking the task making it ready to execute. If this is then the
|
||||||
|
* highest priority task ready to run it will run immediately - with a context
|
||||||
|
* switch occurring at the end of the interrupt service routine. The task
|
||||||
|
* receiving characters is spawned with a higher priority than the task
|
||||||
|
* transmitting the characters.
|
||||||
|
*
|
||||||
|
* With the loop back connector in place, one task will transmit a string and the
|
||||||
|
* other will immediately receive it. The receiving task knows the string it
|
||||||
|
* expects to receive so can detect an error.
|
||||||
|
*
|
||||||
|
* This also creates a third task. This is used to test semaphore usage from an
|
||||||
|
* ISR and does nothing interesting.
|
||||||
|
*
|
||||||
|
* \page ComTestC comtest.c
|
||||||
|
* \ingroup DemoFiles
|
||||||
|
* <HR>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V1.00:
|
||||||
|
|
||||||
|
+ The priority of the Rx task has been lowered. Received characters are
|
||||||
|
now processed (read from the queue) at the idle priority, allowing low
|
||||||
|
priority tasks to run evenly at times of a high communications overhead.
|
||||||
|
|
||||||
|
Changes from V1.01:
|
||||||
|
|
||||||
|
+ The Tx task now waits a pseudo random time between transissions.
|
||||||
|
Previously a fixed period was used but this was not such a good test as
|
||||||
|
interrupts fired at regular intervals.
|
||||||
|
|
||||||
|
Changes From V1.2.0:
|
||||||
|
|
||||||
|
+ Use vSerialPutString() instead of single character puts.
|
||||||
|
+ Only stop the check variable incrementing after two consecutive errors.
|
||||||
|
|
||||||
|
Changed from V1.2.5
|
||||||
|
|
||||||
|
+ Made the Rx task 2 priorities higher than the Tx task. Previously it was
|
||||||
|
only 1. This is done to tie in better with the other demo application
|
||||||
|
tasks.
|
||||||
|
|
||||||
|
Changes from V2.0.0
|
||||||
|
|
||||||
|
+ Delay periods are now specified using variables and constants of
|
||||||
|
TickType_t rather than unsigned long.
|
||||||
|
+ Slight modification to task priorities.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "serial.h"
|
||||||
|
#include "comtest.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
/* The Tx task will transmit the sequence of characters at a pseudo random
|
||||||
|
interval. This is the maximum and minimum block time between sends. */
|
||||||
|
#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x15e )
|
||||||
|
#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0xc8 )
|
||||||
|
|
||||||
|
#define comMAX_CONSECUTIVE_ERRORS ( 2 )
|
||||||
|
|
||||||
|
#define comSTACK_SIZE ( ( unsigned short ) 256 )
|
||||||
|
|
||||||
|
#define comRX_RELATIVE_PRIORITY ( 1 )
|
||||||
|
|
||||||
|
/* Handle to the com port used by both tasks. */
|
||||||
|
static xComPortHandle xPort;
|
||||||
|
|
||||||
|
/* The transmit function as described at the top of the file. */
|
||||||
|
static void vComTxTask( void *pvParameters );
|
||||||
|
|
||||||
|
/* The receive function as described at the top of the file. */
|
||||||
|
static void vComRxTask( void *pvParameters );
|
||||||
|
|
||||||
|
/* The semaphore test function as described at the top of the file. */
|
||||||
|
static void vSemTestTask( void * pvParameters );
|
||||||
|
|
||||||
|
/* The string that is repeatedly transmitted. */
|
||||||
|
const char * const pcMessageToExchange = "Send this message over and over again to check communications interrupts. "
|
||||||
|
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
|
||||||
|
|
||||||
|
/* Variables that are incremented on each cycle of each task. These are used to
|
||||||
|
check that both tasks are still executing. */
|
||||||
|
volatile short sTxCount = 0, sRxCount = 0, sSemCount = 0;
|
||||||
|
|
||||||
|
/* The handle to the semaphore test task. */
|
||||||
|
static TaskHandle_t xSemTestTaskHandle = NULL;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartComTestTasks( unsigned portBASE_TYPE uxPriority, eCOMPort ePort, eBaud eBaudRate )
|
||||||
|
{
|
||||||
|
const unsigned portBASE_TYPE uxBufferLength = 255;
|
||||||
|
|
||||||
|
/* Initialise the com port then spawn both tasks. */
|
||||||
|
xPort = xSerialPortInit( ePort, eBaudRate, serNO_PARITY, serBITS_8, serSTOP_1, uxBufferLength );
|
||||||
|
xTaskCreate( vComTxTask, "COMTx", comSTACK_SIZE, NULL, uxPriority, NULL );
|
||||||
|
xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority + comRX_RELATIVE_PRIORITY, NULL );
|
||||||
|
xTaskCreate( vSemTestTask, "ISRSem", comSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xSemTestTaskHandle );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vComTxTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
const char * const pcTaskStartMsg = "COM Tx task started.\r\n";
|
||||||
|
TickType_t xTimeToWait;
|
||||||
|
|
||||||
|
/* Stop warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Send the string to the serial port. */
|
||||||
|
vSerialPutString( xPort, pcMessageToExchange, strlen( pcMessageToExchange ) );
|
||||||
|
|
||||||
|
/* We have posted all the characters in the string - increment the variable
|
||||||
|
used to check that this task is still running, then wait before re-sending
|
||||||
|
the string. */
|
||||||
|
sTxCount++;
|
||||||
|
|
||||||
|
xTimeToWait = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* Make sure we don't wait too long... */
|
||||||
|
xTimeToWait %= comTX_MAX_BLOCK_TIME;
|
||||||
|
|
||||||
|
/* ...but we do want to wait. */
|
||||||
|
if( xTimeToWait < comTX_MIN_BLOCK_TIME )
|
||||||
|
{
|
||||||
|
xTimeToWait = comTX_MIN_BLOCK_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelay( xTimeToWait );
|
||||||
|
}
|
||||||
|
} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vComRxTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
const char * const pcTaskStartMsg = "COM Rx task started.\r\n";
|
||||||
|
const char * const pcTaskErrorMsg = "COM read error\r\n";
|
||||||
|
const char * const pcTaskRestartMsg = "COM resynced\r\n";
|
||||||
|
const char * const pcTaskTimeoutMsg = "COM Rx timed out\r\n";
|
||||||
|
const TickType_t xBlockTime = ( TickType_t ) 0xffff / portTICK_PERIOD_MS;
|
||||||
|
const char *pcExpectedChar;
|
||||||
|
portBASE_TYPE xGotChar;
|
||||||
|
char cRxedChar;
|
||||||
|
short sResyncRequired, sConsecutiveErrors, sLatchedError;
|
||||||
|
|
||||||
|
/* Stop warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
/* The first expected character is the first character in the string. */
|
||||||
|
pcExpectedChar = pcMessageToExchange;
|
||||||
|
sResyncRequired = pdFALSE;
|
||||||
|
sConsecutiveErrors = 0;
|
||||||
|
sLatchedError = pdFALSE;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Receive a message from the com port interrupt routine. If a message is
|
||||||
|
not yet available the call will block the task. */
|
||||||
|
xGotChar = xSerialGetChar( xPort, &cRxedChar, xBlockTime );
|
||||||
|
if( xGotChar == pdTRUE )
|
||||||
|
{
|
||||||
|
if( sResyncRequired == pdTRUE )
|
||||||
|
{
|
||||||
|
/* We got out of sequence and are waiting for the start of the next
|
||||||
|
transmission of the string. */
|
||||||
|
if( cRxedChar == '\n' )
|
||||||
|
{
|
||||||
|
/* This is the end of the message so we can start again - with
|
||||||
|
the first character in the string being the next thing we expect
|
||||||
|
to receive. */
|
||||||
|
pcExpectedChar = pcMessageToExchange;
|
||||||
|
sResyncRequired = pdFALSE;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say that we are going to try
|
||||||
|
again. */
|
||||||
|
vPrintDisplayMessage( &pcTaskRestartMsg );
|
||||||
|
|
||||||
|
/* Stop incrementing the check variable, if consecutive errors occur. */
|
||||||
|
sConsecutiveErrors++;
|
||||||
|
if( sConsecutiveErrors >= comMAX_CONSECUTIVE_ERRORS )
|
||||||
|
{
|
||||||
|
sLatchedError = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We have received a character, but is it the expected character? */
|
||||||
|
if( cRxedChar != *pcExpectedChar )
|
||||||
|
{
|
||||||
|
/* This was not the expected character so post a message for
|
||||||
|
printing to say that an error has occurred. We will then wait
|
||||||
|
to resynchronise. */
|
||||||
|
vPrintDisplayMessage( &pcTaskErrorMsg );
|
||||||
|
sResyncRequired = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This was the expected character so next time we will expect
|
||||||
|
the next character in the string. Wrap back to the beginning
|
||||||
|
of the string when the null terminator has been reached. */
|
||||||
|
pcExpectedChar++;
|
||||||
|
if( *pcExpectedChar == '\0' )
|
||||||
|
{
|
||||||
|
pcExpectedChar = pcMessageToExchange;
|
||||||
|
|
||||||
|
/* We have got through the entire string without error. */
|
||||||
|
sConsecutiveErrors = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increment the count that is used to check that this task is still
|
||||||
|
running. This is only done if an error has never occurred. */
|
||||||
|
if( sLatchedError == pdFALSE )
|
||||||
|
{
|
||||||
|
sRxCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcTaskTimeoutMsg );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vSemTestTask( void * pvParameters )
|
||||||
|
{
|
||||||
|
const char * const pcTaskStartMsg = "ISR Semaphore test started.\r\n";
|
||||||
|
portBASE_TYPE xError = pdFALSE;
|
||||||
|
|
||||||
|
/* Stop warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
if( xSerialWaitForSemaphore( xPort ) )
|
||||||
|
{
|
||||||
|
if( xError == pdFALSE )
|
||||||
|
{
|
||||||
|
sSemCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xError = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /*lint !e715 !e830 !e818 pvParameters not used but function prototype must be standard for task function. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running. */
|
||||||
|
portBASE_TYPE xAreComTestTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
static short sLastTxCount = 0, sLastRxCount = 0, sLastSemCount = 0;
|
||||||
|
portBASE_TYPE xReturn;
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
|
||||||
|
if( ( sTxCount == sLastTxCount ) || ( sRxCount == sLastRxCount ) || ( sSemCount == sLastSemCount ) )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sLastTxCount = sTxCount;
|
||||||
|
sLastRxCount = sRxCount;
|
||||||
|
sLastSemCount = sSemCount;
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vComTestUnsuspendTask( void )
|
||||||
|
{
|
||||||
|
/* The task that is suspended on the semaphore will be referenced from the
|
||||||
|
Suspended list as it is blocking indefinitely. This call just checks that
|
||||||
|
the kernel correctly detects this and does not attempt to unsuspend the
|
||||||
|
task. */
|
||||||
|
xTaskResumeFromISR( xSemTestTaskHandle );
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,241 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a single persistent task which periodically dynamically creates another
|
||||||
|
* four tasks. The original task is called the creator task, the four tasks it
|
||||||
|
* creates are called suicidal tasks.
|
||||||
|
*
|
||||||
|
* Two of the created suicidal tasks kill one other suicidal task before killing
|
||||||
|
* themselves - leaving just the original task remaining.
|
||||||
|
*
|
||||||
|
* The creator task must be spawned after all of the other demo application tasks
|
||||||
|
* as it keeps a check on the number of tasks under the scheduler control. The
|
||||||
|
* number of tasks it expects to see running should never be greater than the
|
||||||
|
* number of tasks that were in existence when the creator task was spawned, plus
|
||||||
|
* one set of four suicidal tasks. If this number is exceeded an error is flagged.
|
||||||
|
*
|
||||||
|
* \page DeathC death.c
|
||||||
|
* \ingroup DemoFiles
|
||||||
|
* <HR>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V2.0.0
|
||||||
|
|
||||||
|
+ Delay periods are now specified using variables and constants of
|
||||||
|
TickType_t rather than unsigned long.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "death.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
#define deathSTACK_SIZE ( ( unsigned short ) 512 )
|
||||||
|
|
||||||
|
/* The task originally created which is responsible for periodically dynamically
|
||||||
|
creating another four tasks. */
|
||||||
|
static void vCreateTasks( void *pvParameters );
|
||||||
|
|
||||||
|
/* The task function of the dynamically created tasks. */
|
||||||
|
static void vSuicidalTask( void *pvParameters );
|
||||||
|
|
||||||
|
/* A variable which is incremented every time the dynamic tasks are created. This
|
||||||
|
is used to check that the task is still running. */
|
||||||
|
static volatile short sCreationCount = 0;
|
||||||
|
|
||||||
|
/* Used to store the number of tasks that were originally running so the creator
|
||||||
|
task can tell if any of the suicidal tasks have failed to die. */
|
||||||
|
static volatile unsigned portBASE_TYPE uxTasksRunningAtStart = 0;
|
||||||
|
static const unsigned portBASE_TYPE uxMaxNumberOfExtraTasksRunning = 5;
|
||||||
|
|
||||||
|
/* Used to store a handle to the tasks that should be killed by a suicidal task,
|
||||||
|
before it kills itself. */
|
||||||
|
TaskHandle_t xCreatedTask1, xCreatedTask2;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority )
|
||||||
|
{
|
||||||
|
unsigned portBASE_TYPE *puxPriority;
|
||||||
|
|
||||||
|
/* Create the Creator tasks - passing in as a parameter the priority at which
|
||||||
|
the suicidal tasks should be created. */
|
||||||
|
puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) );
|
||||||
|
*puxPriority = uxPriority;
|
||||||
|
|
||||||
|
xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL );
|
||||||
|
|
||||||
|
/* Record the number of tasks that are running now so we know if any of the
|
||||||
|
suicidal tasks have failed to be killed. */
|
||||||
|
uxTasksRunningAtStart = uxTaskGetNumberOfTasks();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vSuicidalTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
portDOUBLE d1, d2;
|
||||||
|
TaskHandle_t xTaskToKill;
|
||||||
|
const TickType_t xDelay = ( TickType_t ) 500 / portTICK_PERIOD_MS;
|
||||||
|
|
||||||
|
if( pvParameters != NULL )
|
||||||
|
{
|
||||||
|
/* This task is periodically created four times. Tow created tasks are
|
||||||
|
passed a handle to the other task so it can kill it before killing itself.
|
||||||
|
The other task is passed in null. */
|
||||||
|
xTaskToKill = *( TaskHandle_t* )pvParameters;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xTaskToKill = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Do something random just to use some stack and registers. */
|
||||||
|
d1 = 2.4;
|
||||||
|
d2 = 89.2;
|
||||||
|
d2 *= d1;
|
||||||
|
vTaskDelay( xDelay );
|
||||||
|
|
||||||
|
if( xTaskToKill != NULL )
|
||||||
|
{
|
||||||
|
/* Make sure the other task has a go before we delete it. */
|
||||||
|
vTaskDelay( ( TickType_t ) 0 );
|
||||||
|
/* Kill the other task that was created by vCreateTasks(). */
|
||||||
|
vTaskDelete( xTaskToKill );
|
||||||
|
/* Kill ourselves. */
|
||||||
|
vTaskDelete( NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}/*lint !e818 !e550 Function prototype must be as per standard for task functions. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vCreateTasks( void *pvParameters )
|
||||||
|
{
|
||||||
|
const TickType_t xDelay = ( TickType_t ) 1000 / portTICK_PERIOD_MS;
|
||||||
|
unsigned portBASE_TYPE uxPriority;
|
||||||
|
const char * const pcTaskStartMsg = "Create task started.\r\n";
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
uxPriority = *( unsigned portBASE_TYPE * ) pvParameters;
|
||||||
|
vPortFree( pvParameters );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Just loop round, delaying then creating the four suicidal tasks. */
|
||||||
|
vTaskDelay( xDelay );
|
||||||
|
|
||||||
|
xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask1 );
|
||||||
|
xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask1, uxPriority, NULL );
|
||||||
|
|
||||||
|
xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask2 );
|
||||||
|
xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask2, uxPriority, NULL );
|
||||||
|
|
||||||
|
++sCreationCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that the creator task is still running and that there
|
||||||
|
are not any more than four extra tasks. */
|
||||||
|
portBASE_TYPE xIsCreateTaskStillRunning( void )
|
||||||
|
{
|
||||||
|
static short sLastCreationCount = 0;
|
||||||
|
short sReturn = pdTRUE;
|
||||||
|
unsigned portBASE_TYPE uxTasksRunningNow;
|
||||||
|
|
||||||
|
if( sLastCreationCount == sCreationCount )
|
||||||
|
{
|
||||||
|
sReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uxTasksRunningNow = uxTaskGetNumberOfTasks();
|
||||||
|
|
||||||
|
if( uxTasksRunningNow < uxTasksRunningAtStart )
|
||||||
|
{
|
||||||
|
sReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning )
|
||||||
|
{
|
||||||
|
sReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Everything is okay. */
|
||||||
|
}
|
||||||
|
|
||||||
|
return sReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,616 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first test creates three tasks - two counter tasks (one continuous count
|
||||||
|
* and one limited count) and one controller. A "count" variable is shared
|
||||||
|
* between all three tasks. The two counter tasks should never be in a "ready"
|
||||||
|
* state at the same time. The controller task runs at the same priority as
|
||||||
|
* the continuous count task, and at a lower priority than the limited count
|
||||||
|
* task.
|
||||||
|
*
|
||||||
|
* One counter task loops indefinitely, incrementing the shared count variable
|
||||||
|
* on each iteration. To ensure it has exclusive access to the variable it
|
||||||
|
* raises it's priority above that of the controller task before each
|
||||||
|
* increment, lowering it again to it's original priority before starting the
|
||||||
|
* next iteration.
|
||||||
|
*
|
||||||
|
* The other counter task increments the shared count variable on each
|
||||||
|
* iteration of it's loop until the count has reached a limit of 0xff - at
|
||||||
|
* which point it suspends itself. It will not start a new loop until the
|
||||||
|
* controller task has made it "ready" again by calling vTaskResume ().
|
||||||
|
* This second counter task operates at a higher priority than controller
|
||||||
|
* task so does not need to worry about mutual exclusion of the counter
|
||||||
|
* variable.
|
||||||
|
*
|
||||||
|
* The controller task is in two sections. The first section controls and
|
||||||
|
* monitors the continuous count task. When this section is operational the
|
||||||
|
* limited count task is suspended. Likewise, the second section controls
|
||||||
|
* and monitors the limited count task. When this section is operational the
|
||||||
|
* continuous count task is suspended.
|
||||||
|
*
|
||||||
|
* In the first section the controller task first takes a copy of the shared
|
||||||
|
* count variable. To ensure mutual exclusion on the count variable it
|
||||||
|
* suspends the continuous count task, resuming it again when the copy has been
|
||||||
|
* taken. The controller task then sleeps for a fixed period - during which
|
||||||
|
* the continuous count task will execute and increment the shared variable.
|
||||||
|
* When the controller task wakes it checks that the continuous count task
|
||||||
|
* has executed by comparing the copy of the shared variable with its current
|
||||||
|
* value. This time, to ensure mutual exclusion, the scheduler itself is
|
||||||
|
* suspended with a call to vTaskSuspendAll (). This is for demonstration
|
||||||
|
* purposes only and is not a recommended technique due to its inefficiency.
|
||||||
|
*
|
||||||
|
* After a fixed number of iterations the controller task suspends the
|
||||||
|
* continuous count task, and moves on to its second section.
|
||||||
|
*
|
||||||
|
* At the start of the second section the shared variable is cleared to zero.
|
||||||
|
* The limited count task is then woken from it's suspension by a call to
|
||||||
|
* vTaskResume (). As this counter task operates at a higher priority than
|
||||||
|
* the controller task the controller task should not run again until the
|
||||||
|
* shared variable has been counted up to the limited value causing the counter
|
||||||
|
* task to suspend itself. The next line after vTaskResume () is therefore
|
||||||
|
* a check on the shared variable to ensure everything is as expected.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The second test consists of a couple of very simple tasks that post onto a
|
||||||
|
* queue while the scheduler is suspended. This test was added to test parts
|
||||||
|
* of the scheduler not exercised by the first test.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The final set of two tasks implements a third test. This simply raises the
|
||||||
|
* priority of a task while the scheduler is suspended. Again this test was
|
||||||
|
* added to exercise parts of the code not covered by the first test.
|
||||||
|
*
|
||||||
|
* \page Priorities dynamic.c
|
||||||
|
* \ingroup DemoFiles
|
||||||
|
* <HR>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V2.0.0
|
||||||
|
|
||||||
|
+ Delay periods are now specified using variables and constants of
|
||||||
|
TickType_t rather than unsigned long.
|
||||||
|
+ Added a second, simple test that uses the functions
|
||||||
|
vQueueReceiveWhenSuspendedTask() and vQueueSendWhenSuspendedTask().
|
||||||
|
|
||||||
|
Changes from V3.1.1
|
||||||
|
|
||||||
|
+ Added a third simple test that uses the vTaskPrioritySet() function
|
||||||
|
while the scheduler is suspended.
|
||||||
|
+ Modified the controller task slightly to test the calling of
|
||||||
|
vTaskResumeAll() while the scheduler is suspended.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "semphr.h"
|
||||||
|
|
||||||
|
/* Demo app include files. */
|
||||||
|
#include "dynamic.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
/* Function that implements the "limited count" task as described above. */
|
||||||
|
static void vLimitedIncrementTask( void * pvParameters );
|
||||||
|
|
||||||
|
/* Function that implements the "continuous count" task as described above. */
|
||||||
|
static void vContinuousIncrementTask( void * pvParameters );
|
||||||
|
|
||||||
|
/* Function that implements the controller task as described above. */
|
||||||
|
static void vCounterControlTask( void * pvParameters );
|
||||||
|
|
||||||
|
/* The simple test functions that check sending and receiving while the
|
||||||
|
scheduler is suspended. */
|
||||||
|
static void vQueueReceiveWhenSuspendedTask( void *pvParameters );
|
||||||
|
static void vQueueSendWhenSuspendedTask( void *pvParameters );
|
||||||
|
|
||||||
|
/* The simple test functions that check raising and lowering of task priorities
|
||||||
|
while the scheduler is suspended. */
|
||||||
|
static void prvChangePriorityWhenSuspendedTask( void *pvParameters );
|
||||||
|
static void prvChangePriorityHelperTask( void *pvParameters );
|
||||||
|
|
||||||
|
|
||||||
|
/* Demo task specific constants. */
|
||||||
|
#define priSTACK_SIZE ( ( unsigned short ) configMINIMAL_STACK_SIZE )
|
||||||
|
#define priSLEEP_TIME ( ( TickType_t ) 50 )
|
||||||
|
#define priLOOPS ( 5 )
|
||||||
|
#define priMAX_COUNT ( ( unsigned long ) 0xff )
|
||||||
|
#define priNO_BLOCK ( ( TickType_t ) 0 )
|
||||||
|
#define priSUSPENDED_QUEUE_LENGTH ( 1 )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Handles to the two counter tasks. These could be passed in as parameters
|
||||||
|
to the controller task to prevent them having to be file scope. */
|
||||||
|
static TaskHandle_t xContinuousIncrementHandle, xLimitedIncrementHandle, xChangePriorityWhenSuspendedHandle;
|
||||||
|
|
||||||
|
/* The shared counter variable. This is passed in as a parameter to the two
|
||||||
|
counter variables for demonstration purposes. */
|
||||||
|
static unsigned long ulCounter;
|
||||||
|
|
||||||
|
/* Variable used in a similar way by the test that checks the raising and
|
||||||
|
lowering of task priorities while the scheduler is suspended. */
|
||||||
|
static unsigned long ulPrioritySetCounter;
|
||||||
|
|
||||||
|
/* Variables used to check that the tasks are still operating without error.
|
||||||
|
Each complete iteration of the controller task increments this variable
|
||||||
|
provided no errors have been found. The variable maintaining the same value
|
||||||
|
is therefore indication of an error. */
|
||||||
|
static unsigned short usCheckVariable = ( unsigned short ) 0;
|
||||||
|
static portBASE_TYPE xSuspendedQueueSendError = pdFALSE;
|
||||||
|
static portBASE_TYPE xSuspendedQueueReceiveError = pdFALSE;
|
||||||
|
static portBASE_TYPE xPriorityRaiseWhenSuspendedError = pdFALSE;
|
||||||
|
|
||||||
|
/* Queue used by the second test. */
|
||||||
|
QueueHandle_t xSuspendedTestQueue;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
* Start the seven tasks as described at the top of the file.
|
||||||
|
* Note that the limited count task is given a higher priority.
|
||||||
|
*/
|
||||||
|
void vStartDynamicPriorityTasks( void )
|
||||||
|
{
|
||||||
|
xSuspendedTestQueue = xQueueCreate( priSUSPENDED_QUEUE_LENGTH, sizeof( unsigned long ) );
|
||||||
|
xTaskCreate( vContinuousIncrementTask, "CONT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinuousIncrementHandle );
|
||||||
|
xTaskCreate( vLimitedIncrementTask, "LIM_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY + 1, &xLimitedIncrementHandle );
|
||||||
|
xTaskCreate( vCounterControlTask, "C_CTRL", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
||||||
|
xTaskCreate( vQueueSendWhenSuspendedTask, "SUSP_SEND", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
||||||
|
xTaskCreate( vQueueReceiveWhenSuspendedTask, "SUSP_RECV", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
||||||
|
xTaskCreate( prvChangePriorityWhenSuspendedTask, "1st_P_CHANGE", priSTACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL );
|
||||||
|
xTaskCreate( prvChangePriorityHelperTask, "2nd_P_CHANGE", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xChangePriorityWhenSuspendedHandle );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just loops around incrementing the shared variable until the limit has been
|
||||||
|
* reached. Once the limit has been reached it suspends itself.
|
||||||
|
*/
|
||||||
|
static void vLimitedIncrementTask( void * pvParameters )
|
||||||
|
{
|
||||||
|
unsigned long *pulCounter;
|
||||||
|
|
||||||
|
/* Take a pointer to the shared variable from the parameters passed into
|
||||||
|
the task. */
|
||||||
|
pulCounter = ( unsigned long * ) pvParameters;
|
||||||
|
|
||||||
|
/* This will run before the control task, so the first thing it does is
|
||||||
|
suspend - the control task will resume it when ready. */
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Just count up to a value then suspend. */
|
||||||
|
( *pulCounter )++;
|
||||||
|
|
||||||
|
if( *pulCounter >= priMAX_COUNT )
|
||||||
|
{
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just keep counting the shared variable up. The control task will suspend
|
||||||
|
* this task when it wants.
|
||||||
|
*/
|
||||||
|
static void vContinuousIncrementTask( void * pvParameters )
|
||||||
|
{
|
||||||
|
unsigned long *pulCounter;
|
||||||
|
unsigned portBASE_TYPE uxOurPriority;
|
||||||
|
|
||||||
|
/* Take a pointer to the shared variable from the parameters passed into
|
||||||
|
the task. */
|
||||||
|
pulCounter = ( unsigned long * ) pvParameters;
|
||||||
|
|
||||||
|
/* Query our priority so we can raise it when exclusive access to the
|
||||||
|
shared variable is required. */
|
||||||
|
uxOurPriority = uxTaskPriorityGet( NULL );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Raise our priority above the controller task to ensure a context
|
||||||
|
switch does not occur while we are accessing this variable. */
|
||||||
|
vTaskPrioritySet( NULL, uxOurPriority + 1 );
|
||||||
|
( *pulCounter )++;
|
||||||
|
vTaskPrioritySet( NULL, uxOurPriority );
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Controller task as described above.
|
||||||
|
*/
|
||||||
|
static void vCounterControlTask( void * pvParameters )
|
||||||
|
{
|
||||||
|
unsigned long ulLastCounter;
|
||||||
|
short sLoops;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
const char * const pcTaskStartMsg = "Priority manipulation tasks started.\r\n";
|
||||||
|
const char * const pcTaskFailMsg = "Priority manipulation Task Failed\r\n";
|
||||||
|
|
||||||
|
/* Just to stop warning messages. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Start with the counter at zero. */
|
||||||
|
ulCounter = ( unsigned long ) 0;
|
||||||
|
|
||||||
|
/* First section : */
|
||||||
|
|
||||||
|
/* Check the continuous count task is running. */
|
||||||
|
for( sLoops = 0; sLoops < priLOOPS; sLoops++ )
|
||||||
|
{
|
||||||
|
/* Suspend the continuous count task so we can take a mirror of the
|
||||||
|
shared variable without risk of corruption. */
|
||||||
|
vTaskSuspend( xContinuousIncrementHandle );
|
||||||
|
ulLastCounter = ulCounter;
|
||||||
|
vTaskResume( xContinuousIncrementHandle );
|
||||||
|
|
||||||
|
/* Now delay to ensure the other task has processor time. */
|
||||||
|
vTaskDelay( priSLEEP_TIME );
|
||||||
|
|
||||||
|
/* Check the shared variable again. This time to ensure mutual
|
||||||
|
exclusion the whole scheduler will be locked. This is just for
|
||||||
|
demo purposes! */
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
if( ulLastCounter == ulCounter )
|
||||||
|
{
|
||||||
|
/* The shared variable has not changed. There is a problem
|
||||||
|
with the continuous count task so flag an error. */
|
||||||
|
sError = pdTRUE;
|
||||||
|
xTaskResumeAll();
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
vTaskSuspendAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xTaskResumeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Second section: */
|
||||||
|
|
||||||
|
/* Suspend the continuous counter task so it stops accessing the shared variable. */
|
||||||
|
vTaskSuspend( xContinuousIncrementHandle );
|
||||||
|
|
||||||
|
/* Reset the variable. */
|
||||||
|
ulCounter = ( unsigned long ) 0;
|
||||||
|
|
||||||
|
/* Resume the limited count task which has a higher priority than us.
|
||||||
|
We should therefore not return from this call until the limited count
|
||||||
|
task has suspended itself with a known value in the counter variable.
|
||||||
|
The scheduler suspension is not necessary but is included for test
|
||||||
|
purposes. */
|
||||||
|
vTaskSuspendAll();
|
||||||
|
vTaskResume( xLimitedIncrementHandle );
|
||||||
|
xTaskResumeAll();
|
||||||
|
|
||||||
|
/* Does the counter variable have the expected value? */
|
||||||
|
if( ulCounter != priMAX_COUNT )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If no errors have occurred then increment the check variable. */
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
usCheckVariable++;
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Resume the continuous count task and do it all again. */
|
||||||
|
vTaskResume( xContinuousIncrementHandle );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vQueueSendWhenSuspendedTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
static unsigned long ulValueToSend = ( unsigned long ) 0;
|
||||||
|
const char * const pcTaskStartMsg = "Queue send while suspended task started.\r\n";
|
||||||
|
const char * const pcTaskFailMsg = "Queue send while suspended failed.\r\n";
|
||||||
|
|
||||||
|
/* Just to stop warning messages. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
/* We must not block while the scheduler is suspended! */
|
||||||
|
if( xQueueSend( xSuspendedTestQueue, ( void * ) &ulValueToSend, priNO_BLOCK ) != pdTRUE )
|
||||||
|
{
|
||||||
|
if( xSuspendedQueueSendError == pdFALSE )
|
||||||
|
{
|
||||||
|
xTaskResumeAll();
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
vTaskSuspendAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
xSuspendedQueueSendError = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xTaskResumeAll();
|
||||||
|
|
||||||
|
vTaskDelay( priSLEEP_TIME );
|
||||||
|
|
||||||
|
++ulValueToSend;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vQueueReceiveWhenSuspendedTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
static unsigned long ulExpectedValue = ( unsigned long ) 0, ulReceivedValue;
|
||||||
|
const char * const pcTaskStartMsg = "Queue receive while suspended task started.\r\n";
|
||||||
|
const char * const pcTaskFailMsg = "Queue receive while suspended failed.\r\n";
|
||||||
|
portBASE_TYPE xGotValue;
|
||||||
|
|
||||||
|
/* Just to stop warning messages. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Suspending the scheduler here is fairly pointless and
|
||||||
|
undesirable for a normal application. It is done here purely
|
||||||
|
to test the scheduler. The inner xTaskResumeAll() should
|
||||||
|
never return pdTRUE as the scheduler is still locked by the
|
||||||
|
outer call. */
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK );
|
||||||
|
}
|
||||||
|
if( xTaskResumeAll() )
|
||||||
|
{
|
||||||
|
xSuspendedQueueReceiveError = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xTaskResumeAll();
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} while( xGotValue == pdFALSE );
|
||||||
|
|
||||||
|
if( ulReceivedValue != ulExpectedValue )
|
||||||
|
{
|
||||||
|
if( xSuspendedQueueReceiveError == pdFALSE )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
}
|
||||||
|
xSuspendedQueueReceiveError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
++ulExpectedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvChangePriorityWhenSuspendedTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
const char * const pcTaskStartMsg = "Priority change when suspended task started.\r\n";
|
||||||
|
const char * const pcTaskFailMsg = "Priority change when suspended task failed.\r\n";
|
||||||
|
|
||||||
|
/* Just to stop warning messages. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Start with the counter at 0 so we know what the counter should be
|
||||||
|
when we check it next. */
|
||||||
|
ulPrioritySetCounter = ( unsigned long ) 0;
|
||||||
|
|
||||||
|
/* Resume the helper task. At this time it has a priority lower than
|
||||||
|
ours so no context switch should occur. */
|
||||||
|
vTaskResume( xChangePriorityWhenSuspendedHandle );
|
||||||
|
|
||||||
|
/* Check to ensure the task just resumed has not executed. */
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
if( ulPrioritySetCounter != ( unsigned long ) 0 )
|
||||||
|
{
|
||||||
|
xPriorityRaiseWhenSuspendedError = pdTRUE;
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
|
||||||
|
/* Now try raising the priority while the scheduler is suspended. */
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, ( configMAX_PRIORITIES - 1 ) );
|
||||||
|
|
||||||
|
/* Again, even though the helper task has a priority greater than
|
||||||
|
ours, it should not have executed yet because the scheduler is
|
||||||
|
suspended. */
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
if( ulPrioritySetCounter != ( unsigned long ) 0 )
|
||||||
|
{
|
||||||
|
xPriorityRaiseWhenSuspendedError = pdTRUE;
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
xTaskResumeAll();
|
||||||
|
|
||||||
|
/* Now the scheduler has been resumed the helper task should
|
||||||
|
immediately preempt us and execute. When it executes it will increment
|
||||||
|
the ulPrioritySetCounter exactly once before suspending itself.
|
||||||
|
|
||||||
|
We should now always find the counter set to 1. */
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
if( ulPrioritySetCounter != ( unsigned long ) 1 )
|
||||||
|
{
|
||||||
|
xPriorityRaiseWhenSuspendedError = pdTRUE;
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
|
||||||
|
/* Delay until we try this again. */
|
||||||
|
vTaskDelay( priSLEEP_TIME * 2 );
|
||||||
|
|
||||||
|
/* Set the priority of the helper task back ready for the next
|
||||||
|
execution of this task. */
|
||||||
|
vTaskSuspendAll();
|
||||||
|
vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, tskIDLE_PRIORITY );
|
||||||
|
xTaskResumeAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvChangePriorityHelperTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
/* Just to stop warning messages. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* This is the helper task for prvChangePriorityWhenSuspendedTask().
|
||||||
|
It has it's priority raised and lowered. When it runs it simply
|
||||||
|
increments the counter then suspends itself again. This allows
|
||||||
|
prvChangePriorityWhenSuspendedTask() to know how many times it has
|
||||||
|
executed. */
|
||||||
|
ulPrioritySetCounter++;
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Called to check that all the created tasks are still running without error. */
|
||||||
|
portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
/* Keep a history of the check variables so we know if it has been incremented
|
||||||
|
since the last call. */
|
||||||
|
static unsigned short usLastTaskCheck = ( unsigned short ) 0;
|
||||||
|
portBASE_TYPE xReturn = pdTRUE;
|
||||||
|
|
||||||
|
/* Check the tasks are still running by ensuring the check variable
|
||||||
|
is still incrementing. */
|
||||||
|
|
||||||
|
if( usCheckVariable == usLastTaskCheck )
|
||||||
|
{
|
||||||
|
/* The check has not incremented so an error exists. */
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xSuspendedQueueSendError == pdTRUE )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xSuspendedQueueReceiveError == pdTRUE )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xPriorityRaiseWhenSuspendedError == pdTRUE )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
usLastTaskCheck = usCheckVariable;
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,406 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 exercises the event mechanism whereby more than one task is
|
||||||
|
* blocked waiting for the same event.
|
||||||
|
*
|
||||||
|
* The demo creates five tasks - four 'event' tasks, and a controlling task.
|
||||||
|
* The event tasks have various different priorities and all block on reading
|
||||||
|
* the same queue. The controlling task writes data to the queue, then checks
|
||||||
|
* to see which of the event tasks read the data from the queue. The
|
||||||
|
* controlling task has the lowest priority of all the tasks so is guaranteed
|
||||||
|
* to always get preempted immediately upon writing to the queue.
|
||||||
|
*
|
||||||
|
* By selectively suspending and resuming the event tasks the controlling task
|
||||||
|
* can check that the highest priority task that is blocked on the queue is the
|
||||||
|
* task that reads the posted data from the queue.
|
||||||
|
*
|
||||||
|
* Two of the event tasks share the same priority. When neither of these tasks
|
||||||
|
* are suspended they should alternate - one reading one message from the queue,
|
||||||
|
* the other the next message, etc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "mevents.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
/* Demo specific constants. */
|
||||||
|
#define evtSTACK_SIZE ( ( unsigned portBASE_TYPE ) configMINIMAL_STACK_SIZE )
|
||||||
|
#define evtNUM_TASKS ( 4 )
|
||||||
|
#define evtQUEUE_LENGTH ( ( unsigned portBASE_TYPE ) 3 )
|
||||||
|
#define evtNO_DELAY 0
|
||||||
|
|
||||||
|
/* Just indexes used to uniquely identify the tasks. Note that two tasks are
|
||||||
|
'highest' priority. */
|
||||||
|
#define evtHIGHEST_PRIORITY_INDEX_2 3
|
||||||
|
#define evtHIGHEST_PRIORITY_INDEX_1 2
|
||||||
|
#define evtMEDIUM_PRIORITY_INDEX 1
|
||||||
|
#define evtLOWEST_PRIORITY_INDEX 0
|
||||||
|
|
||||||
|
/* Each event task increments one of these counters each time it reads data
|
||||||
|
from the queue. */
|
||||||
|
static volatile portBASE_TYPE xTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
/* Each time the controlling task posts onto the queue it increments the
|
||||||
|
expected count of the task that it expected to read the data from the queue
|
||||||
|
(i.e. the task with the highest priority that should be blocked on the queue).
|
||||||
|
|
||||||
|
xExpectedTaskCounters are incremented from the controlling task, and
|
||||||
|
xTaskCounters are incremented from the individual event tasks - therefore
|
||||||
|
comparing xTaskCounters to xExpectedTaskCounters shows whether or not the
|
||||||
|
correct task was unblocked by the post. */
|
||||||
|
static portBASE_TYPE xExpectedTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
/* Handles to the four event tasks. These are required to suspend and resume
|
||||||
|
the tasks. */
|
||||||
|
static TaskHandle_t xCreatedTasks[ evtNUM_TASKS ];
|
||||||
|
|
||||||
|
/* The single queue onto which the controlling task posts, and the four event
|
||||||
|
tasks block. */
|
||||||
|
static QueueHandle_t xQueue;
|
||||||
|
|
||||||
|
/* Flag used to indicate whether or not an error has occurred at any time.
|
||||||
|
An error is either the queue being full when not expected, or an unexpected
|
||||||
|
task reading data from the queue. */
|
||||||
|
static portBASE_TYPE xHealthStatus = pdPASS;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Function that implements the event task. This is created four times. */
|
||||||
|
static void prvMultiEventTask( void *pvParameters );
|
||||||
|
|
||||||
|
/* Function that implements the controlling task. */
|
||||||
|
static void prvEventControllerTask( void *pvParameters );
|
||||||
|
|
||||||
|
/* This is a utility function that posts data to the queue, then compares
|
||||||
|
xExpectedTaskCounters with xTaskCounters to ensure everything worked as
|
||||||
|
expected.
|
||||||
|
|
||||||
|
The event tasks all have higher priorities the controlling task. Therefore
|
||||||
|
the controlling task will always get preempted between writhing to the queue
|
||||||
|
and checking the task counters.
|
||||||
|
|
||||||
|
@param xExpectedTask The index to the task that the controlling task thinks
|
||||||
|
should be the highest priority task waiting for data, and
|
||||||
|
therefore the task that will unblock.
|
||||||
|
|
||||||
|
@param xIncrement The number of items that should be written to the queue.
|
||||||
|
*/
|
||||||
|
static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask, portBASE_TYPE xIncrement );
|
||||||
|
|
||||||
|
/* This is just incremented each cycle of the controlling tasks function so
|
||||||
|
the main application can ensure the test is still running. */
|
||||||
|
static portBASE_TYPE xCheckVariable = 0;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartMultiEventTasks( void )
|
||||||
|
{
|
||||||
|
/* Create the queue to be used for all the communications. */
|
||||||
|
xQueue = xQueueCreate( evtQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
|
||||||
|
|
||||||
|
/* Start the controlling task. This has the idle priority to ensure it is
|
||||||
|
always preempted by the event tasks. */
|
||||||
|
xTaskCreate( prvEventControllerTask, "EvntCTRL", evtSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
||||||
|
|
||||||
|
/* Start the four event tasks. Note that two have priority 3, one
|
||||||
|
priority 2 and the other priority 1. */
|
||||||
|
xTaskCreate( prvMultiEventTask, "Event0", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 0 ] ), 1, &( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ) );
|
||||||
|
xTaskCreate( prvMultiEventTask, "Event1", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 1 ] ), 2, &( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ) );
|
||||||
|
xTaskCreate( prvMultiEventTask, "Event2", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 2 ] ), 3, &( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ) );
|
||||||
|
xTaskCreate( prvMultiEventTask, "Event3", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 3 ] ), 3, &( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] ) );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvMultiEventTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
portBASE_TYPE *pxCounter;
|
||||||
|
unsigned portBASE_TYPE uxDummy;
|
||||||
|
const char * const pcTaskStartMsg = "Multi event task started.\r\n";
|
||||||
|
|
||||||
|
/* The variable this task will increment is passed in as a parameter. */
|
||||||
|
pxCounter = ( portBASE_TYPE * ) pvParameters;
|
||||||
|
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Block on the queue. */
|
||||||
|
if( xQueueReceive( xQueue, &uxDummy, portMAX_DELAY ) )
|
||||||
|
{
|
||||||
|
/* We unblocked by reading the queue - so simply increment
|
||||||
|
the counter specific to this task instance. */
|
||||||
|
( *pxCounter )++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xHealthStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvEventControllerTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
const char * const pcTaskStartMsg = "Multi event controller task started.\r\n";
|
||||||
|
portBASE_TYPE xDummy = 0;
|
||||||
|
|
||||||
|
/* Just to stop warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* All tasks are blocked on the queue. When a message is posted one of
|
||||||
|
the two tasks that share the highest priority should unblock to read
|
||||||
|
the queue. The next message written should unblock the other task with
|
||||||
|
the same high priority, and so on in order. No other task should
|
||||||
|
unblock to read data as they have lower priorities. */
|
||||||
|
|
||||||
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
||||||
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_2, 1 );
|
||||||
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
||||||
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_2, 1 );
|
||||||
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
||||||
|
|
||||||
|
/* For the rest of these tests we don't need the second 'highest'
|
||||||
|
priority task - so it is suspended. */
|
||||||
|
vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Now suspend the other highest priority task. The medium priority
|
||||||
|
task will then be the task with the highest priority that remains
|
||||||
|
blocked on the queue. */
|
||||||
|
vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
||||||
|
|
||||||
|
/* This time, when we post onto the queue we will expect the medium
|
||||||
|
priority task to unblock and preempt us. */
|
||||||
|
prvCheckTaskCounters( evtMEDIUM_PRIORITY_INDEX, 1 );
|
||||||
|
|
||||||
|
/* Now try resuming the highest priority task while the scheduler is
|
||||||
|
suspended. The task should start executing as soon as the scheduler
|
||||||
|
is resumed - therefore when we post to the queue again, the highest
|
||||||
|
priority task should again preempt us. */
|
||||||
|
vTaskSuspendAll();
|
||||||
|
vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
||||||
|
xTaskResumeAll();
|
||||||
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
||||||
|
|
||||||
|
/* Now we are going to suspend the high and medium priority tasks. The
|
||||||
|
low priority task should then preempt us. Again the task suspension is
|
||||||
|
done with the whole scheduler suspended just for test purposes. */
|
||||||
|
vTaskSuspendAll();
|
||||||
|
vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
||||||
|
vTaskSuspend( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] );
|
||||||
|
xTaskResumeAll();
|
||||||
|
prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, 1 );
|
||||||
|
|
||||||
|
/* Do the same basic test another few times - selectively suspending
|
||||||
|
and resuming tasks and each time calling prvCheckTaskCounters() passing
|
||||||
|
to the function the number of the task we expected to be unblocked by
|
||||||
|
the post. */
|
||||||
|
|
||||||
|
vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
||||||
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
||||||
|
|
||||||
|
vTaskSuspendAll(); /* Just for test. */
|
||||||
|
vTaskSuspendAll(); /* Just for test. */
|
||||||
|
vTaskSuspendAll(); /* Just for even more test. */
|
||||||
|
vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
||||||
|
xTaskResumeAll();
|
||||||
|
xTaskResumeAll();
|
||||||
|
xTaskResumeAll();
|
||||||
|
prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, 1 );
|
||||||
|
|
||||||
|
vTaskResume( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] );
|
||||||
|
prvCheckTaskCounters( evtMEDIUM_PRIORITY_INDEX, 1 );
|
||||||
|
|
||||||
|
vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
||||||
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
||||||
|
|
||||||
|
/* Now a slight change, first suspend all tasks. */
|
||||||
|
vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
||||||
|
vTaskSuspend( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] );
|
||||||
|
vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
|
||||||
|
|
||||||
|
/* Now when we resume the low priority task and write to the queue 3
|
||||||
|
times. We expect the low priority task to service the queue three
|
||||||
|
times. */
|
||||||
|
vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
|
||||||
|
prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, evtQUEUE_LENGTH );
|
||||||
|
|
||||||
|
/* Again suspend all tasks (only the low priority task is not suspended
|
||||||
|
already). */
|
||||||
|
vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
|
||||||
|
|
||||||
|
/* This time we are going to suspend the scheduler, resume the low
|
||||||
|
priority task, then resume the high priority task. In this state we
|
||||||
|
will write to the queue three times. When the scheduler is resumed
|
||||||
|
we expect the high priority task to service all three messages. */
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
|
||||||
|
vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
||||||
|
|
||||||
|
for( xDummy = 0; xDummy < evtQUEUE_LENGTH; xDummy++ )
|
||||||
|
{
|
||||||
|
if( xQueueSend( xQueue, &xDummy, evtNO_DELAY ) != pdTRUE )
|
||||||
|
{
|
||||||
|
xHealthStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The queue should not have been serviced yet!. The scheduler
|
||||||
|
is still suspended. */
|
||||||
|
if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) )
|
||||||
|
{
|
||||||
|
xHealthStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xTaskResumeAll();
|
||||||
|
|
||||||
|
/* We should have been preempted by resuming the scheduler - so by the
|
||||||
|
time we are running again we expect the high priority task to have
|
||||||
|
removed three items from the queue. */
|
||||||
|
xExpectedTaskCounters[ evtHIGHEST_PRIORITY_INDEX_1 ] += evtQUEUE_LENGTH;
|
||||||
|
if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) )
|
||||||
|
{
|
||||||
|
xHealthStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The medium priority and second high priority tasks are still
|
||||||
|
suspended. Make sure to resume them before starting again. */
|
||||||
|
vTaskResume( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] );
|
||||||
|
vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] );
|
||||||
|
|
||||||
|
/* Just keep incrementing to show the task is still executing. */
|
||||||
|
xCheckVariable++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask, portBASE_TYPE xIncrement )
|
||||||
|
{
|
||||||
|
portBASE_TYPE xDummy = 0;
|
||||||
|
|
||||||
|
/* Write to the queue the requested number of times. The data written is
|
||||||
|
not important. */
|
||||||
|
for( xDummy = 0; xDummy < xIncrement; xDummy++ )
|
||||||
|
{
|
||||||
|
if( xQueueSend( xQueue, &xDummy, evtNO_DELAY ) != pdTRUE )
|
||||||
|
{
|
||||||
|
/* Did not expect to ever find the queue full. */
|
||||||
|
xHealthStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All the tasks blocked on the queue have a priority higher than the
|
||||||
|
controlling task. Writing to the queue will therefore have caused this
|
||||||
|
task to be preempted. By the time this line executes the event task will
|
||||||
|
have executed and incremented its counter. Increment the expected counter
|
||||||
|
to the same value. */
|
||||||
|
( xExpectedTaskCounters[ xExpectedTask ] ) += xIncrement;
|
||||||
|
|
||||||
|
/* Check the actual counts and expected counts really are the same. */
|
||||||
|
if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) )
|
||||||
|
{
|
||||||
|
/* The counters were not the same. This means a task we did not expect
|
||||||
|
to unblock actually did unblock. */
|
||||||
|
xHealthStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
portBASE_TYPE xAreMultiEventTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
static portBASE_TYPE xPreviousCheckVariable = 0;
|
||||||
|
|
||||||
|
/* Called externally to periodically check that this test is still
|
||||||
|
operational. */
|
||||||
|
|
||||||
|
if( xPreviousCheckVariable == xCheckVariable )
|
||||||
|
{
|
||||||
|
xHealthStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
xPreviousCheckVariable = xCheckVariable;
|
||||||
|
|
||||||
|
return xHealthStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates eight tasks, each of which flash an LED at a different rate. The first
|
||||||
|
* LED flashes every 125ms, the second every 250ms, the third every 375ms, etc.
|
||||||
|
*
|
||||||
|
* The LED flash tasks provide instant visual feedback. They show that the scheduler
|
||||||
|
* is still operational.
|
||||||
|
*
|
||||||
|
* The PC port uses the standard parallel port for outputs, the Flashlite 186 port
|
||||||
|
* uses IO port F.
|
||||||
|
*
|
||||||
|
* \page flashC flash.c
|
||||||
|
* \ingroup DemoFiles
|
||||||
|
* <HR>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V2.0.0
|
||||||
|
|
||||||
|
+ Delay periods are now specified using variables and constants of
|
||||||
|
TickType_t rather than unsigned long.
|
||||||
|
|
||||||
|
Changes from V2.1.1
|
||||||
|
|
||||||
|
+ The stack size now uses configMINIMAL_STACK_SIZE.
|
||||||
|
+ String constants made file scope to decrease stack depth on 8051 port.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "partest.h"
|
||||||
|
#include "flash.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
#define ledSTACK_SIZE configMINIMAL_STACK_SIZE
|
||||||
|
|
||||||
|
/* Structure used to pass parameters to the LED tasks. */
|
||||||
|
typedef struct LED_PARAMETERS
|
||||||
|
{
|
||||||
|
unsigned portBASE_TYPE uxLED; /*< The output the task should use. */
|
||||||
|
TickType_t xFlashRate; /*< The rate at which the LED should flash. */
|
||||||
|
} xLEDParameters;
|
||||||
|
|
||||||
|
/* The task that is created eight times - each time with a different xLEDParaemtes
|
||||||
|
structure passed in as the parameter. */
|
||||||
|
static void vLEDFlashTask( void *pvParameters );
|
||||||
|
|
||||||
|
/* String to print if USE_STDIO is defined. */
|
||||||
|
const char * const pcTaskStartMsg = "LED flash task started.\r\n";
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority )
|
||||||
|
{
|
||||||
|
unsigned portBASE_TYPE uxLEDTask;
|
||||||
|
xLEDParameters *pxLEDParameters;
|
||||||
|
const unsigned portBASE_TYPE uxNumOfLEDs = 8;
|
||||||
|
const TickType_t xFlashRate = 125;
|
||||||
|
|
||||||
|
/* Create the eight tasks. */
|
||||||
|
for( uxLEDTask = 0; uxLEDTask < uxNumOfLEDs; ++uxLEDTask )
|
||||||
|
{
|
||||||
|
/* Create and complete the structure used to pass parameters to the next
|
||||||
|
created task. */
|
||||||
|
pxLEDParameters = ( xLEDParameters * ) pvPortMalloc( sizeof( xLEDParameters ) );
|
||||||
|
pxLEDParameters->uxLED = uxLEDTask;
|
||||||
|
pxLEDParameters->xFlashRate = ( xFlashRate + ( xFlashRate * ( TickType_t ) uxLEDTask ) );
|
||||||
|
pxLEDParameters->xFlashRate /= portTICK_PERIOD_MS;
|
||||||
|
|
||||||
|
/* Spawn the task. */
|
||||||
|
xTaskCreate( vLEDFlashTask, "LEDx", ledSTACK_SIZE, ( void * ) pxLEDParameters, uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vLEDFlashTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
xLEDParameters *pxParameters;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
pxParameters = ( xLEDParameters * ) pvParameters;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
/* Delay for half the flash period then turn the LED on. */
|
||||||
|
vTaskDelay( pxParameters->xFlashRate / ( TickType_t ) 2 );
|
||||||
|
vParTestToggleLED( pxParameters->uxLED );
|
||||||
|
|
||||||
|
/* Delay for half the flash period then turn the LED off. */
|
||||||
|
vTaskDelay( pxParameters->xFlashRate / ( TickType_t ) 2 );
|
||||||
|
vParTestToggleLED( pxParameters->uxLED );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,369 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V1.2.3
|
||||||
|
|
||||||
|
+ The created tasks now include calls to tskYIELD(), allowing them to be used
|
||||||
|
with the cooperative scheduler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates eight tasks, each of which loops continuously performing an (emulated)
|
||||||
|
* floating point calculation.
|
||||||
|
*
|
||||||
|
* All the tasks run at the idle priority and never block or yield. This causes
|
||||||
|
* all eight tasks to time slice with the idle task. Running at the idle priority
|
||||||
|
* means that these tasks will get pre-empted any time another task is ready to run
|
||||||
|
* or a time slice occurs. More often than not the pre-emption will occur mid
|
||||||
|
* calculation, creating a good test of the schedulers context switch mechanism - a
|
||||||
|
* calculation producing an unexpected result could be a symptom of a corruption in
|
||||||
|
* the context of a task.
|
||||||
|
*
|
||||||
|
* \page FlopC flop.c
|
||||||
|
* \ingroup DemoFiles
|
||||||
|
* <HR>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "flop.h"
|
||||||
|
|
||||||
|
#define mathSTACK_SIZE ( ( unsigned short ) 512 )
|
||||||
|
#define mathNUMBER_OF_TASKS ( 8 )
|
||||||
|
|
||||||
|
/* Four tasks, each of which performs a different floating point calculation.
|
||||||
|
Each of the four is created twice. */
|
||||||
|
static void vCompetingMathTask1( void *pvParameters );
|
||||||
|
static void vCompetingMathTask2( void *pvParameters );
|
||||||
|
static void vCompetingMathTask3( void *pvParameters );
|
||||||
|
static void vCompetingMathTask4( void *pvParameters );
|
||||||
|
|
||||||
|
/* These variables are used to check that all the tasks are still running. If a
|
||||||
|
task gets a calculation wrong it will
|
||||||
|
stop incrementing its check variable. */
|
||||||
|
static volatile unsigned short usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartMathTasks( unsigned portBASE_TYPE uxPriority )
|
||||||
|
{
|
||||||
|
xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask1, "Math5", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask2, "Math6", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask3, "Math7", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask4, "Math8", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vCompetingMathTask1( void *pvParameters )
|
||||||
|
{
|
||||||
|
portDOUBLE d1, d2, d3, d4;
|
||||||
|
volatile unsigned short *pusTaskCheckVariable;
|
||||||
|
const portDOUBLE dAnswer = ( 123.4567 + 2345.6789 ) * -918.222;
|
||||||
|
const char * const pcTaskStartMsg = "Math task 1 started.\r\n";
|
||||||
|
const char * const pcTaskFailMsg = "Math task 1 failed.\r\n";
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
d1 = 123.4567;
|
||||||
|
d2 = 2345.6789;
|
||||||
|
d3 = -918.222;
|
||||||
|
|
||||||
|
d4 = ( d1 + d2 ) * d3;
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
/* If the calculation does not match the expected constant, stop the
|
||||||
|
increment of the check variable. */
|
||||||
|
if( fabs( d4 - dAnswer ) > 0.001 )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct, increment the check
|
||||||
|
variable so we know this task is still running okay. */
|
||||||
|
( *pusTaskCheckVariable )++;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vCompetingMathTask2( void *pvParameters )
|
||||||
|
{
|
||||||
|
portDOUBLE d1, d2, d3, d4;
|
||||||
|
volatile unsigned short *pusTaskCheckVariable;
|
||||||
|
const portDOUBLE dAnswer = ( -389.38 / 32498.2 ) * -2.0001;
|
||||||
|
const char * const pcTaskStartMsg = "Math task 2 started.\r\n";
|
||||||
|
const char * const pcTaskFailMsg = "Math task 2 failed.\r\n";
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
d1 = -389.38;
|
||||||
|
d2 = 32498.2;
|
||||||
|
d3 = -2.0001;
|
||||||
|
|
||||||
|
d4 = ( d1 / d2 ) * d3;
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
/* If the calculation does not match the expected constant, stop the
|
||||||
|
increment of the check variable. */
|
||||||
|
if( fabs( d4 - dAnswer ) > 0.001 )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct, increment the check
|
||||||
|
variable so we know
|
||||||
|
this task is still running okay. */
|
||||||
|
( *pusTaskCheckVariable )++;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vCompetingMathTask3( void *pvParameters )
|
||||||
|
{
|
||||||
|
portDOUBLE *pdArray, dTotal1, dTotal2, dDifference;
|
||||||
|
volatile unsigned short *pusTaskCheckVariable;
|
||||||
|
const unsigned short usArraySize = 250;
|
||||||
|
unsigned short usPosition;
|
||||||
|
const char * const pcTaskStartMsg = "Math task 3 started.\r\n";
|
||||||
|
const char * const pcTaskFailMsg = "Math task 3 failed.\r\n";
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
|
pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) );
|
||||||
|
|
||||||
|
/* Keep filling an array, keeping a running total of the values placed in the
|
||||||
|
array. Then run through the array adding up all the values. If the two totals
|
||||||
|
do not match, stop the check variable from incrementing. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
dTotal1 = 0.0;
|
||||||
|
dTotal2 = 0.0;
|
||||||
|
|
||||||
|
for( usPosition = 0; usPosition < usArraySize; usPosition++ )
|
||||||
|
{
|
||||||
|
pdArray[ usPosition ] = ( portDOUBLE ) usPosition + 5.5;
|
||||||
|
dTotal1 += ( portDOUBLE ) usPosition + 5.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
for( usPosition = 0; usPosition < usArraySize; usPosition++ )
|
||||||
|
{
|
||||||
|
dTotal2 += pdArray[ usPosition ];
|
||||||
|
}
|
||||||
|
|
||||||
|
dDifference = dTotal1 - dTotal2;
|
||||||
|
if( fabs( dDifference ) > 0.001 )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct, increment the check
|
||||||
|
variable so we know this task is still running okay. */
|
||||||
|
( *pusTaskCheckVariable )++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vCompetingMathTask4( void *pvParameters )
|
||||||
|
{
|
||||||
|
portDOUBLE *pdArray, dTotal1, dTotal2, dDifference;
|
||||||
|
volatile unsigned short *pusTaskCheckVariable;
|
||||||
|
const unsigned short usArraySize = 250;
|
||||||
|
unsigned short usPosition;
|
||||||
|
const char * const pcTaskStartMsg = "Math task 4 started.\r\n";
|
||||||
|
const char * const pcTaskFailMsg = "Math task 4 failed.\r\n";
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
|
pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) );
|
||||||
|
|
||||||
|
/* Keep filling an array, keeping a running total of the values placed in the
|
||||||
|
array. Then run through the array adding up all the values. If the two totals
|
||||||
|
do not match, stop the check variable from incrementing. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
dTotal1 = 0.0;
|
||||||
|
dTotal2 = 0.0;
|
||||||
|
|
||||||
|
for( usPosition = 0; usPosition < usArraySize; usPosition++ )
|
||||||
|
{
|
||||||
|
pdArray[ usPosition ] = ( portDOUBLE ) usPosition * 12.123;
|
||||||
|
dTotal1 += ( portDOUBLE ) usPosition * 12.123;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
for( usPosition = 0; usPosition < usArraySize; usPosition++ )
|
||||||
|
{
|
||||||
|
dTotal2 += pdArray[ usPosition ];
|
||||||
|
}
|
||||||
|
|
||||||
|
dDifference = dTotal1 - dTotal2;
|
||||||
|
if( fabs( dDifference ) > 0.001 )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct, increment the check
|
||||||
|
variable so we know this task is still running okay. */
|
||||||
|
( *pusTaskCheckVariable )++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running. */
|
||||||
|
portBASE_TYPE xAreMathsTaskStillRunning( void )
|
||||||
|
{
|
||||||
|
/* Keep a history of the check variables so we know if they have been incremented
|
||||||
|
since the last call. */
|
||||||
|
static unsigned short usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
|
||||||
|
portBASE_TYPE xReturn = pdTRUE, xTask;
|
||||||
|
|
||||||
|
/* Check the maths tasks are still running by ensuring their check variables
|
||||||
|
are still incrementing. */
|
||||||
|
for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )
|
||||||
|
{
|
||||||
|
if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )
|
||||||
|
{
|
||||||
|
/* The check has not incremented so an error exists. */
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ];
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,365 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V1.2.3
|
||||||
|
|
||||||
|
+ The created tasks now include calls to tskYIELD(), allowing them to be used
|
||||||
|
with the cooperative scheduler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This does the same as flop. c, but uses variables of type long instead of
|
||||||
|
* type double.
|
||||||
|
*
|
||||||
|
* As with flop. c, the tasks created in this file are a good test of the
|
||||||
|
* scheduler context switch mechanism. The processor has to access 32bit
|
||||||
|
* variables in two or four chunks (depending on the processor). The low
|
||||||
|
* priority of these tasks means there is a high probability that a context
|
||||||
|
* switch will occur mid calculation. See the flop. c documentation for
|
||||||
|
* more information.
|
||||||
|
*
|
||||||
|
* \page IntegerC integer.c
|
||||||
|
* \ingroup DemoFiles
|
||||||
|
* <HR>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V1.2.1
|
||||||
|
|
||||||
|
+ The constants used in the calculations are larger to ensure the
|
||||||
|
optimiser does not truncate them to 16 bits.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "integer.h"
|
||||||
|
|
||||||
|
#define intgSTACK_SIZE ( ( unsigned short ) 256 )
|
||||||
|
#define intgNUMBER_OF_TASKS ( 8 )
|
||||||
|
|
||||||
|
/* Four tasks, each of which performs a different calculation on four byte
|
||||||
|
variables. Each of the four is created twice. */
|
||||||
|
static void vCompeteingIntMathTask1( void *pvParameters );
|
||||||
|
static void vCompeteingIntMathTask2( void *pvParameters );
|
||||||
|
static void vCompeteingIntMathTask3( void *pvParameters );
|
||||||
|
static void vCompeteingIntMathTask4( void *pvParameters );
|
||||||
|
|
||||||
|
/* These variables are used to check that all the tasks are still running. If a
|
||||||
|
task gets a calculation wrong it will stop incrementing its check variable. */
|
||||||
|
static volatile unsigned short usTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartIntegerMathTasks( unsigned portBASE_TYPE uxPriority )
|
||||||
|
{
|
||||||
|
xTaskCreate( vCompeteingIntMathTask1, "IntMath1", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompeteingIntMathTask2, "IntMath2", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompeteingIntMathTask3, "IntMath3", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompeteingIntMathTask4, "IntMath4", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompeteingIntMathTask1, "IntMath5", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompeteingIntMathTask2, "IntMath6", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompeteingIntMathTask3, "IntMath7", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompeteingIntMathTask4, "IntMath8", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vCompeteingIntMathTask1( void *pvParameters )
|
||||||
|
{
|
||||||
|
long l1, l2, l3, l4;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
volatile unsigned short *pusTaskCheckVariable;
|
||||||
|
const long lAnswer = ( ( long ) 74565L + ( long ) 1234567L ) * ( long ) -918L;
|
||||||
|
const char * const pcTaskStartMsg = "Integer math task 1 started.\r\n";
|
||||||
|
const char * const pcTaskFailMsg = "Integer math task 1 failed.\r\n";
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
l1 = ( long ) 74565L;
|
||||||
|
l2 = ( long ) 1234567L;
|
||||||
|
l3 = ( long ) -918L;
|
||||||
|
|
||||||
|
l4 = ( l1 + l2 ) * l3;
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
/* If the calculation does not match the expected constant, stop the
|
||||||
|
increment of the check variable. */
|
||||||
|
if( l4 != lAnswer )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct, increment the check
|
||||||
|
variable so we know this task is still running okay. */
|
||||||
|
( *pusTaskCheckVariable )++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vCompeteingIntMathTask2( void *pvParameters )
|
||||||
|
{
|
||||||
|
long l1, l2, l3, l4;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
volatile unsigned short *pusTaskCheckVariable;
|
||||||
|
const long lAnswer = ( ( long ) -389000L / ( long ) 329999L ) * ( long ) -89L;
|
||||||
|
const char * const pcTaskStartMsg = "Integer math task 2 started.\r\n";
|
||||||
|
const char * const pcTaskFailMsg = "Integer math task 2 failed.\r\n";
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
l1 = -389000L;
|
||||||
|
l2 = 329999L;
|
||||||
|
l3 = -89L;
|
||||||
|
|
||||||
|
l4 = ( l1 / l2 ) * l3;
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
/* If the calculation does not match the expected constant, stop the
|
||||||
|
increment of the check variable. */
|
||||||
|
if( l4 != lAnswer )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct, increment the check
|
||||||
|
variable so we know this task is still running okay. */
|
||||||
|
( *pusTaskCheckVariable )++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vCompeteingIntMathTask3( void *pvParameters )
|
||||||
|
{
|
||||||
|
long *plArray, lTotal1, lTotal2;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
volatile unsigned short *pusTaskCheckVariable;
|
||||||
|
const unsigned short usArraySize = ( unsigned short ) 250;
|
||||||
|
unsigned short usPosition;
|
||||||
|
const char * const pcTaskStartMsg = "Integer math task 3 started.\r\n";
|
||||||
|
const char * const pcTaskFailMsg = "Integer math task 3 failed.\r\n";
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
|
/* Create the array we are going to use for our check calculation. */
|
||||||
|
plArray = ( long * ) pvPortMalloc( ( size_t ) 250 * sizeof( long ) );
|
||||||
|
|
||||||
|
/* Keep filling the array, keeping a running total of the values placed in the
|
||||||
|
array. Then run through the array adding up all the values. If the two totals
|
||||||
|
do not match, stop the check variable from incrementing. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
lTotal1 = ( long ) 0;
|
||||||
|
lTotal2 = ( long ) 0;
|
||||||
|
|
||||||
|
for( usPosition = 0; usPosition < usArraySize; usPosition++ )
|
||||||
|
{
|
||||||
|
plArray[ usPosition ] = ( long ) usPosition + ( long ) 5;
|
||||||
|
lTotal1 += ( long ) usPosition + ( long ) 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
for( usPosition = 0; usPosition < usArraySize; usPosition++ )
|
||||||
|
{
|
||||||
|
lTotal2 += plArray[ usPosition ];
|
||||||
|
}
|
||||||
|
|
||||||
|
if( lTotal1 != lTotal2 )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct, increment the check
|
||||||
|
variable so we know this task is still running okay. */
|
||||||
|
( *pusTaskCheckVariable )++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vCompeteingIntMathTask4( void *pvParameters )
|
||||||
|
{
|
||||||
|
long *plArray, lTotal1, lTotal2;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
volatile unsigned short *pusTaskCheckVariable;
|
||||||
|
const unsigned short usArraySize = 250;
|
||||||
|
unsigned short usPosition;
|
||||||
|
const char * const pcTaskStartMsg = "Integer math task 4 started.\r\n";
|
||||||
|
const char * const pcTaskFailMsg = "Integer math task 4 failed.\r\n";
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
|
/* Create the array we are going to use for our check calculation. */
|
||||||
|
plArray = ( long * ) pvPortMalloc( ( size_t ) 250 * sizeof( long ) );
|
||||||
|
|
||||||
|
/* Keep filling the array, keeping a running total of the values placed in the
|
||||||
|
array. Then run through the array adding up all the values. If the two totals
|
||||||
|
do not match, stop the check variable from incrementing. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
lTotal1 = ( long ) 0;
|
||||||
|
lTotal2 = ( long ) 0;
|
||||||
|
|
||||||
|
for( usPosition = 0; usPosition < usArraySize; usPosition++ )
|
||||||
|
{
|
||||||
|
plArray[ usPosition ] = ( long ) usPosition * ( long ) 12;
|
||||||
|
lTotal1 += ( long ) usPosition * ( long ) 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
for( usPosition = 0; usPosition < usArraySize; usPosition++ )
|
||||||
|
{
|
||||||
|
lTotal2 += plArray[ usPosition ];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( lTotal1 != lTotal2 )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct, increment the check
|
||||||
|
variable so we know this task is still running okay. */
|
||||||
|
( *pusTaskCheckVariable )++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running. */
|
||||||
|
portBASE_TYPE xAreIntegerMathsTaskStillRunning( void )
|
||||||
|
{
|
||||||
|
/* Keep a history of the check variables so we know if they have been incremented
|
||||||
|
since the last call. */
|
||||||
|
static unsigned short usLastTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
|
||||||
|
portBASE_TYPE xReturn = pdTRUE, xTask;
|
||||||
|
|
||||||
|
/* Check the maths tasks are still running by ensuring their check variables
|
||||||
|
are still incrementing. */
|
||||||
|
for( xTask = 0; xTask < intgNUMBER_OF_TASKS; xTask++ )
|
||||||
|
{
|
||||||
|
if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )
|
||||||
|
{
|
||||||
|
/* The check has not incremented so an error exists. */
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ];
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages a queue of strings that are waiting to be displayed. This is used to
|
||||||
|
* ensure mutual exclusion of console output.
|
||||||
|
*
|
||||||
|
* A task wishing to display a message will call vPrintDisplayMessage (), with a
|
||||||
|
* pointer to the string as the parameter. The pointer is posted onto the
|
||||||
|
* xPrintQueue queue.
|
||||||
|
*
|
||||||
|
* The task spawned in main. c blocks on xPrintQueue. When a message becomes
|
||||||
|
* available it calls pcPrintGetNextMessage () to obtain a pointer to the next
|
||||||
|
* string, then uses the functions defined in the portable layer FileIO. c to
|
||||||
|
* display the message.
|
||||||
|
*
|
||||||
|
* <b>NOTE:</b>
|
||||||
|
* Using console IO can disrupt real time performance - depending on the port.
|
||||||
|
* Standard C IO routines are not designed for real time applications. While
|
||||||
|
* standard IO is useful for demonstration and debugging an alternative method
|
||||||
|
* should be used if you actually require console IO as part of your application.
|
||||||
|
*
|
||||||
|
* \page PrintC print.c
|
||||||
|
* \ingroup DemoFiles
|
||||||
|
* <HR>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V2.0.0
|
||||||
|
|
||||||
|
+ Delay periods are now specified using variables and constants of
|
||||||
|
TickType_t rather than unsigned long.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
static QueueHandle_t xPrintQueue;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPrintInitialise( void )
|
||||||
|
{
|
||||||
|
const unsigned portBASE_TYPE uxQueueSize = 20;
|
||||||
|
|
||||||
|
/* Create the queue on which errors will be reported. */
|
||||||
|
xPrintQueue = xQueueCreate( uxQueueSize, ( unsigned portBASE_TYPE ) sizeof( char * ) );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPrintDisplayMessage( const char * const * ppcMessageToSend )
|
||||||
|
{
|
||||||
|
#ifdef USE_STDIO
|
||||||
|
xQueueSend( xPrintQueue, ( void * ) ppcMessageToSend, ( TickType_t ) 0 );
|
||||||
|
#else
|
||||||
|
/* Stop warnings. */
|
||||||
|
( void ) ppcMessageToSend;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
const char *pcPrintGetNextMessage( TickType_t xPrintRate )
|
||||||
|
{
|
||||||
|
char *pcMessage;
|
||||||
|
|
||||||
|
if( xQueueReceive( xPrintQueue, &pcMessage, xPrintRate ) == pdPASS )
|
||||||
|
{
|
||||||
|
return pcMessage;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,323 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates two sets of two tasks. The tasks within a set share a variable, access
|
||||||
|
* to which is guarded by a semaphore.
|
||||||
|
*
|
||||||
|
* Each task starts by attempting to obtain the semaphore. On obtaining a
|
||||||
|
* semaphore a task checks to ensure that the guarded variable has an expected
|
||||||
|
* value. It then clears the variable to zero before counting it back up to the
|
||||||
|
* expected value in increments of 1. After each increment the variable is checked
|
||||||
|
* to ensure it contains the value to which it was just set. When the starting
|
||||||
|
* value is again reached the task releases the semaphore giving the other task in
|
||||||
|
* the set a chance to do exactly the same thing. The starting value is high
|
||||||
|
* enough to ensure that a tick is likely to occur during the incrementing loop.
|
||||||
|
*
|
||||||
|
* An error is flagged if at any time during the process a shared variable is
|
||||||
|
* found to have a value other than that expected. Such an occurrence would
|
||||||
|
* suggest an error in the mutual exclusion mechanism by which access to the
|
||||||
|
* variable is restricted.
|
||||||
|
*
|
||||||
|
* The first set of two tasks poll their semaphore. The second set use blocking
|
||||||
|
* calls.
|
||||||
|
*
|
||||||
|
* \page SemTestC semtest.c
|
||||||
|
* \ingroup DemoFiles
|
||||||
|
* <HR>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Changes from V1.2.0:
|
||||||
|
|
||||||
|
+ The tasks that operate at the idle priority now use a lower expected
|
||||||
|
count than those running at a higher priority. This prevents the low
|
||||||
|
priority tasks from signaling an error because they have not been
|
||||||
|
scheduled enough time for each of them to count the shared variable to
|
||||||
|
the high value.
|
||||||
|
|
||||||
|
Changes from V2.0.0
|
||||||
|
|
||||||
|
+ Delay periods are now specified using variables and constants of
|
||||||
|
TickType_t rather than unsigned long.
|
||||||
|
|
||||||
|
Changes from V2.1.1
|
||||||
|
|
||||||
|
+ The stack size now uses configMINIMAL_STACK_SIZE.
|
||||||
|
+ String constants made file scope to decrease stack depth on 8051 port.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "semphr.h"
|
||||||
|
|
||||||
|
/* Demo app include files. */
|
||||||
|
#include "semtest.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
/* The value to which the shared variables are counted. */
|
||||||
|
#define semtstBLOCKING_EXPECTED_VALUE ( ( unsigned long ) 0xfff )
|
||||||
|
#define semtstNON_BLOCKING_EXPECTED_VALUE ( ( unsigned long ) 0xff )
|
||||||
|
|
||||||
|
#define semtstSTACK_SIZE configMINIMAL_STACK_SIZE
|
||||||
|
|
||||||
|
#define semtstNUM_TASKS ( 4 )
|
||||||
|
|
||||||
|
#define semtstDELAY_FACTOR ( ( TickType_t ) 10 )
|
||||||
|
|
||||||
|
/* The task function as described at the top of the file. */
|
||||||
|
static void prvSemaphoreTest( void *pvParameters );
|
||||||
|
|
||||||
|
/* Structure used to pass parameters to each task. */
|
||||||
|
typedef struct SEMAPHORE_PARAMETERS
|
||||||
|
{
|
||||||
|
SemaphoreHandle_t xSemaphore;
|
||||||
|
volatile unsigned long *pulSharedVariable;
|
||||||
|
TickType_t xBlockTime;
|
||||||
|
} xSemaphoreParameters;
|
||||||
|
|
||||||
|
/* Variables used to check that all the tasks are still running without errors. */
|
||||||
|
static volatile short sCheckVariables[ semtstNUM_TASKS ] = { 0 };
|
||||||
|
static volatile short sNextCheckVariable = 0;
|
||||||
|
|
||||||
|
/* Strings to print if USE_STDIO is defined. */
|
||||||
|
const char * const pcPollingSemaphoreTaskError = "Guarded shared variable in unexpected state.\r\n";
|
||||||
|
const char * const pcSemaphoreTaskStart = "Guarded shared variable task started.\r\n";
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartSemaphoreTasks( unsigned portBASE_TYPE uxPriority )
|
||||||
|
{
|
||||||
|
xSemaphoreParameters *pxFirstSemaphoreParameters, *pxSecondSemaphoreParameters;
|
||||||
|
const TickType_t xBlockTime = ( TickType_t ) 100;
|
||||||
|
|
||||||
|
/* Create the structure used to pass parameters to the first two tasks. */
|
||||||
|
pxFirstSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) );
|
||||||
|
|
||||||
|
if( pxFirstSemaphoreParameters != NULL )
|
||||||
|
{
|
||||||
|
/* Create the semaphore used by the first two tasks. */
|
||||||
|
vSemaphoreCreateBinary( pxFirstSemaphoreParameters->xSemaphore );
|
||||||
|
|
||||||
|
if( pxFirstSemaphoreParameters->xSemaphore != NULL )
|
||||||
|
{
|
||||||
|
/* Create the variable which is to be shared by the first two tasks. */
|
||||||
|
pxFirstSemaphoreParameters->pulSharedVariable = ( unsigned long * ) pvPortMalloc( sizeof( unsigned long ) );
|
||||||
|
|
||||||
|
/* Initialise the share variable to the value the tasks expect. */
|
||||||
|
*( pxFirstSemaphoreParameters->pulSharedVariable ) = semtstNON_BLOCKING_EXPECTED_VALUE;
|
||||||
|
|
||||||
|
/* The first two tasks do not block on semaphore calls. */
|
||||||
|
pxFirstSemaphoreParameters->xBlockTime = ( TickType_t ) 0;
|
||||||
|
|
||||||
|
/* Spawn the first two tasks. As they poll they operate at the idle priority. */
|
||||||
|
xTaskCreate( prvSemaphoreTest, "PolSEM1", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL );
|
||||||
|
xTaskCreate( prvSemaphoreTest, "PolSEM2", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do exactly the same to create the second set of tasks, only this time
|
||||||
|
provide a block time for the semaphore calls. */
|
||||||
|
pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) );
|
||||||
|
if( pxSecondSemaphoreParameters != NULL )
|
||||||
|
{
|
||||||
|
vSemaphoreCreateBinary( pxSecondSemaphoreParameters->xSemaphore );
|
||||||
|
|
||||||
|
if( pxSecondSemaphoreParameters->xSemaphore != NULL )
|
||||||
|
{
|
||||||
|
pxSecondSemaphoreParameters->pulSharedVariable = ( unsigned long * ) pvPortMalloc( sizeof( unsigned long ) );
|
||||||
|
*( pxSecondSemaphoreParameters->pulSharedVariable ) = semtstBLOCKING_EXPECTED_VALUE;
|
||||||
|
pxSecondSemaphoreParameters->xBlockTime = xBlockTime / portTICK_PERIOD_MS;
|
||||||
|
|
||||||
|
xTaskCreate( prvSemaphoreTest, "BlkSEM1", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
|
xTaskCreate( prvSemaphoreTest, "BlkSEM2", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSemaphoreTest( void *pvParameters )
|
||||||
|
{
|
||||||
|
xSemaphoreParameters *pxParameters;
|
||||||
|
volatile unsigned long *pulSharedVariable, ulExpectedValue;
|
||||||
|
unsigned long ulCounter;
|
||||||
|
short sError = pdFALSE, sCheckVariableToUse;
|
||||||
|
|
||||||
|
/* See which check variable to use. sNextCheckVariable is not semaphore
|
||||||
|
protected! */
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
sCheckVariableToUse = sNextCheckVariable;
|
||||||
|
sNextCheckVariable++;
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcSemaphoreTaskStart );
|
||||||
|
|
||||||
|
/* A structure is passed in as the parameter. This contains the shared
|
||||||
|
variable being guarded. */
|
||||||
|
pxParameters = ( xSemaphoreParameters * ) pvParameters;
|
||||||
|
pulSharedVariable = pxParameters->pulSharedVariable;
|
||||||
|
|
||||||
|
/* If we are blocking we use a much higher count to ensure loads of context
|
||||||
|
switches occur during the count. */
|
||||||
|
if( pxParameters->xBlockTime > ( TickType_t ) 0 )
|
||||||
|
{
|
||||||
|
ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ulExpectedValue = semtstNON_BLOCKING_EXPECTED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Try to obtain the semaphore. */
|
||||||
|
if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS )
|
||||||
|
{
|
||||||
|
/* We have the semaphore and so expect any other tasks using the
|
||||||
|
shared variable to have left it in the state we expect to find
|
||||||
|
it. */
|
||||||
|
if( *pulSharedVariable != ulExpectedValue )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcPollingSemaphoreTaskError );
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the variable, then count it back up to the expected value
|
||||||
|
before releasing the semaphore. Would expect a context switch or
|
||||||
|
two during this time. */
|
||||||
|
for( ulCounter = ( unsigned long ) 0; ulCounter <= ulExpectedValue; ulCounter++ )
|
||||||
|
{
|
||||||
|
*pulSharedVariable = ulCounter;
|
||||||
|
if( *pulSharedVariable != ulCounter )
|
||||||
|
{
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcPollingSemaphoreTaskError );
|
||||||
|
}
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the semaphore, and if no errors have occurred increment the check
|
||||||
|
variable. */
|
||||||
|
if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE )
|
||||||
|
{
|
||||||
|
vPrintDisplayMessage( &pcPollingSemaphoreTaskError );
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
if( sCheckVariableToUse < semtstNUM_TASKS )
|
||||||
|
{
|
||||||
|
( sCheckVariables[ sCheckVariableToUse ] )++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have a block time then we are running at a priority higher
|
||||||
|
than the idle priority. This task takes a long time to complete
|
||||||
|
a cycle (deliberately so to test the guarding) so will be starving
|
||||||
|
out lower priority tasks. Block for some time to allow give lower
|
||||||
|
priority tasks some processor time. */
|
||||||
|
vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( pxParameters->xBlockTime == ( TickType_t ) 0 )
|
||||||
|
{
|
||||||
|
/* We have not got the semaphore yet, so no point using the
|
||||||
|
processor. We are not blocking when attempting to obtain the
|
||||||
|
semaphore. */
|
||||||
|
taskYIELD();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running. */
|
||||||
|
portBASE_TYPE xAreSemaphoreTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
static short sLastCheckVariables[ semtstNUM_TASKS ] = { 0 };
|
||||||
|
portBASE_TYPE xTask, xReturn = pdTRUE;
|
||||||
|
|
||||||
|
for( xTask = 0; xTask < semtstNUM_TASKS; xTask++ )
|
||||||
|
{
|
||||||
|
if( sLastCheckVariables[ xTask ] == sCheckVariables[ xTask ] )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sLastCheckVariables[ xTask ] = sCheckVariables[ xTask ];
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,332 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,549 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,275 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,587 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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,324 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 "BlockQ.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 vStartBlockingQueueTasks( 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, "QConsB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL );
|
||||||
|
xTaskCreate( vBlockingQueueProducer, "QProdB4", 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;
|
||||||
|
|
||||||
|
pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
if( xQueueSend( 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;
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vBlockingQueueConsumer, pvParameters )
|
||||||
|
{
|
||||||
|
uint16_t usData, usExpectedValue = 0;
|
||||||
|
xBlockingQueueParameters *pxQueueParameters;
|
||||||
|
short sErrorEverOccurred = pdFALSE;
|
||||||
|
|
||||||
|
pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
if( xQueueReceive( 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
{
|
||||||
|
if( pxQueueParameters->xBlockTime == 0 )
|
||||||
|
{
|
||||||
|
taskYIELD();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running. */
|
||||||
|
BaseType_t xAreBlockingQueuesStillRunning( 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;
|
||||||
|
}
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,857 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests the extra queue functionality introduced in FreeRTOS.org V4.5.0 -
|
||||||
|
* including xQueueSendToFront(), xQueueSendToBack(), xQueuePeek() and
|
||||||
|
* mutex behaviour.
|
||||||
|
*
|
||||||
|
* See the comments above the prvSendFrontAndBackTest() and
|
||||||
|
* prvLowPriorityMutexTask() prototypes below for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "queue.h"
|
||||||
|
#include "semphr.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "GenQTest.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 )
|
||||||
|
|
||||||
|
#define genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ( 100 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests the behaviour of the xQueueSendToFront() and xQueueSendToBack()
|
||||||
|
* 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 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exercises the priority inheritance when a task takes two mutexes, returning
|
||||||
|
* them in a different order to which they were taken.
|
||||||
|
*/
|
||||||
|
static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exercises the priority inheritance when a task takes two mutexes, returning
|
||||||
|
* them in the same order in which they were taken.
|
||||||
|
*/
|
||||||
|
static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Task that receives an a mutex that is given from an interrupt - although
|
||||||
|
* generally mutexes should not be used given in interrupts (and definitely
|
||||||
|
* never taken in an interrupt) there are some circumstances when it may be
|
||||||
|
* desirable. NOTE: This function is not declared static to prevent compiler
|
||||||
|
* warnings being generated in demos where the function is declared but not
|
||||||
|
* used.
|
||||||
|
*/
|
||||||
|
void vInterruptMutexTask( void *pvParameters );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
||||||
|
detected in any of the tasks. */
|
||||||
|
static volatile 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;
|
||||||
|
|
||||||
|
/* A mutex which is given from an interrupt - although generally mutexes should
|
||||||
|
not be used given in interrupts (and definitely never taken in an interrupt)
|
||||||
|
there are some circumstances when it may be desirable. */
|
||||||
|
static SemaphoreHandle_t xISRMutex = NULL;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartGenericQueueTasks( UBaseType_t uxPriority )
|
||||||
|
{
|
||||||
|
QueueHandle_t xQueue;
|
||||||
|
SemaphoreHandle_t xMutex;
|
||||||
|
|
||||||
|
xISRMutex = xSemaphoreCreateMutex();
|
||||||
|
configASSERT( xISRMutex );
|
||||||
|
|
||||||
|
/* 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, "Gen_Queue_Test" );
|
||||||
|
|
||||||
|
/* 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, "GenQ", 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 mutexes 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, "Gen_Queue_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, "MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );
|
||||||
|
xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );
|
||||||
|
xTaskCreate( prvHighPriorityMutexTask, "MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );
|
||||||
|
|
||||||
|
/* Only when the windows simulator is being used - create the task that
|
||||||
|
receives a mutex from an interrupt. */
|
||||||
|
#ifdef _WINDOWS_
|
||||||
|
{
|
||||||
|
xTaskCreate( vInterruptMutexTask, "IntMu", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, NULL );
|
||||||
|
}
|
||||||
|
#endif /* __WINDOWS__ */
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
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 = "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. */
|
||||||
|
xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );
|
||||||
|
|
||||||
|
if( uxQueueMessagesWaiting( xQueue ) != 1 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xQueueReceive( 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK );
|
||||||
|
|
||||||
|
if( uxQueueMessagesWaiting( xQueue ) != 1 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xQueueReceive( 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++ )
|
||||||
|
{
|
||||||
|
xQueueSendToBack( 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;
|
||||||
|
xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK );
|
||||||
|
ulData = 0;
|
||||||
|
xQueueSendToFront( 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( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xQueueSendToBack( 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( xQueuePeek( 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( xQueueReceive( 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( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
ulData = 11;
|
||||||
|
if( xQueueSend( 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( xQueueSendToFront( 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( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xQueueSendToBack( 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( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ulData != ulData2 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxQueueMessagesWaiting( xQueue ) != 0 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulLoopCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )
|
||||||
|
{
|
||||||
|
/* Take the mutex. It should be available now. */
|
||||||
|
if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the guarded variable to a known start value. */
|
||||||
|
ulGuardedVariable = 0;
|
||||||
|
|
||||||
|
/* This task's 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 );
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Ensure the task is reporting its priority as blocked and not
|
||||||
|
suspended (as it would have done in versions up to V7.5.3). */
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
/* The priority of the high priority task should now have been inherited
|
||||||
|
as by now it will have attempted to get the mutex. */
|
||||||
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to set the priority of this task to the test priority -
|
||||||
|
between the idle priority and the medium/high test priorities, but the
|
||||||
|
actual priority 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 the
|
||||||
|
inherited priority of this task is above that of the medium priority
|
||||||
|
task. */
|
||||||
|
vTaskResume( xMediumPriorityMutexTask );
|
||||||
|
|
||||||
|
/* If the medium priority task did run then it will have incremented the
|
||||||
|
guarded variable. */
|
||||||
|
if( ulGuardedVariable != 0 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take the local mutex too, so two mutexes are now held. */
|
||||||
|
if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the semaphore is given back the priority of this task should not
|
||||||
|
yet be disinherited because the local mutex is still held. This is a
|
||||||
|
simplification to allow FreeRTOS to be integrated with middleware that
|
||||||
|
attempts to hold multiple mutexes without bloating the code with complex
|
||||||
|
algorithms. It is possible that the high priority mutex task will
|
||||||
|
execute as it shares a priority with this task. */
|
||||||
|
if( xSemaphoreGive( xMutex ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The guarded variable is only incremented by the medium priority task,
|
||||||
|
which still should not have executed as this task should remain at the
|
||||||
|
higher priority, ensure this is the case. */
|
||||||
|
if( ulGuardedVariable != 0 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now also give back the local mutex, taking the held count back to 0.
|
||||||
|
This time the priority of this task should be disinherited back to the
|
||||||
|
priority to which it was set while the mutex was held. This means
|
||||||
|
the medium priority task should execute and increment the guarded
|
||||||
|
variable. When this task next runs both the high and medium priority
|
||||||
|
tasks will have been suspended again. */
|
||||||
|
if( xSemaphoreGive( xLocalMutex ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check the guarded variable did indeed increment... */
|
||||||
|
if( ulGuardedVariable != 1 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... and that the priority of this task has been disinherited to
|
||||||
|
genqMUTEX_TEST_PRIORITY. */
|
||||||
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the priority of this task back to its original value, ready for
|
||||||
|
the next loop around this test. */
|
||||||
|
vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )
|
||||||
|
{
|
||||||
|
/* Take the mutex. It should be available now. */
|
||||||
|
if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the guarded variable to a known start value. */
|
||||||
|
ulGuardedVariable = 0;
|
||||||
|
|
||||||
|
/* This task's 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 );
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Ensure the task is reporting its priority as blocked and not
|
||||||
|
suspended (as it would have done in versions up to V7.5.3). */
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
/* The priority of the high priority task should now have been inherited
|
||||||
|
as by now it will have attempted to get the mutex. */
|
||||||
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now unsuspend the medium priority task. This should not run as the
|
||||||
|
inherited priority of this task is above that of the medium priority
|
||||||
|
task. */
|
||||||
|
vTaskResume( xMediumPriorityMutexTask );
|
||||||
|
|
||||||
|
/* If the medium priority task did run then it will have incremented the
|
||||||
|
guarded variable. */
|
||||||
|
if( ulGuardedVariable != 0 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take the local mutex too, so two mutexes are now held. */
|
||||||
|
if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the local semaphore is given back the priority of this task should
|
||||||
|
not yet be disinherited because the shared mutex is still held. This is a
|
||||||
|
simplification to allow FreeRTOS to be integrated with middleware that
|
||||||
|
attempts to hold multiple mutexes without bloating the code with complex
|
||||||
|
algorithms. It is possible that the high priority mutex task will
|
||||||
|
execute as it shares a priority with this task. */
|
||||||
|
if( xSemaphoreGive( xLocalMutex ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The guarded variable is only incremented by the medium priority task,
|
||||||
|
which still should not have executed as this task should remain at the
|
||||||
|
higher priority, ensure this is the case. */
|
||||||
|
if( ulGuardedVariable != 0 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now also give back the shared mutex, taking the held count back to 0.
|
||||||
|
This time the priority of this task should be disinherited back to the
|
||||||
|
priority at which it was created. This means the medium priority task
|
||||||
|
should execute and increment the guarded variable. When this task next runs
|
||||||
|
both the high and medium priority tasks will have been suspended again. */
|
||||||
|
if( xSemaphoreGive( xMutex ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check the guarded variable did indeed increment... */
|
||||||
|
if( ulGuardedVariable != 1 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... and that the priority of this task has been disinherited to
|
||||||
|
genqMUTEX_LOW_PRIORITY. */
|
||||||
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvLowPriorityMutexTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex;
|
||||||
|
|
||||||
|
#ifdef USE_STDIO
|
||||||
|
void vPrintDisplayMessage( const char * const * ppcMessageToSend );
|
||||||
|
|
||||||
|
const char * const pcTaskStartMsg = "Mutex with priority inheritance test started.\r\n";
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The local mutex is used to check the 'mutexs held' count. */
|
||||||
|
xLocalMutex = xSemaphoreCreateMutex();
|
||||||
|
configASSERT( xLocalMutex );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* The first tests exercise the priority inheritance when two mutexes
|
||||||
|
are taken then returned in a different order to which they were
|
||||||
|
taken. */
|
||||||
|
prvTakeTwoMutexesReturnInDifferentOrder( xMutex, xLocalMutex );
|
||||||
|
|
||||||
|
/* Just to show this task is still running. */
|
||||||
|
ulLoopCounter2++;
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The second tests exercise the priority inheritance when two mutexes
|
||||||
|
are taken then returned in the same order in which they were taken. */
|
||||||
|
prvTakeTwoMutexesReturnInSameOrder( xMutex, xLocalMutex );
|
||||||
|
|
||||||
|
/* Just to show this task is 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;
|
||||||
|
|
||||||
|
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( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the mutex is eventually obtained it is just given back before
|
||||||
|
returning to suspend ready for the next cycle. */
|
||||||
|
if( xSemaphoreGive( xMutex ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* NOTE: This function is not declared static to prevent compiler warnings in
|
||||||
|
demos where the function is declared but not used. */
|
||||||
|
void vInterruptMutexTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS );
|
||||||
|
volatile uint32_t ulLoops = 0;
|
||||||
|
|
||||||
|
/* Just to avoid compiler warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Has to wait longer than the time between gives to make sure it
|
||||||
|
should definitely have received the mutex. */
|
||||||
|
if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ulLoops++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vMutexISRInteractionTest( void )
|
||||||
|
{
|
||||||
|
static TickType_t xLastGiveTime = 0;
|
||||||
|
TickType_t xTimeNow;
|
||||||
|
|
||||||
|
xTimeNow = xTaskGetTickCountFromISR();
|
||||||
|
if( ( xTimeNow - xLastGiveTime ) >= pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ) )
|
||||||
|
{
|
||||||
|
configASSERT( xISRMutex );
|
||||||
|
xSemaphoreGiveFromISR( xISRMutex, NULL );
|
||||||
|
xLastGiveTime = xTimeNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running. */
|
||||||
|
BaseType_t xAreGenericQueueTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
static uint32_t ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;
|
||||||
|
|
||||||
|
/* If the demo task is still running then we expect the loop counters 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 ( BaseType_t ) !xErrorDetected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,760 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 defines one of the more complex set of demo/test tasks. They are
|
||||||
|
* designed to stress test the queue implementation though pseudo simultaneous
|
||||||
|
* multiple reads and multiple writes from both tasks of varying priority and
|
||||||
|
* interrupts. The interrupts are prioritised such to ensure that nesting
|
||||||
|
* occurs (for those ports that support it).
|
||||||
|
*
|
||||||
|
* The test ensures that, while being accessed from three tasks and two
|
||||||
|
* interrupts, all the data sent to the queues is also received from
|
||||||
|
* the same queue, and that no duplicate items are either sent or received.
|
||||||
|
* The tests also ensure that a low priority task is never able to successfully
|
||||||
|
* read from or write to a queue when a task of higher priority is attempting
|
||||||
|
* the same operation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* SafeRTOS includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "queue.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Demo app includes. */
|
||||||
|
#include "IntQueue.h"
|
||||||
|
#include "IntQueueTimer.h"
|
||||||
|
|
||||||
|
#if( INCLUDE_eTaskGetState != 1 )
|
||||||
|
#error INCLUDE_eTaskGetState must be set to 1 in FreeRTOSConfig.h to use this demo file.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Priorities used by test tasks. */
|
||||||
|
#ifndef intqHIGHER_PRIORITY
|
||||||
|
#define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 2 )
|
||||||
|
#endif
|
||||||
|
#define intqLOWER_PRIORITY ( tskIDLE_PRIORITY )
|
||||||
|
|
||||||
|
/* The number of values to send/receive before checking that all values were
|
||||||
|
processed as expected. */
|
||||||
|
#define intqNUM_VALUES_TO_LOG ( 200 )
|
||||||
|
#define intqSHORT_DELAY ( 140 )
|
||||||
|
|
||||||
|
/* The value by which the value being sent to or received from a queue should
|
||||||
|
increment past intqNUM_VALUES_TO_LOG before we check that all values have been
|
||||||
|
sent/received correctly. This is done to ensure that all tasks and interrupts
|
||||||
|
accessing the queue have completed their accesses with the
|
||||||
|
intqNUM_VALUES_TO_LOG range. */
|
||||||
|
#define intqVALUE_OVERRUN ( 50 )
|
||||||
|
|
||||||
|
/* The delay used by the polling task. A short delay is used for code
|
||||||
|
coverage. */
|
||||||
|
#define intqONE_TICK_DELAY ( 1 )
|
||||||
|
|
||||||
|
/* Each task and interrupt is given a unique identifier. This value is used to
|
||||||
|
identify which task sent or received each value. The identifier is also used
|
||||||
|
to distinguish between two tasks that are running the same task function. */
|
||||||
|
#define intqHIGH_PRIORITY_TASK1 ( ( UBaseType_t ) 1 )
|
||||||
|
#define intqHIGH_PRIORITY_TASK2 ( ( UBaseType_t ) 2 )
|
||||||
|
#define intqLOW_PRIORITY_TASK ( ( UBaseType_t ) 3 )
|
||||||
|
#define intqFIRST_INTERRUPT ( ( UBaseType_t ) 4 )
|
||||||
|
#define intqSECOND_INTERRUPT ( ( UBaseType_t ) 5 )
|
||||||
|
#define intqQUEUE_LENGTH ( ( UBaseType_t ) 10 )
|
||||||
|
|
||||||
|
/* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received
|
||||||
|
from each queue by each task, otherwise an error is detected. */
|
||||||
|
#define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 )
|
||||||
|
|
||||||
|
/* Send the next value to the queue that is normally empty. This is called
|
||||||
|
from within the interrupts. */
|
||||||
|
#define timerNORMALLY_EMPTY_TX() \
|
||||||
|
if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \
|
||||||
|
{ \
|
||||||
|
UBaseType_t uxSavedInterruptStatus; \
|
||||||
|
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
|
||||||
|
{ \
|
||||||
|
uxValueForNormallyEmptyQueue++; \
|
||||||
|
xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken ); \
|
||||||
|
} \
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
/* Send the next value to the queue that is normally full. This is called
|
||||||
|
from within the interrupts. */
|
||||||
|
#define timerNORMALLY_FULL_TX() \
|
||||||
|
if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \
|
||||||
|
{ \
|
||||||
|
UBaseType_t uxSavedInterruptStatus; \
|
||||||
|
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
|
||||||
|
{ \
|
||||||
|
uxValueForNormallyFullQueue++; \
|
||||||
|
xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken ); \
|
||||||
|
} \
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
/* Receive a value from the normally empty queue. This is called from within
|
||||||
|
an interrupt. */
|
||||||
|
#define timerNORMALLY_EMPTY_RX() \
|
||||||
|
if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \
|
||||||
|
{ \
|
||||||
|
prvQueueAccessLogError( __LINE__ ); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Receive a value from the normally full queue. This is called from within
|
||||||
|
an interrupt. */
|
||||||
|
#define timerNORMALLY_FULL_RX() \
|
||||||
|
if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \
|
||||||
|
{ \
|
||||||
|
prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT ); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* The two queues used by the test. */
|
||||||
|
static QueueHandle_t xNormallyEmptyQueue, xNormallyFullQueue;
|
||||||
|
|
||||||
|
/* Variables used to detect a stall in one of the tasks. */
|
||||||
|
static UBaseType_t uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
|
||||||
|
|
||||||
|
/* Any unexpected behaviour sets xErrorStatus to fail and log the line that
|
||||||
|
caused the error in xErrorLine. */
|
||||||
|
static BaseType_t xErrorStatus = pdPASS;
|
||||||
|
static volatile UBaseType_t xErrorLine = ( UBaseType_t ) 0;
|
||||||
|
|
||||||
|
/* Used for sequencing between tasks. */
|
||||||
|
static BaseType_t xWasSuspended = pdFALSE;
|
||||||
|
|
||||||
|
/* The values that are sent to the queues. An incremented value is sent each
|
||||||
|
time to each queue. */
|
||||||
|
volatile UBaseType_t uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
|
||||||
|
|
||||||
|
/* A handle to some of the tasks is required so they can be suspended/resumed. */
|
||||||
|
TaskHandle_t xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;
|
||||||
|
|
||||||
|
/* When a value is received in a queue the value is ticked off in the array
|
||||||
|
the array position of the value is set to a the identifier of the task or
|
||||||
|
interrupt that accessed the queue. This way missing or duplicate values can be
|
||||||
|
detected. */
|
||||||
|
static uint8_t ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
|
||||||
|
static uint8_t ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
|
||||||
|
|
||||||
|
/* The test tasks themselves. */
|
||||||
|
static void prvLowerPriorityNormallyEmptyTask( void *pvParameters );
|
||||||
|
static void prvLowerPriorityNormallyFullTask( void *pvParameters );
|
||||||
|
static void prvHigherPriorityNormallyEmptyTask( void *pvParameters );
|
||||||
|
static void prv1stHigherPriorityNormallyFullTask( void *pvParameters );
|
||||||
|
static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters );
|
||||||
|
|
||||||
|
/* Used to mark the positions within the ucNormallyEmptyReceivedValues and
|
||||||
|
ucNormallyFullReceivedValues arrays, while checking for duplicates. */
|
||||||
|
static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource );
|
||||||
|
static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource );
|
||||||
|
|
||||||
|
/* Logs the line on which an error occurred. */
|
||||||
|
static void prvQueueAccessLogError( UBaseType_t uxLine );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartInterruptQueueTasks( void )
|
||||||
|
{
|
||||||
|
/* Start the test tasks. */
|
||||||
|
xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 );
|
||||||
|
xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 );
|
||||||
|
xTaskCreate( prvLowerPriorityNormallyEmptyTask, "L1QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
|
||||||
|
xTaskCreate( prv1stHigherPriorityNormallyFullTask, "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 );
|
||||||
|
xTaskCreate( prv2ndHigherPriorityNormallyFullTask, "H2QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 );
|
||||||
|
xTaskCreate( prvLowerPriorityNormallyFullTask, "L2QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
|
||||||
|
|
||||||
|
/* Create the queues that are accessed by multiple tasks and multiple
|
||||||
|
interrupts. */
|
||||||
|
xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
|
||||||
|
xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_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( xNormallyFullQueue, "NormallyFull" );
|
||||||
|
vQueueAddToRegistry( xNormallyEmptyQueue, "NormallyEmpty" );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource )
|
||||||
|
{
|
||||||
|
if( uxValue < intqNUM_VALUES_TO_LOG )
|
||||||
|
{
|
||||||
|
/* We don't expect to receive the same value twice, so if the value
|
||||||
|
has already been marked as received an error has occurred. */
|
||||||
|
if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )
|
||||||
|
{
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Log that this value has been received. */
|
||||||
|
ucNormallyFullReceivedValues[ uxValue ] = ( uint8_t ) uxSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource )
|
||||||
|
{
|
||||||
|
if( uxValue < intqNUM_VALUES_TO_LOG )
|
||||||
|
{
|
||||||
|
/* We don't expect to receive the same value twice, so if the value
|
||||||
|
has already been marked as received an error has occurred. */
|
||||||
|
if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )
|
||||||
|
{
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Log that this value has been received. */
|
||||||
|
ucNormallyEmptyReceivedValues[ uxValue ] = ( uint8_t ) uxSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvQueueAccessLogError( UBaseType_t uxLine )
|
||||||
|
{
|
||||||
|
/* Latch the line number that caused the error. */
|
||||||
|
xErrorLine = uxLine;
|
||||||
|
xErrorStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvHigherPriorityNormallyEmptyTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErrorCount2 = 0;
|
||||||
|
|
||||||
|
/* The timer should not be started until after the scheduler has started.
|
||||||
|
More than one task is running this code so we check the parameter value
|
||||||
|
to determine which task should start the timer. */
|
||||||
|
if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
|
||||||
|
{
|
||||||
|
vInitialiseTimerForIntQueueTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Block waiting to receive a value from the normally empty queue.
|
||||||
|
Interrupts will write to the queue so we should receive a value. */
|
||||||
|
if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Note which value was received so we can check all expected
|
||||||
|
values are received and no values are duplicated. */
|
||||||
|
prvRecordValue_NormallyEmpty( uxRxed, ( UBaseType_t ) pvParameters );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure the other task running this code gets a chance to execute. */
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
|
||||||
|
{
|
||||||
|
/* Have we received all the expected values? */
|
||||||
|
if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
|
||||||
|
{
|
||||||
|
vTaskSuspend( xHighPriorityNormallyEmptyTask2 );
|
||||||
|
|
||||||
|
uxTask1 = 0;
|
||||||
|
uxTask2 = 0;
|
||||||
|
uxInterrupts = 0;
|
||||||
|
|
||||||
|
/* Loop through the array, checking that both tasks have
|
||||||
|
placed values into the array, and that no values are missing.
|
||||||
|
Start at 1 as we expect position 0 to be unused. */
|
||||||
|
for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
|
||||||
|
{
|
||||||
|
if( ucNormallyEmptyReceivedValues[ ux ] == 0 )
|
||||||
|
{
|
||||||
|
/* A value is missing. */
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 )
|
||||||
|
{
|
||||||
|
/* Value was placed into the array by task 1. */
|
||||||
|
uxTask1++;
|
||||||
|
}
|
||||||
|
else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 )
|
||||||
|
{
|
||||||
|
/* Value was placed into the array by task 2. */
|
||||||
|
uxTask2++;
|
||||||
|
}
|
||||||
|
else if( ucNormallyEmptyReceivedValues[ ux ] == intqSECOND_INTERRUPT )
|
||||||
|
{
|
||||||
|
uxInterrupts++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT )
|
||||||
|
{
|
||||||
|
/* Only task 2 seemed to log any values. */
|
||||||
|
uxErrorCount1++;
|
||||||
|
if( uxErrorCount1 > 2 )
|
||||||
|
{
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uxErrorCount1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT )
|
||||||
|
{
|
||||||
|
/* Only task 1 seemed to log any values. */
|
||||||
|
uxErrorCount2++;
|
||||||
|
if( uxErrorCount2 > 2 )
|
||||||
|
{
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uxErrorCount2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxInterrupts == 0 )
|
||||||
|
{
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the array again, ready to start a new cycle. */
|
||||||
|
memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) );
|
||||||
|
|
||||||
|
uxHighPriorityLoops1++;
|
||||||
|
uxValueForNormallyEmptyQueue = 0;
|
||||||
|
|
||||||
|
/* Suspend ourselves, allowing the lower priority task to
|
||||||
|
actually receive something from the queue. Until now it
|
||||||
|
will have been prevented from doing so by the higher
|
||||||
|
priority tasks. The lower priority task will resume us
|
||||||
|
if it receives something. We will then resume the other
|
||||||
|
higher priority task. */
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
vTaskResume( xHighPriorityNormallyEmptyTask2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvLowerPriorityNormallyEmptyTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
UBaseType_t uxValue, uxRxed;
|
||||||
|
|
||||||
|
/* The parameters are not being used so avoid compiler warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) != errQUEUE_EMPTY )
|
||||||
|
{
|
||||||
|
/* A value should only be obtained when the high priority task is
|
||||||
|
suspended. */
|
||||||
|
if( eTaskGetState( xHighPriorityNormallyEmptyTask1 ) != eSuspended )
|
||||||
|
{
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK );
|
||||||
|
|
||||||
|
/* Wake the higher priority task again. */
|
||||||
|
vTaskResume( xHighPriorityNormallyEmptyTask1 );
|
||||||
|
uxLowPriorityLoops1++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Raise our priority while we send so we can preempt the higher
|
||||||
|
priority task, and ensure we get the Tx value into the queue. */
|
||||||
|
vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
|
||||||
|
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
uxValueForNormallyEmptyQueue++;
|
||||||
|
uxValue = uxValueForNormallyEmptyQueue;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
|
||||||
|
if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prv1stHigherPriorityNormallyFullTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
UBaseType_t uxValueToTx, ux, uxInterrupts;
|
||||||
|
|
||||||
|
/* The parameters are not being used so avoid compiler warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Make sure the queue starts full or near full. >> 1 as there are two
|
||||||
|
high priority tasks. */
|
||||||
|
for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
|
||||||
|
{
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
uxValueForNormallyFullQueue++;
|
||||||
|
uxValueToTx = uxValueForNormallyFullQueue;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
|
||||||
|
xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
uxValueForNormallyFullQueue++;
|
||||||
|
uxValueToTx = uxValueForNormallyFullQueue;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
|
||||||
|
if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* intqHIGH_PRIORITY_TASK2 is never suspended so we would not
|
||||||
|
expect it to ever time out. */
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow the other task running this code to run. */
|
||||||
|
taskYIELD();
|
||||||
|
|
||||||
|
/* Have all the expected values been sent to the queue? */
|
||||||
|
if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
|
||||||
|
{
|
||||||
|
/* Make sure the other high priority task completes its send of
|
||||||
|
any values below intqNUM_VALUE_TO_LOG. */
|
||||||
|
vTaskDelay( intqSHORT_DELAY );
|
||||||
|
|
||||||
|
vTaskSuspend( xHighPriorityNormallyFullTask2 );
|
||||||
|
|
||||||
|
if( xWasSuspended == pdTRUE )
|
||||||
|
{
|
||||||
|
/* We would have expected the other high priority task to have
|
||||||
|
set this back to false by now. */
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the suspended flag so an error is not logged if the other
|
||||||
|
task recognises a time out when it is unsuspended. */
|
||||||
|
xWasSuspended = pdTRUE;
|
||||||
|
|
||||||
|
/* Check interrupts are also sending. */
|
||||||
|
uxInterrupts = 0U;
|
||||||
|
|
||||||
|
/* Start at 1 as we expect position 0 to be unused. */
|
||||||
|
for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
|
||||||
|
{
|
||||||
|
if( ucNormallyFullReceivedValues[ ux ] == 0 )
|
||||||
|
{
|
||||||
|
/* A value was missing. */
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
else if( ucNormallyFullReceivedValues[ ux ] == intqSECOND_INTERRUPT )
|
||||||
|
{
|
||||||
|
uxInterrupts++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxInterrupts == 0 )
|
||||||
|
{
|
||||||
|
/* No writes from interrupts were found. Are interrupts
|
||||||
|
actually running? */
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the array ready for the next cycle. */
|
||||||
|
memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) );
|
||||||
|
|
||||||
|
uxHighPriorityLoops2++;
|
||||||
|
uxValueForNormallyFullQueue = 0;
|
||||||
|
|
||||||
|
/* Suspend ourselves, allowing the lower priority task to
|
||||||
|
actually receive something from the queue. Until now it
|
||||||
|
will have been prevented from doing so by the higher
|
||||||
|
priority tasks. The lower priority task will resume us
|
||||||
|
if it receives something. We will then resume the other
|
||||||
|
higher priority task. */
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
vTaskResume( xHighPriorityNormallyFullTask2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
UBaseType_t uxValueToTx, ux;
|
||||||
|
|
||||||
|
/* The parameters are not being used so avoid compiler warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Make sure the queue starts full or near full. >> 1 as there are two
|
||||||
|
high priority tasks. */
|
||||||
|
for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
|
||||||
|
{
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
uxValueForNormallyFullQueue++;
|
||||||
|
uxValueToTx = uxValueForNormallyFullQueue;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
|
||||||
|
xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
uxValueForNormallyFullQueue++;
|
||||||
|
uxValueToTx = uxValueForNormallyFullQueue;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
|
||||||
|
if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
if( xWasSuspended != pdTRUE )
|
||||||
|
{
|
||||||
|
/* It is ok to time out if the task has been suspended. */
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xWasSuspended = pdFALSE;
|
||||||
|
|
||||||
|
taskYIELD();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvLowerPriorityNormallyFullTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
UBaseType_t uxValue, uxTxed = 9999;
|
||||||
|
|
||||||
|
/* The parameters are not being used so avoid compiler warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
if( xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) != errQUEUE_FULL )
|
||||||
|
{
|
||||||
|
/* Should only succeed when the higher priority task is suspended */
|
||||||
|
if( eTaskGetState( xHighPriorityNormallyFullTask1 ) != eSuspended )
|
||||||
|
{
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskResume( xHighPriorityNormallyFullTask1 );
|
||||||
|
uxLowPriorityLoops2++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Raise our priority while we receive so we can preempt the higher
|
||||||
|
priority task, and ensure we get the value from the queue. */
|
||||||
|
vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
|
||||||
|
|
||||||
|
if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prvRecordValue_NormallyFull( uxValue, intqLOW_PRIORITY_TASK );
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskPrioritySet( NULL, intqLOWER_PRIORITY );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xFirstTimerHandler( void )
|
||||||
|
{
|
||||||
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
UBaseType_t uxRxedValue;
|
||||||
|
static UBaseType_t uxNextOperation = 0;
|
||||||
|
|
||||||
|
/* Called from a timer interrupt. Perform various read and write
|
||||||
|
accesses on the queues. */
|
||||||
|
|
||||||
|
uxNextOperation++;
|
||||||
|
|
||||||
|
if( uxNextOperation & ( UBaseType_t ) 0x01 )
|
||||||
|
{
|
||||||
|
timerNORMALLY_EMPTY_TX();
|
||||||
|
timerNORMALLY_EMPTY_TX();
|
||||||
|
timerNORMALLY_EMPTY_TX();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timerNORMALLY_FULL_RX();
|
||||||
|
timerNORMALLY_FULL_RX();
|
||||||
|
timerNORMALLY_FULL_RX();
|
||||||
|
}
|
||||||
|
|
||||||
|
return xHigherPriorityTaskWoken;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xSecondTimerHandler( void )
|
||||||
|
{
|
||||||
|
UBaseType_t uxRxedValue;
|
||||||
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
static UBaseType_t uxNextOperation = 0;
|
||||||
|
|
||||||
|
/* Called from a timer interrupt. Perform various read and write
|
||||||
|
accesses on the queues. */
|
||||||
|
|
||||||
|
uxNextOperation++;
|
||||||
|
|
||||||
|
if( uxNextOperation & ( UBaseType_t ) 0x01 )
|
||||||
|
{
|
||||||
|
timerNORMALLY_EMPTY_TX();
|
||||||
|
timerNORMALLY_EMPTY_TX();
|
||||||
|
|
||||||
|
timerNORMALLY_EMPTY_RX();
|
||||||
|
timerNORMALLY_EMPTY_RX();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timerNORMALLY_FULL_RX();
|
||||||
|
timerNORMALLY_FULL_TX();
|
||||||
|
timerNORMALLY_FULL_TX();
|
||||||
|
timerNORMALLY_FULL_TX();
|
||||||
|
timerNORMALLY_FULL_TX();
|
||||||
|
}
|
||||||
|
|
||||||
|
return xHigherPriorityTaskWoken;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
BaseType_t xAreIntQueueTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
static UBaseType_t uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;
|
||||||
|
|
||||||
|
/* xErrorStatus can be set outside of this function. This function just
|
||||||
|
checks that all the tasks are still cycling. */
|
||||||
|
|
||||||
|
if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )
|
||||||
|
{
|
||||||
|
/* The high priority 1 task has stalled. */
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
uxLastHighPriorityLoops1 = uxHighPriorityLoops1;
|
||||||
|
|
||||||
|
if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 )
|
||||||
|
{
|
||||||
|
/* The high priority 2 task has stalled. */
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
uxLastHighPriorityLoops2 = uxHighPriorityLoops2;
|
||||||
|
|
||||||
|
if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 )
|
||||||
|
{
|
||||||
|
/* The low priority 1 task has stalled. */
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
uxLastLowPriorityLoops1 = uxLowPriorityLoops1;
|
||||||
|
|
||||||
|
if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 )
|
||||||
|
{
|
||||||
|
/* The low priority 2 task has stalled. */
|
||||||
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
uxLastLowPriorityLoops2 = uxLowPriorityLoops2;
|
||||||
|
|
||||||
|
return xErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,258 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 version of PollQ. c is for use on systems that have limited stack
|
||||||
|
* space and no display facilities. The complete version can be found in
|
||||||
|
* the Demo/Common/Full directory.
|
||||||
|
*
|
||||||
|
* 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 "PollQ.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 vStartPolledQueueTasks( 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, "Poll_Test_Queue" );
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
for( xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++ )
|
||||||
|
{
|
||||||
|
/* Send an incrementing number on the queue without blocking. */
|
||||||
|
if( xQueueSend( *( ( 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;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Loop until the queue is empty. */
|
||||||
|
while( uxQueueMessagesWaiting( *( ( QueueHandle_t * ) pvParameters ) ) )
|
||||||
|
{
|
||||||
|
if( xQueueReceive( *( ( 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 xArePollingQueuesStillRunning( 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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,474 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests the behaviour when data is peeked from a queue when there are
|
||||||
|
* multiple tasks blocked on the queue.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "queue.h"
|
||||||
|
#include "semphr.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "QPeek.h"
|
||||||
|
|
||||||
|
#define qpeekQUEUE_LENGTH ( 5 )
|
||||||
|
#define qpeekNO_BLOCK ( 0 )
|
||||||
|
#define qpeekSHORT_DELAY ( 10 )
|
||||||
|
|
||||||
|
#define qpeekLOW_PRIORITY ( tskIDLE_PRIORITY + 0 )
|
||||||
|
#define qpeekMEDIUM_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||||
|
#define qpeekHIGH_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||||
|
#define qpeekHIGHEST_PRIORITY ( tskIDLE_PRIORITY + 3 )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following three tasks are used to demonstrate the peeking behaviour.
|
||||||
|
* Each task is given a different priority to demonstrate the order in which
|
||||||
|
* tasks are woken as data is peeked from a queue.
|
||||||
|
*/
|
||||||
|
static void prvLowPriorityPeekTask( void *pvParameters );
|
||||||
|
static void prvMediumPriorityPeekTask( void *pvParameters );
|
||||||
|
static void prvHighPriorityPeekTask( void *pvParameters );
|
||||||
|
static void prvHighestPriorityPeekTask( void *pvParameters );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
||||||
|
detected in any of the tasks. */
|
||||||
|
static volatile BaseType_t xErrorDetected = pdFALSE;
|
||||||
|
|
||||||
|
/* Counter that is 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;
|
||||||
|
|
||||||
|
/* Handles to the test tasks. */
|
||||||
|
TaskHandle_t xMediumPriorityTask, xHighPriorityTask, xHighestPriorityTask;
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartQueuePeekTasks( void )
|
||||||
|
{
|
||||||
|
QueueHandle_t xQueue;
|
||||||
|
|
||||||
|
/* Create the queue that we are going to use for the test/demo. */
|
||||||
|
xQueue = xQueueCreate( qpeekQUEUE_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, "QPeek_Test_Queue" );
|
||||||
|
|
||||||
|
/* Create the demo tasks 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( prvLowPriorityPeekTask, "PeekL", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekLOW_PRIORITY, NULL );
|
||||||
|
xTaskCreate( prvMediumPriorityPeekTask, "PeekM", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekMEDIUM_PRIORITY, &xMediumPriorityTask );
|
||||||
|
xTaskCreate( prvHighPriorityPeekTask, "PeekH1", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGH_PRIORITY, &xHighPriorityTask );
|
||||||
|
xTaskCreate( prvHighestPriorityPeekTask, "PeekH2", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGHEST_PRIORITY, &xHighestPriorityTask );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvHighestPriorityPeekTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters;
|
||||||
|
uint32_t ulValue;
|
||||||
|
|
||||||
|
#ifdef USE_STDIO
|
||||||
|
{
|
||||||
|
void vPrintDisplayMessage( const char * const * ppcMessageToSend );
|
||||||
|
|
||||||
|
const char * const pcTaskStartMsg = "Queue peek test started.\r\n";
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Try peeking from the queue. The queue should be empty so we will
|
||||||
|
block, allowing the high priority task to execute. */
|
||||||
|
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* We expected to have received something by the time we unblock. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When we reach here the high and medium priority tasks should still
|
||||||
|
be blocked on the queue. We unblocked because the low priority task
|
||||||
|
wrote a value to the queue, which we should have peeked. Peeking the
|
||||||
|
data (rather than receiving it) will leave the data on the queue, so
|
||||||
|
the high priority task should then have also been unblocked, but not
|
||||||
|
yet executed. */
|
||||||
|
if( ulValue != 0x11223344 )
|
||||||
|
{
|
||||||
|
/* We did not receive the expected value. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxQueueMessagesWaiting( xQueue ) != 1 )
|
||||||
|
{
|
||||||
|
/* The message should have been left on the queue. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we are going to actually receive the data, so when the high
|
||||||
|
priority task runs it will find the queue empty and return to the
|
||||||
|
blocked state. */
|
||||||
|
ulValue = 0;
|
||||||
|
if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* We expected to receive the value. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ulValue != 0x11223344 )
|
||||||
|
{
|
||||||
|
/* We did not receive the expected value - which should have been
|
||||||
|
the same value as was peeked. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we will block again as the queue is once more empty. The low
|
||||||
|
priority task can then execute again. */
|
||||||
|
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* We expected to have received something by the time we unblock. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When we get here the low priority task should have again written to the
|
||||||
|
queue. */
|
||||||
|
if( ulValue != 0x01234567 )
|
||||||
|
{
|
||||||
|
/* We did not receive the expected value. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxQueueMessagesWaiting( xQueue ) != 1 )
|
||||||
|
{
|
||||||
|
/* The message should have been left on the queue. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We only peeked the data, so suspending ourselves now should enable
|
||||||
|
the high priority task to also peek the data. The high priority task
|
||||||
|
will have been unblocked when we peeked the data as we left the data
|
||||||
|
in the queue. */
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* This time we are going to do the same as the above test, but the
|
||||||
|
high priority task is going to receive the data, rather than peek it.
|
||||||
|
This means that the medium priority task should never peek the value. */
|
||||||
|
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ulValue != 0xaabbaabb )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvHighPriorityPeekTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters;
|
||||||
|
uint32_t ulValue;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Try peeking from the queue. The queue should be empty so we will
|
||||||
|
block, allowing the medium priority task to execute. Both the high
|
||||||
|
and highest priority tasks will then be blocked on the queue. */
|
||||||
|
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* We expected to have received something by the time we unblock. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When we get here the highest priority task should have peeked the data
|
||||||
|
(unblocking this task) then suspended (allowing this task to also peek
|
||||||
|
the data). */
|
||||||
|
if( ulValue != 0x01234567 )
|
||||||
|
{
|
||||||
|
/* We did not receive the expected value. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxQueueMessagesWaiting( xQueue ) != 1 )
|
||||||
|
{
|
||||||
|
/* The message should have been left on the queue. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We only peeked the data, so suspending ourselves now should enable
|
||||||
|
the medium priority task to also peek the data. The medium priority task
|
||||||
|
will have been unblocked when we peeked the data as we left the data
|
||||||
|
in the queue. */
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
|
|
||||||
|
/* This time we are going actually receive the value, so the medium
|
||||||
|
priority task will never peek the data - we removed it from the queue. */
|
||||||
|
if( xQueueReceive( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ulValue != 0xaabbaabb )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvMediumPriorityPeekTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters;
|
||||||
|
uint32_t ulValue;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Try peeking from the queue. The queue should be empty so we will
|
||||||
|
block, allowing the low priority task to execute. The highest, high
|
||||||
|
and medium priority tasks will then all be blocked on the queue. */
|
||||||
|
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* We expected to have received something by the time we unblock. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When we get here the high priority task should have peeked the data
|
||||||
|
(unblocking this task) then suspended (allowing this task to also peek
|
||||||
|
the data). */
|
||||||
|
if( ulValue != 0x01234567 )
|
||||||
|
{
|
||||||
|
/* We did not receive the expected value. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxQueueMessagesWaiting( xQueue ) != 1 )
|
||||||
|
{
|
||||||
|
/* The message should have been left on the queue. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just so we know the test is still running. */
|
||||||
|
ulLoopCounter++;
|
||||||
|
|
||||||
|
/* Now we can suspend ourselves so the low priority task can execute
|
||||||
|
again. */
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvLowPriorityPeekTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters;
|
||||||
|
uint32_t ulValue;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Write some data to the queue. This should unblock the highest
|
||||||
|
priority task that is waiting to peek data from the queue. */
|
||||||
|
ulValue = 0x11223344;
|
||||||
|
if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* We were expecting the queue to be empty so we should not of
|
||||||
|
had a problem writing to the queue. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* By the time we get here the data should have been removed from
|
||||||
|
the queue. */
|
||||||
|
if( uxQueueMessagesWaiting( xQueue ) != 0 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write another value to the queue, again waking the highest priority
|
||||||
|
task that is blocked on the queue. */
|
||||||
|
ulValue = 0x01234567;
|
||||||
|
if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* We were expecting the queue to be empty so we should not of
|
||||||
|
had a problem writing to the queue. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* All the other tasks should now have successfully peeked the data.
|
||||||
|
The data is still in the queue so we should be able to receive it. */
|
||||||
|
ulValue = 0;
|
||||||
|
if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* We expected to receive the data. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ulValue != 0x01234567 )
|
||||||
|
{
|
||||||
|
/* We did not receive the expected value. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lets just delay a while as this is an intensive test as we don't
|
||||||
|
want to starve other tests of processing time. */
|
||||||
|
vTaskDelay( qpeekSHORT_DELAY );
|
||||||
|
|
||||||
|
/* Unsuspend the other tasks so we can repeat the test - this time
|
||||||
|
however not all the other tasks will peek the data as the high
|
||||||
|
priority task is actually going to remove it from the queue. Send
|
||||||
|
to front is used just to be different. As the queue is empty it
|
||||||
|
makes no difference to the result. */
|
||||||
|
vTaskResume( xMediumPriorityTask );
|
||||||
|
vTaskResume( xHighPriorityTask );
|
||||||
|
vTaskResume( xHighestPriorityTask );
|
||||||
|
|
||||||
|
#if( configUSE_PREEMPTION == 0 )
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ulValue = 0xaabbaabb;
|
||||||
|
if( xQueueSendToFront( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* We were expecting the queue to be empty so we should not of
|
||||||
|
had a problem writing to the queue. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This time we should find that the queue is empty. The high priority
|
||||||
|
task actually removed the data rather than just peeking it. */
|
||||||
|
if( xQueuePeek( xQueue, &ulValue, qpeekNO_BLOCK ) != errQUEUE_EMPTY )
|
||||||
|
{
|
||||||
|
/* We expected to receive the data. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unsuspend the highest and high priority tasks so we can go back
|
||||||
|
and repeat the whole thing. The medium priority task should not be
|
||||||
|
suspended as it was not able to peek the data in this last case. */
|
||||||
|
vTaskResume( xHighPriorityTask );
|
||||||
|
vTaskResume( xHighestPriorityTask );
|
||||||
|
|
||||||
|
/* Lets just delay a while as this is an intensive test as we don't
|
||||||
|
want to starve other tests of processing time. */
|
||||||
|
vTaskDelay( qpeekSHORT_DELAY );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running. */
|
||||||
|
BaseType_t xAreQueuePeekTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
static uint32_t ulLastLoopCounter = 0;
|
||||||
|
|
||||||
|
/* If the demo task is still running then we expect the loopcounter to
|
||||||
|
have incremented since this function was last called. */
|
||||||
|
if( ulLastLoopCounter == ulLoopCounter )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulLastLoopCounter = ulLoopCounter;
|
||||||
|
|
||||||
|
/* Errors detected in the task itself will have latched xErrorDetected
|
||||||
|
to true. */
|
||||||
|
|
||||||
|
return ( BaseType_t ) !xErrorDetected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,268 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Basic task to demonstrate the xQueueOverwrite() function. See the comments
|
||||||
|
* in the function itself.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "QueueOverwrite.h"
|
||||||
|
|
||||||
|
/* A block time of 0 just means "don't block". */
|
||||||
|
#define qoDONT_BLOCK 0
|
||||||
|
|
||||||
|
/* Number of times to overwrite the value in the queue. */
|
||||||
|
#define qoLOOPS 5
|
||||||
|
|
||||||
|
/* The task that uses the queue. */
|
||||||
|
static void prvQueueOverwriteTask( void *pvParameters );
|
||||||
|
|
||||||
|
/* Variable that is incremented on each loop of prvQueueOverwriteTask() provided
|
||||||
|
prvQueueOverwriteTask() has not found any errors. */
|
||||||
|
static uint32_t ulLoopCounter = 0;
|
||||||
|
|
||||||
|
/* Set to pdFALSE if an error is discovered by the
|
||||||
|
vQueueOverwritePeriodicISRDemo() function. */
|
||||||
|
static BaseType_t xISRTestStatus = pdPASS;
|
||||||
|
|
||||||
|
/* The queue that is accessed from the ISR. The queue accessed by the task is
|
||||||
|
created inside the task itself. */
|
||||||
|
static QueueHandle_t xISRQueue = NULL;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartQueueOverwriteTask( UBaseType_t uxPriority )
|
||||||
|
{
|
||||||
|
const UBaseType_t uxQueueLength = 1;
|
||||||
|
|
||||||
|
/* Create the queue used by the ISR. xQueueOverwriteFromISR() should only
|
||||||
|
be used on queues that have a length of 1. */
|
||||||
|
xISRQueue = xQueueCreate( uxQueueLength, ( UBaseType_t ) sizeof( uint32_t ) );
|
||||||
|
|
||||||
|
/* Create the test task. The queue used by the test task is created inside
|
||||||
|
the task itself. */
|
||||||
|
xTaskCreate( prvQueueOverwriteTask, "QOver", configMINIMAL_STACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvQueueOverwriteTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
QueueHandle_t xTaskQueue;
|
||||||
|
const UBaseType_t uxQueueLength = 1;
|
||||||
|
uint32_t ulValue, ulStatus = pdPASS, x;
|
||||||
|
|
||||||
|
/* The parameter is not used. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Create the queue. xQueueOverwrite() should only be used on queues that
|
||||||
|
have a length of 1. */
|
||||||
|
xTaskQueue = xQueueCreate( uxQueueLength, ( UBaseType_t ) sizeof( uint32_t ) );
|
||||||
|
configASSERT( xTaskQueue );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* The queue is empty. Writing to the queue then reading from the queue
|
||||||
|
should return the item written. */
|
||||||
|
ulValue = 10;
|
||||||
|
xQueueOverwrite( xTaskQueue, &ulValue );
|
||||||
|
|
||||||
|
ulValue = 0;
|
||||||
|
xQueueReceive( xTaskQueue, &ulValue, qoDONT_BLOCK );
|
||||||
|
|
||||||
|
if( ulValue != 10 )
|
||||||
|
{
|
||||||
|
ulStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now try writing to the queue several times. Each time the value
|
||||||
|
in the queue should get overwritten. */
|
||||||
|
for( x = 0; x < qoLOOPS; x++ )
|
||||||
|
{
|
||||||
|
/* Write to the queue. */
|
||||||
|
xQueueOverwrite( xTaskQueue, &x );
|
||||||
|
|
||||||
|
/* Check the value in the queue is that written, even though the
|
||||||
|
queue was not necessarily empty. */
|
||||||
|
xQueuePeek( xTaskQueue, &ulValue, qoDONT_BLOCK );
|
||||||
|
if( ulValue != x )
|
||||||
|
{
|
||||||
|
ulStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There should always be one item in the queue. */
|
||||||
|
if( uxQueueMessagesWaiting( xTaskQueue ) != uxQueueLength )
|
||||||
|
{
|
||||||
|
ulStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Empty the queue again. */
|
||||||
|
xQueueReceive( xTaskQueue, &ulValue, qoDONT_BLOCK );
|
||||||
|
|
||||||
|
if( uxQueueMessagesWaiting( xTaskQueue ) != 0 )
|
||||||
|
{
|
||||||
|
ulStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ulStatus != pdFAIL )
|
||||||
|
{
|
||||||
|
/* Increment a counter to show this task is still running without
|
||||||
|
error. */
|
||||||
|
ulLoopCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if( configUSE_PREEMPTION == 0 )
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xIsQueueOverwriteTaskStillRunning( void )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
if( xISRTestStatus != pdPASS )
|
||||||
|
{
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
else if( ulLoopCounter > 0 )
|
||||||
|
{
|
||||||
|
xReturn = pdPASS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The task has either stalled of discovered an error. */
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulLoopCounter = 0;
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vQueueOverwritePeriodicISRDemo( void )
|
||||||
|
{
|
||||||
|
static uint32_t ulCallCount = 0;
|
||||||
|
const uint32_t ulTx1 = 10UL, ulTx2 = 20UL, ulNumberOfSwitchCases = 3UL;
|
||||||
|
uint32_t ulRx;
|
||||||
|
|
||||||
|
/* This function should be called from an interrupt, such as the tick hook
|
||||||
|
function vApplicationTickHook(). */
|
||||||
|
|
||||||
|
configASSERT( xISRQueue );
|
||||||
|
|
||||||
|
switch( ulCallCount )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
/* The queue is empty. Write ulTx1 to the queue. In this demo the
|
||||||
|
last parameter is not used because there are no tasks blocked on
|
||||||
|
this queue. */
|
||||||
|
xQueueOverwriteFromISR( xISRQueue, &ulTx1, NULL );
|
||||||
|
|
||||||
|
/* Peek the queue to check it holds the expected value. */
|
||||||
|
xQueuePeekFromISR( xISRQueue, &ulRx );
|
||||||
|
if( ulRx != ulTx1 )
|
||||||
|
{
|
||||||
|
xISRTestStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
/* The queue already holds ulTx1. Overwrite the value in the queue
|
||||||
|
with ulTx2. */
|
||||||
|
xQueueOverwriteFromISR( xISRQueue, &ulTx2, NULL );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
/* Read from the queue to empty the queue again. The value read
|
||||||
|
should be ulTx2. */
|
||||||
|
xQueueReceiveFromISR( xISRQueue, &ulRx, NULL );
|
||||||
|
|
||||||
|
if( ulRx != ulTx2 )
|
||||||
|
{
|
||||||
|
xISRTestStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Run the next case in the switch statement above next time this function
|
||||||
|
is called. */
|
||||||
|
ulCallCount++;
|
||||||
|
|
||||||
|
if( ulCallCount >= ulNumberOfSwitchCases )
|
||||||
|
{
|
||||||
|
/* Go back to the start. */
|
||||||
|
ulCallCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,715 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests the use of queue sets.
|
||||||
|
*
|
||||||
|
* A receive task creates a number of queues and adds them to a queue set before
|
||||||
|
* blocking on the queue set receive. A transmit task and (optionally) an
|
||||||
|
* interrupt repeatedly unblocks the receive task by sending messages to the
|
||||||
|
* queues in a pseudo random order. The receive task removes the messages from
|
||||||
|
* the queues and flags an error if the received message does not match that
|
||||||
|
* expected. The task sends values in the range 0 to
|
||||||
|
* queuesetINITIAL_ISR_TX_VALUE, and the ISR sends value in the range
|
||||||
|
* queuesetINITIAL_ISR_TX_VALUE to ULONG_MAX.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Standard includes. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
/* Kernel includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
/* Demo includes. */
|
||||||
|
#include "QueueSet.h"
|
||||||
|
|
||||||
|
/* The number of queues that are created and added to the queue set. */
|
||||||
|
#define queuesetNUM_QUEUES_IN_SET 3
|
||||||
|
|
||||||
|
/* The length of each created queue. */
|
||||||
|
#define queuesetQUEUE_LENGTH 3
|
||||||
|
|
||||||
|
/* Block times used in this demo. A block time or 0 means "don't block". */
|
||||||
|
#define queuesetSHORT_DELAY 200
|
||||||
|
#define queuesetDONT_BLOCK 0
|
||||||
|
|
||||||
|
/* Messages are sent in incrementing order from both a task and an interrupt.
|
||||||
|
The task sends values in the range 0 to 0xfffe, and the interrupt sends values
|
||||||
|
in the range of 0xffff to ULONG_MAX. */
|
||||||
|
#define queuesetINITIAL_ISR_TX_VALUE 0xffffUL
|
||||||
|
|
||||||
|
/* The priorities used in this demo. */
|
||||||
|
#define queuesetLOW_PRIORITY ( tskIDLE_PRIORITY )
|
||||||
|
#define queuesetMEDIUM_PRIORITY ( queuesetLOW_PRIORITY + 1 )
|
||||||
|
|
||||||
|
/* For test purposes the priority of the sending task is changed after every
|
||||||
|
queuesetPRIORITY_CHANGE_LOOPS number of values are sent to a queue. */
|
||||||
|
#define queuesetPRIORITY_CHANGE_LOOPS ( ( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH ) * 2 )
|
||||||
|
|
||||||
|
/* The ISR sends to the queue every queuesetISR_TX_PERIOD ticks. */
|
||||||
|
#define queuesetISR_TX_PERIOD ( 100UL )
|
||||||
|
|
||||||
|
/* A delay inserted when the Tx task changes its priority to be above the idle
|
||||||
|
task priority to ensure the idle priority tasks get some CPU time before the
|
||||||
|
next iteration of the queue set Tx task. */
|
||||||
|
#define queuesetTX_LOOP_DELAY ( 200 / portTICK_PERIOD_MS )
|
||||||
|
|
||||||
|
/* The allowable maximum deviation between a received value and the expected
|
||||||
|
received value. A deviation will occur when data is received from a queue
|
||||||
|
inside an ISR in between a task receiving from a queue and the task checking
|
||||||
|
the received value. */
|
||||||
|
#define queuesetALLOWABLE_RX_DEVIATION 3
|
||||||
|
|
||||||
|
/* Ignore values that are at the boundaries of allowable values to make the
|
||||||
|
testing of limits easier (don't have to deal with wrapping values). */
|
||||||
|
#define queuesetIGNORED_BOUNDARY ( queuesetALLOWABLE_RX_DEVIATION * 2 )
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
eEqualPriority = 0, /* Tx and Rx tasks have the same priority. */
|
||||||
|
eTxHigherPriority, /* The priority of the Tx task is above that of the Rx task. */
|
||||||
|
eTxLowerPriority /* The priority of the Tx task is below that of the Rx task. */
|
||||||
|
} eRelativePriorities;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The task that periodically sends to the queue set.
|
||||||
|
*/
|
||||||
|
static void prvQueueSetSendingTask( void *pvParameters );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The task that reads from the queue set.
|
||||||
|
*/
|
||||||
|
static void prvQueueSetReceivingTask( void *pvParameters );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the value received from a queue is the expected value. Some values
|
||||||
|
* originate from the send task, some values originate from the ISR, with the
|
||||||
|
* range of the value being used to distinguish between the two message
|
||||||
|
* sources.
|
||||||
|
*/
|
||||||
|
static void prvCheckReceivedValue( uint32_t ulReceived );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For purposes of test coverage, functions that read from and write to a
|
||||||
|
* queue set from an ISR respectively.
|
||||||
|
*/
|
||||||
|
static void prvReceiveFromQueueInSetFromISR( void );
|
||||||
|
static void prvSendToQueueInSetFromISR( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the queues and add them to a queue set before resuming the Tx
|
||||||
|
* task.
|
||||||
|
*/
|
||||||
|
static void prvSetupTest( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checks a value received from a queue falls within the range of expected
|
||||||
|
* values.
|
||||||
|
*/
|
||||||
|
static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived, uint32_t ulExpectedReceived );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Increase test coverage by occasionally change the priorities of the two tasks
|
||||||
|
* relative to each other. */
|
||||||
|
static void prvChangeRelativePriorities( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local pseudo random number seed and return functions. Used to avoid calls
|
||||||
|
* to the standard library.
|
||||||
|
*/
|
||||||
|
static uint32_t prvRand( void );
|
||||||
|
static void prvSRand( uint32_t ulSeed );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* The queues that are added to the set. */
|
||||||
|
static QueueHandle_t xQueues[ queuesetNUM_QUEUES_IN_SET ] = { 0 };
|
||||||
|
|
||||||
|
/* Counts how many times each queue in the set is used to ensure all the
|
||||||
|
queues are used. */
|
||||||
|
static uint32_t ulQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 };
|
||||||
|
|
||||||
|
/* The handle of the queue set to which the queues are added. */
|
||||||
|
static QueueSetHandle_t xQueueSet;
|
||||||
|
|
||||||
|
/* If the prvQueueSetReceivingTask() task has not detected any errors then
|
||||||
|
it increments ulCycleCounter on each iteration.
|
||||||
|
xAreQueueSetTasksStillRunning() returns pdPASS if the value of
|
||||||
|
ulCycleCounter has changed between consecutive calls, and pdFALSE if
|
||||||
|
ulCycleCounter has stopped incrementing (indicating an error condition). */
|
||||||
|
static volatile uint32_t ulCycleCounter = 0UL;
|
||||||
|
|
||||||
|
/* Set to pdFAIL if an error is detected by any queue set task.
|
||||||
|
ulCycleCounter will only be incremented if xQueueSetTasksSatus equals pdPASS. */
|
||||||
|
static volatile BaseType_t xQueueSetTasksStatus = pdPASS;
|
||||||
|
|
||||||
|
/* Just a flag to let the function that writes to a queue from an ISR know that
|
||||||
|
the queues are setup and can be used. */
|
||||||
|
static volatile BaseType_t xSetupComplete = pdFALSE;
|
||||||
|
|
||||||
|
/* The value sent to the queue from the ISR is file scope so the
|
||||||
|
xAreQueeuSetTasksStillRunning() function can check it is incrementing as
|
||||||
|
expected. */
|
||||||
|
static volatile uint32_t ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE;
|
||||||
|
|
||||||
|
/* Used by the pseudo random number generator. */
|
||||||
|
static uint32_t ulNextRand = 0;
|
||||||
|
|
||||||
|
/* The task handles are stored so their priorities can be changed. */
|
||||||
|
TaskHandle_t xQueueSetSendingTask, xQueueSetReceivingTask;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartQueueSetTasks( void )
|
||||||
|
{
|
||||||
|
/* Create the tasks. */
|
||||||
|
xTaskCreate( prvQueueSetSendingTask, "SetTx", configMINIMAL_STACK_SIZE, NULL, queuesetMEDIUM_PRIORITY, &xQueueSetSendingTask );
|
||||||
|
xTaskCreate( prvQueueSetReceivingTask, "SetRx", configMINIMAL_STACK_SIZE, ( void * ) xQueueSetSendingTask, queuesetMEDIUM_PRIORITY, &xQueueSetReceivingTask );
|
||||||
|
|
||||||
|
/* It is important that the sending task does not attempt to write to a
|
||||||
|
queue before the queue has been created. It is therefore placed into the
|
||||||
|
suspended state before the scheduler has started. It is resumed by the
|
||||||
|
receiving task after the receiving task has created the queues and added the
|
||||||
|
queues to the queue set. */
|
||||||
|
vTaskSuspend( xQueueSetSendingTask );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xAreQueueSetTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
static uint32_t ulLastCycleCounter, ulLastISRTxValue = 0;
|
||||||
|
static uint32_t ulLastQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 };
|
||||||
|
BaseType_t xReturn = pdPASS, x;
|
||||||
|
|
||||||
|
if( ulLastCycleCounter == ulCycleCounter )
|
||||||
|
{
|
||||||
|
/* The cycle counter is no longer being incremented. Either one of the
|
||||||
|
tasks is stalled or an error has been detected. */
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulLastCycleCounter = ulCycleCounter;
|
||||||
|
|
||||||
|
/* Ensure that all the queues in the set have been used. This ensures the
|
||||||
|
test is working as intended and guards against the rand() in the Tx task
|
||||||
|
missing some values. */
|
||||||
|
for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )
|
||||||
|
{
|
||||||
|
if( ulLastQueueUsedCounter[ x ] == ulQueueUsedCounter[ x ] )
|
||||||
|
{
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulLastQueueUsedCounter[ x ] = ulQueueUsedCounter[ x ];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the global status flag. */
|
||||||
|
if( xQueueSetTasksStatus != pdPASS )
|
||||||
|
{
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the ISR is still sending values to the queues too. */
|
||||||
|
if( ulISRTxValue == ulLastISRTxValue )
|
||||||
|
{
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ulLastISRTxValue = ulISRTxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvQueueSetSendingTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
uint32_t ulTaskTxValue = 0, ulQueueToWriteTo;
|
||||||
|
QueueHandle_t xQueueInUse;
|
||||||
|
|
||||||
|
/* Remove compiler warning about the unused parameter. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Seed mini pseudo random number generator. */
|
||||||
|
prvSRand( ( uint32_t ) &ulTaskTxValue );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Generate the index for the queue to which a value is to be sent. */
|
||||||
|
ulQueueToWriteTo = prvRand() % queuesetNUM_QUEUES_IN_SET;
|
||||||
|
xQueueInUse = xQueues[ ulQueueToWriteTo ];
|
||||||
|
|
||||||
|
/* Note which index is being written to to ensure all the queues are
|
||||||
|
used. */
|
||||||
|
( ulQueueUsedCounter[ ulQueueToWriteTo ] )++;
|
||||||
|
|
||||||
|
/* Send to the queue to unblock the task that is waiting for data to
|
||||||
|
arrive on a queue within the queue set to which this queue belongs. */
|
||||||
|
if( xQueueSendToBack( xQueueInUse, &ulTaskTxValue, portMAX_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* The send should always pass as an infinite block time was
|
||||||
|
used. */
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if( configUSE_PREEMPTION == 0 )
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ulTaskTxValue++;
|
||||||
|
|
||||||
|
/* If the Tx value has reached the range used by the ISR then set it
|
||||||
|
back to 0. */
|
||||||
|
if( ulTaskTxValue == queuesetINITIAL_ISR_TX_VALUE )
|
||||||
|
{
|
||||||
|
ulTaskTxValue = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increase test coverage by occasionally change the priorities of the
|
||||||
|
two tasks relative to each other. */
|
||||||
|
prvChangeRelativePriorities();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvChangeRelativePriorities( void )
|
||||||
|
{
|
||||||
|
static UBaseType_t ulLoops = 0;
|
||||||
|
static eRelativePriorities ePriorities = eEqualPriority;
|
||||||
|
|
||||||
|
/* Occasionally change the task priority relative to the priority of
|
||||||
|
the receiving task. */
|
||||||
|
ulLoops++;
|
||||||
|
if( ulLoops >= queuesetPRIORITY_CHANGE_LOOPS )
|
||||||
|
{
|
||||||
|
ulLoops = 0;
|
||||||
|
|
||||||
|
switch( ePriorities )
|
||||||
|
{
|
||||||
|
case eEqualPriority:
|
||||||
|
/* Both tasks are running with medium priority. Now lower the
|
||||||
|
priority of the receiving task so the Tx task has the higher
|
||||||
|
relative priority. */
|
||||||
|
vTaskPrioritySet( xQueueSetReceivingTask, queuesetLOW_PRIORITY );
|
||||||
|
ePriorities = eTxHigherPriority;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eTxHigherPriority:
|
||||||
|
/* The Tx task is running with a higher priority than the Rx
|
||||||
|
task. Switch the priorities around so the Rx task has the
|
||||||
|
higher relative priority. */
|
||||||
|
vTaskPrioritySet( xQueueSetReceivingTask, queuesetMEDIUM_PRIORITY );
|
||||||
|
vTaskPrioritySet( xQueueSetSendingTask, queuesetLOW_PRIORITY );
|
||||||
|
ePriorities = eTxLowerPriority;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eTxLowerPriority:
|
||||||
|
/* The Tx task is running with a lower priority than the Rx
|
||||||
|
task. Make the priorities equal again. */
|
||||||
|
vTaskPrioritySet( xQueueSetSendingTask, queuesetMEDIUM_PRIORITY );
|
||||||
|
ePriorities = eEqualPriority;
|
||||||
|
|
||||||
|
/* When both tasks are using a non-idle priority the queue set
|
||||||
|
tasks will starve idle priority tasks of execution time - so
|
||||||
|
relax a bit before the next iteration to minimise the impact. */
|
||||||
|
vTaskDelay( queuesetTX_LOOP_DELAY );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvQueueSetReceivingTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
uint32_t ulReceived;
|
||||||
|
QueueHandle_t xActivatedQueue;
|
||||||
|
|
||||||
|
/* Remove compiler warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Create the queues and add them to the queue set before resuming the Tx
|
||||||
|
task. */
|
||||||
|
prvSetupTest();
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Wait for a message to arrive on one of the queues in the set. */
|
||||||
|
xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY );
|
||||||
|
configASSERT( xActivatedQueue );
|
||||||
|
|
||||||
|
if( xActivatedQueue == NULL )
|
||||||
|
{
|
||||||
|
/* This should not happen as an infinite delay was used. */
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Reading from the queue should pass with a zero block time as
|
||||||
|
this task will only run when something has been posted to a task
|
||||||
|
in the queue set. */
|
||||||
|
if( xQueueReceive( xActivatedQueue, &ulReceived, queuesetDONT_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure the value received was the value expected. This function
|
||||||
|
manipulates file scope data and is also called from an ISR, hence
|
||||||
|
the critical section. */
|
||||||
|
taskENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
prvCheckReceivedValue( ulReceived );
|
||||||
|
}
|
||||||
|
taskEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xQueueSetTasksStatus == pdPASS )
|
||||||
|
{
|
||||||
|
ulCycleCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vQueueSetAccessQueueSetFromISR( void )
|
||||||
|
{
|
||||||
|
static uint32_t ulCallCount = 0;
|
||||||
|
|
||||||
|
/* xSetupComplete is set to pdTRUE when the queues have been created and
|
||||||
|
are available for use. */
|
||||||
|
if( xSetupComplete == pdTRUE )
|
||||||
|
{
|
||||||
|
/* It is intended that this function is called from the tick hook
|
||||||
|
function, so each call is one tick period apart. */
|
||||||
|
ulCallCount++;
|
||||||
|
if( ulCallCount > queuesetISR_TX_PERIOD )
|
||||||
|
{
|
||||||
|
ulCallCount = 0;
|
||||||
|
|
||||||
|
/* First attempt to read from the queue set. */
|
||||||
|
prvReceiveFromQueueInSetFromISR();
|
||||||
|
|
||||||
|
/* Then write to the queue set. */
|
||||||
|
prvSendToQueueInSetFromISR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvCheckReceivedValue( uint32_t ulReceived )
|
||||||
|
{
|
||||||
|
static uint32_t ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;
|
||||||
|
|
||||||
|
/* Values are received in tasks and interrupts. It is likely that the
|
||||||
|
receiving task will sometimes get preempted by the receiving interrupt
|
||||||
|
between reading a value from the queue and calling this function. When
|
||||||
|
that happens, if the receiving interrupt calls this function the values
|
||||||
|
will get passed into this function slightly out of order. For that
|
||||||
|
reason the value passed in is tested against a small range of expected
|
||||||
|
values, rather than a single absolute value. To make the range testing
|
||||||
|
easier values in the range limits are ignored. */
|
||||||
|
|
||||||
|
/* If the received value is equal to or greater than
|
||||||
|
queuesetINITIAL_ISR_TX_VALUE then it was sent by an ISR. */
|
||||||
|
if( ulReceived >= queuesetINITIAL_ISR_TX_VALUE )
|
||||||
|
{
|
||||||
|
/* The value was sent from the ISR. */
|
||||||
|
if( ( ulReceived - queuesetINITIAL_ISR_TX_VALUE ) < queuesetIGNORED_BOUNDARY )
|
||||||
|
{
|
||||||
|
/* The value received is at the lower limit of the expected range.
|
||||||
|
Don't test it and expect to receive one higher next time. */
|
||||||
|
}
|
||||||
|
else if( ( ULONG_MAX - ulReceived ) <= queuesetIGNORED_BOUNDARY )
|
||||||
|
{
|
||||||
|
/* The value received is at the higher limit of the expected range.
|
||||||
|
Don't test it and expect to wrap soon. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Check the value against its expected value range. */
|
||||||
|
if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromISR ) != pdPASS )
|
||||||
|
{
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configASSERT( xQueueSetTasksStatus );
|
||||||
|
|
||||||
|
/* It is expected to receive an incrementing number. */
|
||||||
|
ulExpectedReceivedFromISR++;
|
||||||
|
if( ulExpectedReceivedFromISR == 0 )
|
||||||
|
{
|
||||||
|
ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The value was sent from the Tx task. */
|
||||||
|
if( ulReceived < queuesetIGNORED_BOUNDARY )
|
||||||
|
{
|
||||||
|
/* The value received is at the lower limit of the expected range.
|
||||||
|
Don't test it, and expect to receive one higher next time. */
|
||||||
|
}
|
||||||
|
else if( ( ( queuesetINITIAL_ISR_TX_VALUE - 1 ) - ulReceived ) <= queuesetIGNORED_BOUNDARY )
|
||||||
|
{
|
||||||
|
/* The value received is at the higher limit of the expected range.
|
||||||
|
Don't test it and expect to wrap soon. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Check the value against its expected value range. */
|
||||||
|
if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromTask ) != pdPASS )
|
||||||
|
{
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configASSERT( xQueueSetTasksStatus );
|
||||||
|
|
||||||
|
/* It is expected to receive an incrementing number. */
|
||||||
|
ulExpectedReceivedFromTask++;
|
||||||
|
if( ulExpectedReceivedFromTask >= queuesetINITIAL_ISR_TX_VALUE )
|
||||||
|
{
|
||||||
|
ulExpectedReceivedFromTask = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived, uint32_t ulExpectedReceived )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn = pdPASS;
|
||||||
|
|
||||||
|
if( ulReceived > ulExpectedReceived )
|
||||||
|
{
|
||||||
|
configASSERT( ( ulReceived - ulExpectedReceived ) <= queuesetALLOWABLE_RX_DEVIATION );
|
||||||
|
if( ( ulReceived - ulExpectedReceived ) > queuesetALLOWABLE_RX_DEVIATION )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configASSERT( ( ulExpectedReceived - ulReceived ) <= queuesetALLOWABLE_RX_DEVIATION );
|
||||||
|
if( ( ulExpectedReceived - ulReceived ) > queuesetALLOWABLE_RX_DEVIATION )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvReceiveFromQueueInSetFromISR( void )
|
||||||
|
{
|
||||||
|
QueueSetMemberHandle_t xActivatedQueue;
|
||||||
|
uint32_t ulReceived;
|
||||||
|
|
||||||
|
/* See if any of the queues in the set contain data. */
|
||||||
|
xActivatedQueue = xQueueSelectFromSetFromISR( xQueueSet );
|
||||||
|
|
||||||
|
if( xActivatedQueue != NULL )
|
||||||
|
{
|
||||||
|
/* Reading from the queue for test purposes only. */
|
||||||
|
if( xQueueReceiveFromISR( xActivatedQueue, &ulReceived, NULL ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* Data should have been available as the handle was returned from
|
||||||
|
xQueueSelectFromSetFromISR(). */
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure the value received was the value expected. */
|
||||||
|
prvCheckReceivedValue( ulReceived );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSendToQueueInSetFromISR( void )
|
||||||
|
{
|
||||||
|
static BaseType_t xQueueToWriteTo = 0;
|
||||||
|
|
||||||
|
if( xQueueSendFromISR( xQueues[ xQueueToWriteTo ], ( void * ) &ulISRTxValue, NULL ) == pdPASS )
|
||||||
|
{
|
||||||
|
ulISRTxValue++;
|
||||||
|
|
||||||
|
/* If the Tx value has wrapped then set it back to its
|
||||||
|
initial value. */
|
||||||
|
if( ulISRTxValue == 0UL )
|
||||||
|
{
|
||||||
|
ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use a different queue next time. */
|
||||||
|
xQueueToWriteTo++;
|
||||||
|
if( xQueueToWriteTo >= queuesetNUM_QUEUES_IN_SET )
|
||||||
|
{
|
||||||
|
xQueueToWriteTo = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSetupTest( void )
|
||||||
|
{
|
||||||
|
BaseType_t x;
|
||||||
|
uint32_t ulValueToSend = 0;
|
||||||
|
|
||||||
|
/* Ensure the queues are created and the queue set configured before the
|
||||||
|
sending task is unsuspended.
|
||||||
|
|
||||||
|
First Create the queue set such that it will be able to hold a message for
|
||||||
|
every space in every queue in the set. */
|
||||||
|
xQueueSet = xQueueCreateSet( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH );
|
||||||
|
|
||||||
|
for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )
|
||||||
|
{
|
||||||
|
/* Create the queue and add it to the set. The queue is just holding
|
||||||
|
uint32_t value. */
|
||||||
|
xQueues[ x ] = xQueueCreate( queuesetQUEUE_LENGTH, sizeof( uint32_t ) );
|
||||||
|
configASSERT( xQueues[ x ] );
|
||||||
|
if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdPASS )
|
||||||
|
{
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The queue has now been added to the queue set and cannot be added to
|
||||||
|
another. */
|
||||||
|
if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdFAIL )
|
||||||
|
{
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to remove a queue from a queue set it does not belong
|
||||||
|
to (NULL being passed as the queue set in this case). */
|
||||||
|
if( xQueueRemoveFromSet( xQueues[ 0 ], NULL ) != pdFAIL )
|
||||||
|
{
|
||||||
|
/* It is not possible to successfully remove a queue from a queue
|
||||||
|
set it does not belong to. */
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to remove a queue from the queue set it does belong to. */
|
||||||
|
if( xQueueRemoveFromSet( xQueues[ 0 ], xQueueSet ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* It should be possible to remove the queue from the queue set it
|
||||||
|
does belong to. */
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add an item to the queue before attempting to add it back into the
|
||||||
|
set. */
|
||||||
|
xQueueSend( xQueues[ 0 ], ( void * ) &ulValueToSend, 0 );
|
||||||
|
if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdFAIL )
|
||||||
|
{
|
||||||
|
/* Should not be able to add a non-empty queue to a set. */
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the item from the queue before adding the queue back into the
|
||||||
|
set so the dynamic tests can begin. */
|
||||||
|
xQueueReceive( xQueues[ 0 ], &ulValueToSend, 0 );
|
||||||
|
if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* If the queue was successfully removed from the queue set then it
|
||||||
|
should be possible to add it back in again. */
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The task that sends to the queues is not running yet, so attempting to
|
||||||
|
read from the queue set should fail. */
|
||||||
|
if( xQueueSelectFromSet( xQueueSet, queuesetSHORT_DELAY ) != NULL )
|
||||||
|
{
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resume the task that writes to the queues. */
|
||||||
|
vTaskResume( xQueueSetSendingTask );
|
||||||
|
|
||||||
|
/* Let the ISR access the queues also. */
|
||||||
|
xSetupComplete = pdTRUE;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static uint32_t prvRand( void )
|
||||||
|
{
|
||||||
|
ulNextRand = ( ulNextRand * 1103515245UL ) + 12345UL;
|
||||||
|
return ( ulNextRand / 65536UL ) % 32768UL;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSRand( uint32_t ulSeed )
|
||||||
|
{
|
||||||
|
ulNextRand = ulSeed;
|
||||||
|
}
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,505 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 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 "blocktim.h"
|
||||||
|
|
||||||
|
/* Task priorities. Allow these to be overridden. */
|
||||||
|
#ifndef bktPRIMARY_PRIORITY
|
||||||
|
#define bktPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef bktSECONDARY_PRIORITY
|
||||||
|
#define bktSECONDARY_PRIORITY ( configMAX_PRIORITIES - 4 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Task behaviour. */
|
||||||
|
#define bktQUEUE_LENGTH ( 5 )
|
||||||
|
#define bktSHORT_WAIT ( ( ( TickType_t ) 20 ) / portTICK_PERIOD_MS )
|
||||||
|
#define bktPRIMARY_BLOCK_TIME ( 10 )
|
||||||
|
#define bktALLOWABLE_MARGIN ( 15 )
|
||||||
|
#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 volatile BaseType_t xPrimaryCycles = 0, xSecondaryCycles = 0;
|
||||||
|
static volatile 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 vCreateBlockTimeTasks( 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, "Block_Time_Queue" );
|
||||||
|
|
||||||
|
/* Create the two test tasks. */
|
||||||
|
xTaskCreate( vPrimaryBlockTimeTestTask, "BTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );
|
||||||
|
xTaskCreate( vSecondaryBlockTimeTestTask, "BTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vPrimaryBlockTimeTestTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
BaseType_t xItem, xData;
|
||||||
|
TickType_t xTimeWhenBlocking;
|
||||||
|
TickType_t xTimeToBlock, xBlockedTime;
|
||||||
|
|
||||||
|
( 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 = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem );
|
||||||
|
|
||||||
|
xTimeWhenBlocking = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* We should unblock after xTimeToBlock having not received
|
||||||
|
anything on the queue. */
|
||||||
|
if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* How long were we blocked for? */
|
||||||
|
xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
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( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem );
|
||||||
|
|
||||||
|
xTimeWhenBlocking = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* We should unblock after xTimeToBlock having not received
|
||||||
|
anything on the queue. */
|
||||||
|
if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* How long were we blocked for? */
|
||||||
|
xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
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( xQueueReceive( 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( xQueueSend( 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;
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
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( xQueueReceive( 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( xQueueSend( 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( xQueueReceive( 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;
|
||||||
|
|
||||||
|
( 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. */
|
||||||
|
xTimeWhenBlocking = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* We should unblock after bktTIME_TO_BLOCK having not sent
|
||||||
|
anything to the queue. */
|
||||||
|
xData = 0;
|
||||||
|
xRunIndicator = bktRUN_INDICATOR;
|
||||||
|
if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* How long were we inside the send function? */
|
||||||
|
xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
xTimeWhenBlocking = xTaskGetTickCount();
|
||||||
|
|
||||||
|
/* We should unblock after bktTIME_TO_BLOCK having not received
|
||||||
|
anything on the queue. */
|
||||||
|
xRunIndicator = bktRUN_INDICATOR;
|
||||||
|
if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
|
||||||
|
|
||||||
|
/* 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 xAreBlockTimeTestTasksStillRunning( 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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,303 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 version of comtest. c is for use on systems that have limited stack
|
||||||
|
* space and no display facilities. The complete version can be found in
|
||||||
|
* the Demo/Common/Full directory.
|
||||||
|
*
|
||||||
|
* Creates two tasks that operate on an interrupt driven serial port. A
|
||||||
|
* loopback connector should be used so that everything that is transmitted is
|
||||||
|
* also received. The serial port does not use any flow control. On a
|
||||||
|
* standard 9way 'D' connector pins two and three should be connected together.
|
||||||
|
*
|
||||||
|
* The first task posts a sequence of characters to the Tx queue, toggling an
|
||||||
|
* LED on each successful post. At the end of the sequence it sleeps for a
|
||||||
|
* pseudo-random period before resending the same sequence.
|
||||||
|
*
|
||||||
|
* The UART Tx end interrupt is enabled whenever data is available in the Tx
|
||||||
|
* queue. The Tx end ISR removes a single character from the Tx queue and
|
||||||
|
* passes it to the UART for transmission.
|
||||||
|
*
|
||||||
|
* The second task blocks on the Rx queue waiting for a character to become
|
||||||
|
* available. When the UART Rx end interrupt receives a character it places
|
||||||
|
* it in the Rx queue, waking the second task. The second task checks that the
|
||||||
|
* characters removed from the Rx queue form the same sequence as those posted
|
||||||
|
* to the Tx queue, and toggles an LED for each correct character.
|
||||||
|
*
|
||||||
|
* The receiving task is spawned with a higher priority than the transmitting
|
||||||
|
* task. The receiver will therefore wake every time a character is
|
||||||
|
* transmitted so neither the Tx or Rx queue should ever hold more than a few
|
||||||
|
* characters.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "serial.h"
|
||||||
|
#include "comtest.h"
|
||||||
|
#include "partest.h"
|
||||||
|
|
||||||
|
#define comSTACK_SIZE configMINIMAL_STACK_SIZE
|
||||||
|
#define comTX_LED_OFFSET ( 0 )
|
||||||
|
#define comRX_LED_OFFSET ( 1 )
|
||||||
|
#define comTOTAL_PERMISSIBLE_ERRORS ( 2 )
|
||||||
|
|
||||||
|
/* The Tx task will transmit the sequence of characters at a pseudo random
|
||||||
|
interval. This is the maximum and minimum block time between sends. */
|
||||||
|
#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x96 )
|
||||||
|
#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0x32 )
|
||||||
|
#define comOFFSET_TIME ( ( TickType_t ) 3 )
|
||||||
|
|
||||||
|
/* We should find that each character can be queued for Tx immediately and we
|
||||||
|
don't have to block to send. */
|
||||||
|
#define comNO_BLOCK ( ( TickType_t ) 0 )
|
||||||
|
|
||||||
|
/* The Rx task will block on the Rx queue for a long period. */
|
||||||
|
#define comRX_BLOCK_TIME ( ( TickType_t ) 0xffff )
|
||||||
|
|
||||||
|
/* The sequence transmitted is from comFIRST_BYTE to and including comLAST_BYTE. */
|
||||||
|
#define comFIRST_BYTE ( 'A' )
|
||||||
|
#define comLAST_BYTE ( 'X' )
|
||||||
|
|
||||||
|
#define comBUFFER_LEN ( ( UBaseType_t ) ( comLAST_BYTE - comFIRST_BYTE ) + ( UBaseType_t ) 1 )
|
||||||
|
#define comINITIAL_RX_COUNT_VALUE ( 0 )
|
||||||
|
|
||||||
|
/* Handle to the com port used by both tasks. */
|
||||||
|
static xComPortHandle xPort = NULL;
|
||||||
|
|
||||||
|
/* The transmit task as described at the top of the file. */
|
||||||
|
static portTASK_FUNCTION_PROTO( vComTxTask, pvParameters );
|
||||||
|
|
||||||
|
/* The receive task as described at the top of the file. */
|
||||||
|
static portTASK_FUNCTION_PROTO( vComRxTask, pvParameters );
|
||||||
|
|
||||||
|
/* The LED that should be toggled by the Rx and Tx tasks. The Rx task will
|
||||||
|
toggle LED ( uxBaseLED + comRX_LED_OFFSET). The Tx task will toggle LED
|
||||||
|
( uxBaseLED + comTX_LED_OFFSET ). */
|
||||||
|
static UBaseType_t uxBaseLED = 0;
|
||||||
|
|
||||||
|
/* Check variable used to ensure no error have occurred. The Rx task will
|
||||||
|
increment this variable after every successfully received sequence. If at any
|
||||||
|
time the sequence is incorrect the the variable will stop being incremented. */
|
||||||
|
static volatile UBaseType_t uxRxLoops = comINITIAL_RX_COUNT_VALUE;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vAltStartComTestTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED )
|
||||||
|
{
|
||||||
|
/* Initialise the com port then spawn the Rx and Tx tasks. */
|
||||||
|
uxBaseLED = uxLED;
|
||||||
|
xSerialPortInitMinimal( ulBaudRate, comBUFFER_LEN );
|
||||||
|
|
||||||
|
/* The Tx task is spawned with a lower priority than the Rx task. */
|
||||||
|
xTaskCreate( vComTxTask, "COMTx", comSTACK_SIZE, NULL, uxPriority - 1, ( TaskHandle_t * ) NULL );
|
||||||
|
xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vComTxTask, pvParameters )
|
||||||
|
{
|
||||||
|
char cByteToSend;
|
||||||
|
TickType_t xTimeToWait;
|
||||||
|
|
||||||
|
/* Just to stop compiler warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Simply transmit a sequence of characters from comFIRST_BYTE to
|
||||||
|
comLAST_BYTE. */
|
||||||
|
for( cByteToSend = comFIRST_BYTE; cByteToSend <= comLAST_BYTE; cByteToSend++ )
|
||||||
|
{
|
||||||
|
if( xSerialPutChar( xPort, cByteToSend, comNO_BLOCK ) == pdPASS )
|
||||||
|
{
|
||||||
|
vParTestToggleLED( uxBaseLED + comTX_LED_OFFSET );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Turn the LED off while we are not doing anything. */
|
||||||
|
vParTestSetLED( uxBaseLED + comTX_LED_OFFSET, pdFALSE );
|
||||||
|
|
||||||
|
/* We have posted all the characters in the string - wait before
|
||||||
|
re-sending. Wait a pseudo-random time as this will provide a better
|
||||||
|
test. */
|
||||||
|
xTimeToWait = xTaskGetTickCount() + comOFFSET_TIME;
|
||||||
|
|
||||||
|
/* Make sure we don't wait too long... */
|
||||||
|
xTimeToWait %= comTX_MAX_BLOCK_TIME;
|
||||||
|
|
||||||
|
/* ...but we do want to wait. */
|
||||||
|
if( xTimeToWait < comTX_MIN_BLOCK_TIME )
|
||||||
|
{
|
||||||
|
xTimeToWait = comTX_MIN_BLOCK_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelay( xTimeToWait );
|
||||||
|
}
|
||||||
|
} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vComRxTask, pvParameters )
|
||||||
|
{
|
||||||
|
signed char cExpectedByte, cByteRxed;
|
||||||
|
BaseType_t xResyncRequired = pdFALSE, xErrorOccurred = pdFALSE;
|
||||||
|
|
||||||
|
/* Just to stop compiler warnings. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* We expect to receive the characters from comFIRST_BYTE to
|
||||||
|
comLAST_BYTE in an incrementing order. Loop to receive each byte. */
|
||||||
|
for( cExpectedByte = comFIRST_BYTE; cExpectedByte <= comLAST_BYTE; cExpectedByte++ )
|
||||||
|
{
|
||||||
|
/* Block on the queue that contains received bytes until a byte is
|
||||||
|
available. */
|
||||||
|
if( xSerialGetChar( xPort, &cByteRxed, comRX_BLOCK_TIME ) )
|
||||||
|
{
|
||||||
|
/* Was this the byte we were expecting? If so, toggle the LED,
|
||||||
|
otherwise we are out on sync and should break out of the loop
|
||||||
|
until the expected character sequence is about to restart. */
|
||||||
|
if( cByteRxed == cExpectedByte )
|
||||||
|
{
|
||||||
|
vParTestToggleLED( uxBaseLED + comRX_LED_OFFSET );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xResyncRequired = pdTRUE;
|
||||||
|
break; /*lint !e960 Non-switch break allowed. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Turn the LED off while we are not doing anything. */
|
||||||
|
vParTestSetLED( uxBaseLED + comRX_LED_OFFSET, pdFALSE );
|
||||||
|
|
||||||
|
/* Did we break out of the loop because the characters were received in
|
||||||
|
an unexpected order? If so wait here until the character sequence is
|
||||||
|
about to restart. */
|
||||||
|
if( xResyncRequired == pdTRUE )
|
||||||
|
{
|
||||||
|
while( cByteRxed != comLAST_BYTE )
|
||||||
|
{
|
||||||
|
/* Block until the next char is available. */
|
||||||
|
xSerialGetChar( xPort, &cByteRxed, comRX_BLOCK_TIME );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note that an error occurred which caused us to have to resync.
|
||||||
|
We use this to stop incrementing the loop counter so
|
||||||
|
sAreComTestTasksStillRunning() will return false - indicating an
|
||||||
|
error. */
|
||||||
|
xErrorOccurred++;
|
||||||
|
|
||||||
|
/* We have now resynced with the Tx task and can continue. */
|
||||||
|
xResyncRequired = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( xErrorOccurred < comTOTAL_PERMISSIBLE_ERRORS )
|
||||||
|
{
|
||||||
|
/* Increment the count of successful loops. As error
|
||||||
|
occurring (i.e. an unexpected character being received) will
|
||||||
|
prevent this counter being incremented for the rest of the
|
||||||
|
execution. Don't worry about mutual exclusion on this
|
||||||
|
variable - it doesn't really matter as we just want it
|
||||||
|
to change. */
|
||||||
|
uxRxLoops++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xAreComTestTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
/* If the count of successful reception loops has not changed than at
|
||||||
|
some time an error occurred (i.e. a character was received out of sequence)
|
||||||
|
and we will return false. */
|
||||||
|
if( uxRxLoops == comINITIAL_RX_COUNT_VALUE )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the count of successful Rx loops. When this function is called
|
||||||
|
again we expect this to have been incremented. */
|
||||||
|
uxRxLoops = comINITIAL_RX_COUNT_VALUE;
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,349 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a task and a timer that operate on an interrupt driven serial port.
|
||||||
|
* This demo assumes that the characters transmitted on a port will also be
|
||||||
|
* received on the same port. Therefore, the UART must either be connected to
|
||||||
|
* an echo server, or the uart connector must have a loopback connector fitted.
|
||||||
|
* See http://www.serialporttool.com/CommEcho.htm for a suitable echo server
|
||||||
|
* for Windows hosts.
|
||||||
|
*
|
||||||
|
* The timer sends a string to the UART, toggles an LED, then resets itself by
|
||||||
|
* changing its own period. The period is calculated as a pseudo random number
|
||||||
|
* between comTX_MAX_BLOCK_TIME and comTX_MIN_BLOCK_TIME.
|
||||||
|
*
|
||||||
|
* The task blocks on an Rx queue waiting for a character to become available.
|
||||||
|
* Received characters are checked to ensure they match those transmitted by the
|
||||||
|
* Tx timer. An error is latched if characters are missing, incorrect, or
|
||||||
|
* arrive too slowly.
|
||||||
|
*
|
||||||
|
* How characters are actually transmitted and received is port specific. Demos
|
||||||
|
* that include this test/demo file will provide example drivers. The Tx timer
|
||||||
|
* executes in the context of the timer service (daemon) task, and must
|
||||||
|
* therefore never attempt to block.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "timers.h"
|
||||||
|
|
||||||
|
#ifndef configUSE_TIMERS
|
||||||
|
#error This demo uses timers. configUSE_TIMERS must be set to 1 in FreeRTOSConfig.h.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if configUSE_TIMERS != 1
|
||||||
|
#error This demo uses timers. configUSE_TIMERS must be set to 1 in FreeRTOSConfig.h.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "serial.h"
|
||||||
|
#include "comtest_strings.h"
|
||||||
|
#include "partest.h"
|
||||||
|
|
||||||
|
/* The size of the stack given to the Rx task. */
|
||||||
|
#define comSTACK_SIZE configMINIMAL_STACK_SIZE
|
||||||
|
|
||||||
|
/* See the comment above the declaraction of the uxBaseLED variable. */
|
||||||
|
#define comTX_LED_OFFSET ( 0 )
|
||||||
|
#define comRX_LED_OFFSET ( 1 )
|
||||||
|
|
||||||
|
/* The Tx timer transmits the sequence of characters at a pseudo random
|
||||||
|
interval that is capped between comTX_MAX_BLOCK_TIME and
|
||||||
|
comTX_MIN_BLOCK_TIME. */
|
||||||
|
#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x96 )
|
||||||
|
#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0x32 )
|
||||||
|
#define comOFFSET_TIME ( ( TickType_t ) 3 )
|
||||||
|
|
||||||
|
/* States for the simple state machine implemented in the Rx task. */
|
||||||
|
#define comtstWAITING_START_OF_STRING 0
|
||||||
|
#define comtstWAITING_END_OF_STRING 1
|
||||||
|
|
||||||
|
/* A short delay in ticks - this delay is used to allow the Rx queue to fill up
|
||||||
|
a bit so more than one character can be processed at a time. This is relative
|
||||||
|
to comTX_MIN_BLOCK_TIME to ensure it is never longer than the shortest gap
|
||||||
|
between transmissions. It could be worked out more scientifically from the
|
||||||
|
baud rate being used. */
|
||||||
|
#define comSHORT_DELAY ( comTX_MIN_BLOCK_TIME >> ( TickType_t ) 2 )
|
||||||
|
|
||||||
|
/* The string that is transmitted and received. */
|
||||||
|
#define comTRANSACTED_STRING "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
|
||||||
|
|
||||||
|
/* A block time of 0 simply means "don't block". */
|
||||||
|
#define comtstDONT_BLOCK ( TickType_t ) 0
|
||||||
|
|
||||||
|
/* Handle to the com port used by both tasks. */
|
||||||
|
static xComPortHandle xPort = NULL;
|
||||||
|
|
||||||
|
/* The callback function allocated to the transmit timer, as described in the
|
||||||
|
comments at the top of this file. */
|
||||||
|
static void prvComTxTimerCallback( TimerHandle_t xTimer );
|
||||||
|
|
||||||
|
/* The receive task as described in the comments at the top of this file. */
|
||||||
|
static void vComRxTask( void *pvParameters );
|
||||||
|
|
||||||
|
/* The Rx task will toggle LED ( uxBaseLED + comRX_LED_OFFSET). The Tx task
|
||||||
|
will toggle LED ( uxBaseLED + comTX_LED_OFFSET ). */
|
||||||
|
static UBaseType_t uxBaseLED = 0;
|
||||||
|
|
||||||
|
/* The Rx task toggles uxRxLoops on each successful iteration of its defined
|
||||||
|
function - provided no errors have ever been latched. If this variable stops
|
||||||
|
incrementing, then an error has occurred. */
|
||||||
|
static volatile UBaseType_t uxRxLoops = 0UL;
|
||||||
|
|
||||||
|
/* The timer used to periodically transmit the string. This is the timer that
|
||||||
|
has prvComTxTimerCallback allocated to it as its callback function. */
|
||||||
|
static TimerHandle_t xTxTimer = NULL;
|
||||||
|
|
||||||
|
/* The string length is held at file scope so the Tx timer does not need to
|
||||||
|
calculate it each time it executes. */
|
||||||
|
static size_t xStringLength = 0U;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartComTestStringsTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED )
|
||||||
|
{
|
||||||
|
/* Store values that are used at run time. */
|
||||||
|
uxBaseLED = uxLED;
|
||||||
|
|
||||||
|
/* Calculate the string length here, rather than each time the Tx timer
|
||||||
|
executes. */
|
||||||
|
xStringLength = strlen( comTRANSACTED_STRING );
|
||||||
|
|
||||||
|
/* Include the null terminator in the string length as this is used to
|
||||||
|
detect the end of the string in the Rx task. */
|
||||||
|
xStringLength++;
|
||||||
|
|
||||||
|
/* Initialise the com port, then spawn the Rx task and create the Tx
|
||||||
|
timer. */
|
||||||
|
xSerialPortInitMinimal( ulBaudRate, ( xStringLength * 2U ) );
|
||||||
|
|
||||||
|
/* Create the Rx task and the Tx timer. The timer is started from the
|
||||||
|
Rx task. */
|
||||||
|
xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
|
xTxTimer = xTimerCreate( "TxTimer", comTX_MIN_BLOCK_TIME, pdFALSE, NULL, prvComTxTimerCallback );
|
||||||
|
configASSERT( xTxTimer );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvComTxTimerCallback( TimerHandle_t xTimer )
|
||||||
|
{
|
||||||
|
TickType_t xTimeToWait;
|
||||||
|
|
||||||
|
/* The parameter is not used in this case. */
|
||||||
|
( void ) xTimer;
|
||||||
|
|
||||||
|
/* Send the string. How this is actually performed depends on the
|
||||||
|
sample driver provided with this demo. However - as this is a timer,
|
||||||
|
it executes in the context of the timer task and therefore must not
|
||||||
|
block. */
|
||||||
|
vSerialPutString( xPort, comTRANSACTED_STRING, xStringLength );
|
||||||
|
|
||||||
|
/* Toggle an LED to give a visible indication that another transmission
|
||||||
|
has been performed. */
|
||||||
|
vParTestToggleLED( uxBaseLED + comTX_LED_OFFSET );
|
||||||
|
|
||||||
|
/* Wait a pseudo random time before sending the string again. */
|
||||||
|
xTimeToWait = xTaskGetTickCount() + comOFFSET_TIME;
|
||||||
|
|
||||||
|
/* Ensure the time to wait is not greater than comTX_MAX_BLOCK_TIME. */
|
||||||
|
xTimeToWait %= comTX_MAX_BLOCK_TIME;
|
||||||
|
|
||||||
|
/* Ensure the time to wait is not less than comTX_MIN_BLOCK_TIME. */
|
||||||
|
if( xTimeToWait < comTX_MIN_BLOCK_TIME )
|
||||||
|
{
|
||||||
|
xTimeToWait = comTX_MIN_BLOCK_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the timer to run again xTimeToWait ticks from now. This function
|
||||||
|
is called from the context of the timer task, so the block time must not
|
||||||
|
be anything other than zero. */
|
||||||
|
xTimerChangePeriod( xTxTimer, xTimeToWait, comtstDONT_BLOCK );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vComRxTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
BaseType_t xState = comtstWAITING_START_OF_STRING, xErrorOccurred = pdFALSE;
|
||||||
|
char *pcExpectedByte, cRxedChar;
|
||||||
|
const xComPortHandle xPort = NULL;
|
||||||
|
|
||||||
|
/* The parameter is not used in this example. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Start the Tx timer. This only needs to be started once, as it will
|
||||||
|
reset itself thereafter. */
|
||||||
|
xTimerStart( xTxTimer, portMAX_DELAY );
|
||||||
|
|
||||||
|
/* The first expected Rx character is the first in the string that is
|
||||||
|
transmitted. */
|
||||||
|
pcExpectedByte = comTRANSACTED_STRING;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Wait for the next character. */
|
||||||
|
if( xSerialGetChar( xPort, &cRxedChar, ( comTX_MAX_BLOCK_TIME * 2 ) ) == pdFALSE )
|
||||||
|
{
|
||||||
|
/* A character definitely should have been received by now. As a
|
||||||
|
character was not received an error must have occurred (which might
|
||||||
|
just be that the loopback connector is not fitted). */
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( xState )
|
||||||
|
{
|
||||||
|
case comtstWAITING_START_OF_STRING:
|
||||||
|
if( cRxedChar == *pcExpectedByte )
|
||||||
|
{
|
||||||
|
/* The received character was the first character of the
|
||||||
|
string. Move to the next state to check each character
|
||||||
|
as it comes in until the entire string has been received. */
|
||||||
|
xState = comtstWAITING_END_OF_STRING;
|
||||||
|
pcExpectedByte++;
|
||||||
|
|
||||||
|
/* Block for a short period. This just allows the Rx queue
|
||||||
|
to contain more than one character, and therefore prevent
|
||||||
|
thrashing reads to the queue, and repetitive context
|
||||||
|
switches as each character is received. */
|
||||||
|
vTaskDelay( comSHORT_DELAY );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case comtstWAITING_END_OF_STRING:
|
||||||
|
if( cRxedChar == *pcExpectedByte )
|
||||||
|
{
|
||||||
|
/* The received character was the expected character. Was
|
||||||
|
it the last character in the string - i.e. the null
|
||||||
|
terminator? */
|
||||||
|
if( cRxedChar == 0x00 )
|
||||||
|
{
|
||||||
|
/* The entire string has been received. If no errors
|
||||||
|
have been latched, then increment the loop counter to
|
||||||
|
show this task is still healthy. */
|
||||||
|
if( xErrorOccurred == pdFALSE )
|
||||||
|
{
|
||||||
|
uxRxLoops++;
|
||||||
|
|
||||||
|
/* Toggle an LED to give a visible sign that a
|
||||||
|
complete string has been received. */
|
||||||
|
vParTestToggleLED( uxBaseLED + comRX_LED_OFFSET );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go back to wait for the start of the next string. */
|
||||||
|
pcExpectedByte = comTRANSACTED_STRING;
|
||||||
|
xState = comtstWAITING_START_OF_STRING;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Wait for the next character in the string. */
|
||||||
|
pcExpectedByte++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The character received was not that expected. */
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Should not get here. Stop the Rx loop counter from
|
||||||
|
incrementing to latch the error. */
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xAreComTestTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
/* If the count of successful reception loops has not changed than at
|
||||||
|
some time an error occurred (i.e. a character was received out of sequence)
|
||||||
|
and false is returned. */
|
||||||
|
if( uxRxLoops == 0UL )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the count of successful Rx loops. When this function is called
|
||||||
|
again it should have been incremented again. */
|
||||||
|
uxRxLoops = 0UL;
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,322 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple demonstration of the usage of counting semaphore.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "semphr.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "countsem.h"
|
||||||
|
|
||||||
|
/* The maximum count value that the semaphore used for the demo can hold. */
|
||||||
|
#define countMAX_COUNT_VALUE ( 200 )
|
||||||
|
|
||||||
|
/* Constants used to indicate whether or not the semaphore should have been
|
||||||
|
created with its maximum count value, or its minimum count value. These
|
||||||
|
numbers are used to ensure that the pointers passed in as the task parameters
|
||||||
|
are valid. */
|
||||||
|
#define countSTART_AT_MAX_COUNT ( 0xaa )
|
||||||
|
#define countSTART_AT_ZERO ( 0x55 )
|
||||||
|
|
||||||
|
/* Two tasks are created for the test. One uses a semaphore created with its
|
||||||
|
count value set to the maximum, and one with the count value set to zero. */
|
||||||
|
#define countNUM_TEST_TASKS ( 2 )
|
||||||
|
#define countDONT_BLOCK ( 0 )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
||||||
|
detected in any of the tasks. */
|
||||||
|
static volatile BaseType_t xErrorDetected = pdFALSE;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The demo task. This simply counts the semaphore up to its maximum value,
|
||||||
|
* the counts it back down again. The result of each semaphore 'give' and
|
||||||
|
* 'take' is inspected, with an error being flagged if it is found not to be
|
||||||
|
* the expected result.
|
||||||
|
*/
|
||||||
|
static void prvCountingSemaphoreTask( void *pvParameters );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to increment the semaphore count value up from zero to
|
||||||
|
* countMAX_COUNT_VALUE.
|
||||||
|
*/
|
||||||
|
static void prvIncrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility function to decrement the semaphore count value up from
|
||||||
|
* countMAX_COUNT_VALUE to zero.
|
||||||
|
*/
|
||||||
|
static void prvDecrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* The structure that is passed into the task as the task parameter. */
|
||||||
|
typedef struct COUNT_SEM_STRUCT
|
||||||
|
{
|
||||||
|
/* The semaphore to be used for the demo. */
|
||||||
|
SemaphoreHandle_t xSemaphore;
|
||||||
|
|
||||||
|
/* Set to countSTART_AT_MAX_COUNT if the semaphore should be created with
|
||||||
|
its count value set to its max count value, or countSTART_AT_ZERO if it
|
||||||
|
should have been created with its count value set to 0. */
|
||||||
|
UBaseType_t uxExpectedStartCount;
|
||||||
|
|
||||||
|
/* Incremented on each cycle of the demo task. Used to detect a stalled
|
||||||
|
task. */
|
||||||
|
UBaseType_t uxLoopCounter;
|
||||||
|
} xCountSemStruct;
|
||||||
|
|
||||||
|
/* Two structures are defined, one is passed to each test task. */
|
||||||
|
static volatile xCountSemStruct xParameters[ countNUM_TEST_TASKS ];
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartCountingSemaphoreTasks( void )
|
||||||
|
{
|
||||||
|
/* Create the semaphores that we are going to use for the test/demo. The
|
||||||
|
first should be created such that it starts at its maximum count value,
|
||||||
|
the second should be created such that it starts with a count value of zero. */
|
||||||
|
xParameters[ 0 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, countMAX_COUNT_VALUE );
|
||||||
|
xParameters[ 0 ].uxExpectedStartCount = countSTART_AT_MAX_COUNT;
|
||||||
|
xParameters[ 0 ].uxLoopCounter = 0;
|
||||||
|
|
||||||
|
xParameters[ 1 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, 0 );
|
||||||
|
xParameters[ 1 ].uxExpectedStartCount = 0;
|
||||||
|
xParameters[ 1 ].uxLoopCounter = 0;
|
||||||
|
|
||||||
|
/* vQueueAddToRegistry() adds the semaphore to the registry, if one is
|
||||||
|
in use. The registry is provided as a means for kernel aware
|
||||||
|
debuggers to locate semaphores 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 ) xParameters[ 0 ].xSemaphore, "Counting_Sem_1" );
|
||||||
|
vQueueAddToRegistry( ( QueueHandle_t ) xParameters[ 1 ].xSemaphore, "Counting_Sem_2" );
|
||||||
|
|
||||||
|
|
||||||
|
/* Were the semaphores created? */
|
||||||
|
if( ( xParameters[ 0 ].xSemaphore != NULL ) || ( xParameters[ 1 ].xSemaphore != NULL ) )
|
||||||
|
{
|
||||||
|
/* Create the demo tasks, passing in the semaphore to use as the parameter. */
|
||||||
|
xTaskCreate( prvCountingSemaphoreTask, "CNT1", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 0 ] ), tskIDLE_PRIORITY, NULL );
|
||||||
|
xTaskCreate( prvCountingSemaphoreTask, "CNT2", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 1 ] ), tskIDLE_PRIORITY, NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvDecrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter )
|
||||||
|
{
|
||||||
|
UBaseType_t ux;
|
||||||
|
|
||||||
|
/* If the semaphore count is at its maximum then we should not be able to
|
||||||
|
'give' the semaphore. */
|
||||||
|
if( xSemaphoreGive( xSemaphore ) == pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We should be able to 'take' the semaphore countMAX_COUNT_VALUE times. */
|
||||||
|
for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ )
|
||||||
|
{
|
||||||
|
if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* We expected to be able to take the semaphore. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
( *puxLoopCounter )++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If the semaphore count is zero then we should not be able to 'take'
|
||||||
|
the semaphore. */
|
||||||
|
if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvIncrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter )
|
||||||
|
{
|
||||||
|
UBaseType_t ux;
|
||||||
|
|
||||||
|
/* If the semaphore count is zero then we should not be able to 'take'
|
||||||
|
the semaphore. */
|
||||||
|
if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We should be able to 'give' the semaphore countMAX_COUNT_VALUE times. */
|
||||||
|
for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ )
|
||||||
|
{
|
||||||
|
if( xSemaphoreGive( xSemaphore ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* We expected to be able to take the semaphore. */
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
( *puxLoopCounter )++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If the semaphore count is at its maximum then we should not be able to
|
||||||
|
'give' the semaphore. */
|
||||||
|
if( xSemaphoreGive( xSemaphore ) == pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvCountingSemaphoreTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
xCountSemStruct *pxParameter;
|
||||||
|
|
||||||
|
#ifdef USE_STDIO
|
||||||
|
void vPrintDisplayMessage( const char * const * ppcMessageToSend );
|
||||||
|
|
||||||
|
const char * const pcTaskStartMsg = "Counting semaphore demo started.\r\n";
|
||||||
|
|
||||||
|
/* Queue a message for printing to say the task has started. */
|
||||||
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The semaphore to be used was passed as the parameter. */
|
||||||
|
pxParameter = ( xCountSemStruct * ) pvParameters;
|
||||||
|
|
||||||
|
/* Did we expect to find the semaphore already at its max count value, or
|
||||||
|
at zero? */
|
||||||
|
if( pxParameter->uxExpectedStartCount == countSTART_AT_MAX_COUNT )
|
||||||
|
{
|
||||||
|
prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we expect the semaphore count to be 0, so this time there is an
|
||||||
|
error if we can take the semaphore. */
|
||||||
|
if( xSemaphoreTake( pxParameter->xSemaphore, 0 ) == pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
prvIncrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );
|
||||||
|
prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xAreCountingSemaphoreTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
static UBaseType_t uxLastCount0 = 0, uxLastCount1 = 0;
|
||||||
|
BaseType_t xReturn = pdPASS;
|
||||||
|
|
||||||
|
/* Return fail if any 'give' or 'take' did not result in the expected
|
||||||
|
behaviour. */
|
||||||
|
if( xErrorDetected != pdFALSE )
|
||||||
|
{
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return fail if either task is not still incrementing its loop counter. */
|
||||||
|
if( uxLastCount0 == xParameters[ 0 ].uxLoopCounter )
|
||||||
|
{
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uxLastCount0 = xParameters[ 0 ].uxLoopCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxLastCount1 == xParameters[ 1 ].uxLoopCounter )
|
||||||
|
{
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uxLastCount1 = xParameters[ 1 ].uxLoopCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,246 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 demo application file demonstrates the use of queues to pass data
|
||||||
|
* between co-routines.
|
||||||
|
*
|
||||||
|
* N represents the number of 'fixed delay' co-routines that are created and
|
||||||
|
* is set during initialisation.
|
||||||
|
*
|
||||||
|
* N 'fixed delay' co-routines are created that just block for a fixed
|
||||||
|
* period then post the number of an LED onto a queue. Each such co-routine
|
||||||
|
* uses a different block period. A single 'flash' co-routine is also created
|
||||||
|
* that blocks on the same queue, waiting for the number of the next LED it
|
||||||
|
* should flash. Upon receiving a number it simply toggle the instructed LED
|
||||||
|
* then blocks on the queue once more. In this manner each LED from LED 0 to
|
||||||
|
* LED N-1 is caused to flash at a different rate.
|
||||||
|
*
|
||||||
|
* The 'fixed delay' co-routines are created with co-routine priority 0. The
|
||||||
|
* flash co-routine is created with co-routine priority 1. This means that
|
||||||
|
* the queue should never contain more than a single item. This is because
|
||||||
|
* posting to the queue will unblock the 'flash' co-routine, and as this has
|
||||||
|
* a priority greater than the tasks posting to the queue it is guaranteed to
|
||||||
|
* have emptied the queue and blocked once again before the queue can contain
|
||||||
|
* any more date. An error is indicated if an attempt to post data to the
|
||||||
|
* queue fails - indicating that the queue is already full.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Scheduler includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "croutine.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
/* Demo application includes. */
|
||||||
|
#include "partest.h"
|
||||||
|
#include "crflash.h"
|
||||||
|
|
||||||
|
/* The queue should only need to be of length 1. See the description at the
|
||||||
|
top of the file. */
|
||||||
|
#define crfQUEUE_LENGTH 1
|
||||||
|
|
||||||
|
#define crfFIXED_DELAY_PRIORITY 0
|
||||||
|
#define crfFLASH_PRIORITY 1
|
||||||
|
|
||||||
|
/* Only one flash co-routine is created so the index is not significant. */
|
||||||
|
#define crfFLASH_INDEX 0
|
||||||
|
|
||||||
|
/* Don't allow more than crfMAX_FLASH_TASKS 'fixed delay' co-routines to be
|
||||||
|
created. */
|
||||||
|
#define crfMAX_FLASH_TASKS 8
|
||||||
|
|
||||||
|
/* We don't want to block when posting to the queue. */
|
||||||
|
#define crfPOSTING_BLOCK_TIME 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The 'fixed delay' co-routine as described at the top of the file.
|
||||||
|
*/
|
||||||
|
static void prvFixedDelayCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The 'flash' co-routine as described at the top of the file.
|
||||||
|
*/
|
||||||
|
static void prvFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex );
|
||||||
|
|
||||||
|
/* The queue used to pass data between the 'fixed delay' co-routines and the
|
||||||
|
'flash' co-routine. */
|
||||||
|
static QueueHandle_t xFlashQueue;
|
||||||
|
|
||||||
|
/* This will be set to pdFALSE if we detect an error. */
|
||||||
|
static BaseType_t xCoRoutineFlashStatus = pdPASS;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See the header file for details.
|
||||||
|
*/
|
||||||
|
void vStartFlashCoRoutines( UBaseType_t uxNumberToCreate )
|
||||||
|
{
|
||||||
|
UBaseType_t uxIndex;
|
||||||
|
|
||||||
|
if( uxNumberToCreate > crfMAX_FLASH_TASKS )
|
||||||
|
{
|
||||||
|
uxNumberToCreate = crfMAX_FLASH_TASKS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the queue used to pass data between the co-routines. */
|
||||||
|
xFlashQueue = xQueueCreate( crfQUEUE_LENGTH, sizeof( UBaseType_t ) );
|
||||||
|
|
||||||
|
if( xFlashQueue )
|
||||||
|
{
|
||||||
|
/* Create uxNumberToCreate 'fixed delay' co-routines. */
|
||||||
|
for( uxIndex = 0; uxIndex < uxNumberToCreate; uxIndex++ )
|
||||||
|
{
|
||||||
|
xCoRoutineCreate( prvFixedDelayCoRoutine, crfFIXED_DELAY_PRIORITY, uxIndex );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the 'flash' co-routine. */
|
||||||
|
xCoRoutineCreate( prvFlashCoRoutine, crfFLASH_PRIORITY, crfFLASH_INDEX );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvFixedDelayCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
{
|
||||||
|
/* Even though this is a co-routine the xResult variable does not need to be
|
||||||
|
static as we do not need it to maintain its state between blocks. */
|
||||||
|
BaseType_t xResult;
|
||||||
|
/* The uxIndex parameter of the co-routine function is used as an index into
|
||||||
|
the xFlashRates array to obtain the delay period to use. */
|
||||||
|
static const TickType_t xFlashRates[ crfMAX_FLASH_TASKS ] = { 150 / portTICK_PERIOD_MS,
|
||||||
|
200 / portTICK_PERIOD_MS,
|
||||||
|
250 / portTICK_PERIOD_MS,
|
||||||
|
300 / portTICK_PERIOD_MS,
|
||||||
|
350 / portTICK_PERIOD_MS,
|
||||||
|
400 / portTICK_PERIOD_MS,
|
||||||
|
450 / portTICK_PERIOD_MS,
|
||||||
|
500 / portTICK_PERIOD_MS };
|
||||||
|
|
||||||
|
/* Co-routines MUST start with a call to crSTART. */
|
||||||
|
crSTART( xHandle );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Post our uxIndex value onto the queue. This is used as the LED to
|
||||||
|
flash. */
|
||||||
|
crQUEUE_SEND( xHandle, xFlashQueue, ( void * ) &uxIndex, crfPOSTING_BLOCK_TIME, &xResult );
|
||||||
|
|
||||||
|
if( xResult != pdPASS )
|
||||||
|
{
|
||||||
|
/* For the reasons stated at the top of the file we should always
|
||||||
|
find that we can post to the queue. If we could not then an error
|
||||||
|
has occurred. */
|
||||||
|
xCoRoutineFlashStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
crDELAY( xHandle, xFlashRates[ uxIndex ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Co-routines MUST end with a call to crEND. */
|
||||||
|
crEND();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
{
|
||||||
|
/* Even though this is a co-routine the variable do not need to be
|
||||||
|
static as we do not need it to maintain their state between blocks. */
|
||||||
|
BaseType_t xResult;
|
||||||
|
UBaseType_t uxLEDToFlash;
|
||||||
|
|
||||||
|
/* Co-routines MUST start with a call to crSTART. */
|
||||||
|
crSTART( xHandle );
|
||||||
|
( void ) uxIndex;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Block to wait for the number of the LED to flash. */
|
||||||
|
crQUEUE_RECEIVE( xHandle, xFlashQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
|
||||||
|
|
||||||
|
if( xResult != pdPASS )
|
||||||
|
{
|
||||||
|
/* We would not expect to wake unless we received something. */
|
||||||
|
xCoRoutineFlashStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We received the number of an LED to flash - flash it! */
|
||||||
|
vParTestToggleLED( uxLEDToFlash );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Co-routines MUST end with a call to crEND. */
|
||||||
|
crEND();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xAreFlashCoRoutinesStillRunning( void )
|
||||||
|
{
|
||||||
|
/* Return pdPASS or pdFAIL depending on whether an error has been detected
|
||||||
|
or not. */
|
||||||
|
return xCoRoutineFlashStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,270 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 demo file demonstrates how to send data between an ISR and a
|
||||||
|
* co-routine. A tick hook function is used to periodically pass data between
|
||||||
|
* the RTOS tick and a set of 'hook' co-routines.
|
||||||
|
*
|
||||||
|
* hookNUM_HOOK_CO_ROUTINES co-routines are created. Each co-routine blocks
|
||||||
|
* to wait for a character to be received on a queue from the tick ISR, checks
|
||||||
|
* to ensure the character received was that expected, then sends the number
|
||||||
|
* back to the tick ISR on a different queue.
|
||||||
|
*
|
||||||
|
* The tick ISR checks the numbers received back from the 'hook' co-routines
|
||||||
|
* matches the number previously sent.
|
||||||
|
*
|
||||||
|
* If at any time a queue function returns unexpectedly, or an incorrect value
|
||||||
|
* is received either by the tick hook or a co-routine then an error is
|
||||||
|
* latched.
|
||||||
|
*
|
||||||
|
* This demo relies on each 'hook' co-routine to execute between each
|
||||||
|
* hookTICK_CALLS_BEFORE_POST tick interrupts. This and the heavy use of
|
||||||
|
* queues from within an interrupt may result in an error being detected on
|
||||||
|
* slower targets simply due to timing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Scheduler includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "croutine.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
/* Demo application includes. */
|
||||||
|
#include "crhook.h"
|
||||||
|
|
||||||
|
/* The number of 'hook' co-routines that are to be created. */
|
||||||
|
#define hookNUM_HOOK_CO_ROUTINES ( 4 )
|
||||||
|
|
||||||
|
/* The number of times the tick hook should be called before a character is
|
||||||
|
posted to the 'hook' co-routines. */
|
||||||
|
#define hookTICK_CALLS_BEFORE_POST ( 500 )
|
||||||
|
|
||||||
|
/* There should never be more than one item in any queue at any time. */
|
||||||
|
#define hookHOOK_QUEUE_LENGTH ( 1 )
|
||||||
|
|
||||||
|
/* Don't block when initially posting to the queue. */
|
||||||
|
#define hookNO_BLOCK_TIME ( 0 )
|
||||||
|
|
||||||
|
/* The priority relative to other co-routines (rather than tasks) that the
|
||||||
|
'hook' co-routines should take. */
|
||||||
|
#define mainHOOK_CR_PRIORITY ( 1 )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The co-routine function itself.
|
||||||
|
*/
|
||||||
|
static void prvHookCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex );
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The tick hook function. This receives a number from each 'hook' co-routine
|
||||||
|
* then sends a number to each co-routine. An error is flagged if a send or
|
||||||
|
* receive fails, or an unexpected number is received.
|
||||||
|
*/
|
||||||
|
void vApplicationTickHook( void );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Queues used to send data FROM a co-routine TO the tick hook function.
|
||||||
|
The hook functions received (Rx's) on these queues. One queue per
|
||||||
|
'hook' co-routine. */
|
||||||
|
static QueueHandle_t xHookRxQueues[ hookNUM_HOOK_CO_ROUTINES ];
|
||||||
|
|
||||||
|
/* Queues used to send data FROM the tick hook TO a co-routine function.
|
||||||
|
The hood function transmits (Tx's) on these queues. One queue per
|
||||||
|
'hook' co-routine. */
|
||||||
|
static QueueHandle_t xHookTxQueues[ hookNUM_HOOK_CO_ROUTINES ];
|
||||||
|
|
||||||
|
/* Set to true if an error is detected at any time. */
|
||||||
|
static BaseType_t xCoRoutineErrorDetected = pdFALSE;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartHookCoRoutines( void )
|
||||||
|
{
|
||||||
|
UBaseType_t uxIndex, uxValueToPost = 0;
|
||||||
|
|
||||||
|
for( uxIndex = 0; uxIndex < hookNUM_HOOK_CO_ROUTINES; uxIndex++ )
|
||||||
|
{
|
||||||
|
/* Create a queue to transmit to and receive from each 'hook'
|
||||||
|
co-routine. */
|
||||||
|
xHookRxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) );
|
||||||
|
xHookTxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) );
|
||||||
|
|
||||||
|
/* To start things off the tick hook function expects the queue it
|
||||||
|
uses to receive data to contain a value. */
|
||||||
|
xQueueSend( xHookRxQueues[ uxIndex ], &uxValueToPost, hookNO_BLOCK_TIME );
|
||||||
|
|
||||||
|
/* Create the 'hook' co-routine itself. */
|
||||||
|
xCoRoutineCreate( prvHookCoRoutine, mainHOOK_CR_PRIORITY, uxIndex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static UBaseType_t uxCallCounter = 0, uxNumberToPost = 0;
|
||||||
|
void vApplicationTickHook( void )
|
||||||
|
{
|
||||||
|
UBaseType_t uxReceivedNumber;
|
||||||
|
BaseType_t xIndex, xCoRoutineWoken;
|
||||||
|
|
||||||
|
/* Is it time to talk to the 'hook' co-routines again? */
|
||||||
|
uxCallCounter++;
|
||||||
|
if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST )
|
||||||
|
{
|
||||||
|
uxCallCounter = 0;
|
||||||
|
|
||||||
|
for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )
|
||||||
|
{
|
||||||
|
xCoRoutineWoken = pdFALSE;
|
||||||
|
if( crQUEUE_RECEIVE_FROM_ISR( xHookRxQueues[ xIndex ], &uxReceivedNumber, &xCoRoutineWoken ) != pdPASS )
|
||||||
|
{
|
||||||
|
/* There is no reason why we would not expect the queue to
|
||||||
|
contain a value. */
|
||||||
|
xCoRoutineErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Each queue used to receive data from the 'hook' co-routines
|
||||||
|
should contain the number we last posted to the same co-routine. */
|
||||||
|
if( uxReceivedNumber != uxNumberToPost )
|
||||||
|
{
|
||||||
|
xCoRoutineErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing should be blocked waiting to post to the queue. */
|
||||||
|
if( xCoRoutineWoken != pdFALSE )
|
||||||
|
{
|
||||||
|
xCoRoutineErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start the next cycle by posting the next number onto each Tx queue. */
|
||||||
|
uxNumberToPost++;
|
||||||
|
|
||||||
|
for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )
|
||||||
|
{
|
||||||
|
if( crQUEUE_SEND_FROM_ISR( xHookTxQueues[ xIndex ], &uxNumberToPost, pdFALSE ) != pdTRUE )
|
||||||
|
{
|
||||||
|
/* Posting to the queue should have woken the co-routine that
|
||||||
|
was blocked on the queue. */
|
||||||
|
xCoRoutineErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvHookCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||||
|
{
|
||||||
|
static UBaseType_t uxReceivedValue[ hookNUM_HOOK_CO_ROUTINES ];
|
||||||
|
BaseType_t xResult;
|
||||||
|
|
||||||
|
/* Each co-routine MUST start with a call to crSTART(); */
|
||||||
|
crSTART( xHandle );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Wait to receive a value from the tick hook. */
|
||||||
|
xResult = pdFAIL;
|
||||||
|
crQUEUE_RECEIVE( xHandle, xHookTxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), portMAX_DELAY, &xResult );
|
||||||
|
|
||||||
|
/* There is no reason why we should not have received something on
|
||||||
|
the queue. */
|
||||||
|
if( xResult != pdPASS )
|
||||||
|
{
|
||||||
|
xCoRoutineErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the same number back to the idle hook so it can verify it. */
|
||||||
|
xResult = pdFAIL;
|
||||||
|
crQUEUE_SEND( xHandle, xHookRxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), hookNO_BLOCK_TIME, &xResult );
|
||||||
|
if( xResult != pdPASS )
|
||||||
|
{
|
||||||
|
/* There is no reason why we should not have been able to post to
|
||||||
|
the queue. */
|
||||||
|
xCoRoutineErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Each co-routine MUST end with a call to crEND(). */
|
||||||
|
crEND();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xAreHookCoRoutinesStillRunning( void )
|
||||||
|
{
|
||||||
|
if( xCoRoutineErrorDetected )
|
||||||
|
{
|
||||||
|
return pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,254 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a single persistent task which periodically dynamically creates another
|
||||||
|
* two tasks. The original task is called the creator task, the two tasks it
|
||||||
|
* creates are called suicidal tasks.
|
||||||
|
*
|
||||||
|
* One of the created suicidal tasks kill one other suicidal task before killing
|
||||||
|
* itself - leaving just the original task remaining.
|
||||||
|
*
|
||||||
|
* The creator task must be spawned after all of the other demo application tasks
|
||||||
|
* as it keeps a check on the number of tasks under the scheduler control. The
|
||||||
|
* number of tasks it expects to see running should never be greater than the
|
||||||
|
* number of tasks that were in existence when the creator task was spawned, plus
|
||||||
|
* one set of four suicidal tasks. If this number is exceeded an error is flagged.
|
||||||
|
*
|
||||||
|
* \page DeathC death.c
|
||||||
|
* \ingroup DemoFiles
|
||||||
|
* <HR>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "death.h"
|
||||||
|
|
||||||
|
#define deathSTACK_SIZE ( configMINIMAL_STACK_SIZE + 60 )
|
||||||
|
|
||||||
|
/* The task originally created which is responsible for periodically dynamically
|
||||||
|
creating another four tasks. */
|
||||||
|
static portTASK_FUNCTION_PROTO( vCreateTasks, pvParameters );
|
||||||
|
|
||||||
|
/* The task function of the dynamically created tasks. */
|
||||||
|
static portTASK_FUNCTION_PROTO( vSuicidalTask, pvParameters );
|
||||||
|
|
||||||
|
/* A variable which is incremented every time the dynamic tasks are created. This
|
||||||
|
is used to check that the task is still running. */
|
||||||
|
static volatile uint16_t usCreationCount = 0;
|
||||||
|
|
||||||
|
/* Used to store the number of tasks that were originally running so the creator
|
||||||
|
task can tell if any of the suicidal tasks have failed to die.
|
||||||
|
*/
|
||||||
|
static volatile UBaseType_t uxTasksRunningAtStart = 0;
|
||||||
|
|
||||||
|
/* Tasks are deleted by the idle task. Under heavy load the idle task might
|
||||||
|
not get much processing time, so it would be legitimate for several tasks to
|
||||||
|
remain undeleted for a short period. */
|
||||||
|
static const UBaseType_t uxMaxNumberOfExtraTasksRunning = 3;
|
||||||
|
|
||||||
|
/* Used to store a handle to the task that should be killed by a suicidal task,
|
||||||
|
before it kills itself. */
|
||||||
|
TaskHandle_t xCreatedTask;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vCreateSuicidalTasks( UBaseType_t uxPriority )
|
||||||
|
{
|
||||||
|
UBaseType_t *puxPriority;
|
||||||
|
|
||||||
|
/* Create the Creator tasks - passing in as a parameter the priority at which
|
||||||
|
the suicidal tasks should be created. */
|
||||||
|
puxPriority = ( UBaseType_t * ) pvPortMalloc( sizeof( UBaseType_t ) );
|
||||||
|
*puxPriority = uxPriority;
|
||||||
|
|
||||||
|
xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL );
|
||||||
|
|
||||||
|
/* Record the number of tasks that are running now so we know if any of the
|
||||||
|
suicidal tasks have failed to be killed. */
|
||||||
|
uxTasksRunningAtStart = ( UBaseType_t ) uxTaskGetNumberOfTasks();
|
||||||
|
|
||||||
|
/* FreeRTOS.org versions before V3.0 started the idle-task as the very
|
||||||
|
first task. The idle task was then already included in uxTasksRunningAtStart.
|
||||||
|
From FreeRTOS V3.0 on, the idle task is started when the scheduler is
|
||||||
|
started. Therefore the idle task is not yet accounted for. We correct
|
||||||
|
this by increasing uxTasksRunningAtStart by 1. */
|
||||||
|
uxTasksRunningAtStart++;
|
||||||
|
|
||||||
|
/* From FreeRTOS version 7.0.0 can optionally create a timer service task.
|
||||||
|
If this is done, then uxTasksRunningAtStart needs incrementing again as that
|
||||||
|
too is created when the scheduler is started. */
|
||||||
|
#if configUSE_TIMERS == 1
|
||||||
|
uxTasksRunningAtStart++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vSuicidalTask, pvParameters )
|
||||||
|
{
|
||||||
|
volatile long l1, l2;
|
||||||
|
TaskHandle_t xTaskToKill;
|
||||||
|
const TickType_t xDelay = ( TickType_t ) 200 / portTICK_PERIOD_MS;
|
||||||
|
|
||||||
|
if( pvParameters != NULL )
|
||||||
|
{
|
||||||
|
/* This task is periodically created four times. Two created tasks are
|
||||||
|
passed a handle to the other task so it can kill it before killing itself.
|
||||||
|
The other task is passed in null. */
|
||||||
|
xTaskToKill = *( TaskHandle_t* )pvParameters;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xTaskToKill = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Do something random just to use some stack and registers. */
|
||||||
|
l1 = 2;
|
||||||
|
l2 = 89;
|
||||||
|
l2 *= l1;
|
||||||
|
vTaskDelay( xDelay );
|
||||||
|
|
||||||
|
if( xTaskToKill != NULL )
|
||||||
|
{
|
||||||
|
/* Make sure the other task has a go before we delete it. */
|
||||||
|
vTaskDelay( ( TickType_t ) 0 );
|
||||||
|
|
||||||
|
/* Kill the other task that was created by vCreateTasks(). */
|
||||||
|
vTaskDelete( xTaskToKill );
|
||||||
|
|
||||||
|
/* Kill ourselves. */
|
||||||
|
vTaskDelete( NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}/*lint !e818 !e550 Function prototype must be as per standard for task functions. */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vCreateTasks, pvParameters )
|
||||||
|
{
|
||||||
|
const TickType_t xDelay = ( TickType_t ) 1000 / portTICK_PERIOD_MS;
|
||||||
|
UBaseType_t uxPriority;
|
||||||
|
|
||||||
|
uxPriority = *( UBaseType_t * ) pvParameters;
|
||||||
|
vPortFree( pvParameters );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Just loop round, delaying then creating the four suicidal tasks. */
|
||||||
|
vTaskDelay( xDelay );
|
||||||
|
|
||||||
|
xCreatedTask = NULL;
|
||||||
|
|
||||||
|
xTaskCreate( vSuicidalTask, "SUICID1", configMINIMAL_STACK_SIZE, NULL, uxPriority, &xCreatedTask );
|
||||||
|
xTaskCreate( vSuicidalTask, "SUICID2", configMINIMAL_STACK_SIZE, &xCreatedTask, uxPriority, NULL );
|
||||||
|
|
||||||
|
++usCreationCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that the creator task is still running and that there
|
||||||
|
are not any more than four extra tasks. */
|
||||||
|
BaseType_t xIsCreateTaskStillRunning( void )
|
||||||
|
{
|
||||||
|
static uint16_t usLastCreationCount = 0xfff;
|
||||||
|
BaseType_t xReturn = pdTRUE;
|
||||||
|
static UBaseType_t uxTasksRunningNow;
|
||||||
|
|
||||||
|
if( usLastCreationCount == usCreationCount )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usLastCreationCount = usCreationCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
uxTasksRunningNow = ( UBaseType_t ) uxTaskGetNumberOfTasks();
|
||||||
|
|
||||||
|
if( uxTasksRunningNow < uxTasksRunningAtStart )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Everything is okay. */
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,511 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The first test creates three tasks - two counter tasks (one continuous count
|
||||||
|
* and one limited count) and one controller. A "count" variable is shared
|
||||||
|
* between all three tasks. The two counter tasks should never be in a "ready"
|
||||||
|
* state at the same time. The controller task runs at the same priority as
|
||||||
|
* the continuous count task, and at a lower priority than the limited count
|
||||||
|
* task.
|
||||||
|
*
|
||||||
|
* One counter task loops indefinitely, incrementing the shared count variable
|
||||||
|
* on each iteration. To ensure it has exclusive access to the variable it
|
||||||
|
* raises its priority above that of the controller task before each
|
||||||
|
* increment, lowering it again to its original priority before starting the
|
||||||
|
* next iteration.
|
||||||
|
*
|
||||||
|
* The other counter task increments the shared count variable on each
|
||||||
|
* iteration of its loop until the count has reached a limit of 0xff - at
|
||||||
|
* which point it suspends itself. It will not start a new loop until the
|
||||||
|
* controller task has made it "ready" again by calling vTaskResume().
|
||||||
|
* This second counter task operates at a higher priority than controller
|
||||||
|
* task so does not need to worry about mutual exclusion of the counter
|
||||||
|
* variable.
|
||||||
|
*
|
||||||
|
* The controller task is in two sections. The first section controls and
|
||||||
|
* monitors the continuous count task. When this section is operational the
|
||||||
|
* limited count task is suspended. Likewise, the second section controls
|
||||||
|
* and monitors the limited count task. When this section is operational the
|
||||||
|
* continuous count task is suspended.
|
||||||
|
*
|
||||||
|
* In the first section the controller task first takes a copy of the shared
|
||||||
|
* count variable. To ensure mutual exclusion on the count variable it
|
||||||
|
* suspends the continuous count task, resuming it again when the copy has been
|
||||||
|
* taken. The controller task then sleeps for a fixed period - during which
|
||||||
|
* the continuous count task will execute and increment the shared variable.
|
||||||
|
* When the controller task wakes it checks that the continuous count task
|
||||||
|
* has executed by comparing the copy of the shared variable with its current
|
||||||
|
* value. This time, to ensure mutual exclusion, the scheduler itself is
|
||||||
|
* suspended with a call to vTaskSuspendAll (). This is for demonstration
|
||||||
|
* purposes only and is not a recommended technique due to its inefficiency.
|
||||||
|
*
|
||||||
|
* After a fixed number of iterations the controller task suspends the
|
||||||
|
* continuous count task, and moves on to its second section.
|
||||||
|
*
|
||||||
|
* At the start of the second section the shared variable is cleared to zero.
|
||||||
|
* The limited count task is then woken from its suspension by a call to
|
||||||
|
* vTaskResume (). As this counter task operates at a higher priority than
|
||||||
|
* the controller task the controller task should not run again until the
|
||||||
|
* shared variable has been counted up to the limited value causing the counter
|
||||||
|
* task to suspend itself. The next line after vTaskResume () is therefore
|
||||||
|
* a check on the shared variable to ensure everything is as expected.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The second test consists of a couple of very simple tasks that post onto a
|
||||||
|
* queue while the scheduler is suspended. This test was added to test parts
|
||||||
|
* of the scheduler not exercised by the first test.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "semphr.h"
|
||||||
|
|
||||||
|
/* Demo app include files. */
|
||||||
|
#include "dynamic.h"
|
||||||
|
|
||||||
|
/* Function that implements the "limited count" task as described above. */
|
||||||
|
static portTASK_FUNCTION_PROTO( vLimitedIncrementTask, pvParameters );
|
||||||
|
|
||||||
|
/* Function that implements the "continuous count" task as described above. */
|
||||||
|
static portTASK_FUNCTION_PROTO( vContinuousIncrementTask, pvParameters );
|
||||||
|
|
||||||
|
/* Function that implements the controller task as described above. */
|
||||||
|
static portTASK_FUNCTION_PROTO( vCounterControlTask, pvParameters );
|
||||||
|
|
||||||
|
static portTASK_FUNCTION_PROTO( vQueueReceiveWhenSuspendedTask, pvParameters );
|
||||||
|
static portTASK_FUNCTION_PROTO( vQueueSendWhenSuspendedTask, pvParameters );
|
||||||
|
|
||||||
|
/* Demo task specific constants. */
|
||||||
|
#define priSTACK_SIZE ( configMINIMAL_STACK_SIZE )
|
||||||
|
#define priSLEEP_TIME ( ( TickType_t ) 128 / portTICK_PERIOD_MS )
|
||||||
|
#define priLOOPS ( 5 )
|
||||||
|
#define priMAX_COUNT ( ( uint32_t ) 0xff )
|
||||||
|
#define priNO_BLOCK ( ( TickType_t ) 0 )
|
||||||
|
#define priSUSPENDED_QUEUE_LENGTH ( 1 )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Handles to the two counter tasks. These could be passed in as parameters
|
||||||
|
to the controller task to prevent them having to be file scope. */
|
||||||
|
static TaskHandle_t xContinuousIncrementHandle, xLimitedIncrementHandle;
|
||||||
|
|
||||||
|
/* The shared counter variable. This is passed in as a parameter to the two
|
||||||
|
counter variables for demonstration purposes. */
|
||||||
|
static volatile uint32_t ulCounter;
|
||||||
|
|
||||||
|
/* Variables used to check that the tasks are still operating without error.
|
||||||
|
Each complete iteration of the controller task increments this variable
|
||||||
|
provided no errors have been found. The variable maintaining the same value
|
||||||
|
is therefore indication of an error. */
|
||||||
|
static volatile uint16_t usCheckVariable = ( uint16_t ) 0;
|
||||||
|
static volatile BaseType_t xSuspendedQueueSendError = pdFALSE;
|
||||||
|
static volatile BaseType_t xSuspendedQueueReceiveError = pdFALSE;
|
||||||
|
|
||||||
|
/* Queue used by the second test. */
|
||||||
|
QueueHandle_t xSuspendedTestQueue;
|
||||||
|
|
||||||
|
/* The value the queue receive task expects to receive next. This is file
|
||||||
|
scope so xAreDynamicPriorityTasksStillRunning() can ensure it is still
|
||||||
|
incrementing. */
|
||||||
|
static uint32_t ulExpectedValue = ( uint32_t ) 0;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
* Start the three tasks as described at the top of the file.
|
||||||
|
* Note that the limited count task is given a higher priority.
|
||||||
|
*/
|
||||||
|
void vStartDynamicPriorityTasks( void )
|
||||||
|
{
|
||||||
|
xSuspendedTestQueue = xQueueCreate( priSUSPENDED_QUEUE_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( xSuspendedTestQueue, "Suspended_Test_Queue" );
|
||||||
|
|
||||||
|
xTaskCreate( vContinuousIncrementTask, "CNT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinuousIncrementHandle );
|
||||||
|
xTaskCreate( vLimitedIncrementTask, "LIM_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY + 1, &xLimitedIncrementHandle );
|
||||||
|
xTaskCreate( vCounterControlTask, "C_CTRL", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
||||||
|
xTaskCreate( vQueueSendWhenSuspendedTask, "SUSP_TX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
||||||
|
xTaskCreate( vQueueReceiveWhenSuspendedTask, "SUSP_RX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just loops around incrementing the shared variable until the limit has been
|
||||||
|
* reached. Once the limit has been reached it suspends itself.
|
||||||
|
*/
|
||||||
|
static portTASK_FUNCTION( vLimitedIncrementTask, pvParameters )
|
||||||
|
{
|
||||||
|
uint32_t *pulCounter;
|
||||||
|
|
||||||
|
/* Take a pointer to the shared variable from the parameters passed into
|
||||||
|
the task. */
|
||||||
|
pulCounter = ( uint32_t * ) pvParameters;
|
||||||
|
|
||||||
|
/* This will run before the control task, so the first thing it does is
|
||||||
|
suspend - the control task will resume it when ready. */
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Just count up to a value then suspend. */
|
||||||
|
( *pulCounter )++;
|
||||||
|
|
||||||
|
if( *pulCounter >= priMAX_COUNT )
|
||||||
|
{
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just keep counting the shared variable up. The control task will suspend
|
||||||
|
* this task when it wants.
|
||||||
|
*/
|
||||||
|
static portTASK_FUNCTION( vContinuousIncrementTask, pvParameters )
|
||||||
|
{
|
||||||
|
volatile uint32_t *pulCounter;
|
||||||
|
UBaseType_t uxOurPriority;
|
||||||
|
|
||||||
|
/* Take a pointer to the shared variable from the parameters passed into
|
||||||
|
the task. */
|
||||||
|
pulCounter = ( uint32_t * ) pvParameters;
|
||||||
|
|
||||||
|
/* Query our priority so we can raise it when exclusive access to the
|
||||||
|
shared variable is required. */
|
||||||
|
uxOurPriority = uxTaskPriorityGet( NULL );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Raise the priority above the controller task to ensure a context
|
||||||
|
switch does not occur while the variable is being accessed. */
|
||||||
|
vTaskPrioritySet( NULL, uxOurPriority + 1 );
|
||||||
|
{
|
||||||
|
configASSERT( ( uxTaskPriorityGet( NULL ) == ( uxOurPriority + 1 ) ) );
|
||||||
|
( *pulCounter )++;
|
||||||
|
}
|
||||||
|
vTaskPrioritySet( NULL, uxOurPriority );
|
||||||
|
|
||||||
|
#if( configUSE_PREEMPTION == 0 )
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
configASSERT( ( uxTaskPriorityGet( NULL ) == uxOurPriority ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Controller task as described above.
|
||||||
|
*/
|
||||||
|
static portTASK_FUNCTION( vCounterControlTask, pvParameters )
|
||||||
|
{
|
||||||
|
uint32_t ulLastCounter;
|
||||||
|
short sLoops;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* Just to stop warning messages. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Start with the counter at zero. */
|
||||||
|
ulCounter = ( uint32_t ) 0;
|
||||||
|
|
||||||
|
/* First section : */
|
||||||
|
|
||||||
|
/* Check the continuous count task is running. */
|
||||||
|
for( sLoops = 0; sLoops < priLOOPS; sLoops++ )
|
||||||
|
{
|
||||||
|
/* Suspend the continuous count task so we can take a mirror of the
|
||||||
|
shared variable without risk of corruption. This is not really
|
||||||
|
needed as the other task raises its priority above this task's
|
||||||
|
priority. */
|
||||||
|
vTaskSuspend( xContinuousIncrementHandle );
|
||||||
|
{
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xContinuousIncrementHandle ) == eSuspended );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
ulLastCounter = ulCounter;
|
||||||
|
}
|
||||||
|
vTaskResume( xContinuousIncrementHandle );
|
||||||
|
|
||||||
|
#if( configUSE_PREEMPTION == 0 )
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xContinuousIncrementHandle ) == eReady );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
/* Now delay to ensure the other task has processor time. */
|
||||||
|
vTaskDelay( priSLEEP_TIME );
|
||||||
|
|
||||||
|
/* Check the shared variable again. This time to ensure mutual
|
||||||
|
exclusion the whole scheduler will be locked. This is just for
|
||||||
|
demo purposes! */
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
if( ulLastCounter == ulCounter )
|
||||||
|
{
|
||||||
|
/* The shared variable has not changed. There is a problem
|
||||||
|
with the continuous count task so flag an error. */
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xTaskResumeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Second section: */
|
||||||
|
|
||||||
|
/* Suspend the continuous counter task so it stops accessing the shared
|
||||||
|
variable. */
|
||||||
|
vTaskSuspend( xContinuousIncrementHandle );
|
||||||
|
|
||||||
|
/* Reset the variable. */
|
||||||
|
ulCounter = ( uint32_t ) 0;
|
||||||
|
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xLimitedIncrementHandle ) == eSuspended );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
/* Resume the limited count task which has a higher priority than us.
|
||||||
|
We should therefore not return from this call until the limited count
|
||||||
|
task has suspended itself with a known value in the counter variable. */
|
||||||
|
vTaskResume( xLimitedIncrementHandle );
|
||||||
|
|
||||||
|
#if( configUSE_PREEMPTION == 0 )
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This task should not run again until xLimitedIncrementHandle has
|
||||||
|
suspended itself. */
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xLimitedIncrementHandle ) == eSuspended );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
/* Does the counter variable have the expected value? */
|
||||||
|
if( ulCounter != priMAX_COUNT )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If no errors have occurred then increment the check variable. */
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
usCheckVariable++;
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resume the continuous count task and do it all again. */
|
||||||
|
vTaskResume( xContinuousIncrementHandle );
|
||||||
|
|
||||||
|
#if( configUSE_PREEMPTION == 0 )
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vQueueSendWhenSuspendedTask, pvParameters )
|
||||||
|
{
|
||||||
|
static uint32_t ulValueToSend = ( uint32_t ) 0;
|
||||||
|
|
||||||
|
/* Just to stop warning messages. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
/* We must not block while the scheduler is suspended! */
|
||||||
|
if( xQueueSend( xSuspendedTestQueue, ( void * ) &ulValueToSend, priNO_BLOCK ) != pdTRUE )
|
||||||
|
{
|
||||||
|
xSuspendedQueueSendError = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xTaskResumeAll();
|
||||||
|
|
||||||
|
vTaskDelay( priSLEEP_TIME );
|
||||||
|
|
||||||
|
++ulValueToSend;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vQueueReceiveWhenSuspendedTask, pvParameters )
|
||||||
|
{
|
||||||
|
uint32_t ulReceivedValue;
|
||||||
|
BaseType_t xGotValue;
|
||||||
|
|
||||||
|
/* Just to stop warning messages. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Suspending the scheduler here is fairly pointless and
|
||||||
|
undesirable for a normal application. It is done here purely
|
||||||
|
to test the scheduler. The inner xTaskResumeAll() should
|
||||||
|
never return pdTRUE as the scheduler is still locked by the
|
||||||
|
outer call. */
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK );
|
||||||
|
}
|
||||||
|
if( xTaskResumeAll() != pdFALSE )
|
||||||
|
{
|
||||||
|
xSuspendedQueueReceiveError = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xTaskResumeAll();
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
{
|
||||||
|
taskYIELD();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} while( xGotValue == pdFALSE );
|
||||||
|
|
||||||
|
if( ulReceivedValue != ulExpectedValue )
|
||||||
|
{
|
||||||
|
xSuspendedQueueReceiveError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xSuspendedQueueReceiveError != pdTRUE )
|
||||||
|
{
|
||||||
|
/* Only increment the variable if an error has not occurred. This
|
||||||
|
allows xAreDynamicPriorityTasksStillRunning() to check for stalled
|
||||||
|
tasks as well as explicit errors. */
|
||||||
|
++ulExpectedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Called to check that all the created tasks are still running without error. */
|
||||||
|
BaseType_t xAreDynamicPriorityTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
/* Keep a history of the check variables so we know if it has been incremented
|
||||||
|
since the last call. */
|
||||||
|
static uint16_t usLastTaskCheck = ( uint16_t ) 0;
|
||||||
|
static uint32_t ulLastExpectedValue = ( uint32_t ) 0U;
|
||||||
|
BaseType_t xReturn = pdTRUE;
|
||||||
|
|
||||||
|
/* Check the tasks are still running by ensuring the check variable
|
||||||
|
is still incrementing. */
|
||||||
|
|
||||||
|
if( usCheckVariable == usLastTaskCheck )
|
||||||
|
{
|
||||||
|
/* The check has not incremented so an error exists. */
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ulExpectedValue == ulLastExpectedValue )
|
||||||
|
{
|
||||||
|
/* The value being received by the queue receive task has not
|
||||||
|
incremented so an error exists. */
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xSuspendedQueueSendError == pdTRUE )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xSuspendedQueueReceiveError == pdTRUE )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
usLastTaskCheck = usCheckVariable;
|
||||||
|
ulLastExpectedValue = ulExpectedValue;
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 version of flash .c is for use on systems that have limited stack space
|
||||||
|
* and no display facilities. The complete version can be found in the
|
||||||
|
* Demo/Common/Full directory.
|
||||||
|
*
|
||||||
|
* Three tasks are created, each of which flash an LED at a different rate. The first
|
||||||
|
* LED flashes every 200ms, the second every 400ms, the third every 600ms.
|
||||||
|
*
|
||||||
|
* The LED flash tasks provide instant visual feedback. They show that the scheduler
|
||||||
|
* is still operational.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "partest.h"
|
||||||
|
#include "flash.h"
|
||||||
|
|
||||||
|
#define ledSTACK_SIZE configMINIMAL_STACK_SIZE
|
||||||
|
#define ledNUMBER_OF_LEDS ( 3 )
|
||||||
|
#define ledFLASH_RATE_BASE ( ( TickType_t ) 333 )
|
||||||
|
|
||||||
|
/* Variable used by the created tasks to calculate the LED number to use, and
|
||||||
|
the rate at which they should flash the LED. */
|
||||||
|
static volatile UBaseType_t uxFlashTaskNumber = 0;
|
||||||
|
|
||||||
|
/* The task that is created three times. */
|
||||||
|
static portTASK_FUNCTION_PROTO( vLEDFlashTask, pvParameters );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartLEDFlashTasks( UBaseType_t uxPriority )
|
||||||
|
{
|
||||||
|
BaseType_t xLEDTask;
|
||||||
|
|
||||||
|
/* Create the three tasks. */
|
||||||
|
for( xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask )
|
||||||
|
{
|
||||||
|
/* Spawn the task. */
|
||||||
|
xTaskCreate( vLEDFlashTask, "LEDx", ledSTACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vLEDFlashTask, pvParameters )
|
||||||
|
{
|
||||||
|
TickType_t xFlashRate, xLastFlashTime;
|
||||||
|
UBaseType_t uxLED;
|
||||||
|
|
||||||
|
/* The parameters are not used. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
/* Calculate the LED and flash rate. */
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
/* See which of the eight LED's we should use. */
|
||||||
|
uxLED = uxFlashTaskNumber;
|
||||||
|
|
||||||
|
/* Update so the next task uses the next LED. */
|
||||||
|
uxFlashTaskNumber++;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
|
||||||
|
xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( TickType_t ) uxLED );
|
||||||
|
xFlashRate /= portTICK_PERIOD_MS;
|
||||||
|
|
||||||
|
/* We will turn the LED on and off again in the delay period, so each
|
||||||
|
delay is only half the total period. */
|
||||||
|
xFlashRate /= ( TickType_t ) 2;
|
||||||
|
|
||||||
|
/* We need to initialise xLastFlashTime prior to the first call to
|
||||||
|
vTaskDelayUntil(). */
|
||||||
|
xLastFlashTime = xTaskGetTickCount();
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
/* Delay for half the flash period then turn the LED on. */
|
||||||
|
vTaskDelayUntil( &xLastFlashTime, xFlashRate );
|
||||||
|
vParTestToggleLED( uxLED );
|
||||||
|
|
||||||
|
/* Delay for half the flash period then turn the LED off. */
|
||||||
|
vTaskDelayUntil( &xLastFlashTime, xFlashRate );
|
||||||
|
vParTestToggleLED( uxLED );
|
||||||
|
}
|
||||||
|
} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repeatedly toggles one or more LEDs using software timers - one timer per
|
||||||
|
* LED.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "timers.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "partest.h"
|
||||||
|
#include "flash_timer.h"
|
||||||
|
|
||||||
|
/* The toggle rates are all a multple of ledFLASH_RATE_BASE. */
|
||||||
|
#define ledFLASH_RATE_BASE ( ( ( TickType_t ) 333 ) / portTICK_PERIOD_MS )
|
||||||
|
|
||||||
|
/* A block time of zero simple means "don't block". */
|
||||||
|
#define ledDONT_BLOCK ( ( TickType_t ) 0 )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The callback function used by each LED flashing timer. All the timers use
|
||||||
|
* this function, and the timer ID is used within the function to determine
|
||||||
|
* which timer has actually expired.
|
||||||
|
*/
|
||||||
|
static void prvLEDTimerCallback( TimerHandle_t xTimer );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartLEDFlashTimers( UBaseType_t uxNumberOfLEDs )
|
||||||
|
{
|
||||||
|
UBaseType_t uxLEDTimer;
|
||||||
|
TimerHandle_t xTimer;
|
||||||
|
|
||||||
|
/* Create and start the requested number of timers. */
|
||||||
|
for( uxLEDTimer = 0; uxLEDTimer < uxNumberOfLEDs; ++uxLEDTimer )
|
||||||
|
{
|
||||||
|
/* Create the timer. */
|
||||||
|
xTimer = xTimerCreate( "Flasher", /* A text name, purely to help debugging. */
|
||||||
|
ledFLASH_RATE_BASE * ( uxLEDTimer + 1 ),/* The timer period, which is a multiple of ledFLASH_RATE_BASE. */
|
||||||
|
pdTRUE, /* This is an auto-reload timer, so xAutoReload is set to pdTRUE. */
|
||||||
|
( void * ) uxLEDTimer, /* The ID is used to identify the timer within the timer callback function, as each timer uses the same callback. */
|
||||||
|
prvLEDTimerCallback /* Each timer uses the same callback. */
|
||||||
|
);
|
||||||
|
|
||||||
|
/* If the timer was created successfully, attempt to start it. If the
|
||||||
|
scheduler has not yet been started then the timer command queue must
|
||||||
|
be long enough to hold each command sent to it until such time that the
|
||||||
|
scheduler is started. The timer command queue length is set by
|
||||||
|
configTIMER_QUEUE_LENGTH in FreeRTOSConfig.h. */
|
||||||
|
if( xTimer != NULL )
|
||||||
|
{
|
||||||
|
xTimerStart( xTimer, ledDONT_BLOCK );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvLEDTimerCallback( TimerHandle_t xTimer )
|
||||||
|
{
|
||||||
|
BaseType_t xTimerID;
|
||||||
|
|
||||||
|
/* The timer ID is used to identify the timer that has actually expired as
|
||||||
|
each timer uses the same callback. The ID is then also used as the number
|
||||||
|
of the LED that is to be toggled. */
|
||||||
|
xTimerID = ( BaseType_t ) pvTimerGetTimerID( xTimer );
|
||||||
|
vParTestToggleLED( xTimerID );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,383 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates eight tasks, each of which loops continuously performing a floating
|
||||||
|
* point calculation.
|
||||||
|
*
|
||||||
|
* All the tasks run at the idle priority and never block or yield. This causes
|
||||||
|
* all eight tasks to time slice with the idle task. Running at the idle
|
||||||
|
* priority means that these tasks will get pre-empted any time another task is
|
||||||
|
* ready to run or a time slice occurs. More often than not the pre-emption
|
||||||
|
* will occur mid calculation, creating a good test of the schedulers context
|
||||||
|
* switch mechanism - a calculation producing an unexpected result could be a
|
||||||
|
* symptom of a corruption in the context of a task.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "flop.h"
|
||||||
|
|
||||||
|
#define mathSTACK_SIZE configMINIMAL_STACK_SIZE
|
||||||
|
#define mathNUMBER_OF_TASKS ( 4 )
|
||||||
|
|
||||||
|
/* Four tasks, each of which performs a different floating point calculation.
|
||||||
|
Each of the four is created twice. */
|
||||||
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters );
|
||||||
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters );
|
||||||
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters );
|
||||||
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters );
|
||||||
|
|
||||||
|
/* These variables are used to check that all the tasks are still running. If a
|
||||||
|
task gets a calculation wrong it will stop setting its check variable. */
|
||||||
|
static volatile uint16_t usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 };
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartMathTasks( UBaseType_t uxPriority )
|
||||||
|
{
|
||||||
|
xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vCompetingMathTask1, pvParameters )
|
||||||
|
{
|
||||||
|
volatile portDOUBLE d1, d2, d3, d4;
|
||||||
|
volatile uint16_t *pusTaskCheckVariable;
|
||||||
|
volatile portDOUBLE dAnswer;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* Some ports require that tasks that use a hardware floating point unit
|
||||||
|
tell the kernel that they require a floating point context before any
|
||||||
|
floating point instructions are executed. */
|
||||||
|
portTASK_USES_FLOATING_POINT();
|
||||||
|
|
||||||
|
d1 = 123.4567;
|
||||||
|
d2 = 2345.6789;
|
||||||
|
d3 = -918.222;
|
||||||
|
|
||||||
|
dAnswer = ( d1 + d2 ) * d3;
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
||||||
|
|
||||||
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
d1 = 123.4567;
|
||||||
|
d2 = 2345.6789;
|
||||||
|
d3 = -918.222;
|
||||||
|
|
||||||
|
d4 = ( d1 + d2 ) * d3;
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If the calculation does not match the expected constant, stop the
|
||||||
|
increment of the check variable. */
|
||||||
|
if( fabs( d4 - dAnswer ) > 0.001 )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct then set set the check
|
||||||
|
variable. The check variable will get set to pdFALSE each time
|
||||||
|
xAreMathsTaskStillRunning() is executed. */
|
||||||
|
( *pusTaskCheckVariable ) = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vCompetingMathTask2, pvParameters )
|
||||||
|
{
|
||||||
|
volatile portDOUBLE d1, d2, d3, d4;
|
||||||
|
volatile uint16_t *pusTaskCheckVariable;
|
||||||
|
volatile portDOUBLE dAnswer;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* Some ports require that tasks that use a hardware floating point unit
|
||||||
|
tell the kernel that they require a floating point context before any
|
||||||
|
floating point instructions are executed. */
|
||||||
|
portTASK_USES_FLOATING_POINT();
|
||||||
|
|
||||||
|
d1 = -389.38;
|
||||||
|
d2 = 32498.2;
|
||||||
|
d3 = -2.0001;
|
||||||
|
|
||||||
|
dAnswer = ( d1 / d2 ) * d3;
|
||||||
|
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
||||||
|
|
||||||
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
d1 = -389.38;
|
||||||
|
d2 = 32498.2;
|
||||||
|
d3 = -2.0001;
|
||||||
|
|
||||||
|
d4 = ( d1 / d2 ) * d3;
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If the calculation does not match the expected constant, stop the
|
||||||
|
increment of the check variable. */
|
||||||
|
if( fabs( d4 - dAnswer ) > 0.001 )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct then set set the check
|
||||||
|
variable. The check variable will get set to pdFALSE each time
|
||||||
|
xAreMathsTaskStillRunning() is executed. */
|
||||||
|
( *pusTaskCheckVariable ) = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vCompetingMathTask3, pvParameters )
|
||||||
|
{
|
||||||
|
volatile portDOUBLE *pdArray, dTotal1, dTotal2, dDifference;
|
||||||
|
volatile uint16_t *pusTaskCheckVariable;
|
||||||
|
const size_t xArraySize = 10;
|
||||||
|
size_t xPosition;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* Some ports require that tasks that use a hardware floating point unit
|
||||||
|
tell the kernel that they require a floating point context before any
|
||||||
|
floating point instructions are executed. */
|
||||||
|
portTASK_USES_FLOATING_POINT();
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
||||||
|
|
||||||
|
pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) );
|
||||||
|
|
||||||
|
/* Keep filling an array, keeping a running total of the values placed in the
|
||||||
|
array. Then run through the array adding up all the values. If the two totals
|
||||||
|
do not match, stop the check variable from incrementing. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
dTotal1 = 0.0;
|
||||||
|
dTotal2 = 0.0;
|
||||||
|
|
||||||
|
for( xPosition = 0; xPosition < xArraySize; xPosition++ )
|
||||||
|
{
|
||||||
|
pdArray[ xPosition ] = ( portDOUBLE ) xPosition + 5.5;
|
||||||
|
dTotal1 += ( portDOUBLE ) xPosition + 5.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for( xPosition = 0; xPosition < xArraySize; xPosition++ )
|
||||||
|
{
|
||||||
|
dTotal2 += pdArray[ xPosition ];
|
||||||
|
}
|
||||||
|
|
||||||
|
dDifference = dTotal1 - dTotal2;
|
||||||
|
if( fabs( dDifference ) > 0.001 )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct then set set the check
|
||||||
|
variable. The check variable will get set to pdFALSE each time
|
||||||
|
xAreMathsTaskStillRunning() is executed. */
|
||||||
|
( *pusTaskCheckVariable ) = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vCompetingMathTask4, pvParameters )
|
||||||
|
{
|
||||||
|
volatile portDOUBLE *pdArray, dTotal1, dTotal2, dDifference;
|
||||||
|
volatile uint16_t *pusTaskCheckVariable;
|
||||||
|
const size_t xArraySize = 10;
|
||||||
|
size_t xPosition;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* Some ports require that tasks that use a hardware floating point unit
|
||||||
|
tell the kernel that they require a floating point context before any
|
||||||
|
floating point instructions are executed. */
|
||||||
|
portTASK_USES_FLOATING_POINT();
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
||||||
|
|
||||||
|
pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) );
|
||||||
|
|
||||||
|
/* Keep filling an array, keeping a running total of the values placed in the
|
||||||
|
array. Then run through the array adding up all the values. If the two totals
|
||||||
|
do not match, stop the check variable from incrementing. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
dTotal1 = 0.0;
|
||||||
|
dTotal2 = 0.0;
|
||||||
|
|
||||||
|
for( xPosition = 0; xPosition < xArraySize; xPosition++ )
|
||||||
|
{
|
||||||
|
pdArray[ xPosition ] = ( portDOUBLE ) xPosition * 12.123;
|
||||||
|
dTotal1 += ( portDOUBLE ) xPosition * 12.123;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for( xPosition = 0; xPosition < xArraySize; xPosition++ )
|
||||||
|
{
|
||||||
|
dTotal2 += pdArray[ xPosition ];
|
||||||
|
}
|
||||||
|
|
||||||
|
dDifference = dTotal1 - dTotal2;
|
||||||
|
if( fabs( dDifference ) > 0.001 )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct then set set the check
|
||||||
|
variable. The check variable will get set to pdFALSE each time
|
||||||
|
xAreMathsTaskStillRunning() is executed. */
|
||||||
|
( *pusTaskCheckVariable ) = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running. */
|
||||||
|
BaseType_t xAreMathsTaskStillRunning( void )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn = pdPASS, xTask;
|
||||||
|
|
||||||
|
/* Check the maths tasks are still running by ensuring their check variables
|
||||||
|
have been set to pdPASS. */
|
||||||
|
for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )
|
||||||
|
{
|
||||||
|
if( usTaskCheck[ xTask ] != pdTRUE )
|
||||||
|
{
|
||||||
|
/* The check has not been set so the associated task has either
|
||||||
|
stalled or detected an error. */
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Reset the variable so it can be checked again the next time this
|
||||||
|
function is executed. */
|
||||||
|
usTaskCheck[ xTask ] = pdFALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,201 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates one or more tasks that repeatedly perform a set of integer
|
||||||
|
* calculations. The result of each run-time calculation is compared to the
|
||||||
|
* known expected result - with a mismatch being indicative of an error in the
|
||||||
|
* context switch mechanism.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "integer.h"
|
||||||
|
|
||||||
|
/* The constants used in the calculation. */
|
||||||
|
#define intgCONST1 ( ( long ) 123 )
|
||||||
|
#define intgCONST2 ( ( long ) 234567 )
|
||||||
|
#define intgCONST3 ( ( long ) -3 )
|
||||||
|
#define intgCONST4 ( ( long ) 7 )
|
||||||
|
#define intgEXPECTED_ANSWER ( ( ( intgCONST1 + intgCONST2 ) * intgCONST3 ) / intgCONST4 )
|
||||||
|
|
||||||
|
#define intgSTACK_SIZE configMINIMAL_STACK_SIZE
|
||||||
|
|
||||||
|
/* As this is the minimal version, we will only create one task. */
|
||||||
|
#define intgNUMBER_OF_TASKS ( 1 )
|
||||||
|
|
||||||
|
/* The task function. Repeatedly performs a 32 bit calculation, checking the
|
||||||
|
result against the expected result. If the result is incorrect then the
|
||||||
|
context switch must have caused some corruption. */
|
||||||
|
static portTASK_FUNCTION_PROTO( vCompeteingIntMathTask, pvParameters );
|
||||||
|
|
||||||
|
/* Variables that are set to true within the calculation task to indicate
|
||||||
|
that the task is still executing. The check task sets the variable back to
|
||||||
|
false, flagging an error if the variable is still false the next time it
|
||||||
|
is called. */
|
||||||
|
static volatile BaseType_t xTaskCheck[ intgNUMBER_OF_TASKS ] = { ( BaseType_t ) pdFALSE };
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartIntegerMathTasks( UBaseType_t uxPriority )
|
||||||
|
{
|
||||||
|
short sTask;
|
||||||
|
|
||||||
|
for( sTask = 0; sTask < intgNUMBER_OF_TASKS; sTask++ )
|
||||||
|
{
|
||||||
|
xTaskCreate( vCompeteingIntMathTask, "IntMath", intgSTACK_SIZE, ( void * ) &( xTaskCheck[ sTask ] ), uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vCompeteingIntMathTask, pvParameters )
|
||||||
|
{
|
||||||
|
/* These variables are all effectively set to constants so they are volatile to
|
||||||
|
ensure the compiler does not just get rid of them. */
|
||||||
|
volatile long lValue;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
volatile BaseType_t *pxTaskHasExecuted;
|
||||||
|
|
||||||
|
/* Set a pointer to the variable we are going to set to true each
|
||||||
|
iteration. This is also a good test of the parameter passing mechanism
|
||||||
|
within each port. */
|
||||||
|
pxTaskHasExecuted = ( volatile BaseType_t * ) pvParameters;
|
||||||
|
|
||||||
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Perform the calculation. This will store partial value in
|
||||||
|
registers, resulting in a good test of the context switch mechanism. */
|
||||||
|
lValue = intgCONST1;
|
||||||
|
lValue += intgCONST2;
|
||||||
|
|
||||||
|
/* Yield in case cooperative scheduling is being used. */
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
{
|
||||||
|
taskYIELD();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Finish off the calculation. */
|
||||||
|
lValue *= intgCONST3;
|
||||||
|
lValue /= intgCONST4;
|
||||||
|
|
||||||
|
/* If the calculation is found to be incorrect we stop setting the
|
||||||
|
TaskHasExecuted variable so the check task can see an error has
|
||||||
|
occurred. */
|
||||||
|
if( lValue != intgEXPECTED_ANSWER ) /*lint !e774 volatile used to prevent this being optimised out. */
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* We have not encountered any errors, so set the flag that show
|
||||||
|
we are still executing. This will be periodically cleared by
|
||||||
|
the check task. */
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
*pxTaskHasExecuted = pdTRUE;
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Yield in case cooperative scheduling is being used. */
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
{
|
||||||
|
taskYIELD();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running. */
|
||||||
|
BaseType_t xAreIntegerMathsTaskStillRunning( void )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn = pdTRUE;
|
||||||
|
short sTask;
|
||||||
|
|
||||||
|
/* Check the maths tasks are still running by ensuring their check variables
|
||||||
|
are still being set to true. */
|
||||||
|
for( sTask = 0; sTask < intgNUMBER_OF_TASKS; sTask++ )
|
||||||
|
{
|
||||||
|
if( xTaskCheck[ sTask ] == pdFALSE )
|
||||||
|
{
|
||||||
|
/* The check has not incremented so an error exists. */
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the check variable so we can tell if it has been set by
|
||||||
|
the next time around. */
|
||||||
|
xTaskCheck[ sTask ] = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,440 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
The tasks defined on this page demonstrate the use of recursive mutexes.
|
||||||
|
|
||||||
|
For recursive mutex functionality the created mutex should be created using
|
||||||
|
xSemaphoreCreateRecursiveMutex(), then be manipulated
|
||||||
|
using the xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() API
|
||||||
|
functions.
|
||||||
|
|
||||||
|
This demo creates three tasks all of which access the same recursive mutex:
|
||||||
|
|
||||||
|
prvRecursiveMutexControllingTask() has the highest priority so executes
|
||||||
|
first and grabs the mutex. It then performs some recursive accesses -
|
||||||
|
between each of which it sleeps for a short period to let the lower
|
||||||
|
priority tasks execute. When it has completed its demo functionality
|
||||||
|
it gives the mutex back before suspending itself.
|
||||||
|
|
||||||
|
prvRecursiveMutexBlockingTask() attempts to access the mutex by performing
|
||||||
|
a blocking 'take'. The blocking task has a lower priority than the
|
||||||
|
controlling task so by the time it executes the mutex has already been
|
||||||
|
taken by the controlling task, causing the blocking task to block. It
|
||||||
|
does not unblock until the controlling task has given the mutex back,
|
||||||
|
and it does not actually run until the controlling task has suspended
|
||||||
|
itself (due to the relative priorities). When it eventually does obtain
|
||||||
|
the mutex all it does is give the mutex back prior to also suspending
|
||||||
|
itself. At this point both the controlling task and the blocking task are
|
||||||
|
suspended.
|
||||||
|
|
||||||
|
prvRecursiveMutexPollingTask() runs at the idle priority. It spins round
|
||||||
|
a tight loop attempting to obtain the mutex with a non-blocking call. As
|
||||||
|
the lowest priority task it will not successfully obtain the mutex until
|
||||||
|
both the controlling and blocking tasks are suspended. Once it eventually
|
||||||
|
does obtain the mutex it first unsuspends both the controlling task and
|
||||||
|
blocking task prior to giving the mutex back - resulting in the polling
|
||||||
|
task temporarily inheriting the controlling tasks priority.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "semphr.h"
|
||||||
|
|
||||||
|
/* Demo app include files. */
|
||||||
|
#include "recmutex.h"
|
||||||
|
|
||||||
|
/* Priorities assigned to the three tasks. recmuCONTROLLING_TASK_PRIORITY can
|
||||||
|
be overridden by a definition in FreeRTOSConfig.h. */
|
||||||
|
#ifndef recmuCONTROLLING_TASK_PRIORITY
|
||||||
|
#define recmuCONTROLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||||
|
#endif
|
||||||
|
#define recmuBLOCKING_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||||
|
#define recmuPOLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 0 )
|
||||||
|
|
||||||
|
/* The recursive call depth. */
|
||||||
|
#define recmuMAX_COUNT ( 10 )
|
||||||
|
|
||||||
|
/* Misc. */
|
||||||
|
#define recmuSHORT_DELAY ( 20 / portTICK_PERIOD_MS )
|
||||||
|
#define recmuNO_DELAY ( ( TickType_t ) 0 )
|
||||||
|
#define recmuEIGHT_TICK_DELAY ( ( TickType_t ) 8 )
|
||||||
|
|
||||||
|
/* The three tasks as described at the top of this file. */
|
||||||
|
static void prvRecursiveMutexControllingTask( void *pvParameters );
|
||||||
|
static void prvRecursiveMutexBlockingTask( void *pvParameters );
|
||||||
|
static void prvRecursiveMutexPollingTask( void *pvParameters );
|
||||||
|
|
||||||
|
/* The mutex used by the demo. */
|
||||||
|
static SemaphoreHandle_t xMutex;
|
||||||
|
|
||||||
|
/* Variables used to detect and latch errors. */
|
||||||
|
static volatile BaseType_t xErrorOccurred = pdFALSE, xControllingIsSuspended = pdFALSE, xBlockingIsSuspended = pdFALSE;
|
||||||
|
static volatile UBaseType_t uxControllingCycles = 0, uxBlockingCycles = 0, uxPollingCycles = 0;
|
||||||
|
|
||||||
|
/* Handles of the two higher priority tasks, required so they can be resumed
|
||||||
|
(unsuspended). */
|
||||||
|
static TaskHandle_t xControllingTaskHandle, xBlockingTaskHandle;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartRecursiveMutexTasks( void )
|
||||||
|
{
|
||||||
|
/* Just creates the mutex and the three tasks. */
|
||||||
|
|
||||||
|
xMutex = xSemaphoreCreateRecursiveMutex();
|
||||||
|
|
||||||
|
/* 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, "Recursive_Mutex" );
|
||||||
|
|
||||||
|
|
||||||
|
if( xMutex != NULL )
|
||||||
|
{
|
||||||
|
xTaskCreate( prvRecursiveMutexControllingTask, "Rec1", configMINIMAL_STACK_SIZE, NULL, recmuCONTROLLING_TASK_PRIORITY, &xControllingTaskHandle );
|
||||||
|
xTaskCreate( prvRecursiveMutexBlockingTask, "Rec2", configMINIMAL_STACK_SIZE, NULL, recmuBLOCKING_TASK_PRIORITY, &xBlockingTaskHandle );
|
||||||
|
xTaskCreate( prvRecursiveMutexPollingTask, "Rec3", configMINIMAL_STACK_SIZE, NULL, recmuPOLLING_TASK_PRIORITY, NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvRecursiveMutexControllingTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
UBaseType_t ux;
|
||||||
|
|
||||||
|
/* Just to remove compiler warning. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Should not be able to 'give' the mutex, as we have not yet 'taken'
|
||||||
|
it. The first time through, the mutex will not have been used yet,
|
||||||
|
subsequent times through, at this point the mutex will be held by the
|
||||||
|
polling task. */
|
||||||
|
if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( ux = 0; ux < recmuMAX_COUNT; ux++ )
|
||||||
|
{
|
||||||
|
/* We should now be able to take the mutex as many times as
|
||||||
|
we like.
|
||||||
|
|
||||||
|
The first time through the mutex will be immediately available, on
|
||||||
|
subsequent times through the mutex will be held by the polling task
|
||||||
|
at this point and this Take will cause the polling task to inherit
|
||||||
|
the priority of this task. In this case the block time must be
|
||||||
|
long enough to ensure the polling task will execute again before the
|
||||||
|
block time expires. If the block time does expire then the error
|
||||||
|
flag will be set here. */
|
||||||
|
if( xSemaphoreTakeRecursive( xMutex, recmuEIGHT_TICK_DELAY ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure the other task attempting to access the mutex (and the
|
||||||
|
other demo tasks) are able to execute to ensure they either block
|
||||||
|
(where a block time is specified) or return an error (where no
|
||||||
|
block time is specified) as the mutex is held by this task. */
|
||||||
|
vTaskDelay( recmuSHORT_DELAY );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For each time we took the mutex, give it back. */
|
||||||
|
for( ux = 0; ux < recmuMAX_COUNT; ux++ )
|
||||||
|
{
|
||||||
|
/* Ensure the other task attempting to access the mutex (and the
|
||||||
|
other demo tasks) are able to execute. */
|
||||||
|
vTaskDelay( recmuSHORT_DELAY );
|
||||||
|
|
||||||
|
/* We should now be able to give the mutex as many times as we
|
||||||
|
took it. When the mutex is available again the Blocking task
|
||||||
|
should be unblocked but not run because it has a lower priority
|
||||||
|
than this task. The polling task should also not run at this point
|
||||||
|
as it too has a lower priority than this task. */
|
||||||
|
if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Having given it back the same number of times as it was taken, we
|
||||||
|
should no longer be the mutex owner, so the next give should fail. */
|
||||||
|
if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep count of the number of cycles this task has performed so a
|
||||||
|
stall can be detected. */
|
||||||
|
uxControllingCycles++;
|
||||||
|
|
||||||
|
/* Suspend ourselves so the blocking task can execute. */
|
||||||
|
xControllingIsSuspended = pdTRUE;
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
xControllingIsSuspended = pdFALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvRecursiveMutexBlockingTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
/* Just to remove compiler warning. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* This task will run while the controlling task is blocked, and the
|
||||||
|
controlling task will block only once it has the mutex - therefore
|
||||||
|
this call should block until the controlling task has given up the
|
||||||
|
mutex, and not actually execute past this call until the controlling
|
||||||
|
task is suspended. portMAX_DELAY - 1 is used instead of portMAX_DELAY
|
||||||
|
to ensure the task's state is reported as Blocked and not Suspended in
|
||||||
|
a later call to configASSERT() (within the polling task). */
|
||||||
|
if( xSemaphoreTakeRecursive( xMutex, ( portMAX_DELAY - 1 ) ) == pdPASS )
|
||||||
|
{
|
||||||
|
if( xControllingIsSuspended != pdTRUE )
|
||||||
|
{
|
||||||
|
/* Did not expect to execute until the controlling task was
|
||||||
|
suspended. */
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Give the mutex back before suspending ourselves to allow
|
||||||
|
the polling task to obtain the mutex. */
|
||||||
|
if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
xBlockingIsSuspended = pdTRUE;
|
||||||
|
vTaskSuspend( NULL );
|
||||||
|
xBlockingIsSuspended = pdFALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We should not leave the xSemaphoreTakeRecursive() function
|
||||||
|
until the mutex was obtained. */
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The controlling and blocking tasks should be in lock step. */
|
||||||
|
if( uxControllingCycles != ( uxBlockingCycles + 1 ) )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep count of the number of cycles this task has performed so a
|
||||||
|
stall can be detected. */
|
||||||
|
uxBlockingCycles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvRecursiveMutexPollingTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
/* Just to remove compiler warning. */
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Keep attempting to obtain the mutex. We should only obtain it when
|
||||||
|
the blocking task has suspended itself, which in turn should only
|
||||||
|
happen when the controlling task is also suspended. */
|
||||||
|
if( xSemaphoreTakeRecursive( xMutex, recmuNO_DELAY ) == pdPASS )
|
||||||
|
{
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xControllingTaskHandle ) == eSuspended );
|
||||||
|
configASSERT( eTaskGetState( xBlockingTaskHandle ) == eSuspended );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
/* Is the blocking task suspended? */
|
||||||
|
if( ( xBlockingIsSuspended != pdTRUE ) || ( xControllingIsSuspended != pdTRUE ) )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Keep count of the number of cycles this task has performed
|
||||||
|
so a stall can be detected. */
|
||||||
|
uxPollingCycles++;
|
||||||
|
|
||||||
|
/* We can resume the other tasks here even though they have a
|
||||||
|
higher priority than the polling task. When they execute they
|
||||||
|
will attempt to obtain the mutex but fail because the polling
|
||||||
|
task is still the mutex holder. The polling task (this task)
|
||||||
|
will then inherit the higher priority. The Blocking task will
|
||||||
|
block indefinitely when it attempts to obtain the mutex, the
|
||||||
|
Controlling task will only block for a fixed period and an
|
||||||
|
error will be latched if the polling task has not returned the
|
||||||
|
mutex by the time this fixed period has expired. */
|
||||||
|
vTaskResume( xBlockingTaskHandle );
|
||||||
|
vTaskResume( xControllingTaskHandle );
|
||||||
|
|
||||||
|
/* The other two tasks should now have executed and no longer
|
||||||
|
be suspended. */
|
||||||
|
if( ( xBlockingIsSuspended == pdTRUE ) || ( xControllingIsSuspended == pdTRUE ) )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if( INCLUDE_uxTaskPriorityGet == 1 )
|
||||||
|
{
|
||||||
|
/* Check priority inherited. */
|
||||||
|
configASSERT( uxTaskPriorityGet( NULL ) == recmuCONTROLLING_TASK_PRIORITY );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_uxTaskPriorityGet */
|
||||||
|
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xControllingTaskHandle ) == eBlocked );
|
||||||
|
configASSERT( eTaskGetState( xBlockingTaskHandle ) == eBlocked );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
/* Release the mutex, disinheriting the higher priority again. */
|
||||||
|
if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if( INCLUDE_uxTaskPriorityGet == 1 )
|
||||||
|
{
|
||||||
|
/* Check priority disinherited. */
|
||||||
|
configASSERT( uxTaskPriorityGet( NULL ) == recmuPOLLING_TASK_PRIORITY );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_uxTaskPriorityGet */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
{
|
||||||
|
taskYIELD();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running. */
|
||||||
|
BaseType_t xAreRecursiveMutexTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
static UBaseType_t uxLastControllingCycles = 0, uxLastBlockingCycles = 0, uxLastPollingCycles = 0;
|
||||||
|
|
||||||
|
/* Is the controlling task still cycling? */
|
||||||
|
if( uxLastControllingCycles == uxControllingCycles )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uxLastControllingCycles = uxControllingCycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is the blocking task still cycling? */
|
||||||
|
if( uxLastBlockingCycles == uxBlockingCycles )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uxLastBlockingCycles = uxBlockingCycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is the polling task still cycling? */
|
||||||
|
if( uxLastPollingCycles == uxPollingCycles )
|
||||||
|
{
|
||||||
|
xErrorOccurred = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uxLastPollingCycles = uxPollingCycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xErrorOccurred == pdTRUE )
|
||||||
|
{
|
||||||
|
xReturn = pdFAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,298 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates two sets of two tasks. The tasks within a set share a variable, access
|
||||||
|
* to which is guarded by a semaphore.
|
||||||
|
*
|
||||||
|
* Each task starts by attempting to obtain the semaphore. On obtaining a
|
||||||
|
* semaphore a task checks to ensure that the guarded variable has an expected
|
||||||
|
* value. It then clears the variable to zero before counting it back up to the
|
||||||
|
* expected value in increments of 1. After each increment the variable is checked
|
||||||
|
* to ensure it contains the value to which it was just set. When the starting
|
||||||
|
* value is again reached the task releases the semaphore giving the other task in
|
||||||
|
* the set a chance to do exactly the same thing. The starting value is high
|
||||||
|
* enough to ensure that a tick is likely to occur during the incrementing loop.
|
||||||
|
*
|
||||||
|
* An error is flagged if at any time during the process a shared variable is
|
||||||
|
* found to have a value other than that expected. Such an occurrence would
|
||||||
|
* suggest an error in the mutual exclusion mechanism by which access to the
|
||||||
|
* variable is restricted.
|
||||||
|
*
|
||||||
|
* The first set of two tasks poll their semaphore. The second set use blocking
|
||||||
|
* calls.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "semphr.h"
|
||||||
|
|
||||||
|
/* Demo app include files. */
|
||||||
|
#include "semtest.h"
|
||||||
|
|
||||||
|
/* The value to which the shared variables are counted. */
|
||||||
|
#define semtstBLOCKING_EXPECTED_VALUE ( ( uint32_t ) 0xfff )
|
||||||
|
#define semtstNON_BLOCKING_EXPECTED_VALUE ( ( uint32_t ) 0xff )
|
||||||
|
|
||||||
|
#define semtstSTACK_SIZE configMINIMAL_STACK_SIZE
|
||||||
|
|
||||||
|
#define semtstNUM_TASKS ( 4 )
|
||||||
|
|
||||||
|
#define semtstDELAY_FACTOR ( ( TickType_t ) 10 )
|
||||||
|
|
||||||
|
/* The task function as described at the top of the file. */
|
||||||
|
static portTASK_FUNCTION_PROTO( prvSemaphoreTest, pvParameters );
|
||||||
|
|
||||||
|
/* Structure used to pass parameters to each task. */
|
||||||
|
typedef struct SEMAPHORE_PARAMETERS
|
||||||
|
{
|
||||||
|
SemaphoreHandle_t xSemaphore;
|
||||||
|
volatile uint32_t *pulSharedVariable;
|
||||||
|
TickType_t xBlockTime;
|
||||||
|
} xSemaphoreParameters;
|
||||||
|
|
||||||
|
/* Variables used to check that all the tasks are still running without errors. */
|
||||||
|
static volatile short sCheckVariables[ semtstNUM_TASKS ] = { 0 };
|
||||||
|
static volatile short sNextCheckVariable = 0;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartSemaphoreTasks( UBaseType_t uxPriority )
|
||||||
|
{
|
||||||
|
xSemaphoreParameters *pxFirstSemaphoreParameters, *pxSecondSemaphoreParameters;
|
||||||
|
const TickType_t xBlockTime = ( TickType_t ) 100;
|
||||||
|
|
||||||
|
/* Create the structure used to pass parameters to the first two tasks. */
|
||||||
|
pxFirstSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) );
|
||||||
|
|
||||||
|
if( pxFirstSemaphoreParameters != NULL )
|
||||||
|
{
|
||||||
|
/* Create the semaphore used by the first two tasks. */
|
||||||
|
pxFirstSemaphoreParameters->xSemaphore = xSemaphoreCreateBinary();
|
||||||
|
xSemaphoreGive( pxFirstSemaphoreParameters->xSemaphore );
|
||||||
|
|
||||||
|
if( pxFirstSemaphoreParameters->xSemaphore != NULL )
|
||||||
|
{
|
||||||
|
/* Create the variable which is to be shared by the first two tasks. */
|
||||||
|
pxFirstSemaphoreParameters->pulSharedVariable = ( uint32_t * ) pvPortMalloc( sizeof( uint32_t ) );
|
||||||
|
|
||||||
|
/* Initialise the share variable to the value the tasks expect. */
|
||||||
|
*( pxFirstSemaphoreParameters->pulSharedVariable ) = semtstNON_BLOCKING_EXPECTED_VALUE;
|
||||||
|
|
||||||
|
/* The first two tasks do not block on semaphore calls. */
|
||||||
|
pxFirstSemaphoreParameters->xBlockTime = ( TickType_t ) 0;
|
||||||
|
|
||||||
|
/* Spawn the first two tasks. As they poll they operate at the idle priority. */
|
||||||
|
xTaskCreate( prvSemaphoreTest, "PolSEM1", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL );
|
||||||
|
xTaskCreate( prvSemaphoreTest, "PolSEM2", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do exactly the same to create the second set of tasks, only this time
|
||||||
|
provide a block time for the semaphore calls. */
|
||||||
|
pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) );
|
||||||
|
if( pxSecondSemaphoreParameters != NULL )
|
||||||
|
{
|
||||||
|
pxSecondSemaphoreParameters->xSemaphore = xSemaphoreCreateBinary();
|
||||||
|
xSemaphoreGive( pxSecondSemaphoreParameters->xSemaphore );
|
||||||
|
|
||||||
|
if( pxSecondSemaphoreParameters->xSemaphore != NULL )
|
||||||
|
{
|
||||||
|
pxSecondSemaphoreParameters->pulSharedVariable = ( uint32_t * ) pvPortMalloc( sizeof( uint32_t ) );
|
||||||
|
*( pxSecondSemaphoreParameters->pulSharedVariable ) = semtstBLOCKING_EXPECTED_VALUE;
|
||||||
|
pxSecondSemaphoreParameters->xBlockTime = xBlockTime / portTICK_PERIOD_MS;
|
||||||
|
|
||||||
|
xTaskCreate( prvSemaphoreTest, "BlkSEM1", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
|
xTaskCreate( prvSemaphoreTest, "BlkSEM2", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vQueueAddToRegistry() adds the semaphore to the registry, if one is
|
||||||
|
in use. The registry is provided as a means for kernel aware
|
||||||
|
debuggers to locate semaphores 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 ) pxFirstSemaphoreParameters->xSemaphore, "Counting_Sem_1" );
|
||||||
|
vQueueAddToRegistry( ( QueueHandle_t ) pxSecondSemaphoreParameters->xSemaphore, "Counting_Sem_2" );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( prvSemaphoreTest, pvParameters )
|
||||||
|
{
|
||||||
|
xSemaphoreParameters *pxParameters;
|
||||||
|
volatile uint32_t *pulSharedVariable, ulExpectedValue;
|
||||||
|
uint32_t ulCounter;
|
||||||
|
short sError = pdFALSE, sCheckVariableToUse;
|
||||||
|
|
||||||
|
/* See which check variable to use. sNextCheckVariable is not semaphore
|
||||||
|
protected! */
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
sCheckVariableToUse = sNextCheckVariable;
|
||||||
|
sNextCheckVariable++;
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
|
||||||
|
/* A structure is passed in as the parameter. This contains the shared
|
||||||
|
variable being guarded. */
|
||||||
|
pxParameters = ( xSemaphoreParameters * ) pvParameters;
|
||||||
|
pulSharedVariable = pxParameters->pulSharedVariable;
|
||||||
|
|
||||||
|
/* If we are blocking we use a much higher count to ensure loads of context
|
||||||
|
switches occur during the count. */
|
||||||
|
if( pxParameters->xBlockTime > ( TickType_t ) 0 )
|
||||||
|
{
|
||||||
|
ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ulExpectedValue = semtstNON_BLOCKING_EXPECTED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Try to obtain the semaphore. */
|
||||||
|
if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS )
|
||||||
|
{
|
||||||
|
/* We have the semaphore and so expect any other tasks using the
|
||||||
|
shared variable to have left it in the state we expect to find
|
||||||
|
it. */
|
||||||
|
if( *pulSharedVariable != ulExpectedValue )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the variable, then count it back up to the expected value
|
||||||
|
before releasing the semaphore. Would expect a context switch or
|
||||||
|
two during this time. */
|
||||||
|
for( ulCounter = ( uint32_t ) 0; ulCounter <= ulExpectedValue; ulCounter++ )
|
||||||
|
{
|
||||||
|
*pulSharedVariable = ulCounter;
|
||||||
|
if( *pulSharedVariable != ulCounter )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the semaphore, and if no errors have occurred increment the check
|
||||||
|
variable. */
|
||||||
|
if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
if( sCheckVariableToUse < semtstNUM_TASKS )
|
||||||
|
{
|
||||||
|
( sCheckVariables[ sCheckVariableToUse ] )++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have a block time then we are running at a priority higher
|
||||||
|
than the idle priority. This task takes a long time to complete
|
||||||
|
a cycle (deliberately so to test the guarding) so will be starving
|
||||||
|
out lower priority tasks. Block for some time to allow give lower
|
||||||
|
priority tasks some processor time. */
|
||||||
|
vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( pxParameters->xBlockTime == ( TickType_t ) 0 )
|
||||||
|
{
|
||||||
|
/* We have not got the semaphore yet, so no point using the
|
||||||
|
processor. We are not blocking when attempting to obtain the
|
||||||
|
semaphore. */
|
||||||
|
taskYIELD();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running. */
|
||||||
|
BaseType_t xAreSemaphoreTasksStillRunning( void )
|
||||||
|
{
|
||||||
|
static short sLastCheckVariables[ semtstNUM_TASKS ] = { 0 };
|
||||||
|
BaseType_t xTask, xReturn = pdTRUE;
|
||||||
|
|
||||||
|
for( xTask = 0; xTask < semtstNUM_TASKS; xTask++ )
|
||||||
|
{
|
||||||
|
if( sLastCheckVariables[ xTask ] == sCheckVariables[ xTask ] )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sLastCheckVariables[ xTask ] = sCheckVariables[ xTask ];
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,365 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates eight tasks, each of which loops continuously performing a floating
|
||||||
|
* point calculation - using single precision variables.
|
||||||
|
*
|
||||||
|
* All the tasks run at the idle priority and never block or yield. This causes
|
||||||
|
* all eight tasks to time slice with the idle task. Running at the idle priority
|
||||||
|
* means that these tasks will get pre-empted any time another task is ready to run
|
||||||
|
* or a time slice occurs. More often than not the pre-emption will occur mid
|
||||||
|
* calculation, creating a good test of the schedulers context switch mechanism - a
|
||||||
|
* calculation producing an unexpected result could be a symptom of a corruption in
|
||||||
|
* the context of a task.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* Scheduler include files. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Demo program include files. */
|
||||||
|
#include "flop.h"
|
||||||
|
|
||||||
|
#define mathSTACK_SIZE configMINIMAL_STACK_SIZE
|
||||||
|
#define mathNUMBER_OF_TASKS ( 8 )
|
||||||
|
|
||||||
|
/* Four tasks, each of which performs a different floating point calculation.
|
||||||
|
Each of the four is created twice. */
|
||||||
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters );
|
||||||
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters );
|
||||||
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters );
|
||||||
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters );
|
||||||
|
|
||||||
|
/* These variables are used to check that all the tasks are still running. If a
|
||||||
|
task gets a calculation wrong it will
|
||||||
|
stop incrementing its check variable. */
|
||||||
|
static volatile uint16_t usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 };
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vStartMathTasks( UBaseType_t uxPriority )
|
||||||
|
{
|
||||||
|
xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask1, "Math5", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask2, "Math6", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask3, "Math7", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL );
|
||||||
|
xTaskCreate( vCompetingMathTask4, "Math8", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vCompetingMathTask1, pvParameters )
|
||||||
|
{
|
||||||
|
volatile float f1, f2, f3, f4;
|
||||||
|
volatile uint16_t *pusTaskCheckVariable;
|
||||||
|
volatile float fAnswer;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
f1 = 123.4567F;
|
||||||
|
f2 = 2345.6789F;
|
||||||
|
f3 = -918.222F;
|
||||||
|
|
||||||
|
fAnswer = ( f1 + f2 ) * f3;
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
||||||
|
|
||||||
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
f1 = 123.4567F;
|
||||||
|
f2 = 2345.6789F;
|
||||||
|
f3 = -918.222F;
|
||||||
|
|
||||||
|
f4 = ( f1 + f2 ) * f3;
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If the calculation does not match the expected constant, stop the
|
||||||
|
increment of the check variable. */
|
||||||
|
if( fabs( f4 - fAnswer ) > 0.001F )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct, increment the check
|
||||||
|
variable so we know this task is still running okay. */
|
||||||
|
( *pusTaskCheckVariable )++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vCompetingMathTask2, pvParameters )
|
||||||
|
{
|
||||||
|
volatile float f1, f2, f3, f4;
|
||||||
|
volatile uint16_t *pusTaskCheckVariable;
|
||||||
|
volatile float fAnswer;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
f1 = -389.38F;
|
||||||
|
f2 = 32498.2F;
|
||||||
|
f3 = -2.0001F;
|
||||||
|
|
||||||
|
fAnswer = ( f1 / f2 ) * f3;
|
||||||
|
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
||||||
|
|
||||||
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
f1 = -389.38F;
|
||||||
|
f2 = 32498.2F;
|
||||||
|
f3 = -2.0001F;
|
||||||
|
|
||||||
|
f4 = ( f1 / f2 ) * f3;
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If the calculation does not match the expected constant, stop the
|
||||||
|
increment of the check variable. */
|
||||||
|
if( fabs( f4 - fAnswer ) > 0.001F )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct, increment the check
|
||||||
|
variable so we know
|
||||||
|
this task is still running okay. */
|
||||||
|
( *pusTaskCheckVariable )++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vCompetingMathTask3, pvParameters )
|
||||||
|
{
|
||||||
|
volatile float *pfArray, fTotal1, fTotal2, fDifference, fPosition;
|
||||||
|
volatile uint16_t *pusTaskCheckVariable;
|
||||||
|
const size_t xArraySize = 10;
|
||||||
|
size_t xPosition;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
||||||
|
|
||||||
|
pfArray = ( float * ) pvPortMalloc( xArraySize * sizeof( float ) );
|
||||||
|
|
||||||
|
/* Keep filling an array, keeping a running total of the values placed in the
|
||||||
|
array. Then run through the array adding up all the values. If the two totals
|
||||||
|
do not match, stop the check variable from incrementing. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
fTotal1 = 0.0F;
|
||||||
|
fTotal2 = 0.0F;
|
||||||
|
fPosition = 0.0F;
|
||||||
|
|
||||||
|
for( xPosition = 0; xPosition < xArraySize; xPosition++ )
|
||||||
|
{
|
||||||
|
pfArray[ xPosition ] = fPosition + 5.5F;
|
||||||
|
fTotal1 += fPosition + 5.5F;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for( xPosition = 0; xPosition < xArraySize; xPosition++ )
|
||||||
|
{
|
||||||
|
fTotal2 += pfArray[ xPosition ];
|
||||||
|
}
|
||||||
|
|
||||||
|
fDifference = fTotal1 - fTotal2;
|
||||||
|
if( fabs( fDifference ) > 0.001F )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct, increment the check
|
||||||
|
variable so we know this task is still running okay. */
|
||||||
|
( *pusTaskCheckVariable )++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portTASK_FUNCTION( vCompetingMathTask4, pvParameters )
|
||||||
|
{
|
||||||
|
volatile float *pfArray, fTotal1, fTotal2, fDifference, fPosition;
|
||||||
|
volatile uint16_t *pusTaskCheckVariable;
|
||||||
|
const size_t xArraySize = 10;
|
||||||
|
size_t xPosition;
|
||||||
|
short sError = pdFALSE;
|
||||||
|
|
||||||
|
/* The variable this task increments to show it is still running is passed in
|
||||||
|
as the parameter. */
|
||||||
|
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
||||||
|
|
||||||
|
pfArray = ( float * ) pvPortMalloc( xArraySize * sizeof( float ) );
|
||||||
|
|
||||||
|
/* Keep filling an array, keeping a running total of the values placed in the
|
||||||
|
array. Then run through the array adding up all the values. If the two totals
|
||||||
|
do not match, stop the check variable from incrementing. */
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
fTotal1 = 0.0F;
|
||||||
|
fTotal2 = 0.0F;
|
||||||
|
fPosition = 0.0F;
|
||||||
|
|
||||||
|
for( xPosition = 0; xPosition < xArraySize; xPosition++ )
|
||||||
|
{
|
||||||
|
pfArray[ xPosition ] = fPosition * 12.123F;
|
||||||
|
fTotal1 += fPosition * 12.123F;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for( xPosition = 0; xPosition < xArraySize; xPosition++ )
|
||||||
|
{
|
||||||
|
fTotal2 += pfArray[ xPosition ];
|
||||||
|
}
|
||||||
|
|
||||||
|
fDifference = fTotal1 - fTotal2;
|
||||||
|
if( fabs( fDifference ) > 0.001F )
|
||||||
|
{
|
||||||
|
sError = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
taskYIELD();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( sError == pdFALSE )
|
||||||
|
{
|
||||||
|
/* If the calculation has always been correct, increment the check
|
||||||
|
variable so we know this task is still running okay. */
|
||||||
|
( *pusTaskCheckVariable )++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is called to check that all the created tasks are still running. */
|
||||||
|
BaseType_t xAreMathsTaskStillRunning( void )
|
||||||
|
{
|
||||||
|
/* Keep a history of the check variables so we know if they have been incremented
|
||||||
|
since the last call. */
|
||||||
|
static uint16_t usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 };
|
||||||
|
BaseType_t xReturn = pdTRUE, xTask;
|
||||||
|
|
||||||
|
/* Check the maths tasks are still running by ensuring their check variables
|
||||||
|
are still incrementing. */
|
||||||
|
for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )
|
||||||
|
{
|
||||||
|
if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )
|
||||||
|
{
|
||||||
|
/* The check has not incremented so an error exists. */
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ];
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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_POLLED_Q_H
|
||||||
|
#define ALT_POLLED_Q_H
|
||||||
|
|
||||||
|
void vStartAltPolledQueueTasks( UBaseType_t uxPriority );
|
||||||
|
BaseType_t xAreAltPollingQueuesStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 BLOCK_Q_H
|
||||||
|
#define BLOCK_Q_H
|
||||||
|
|
||||||
|
void vStartBlockingQueueTasks( UBaseType_t uxPriority );
|
||||||
|
BaseType_t xAreBlockingQueuesStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 fairly comprehensive checks on the behaviour of event
|
||||||
|
* groups. It is not intended to be a user friendly demonstration of the event
|
||||||
|
* groups API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EVENT_GROUPS_DEMO_H
|
||||||
|
#define EVENT_GROUPS_DEMO_H
|
||||||
|
|
||||||
|
void vStartEventGroupTasks( void );
|
||||||
|
BaseType_t xAreEventGroupTasksStillRunning( void );
|
||||||
|
void vPeriodicEventGroupsProcessing( void );
|
||||||
|
|
||||||
|
#endif /* EVENT_GROUPS_DEMO_H */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 GEN_Q_TEST_H
|
||||||
|
#define GEN_Q_TEST_H
|
||||||
|
|
||||||
|
void vStartGenericQueueTasks( UBaseType_t uxPriority );
|
||||||
|
BaseType_t xAreGenericQueueTasksStillRunning( void );
|
||||||
|
void vMutexISRInteractionTest( void );
|
||||||
|
|
||||||
|
#endif /* GEN_Q_TEST_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 QUEUE_ACCESS_TEST
|
||||||
|
#define QUEUE_ACCESS_TEST
|
||||||
|
|
||||||
|
void vStartInterruptQueueTasks( void );
|
||||||
|
BaseType_t xAreIntQueueTasksStillRunning( void );
|
||||||
|
BaseType_t xFirstTimerHandler( void );
|
||||||
|
BaseType_t xSecondTimerHandler( void );
|
||||||
|
|
||||||
|
#endif /* QUEUE_ACCESS_TEST */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 POLLED_Q_H
|
||||||
|
#define POLLED_Q_H
|
||||||
|
|
||||||
|
void vStartPolledQueueTasks( UBaseType_t uxPriority );
|
||||||
|
BaseType_t xArePollingQueuesStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 Q_PEEK_TEST_H
|
||||||
|
#define Q_PEEK_TEST_H
|
||||||
|
|
||||||
|
void vStartQueuePeekTasks( void );
|
||||||
|
BaseType_t xAreQueuePeekTasksStillRunning( void );
|
||||||
|
|
||||||
|
#endif /* Q_PEEK_TEST_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 QUEUE_OVERWRITE_H
|
||||||
|
#define QUEUE_OVERWRITE_H
|
||||||
|
|
||||||
|
void vStartQueueOverwriteTask( UBaseType_t uxPriority );
|
||||||
|
BaseType_t xIsQueueOverwriteTaskStillRunning( void );
|
||||||
|
void vQueueOverwritePeriodicISRDemo( void );
|
||||||
|
|
||||||
|
#endif /* QUEUE_OVERWRITE_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 QUEUE_WAIT_MULTIPLE_H
|
||||||
|
#define QUEUE_WAIT_MULTIPLE_H
|
||||||
|
|
||||||
|
void vStartQueueSetTasks( void );
|
||||||
|
BaseType_t xAreQueueSetTasksStillRunning( void );
|
||||||
|
void vQueueSetAccessQueueSetFromISR( void );
|
||||||
|
|
||||||
|
#endif /* QUEUE_WAIT_MULTIPLE_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 TIMER_DEMO_H
|
||||||
|
#define TIMER_DEMO_H
|
||||||
|
|
||||||
|
void vStartTimerDemoTask( TickType_t xBaseFrequencyIn );
|
||||||
|
BaseType_t xAreTimerDemoTasksStillRunning( TickType_t xCycleFrequency );
|
||||||
|
void vTimerPeriodicISRTests( void );
|
||||||
|
|
||||||
|
#endif /* TIMER_DEMO_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 BLOCK_TIME_TEST_H
|
||||||
|
#define BLOCK_TIME_TEST_H
|
||||||
|
|
||||||
|
void vCreateBlockTimeTasks( void );
|
||||||
|
BaseType_t xAreBlockTimeTestTasksStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 COMTEST_H
|
||||||
|
#define COMTEST_H
|
||||||
|
|
||||||
|
void vAltStartComTestTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED );
|
||||||
|
void vStartComTestTasks( UBaseType_t uxPriority, eCOMPort ePort, eBaud eBaudRate );
|
||||||
|
BaseType_t xAreComTestTasksStillRunning( void );
|
||||||
|
void vComTestUnsuspendTask( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 COMTEST_H
|
||||||
|
#define COMTEST_H
|
||||||
|
|
||||||
|
void vAltStartComTestTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED );
|
||||||
|
BaseType_t xAreComTestTasksStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 COMTEST_STRINGS_H
|
||||||
|
#define COMTEST_STRINGS_H
|
||||||
|
|
||||||
|
void vStartComTestStringsTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED );
|
||||||
|
BaseType_t xAreComTestTasksStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 COUNT_SEMAPHORE_TEST_H
|
||||||
|
#define COUNT_SEMAPHORE_TEST_H
|
||||||
|
|
||||||
|
void vStartCountingSemaphoreTasks( void );
|
||||||
|
BaseType_t xAreCountingSemaphoreTasksStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 CRFLASH_LED_H
|
||||||
|
#define CRFLASH_LED_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the co-routines used to flash the LED's at different rates.
|
||||||
|
*
|
||||||
|
* @param uxPriority The number of 'fixed delay' co-routines to create. This
|
||||||
|
* also effects the number of LED's that will be utilised. For example,
|
||||||
|
* passing in 3 will cause LED's 0 to 2 to be utilised.
|
||||||
|
*/
|
||||||
|
void vStartFlashCoRoutines( UBaseType_t uxPriority );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return pdPASS or pdFAIL depending on whether an error has been detected
|
||||||
|
* or not.
|
||||||
|
*/
|
||||||
|
BaseType_t xAreFlashCoRoutinesStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 CRHOOK_H
|
||||||
|
#define CRHOOK_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the co-routines used to communicate wit the tick hook.
|
||||||
|
*/
|
||||||
|
void vStartHookCoRoutines( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return pdPASS or pdFAIL depending on whether an error has been detected
|
||||||
|
* or not.
|
||||||
|
*/
|
||||||
|
BaseType_t xAreHookCoRoutinesStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 SUICIDE_TASK_H
|
||||||
|
#define SUICIDE_TASK_H
|
||||||
|
|
||||||
|
void vCreateSuicidalTasks( UBaseType_t uxPriority );
|
||||||
|
BaseType_t xIsCreateTaskStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 DYNAMIC_MANIPULATION_H
|
||||||
|
#define DYNAMIC_MANIPULATION_H
|
||||||
|
|
||||||
|
void vStartDynamicPriorityTasks( void );
|
||||||
|
BaseType_t xAreDynamicPriorityTasksStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 FILE_IO_H
|
||||||
|
#define FILE_OI_H
|
||||||
|
|
||||||
|
void vDisplayMessage( const char * const pcMessageToPrint );
|
||||||
|
void vWriteMessageToDisk( const char * const pcMessage );
|
||||||
|
void vWriteBufferToDisk( const char * const pcBuffer, uint32_t ulBufferLength );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 FLASH_LED_H
|
||||||
|
#define FLASH_LED_H
|
||||||
|
|
||||||
|
void vStartLEDFlashTasks( UBaseType_t uxPriority );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 FLASH_TIMER_H
|
||||||
|
#define FLASH_TIMER_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates the LED flashing timers. xNumberOfLEDs specifies how many timers to
|
||||||
|
* create, with each timer toggling a different LED. The first LED to be
|
||||||
|
* toggled is LED 0, with subsequent LEDs following on in numerical order. Each
|
||||||
|
* timer uses the exact same callback function, with the timer ID being used
|
||||||
|
* within the callback function to determine which timer has actually expired
|
||||||
|
* (and therefore which LED to toggle).
|
||||||
|
*/
|
||||||
|
void vStartLEDFlashTimers( UBaseType_t uxNumberOfLEDs );
|
||||||
|
|
||||||
|
#endif /* FLASH_TIMER_H */
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 FLOP_TASKS_H
|
||||||
|
#define FLOP_TASKS_H
|
||||||
|
|
||||||
|
void vStartMathTasks( UBaseType_t uxPriority );
|
||||||
|
BaseType_t xAreMathsTaskStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 INTEGER_TASKS_H
|
||||||
|
#define INTEGER_TASKS_H
|
||||||
|
|
||||||
|
void vStartIntegerMathTasks( UBaseType_t uxPriority );
|
||||||
|
BaseType_t xAreIntegerMathsTaskStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 EVENTS_TEST_H
|
||||||
|
#define EVENTS_TEST_H
|
||||||
|
|
||||||
|
void vStartMultiEventTasks( void );
|
||||||
|
BaseType_t xAreMultiEventTasksStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 PARTEST_H
|
||||||
|
#define PARTEST_H
|
||||||
|
|
||||||
|
#define partstDEFAULT_PORT_ADDRESS ( ( uint16_t ) 0x378 )
|
||||||
|
|
||||||
|
void vParTestInitialise( void );
|
||||||
|
void vParTestSetLED( UBaseType_t uxLED, BaseType_t xValue );
|
||||||
|
void vParTestToggleLED( UBaseType_t uxLED );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 PRINT_H
|
||||||
|
#define PRINT_H
|
||||||
|
|
||||||
|
void vPrintInitialise( void );
|
||||||
|
void vPrintDisplayMessage( const char * const * pcMessageToSend );
|
||||||
|
const char *pcPrintGetNextMessage( TickType_t xPrintRate );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 RECURSIVE_MUTEX_TEST_H
|
||||||
|
#define RECURSIVE_MUTEX_TEST_H
|
||||||
|
|
||||||
|
void vStartRecursiveMutexTasks( void );
|
||||||
|
BaseType_t xAreRecursiveMutexTasksStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 SEMAPHORE_TEST_H
|
||||||
|
#define SEMAPHORE_TEST_H
|
||||||
|
|
||||||
|
void vStartSemaphoreTasks( UBaseType_t uxPriority );
|
||||||
|
BaseType_t xAreSemaphoreTasksStillRunning( void );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 SERIAL_COMMS_H
|
||||||
|
#define SERIAL_COMMS_H
|
||||||
|
|
||||||
|
typedef void * xComPortHandle;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
serCOM1,
|
||||||
|
serCOM2,
|
||||||
|
serCOM3,
|
||||||
|
serCOM4,
|
||||||
|
serCOM5,
|
||||||
|
serCOM6,
|
||||||
|
serCOM7,
|
||||||
|
serCOM8
|
||||||
|
} eCOMPort;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
serNO_PARITY,
|
||||||
|
serODD_PARITY,
|
||||||
|
serEVEN_PARITY,
|
||||||
|
serMARK_PARITY,
|
||||||
|
serSPACE_PARITY
|
||||||
|
} eParity;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
serSTOP_1,
|
||||||
|
serSTOP_2
|
||||||
|
} eStopBits;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
serBITS_5,
|
||||||
|
serBITS_6,
|
||||||
|
serBITS_7,
|
||||||
|
serBITS_8
|
||||||
|
} eDataBits;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ser50,
|
||||||
|
ser75,
|
||||||
|
ser110,
|
||||||
|
ser134,
|
||||||
|
ser150,
|
||||||
|
ser200,
|
||||||
|
ser300,
|
||||||
|
ser600,
|
||||||
|
ser1200,
|
||||||
|
ser1800,
|
||||||
|
ser2400,
|
||||||
|
ser4800,
|
||||||
|
ser9600,
|
||||||
|
ser19200,
|
||||||
|
ser38400,
|
||||||
|
ser57600,
|
||||||
|
ser115200
|
||||||
|
} eBaud;
|
||||||
|
|
||||||
|
xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength );
|
||||||
|
xComPortHandle xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxBufferLength );
|
||||||
|
void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength );
|
||||||
|
signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime );
|
||||||
|
signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime );
|
||||||
|
portBASE_TYPE xSerialWaitForSemaphore( xComPortHandle xPort );
|
||||||
|
void vSerialClose( xComPortHandle xPort );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
include $(MAKE_INCLUDE_GEN)
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
MODULE_IFLAGS = -I./include
|
||||||
|
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# Object FILE LIST #
|
||||||
|
#*****************************************************************************#
|
||||||
|
OBJS = tasks.o list.o croutine.o queue.o timers.o event_groups.o
|
||||||
|
ifeq ($(CONFIG_RELEASE_BUILD),y)
|
||||||
|
OBJS =
|
||||||
|
else
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# RULES TO GENERATE TARGETS #
|
||||||
|
#*****************************************************************************#
|
||||||
|
|
||||||
|
# Define the Rules to build the core targets
|
||||||
|
#all: CORE_TARGETS COPY_RAM_OBJS
|
||||||
|
all: CORE_TARGETS COPY_RAM_OBJS
|
||||||
|
make -C portable/MemMang all
|
||||||
|
make -C portable/GCC/ARM_CM4F all
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# GENERATE OBJECT FILE
|
||||||
|
#*****************************************************************************#
|
||||||
|
CORE_TARGETS: $(OBJS)
|
||||||
|
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# RULES TO CLEAN TARGETS #
|
||||||
|
#*****************************************************************************#
|
||||||
|
clean:
|
||||||
|
make -C portable/MemMang clean
|
||||||
|
make -C portable/GCC/ARM_CM4F clean
|
||||||
|
$(REMOVE) *.o
|
||||||
|
$(REMOVE) *.i
|
||||||
|
$(REMOVE) *.s
|
||||||
|
$(REMOVE) *.d
|
||||||
|
|
||||||
|
-include $(DEPS)
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
#ifndef FREERTOS_STDINT
|
||||||
|
#define FREERTOS_STDINT
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions
|
||||||
|
* necessary to build the FreeRTOS code. It is provided to allow FreeRTOS to be
|
||||||
|
* built using compilers that do not provide their own stdint.h definition.
|
||||||
|
*
|
||||||
|
* To use this file:
|
||||||
|
*
|
||||||
|
* 1) Copy this file into the directory that contains your FreeRTOSConfig.h
|
||||||
|
* header file, as that directory will already be in the compilers include
|
||||||
|
* path.
|
||||||
|
*
|
||||||
|
* 2) Rename the copied file stdint.h.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef signed char int8_t;
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef short int16_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef long int32_t;
|
||||||
|
typedef unsigned long uint32_t;
|
||||||
|
|
||||||
|
#endif /* FREERTOS_STDINT */
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
include $(MAKE_INCLUDE_GEN)
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
MODULE_IFLAGS =
|
||||||
|
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# Object FILE LIST #
|
||||||
|
#*****************************************************************************#
|
||||||
|
OBJS = port.o
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# RULES TO GENERATE TARGETS #
|
||||||
|
#*****************************************************************************#
|
||||||
|
|
||||||
|
# Define the Rules to build the core targets
|
||||||
|
all: CORE_TARGETS COPY_RAM_OBJS
|
||||||
|
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# GENERATE OBJECT FILE
|
||||||
|
#*****************************************************************************#
|
||||||
|
CORE_TARGETS: $(OBJS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(REMOVE) *.o
|
||||||
|
$(REMOVE) *.i
|
||||||
|
$(REMOVE) *.s
|
||||||
|
$(REMOVE) *.d
|
||||||
|
|
||||||
|
-include $(DEPS)
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,218 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE uint32_t
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
#if( configUSE_16_BIT_TICKS == 1 )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#else
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* MPU specific constants. */
|
||||||
|
#define portUSING_MPU_WRAPPERS 1
|
||||||
|
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||||
|
|
||||||
|
#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL )
|
||||||
|
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||||
|
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||||
|
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||||
|
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||||
|
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||||
|
|
||||||
|
#define portUNPRIVILEGED_FLASH_REGION ( 0UL )
|
||||||
|
#define portPRIVILEGED_FLASH_REGION ( 1UL )
|
||||||
|
#define portPRIVILEGED_RAM_REGION ( 2UL )
|
||||||
|
#define portGENERAL_PERIPHERALS_REGION ( 3UL )
|
||||||
|
#define portSTACK_REGION ( 4UL )
|
||||||
|
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||||
|
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||||
|
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||||
|
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||||
|
|
||||||
|
#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " :::"r0" )
|
||||||
|
|
||||||
|
typedef struct MPU_REGION_REGISTERS
|
||||||
|
{
|
||||||
|
uint32_t ulRegionBaseAddress;
|
||||||
|
uint32_t ulRegionAttribute;
|
||||||
|
} xMPU_REGION_REGISTERS;
|
||||||
|
|
||||||
|
/* Plus 1 to create space for the stack region. */
|
||||||
|
typedef struct MPU_SETTINGS
|
||||||
|
{
|
||||||
|
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
|
||||||
|
} xMPU_SETTINGS;
|
||||||
|
|
||||||
|
/* Architecture specifics. */
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* SVC numbers for various services. */
|
||||||
|
#define portSVC_START_SCHEDULER 0
|
||||||
|
#define portSVC_YIELD 1
|
||||||
|
#define portSVC_RAISE_PRIVILEGE 2
|
||||||
|
|
||||||
|
/* Scheduler utilities. */
|
||||||
|
|
||||||
|
#define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) )
|
||||||
|
#define portYIELD_WITHIN_API() *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET
|
||||||
|
|
||||||
|
#define portNVIC_INT_CTRL ( ( volatile uint32_t *) 0xe000ed04 )
|
||||||
|
#define portNVIC_PENDSVSET 0x10000000
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET
|
||||||
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Critical section management. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set basepri to portMAX_SYSCALL_INTERRUPT_PRIORITY without effecting other
|
||||||
|
* registers. r0 is clobbered.
|
||||||
|
*/
|
||||||
|
#define portSET_INTERRUPT_MASK() \
|
||||||
|
__asm volatile \
|
||||||
|
( \
|
||||||
|
" mov r0, %0 \n" \
|
||||||
|
" msr basepri, r0 \n" \
|
||||||
|
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY):"r0" \
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set basepri back to 0 without effective other registers.
|
||||||
|
* r0 is clobbered. FAQ: Setting BASEPRI to 0 is not a bug. Please see
|
||||||
|
* http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing.
|
||||||
|
*/
|
||||||
|
#define portCLEAR_INTERRUPT_MASK() \
|
||||||
|
__asm volatile \
|
||||||
|
( \
|
||||||
|
" mov r0, #0 \n" \
|
||||||
|
" msr basepri, r0 \n" \
|
||||||
|
:::"r0" \
|
||||||
|
)
|
||||||
|
|
||||||
|
/* FAQ: Setting BASEPRI to 0 is not a bug. Please see
|
||||||
|
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;portSET_INTERRUPT_MASK()
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK();(void)x
|
||||||
|
|
||||||
|
|
||||||
|
extern void vPortEnterCritical( void );
|
||||||
|
extern void vPortExitCritical( void );
|
||||||
|
|
||||||
|
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()
|
||||||
|
#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK()
|
||||||
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||||
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
|
||||||
|
#define portNOP()
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
include $(MAKE_INCLUDE_GEN)
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
MODULE_IFLAGS =
|
||||||
|
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# Object FILE LIST #
|
||||||
|
#*****************************************************************************#
|
||||||
|
OBJS = port.o
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# RULES TO GENERATE TARGETS #
|
||||||
|
#*****************************************************************************#
|
||||||
|
|
||||||
|
# Define the Rules to build the core targets
|
||||||
|
all: CORE_TARGETS COPY_RAM_OBJS
|
||||||
|
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# GENERATE OBJECT FILE
|
||||||
|
#*****************************************************************************#
|
||||||
|
CORE_TARGETS: $(OBJS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(REMOVE) *.o
|
||||||
|
$(REMOVE) *.i
|
||||||
|
$(REMOVE) *.s
|
||||||
|
$(REMOVE) *.d
|
||||||
|
|
||||||
|
-include $(DEPS)
|
||||||
|
|
@ -0,0 +1,784 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Implementation of functions defined in portable.h for the ARM CM4F port.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#ifndef __VFP_FP__
|
||||||
|
#error This port can only be used when the project options are configured to enable hardware floating point support.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||||
|
as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Constants required to manipulate the core. Registers first... */
|
||||||
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
|
/* ...then bits in the registers. */
|
||||||
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
|
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||||
|
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||||
|
|
||||||
|
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
|
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt priority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||||
|
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||||
|
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||||
|
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
#define portPRIGROUP_SHIFT ( 8UL )
|
||||||
|
|
||||||
|
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||||
|
#define portVECTACTIVE_MASK ( 0x1FUL )
|
||||||
|
|
||||||
|
/* Constants required to manipulate the VFP. */
|
||||||
|
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
|
||||||
|
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
||||||
|
|
||||||
|
/* Constants required to set up the initial stack. */
|
||||||
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
|
#define portINITIAL_EXEC_RETURN ( 0xfffffffd )
|
||||||
|
|
||||||
|
/* The systick is a 24-bit counter. */
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||||
|
occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
calculations. */
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
|
||||||
|
/* Let the user override the pre-loading of the initial LR with the address of
|
||||||
|
prvTaskExitError() in case is messes up unwinding of the stack in the
|
||||||
|
debugger. */
|
||||||
|
#ifdef configTASK_RETURN_ADDRESS
|
||||||
|
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||||
|
#else
|
||||||
|
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Each task maintains its own interrupt status in the critical nesting
|
||||||
|
variable. */
|
||||||
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||||
|
* file is weak to allow application writers to change the timer used to
|
||||||
|
* generate the tick interrupt.
|
||||||
|
*/
|
||||||
|
void vPortSetupTimerInterrupt( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exception handlers.
|
||||||
|
*/
|
||||||
|
void xPortPendSVHandler( void ) __attribute__ (( naked ));
|
||||||
|
void xPortSysTickHandler( void );
|
||||||
|
void vPortSVCHandler( void ) __attribute__ (( naked ));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start first task is a separate function so it can be tested in isolation.
|
||||||
|
*/
|
||||||
|
static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to enable the VFP.
|
||||||
|
*/
|
||||||
|
static void vPortEnableVFP( void ) __attribute__ (( naked ));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to catch tasks that attempt to return from their implementing function.
|
||||||
|
*/
|
||||||
|
static void prvTaskExitError( void );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The maximum number of tick periods that can be suppressed is limited by the
|
||||||
|
* 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||||
|
* power functionality only.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||||
|
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||||
|
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*/
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
static uint8_t ucMaxSysCallPriority = 0;
|
||||||
|
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||||
|
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||||
|
{
|
||||||
|
/* Simulate the stack frame as it would be created by a context switch
|
||||||
|
interrupt. */
|
||||||
|
|
||||||
|
/* Offset added to account for the way the MCU uses the stack on entry/exit
|
||||||
|
of interrupts, and to ensure alignment. */
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||||
|
|
||||||
|
/* Save code space by skipping register initialisation. */
|
||||||
|
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||||
|
|
||||||
|
/* A save method is being used that requires each task to maintain its
|
||||||
|
own exec return value. */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = portINITIAL_EXEC_RETURN;
|
||||||
|
|
||||||
|
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||||
|
|
||||||
|
return pxTopOfStack;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTaskExitError( void )
|
||||||
|
{
|
||||||
|
/* A function that implements a task must not exit or attempt to return to
|
||||||
|
its caller as there is nothing to return to. If a task wants to exit it
|
||||||
|
should instead call vTaskDelete( NULL ).
|
||||||
|
|
||||||
|
Artificially force an assert() to be triggered if configASSERT() is
|
||||||
|
defined, then stop here so application writers can catch the error. */
|
||||||
|
configASSERT( uxCriticalNesting == ~0UL );
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
for( ;; );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortSVCHandler( void )
|
||||||
|
{
|
||||||
|
__asm volatile (
|
||||||
|
" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
|
||||||
|
" ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
|
||||||
|
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
" ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
|
||||||
|
" msr psp, r0 \n" /* Restore the task stack pointer. */
|
||||||
|
" isb \n"
|
||||||
|
" mov r0, #0 \n"
|
||||||
|
" msr basepri, r0 \n"
|
||||||
|
" bx r14 \n"
|
||||||
|
" \n"
|
||||||
|
" .align 2 \n"
|
||||||
|
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvPortStartFirstTask( void )
|
||||||
|
{
|
||||||
|
__asm volatile(
|
||||||
|
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||||
|
" ldr r0, [r0] \n"
|
||||||
|
" ldr r0, [r0] \n"
|
||||||
|
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
|
||||||
|
" cpsie i \n" /* Globally enable interrupts. */
|
||||||
|
" cpsie f \n"
|
||||||
|
" dsb \n"
|
||||||
|
" isb \n"
|
||||||
|
" svc 0 \n" /* System call to start first task. */
|
||||||
|
" nop \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
|
||||||
|
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||||
|
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile uint32_t ulOriginalPriority;
|
||||||
|
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
volatile uint8_t ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
functions can be called. ISR safe functions are those that end in
|
||||||
|
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Determine the number of priority bits available. First write to all
|
||||||
|
possible bits. */
|
||||||
|
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||||
|
|
||||||
|
/* Read the value back to see how many bits stuck. */
|
||||||
|
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Use the same mask on the maximum system call priority. */
|
||||||
|
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Calculate the maximum acceptable priority group value for the number
|
||||||
|
of bits read back. */
|
||||||
|
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||||
|
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||||
|
{
|
||||||
|
ulMaxPRIGROUPValue--;
|
||||||
|
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift the priority group value back to its position within the AIRCR
|
||||||
|
register. */
|
||||||
|
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||||
|
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
value. */
|
||||||
|
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
|
here already. */
|
||||||
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
|
uxCriticalNesting = 0;
|
||||||
|
|
||||||
|
/* Ensure the VFP is enabled - it should be anyway. */
|
||||||
|
vPortEnableVFP();
|
||||||
|
|
||||||
|
/* Lazy save always. */
|
||||||
|
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
|
||||||
|
|
||||||
|
/* Start the first task. */
|
||||||
|
prvPortStartFirstTask();
|
||||||
|
|
||||||
|
/* Should never get here as the tasks will now be executing! Call the task
|
||||||
|
exit error function to prevent compiler warnings about a static function
|
||||||
|
not being called in the case that the application writer overrides this
|
||||||
|
functionality by defining configTASK_RETURN_ADDRESS. */
|
||||||
|
prvTaskExitError();
|
||||||
|
|
||||||
|
/* Should not get here! */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEndScheduler( void )
|
||||||
|
{
|
||||||
|
/* Not implemented in ports where there is nothing to return to.
|
||||||
|
Artificially force an assert. */
|
||||||
|
configASSERT( uxCriticalNesting == 1000UL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortYield( void )
|
||||||
|
{
|
||||||
|
/* Set a PendSV to request a context switch. */
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
|
/* Barriers are normally not required but do ensure the code is completely
|
||||||
|
within the specified behaviour for the architecture. */
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEnterCritical( void )
|
||||||
|
{
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
uxCriticalNesting++;
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* This is not the interrupt safe version of the enter critical function so
|
||||||
|
assert() if it is being called from an interrupt context. Only API
|
||||||
|
functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||||
|
the critical nesting count is 1 to protect against recursive calls if the
|
||||||
|
assert function also uses a critical section. */
|
||||||
|
if( uxCriticalNesting == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortExitCritical( void )
|
||||||
|
{
|
||||||
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__attribute__(( naked )) uint32_t ulPortSetInterruptMask( void )
|
||||||
|
{
|
||||||
|
__asm volatile \
|
||||||
|
( \
|
||||||
|
" mrs r0, basepri \n" \
|
||||||
|
" mov r1, %0 \n" \
|
||||||
|
" msr basepri, r1 \n" \
|
||||||
|
" bx lr \n" \
|
||||||
|
:: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "r0", "r1" \
|
||||||
|
);
|
||||||
|
|
||||||
|
/* This return will not be reached but is necessary to prevent compiler
|
||||||
|
warnings. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__attribute__(( naked )) void vPortClearInterruptMask( uint32_t ulNewMaskValue )
|
||||||
|
{
|
||||||
|
__asm volatile \
|
||||||
|
( \
|
||||||
|
" msr basepri, r0 \n" \
|
||||||
|
" bx lr \n" \
|
||||||
|
:::"r0" \
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Just to avoid compiler warnings. */
|
||||||
|
( void ) ulNewMaskValue;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void xPortPendSVHandler( void )
|
||||||
|
{
|
||||||
|
/* This is a naked function. */
|
||||||
|
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" mrs r0, psp \n"
|
||||||
|
" isb \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
|
||||||
|
" ldr r2, [r3] \n"
|
||||||
|
" \n"
|
||||||
|
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */
|
||||||
|
" it eq \n"
|
||||||
|
" vstmdbeq r0!, {s16-s31} \n"
|
||||||
|
" \n"
|
||||||
|
" stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */
|
||||||
|
" \n"
|
||||||
|
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
|
||||||
|
" \n"
|
||||||
|
" stmdb sp!, {r3} \n"
|
||||||
|
" mov r0, %0 \n"
|
||||||
|
" msr basepri, r0 \n"
|
||||||
|
" bl vTaskSwitchContext \n"
|
||||||
|
" mov r0, #0 \n"
|
||||||
|
" msr basepri, r0 \n"
|
||||||
|
" ldmia sp!, {r3} \n"
|
||||||
|
" \n"
|
||||||
|
" ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
" ldr r0, [r1] \n"
|
||||||
|
" \n"
|
||||||
|
" ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */
|
||||||
|
" \n"
|
||||||
|
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */
|
||||||
|
" it eq \n"
|
||||||
|
" vldmiaeq r0!, {s16-s31} \n"
|
||||||
|
" \n"
|
||||||
|
" msr psp, r0 \n"
|
||||||
|
" isb \n"
|
||||||
|
" \n"
|
||||||
|
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */
|
||||||
|
#if WORKAROUND_PMU_CM001 == 1
|
||||||
|
" push { r14 } \n"
|
||||||
|
" pop { pc } \n"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
" \n"
|
||||||
|
" bx r14 \n"
|
||||||
|
" \n"
|
||||||
|
" .align 2 \n"
|
||||||
|
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||||
|
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void xPortSysTickHandler( void )
|
||||||
|
{
|
||||||
|
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
||||||
|
executes all interrupts must be unmasked. There is therefore no need to
|
||||||
|
save and then restore the interrupt mask value as its value is already
|
||||||
|
known. */
|
||||||
|
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
{
|
||||||
|
/* Increment the RTOS tick. */
|
||||||
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
|
{
|
||||||
|
/* A context switch is required. Context switching is performed in
|
||||||
|
the PendSV interrupt. Pend the PendSV interrupt. */
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
|
||||||
|
__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for
|
||||||
|
is accounted for as best it can be, but using the tickless mode will
|
||||||
|
inevitably result in some tiny drift of the time maintained by the
|
||||||
|
kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
tick periods. -1 is used because this code will execute part way
|
||||||
|
through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm volatile( "cpsid i" );
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
to be unsuspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||||
|
above. */
|
||||||
|
__asm volatile( "cpsie i" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
set its parameter to 0 to indicate that its implementation contains
|
||||||
|
its own wait for interrupt or wait for event instruction, and so wfi
|
||||||
|
should not be executed again. However, the original expected idle
|
||||||
|
time variable must remain unmodified, so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "wfi" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Stop SysTick. Again, the time the SysTick is stopped for is
|
||||||
|
accounted for as best it can be, but using the tickless mode will
|
||||||
|
inevitably result in some tiny drift of the time maintained by the
|
||||||
|
kernel with respect to calendar time. */
|
||||||
|
ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||||
|
above. */
|
||||||
|
__asm volatile( "cpsie i" );
|
||||||
|
|
||||||
|
if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt has already executed, and the SysTick
|
||||||
|
count reloaded with ulReloadValue. Reset the
|
||||||
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt handler will already have pended the tick
|
||||||
|
processing in the kernel. As the pending tick will be
|
||||||
|
processed as soon as this function exits, the tick value
|
||||||
|
maintained by the tick is stepped forward by one less than the
|
||||||
|
time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
Work out how long the sleep lasted rounded to complete tick
|
||||||
|
periods (not the ulReload value which accounted for part
|
||||||
|
ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
value. The critical section is used to ensure the tick interrupt
|
||||||
|
can only execute once in the case that the reload register is near
|
||||||
|
zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the systick timer to generate the tick interrupts at the required
|
||||||
|
* frequency.
|
||||||
|
*/
|
||||||
|
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
|
||||||
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* This is a naked function. */
|
||||||
|
static void vPortEnableVFP( void )
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" ldr.w r0, =0xE000ED88 \n" /* The FPU enable bits are in the CPACR. */
|
||||||
|
" ldr r1, [r0] \n"
|
||||||
|
" \n"
|
||||||
|
" orr r1, r1, #( 0xf << 20 ) \n" /* Enable CP10 and CP11 coprocessors, then save back. */
|
||||||
|
" str r1, [r0] \n"
|
||||||
|
" bx r14 "
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrentInterrupt;
|
||||||
|
uint8_t ucCurrentPriority;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
an interrupt that has been assigned a priority above
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
|
function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
|
from interrupts that have been assigned a priority at or below
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Numerically low interrupt priority numbers represent logically high
|
||||||
|
interrupt priorities, therefore the priority of the interrupt must
|
||||||
|
be set to a value equal to or numerically *higher* than
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Interrupts that use the FreeRTOS API must not be left at their
|
||||||
|
default priority of zero as that is the highest possible priority,
|
||||||
|
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||||
|
and therefore also guaranteed to be invalid.
|
||||||
|
|
||||||
|
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||||
|
interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
The following links provide detailed information:
|
||||||
|
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||||
|
http://www.freertos.org/FAQHelp.html */
|
||||||
|
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||||
|
that define each interrupt's priority to be split between bits that
|
||||||
|
define the interrupt's pre-emption priority bits and bits that define
|
||||||
|
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||||
|
to be pre-emption priority bits. The following assertion will fail if
|
||||||
|
this is not the case (if some bits represent a sub-priority).
|
||||||
|
|
||||||
|
If the application only uses CMSIS libraries for interrupt
|
||||||
|
configuration then the correct setting can be achieved on all Cortex-M
|
||||||
|
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
scheduler. Note however that some vendor specific peripheral libraries
|
||||||
|
assume a non-zero priority group setting, in which cases using a value
|
||||||
|
of zero will result in unpredicable behaviour. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE uint32_t
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
#if( configUSE_16_BIT_TICKS == 1 )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#else
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specifics. */
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Scheduler utilities. */
|
||||||
|
extern void vPortYield( void );
|
||||||
|
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||||
|
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||||
|
#define portYIELD() vPortYield()
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||||
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Critical section management. */
|
||||||
|
extern void vPortEnterCritical( void );
|
||||||
|
extern void vPortExitCritical( void );
|
||||||
|
extern uint32_t ulPortSetInterruptMask( void );
|
||||||
|
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||||
|
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0)
|
||||||
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||||
|
not necessary for to use this port. They are defined so the common demo files
|
||||||
|
(which build with all the ports) will build. */
|
||||||
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Tickless idle/low power functionality. */
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specific optimisations. */
|
||||||
|
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||||
|
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||||
|
|
||||||
|
/* Generic helper function. */
|
||||||
|
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||||
|
{
|
||||||
|
uint8_t ucReturn;
|
||||||
|
|
||||||
|
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
|
||||||
|
return ucReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the configuration. */
|
||||||
|
#if( configMAX_PRIORITIES > 32 )
|
||||||
|
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Store/clear the ready priorities in a bit map. */
|
||||||
|
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||||
|
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||||
|
|
||||||
|
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef configASSERT
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* portNOP() is not required by this port. */
|
||||||
|
#define portNOP()
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,655 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Implementation of functions defined in portable.h for the ARM CM3 port.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* IAR includes. */
|
||||||
|
#include <intrinsics.h>
|
||||||
|
|
||||||
|
/* Scheduler includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Platform includes */
|
||||||
|
#include "platform_autoconf.h"
|
||||||
|
|
||||||
|
#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
|
||||||
|
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||||
|
as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Constants required to manipulate the core. Registers first... */
|
||||||
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
|
/* ...then bits in the registers. */
|
||||||
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
|
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||||
|
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||||
|
|
||||||
|
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
|
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt priority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||||
|
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||||
|
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||||
|
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
#define portPRIGROUP_SHIFT ( 8UL )
|
||||||
|
|
||||||
|
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||||
|
#define portVECTACTIVE_MASK ( 0x1FUL )
|
||||||
|
|
||||||
|
/* Constants required to set up the initial stack. */
|
||||||
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
|
|
||||||
|
/* The systick is a 24-bit counter. */
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||||
|
occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
calculations. */
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
|
||||||
|
/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is
|
||||||
|
defined. The value 255 should also ensure backward compatibility.
|
||||||
|
FreeRTOS.org versions prior to V4.3.0 did not include this definition. */
|
||||||
|
#ifndef configKERNEL_INTERRUPT_PRIORITY
|
||||||
|
#define configKERNEL_INTERRUPT_PRIORITY 255
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Each task maintains its own interrupt status in the critical nesting
|
||||||
|
variable. */
|
||||||
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||||
|
* file is weak to allow application writers to change the timer used to
|
||||||
|
* generate the tick interrupt.
|
||||||
|
*/
|
||||||
|
void vPortSetupTimerInterrupt( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exception handlers.
|
||||||
|
*/
|
||||||
|
void xPortSysTickHandler( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start first task is a separate function so it can be tested in isolation.
|
||||||
|
*/
|
||||||
|
extern void vPortStartFirstTask( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to catch tasks that attempt to return from their implementing function.
|
||||||
|
*/
|
||||||
|
static void prvTaskExitError( void );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The maximum number of tick periods that can be suppressed is limited by the
|
||||||
|
* 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||||
|
* power functionality only.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||||
|
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||||
|
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*/
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
static uint8_t ucMaxSysCallPriority = 0;
|
||||||
|
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||||
|
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||||
|
{
|
||||||
|
/* Simulate the stack frame as it would be created by a context switch
|
||||||
|
interrupt. */
|
||||||
|
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||||
|
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
|
||||||
|
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||||
|
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||||
|
|
||||||
|
return pxTopOfStack;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTaskExitError( void )
|
||||||
|
{
|
||||||
|
/* A function that implements a task must not exit or attempt to return to
|
||||||
|
its caller as there is nothing to return to. If a task wants to exit it
|
||||||
|
should instead call vTaskDelete( NULL ).
|
||||||
|
|
||||||
|
Artificially force an assert() to be triggered if configASSERT() is
|
||||||
|
defined, then stop here so application writers can catch the error. */
|
||||||
|
configASSERT( uxCriticalNesting == ~0UL );
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
for( ;; );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile uint32_t ulOriginalPriority;
|
||||||
|
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
volatile uint8_t ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
functions can be called. ISR safe functions are those that end in
|
||||||
|
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Determine the number of priority bits available. First write to all
|
||||||
|
possible bits. */
|
||||||
|
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||||
|
|
||||||
|
/* Read the value back to see how many bits stuck. */
|
||||||
|
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Use the same mask on the maximum system call priority. */
|
||||||
|
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Calculate the maximum acceptable priority group value for the number
|
||||||
|
of bits read back. */
|
||||||
|
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||||
|
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||||
|
{
|
||||||
|
ulMaxPRIGROUPValue--;
|
||||||
|
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift the priority group value back to its position within the AIRCR
|
||||||
|
register. */
|
||||||
|
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||||
|
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
value. */
|
||||||
|
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
|
here already. */
|
||||||
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
|
uxCriticalNesting = 0;
|
||||||
|
|
||||||
|
/* Start the first task. */
|
||||||
|
vPortStartFirstTask();
|
||||||
|
|
||||||
|
/* Should not get here! */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEndScheduler( void )
|
||||||
|
{
|
||||||
|
/* Not implemented in ports where there is nothing to return to.
|
||||||
|
Artificially force an assert. */
|
||||||
|
configASSERT( uxCriticalNesting == 1000UL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortYield( void )
|
||||||
|
{
|
||||||
|
/* Set a PendSV to request a context switch. */
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
|
/* Barriers are normally not required but do ensure the code is completely
|
||||||
|
within the specified behaviour for the architecture. */
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEnterCritical( void )
|
||||||
|
{
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
uxCriticalNesting++;
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
|
||||||
|
/* This is not the interrupt safe version of the enter critical function so
|
||||||
|
assert() if it is being called from an interrupt context. Only API
|
||||||
|
functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||||
|
the critical nesting count is 1 to protect against recursive calls if the
|
||||||
|
assert function also uses a critical section. */
|
||||||
|
if( uxCriticalNesting == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortExitCritical( void )
|
||||||
|
{
|
||||||
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void xPortSysTickHandler( void )
|
||||||
|
{
|
||||||
|
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
||||||
|
executes all interrupts must be unmasked. There is therefore no need to
|
||||||
|
save and then restore the interrupt mask value as its value is already
|
||||||
|
known. */
|
||||||
|
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
{
|
||||||
|
/* Increment the RTOS tick. */
|
||||||
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
|
{
|
||||||
|
/* A context switch is required. Context switching is performed in
|
||||||
|
the PendSV interrupt. Pend the PendSV interrupt. */
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
|
||||||
|
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for
|
||||||
|
is accounted for as best it can be, but using the tickless mode will
|
||||||
|
inevitably result in some tiny drift of the time maintained by the
|
||||||
|
kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
tick periods. -1 is used because this code will execute part way
|
||||||
|
through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__disable_interrupt();
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
to be unsuspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above __disable_interrupt()
|
||||||
|
call above. */
|
||||||
|
__enable_interrupt();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
set its parameter to 0 to indicate that its implementation contains
|
||||||
|
its own wait for interrupt or wait for event instruction, and so wfi
|
||||||
|
should not be executed again. However, the original expected idle
|
||||||
|
time variable must remain unmodified, so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__DSB();
|
||||||
|
__WFI();
|
||||||
|
__ISB();
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Stop SysTick. Again, the time the SysTick is stopped for is
|
||||||
|
accounted for as best it can be, but using the tickless mode will
|
||||||
|
inevitably result in some tiny drift of the time maintained by the
|
||||||
|
kernel with respect to calendar time. */
|
||||||
|
ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above __disable_interrupt()
|
||||||
|
call above. */
|
||||||
|
__enable_interrupt();
|
||||||
|
|
||||||
|
if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt has already executed, and the SysTick
|
||||||
|
count reloaded with ulReloadValue. Reset the
|
||||||
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt handler will already have pended the tick
|
||||||
|
processing in the kernel. As the pending tick will be
|
||||||
|
processed as soon as this function exits, the tick value
|
||||||
|
maintained by the tick is stepped forward by one less than the
|
||||||
|
time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
Work out how long the sleep lasted rounded to complete tick
|
||||||
|
periods (not the ulReload value which accounted for part
|
||||||
|
ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
value. The critical section is used to ensure the tick interrupt
|
||||||
|
can only execute once in the case that the reload register is near
|
||||||
|
zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the systick timer to generate the tick interrupts at the required
|
||||||
|
* frequency.
|
||||||
|
*/
|
||||||
|
__weak void vPortSetupTimerInterrupt( void )
|
||||||
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
#ifdef CONFIG_SOC_PS_MODULE
|
||||||
|
// RTK modified: max system timer can sleep up to 8355ms, set it to 8000
|
||||||
|
xMaximumPossibleSuppressedTicks = 8000;
|
||||||
|
#else // Below is original code. It can only sleep 100ms in 166MHz
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
#endif
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrentInterrupt;
|
||||||
|
uint8_t ucCurrentPriority;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
an interrupt that has been assigned a priority above
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
|
function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
|
from interrupts that have been assigned a priority at or below
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Numerically low interrupt priority numbers represent logically high
|
||||||
|
interrupt priorities, therefore the priority of the interrupt must
|
||||||
|
be set to a value equal to or numerically *higher* than
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Interrupts that use the FreeRTOS API must not be left at their
|
||||||
|
default priority of zero as that is the highest possible priority,
|
||||||
|
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||||
|
and therefore also guaranteed to be invalid.
|
||||||
|
|
||||||
|
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||||
|
interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
The following links provide detailed information:
|
||||||
|
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||||
|
http://www.freertos.org/FAQHelp.html */
|
||||||
|
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||||
|
that define each interrupt's priority to be split between bits that
|
||||||
|
define the interrupt's pre-emption priority bits and bits that define
|
||||||
|
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||||
|
to be pre-emption priority bits. The following assertion will fail if
|
||||||
|
this is not the case (if some bits represent a sub-priority).
|
||||||
|
|
||||||
|
If the application only uses CMSIS libraries for interrupt
|
||||||
|
configuration then the correct setting can be achieved on all Cortex-M
|
||||||
|
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
scheduler. Note however that some vendor specific peripheral libraries
|
||||||
|
assume a non-zero priority group setting, in which cases using a value
|
||||||
|
of zero will result in unpredicable behaviour. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
void vApplicationIdleHook( void )
|
||||||
|
{
|
||||||
|
/* Use the idle task to place the CPU into a low power mode. Greater power
|
||||||
|
saving could be achieved by not including any demo tasks that never block. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName )
|
||||||
|
{
|
||||||
|
/* This function will be called if a task overflows its stack, if
|
||||||
|
configCHECK_FOR_STACK_OVERFLOW != 0. It might be that the function
|
||||||
|
parameters have been corrupted, depending on the severity of the stack
|
||||||
|
overflow. When this is the case pxCurrentTCB can be inspected in the
|
||||||
|
debugger to find the offending task. */
|
||||||
|
// DiagPrintf("\n\r[%s] STACK OVERFLOW - TaskName(%s)\n\r", __FUNCTION__, pcTaskName);
|
||||||
|
for( ;; );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <FreeRTOSConfig.h>
|
||||||
|
|
||||||
|
RSEG CODE:CODE(2)
|
||||||
|
thumb
|
||||||
|
|
||||||
|
EXTERN pxCurrentTCB
|
||||||
|
EXTERN vTaskSwitchContext
|
||||||
|
|
||||||
|
PUBLIC xPortPendSVHandler
|
||||||
|
PUBLIC ulPortSetInterruptMask
|
||||||
|
PUBLIC vPortClearInterruptMask
|
||||||
|
PUBLIC vPortSVCHandler
|
||||||
|
PUBLIC vPortStartFirstTask
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
xPortPendSVHandler:
|
||||||
|
mrs r0, psp
|
||||||
|
isb
|
||||||
|
ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
|
||||||
|
ldr r2, [r3]
|
||||||
|
|
||||||
|
stmdb r0!, {r4-r11} /* Save the remaining registers. */
|
||||||
|
str r0, [r2] /* Save the new top of stack into the first member of the TCB. */
|
||||||
|
|
||||||
|
stmdb sp!, {r3, r14}
|
||||||
|
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r0
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
ldmia sp!, {r3, r14}
|
||||||
|
|
||||||
|
ldr r1, [r3]
|
||||||
|
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
ldmia r0!, {r4-r11} /* Pop the registers. */
|
||||||
|
msr psp, r0
|
||||||
|
isb
|
||||||
|
bx r14
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
ulPortSetInterruptMask:
|
||||||
|
mrs r0, basepri
|
||||||
|
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r1
|
||||||
|
bx r14
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vPortClearInterruptMask:
|
||||||
|
msr basepri, r0
|
||||||
|
bx r14
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vPortSVCHandler:
|
||||||
|
/* Get the location of the current TCB. */
|
||||||
|
ldr r3, =pxCurrentTCB
|
||||||
|
ldr r1, [r3]
|
||||||
|
ldr r0, [r1]
|
||||||
|
/* Pop the core registers. */
|
||||||
|
ldmia r0!, {r4-r11}
|
||||||
|
msr psp, r0
|
||||||
|
isb
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
orr r14, r14, #13
|
||||||
|
bx r14
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vPortStartFirstTask
|
||||||
|
/* Use the NVIC offset register to locate the stack. */
|
||||||
|
ldr r0, =0xE000ED08
|
||||||
|
ldr r0, [r0]
|
||||||
|
ldr r0, [r0]
|
||||||
|
/* Set the msp back to the start of the stack. */
|
||||||
|
msr msp, r0
|
||||||
|
/* Call SVC to start the first task, ensuring interrupts are enabled. */
|
||||||
|
cpsie i
|
||||||
|
cpsie f
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
svc 0
|
||||||
|
|
||||||
|
END
|
||||||
|
|
@ -0,0 +1,210 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PLATFORM_8195A
|
||||||
|
// to prevent marco define use in standard header file
|
||||||
|
#define _NO_DEFINITIONS_IN_HEADER_FILES
|
||||||
|
#include <string.h>
|
||||||
|
//#include "basic_types.h"
|
||||||
|
#include "hal_misc.h"
|
||||||
|
#if !defined(__IARSTDLIB__)
|
||||||
|
#ifndef memcmp
|
||||||
|
#define memcmp(dst, src, sz) _memcmp(dst, src, sz)
|
||||||
|
#endif
|
||||||
|
#ifndef memset
|
||||||
|
#define memset(dst, val, sz) _memset(dst, val, sz)
|
||||||
|
#endif
|
||||||
|
#ifndef memcpy
|
||||||
|
#define memcpy(dst, src, sz) _memcpy(dst, src, sz)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE uint32_t
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
#if( configUSE_16_BIT_TICKS == 1 )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY 0xffff
|
||||||
|
#else
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY 0xffffffffUL
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specifics. */
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler utilities. */
|
||||||
|
extern void vPortYield( void );
|
||||||
|
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04UL ) )
|
||||||
|
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||||
|
#define portYIELD() vPortYield()
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||||
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specific optimisations. */
|
||||||
|
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||||
|
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||||
|
|
||||||
|
/* Check the configuration. */
|
||||||
|
#if( configMAX_PRIORITIES > 32 )
|
||||||
|
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Store/clear the ready priorities in a bit map. */
|
||||||
|
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) )
|
||||||
|
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <intrinsics.h>
|
||||||
|
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) )
|
||||||
|
|
||||||
|
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Critical section management. */
|
||||||
|
extern void vPortEnterCritical( void );
|
||||||
|
extern void vPortExitCritical( void );
|
||||||
|
extern uint32_t ulPortSetInterruptMask( void );
|
||||||
|
extern void vPortClearInterruptMask( uint32_t ulNewMask );
|
||||||
|
|
||||||
|
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
|
||||||
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Tickless idle/low power functionality. */
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||||
|
not necessary for to use this port. They are defined so the common demo files
|
||||||
|
(which build with all the ports) will build. */
|
||||||
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef configASSERT
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* portNOP() is not required by this port. */
|
||||||
|
#define portNOP()
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
the source code because to do so would cause other compilers to generate
|
||||||
|
warnings. */
|
||||||
|
#pragma diag_suppress=Pe191
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,659 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Implementation of functions defined in portable.h for the ARM CM4F port.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Compiler includes. */
|
||||||
|
#include <intrinsics.h>
|
||||||
|
|
||||||
|
/* Scheduler includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#ifndef __ARMVFP__
|
||||||
|
#error This port can only be used when the project options are configured to enable hardware floating point support.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
|
||||||
|
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||||
|
as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Constants required to manipulate the core. Registers first... */
|
||||||
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
|
/* ...then bits in the registers. */
|
||||||
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
|
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||||
|
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||||
|
|
||||||
|
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
|
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt priority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||||
|
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||||
|
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||||
|
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
#define portPRIGROUP_SHIFT ( 8UL )
|
||||||
|
|
||||||
|
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||||
|
#define portVECTACTIVE_MASK ( 0x1FUL )
|
||||||
|
|
||||||
|
/* Constants required to manipulate the VFP. */
|
||||||
|
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
|
||||||
|
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
||||||
|
|
||||||
|
/* Constants required to set up the initial stack. */
|
||||||
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
|
#define portINITIAL_EXEC_RETURN ( 0xfffffffd )
|
||||||
|
|
||||||
|
/* The systick is a 24-bit counter. */
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||||
|
occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
calculations. */
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
|
||||||
|
|
||||||
|
/* Each task maintains its own interrupt status in the critical nesting
|
||||||
|
variable. */
|
||||||
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||||
|
* file is weak to allow application writers to change the timer used to
|
||||||
|
* generate the tick interrupt.
|
||||||
|
*/
|
||||||
|
void vPortSetupTimerInterrupt( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exception handlers.
|
||||||
|
*/
|
||||||
|
void xPortSysTickHandler( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start first task is a separate function so it can be tested in isolation.
|
||||||
|
*/
|
||||||
|
extern void vPortStartFirstTask( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turn the VFP on.
|
||||||
|
*/
|
||||||
|
extern void vPortEnableVFP( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to catch tasks that attempt to return from their implementing function.
|
||||||
|
*/
|
||||||
|
static void prvTaskExitError( void );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The maximum number of tick periods that can be suppressed is limited by the
|
||||||
|
* 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||||
|
* power functionality only.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||||
|
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||||
|
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*/
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
static uint8_t ucMaxSysCallPriority = 0;
|
||||||
|
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||||
|
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||||
|
{
|
||||||
|
/* Simulate the stack frame as it would be created by a context switch
|
||||||
|
interrupt. */
|
||||||
|
|
||||||
|
/* Offset added to account for the way the MCU uses the stack on entry/exit
|
||||||
|
of interrupts, and to ensure alignment. */
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
|
||||||
|
|
||||||
|
/* Save code space by skipping register initialisation. */
|
||||||
|
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||||
|
|
||||||
|
/* A save method is being used that requires each task to maintain its
|
||||||
|
own exec return value. */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = portINITIAL_EXEC_RETURN;
|
||||||
|
|
||||||
|
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||||
|
|
||||||
|
return pxTopOfStack;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTaskExitError( void )
|
||||||
|
{
|
||||||
|
/* A function that implements a task must not exit or attempt to return to
|
||||||
|
its caller as there is nothing to return to. If a task wants to exit it
|
||||||
|
should instead call vTaskDelete( NULL ).
|
||||||
|
|
||||||
|
Artificially force an assert() to be triggered if configASSERT() is
|
||||||
|
defined, then stop here so application writers can catch the error. */
|
||||||
|
configASSERT( uxCriticalNesting == ~0UL );
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
for( ;; );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile uint32_t ulOriginalPriority;
|
||||||
|
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
volatile uint8_t ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
functions can be called. ISR safe functions are those that end in
|
||||||
|
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Determine the number of priority bits available. First write to all
|
||||||
|
possible bits. */
|
||||||
|
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||||
|
|
||||||
|
/* Read the value back to see how many bits stuck. */
|
||||||
|
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Use the same mask on the maximum system call priority. */
|
||||||
|
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Calculate the maximum acceptable priority group value for the number
|
||||||
|
of bits read back. */
|
||||||
|
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||||
|
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||||
|
{
|
||||||
|
ulMaxPRIGROUPValue--;
|
||||||
|
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift the priority group value back to its position within the AIRCR
|
||||||
|
register. */
|
||||||
|
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||||
|
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
value. */
|
||||||
|
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
|
here already. */
|
||||||
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
|
uxCriticalNesting = 0;
|
||||||
|
|
||||||
|
/* Ensure the VFP is enabled - it should be anyway. */
|
||||||
|
vPortEnableVFP();
|
||||||
|
|
||||||
|
/* Lazy save always. */
|
||||||
|
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
|
||||||
|
|
||||||
|
/* Start the first task. */
|
||||||
|
vPortStartFirstTask();
|
||||||
|
|
||||||
|
/* Should not get here! */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEndScheduler( void )
|
||||||
|
{
|
||||||
|
/* Not implemented in ports where there is nothing to return to.
|
||||||
|
Artificially force an assert. */
|
||||||
|
configASSERT( uxCriticalNesting == 1000UL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortYield( void )
|
||||||
|
{
|
||||||
|
/* Set a PendSV to request a context switch. */
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
|
/* Barriers are normally not required but do ensure the code is completely
|
||||||
|
within the specified behaviour for the architecture. */
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEnterCritical( void )
|
||||||
|
{
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
uxCriticalNesting++;
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
|
||||||
|
/* This is not the interrupt safe version of the enter critical function so
|
||||||
|
assert() if it is being called from an interrupt context. Only API
|
||||||
|
functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||||
|
the critical nesting count is 1 to protect against recursive calls if the
|
||||||
|
assert function also uses a critical section. */
|
||||||
|
if( uxCriticalNesting == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortExitCritical( void )
|
||||||
|
{
|
||||||
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void xPortSysTickHandler( void )
|
||||||
|
{
|
||||||
|
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
||||||
|
executes all interrupts must be unmasked. There is therefore no need to
|
||||||
|
save and then restore the interrupt mask value as its value is already
|
||||||
|
known. */
|
||||||
|
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
{
|
||||||
|
/* Increment the RTOS tick. */
|
||||||
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
|
{
|
||||||
|
/* A context switch is required. Context switching is performed in
|
||||||
|
the PendSV interrupt. Pend the PendSV interrupt. */
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
|
||||||
|
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for
|
||||||
|
is accounted for as best it can be, but using the tickless mode will
|
||||||
|
inevitably result in some tiny drift of the time maintained by the
|
||||||
|
kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
tick periods. -1 is used because this code will execute part way
|
||||||
|
through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__disable_interrupt();
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
to be unsuspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above __disable_interrupt()
|
||||||
|
call above. */
|
||||||
|
__enable_interrupt();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
set its parameter to 0 to indicate that its implementation contains
|
||||||
|
its own wait for interrupt or wait for event instruction, and so wfi
|
||||||
|
should not be executed again. However, the original expected idle
|
||||||
|
time variable must remain unmodified, so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__DSB();
|
||||||
|
__WFI();
|
||||||
|
__ISB();
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Stop SysTick. Again, the time the SysTick is stopped for is
|
||||||
|
accounted for as best it can be, but using the tickless mode will
|
||||||
|
inevitably result in some tiny drift of the time maintained by the
|
||||||
|
kernel with respect to calendar time. */
|
||||||
|
ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above __disable_interrupt()
|
||||||
|
call above. */
|
||||||
|
__enable_interrupt();
|
||||||
|
|
||||||
|
if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt has already executed, and the SysTick
|
||||||
|
count reloaded with ulReloadValue. Reset the
|
||||||
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt handler will already have pended the tick
|
||||||
|
processing in the kernel. As the pending tick will be
|
||||||
|
processed as soon as this function exits, the tick value
|
||||||
|
maintained by the tick is stepped forward by one less than the
|
||||||
|
time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
Work out how long the sleep lasted rounded to complete tick
|
||||||
|
periods (not the ulReload value which accounted for part
|
||||||
|
ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
value. The critical section is used to ensure the tick interrupt
|
||||||
|
can only execute once in the case that the reload register is near
|
||||||
|
zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the systick timer to generate the tick interrupts at the required
|
||||||
|
* frequency.
|
||||||
|
*/
|
||||||
|
__weak void vPortSetupTimerInterrupt( void )
|
||||||
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrentInterrupt;
|
||||||
|
uint8_t ucCurrentPriority;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
an interrupt that has been assigned a priority above
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
|
function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
|
from interrupts that have been assigned a priority at or below
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Numerically low interrupt priority numbers represent logically high
|
||||||
|
interrupt priorities, therefore the priority of the interrupt must
|
||||||
|
be set to a value equal to or numerically *higher* than
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Interrupts that use the FreeRTOS API must not be left at their
|
||||||
|
default priority of zero as that is the highest possible priority,
|
||||||
|
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||||
|
and therefore also guaranteed to be invalid.
|
||||||
|
|
||||||
|
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||||
|
interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
The following links provide detailed information:
|
||||||
|
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||||
|
http://www.freertos.org/FAQHelp.html */
|
||||||
|
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||||
|
that define each interrupt's priority to be split between bits that
|
||||||
|
define the interrupt's pre-emption priority bits and bits that define
|
||||||
|
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||||
|
to be pre-emption priority bits. The following assertion will fail if
|
||||||
|
this is not the case (if some bits represent a sub-priority).
|
||||||
|
|
||||||
|
If the application only uses CMSIS libraries for interrupt
|
||||||
|
configuration then the correct setting can be achieved on all Cortex-M
|
||||||
|
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
scheduler. Note however that some vendor specific peripheral libraries
|
||||||
|
assume a non-zero priority group setting, in which cases using a value
|
||||||
|
of zero will result in unpredicable behaviour. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName )
|
||||||
|
{
|
||||||
|
/* This function will be called if a task overflows its stack, if
|
||||||
|
configCHECK_FOR_STACK_OVERFLOW != 0 */
|
||||||
|
|
||||||
|
printf("\n\r[%s] STACK OVERFLOW - TaskName(%s)\n\r", __FUNCTION__, pcTaskName);
|
||||||
|
for( ;; );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <FreeRTOSConfig.h>
|
||||||
|
|
||||||
|
RSEG CODE:CODE(2)
|
||||||
|
thumb
|
||||||
|
|
||||||
|
EXTERN pxCurrentTCB
|
||||||
|
EXTERN vTaskSwitchContext
|
||||||
|
|
||||||
|
PUBLIC xPortPendSVHandler
|
||||||
|
PUBLIC ulPortSetInterruptMask
|
||||||
|
PUBLIC vPortClearInterruptMask
|
||||||
|
PUBLIC vPortSVCHandler
|
||||||
|
PUBLIC vPortStartFirstTask
|
||||||
|
PUBLIC vPortEnableVFP
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
xPortPendSVHandler:
|
||||||
|
mrs r0, psp
|
||||||
|
isb
|
||||||
|
/* Get the location of the current TCB. */
|
||||||
|
ldr r3, =pxCurrentTCB
|
||||||
|
ldr r2, [r3]
|
||||||
|
|
||||||
|
/* Is the task using the FPU context? If so, push high vfp registers. */
|
||||||
|
tst r14, #0x10
|
||||||
|
it eq
|
||||||
|
vstmdbeq r0!, {s16-s31}
|
||||||
|
|
||||||
|
/* Save the core registers. */
|
||||||
|
stmdb r0!, {r4-r11, r14}
|
||||||
|
|
||||||
|
/* Save the new top of stack into the first member of the TCB. */
|
||||||
|
str r0, [r2]
|
||||||
|
|
||||||
|
stmdb sp!, {r3}
|
||||||
|
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r0
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
ldmia sp!, {r3}
|
||||||
|
|
||||||
|
/* The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
ldr r1, [r3]
|
||||||
|
ldr r0, [r1]
|
||||||
|
|
||||||
|
/* Pop the core registers. */
|
||||||
|
ldmia r0!, {r4-r11, r14}
|
||||||
|
|
||||||
|
/* Is the task using the FPU context? If so, pop the high vfp registers
|
||||||
|
too. */
|
||||||
|
tst r14, #0x10
|
||||||
|
it eq
|
||||||
|
vldmiaeq r0!, {s16-s31}
|
||||||
|
|
||||||
|
msr psp, r0
|
||||||
|
isb
|
||||||
|
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
|
||||||
|
#if WORKAROUND_PMU_CM001 == 1
|
||||||
|
push { r14 }
|
||||||
|
pop { pc }
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bx r14
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
ulPortSetInterruptMask:
|
||||||
|
mrs r0, basepri
|
||||||
|
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r1
|
||||||
|
bx r14
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vPortClearInterruptMask:
|
||||||
|
msr basepri, r0
|
||||||
|
bx r14
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vPortSVCHandler:
|
||||||
|
/* Get the location of the current TCB. */
|
||||||
|
ldr r3, =pxCurrentTCB
|
||||||
|
ldr r1, [r3]
|
||||||
|
ldr r0, [r1]
|
||||||
|
/* Pop the core registers. */
|
||||||
|
ldmia r0!, {r4-r11, r14}
|
||||||
|
msr psp, r0
|
||||||
|
isb
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
bx r14
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vPortStartFirstTask
|
||||||
|
/* Use the NVIC offset register to locate the stack. */
|
||||||
|
ldr r0, =0xE000ED08
|
||||||
|
ldr r0, [r0]
|
||||||
|
ldr r0, [r0]
|
||||||
|
/* Set the msp back to the start of the stack. */
|
||||||
|
msr msp, r0
|
||||||
|
/* Call SVC to start the first task. */
|
||||||
|
cpsie i
|
||||||
|
cpsie f
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
svc 0
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
vPortEnableVFP:
|
||||||
|
/* The FPU enable bits are in the CPACR. */
|
||||||
|
ldr.w r0, =0xE000ED88
|
||||||
|
ldr r1, [r0]
|
||||||
|
|
||||||
|
/* Enable CP10 and CP11 coprocessors, then save back. */
|
||||||
|
orr r1, r1, #( 0xf << 20 )
|
||||||
|
str r1, [r0]
|
||||||
|
bx r14
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
END
|
||||||
|
|
||||||
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE uint32_t
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
#if( configUSE_16_BIT_TICKS == 1 )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#else
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specifics. */
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler utilities. */
|
||||||
|
extern void vPortYield( void );
|
||||||
|
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||||
|
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||||
|
#define portYIELD() vPortYield()
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||||
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specific optimisations. */
|
||||||
|
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||||
|
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||||
|
|
||||||
|
/* Check the configuration. */
|
||||||
|
#if( configMAX_PRIORITIES > 32 )
|
||||||
|
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Store/clear the ready priorities in a bit map. */
|
||||||
|
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||||
|
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <intrinsics.h>
|
||||||
|
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) )
|
||||||
|
|
||||||
|
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Critical section management. */
|
||||||
|
extern void vPortEnterCritical( void );
|
||||||
|
extern void vPortExitCritical( void );
|
||||||
|
extern uint32_t ulPortSetInterruptMask( void );
|
||||||
|
extern void vPortClearInterruptMask( uint32_t ulNewMask );
|
||||||
|
|
||||||
|
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
|
||||||
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Tickless idle/low power functionality. */
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||||
|
not necessary for to use this port. They are defined so the common demo files
|
||||||
|
(which build with all the ports) will build. */
|
||||||
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef configASSERT
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* portNOP() is not required by this port. */
|
||||||
|
#define portNOP()
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
the source code because to do so would cause other compilers to generate
|
||||||
|
warnings. */
|
||||||
|
#pragma diag_suppress=Pe191
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
include $(MAKE_INCLUDE_GEN)
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
MODULE_IFLAGS = -I../../include
|
||||||
|
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# Object FILE LIST #
|
||||||
|
#*****************************************************************************#
|
||||||
|
OBJS = heap_4.o
|
||||||
|
ifeq ($(CONFIG_RELEASE_BUILD),y)
|
||||||
|
OBJS =
|
||||||
|
else
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# RULES TO GENERATE TARGETS #
|
||||||
|
#*****************************************************************************#
|
||||||
|
|
||||||
|
# Define the Rules to build the core targets
|
||||||
|
all: CORE_TARGETS COPY_RAM_OBJS
|
||||||
|
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# GENERATE OBJECT FILE
|
||||||
|
#*****************************************************************************#
|
||||||
|
CORE_TARGETS: $(OBJS)
|
||||||
|
|
||||||
|
-include $(DEPS)
|
||||||
|
|
||||||
|
#*****************************************************************************#
|
||||||
|
# RULES TO CLEAN TARGETS #
|
||||||
|
#*****************************************************************************#
|
||||||
|
clean:
|
||||||
|
$(REMOVE) *.o
|
||||||
|
$(REMOVE) *.i
|
||||||
|
$(REMOVE) *.s
|
||||||
|
$(REMOVE) *.d
|
||||||
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The simplest possible implementation of pvPortMalloc(). Note that this
|
||||||
|
* implementation does NOT allow allocated memory to be freed again.
|
||||||
|
*
|
||||||
|
* See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the
|
||||||
|
* memory management pages of http://www.FreeRTOS.org for more information.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||||
|
all the API functions to use the MPU wrappers. That should only be done when
|
||||||
|
task.h is included from an application file. */
|
||||||
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/* A few bytes might be lost to byte aligning the heap start address. */
|
||||||
|
#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
|
||||||
|
|
||||||
|
/* Allocate the memory for the heap. */
|
||||||
|
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
|
||||||
|
static size_t xNextFreeByte = ( size_t ) 0;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void *pvPortMalloc( size_t xWantedSize )
|
||||||
|
{
|
||||||
|
void *pvReturn = NULL;
|
||||||
|
static uint8_t *pucAlignedHeap = NULL;
|
||||||
|
|
||||||
|
/* Ensure that blocks are always aligned to the required number of bytes. */
|
||||||
|
#if portBYTE_ALIGNMENT != 1
|
||||||
|
if( xWantedSize & portBYTE_ALIGNMENT_MASK )
|
||||||
|
{
|
||||||
|
/* Byte alignment required. */
|
||||||
|
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
if( pucAlignedHeap == NULL )
|
||||||
|
{
|
||||||
|
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||||
|
pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check there is enough room left for the allocation. */
|
||||||
|
if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) &&
|
||||||
|
( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) )/* Check for overflow. */
|
||||||
|
{
|
||||||
|
/* Return the next free byte then increment the index past this
|
||||||
|
block. */
|
||||||
|
pvReturn = pucAlignedHeap + xNextFreeByte;
|
||||||
|
xNextFreeByte += xWantedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
traceMALLOC( pvReturn, xWantedSize );
|
||||||
|
}
|
||||||
|
( void ) xTaskResumeAll();
|
||||||
|
|
||||||
|
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||||
|
{
|
||||||
|
if( pvReturn == NULL )
|
||||||
|
{
|
||||||
|
extern void vApplicationMallocFailedHook( void );
|
||||||
|
vApplicationMallocFailedHook();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return pvReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortFree( void *pv )
|
||||||
|
{
|
||||||
|
/* Memory cannot be freed using this scheme. See heap_2.c, heap_3.c and
|
||||||
|
heap_4.c for alternative implementations, and the memory management pages of
|
||||||
|
http://www.FreeRTOS.org for more information. */
|
||||||
|
( void ) pv;
|
||||||
|
|
||||||
|
/* Force an assert as it is invalid to call this function. */
|
||||||
|
configASSERT( pv == NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortInitialiseBlocks( void )
|
||||||
|
{
|
||||||
|
/* Only required when static memory is not cleared. */
|
||||||
|
xNextFreeByte = ( size_t ) 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
size_t xPortGetFreeHeapSize( void )
|
||||||
|
{
|
||||||
|
return ( configADJUSTED_HEAP_SIZE - xNextFreeByte );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,299 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A sample implementation of pvPortMalloc() and vPortFree() that permits
|
||||||
|
* allocated blocks to be freed, but does not combine adjacent free blocks
|
||||||
|
* into a single larger block (and so will fragment memory). See heap_4.c for
|
||||||
|
* an equivalent that does combine adjacent blocks into single larger blocks.
|
||||||
|
*
|
||||||
|
* See heap_1.c, heap_3.c and heap_4.c for alternative implementations, and the
|
||||||
|
* memory management pages of http://www.FreeRTOS.org for more information.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||||
|
all the API functions to use the MPU wrappers. That should only be done when
|
||||||
|
task.h is included from an application file. */
|
||||||
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/* A few bytes might be lost to byte aligning the heap start address. */
|
||||||
|
#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialises the heap structures before their first use.
|
||||||
|
*/
|
||||||
|
static void prvHeapInit( void );
|
||||||
|
|
||||||
|
/* Allocate the memory for the heap. */
|
||||||
|
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
|
||||||
|
|
||||||
|
/* Define the linked list structure. This is used to link free blocks in order
|
||||||
|
of their size. */
|
||||||
|
typedef struct A_BLOCK_LINK
|
||||||
|
{
|
||||||
|
struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */
|
||||||
|
size_t xBlockSize; /*<< The size of the free block. */
|
||||||
|
} BlockLink_t;
|
||||||
|
|
||||||
|
|
||||||
|
static const uint16_t heapSTRUCT_SIZE = ( ( sizeof ( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK );
|
||||||
|
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) )
|
||||||
|
|
||||||
|
/* Create a couple of list links to mark the start and end of the list. */
|
||||||
|
static BlockLink_t xStart, xEnd;
|
||||||
|
|
||||||
|
/* Keeps track of the number of free bytes remaining, but says nothing about
|
||||||
|
fragmentation. */
|
||||||
|
static size_t xFreeBytesRemaining = configADJUSTED_HEAP_SIZE;
|
||||||
|
|
||||||
|
/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert a block into the list of free blocks - which is ordered by size of
|
||||||
|
* the block. Small blocks at the start of the list and large blocks at the end
|
||||||
|
* of the list.
|
||||||
|
*/
|
||||||
|
#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \
|
||||||
|
{ \
|
||||||
|
BlockLink_t *pxIterator; \
|
||||||
|
size_t xBlockSize; \
|
||||||
|
\
|
||||||
|
xBlockSize = pxBlockToInsert->xBlockSize; \
|
||||||
|
\
|
||||||
|
/* Iterate through the list until a block is found that has a larger size */ \
|
||||||
|
/* than the block we are inserting. */ \
|
||||||
|
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock ) \
|
||||||
|
{ \
|
||||||
|
/* There is nothing to do here - just iterate to the correct position. */ \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Update the list to include the block being inserted in the correct */ \
|
||||||
|
/* position. */ \
|
||||||
|
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; \
|
||||||
|
pxIterator->pxNextFreeBlock = pxBlockToInsert; \
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void *pvPortMalloc( size_t xWantedSize )
|
||||||
|
{
|
||||||
|
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
|
||||||
|
static BaseType_t xHeapHasBeenInitialised = pdFALSE;
|
||||||
|
void *pvReturn = NULL;
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
/* If this is the first call to malloc then the heap will require
|
||||||
|
initialisation to setup the list of free blocks. */
|
||||||
|
if( xHeapHasBeenInitialised == pdFALSE )
|
||||||
|
{
|
||||||
|
prvHeapInit();
|
||||||
|
xHeapHasBeenInitialised = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The wanted size is increased so it can contain a BlockLink_t
|
||||||
|
structure in addition to the requested amount of bytes. */
|
||||||
|
if( xWantedSize > 0 )
|
||||||
|
{
|
||||||
|
xWantedSize += heapSTRUCT_SIZE;
|
||||||
|
|
||||||
|
/* Ensure that blocks are always aligned to the required number of bytes. */
|
||||||
|
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0 )
|
||||||
|
{
|
||||||
|
/* Byte alignment required. */
|
||||||
|
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( xWantedSize > 0 ) && ( xWantedSize < configADJUSTED_HEAP_SIZE ) )
|
||||||
|
{
|
||||||
|
/* Blocks are stored in byte order - traverse the list from the start
|
||||||
|
(smallest) block until one of adequate size is found. */
|
||||||
|
pxPreviousBlock = &xStart;
|
||||||
|
pxBlock = xStart.pxNextFreeBlock;
|
||||||
|
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||||
|
{
|
||||||
|
pxPreviousBlock = pxBlock;
|
||||||
|
pxBlock = pxBlock->pxNextFreeBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we found the end marker then a block of adequate size was not found. */
|
||||||
|
if( pxBlock != &xEnd )
|
||||||
|
{
|
||||||
|
/* Return the memory space - jumping over the BlockLink_t structure
|
||||||
|
at its start. */
|
||||||
|
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );
|
||||||
|
|
||||||
|
/* This block is being returned for use so must be taken out of the
|
||||||
|
list of free blocks. */
|
||||||
|
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||||
|
|
||||||
|
/* If the block is larger than required it can be split into two. */
|
||||||
|
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
|
||||||
|
{
|
||||||
|
/* This block is to be split into two. Create a new block
|
||||||
|
following the number of bytes requested. The void cast is
|
||||||
|
used to prevent byte alignment warnings from the compiler. */
|
||||||
|
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||||
|
|
||||||
|
/* Calculate the sizes of two blocks split from the single
|
||||||
|
block. */
|
||||||
|
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||||
|
pxBlock->xBlockSize = xWantedSize;
|
||||||
|
|
||||||
|
/* Insert the new block into the list of free blocks. */
|
||||||
|
prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
traceMALLOC( pvReturn, xWantedSize );
|
||||||
|
}
|
||||||
|
( void ) xTaskResumeAll();
|
||||||
|
|
||||||
|
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||||
|
{
|
||||||
|
if( pvReturn == NULL )
|
||||||
|
{
|
||||||
|
extern void vApplicationMallocFailedHook( void );
|
||||||
|
vApplicationMallocFailedHook();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return pvReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortFree( void *pv )
|
||||||
|
{
|
||||||
|
uint8_t *puc = ( uint8_t * ) pv;
|
||||||
|
BlockLink_t *pxLink;
|
||||||
|
|
||||||
|
if( pv != NULL )
|
||||||
|
{
|
||||||
|
/* The memory being freed will have an BlockLink_t structure immediately
|
||||||
|
before it. */
|
||||||
|
puc -= heapSTRUCT_SIZE;
|
||||||
|
|
||||||
|
/* This unexpected casting is to keep some compilers from issuing
|
||||||
|
byte alignment warnings. */
|
||||||
|
pxLink = ( void * ) puc;
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
/* Add this block to the list of free blocks. */
|
||||||
|
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||||
|
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||||
|
traceFREE( pv, pxLink->xBlockSize );
|
||||||
|
}
|
||||||
|
( void ) xTaskResumeAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
size_t xPortGetFreeHeapSize( void )
|
||||||
|
{
|
||||||
|
return xFreeBytesRemaining;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortInitialiseBlocks( void )
|
||||||
|
{
|
||||||
|
/* This just exists to keep the linker quiet. */
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvHeapInit( void )
|
||||||
|
{
|
||||||
|
BlockLink_t *pxFirstFreeBlock;
|
||||||
|
uint8_t *pucAlignedHeap;
|
||||||
|
|
||||||
|
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||||
|
pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) );
|
||||||
|
|
||||||
|
/* xStart is used to hold a pointer to the first item in the list of free
|
||||||
|
blocks. The void cast is used to prevent compiler warnings. */
|
||||||
|
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||||
|
xStart.xBlockSize = ( size_t ) 0;
|
||||||
|
|
||||||
|
/* xEnd is used to mark the end of the list of free blocks. */
|
||||||
|
xEnd.xBlockSize = configADJUSTED_HEAP_SIZE;
|
||||||
|
xEnd.pxNextFreeBlock = NULL;
|
||||||
|
|
||||||
|
/* To start with there is a single free block that is sized to take up the
|
||||||
|
entire heap space. */
|
||||||
|
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||||
|
pxFirstFreeBlock->xBlockSize = configADJUSTED_HEAP_SIZE;
|
||||||
|
pxFirstFreeBlock->pxNextFreeBlock = &xEnd;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implementation of pvPortMalloc() and vPortFree() that relies on the
|
||||||
|
* compilers own malloc() and free() implementations.
|
||||||
|
*
|
||||||
|
* This file can only be used if the linker is configured to to generate
|
||||||
|
* a heap memory area.
|
||||||
|
*
|
||||||
|
* See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the
|
||||||
|
* memory management pages of http://www.FreeRTOS.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||||
|
all the API functions to use the MPU wrappers. That should only be done when
|
||||||
|
task.h is included from an application file. */
|
||||||
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void *pvPortMalloc( size_t xWantedSize )
|
||||||
|
{
|
||||||
|
void *pvReturn;
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
pvReturn = malloc( xWantedSize );
|
||||||
|
traceMALLOC( pvReturn, xWantedSize );
|
||||||
|
}
|
||||||
|
( void ) xTaskResumeAll();
|
||||||
|
|
||||||
|
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||||
|
{
|
||||||
|
if( pvReturn == NULL )
|
||||||
|
{
|
||||||
|
extern void vApplicationMallocFailedHook( void );
|
||||||
|
vApplicationMallocFailedHook();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return pvReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortFree( void *pv )
|
||||||
|
{
|
||||||
|
if( pv )
|
||||||
|
{
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
free( pv );
|
||||||
|
traceFREE( pv, 0 );
|
||||||
|
}
|
||||||
|
( void ) xTaskResumeAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,544 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A sample implementation of pvPortMalloc() and vPortFree() that combines
|
||||||
|
* (coalescences) adjacent memory blocks as they are freed, and in so doing
|
||||||
|
* limits memory fragmentation.
|
||||||
|
*
|
||||||
|
* See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the
|
||||||
|
* memory management pages of http://www.FreeRTOS.org for more information.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||||
|
all the API functions to use the MPU wrappers. That should only be done when
|
||||||
|
task.h is included from an application file. */
|
||||||
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
|
||||||
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
|
/* Block sizes must not get too small. */
|
||||||
|
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize * 2 ) )
|
||||||
|
|
||||||
|
/* Assumes 8bit bytes! */
|
||||||
|
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||||
|
|
||||||
|
/* Allocate the memory for the heap. */
|
||||||
|
//TODO: remove section when combine BD and BF
|
||||||
|
#if ((defined CONFIG_PLATFORM_8195A) || (defined CONFIG_PLATFORM_8711B))
|
||||||
|
#include "section_config.h"
|
||||||
|
SRAM_BF_DATA_SECTION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
|
||||||
|
|
||||||
|
/* Define the linked list structure. This is used to link free blocks in order
|
||||||
|
of their memory address. */
|
||||||
|
typedef struct A_BLOCK_LINK
|
||||||
|
{
|
||||||
|
struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */
|
||||||
|
size_t xBlockSize; /*<< The size of the free block. */
|
||||||
|
} BlockLink_t;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inserts a block of memory that is being freed into the correct position in
|
||||||
|
* the list of free memory blocks. The block being freed will be merged with
|
||||||
|
* the block in front it and/or the block behind it if the memory blocks are
|
||||||
|
* adjacent to each other.
|
||||||
|
*/
|
||||||
|
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called automatically to setup the required heap structures the first time
|
||||||
|
* pvPortMalloc() is called.
|
||||||
|
*/
|
||||||
|
static void prvHeapInit( void );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* The size of the structure placed at the beginning of each allocated memory
|
||||||
|
block must by correctly byte aligned. */
|
||||||
|
static const size_t xHeapStructSize = ( ( sizeof( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK );
|
||||||
|
|
||||||
|
/* Create a couple of list links to mark the start and end of the list. */
|
||||||
|
static BlockLink_t xStart, *pxEnd = NULL;
|
||||||
|
|
||||||
|
/* Keeps track of the number of free bytes remaining, but says nothing about
|
||||||
|
fragmentation. */
|
||||||
|
static size_t xFreeBytesRemaining = 0U;
|
||||||
|
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||||
|
|
||||||
|
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
|
||||||
|
member of an BlockLink_t structure is set then the block belongs to the
|
||||||
|
application. When the bit is free the block is still part of the free heap
|
||||||
|
space. */
|
||||||
|
static size_t xBlockAllocatedBit = 0;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void *pvPortMalloc( size_t xWantedSize )
|
||||||
|
{
|
||||||
|
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
|
||||||
|
void *pvReturn = NULL;
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
/* If this is the first call to malloc then the heap will require
|
||||||
|
initialisation to setup the list of free blocks. */
|
||||||
|
if( pxEnd == NULL )
|
||||||
|
{
|
||||||
|
prvHeapInit();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the requested block size is not so large that the top bit is
|
||||||
|
set. The top bit of the block size member of the BlockLink_t structure
|
||||||
|
is used to determine who owns the block - the application or the
|
||||||
|
kernel, so it must be free. */
|
||||||
|
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||||
|
{
|
||||||
|
/* The wanted size is increased so it can contain a BlockLink_t
|
||||||
|
structure in addition to the requested amount of bytes. */
|
||||||
|
if( xWantedSize > 0 )
|
||||||
|
{
|
||||||
|
xWantedSize += xHeapStructSize;
|
||||||
|
|
||||||
|
/* Ensure that blocks are always aligned to the required number
|
||||||
|
of bytes. */
|
||||||
|
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||||
|
{
|
||||||
|
/* Byte alignment required. */
|
||||||
|
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
|
||||||
|
configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||||
|
{
|
||||||
|
/* Traverse the list from the start (lowest address) block until
|
||||||
|
one of adequate size is found. */
|
||||||
|
pxPreviousBlock = &xStart;
|
||||||
|
pxBlock = xStart.pxNextFreeBlock;
|
||||||
|
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||||
|
{
|
||||||
|
pxPreviousBlock = pxBlock;
|
||||||
|
pxBlock = pxBlock->pxNextFreeBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the end marker was reached then a block of adequate size
|
||||||
|
was not found. */
|
||||||
|
if( pxBlock != pxEnd )
|
||||||
|
{
|
||||||
|
/* Return the memory space pointed to - jumping over the
|
||||||
|
BlockLink_t structure at its start. */
|
||||||
|
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||||
|
|
||||||
|
/* This block is being returned for use so must be taken out
|
||||||
|
of the list of free blocks. */
|
||||||
|
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||||
|
|
||||||
|
/* If the block is larger than required it can be split into
|
||||||
|
two. */
|
||||||
|
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
|
||||||
|
{
|
||||||
|
/* This block is to be split into two. Create a new
|
||||||
|
block following the number of bytes requested. The void
|
||||||
|
cast is used to prevent byte alignment warnings from the
|
||||||
|
compiler. */
|
||||||
|
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||||
|
configASSERT( ( ( ( uint32_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||||
|
|
||||||
|
/* Calculate the sizes of two blocks split from the
|
||||||
|
single block. */
|
||||||
|
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||||
|
pxBlock->xBlockSize = xWantedSize;
|
||||||
|
|
||||||
|
/* Insert the new block into the list of free blocks. */
|
||||||
|
prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||||
|
|
||||||
|
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||||
|
{
|
||||||
|
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The block is being returned - it is allocated and owned
|
||||||
|
by the application and has no "next" block. */
|
||||||
|
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||||
|
pxBlock->pxNextFreeBlock = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
traceMALLOC( pvReturn, xWantedSize );
|
||||||
|
}
|
||||||
|
( void ) xTaskResumeAll();
|
||||||
|
|
||||||
|
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||||
|
{
|
||||||
|
if( pvReturn == NULL )
|
||||||
|
{
|
||||||
|
extern void vApplicationMallocFailedHook( void );
|
||||||
|
vApplicationMallocFailedHook();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
configASSERT( ( ( ( uint32_t ) pvReturn ) & portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||||
|
return pvReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void __vPortFree( void *pv )
|
||||||
|
{
|
||||||
|
uint8_t *puc = ( uint8_t * ) pv;
|
||||||
|
BlockLink_t *pxLink;
|
||||||
|
|
||||||
|
if( pv != NULL )
|
||||||
|
{
|
||||||
|
/* The memory being freed will have an BlockLink_t structure immediately
|
||||||
|
before it. */
|
||||||
|
puc -= xHeapStructSize;
|
||||||
|
|
||||||
|
/* This casting is to keep the compiler from issuing warnings. */
|
||||||
|
pxLink = ( void * ) puc;
|
||||||
|
|
||||||
|
/* Check the block is actually allocated. */
|
||||||
|
configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||||
|
configASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||||
|
|
||||||
|
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||||
|
{
|
||||||
|
if( pxLink->pxNextFreeBlock == NULL )
|
||||||
|
{
|
||||||
|
/* The block is being returned to the heap - it is no longer
|
||||||
|
allocated. */
|
||||||
|
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
/* Add this block to the list of free blocks. */
|
||||||
|
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||||
|
traceFREE( pv, pxLink->xBlockSize );
|
||||||
|
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||||
|
}
|
||||||
|
( void ) xTaskResumeAll();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
/* Add by Alfa 2015/02/04 -----------------------------------*/
|
||||||
|
static void (*ext_free)( void *p ) = NULL;
|
||||||
|
static uint32_t ext_upper = 0;
|
||||||
|
static uint32_t ext_lower = 0;
|
||||||
|
void vPortSetExtFree( void (*free)( void *p ), uint32_t upper, uint32_t lower )
|
||||||
|
{
|
||||||
|
ext_free = free;
|
||||||
|
ext_upper = upper;
|
||||||
|
ext_lower = lower;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vPortFree( void *pv )
|
||||||
|
{
|
||||||
|
if( ((uint32_t)pv >= ext_lower) && ((uint32_t)pv < ext_upper) ){
|
||||||
|
// use external free function
|
||||||
|
if( ext_free ) ext_free( pv );
|
||||||
|
}else
|
||||||
|
__vPortFree( pv );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
size_t xPortGetFreeHeapSize( void )
|
||||||
|
{
|
||||||
|
return xFreeBytesRemaining;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||||
|
{
|
||||||
|
return xMinimumEverFreeBytesRemaining;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortInitialiseBlocks( void )
|
||||||
|
{
|
||||||
|
/* This just exists to keep the linker quiet. */
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvHeapInit( void )
|
||||||
|
{
|
||||||
|
BlockLink_t *pxFirstFreeBlock;
|
||||||
|
uint8_t *pucAlignedHeap;
|
||||||
|
uint32_t ulAddress;
|
||||||
|
size_t xTotalHeapSize = configTOTAL_HEAP_SIZE;
|
||||||
|
|
||||||
|
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||||
|
ulAddress = ( uint32_t ) ucHeap;
|
||||||
|
|
||||||
|
if( ( ulAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
|
||||||
|
{
|
||||||
|
ulAddress += ( portBYTE_ALIGNMENT - 1 );
|
||||||
|
ulAddress &= ~portBYTE_ALIGNMENT_MASK;
|
||||||
|
xTotalHeapSize -= ulAddress - ( uint32_t ) ucHeap;
|
||||||
|
}
|
||||||
|
|
||||||
|
pucAlignedHeap = ( uint8_t * ) ulAddress;
|
||||||
|
|
||||||
|
/* xStart is used to hold a pointer to the first item in the list of free
|
||||||
|
blocks. The void cast is used to prevent compiler warnings. */
|
||||||
|
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||||
|
xStart.xBlockSize = ( size_t ) 0;
|
||||||
|
|
||||||
|
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||||
|
at the end of the heap space. */
|
||||||
|
ulAddress = ( ( uint32_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||||
|
ulAddress -= xHeapStructSize;
|
||||||
|
ulAddress &= ~portBYTE_ALIGNMENT_MASK;
|
||||||
|
pxEnd = ( void * ) ulAddress;
|
||||||
|
pxEnd->xBlockSize = 0;
|
||||||
|
pxEnd->pxNextFreeBlock = NULL;
|
||||||
|
|
||||||
|
/* To start with there is a single free block that is sized to take up the
|
||||||
|
entire heap space, minus the space taken by pxEnd. */
|
||||||
|
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||||
|
pxFirstFreeBlock->xBlockSize = ulAddress - ( uint32_t ) pxFirstFreeBlock;
|
||||||
|
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||||
|
|
||||||
|
/* Only one block exists - and it covers the entire usable heap space. */
|
||||||
|
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||||
|
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||||
|
|
||||||
|
/* Work out the position of the top bit in a size_t variable. */
|
||||||
|
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert )
|
||||||
|
{
|
||||||
|
BlockLink_t *pxIterator;
|
||||||
|
uint8_t *puc;
|
||||||
|
|
||||||
|
/* Iterate through the list until a block is found that has a higher address
|
||||||
|
than the block being inserted. */
|
||||||
|
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||||
|
{
|
||||||
|
/* Nothing to do here, just iterate to the right position. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the block being inserted, and the block it is being inserted after
|
||||||
|
make a contiguous block of memory? */
|
||||||
|
puc = ( uint8_t * ) pxIterator;
|
||||||
|
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||||
|
{
|
||||||
|
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||||
|
pxBlockToInsert = pxIterator;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the block being inserted, and the block it is being inserted before
|
||||||
|
make a contiguous block of memory? */
|
||||||
|
puc = ( uint8_t * ) pxBlockToInsert;
|
||||||
|
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||||
|
{
|
||||||
|
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||||
|
{
|
||||||
|
/* Form one big block from the two blocks. */
|
||||||
|
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||||
|
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the block being inserted plugged a gab, so was merged with the block
|
||||||
|
before and the block after, then it's pxNextFreeBlock pointer will have
|
||||||
|
already been set, and should not be set here as that would make it point
|
||||||
|
to itself. */
|
||||||
|
if( pxIterator != pxBlockToInsert )
|
||||||
|
{
|
||||||
|
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* pvPortReAlloc( void *pv, size_t xWantedSize )
|
||||||
|
{
|
||||||
|
BlockLink_t *pxLink;
|
||||||
|
|
||||||
|
if( ((uint32_t)pv >= ext_lower) && ((uint32_t)pv < ext_upper) ){
|
||||||
|
if( ext_free ) ext_free( pv );
|
||||||
|
pv = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *puc = ( unsigned char * ) pv;
|
||||||
|
|
||||||
|
if( pv )
|
||||||
|
{
|
||||||
|
if( !xWantedSize )
|
||||||
|
{
|
||||||
|
vPortFree( pv );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *newArea = pvPortMalloc( xWantedSize );
|
||||||
|
if( newArea )
|
||||||
|
{
|
||||||
|
/* The memory being freed will have an xBlockLink structure immediately
|
||||||
|
before it. */
|
||||||
|
puc -= xHeapStructSize;
|
||||||
|
|
||||||
|
/* This casting is to keep the compiler from issuing warnings. */
|
||||||
|
pxLink = ( void * ) puc;
|
||||||
|
|
||||||
|
int oldSize = (pxLink->xBlockSize & ~xBlockAllocatedBit) - xHeapStructSize;
|
||||||
|
int copySize = ( oldSize < xWantedSize ) ? oldSize : xWantedSize;
|
||||||
|
memcpy( newArea, pv, copySize );
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
/* Add this block to the list of free blocks. */
|
||||||
|
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||||
|
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||||
|
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||||
|
}
|
||||||
|
xTaskResumeAll();
|
||||||
|
return newArea;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( xWantedSize )
|
||||||
|
return pvPortMalloc( xWantedSize );
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -680,6 +680,15 @@ void* pvPortReAlloc( void *pv, size_t xWantedSize )
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern _LONG_CALL_ROM_ void *_memset( void *s, int c, SIZE_T n );
|
||||||
|
|
||||||
|
void *pvPortZalloc( size_t xWantedSize )
|
||||||
|
{
|
||||||
|
void * prt = pvPortMalloc(xWantedSize);
|
||||||
|
if(prt) _memset(prt, 0, xWantedSize);
|
||||||
|
return prt;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#ifdef ARDUINO_SDK
|
#ifdef ARDUINO_SDK
|
||||||
int vPortAddHeapRegion(uint8_t *addr, size_t size)
|
int vPortAddHeapRegion(uint8_t *addr, size_t size)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,724 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Implementation of functions defined in portable.h for the ARM CM3 port.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#ifndef configKERNEL_INTERRUPT_PRIORITY
|
||||||
|
#define configKERNEL_INTERRUPT_PRIORITY 255
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
|
||||||
|
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||||
|
as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The __weak attribute does not work as you might expect with the Keil tools
|
||||||
|
so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if
|
||||||
|
the application writer wants to provide their own implementation of
|
||||||
|
vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION
|
||||||
|
is defined. */
|
||||||
|
#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION
|
||||||
|
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Constants required to manipulate the core. Registers first... */
|
||||||
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
|
/* ...then bits in the registers. */
|
||||||
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
|
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||||
|
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||||
|
|
||||||
|
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||||
|
#define portVECTACTIVE_MASK ( 0x1FUL )
|
||||||
|
|
||||||
|
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
|
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt priority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||||
|
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||||
|
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||||
|
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
#define portPRIGROUP_SHIFT ( 8UL )
|
||||||
|
|
||||||
|
/* Constants required to set up the initial stack. */
|
||||||
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
|
|
||||||
|
/* Constants used with memory barrier intrinsics. */
|
||||||
|
#define portSY_FULL_READ_WRITE ( 15 )
|
||||||
|
|
||||||
|
/* The systick is a 24-bit counter. */
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||||
|
occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
calculations. */
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
|
||||||
|
/* Each task maintains its own interrupt status in the critical nesting
|
||||||
|
variable. */
|
||||||
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||||
|
* file is weak to allow application writers to change the timer used to
|
||||||
|
* generate the tick interrupt.
|
||||||
|
*/
|
||||||
|
void vPortSetupTimerInterrupt( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exception handlers.
|
||||||
|
*/
|
||||||
|
void xPortPendSVHandler( void );
|
||||||
|
void xPortSysTickHandler( void );
|
||||||
|
void vPortSVCHandler( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start first task is a separate function so it can be tested in isolation.
|
||||||
|
*/
|
||||||
|
static void prvStartFirstTask( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to catch tasks that attempt to return from their implementing function.
|
||||||
|
*/
|
||||||
|
static void prvTaskExitError( void );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The maximum number of tick periods that can be suppressed is limited by the
|
||||||
|
* 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||||
|
* power functionality only.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||||
|
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||||
|
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*/
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
static uint8_t ucMaxSysCallPriority = 0;
|
||||||
|
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||||
|
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||||
|
{
|
||||||
|
/* Simulate the stack frame as it would be created by a context switch
|
||||||
|
interrupt. */
|
||||||
|
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||||
|
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
|
||||||
|
|
||||||
|
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||||
|
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||||
|
|
||||||
|
return pxTopOfStack;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTaskExitError( void )
|
||||||
|
{
|
||||||
|
/* A function that implements a task must not exit or attempt to return to
|
||||||
|
its caller as there is nothing to return to. If a task wants to exit it
|
||||||
|
should instead call vTaskDelete( NULL ).
|
||||||
|
|
||||||
|
Artificially force an assert() to be triggered if configASSERT() is
|
||||||
|
defined, then stop here so application writers can catch the error. */
|
||||||
|
configASSERT( uxCriticalNesting == ~0UL );
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
for( ;; );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm void vPortSVCHandler( void )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
ldr r3, =pxCurrentTCB /* Restore the context. */
|
||||||
|
ldr r1, [r3] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
|
||||||
|
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
|
||||||
|
msr psp, r0 /* Restore the task stack pointer. */
|
||||||
|
isb
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
orr r14, #0xd
|
||||||
|
bx r14
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm void prvStartFirstTask( void )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
/* Use the NVIC offset register to locate the stack. */
|
||||||
|
ldr r0, =0xE000ED08
|
||||||
|
ldr r0, [r0]
|
||||||
|
ldr r0, [r0]
|
||||||
|
/* Set the msp back to the start of the stack. */
|
||||||
|
msr msp, r0
|
||||||
|
/* Globally enable interrupts. */
|
||||||
|
cpsie i
|
||||||
|
cpsie f
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
/* Call SVC to start the first task. */
|
||||||
|
svc 0
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile uint32_t ulOriginalPriority;
|
||||||
|
volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
volatile uint8_t ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
functions can be called. ISR safe functions are those that end in
|
||||||
|
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Determine the number of priority bits available. First write to all
|
||||||
|
possible bits. */
|
||||||
|
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||||
|
|
||||||
|
/* Read the value back to see how many bits stuck. */
|
||||||
|
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Use the same mask on the maximum system call priority. */
|
||||||
|
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Calculate the maximum acceptable priority group value for the number
|
||||||
|
of bits read back. */
|
||||||
|
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||||
|
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||||
|
{
|
||||||
|
ulMaxPRIGROUPValue--;
|
||||||
|
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift the priority group value back to its position within the AIRCR
|
||||||
|
register. */
|
||||||
|
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||||
|
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
value. */
|
||||||
|
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
|
here already. */
|
||||||
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
|
uxCriticalNesting = 0;
|
||||||
|
|
||||||
|
/* Start the first task. */
|
||||||
|
prvStartFirstTask();
|
||||||
|
|
||||||
|
/* Should not get here! */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEndScheduler( void )
|
||||||
|
{
|
||||||
|
/* Not implemented in ports where there is nothing to return to.
|
||||||
|
Artificially force an assert. */
|
||||||
|
configASSERT( uxCriticalNesting == 1000UL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortYield( void )
|
||||||
|
{
|
||||||
|
/* Set a PendSV to request a context switch. */
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
|
/* Barriers are normally not required but do ensure the code is completely
|
||||||
|
within the specified behaviour for the architecture. */
|
||||||
|
__dsb( portSY_FULL_READ_WRITE );
|
||||||
|
__isb( portSY_FULL_READ_WRITE );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEnterCritical( void )
|
||||||
|
{
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
uxCriticalNesting++;
|
||||||
|
__dsb( portSY_FULL_READ_WRITE );
|
||||||
|
__isb( portSY_FULL_READ_WRITE );
|
||||||
|
|
||||||
|
/* This is not the interrupt safe version of the enter critical function so
|
||||||
|
assert() if it is being called from an interrupt context. Only API
|
||||||
|
functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||||
|
the critical nesting count is 1 to protect against recursive calls if the
|
||||||
|
assert function also uses a critical section. */
|
||||||
|
if( uxCriticalNesting == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortExitCritical( void )
|
||||||
|
{
|
||||||
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm void xPortPendSVHandler( void )
|
||||||
|
{
|
||||||
|
extern uxCriticalNesting;
|
||||||
|
extern pxCurrentTCB;
|
||||||
|
extern vTaskSwitchContext;
|
||||||
|
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
mrs r0, psp
|
||||||
|
isb
|
||||||
|
|
||||||
|
ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
|
||||||
|
ldr r2, [r3]
|
||||||
|
|
||||||
|
stmdb r0!, {r4-r11} /* Save the remaining registers. */
|
||||||
|
str r0, [r2] /* Save the new top of stack into the first member of the TCB. */
|
||||||
|
|
||||||
|
stmdb sp!, {r3, r14}
|
||||||
|
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r0
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
ldmia sp!, {r3, r14}
|
||||||
|
|
||||||
|
ldr r1, [r3]
|
||||||
|
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */
|
||||||
|
msr psp, r0
|
||||||
|
isb
|
||||||
|
bx r14
|
||||||
|
nop
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void xPortSysTickHandler( void )
|
||||||
|
{
|
||||||
|
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
||||||
|
executes all interrupts must be unmasked. There is therefore no need to
|
||||||
|
save and then restore the interrupt mask value as its value is already
|
||||||
|
known. */
|
||||||
|
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
{
|
||||||
|
/* Increment the RTOS tick. */
|
||||||
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
|
{
|
||||||
|
/* A context switch is required. Context switching is performed in
|
||||||
|
the PendSV interrupt. Pend the PendSV interrupt. */
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
|
||||||
|
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for
|
||||||
|
is accounted for as best it can be, but using the tickless mode will
|
||||||
|
inevitably result in some tiny drift of the time maintained by the
|
||||||
|
kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
tick periods. -1 is used because this code will execute part way
|
||||||
|
through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__disable_irq();
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
to be unsuspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above __disable_irq() call
|
||||||
|
above. */
|
||||||
|
__enable_irq();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
set its parameter to 0 to indicate that its implementation contains
|
||||||
|
its own wait for interrupt or wait for event instruction, and so wfi
|
||||||
|
should not be executed again. However, the original expected idle
|
||||||
|
time variable must remain unmodified, so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__dsb( portSY_FULL_READ_WRITE );
|
||||||
|
__wfi();
|
||||||
|
__isb( portSY_FULL_READ_WRITE );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Stop SysTick. Again, the time the SysTick is stopped for is
|
||||||
|
accounted for as best it can be, but using the tickless mode will
|
||||||
|
inevitably result in some tiny drift of the time maintained by the
|
||||||
|
kernel with respect to calendar time. */
|
||||||
|
ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above __disable_irq() call
|
||||||
|
above. */
|
||||||
|
__enable_irq();
|
||||||
|
|
||||||
|
if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt has already executed, and the SysTick
|
||||||
|
count reloaded with ulReloadValue. Reset the
|
||||||
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt handler will already have pended the tick
|
||||||
|
processing in the kernel. As the pending tick will be
|
||||||
|
processed as soon as this function exits, the tick value
|
||||||
|
maintained by the tick is stepped forward by one less than the
|
||||||
|
time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
Work out how long the sleep lasted rounded to complete tick
|
||||||
|
periods (not the ulReload value which accounted for part
|
||||||
|
ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
value. The critical section is used to ensure the tick interrupt
|
||||||
|
can only execute once in the case that the reload register is near
|
||||||
|
zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the SysTick timer to generate the tick interrupts at the required
|
||||||
|
* frequency.
|
||||||
|
*/
|
||||||
|
#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0
|
||||||
|
|
||||||
|
void vPortSetupTimerInterrupt( void )
|
||||||
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm uint32_t ulPortSetInterruptMask( void )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
mrs r0, basepri
|
||||||
|
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r1
|
||||||
|
bx r14
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm void vPortClearInterruptMask( uint32_t ulNewMask )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
msr basepri, r0
|
||||||
|
bx r14
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm uint32_t vPortGetIPSR( void )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
mrs r0, ipsr
|
||||||
|
bx r14
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrentInterrupt;
|
||||||
|
uint8_t ucCurrentPriority;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
ulCurrentInterrupt = vPortGetIPSR();
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
an interrupt that has been assigned a priority above
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
|
function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
|
from interrupts that have been assigned a priority at or below
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Numerically low interrupt priority numbers represent logically high
|
||||||
|
interrupt priorities, therefore the priority of the interrupt must
|
||||||
|
be set to a value equal to or numerically *higher* than
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Interrupts that use the FreeRTOS API must not be left at their
|
||||||
|
default priority of zero as that is the highest possible priority,
|
||||||
|
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||||
|
and therefore also guaranteed to be invalid.
|
||||||
|
|
||||||
|
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||||
|
interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
The following links provide detailed information:
|
||||||
|
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||||
|
http://www.freertos.org/FAQHelp.html */
|
||||||
|
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||||
|
that define each interrupt's priority to be split between bits that
|
||||||
|
define the interrupt's pre-emption priority bits and bits that define
|
||||||
|
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||||
|
to be pre-emption priority bits. The following assertion will fail if
|
||||||
|
this is not the case (if some bits represent a sub-priority).
|
||||||
|
|
||||||
|
If the application only uses CMSIS libraries for interrupt
|
||||||
|
configuration then the correct setting can be achieved on all Cortex-M
|
||||||
|
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
scheduler. Note however that some vendor specific peripheral libraries
|
||||||
|
assume a non-zero priority group setting, in which cases using a value
|
||||||
|
of zero will result in unpredicable behaviour. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,185 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE uint32_t
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
#if( configUSE_16_BIT_TICKS == 1 )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#else
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specifics. */
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler utilities. */
|
||||||
|
extern void vPortYield( void );
|
||||||
|
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||||
|
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||||
|
#define portYIELD() vPortYield()
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||||
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Critical section management. */
|
||||||
|
extern uint32_t ulPortSetInterruptMask( void );
|
||||||
|
extern void vPortClearInterruptMask( uint32_t ulNewMask );
|
||||||
|
extern void vPortEnterCritical( void );
|
||||||
|
extern void vPortExitCritical( void );
|
||||||
|
|
||||||
|
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
|
||||||
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Tickless idle/low power functionality. */
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Port specific optimisations. */
|
||||||
|
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||||
|
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||||
|
|
||||||
|
/* Check the configuration. */
|
||||||
|
#if( configMAX_PRIORITIES > 32 )
|
||||||
|
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Store/clear the ready priorities in a bit map. */
|
||||||
|
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||||
|
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
|
||||||
|
|
||||||
|
#endif /* taskRECORD_READY_PRIORITY */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||||
|
not necessary for to use this port. They are defined so the common demo files
|
||||||
|
(which build with all the ports) will build. */
|
||||||
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef configASSERT
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* portNOP() is not required by this port. */
|
||||||
|
#define portNOP()
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,803 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Implementation of functions defined in portable.h for the ARM CM4F port.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#ifndef __TARGET_FPU_VFP
|
||||||
|
#error This port can only be used when the project options are configured to enable hardware floating point support.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
|
||||||
|
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||||
|
as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The __weak attribute does not work as you might expect with the Keil tools
|
||||||
|
so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if
|
||||||
|
the application writer wants to provide their own implementation of
|
||||||
|
vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION
|
||||||
|
is defined. */
|
||||||
|
#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION
|
||||||
|
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Constants required to manipulate the core. Registers first... */
|
||||||
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
|
/* ...then bits in the registers. */
|
||||||
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
|
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||||
|
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||||
|
|
||||||
|
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
|
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt priority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||||
|
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||||
|
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||||
|
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
#define portPRIGROUP_SHIFT ( 8UL )
|
||||||
|
|
||||||
|
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||||
|
#define portVECTACTIVE_MASK ( 0x1FUL )
|
||||||
|
|
||||||
|
/* Constants required to manipulate the VFP. */
|
||||||
|
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
|
||||||
|
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
||||||
|
|
||||||
|
/* Constants required to set up the initial stack. */
|
||||||
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
|
#define portINITIAL_EXEC_RETURN ( 0xfffffffd )
|
||||||
|
|
||||||
|
/* Constants used with memory barrier intrinsics. */
|
||||||
|
#define portSY_FULL_READ_WRITE ( 15 )
|
||||||
|
|
||||||
|
/* The systick is a 24-bit counter. */
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||||
|
occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
calculations. */
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
|
||||||
|
/* Each task maintains its own interrupt status in the critical nesting
|
||||||
|
variable. */
|
||||||
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||||
|
* file is weak to allow application writers to change the timer used to
|
||||||
|
* generate the tick interrupt.
|
||||||
|
*/
|
||||||
|
void vPortSetupTimerInterrupt( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exception handlers.
|
||||||
|
*/
|
||||||
|
void xPortPendSVHandler( void );
|
||||||
|
void xPortSysTickHandler( void );
|
||||||
|
void vPortSVCHandler( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start first task is a separate function so it can be tested in isolation.
|
||||||
|
*/
|
||||||
|
static void prvStartFirstTask( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions defined in portasm.s to enable the VFP.
|
||||||
|
*/
|
||||||
|
static void prvEnableVFP( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to catch tasks that attempt to return from their implementing function.
|
||||||
|
*/
|
||||||
|
static void prvTaskExitError( void );
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The maximum number of tick periods that can be suppressed is limited by the
|
||||||
|
* 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||||
|
* power functionality only.
|
||||||
|
*/
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||||
|
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||||
|
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*/
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
static uint8_t ucMaxSysCallPriority = 0;
|
||||||
|
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||||
|
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||||
|
{
|
||||||
|
/* Simulate the stack frame as it would be created by a context switch
|
||||||
|
interrupt. */
|
||||||
|
|
||||||
|
/* Offset added to account for the way the MCU uses the stack on entry/exit
|
||||||
|
of interrupts, and to ensure alignment. */
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
|
||||||
|
|
||||||
|
/* Save code space by skipping register initialisation. */
|
||||||
|
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||||
|
|
||||||
|
/* A save method is being used that requires each task to maintain its
|
||||||
|
own exec return value. */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = portINITIAL_EXEC_RETURN;
|
||||||
|
|
||||||
|
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||||
|
|
||||||
|
return pxTopOfStack;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTaskExitError( void )
|
||||||
|
{
|
||||||
|
/* A function that implements a task must not exit or attempt to return to
|
||||||
|
its caller as there is nothing to return to. If a task wants to exit it
|
||||||
|
should instead call vTaskDelete( NULL ).
|
||||||
|
|
||||||
|
Artificially force an assert() to be triggered if configASSERT() is
|
||||||
|
defined, then stop here so application writers can catch the error. */
|
||||||
|
configASSERT( uxCriticalNesting == ~0UL );
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
for( ;; );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm void vPortSVCHandler( void )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
/* Get the location of the current TCB. */
|
||||||
|
ldr r3, =pxCurrentTCB
|
||||||
|
ldr r1, [r3]
|
||||||
|
ldr r0, [r1]
|
||||||
|
/* Pop the core registers. */
|
||||||
|
ldmia r0!, {r4-r11, r14}
|
||||||
|
msr psp, r0
|
||||||
|
isb
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
bx r14
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm void prvStartFirstTask( void )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
/* Use the NVIC offset register to locate the stack. */
|
||||||
|
ldr r0, =0xE000ED08
|
||||||
|
ldr r0, [r0]
|
||||||
|
ldr r0, [r0]
|
||||||
|
/* Set the msp back to the start of the stack. */
|
||||||
|
msr msp, r0
|
||||||
|
/* Globally enable interrupts. */
|
||||||
|
cpsie i
|
||||||
|
cpsie f
|
||||||
|
dsb
|
||||||
|
isb
|
||||||
|
/* Call SVC to start the first task. */
|
||||||
|
svc 0
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm void prvEnableVFP( void )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
/* The FPU enable bits are in the CPACR. */
|
||||||
|
ldr.w r0, =0xE000ED88
|
||||||
|
ldr r1, [r0]
|
||||||
|
|
||||||
|
/* Enable CP10 and CP11 coprocessors, then save back. */
|
||||||
|
orr r1, r1, #( 0xf << 20 )
|
||||||
|
str r1, [r0]
|
||||||
|
bx r14
|
||||||
|
nop
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile uint32_t ulOriginalPriority;
|
||||||
|
volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
volatile uint8_t ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
functions can be called. ISR safe functions are those that end in
|
||||||
|
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Determine the number of priority bits available. First write to all
|
||||||
|
possible bits. */
|
||||||
|
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||||
|
|
||||||
|
/* Read the value back to see how many bits stuck. */
|
||||||
|
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Use the same mask on the maximum system call priority. */
|
||||||
|
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||||
|
|
||||||
|
/* Calculate the maximum acceptable priority group value for the number
|
||||||
|
of bits read back. */
|
||||||
|
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||||
|
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||||
|
{
|
||||||
|
ulMaxPRIGROUPValue--;
|
||||||
|
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift the priority group value back to its position within the AIRCR
|
||||||
|
register. */
|
||||||
|
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||||
|
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
value. */
|
||||||
|
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
|
here already. */
|
||||||
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
|
uxCriticalNesting = 0;
|
||||||
|
|
||||||
|
/* Ensure the VFP is enabled - it should be anyway. */
|
||||||
|
prvEnableVFP();
|
||||||
|
|
||||||
|
/* Lazy save always. */
|
||||||
|
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
|
||||||
|
|
||||||
|
/* Start the first task. */
|
||||||
|
prvStartFirstTask();
|
||||||
|
|
||||||
|
/* Should not get here! */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEndScheduler( void )
|
||||||
|
{
|
||||||
|
/* Not implemented in ports where there is nothing to return to.
|
||||||
|
Artificially force an assert. */
|
||||||
|
configASSERT( uxCriticalNesting == 1000UL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortYield( void )
|
||||||
|
{
|
||||||
|
/* Set a PendSV to request a context switch. */
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
|
/* Barriers are normally not required but do ensure the code is completely
|
||||||
|
within the specified behaviour for the architecture. */
|
||||||
|
__dsb( portSY_FULL_READ_WRITE );
|
||||||
|
__isb( portSY_FULL_READ_WRITE );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEnterCritical( void )
|
||||||
|
{
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
uxCriticalNesting++;
|
||||||
|
__dsb( portSY_FULL_READ_WRITE );
|
||||||
|
__isb( portSY_FULL_READ_WRITE );
|
||||||
|
|
||||||
|
/* This is not the interrupt safe version of the enter critical function so
|
||||||
|
assert() if it is being called from an interrupt context. Only API
|
||||||
|
functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||||
|
the critical nesting count is 1 to protect against recursive calls if the
|
||||||
|
assert function also uses a critical section. */
|
||||||
|
if( uxCriticalNesting == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortExitCritical( void )
|
||||||
|
{
|
||||||
|
configASSERT( uxCriticalNesting );
|
||||||
|
uxCriticalNesting--;
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm void xPortPendSVHandler( void )
|
||||||
|
{
|
||||||
|
extern uxCriticalNesting;
|
||||||
|
extern pxCurrentTCB;
|
||||||
|
extern vTaskSwitchContext;
|
||||||
|
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
mrs r0, psp
|
||||||
|
isb
|
||||||
|
/* Get the location of the current TCB. */
|
||||||
|
ldr r3, =pxCurrentTCB
|
||||||
|
ldr r2, [r3]
|
||||||
|
|
||||||
|
/* Is the task using the FPU context? If so, push high vfp registers. */
|
||||||
|
tst r14, #0x10
|
||||||
|
it eq
|
||||||
|
vstmdbeq r0!, {s16-s31}
|
||||||
|
|
||||||
|
/* Save the core registers. */
|
||||||
|
stmdb r0!, {r4-r11, r14}
|
||||||
|
|
||||||
|
/* Save the new top of stack into the first member of the TCB. */
|
||||||
|
str r0, [r2]
|
||||||
|
|
||||||
|
stmdb sp!, {r3}
|
||||||
|
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r0
|
||||||
|
bl vTaskSwitchContext
|
||||||
|
mov r0, #0
|
||||||
|
msr basepri, r0
|
||||||
|
ldmia sp!, {r3}
|
||||||
|
|
||||||
|
/* The first item in pxCurrentTCB is the task top of stack. */
|
||||||
|
ldr r1, [r3]
|
||||||
|
ldr r0, [r1]
|
||||||
|
|
||||||
|
/* Pop the core registers. */
|
||||||
|
ldmia r0!, {r4-r11, r14}
|
||||||
|
|
||||||
|
/* Is the task using the FPU context? If so, pop the high vfp registers
|
||||||
|
too. */
|
||||||
|
tst r14, #0x10
|
||||||
|
it eq
|
||||||
|
vldmiaeq r0!, {s16-s31}
|
||||||
|
|
||||||
|
msr psp, r0
|
||||||
|
isb
|
||||||
|
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
|
||||||
|
#if WORKAROUND_PMU_CM001 == 1
|
||||||
|
push { r14 }
|
||||||
|
pop { pc }
|
||||||
|
nop
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bx r14
|
||||||
|
nop
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void xPortSysTickHandler( void )
|
||||||
|
{
|
||||||
|
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
||||||
|
executes all interrupts must be unmasked. There is therefore no need to
|
||||||
|
save and then restore the interrupt mask value as its value is already
|
||||||
|
known. */
|
||||||
|
( void ) portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
{
|
||||||
|
/* Increment the RTOS tick. */
|
||||||
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
|
{
|
||||||
|
/* A context switch is required. Context switching is performed in
|
||||||
|
the PendSV interrupt. Pend the PendSV interrupt. */
|
||||||
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
|
||||||
|
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for
|
||||||
|
is accounted for as best it can be, but using the tickless mode will
|
||||||
|
inevitably result in some tiny drift of the time maintained by the
|
||||||
|
kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
tick periods. -1 is used because this code will execute part way
|
||||||
|
through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__disable_irq();
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
to be unsuspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above __disable_irq() call
|
||||||
|
above. */
|
||||||
|
__enable_irq();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
set its parameter to 0 to indicate that its implementation contains
|
||||||
|
its own wait for interrupt or wait for event instruction, and so wfi
|
||||||
|
should not be executed again. However, the original expected idle
|
||||||
|
time variable must remain unmodified, so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__dsb( portSY_FULL_READ_WRITE );
|
||||||
|
__wfi();
|
||||||
|
__isb( portSY_FULL_READ_WRITE );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Stop SysTick. Again, the time the SysTick is stopped for is
|
||||||
|
accounted for as best it can be, but using the tickless mode will
|
||||||
|
inevitably result in some tiny drift of the time maintained by the
|
||||||
|
kernel with respect to calendar time. */
|
||||||
|
ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above __disable_irq() call
|
||||||
|
above. */
|
||||||
|
__enable_irq();
|
||||||
|
|
||||||
|
if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt has already executed, and the SysTick
|
||||||
|
count reloaded with ulReloadValue. Reset the
|
||||||
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt handler will already have pended the tick
|
||||||
|
processing in the kernel. As the pending tick will be
|
||||||
|
processed as soon as this function exits, the tick value
|
||||||
|
maintained by the tick is stepped forward by one less than the
|
||||||
|
time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
Work out how long the sleep lasted rounded to complete tick
|
||||||
|
periods (not the ulReload value which accounted for part
|
||||||
|
ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
value. The critical section is used to ensure the tick interrupt
|
||||||
|
can only execute once in the case that the reload register is near
|
||||||
|
zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the SysTick timer to generate the tick interrupts at the required
|
||||||
|
* frequency.
|
||||||
|
*/
|
||||||
|
#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0
|
||||||
|
|
||||||
|
void vPortSetupTimerInterrupt( void )
|
||||||
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if configUSE_TICKLESS_IDLE == 1
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm uint32_t ulPortSetInterruptMask( void )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
mrs r0, basepri
|
||||||
|
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||||
|
msr basepri, r1
|
||||||
|
bx r14
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm void vPortClearInterruptMask( uint32_t ulNewMask )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
msr basepri, r0
|
||||||
|
bx r14
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm uint32_t vPortGetIPSR( void )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
mrs r0, ipsr
|
||||||
|
bx r14
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrentInterrupt;
|
||||||
|
uint8_t ucCurrentPriority;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
ulCurrentInterrupt = vPortGetIPSR();
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
an interrupt that has been assigned a priority above
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
|
function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
|
from interrupts that have been assigned a priority at or below
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Numerically low interrupt priority numbers represent logically high
|
||||||
|
interrupt priorities, therefore the priority of the interrupt must
|
||||||
|
be set to a value equal to or numerically *higher* than
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Interrupts that use the FreeRTOS API must not be left at their
|
||||||
|
default priority of zero as that is the highest possible priority,
|
||||||
|
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||||
|
and therefore also guaranteed to be invalid.
|
||||||
|
|
||||||
|
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||||
|
interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
The following links provide detailed information:
|
||||||
|
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||||
|
http://www.freertos.org/FAQHelp.html */
|
||||||
|
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||||
|
that define each interrupt's priority to be split between bits that
|
||||||
|
define the interrupt's pre-emption priority bits and bits that define
|
||||||
|
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||||
|
to be pre-emption priority bits. The following assertion will fail if
|
||||||
|
this is not the case (if some bits represent a sub-priority).
|
||||||
|
|
||||||
|
If the application only uses CMSIS libraries for interrupt
|
||||||
|
configuration then the correct setting can be achieved on all Cortex-M
|
||||||
|
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
scheduler. Note however that some vendor specific peripheral libraries
|
||||||
|
assume a non-zero priority group setting, in which cases using a value
|
||||||
|
of zero will result in unpredicable behaviour. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName )
|
||||||
|
{
|
||||||
|
/* This function will be called if a task overflows its stack, if
|
||||||
|
configCHECK_FOR_STACK_OVERFLOW != 0. It might be that the function
|
||||||
|
parameters have been corrupted, depending on the severity of the stack
|
||||||
|
overflow. When this is the case pxCurrentTCB can be inspected in the
|
||||||
|
debugger to find the offending task. */
|
||||||
|
printf("\n\r[%s] STACK OVERFLOW - TaskName(%s)\n\r", __FUNCTION__, pcTaskName);
|
||||||
|
for( ;; );
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,186 @@
|
||||||
|
/*
|
||||||
|
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||||
|
All rights reserved
|
||||||
|
|
||||||
|
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* FreeRTOS provides completely free yet professionally developed, *
|
||||||
|
* robust, strictly quality controlled, supported, and cross *
|
||||||
|
* platform software that has become a de facto standard. *
|
||||||
|
* *
|
||||||
|
* Help yourself get started quickly and support the FreeRTOS *
|
||||||
|
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||||
|
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||||
|
* *
|
||||||
|
* Thank you! *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
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 from the following
|
||||||
|
link: http://www.freertos.org/a00114.html
|
||||||
|
|
||||||
|
1 tab == 4 spaces!
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* Having a problem? Start by reading the FAQ "My application does *
|
||||||
|
* not run, what could be wrong?" *
|
||||||
|
* *
|
||||||
|
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||||
|
license and Real Time Engineers Ltd. contact details.
|
||||||
|
|
||||||
|
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.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||||
|
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||||
|
licenses offer ticketed support, indemnification and 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 PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE uint32_t
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
#if( configUSE_16_BIT_TICKS == 1 )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#else
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specifics. */
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler utilities. */
|
||||||
|
extern void vPortYield( void );
|
||||||
|
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||||
|
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||||
|
#define portYIELD() vPortYield()
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||||
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Critical section management. */
|
||||||
|
extern uint32_t ulPortSetInterruptMask( void );
|
||||||
|
extern void vPortClearInterruptMask( uint32_t ulNewMask );
|
||||||
|
extern void vPortEnterCritical( void );
|
||||||
|
extern void vPortExitCritical( void );
|
||||||
|
|
||||||
|
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||||
|
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
|
||||||
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Tickless idle/low power functionality. */
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Port specific optimisations. */
|
||||||
|
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||||
|
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||||
|
|
||||||
|
/* Check the configuration. */
|
||||||
|
#if 0//( configMAX_PRIORITIES > 32 )
|
||||||
|
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Store/clear the ready priorities in a bit map. */
|
||||||
|
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||||
|
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
|
||||||
|
|
||||||
|
#endif /* taskRECORD_READY_PRIORITY */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||||
|
not necessary for to use this port. They are defined so the common demo files
|
||||||
|
(which build with all the ports) will build. */
|
||||||
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef configASSERT
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* portNOP() is not required by this port. */
|
||||||
|
#define portNOP()
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
|
|
||||||
|
|
@ -39,7 +39,6 @@ typedef enum _ADC_DBG_LVL_ {
|
||||||
VERI_ADC_LVL = 0x04,
|
VERI_ADC_LVL = 0x04,
|
||||||
}ADC_DBG_LVL,*PADC_DBG_LVL;
|
}ADC_DBG_LVL,*PADC_DBG_LVL;
|
||||||
|
|
||||||
#if CONFIG_DEBUG_LOG > 0
|
|
||||||
#ifdef CONFIG_DEBUG_LOG_ADC_HAL
|
#ifdef CONFIG_DEBUG_LOG_ADC_HAL
|
||||||
|
|
||||||
#define DBG_8195A_ADC(...) do{ \
|
#define DBG_8195A_ADC(...) do{ \
|
||||||
|
|
@ -58,7 +57,6 @@ typedef enum _ADC_DBG_LVL_ {
|
||||||
#define DBG_8195A_ADC(...)
|
#define DBG_8195A_ADC(...)
|
||||||
#define DBG_8195A_ADC_LVL(...)
|
#define DBG_8195A_ADC_LVL(...)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//================ ADC HAL Related Enumeration ==================
|
//================ ADC HAL Related Enumeration ==================
|
||||||
|
|
|
||||||
|
|
@ -146,5 +146,6 @@ VOID HalLogUartAbortIntRecv(HAL_LOG_UART_ADAPTER *pUartAdapter);
|
||||||
HAL_Status HalLogUartRstFIFO(HAL_LOG_UART_ADAPTER *pUartAdapter, u8 RstCtrl);
|
HAL_Status HalLogUartRstFIFO(HAL_LOG_UART_ADAPTER *pUartAdapter, u8 RstCtrl);
|
||||||
VOID HalLogUartEnable(HAL_LOG_UART_ADAPTER *pUartAdapter);
|
VOID HalLogUartEnable(HAL_LOG_UART_ADAPTER *pUartAdapter);
|
||||||
VOID HalLogUartDisable(HAL_LOG_UART_ADAPTER *pUartAdapter);
|
VOID HalLogUartDisable(HAL_LOG_UART_ADAPTER *pUartAdapter);
|
||||||
|
VOID HalLogUartWaitTxFifoEmpty(VOID);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue