OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [Minimal/] [blocktim.c] - Blame information for rev 609

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 606 jeremybenn
/*
2
    FreeRTOS V6.1.1 - Copyright (C) 2011 Real Time Engineers Ltd.
3
 
4
    ***************************************************************************
5
    *                                                                         *
6
    * If you are:                                                             *
7
    *                                                                         *
8
    *    + New to FreeRTOS,                                                   *
9
    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
10
    *    + Looking for basic training,                                        *
11
    *    + Wanting to improve your FreeRTOS skills and productivity           *
12
    *                                                                         *
13
    * then take a look at the FreeRTOS books - available as PDF or paperback  *
14
    *                                                                         *
15
    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
16
    *                  http://www.FreeRTOS.org/Documentation                  *
17
    *                                                                         *
18
    * A pdf reference manual is also available.  Both are usually delivered   *
19
    * to your inbox within 20 minutes to two hours when purchased between 8am *
20
    * and 8pm GMT (although please allow up to 24 hours in case of            *
21
    * exceptional circumstances).  Thank you for your support!                *
22
    *                                                                         *
23
    ***************************************************************************
24
 
25
    This file is part of the FreeRTOS distribution.
26
 
27
    FreeRTOS is free software; you can redistribute it and/or modify it under
28
    the terms of the GNU General Public License (version 2) as published by the
29
    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
30
    ***NOTE*** The exception to the GPL is included to allow you to distribute
31
    a combined work that includes FreeRTOS without being obliged to provide the
32
    source code for proprietary components outside of the FreeRTOS kernel.
33
    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
34
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
36
    more details. You should have received a copy of the GNU General Public
37
    License and the FreeRTOS license exception along with FreeRTOS; if not it
38
    can be viewed here: http://www.freertos.org/a00114.html and also obtained
39
    by writing to Richard Barry, contact details for whom are available on the
40
    FreeRTOS WEB site.
41
 
42
    1 tab == 4 spaces!
43
 
44
    http://www.FreeRTOS.org - Documentation, latest information, license and
45
    contact details.
46
 
47
    http://www.SafeRTOS.com - A version that is certified for use in safety
48
    critical systems.
49
 
50
    http://www.OpenRTOS.com - Commercial support, development, porting,
51
    licensing and training services.
52
*/
53
 
54
/*
55
 * This file contains some test scenarios that ensure tasks do not exit queue
56
 * send or receive functions prematurely.  A description of the tests is
57
 * included within the code.
58
 */
59
 
60
/* Kernel includes. */
61
#include "FreeRTOS.h"
62
#include "task.h"
63
#include "queue.h"
64
 
65
/* Demo includes. */
66
#include "blocktim.h"
67
 
68
/* Task priorities.  Allow these to be overridden. */
69
#ifndef bktPRIMARY_PRIORITY
70
        #define bktPRIMARY_PRIORITY                     ( 3 )
71
#endif
72
 
73
#ifndef bktSECONDARY_PRIORITY
74
        #define bktSECONDARY_PRIORITY           ( 2 )
75
#endif
76
 
77
/* Task behaviour. */
78
#define bktQUEUE_LENGTH                         ( 5 )
79
#define bktSHORT_WAIT                           ( ( ( portTickType ) 20 ) / portTICK_RATE_MS )
80
#define bktPRIMARY_BLOCK_TIME           ( 10 )
81
#define bktALLOWABLE_MARGIN                     ( 15 )
82
#define bktTIME_TO_BLOCK                        ( 175 )
83
#define bktDONT_BLOCK                           ( ( portTickType ) 0 )
84
#define bktRUN_INDICATOR                        ( ( unsigned portBASE_TYPE ) 0x55 )
85
 
86
/* The queue on which the tasks block. */
87
static xQueueHandle xTestQueue;
88
 
89
/* Handle to the secondary task is required by the primary task for calls
90
to vTaskSuspend/Resume(). */
91
static xTaskHandle xSecondary;
92
 
93
/* Used to ensure that tasks are still executing without error. */
94
static volatile portBASE_TYPE xPrimaryCycles = 0, xSecondaryCycles = 0;
95
static volatile portBASE_TYPE xErrorOccurred = pdFALSE;
96
 
97
/* Provides a simple mechanism for the primary task to know when the
98
secondary task has executed. */
99
static volatile unsigned portBASE_TYPE xRunIndicator;
100
 
