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/events.c | 406 +++++++++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 third_party/FreeRTOS/Demo/Common/Full/events.c (limited to 'third_party/FreeRTOS/Demo/Common/Full/events.c') diff --git a/third_party/FreeRTOS/Demo/Common/Full/events.c b/third_party/FreeRTOS/Demo/Common/Full/events.c new file mode 100644 index 0000000..8ff96a9 --- /dev/null +++ b/third_party/FreeRTOS/Demo/Common/Full/events.c @@ -0,0 +1,406 @@ +/* + 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! +*/ + +/** + * 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 +#include +#include + +/* 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 xTaskHandle xCreatedTasks[ evtNUM_TASKS ]; + +/* The single queue onto which the controlling task posts, and the four event +tasks block. */ +static xQueueHandle 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; +} + + -- cgit v1.3.1