root/webserver/example/freeRTOSexample/EnergyMeters/Common/Minimal/QPeek.c

Revision 14, 15.1 kB (checked in by phil, 15 years ago)

added unmodified FreeRTOS package V5.4.1 with only web srv demo source for LPC2368 for CrossWorks?

Line 
1 /*
2         FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd.
3
4         This file is part of the FreeRTOS distribution.
5
6         FreeRTOS is free software; you can redistribute it and/or modify it     under
7         the terms of the GNU General Public License (version 2) as published by the
8         Free Software Foundation and modified by the FreeRTOS exception.
9         **NOTE** The exception to the GPL is included to allow you to distribute a
10         combined work that includes FreeRTOS without being obliged to provide the
11         source code for proprietary components outside of the FreeRTOS kernel. 
12         Alternative commercial license and support terms are also available upon
13         request.  See the licensing section of http://www.FreeRTOS.org for full
14         license details.
15
16         FreeRTOS is distributed in the hope that it will be useful,     but WITHOUT
17         ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18         FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19         more details.
20
21         You should have received a copy of the GNU General Public License along
22         with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59
23         Temple Place, Suite 330, Boston, MA  02111-1307  USA.
24
25
26         ***************************************************************************
27         *                                                                         *
28         * Looking for a quick start?  Then check out the FreeRTOS eBook!          *
29         * See http://www.FreeRTOS.org/Documentation for details                   *
30         *                                                                         *
31         ***************************************************************************
32
33         1 tab == 4 spaces!
34
35         Please ensure to read the configuration and relevant port sections of the
36         online documentation.
37
38         http://www.FreeRTOS.org - Documentation, latest information, license and
39         contact details.
40
41         http://www.SafeRTOS.com - A version that is certified for use in safety
42         critical systems.
43
44         http://www.OpenRTOS.com - Commercial support, development, porting,
45         licensing and training services.
46 */
47
48
49 /*
50  * Tests the behaviour when data is peeked from a queue when there are
51  * multiple tasks blocked on the queue.
52  */
53
54
55 #include <stdlib.h>
56
57 /* Scheduler include files. */
58 #include "FreeRTOS.h"
59 #include "task.h"
60 #include "queue.h"
61 #include "semphr.h"
62
63 /* Demo program include files. */
64 #include "QPeek.h"
65
66 #define qpeekQUEUE_LENGTH               ( 5 )
67 #define qpeekNO_BLOCK                   ( 0 )
68 #define qpeekSHORT_DELAY                ( 10 )
69
70 #define qpeekLOW_PRIORITY                       ( tskIDLE_PRIORITY + 0 )
71 #define qpeekMEDIUM_PRIORITY            ( tskIDLE_PRIORITY + 1 )
72 #define qpeekHIGH_PRIORITY                      ( tskIDLE_PRIORITY + 2 )
73 #define qpeekHIGHEST_PRIORITY           ( tskIDLE_PRIORITY + 3 )
74
75 /*-----------------------------------------------------------*/
76
77 /*
78  * The following three tasks are used to demonstrate the peeking behaviour.
79  * Each task is given a different priority to demonstrate the order in which
80  * tasks are woken as data is peeked from a queue.
81  */
82 static void prvLowPriorityPeekTask( void *pvParameters );
83 static void prvMediumPriorityPeekTask( void *pvParameters );
84 static void prvHighPriorityPeekTask( void *pvParameters );
85 static void prvHighestPriorityPeekTask( void *pvParameters );
86
87 /*-----------------------------------------------------------*/
88
89 /* Flag that will be latched to pdTRUE should any unexpected behaviour be
90 detected in any of the tasks. */
91 static volatile portBASE_TYPE xErrorDetected = pdFALSE;
92
93 /* Counter that is incremented on each cycle of a test.  This is used to
94 detect a stalled task - a test that is no longer running. */
95 static volatile unsigned portLONG ulLoopCounter = 0;
96
97 /* Handles to the test tasks. */
98 xTaskHandle xMediumPriorityTask, xHighPriorityTask, xHighestPriorityTask;
99 /*-----------------------------------------------------------*/
100
101 void vStartQueuePeekTasks( void )
102 {
103 xQueueHandle xQueue;
104
105         /* Create the queue that we are going to use for the test/demo. */
106         xQueue = xQueueCreate( qpeekQUEUE_LENGTH, sizeof( unsigned portLONG ) );
107
108         /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
109         in use.  The queue registry is provided as a means for kernel aware
110         debuggers to locate queues and has no purpose if a kernel aware debugger
111         is not being used.  The call to vQueueAddToRegistry() will be removed
112         by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
113         defined to be less than 1. */
114         vQueueAddToRegistry( xQueue, ( signed portCHAR * ) "QPeek_Test_Queue" );
115
116         /* Create the demo tasks and pass it the queue just created.  We are
117         passing the queue handle by value so it does not matter that it is declared
118         on the stack here. */
119         xTaskCreate( prvLowPriorityPeekTask, ( signed portCHAR * )"PeekL", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekLOW_PRIORITY, NULL );
120         xTaskCreate( prvMediumPriorityPeekTask, ( signed portCHAR * )"PeekM", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekMEDIUM_PRIORITY, &xMediumPriorityTask );
121         xTaskCreate( prvHighPriorityPeekTask, ( signed portCHAR * )"PeekH1", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGH_PRIORITY, &xHighPriorityTask );
122         xTaskCreate( prvHighestPriorityPeekTask, ( signed portCHAR * )"PeekH2", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGHEST_PRIORITY, &xHighestPriorityTask );
123 }
124 /*-----------------------------------------------------------*/
125
126 static void prvHighestPriorityPeekTask( void *pvParameters )
127 {
128 xQueueHandle xQueue = ( xQueueHandle ) pvParameters;
129 unsigned portLONG ulValue;
130
131         #ifdef USE_STDIO
132         {
133                 void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend );
134        
135                 const portCHAR * const pcTaskStartMsg = "Queue peek test started.\r\n";
136
137                 /* Queue a message for printing to say the task has started. */
138                 vPrintDisplayMessage( &pcTaskStartMsg );
139         }
140         #endif
141
142         for( ;; )
143         {
144                 /* Try peeking from the queue.  The queue should be empty so we will
145                 block, allowing the high priority task to execute. */
146                 if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
147                 {
148                         /* We expected to have received something by the time we unblock. */
149                         xErrorDetected = pdTRUE;
150                 }
151
152                 /* When we reach here the high and medium priority tasks should still
153                 be blocked on the queue.  We unblocked because the low priority task
154                 wrote a value to the queue, which we should have peeked.  Peeking the
155                 data (rather than receiving it) will leave the data on the queue, so
156                 the high priority task should then have also been unblocked, but not
157                 yet executed. */
158                 if( ulValue != 0x11223344 )
159                 {
160                         /* We did not receive the expected value. */
161                         xErrorDetected = pdTRUE;
162                 }
163
164                 if( uxQueueMessagesWaiting( xQueue ) != 1 )
165                 {
166                         /* The message should have been left on the queue. */
167                         xErrorDetected = pdTRUE;
168                 }
169
170                 /* Now we are going to actually receive the data, so when the high
171                 priority task runs it will find the queue empty and return to the
172                 blocked state. */
173                 ulValue = 0;
174                 if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
175                 {
176                         /* We expected to receive the value. */
177                         xErrorDetected = pdTRUE;
178                 }
179
180                 if( ulValue != 0x11223344 )
181                 {
182                         /* We did not receive the expected value - which should have been
183                         the same value as was peeked. */
184                         xErrorDetected = pdTRUE;
185                 }
186
187                 /* Now we will block again as the queue is once more empty.  The low
188                 priority task can then execute again. */
189                 if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
190                 {
191                         /* We expected to have received something by the time we unblock. */
192                         xErrorDetected = pdTRUE;
193                 }
194
195                 /* When we get here the low priority task should have again written to the
196                 queue. */
197                 if( ulValue != 0x01234567 )
198                 {
199                         /* We did not receive the expected value. */
200                         xErrorDetected = pdTRUE;
201                 }
202
203                 if( uxQueueMessagesWaiting( xQueue ) != 1 )
204                 {
205                         /* The message should have been left on the queue. */
206                         xErrorDetected = pdTRUE;
207                 }
208
209                 /* We only peeked the data, so suspending ourselves now should enable
210                 the high priority task to also peek the data.  The high priority task
211                 will have been unblocked when we peeked the data as we left the data
212                 in the queue. */
213                 vTaskSuspend( NULL );
214
215
216
217                 /* This time we are going to do the same as the above test, but the
218                 high priority task is going to receive the data, rather than peek it.
219                 This means that the medium priority task should never peek the value. */
220                 if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
221                 {
222                         xErrorDetected = pdTRUE;
223                 }
224
225                 if( ulValue != 0xaabbaabb )
226                 {
227                         xErrorDetected = pdTRUE;
228                 }
229
230                 vTaskSuspend( NULL );           
231         }
232 }
233 /*-----------------------------------------------------------*/
234
235 static void prvHighPriorityPeekTask( void *pvParameters )
236 {
237 xQueueHandle xQueue = ( xQueueHandle ) pvParameters;
238 unsigned portLONG ulValue;
239
240         for( ;; )
241         {
242                 /* Try peeking from the queue.  The queue should be empty so we will
243                 block, allowing the medium priority task to execute.  Both the high
244                 and highest priority tasks will then be blocked on the queue. */
245                 if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
246                 {
247                         /* We expected to have received something by the time we unblock. */
248                         xErrorDetected = pdTRUE;
249                 }
250
251                 /* When we get here the highest priority task should have peeked the data
252                 (unblocking this task) then suspended (allowing this task to also peek
253                 the data). */
254                 if( ulValue != 0x01234567 )
255                 {
256                         /* We did not receive the expected value. */
257                         xErrorDetected = pdTRUE;
258                 }
259
260                 if( uxQueueMessagesWaiting( xQueue ) != 1 )
261                 {
262                         /* The message should have been left on the queue. */
263                         xErrorDetected = pdTRUE;
264                 }
265
266                 /* We only peeked the data, so suspending ourselves now should enable
267                 the medium priority task to also peek the data.  The medium priority task
268                 will have been unblocked when we peeked the data as we left the data
269                 in the queue. */
270                 vTaskSuspend( NULL );
271
272
273                 /* This time we are going actually receive the value, so the medium
274                 priority task will never peek the data - we removed it from the queue. */
275                 if( xQueueReceive( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
276                 {
277                         xErrorDetected = pdTRUE;
278                 }
279
280                 if( ulValue != 0xaabbaabb )
281                 {
282                         xErrorDetected = pdTRUE;
283                 }
284
285                 vTaskSuspend( NULL );                           
286         }
287 }
288 /*-----------------------------------------------------------*/
289
290 static void prvMediumPriorityPeekTask( void *pvParameters )
291 {
292 xQueueHandle xQueue = ( xQueueHandle ) pvParameters;
293 unsigned portLONG ulValue;
294
295         for( ;; )
296         {
297                 /* Try peeking from the queue.  The queue should be empty so we will
298                 block, allowing the low priority task to execute.  The highest, high
299                 and medium priority tasks will then all be blocked on the queue. */
300                 if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
301                 {
302                         /* We expected to have received something by the time we unblock. */
303                         xErrorDetected = pdTRUE;
304                 }
305
306                 /* When we get here the high priority task should have peeked the data
307                 (unblocking this task) then suspended (allowing this task to also peek
308                 the data). */
309                 if( ulValue != 0x01234567 )
310                 {
311                         /* We did not receive the expected value. */
312                         xErrorDetected = pdTRUE;
313                 }
314
315                 if( uxQueueMessagesWaiting( xQueue ) != 1 )
316                 {
317                         /* The message should have been left on the queue. */
318                         xErrorDetected = pdTRUE;
319                 }
320
321                 /* Just so we know the test is still running. */
322                 ulLoopCounter++;
323
324                 /* Now we can suspend ourselves so the low priority task can execute
325                 again. */
326                 vTaskSuspend( NULL );
327         }
328 }
329 /*-----------------------------------------------------------*/
330
331 static void prvLowPriorityPeekTask( void *pvParameters )
332 {
333 xQueueHandle xQueue = ( xQueueHandle ) pvParameters;
334 unsigned portLONG ulValue;
335
336         for( ;; )
337         {
338                 /* Write some data to the queue.  This should unblock the highest
339                 priority task that is waiting to peek data from the queue. */
340                 ulValue = 0x11223344;
341                 if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
342                 {
343                         /* We were expecting the queue to be empty so we should not of
344                         had a problem writing to the queue. */
345                         xErrorDetected = pdTRUE;
346                 }
347
348                 /* By the time we get here the data should have been removed from
349                 the queue. */
350                 if( uxQueueMessagesWaiting( xQueue ) != 0 )
351                 {
352                         xErrorDetected = pdTRUE;
353                 }
354
355                 /* Write another value to the queue, again waking the highest priority
356                 task that is blocked on the queue. */
357                 ulValue = 0x01234567;
358                 if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
359                 {
360                         /* We were expecting the queue to be empty so we should not of
361                         had a problem writing to the queue. */
362                         xErrorDetected = pdTRUE;
363                 }
364
365                 /* All the other tasks should now have successfully peeked the data.
366                 The data is still in the queue so we should be able to receive it. */
367                 ulValue = 0;
368                 if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
369                 {
370                         /* We expected to receive the data. */
371                         xErrorDetected = pdTRUE;
372                 }
373
374                 if( ulValue != 0x01234567 )
375                 {
376                         /* We did not receive the expected value. */
377                 }
378                
379                 /* Lets just delay a while as this is an intensive test as we don't
380                 want to starve other tests of processing time. */
381                 vTaskDelay( qpeekSHORT_DELAY );
382
383                 /* Unsuspend the other tasks so we can repeat the test - this time
384                 however not all the other tasks will peek the data as the high
385                 priority task is actually going to remove it from the queue.  Send
386                 to front is used just to be different.  As the queue is empty it
387                 makes no difference to the result. */
388                 vTaskResume( xMediumPriorityTask );
389                 vTaskResume( xHighPriorityTask );
390                 vTaskResume( xHighestPriorityTask );
391
392                 ulValue = 0xaabbaabb;
393                 if( xQueueSendToFront( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
394                 {
395                         /* We were expecting the queue to be empty so we should not of
396                         had a problem writing to the queue. */
397                         xErrorDetected = pdTRUE;
398                 }
399
400                 /* This time we should find that the queue is empty.  The high priority
401                 task actually removed the data rather than just peeking it. */
402                 if( xQueuePeek( xQueue, &ulValue, qpeekNO_BLOCK ) != errQUEUE_EMPTY )
403                 {
404                         /* We expected to receive the data. */
405                         xErrorDetected = pdTRUE;
406                 }
407
408                 /* Unsuspend the highest and high priority tasks so we can go back
409                 and repeat the whole thing.  The medium priority task should not be
410                 suspended as it was not able to peek the data in this last case. */
411                 vTaskResume( xHighPriorityTask );
412                 vTaskResume( xHighestPriorityTask );           
413
414                 /* Lets just delay a while as this is an intensive test as we don't
415                 want to starve other tests of processing time. */
416                 vTaskDelay( qpeekSHORT_DELAY );
417         }
418 }
419 /*-----------------------------------------------------------*/
420
421 /* This is called to check that all the created tasks are still running. */
422 portBASE_TYPE xAreQueuePeekTasksStillRunning( void )
423 {
424 static unsigned portLONG ulLastLoopCounter = 0;
425
426         /* If the demo task is still running then we expect the loopcounter to
427         have incremented since this function was last called. */
428         if( ulLastLoopCounter == ulLoopCounter )
429         {
430                 xErrorDetected = pdTRUE;
431         }
432
433         ulLastLoopCounter = ulLoopCounter;
434
435         /* Errors detected in the task itself will have latched xErrorDetected
436         to true. */
437
438         return !xErrorDetected;
439 }
440
Note: See TracBrowser for help on using the browser.