101
/* The two test tasks.  Their behaviour is commented within the files. */
102
static void vPrimaryBlockTimeTestTask( void *pvParameters );
103
static void vSecondaryBlockTimeTestTask( void *pvParameters );
104
 
105
/*-----------------------------------------------------------*/
106
 
107
void vCreateBlockTimeTasks( void )
108
{
109
        /* Create the queue on which the two tasks block. */
110
    xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( portBASE_TYPE ) );
111
 
112
        /* vQueueAddToRegistry() adds the queue to the queue registry, if one is
113
        in use.  The queue registry is provided as a means for kernel aware
114
        debuggers to locate queues and has no purpose if a kernel aware debugger
115
        is not being used.  The call to vQueueAddToRegistry() will be removed
116
        by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
117
        defined to be less than 1. */
118
        vQueueAddToRegistry( xTestQueue, ( signed char * ) "Block_Time_Queue" );
119
 
120
        /* Create the two test tasks. */
121
        xTaskCreate( vPrimaryBlockTimeTestTask, ( signed char * )"BTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );
122
        xTaskCreate( vSecondaryBlockTimeTestTask, ( signed char * )"BTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary );
123
}
124
/*-----------------------------------------------------------*/
125
 
126
static void vPrimaryBlockTimeTestTask( void *pvParameters )
127
{
128
portBASE_TYPE xItem, xData;
129
portTickType xTimeWhenBlocking;
130
portTickType xTimeToBlock, xBlockedTime;
131
 
132
        ( void ) pvParameters;
133
 
134
        for( ;; )
135
        {
136
                /*********************************************************************
137
        Test 1
138
 
139
        Simple block time wakeup test on queue receives. */
140
                for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
141
                {
142
                        /* The queue is empty. Attempt to read from the queue using a block
143
                        time.  When we wake, ensure the delta in time is as expected. */
144
                        xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;
145
 
146
                        xTimeWhenBlocking = xTaskGetTickCount();
147
 
148
                        /* We should unblock after xTimeToBlock having not received
149
                        anything on the queue. */
150
                        if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )
151
                        {
152
                                xErrorOccurred = pdTRUE;
153
                        }
154
 
155
                        /* How long were we blocked for? */
156
                        xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
157
 
158
                        if( xBlockedTime < xTimeToBlock )
159
                        {
160
                                /* Should not have blocked for less than we requested. */
161
                                xErrorOccurred = pdTRUE;
162
                        }
163
 
164
                        if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
165
                        {
166
                                /* Should not have blocked for longer than we requested,
167
                                although we would not necessarily run as soon as we were
168
                                unblocked so a margin is allowed. */
169
                                xErrorOccurred = pdTRUE;
170
                        }
171
                }
172
 
173
                /*********************************************************************
174
        Test 2
175
 
176
        Simple block time wakeup test on queue sends.
177
 
178
                First fill the queue.  It should be empty so all sends should pass. */
179
                for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
180
                {
181
                        if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
182
                        {
183
                                xErrorOccurred = pdTRUE;
184
                        }
185
 
186
                        #if configUSE_PREEMPTION == 0
187
                                taskYIELD();
188
                        #endif
189
                }
190
 
191
                for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
192
                {
193
                        /* The queue is full. Attempt to write to the queue using a block
194
                        time.  When we wake, ensure the delta in time is as expected. */
195
                        xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;
196
 
197
                        xTimeWhenBlocking = xTaskGetTickCount();
198
 
199
                        /* We should unblock after xTimeToBlock having not received
200
                        anything on the queue. */
201
                        if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )
202
                        {
203
                                xErrorOccurred = pdTRUE;
204
                        }
205
 
206
                        /* How long were we blocked for? */
207
                        xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
208
 
209
                        if( xBlockedTime < xTimeToBlock )
210
                        {
211
                                /* Should not have blocked for less than we requested. */
212
                                xErrorOccurred = pdTRUE;
213
                        }
214
 
215
                        if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
216
                        {
217
                                /* Should not have blocked for longer than we requested,
218
                                although we would not necessarily run as soon as we were
219
                                unblocked so a margin is allowed. */
220
                                xErrorOccurred = pdTRUE;
221
                        }
222
                }
223
 
224
                /*********************************************************************
225
        Test 3
226
 
227
                Wake the other task, it will block attempting to post to the queue.
228
                When we read from the queue the other task will wake, but before it
229
                can run we will post to the queue again.  When the other task runs it
230
                will find the queue still full, even though it was woken.  It should
231
                recognise that its block time has not expired and return to block for
232
                the remains of its block time.
233
 
234
                Wake the other task so it blocks attempting to post to the already
235
                full queue. */
236
                xRunIndicator = 0;
237
                vTaskResume( xSecondary );
238
 
239
                /* We need to wait a little to ensure the other task executes. */
240
                while( xRunIndicator != bktRUN_INDICATOR )
241
                {
242
                        /* The other task has not yet executed. */
243
                        vTaskDelay( bktSHORT_WAIT );
244
                }
245
                /* Make sure the other task is blocked on the queue. */
246
                vTaskDelay( bktSHORT_WAIT );
247
                xRunIndicator = 0;
248
 
249
                for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
250
                {
251
                        /* Now when we make space on the queue the other task should wake
252
                        but not execute as this task has higher priority. */
253
                        if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
254
                        {
255
                                xErrorOccurred = pdTRUE;
256
                        }
257
 
258
                        /* Now fill the queue again before the other task gets a chance to
259
                        execute.  If the other task had executed we would find the queue
260
                        full ourselves, and the other task have set xRunIndicator. */
261
                        if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
262
                        {
263
                                xErrorOccurred = pdTRUE;
264
                        }
265
 
266
                        if( xRunIndicator == bktRUN_INDICATOR )
267
                        {
268
                                /* The other task should not have executed. */
269
                                xErrorOccurred = pdTRUE;
270
                        }
271
 
272
                        /* Raise the priority of the other task so it executes and blocks
273
                        on the queue again. */
274
                        vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
275
 
276
                        /* The other task should now have re-blocked without exiting the
277
                        queue function. */
278
                        if( xRunIndicator == bktRUN_INDICATOR )
279
                        {
280
                                /* The other task should not have executed outside of the
281
                                queue function. */
282
                                xErrorOccurred = pdTRUE;
283
                        }
284
 
285
                        /* Set the priority back down. */
286
                        vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
287
                }
288
 
289
                /* Let the other task timeout.  When it unblockes it will check that it
290
                unblocked at the correct time, then suspend itself. */
291
                while( xRunIndicator != bktRUN_INDICATOR )
292
                {
293
                        vTaskDelay( bktSHORT_WAIT );
294
                }
295
                vTaskDelay( bktSHORT_WAIT );
296
                xRunIndicator = 0;
297
 
298
 
299
                /*********************************************************************
300
        Test 4
301
 
302
                As per test 3 - but with the send and receive the other way around.
303
                The other task blocks attempting to read from the queue.
304
 
305
                Empty the queue.  We should find that it is full. */
306
                for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
307
                {
308
                        if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
309
                        {
310
                                xErrorOccurred = pdTRUE;
311
                        }
312
                }
313
 
314
                /* Wake the other task so it blocks attempting to read from  the
315
                already empty queue. */
316
                vTaskResume( xSecondary );
317
 
318
                /* We need to wait a little to ensure the other task executes. */
319
                while( xRunIndicator != bktRUN_INDICATOR )
320
                {
321
                        vTaskDelay( bktSHORT_WAIT );
322
                }
323
                vTaskDelay( bktSHORT_WAIT );
324
                xRunIndicator = 0;
325
 
326
                for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
327
                {
328
                        /* Now when we place an item on the queue the other task should
329
                        wake but not execute as this task has higher priority. */
330
                        if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
331
                        {
332
                                xErrorOccurred = pdTRUE;
333
                        }
334
 
335
                        /* Now empty the queue again before the other task gets a chance to
336
                        execute.  If the other task had executed we would find the queue
337
                        empty ourselves, and the other task would be suspended. */
338
                        if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
339
                        {
340
                                xErrorOccurred = pdTRUE;
341
                        }
342
 
343
                        if( xRunIndicator == bktRUN_INDICATOR )
344
                        {
345
                                /* The other task should not have executed. */
346
                                xErrorOccurred = pdTRUE;
347
                        }
348
 
349
                        /* Raise the priority of the other task so it executes and blocks
350
                        on the queue again. */
351
                        vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
352
 
353
                        /* The other task should now have re-blocked without exiting the
354
                        queue function. */
355
                        if( xRunIndicator == bktRUN_INDICATOR )
356
                        {
357
                                /* The other task should not have executed outside of the
358
                                queue function. */
359
                                xErrorOccurred = pdTRUE;
360
                        }
361
                        vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
362
                }
363
 
364
                /* Let the other task timeout.  When it unblockes it will check that it
365
                unblocked at the correct time, then suspend itself. */
366
                while( xRunIndicator != bktRUN_INDICATOR )
367
                {
368
                        vTaskDelay( bktSHORT_WAIT );
369
                }
370
                vTaskDelay( bktSHORT_WAIT );
371
 
372
                xPrimaryCycles++;
373
        }
