From a6163888f3c56123b1db313743c6147ba498732c Mon Sep 17 00:00:00 2001 From: Yuval Adam Date: Fri, 8 Aug 2014 14:42:07 +0300 Subject: Add third_party libs --- third_party/FreeRTOS/Demo/Common/Full/dynamic.c | 616 ++++++++++++++++++++++++ 1 file changed, 616 insertions(+) create mode 100644 third_party/FreeRTOS/Demo/Common/Full/dynamic.c (limited to 'third_party/FreeRTOS/Demo/Common/Full/dynamic.c') diff --git a/third_party/FreeRTOS/Demo/Common/Full/dynamic.c b/third_party/FreeRTOS/Demo/Common/Full/dynamic.c new file mode 100644 index 0000000..b9c4b18 --- /dev/null +++ b/third_party/FreeRTOS/Demo/Common/Full/dynamic.c @@ -0,0 +1,616 @@ +/* + FreeRTOS V7.6.0 - Copyright (C) 2013 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 + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + portTickType 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 + +/* 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 ( ( portTickType ) 50 ) +#define priLOOPS ( 5 ) +#define priMAX_COUNT ( ( unsigned long ) 0xff ) +#define priNO_BLOCK ( ( portTickType ) 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 xTaskHandle 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. */ +xQueueHandle 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; +} + + + + -- cgit v1.3.1