374
}
375
/*-----------------------------------------------------------*/
376
 
377
static void vSecondaryBlockTimeTestTask( void *pvParameters )
378
{
379
portTickType xTimeWhenBlocking, xBlockedTime;
380
portBASE_TYPE xData;
381
 
382
        ( void ) pvParameters;
383
 
384
        for( ;; )
385
        {
386
                /*********************************************************************
387
        Test 1 and 2
388
 
389
                This task does does not participate in these tests. */
390
                vTaskSuspend( NULL );
391
 
392
                /*********************************************************************
393
        Test 3
394
 
395
                The first thing we do is attempt to read from the queue.  It should be
396
                full so we block.  Note the time before we block so we can check the
397
                wake time is as per that expected. */
398
                xTimeWhenBlocking = xTaskGetTickCount();
399
 
400
                /* We should unblock after bktTIME_TO_BLOCK having not sent
401
                anything to the queue. */
402
                xData = 0;
403
                xRunIndicator = bktRUN_INDICATOR;
404
                if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )
405
                {
406
                        xErrorOccurred = pdTRUE;
407
                }
408
 
409
                /* How long were we inside the send function? */
410
                xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
411
 
412
                /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
413
                if( xBlockedTime < bktTIME_TO_BLOCK )
414
                {
415
                        xErrorOccurred = pdTRUE;
416
                }
417
 
418
                /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
419
                either.  A margin is permitted as we would not necessarily run as
420
                soon as we unblocked. */
421
                if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
422
                {
423
                        xErrorOccurred = pdTRUE;
424
                }
425
 
426
                /* Suspend ready for test 3. */
427
                xRunIndicator = bktRUN_INDICATOR;
428
                vTaskSuspend( NULL );
429
 
430
                /*********************************************************************
431
        Test 4
432
 
433
                As per test three, but with the send and receive reversed. */
434
                xTimeWhenBlocking = xTaskGetTickCount();
435
 
436
                /* We should unblock after bktTIME_TO_BLOCK having not received
437
                anything on the queue. */
438
                xRunIndicator = bktRUN_INDICATOR;
439
                if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )
440
                {
441
                        xErrorOccurred = pdTRUE;
442
                }
443
 
444
                xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
445
 
446
                /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
447
                if( xBlockedTime < bktTIME_TO_BLOCK )
448
                {
449
                        xErrorOccurred = pdTRUE;
450
                }
451
 
452
                /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
453
                either.  A margin is permitted as we would not necessarily run as soon
454
                as we unblocked. */
455
                if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
456
                {
457
                        xErrorOccurred = pdTRUE;
458
                }
459
 
460
                xRunIndicator = bktRUN_INDICATOR;
461
 
462
                xSecondaryCycles++;
463
        }
464
}
465
/*-----------------------------------------------------------*/
466
 
467
portBASE_TYPE xAreBlockTimeTestTasksStillRunning( void )
468
{
469
static portBASE_TYPE xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;
470
portBASE_TYPE xReturn = pdPASS;
471
 
472
        /* Have both tasks performed at least one cycle since this function was
473
        last called? */
474
        if( xPrimaryCycles == xLastPrimaryCycleCount )
475
        {
476
                xReturn = pdFAIL;
477
        }
478
 
479
        if( xSecondaryCycles == xLastSecondaryCycleCount )
480
        {
481
                xReturn = pdFAIL;
482
        }
483
 
484
        if( xErrorOccurred == pdTRUE )
485
        {
486
                xReturn = pdFAIL;
487
        }
488
 
489
        xLastSecondaryCycleCount = xSecondaryCycles;
490
        xLastPrimaryCycleCount = xPrimaryCycles;
491
 
492
        return xReturn;
493
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.