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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [Full/] [comtest.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
 * Creates two tasks that operate on an interrupt driven serial port.  A loopback
56
 * connector should be used so that everything that is transmitted is also received.
57
 * The serial port does not use any flow control.  On a standard 9way 'D' connector
58
 * pins two and three should be connected together.
59
 *
60
 * The first task repeatedly sends a string to a queue, character at a time.  The
61
 * serial port interrupt will empty the queue and transmit the characters.  The
62
 * task blocks for a pseudo random period before resending the string.
63
 *
64
 * The second task blocks on a queue waiting for a character to be received.
65
 * Characters received by the serial port interrupt routine are posted onto the
66
 * queue - unblocking the task making it ready to execute.  If this is then the
67
 * highest priority task ready to run it will run immediately - with a context
68
 * switch occurring at the end of the interrupt service routine.  The task
69
 * receiving characters is spawned with a higher priority than the task
70
 * transmitting the characters.
71
 *
72
 * With the loop back connector in place, one task will transmit a string and the
73
 * other will immediately receive it.  The receiving task knows the string it
74
 * expects to receive so can detect an error.
75
 *
76
 * This also creates a third task.  This is used to test semaphore usage from an
77
 * ISR and does nothing interesting.
78
 *
79
 * \page ComTestC comtest.c
80
 * \ingroup DemoFiles
81
 * <HR>
82
 */
83
 
84
/*
85
Changes from V1.00:
86
 
87
        + The priority of the Rx task has been lowered.  Received characters are
88
          now processed (read from the queue) at the idle priority, allowing low
89
          priority tasks to run evenly at times of a high communications overhead.
90
 
91
Changes from V1.01:
92
 
93
        + The Tx task now waits a pseudo random time between transissions.
94
          Previously a fixed period was used but this was not such a good test as
95
          interrupts fired at regular intervals.
96
 
97
Changes From V1.2.0:
98
 
99
        + Use vSerialPutString() instead of single character puts.
100
        + Only stop the check variable incrementing after two consecutive errors.
101
 
102
Changed from V1.2.5
103
 
104
        + Made the Rx task 2 priorities higher than the Tx task.  Previously it was
105
          only 1.  This is done to tie in better with the other demo application
106
          tasks.
107
 
108
Changes from V2.0.0
109
 
110
        + Delay periods are now specified using variables and constants of
111
          portTickType rather than unsigned long.
112
        + Slight modification to task priorities.
113
 
114
*/
115
 
116
 
117
/* Scheduler include files. */
118
#include <stdlib.h>
119
#include <string.h>
120
#include "FreeRTOS.h"
121
#include "task.h"
122
 
123
/* Demo program include files. */
124
#include "serial.h"
125
#include "comtest.h"
126
#include "print.h"
127
 
128
/* The Tx task will transmit the sequence of characters at a pseudo random
129
interval.  This is the maximum and minimum block time between sends. */
130
#define comTX_MAX_BLOCK_TIME            ( ( portTickType ) 0x15e )
131
#define comTX_MIN_BLOCK_TIME            ( ( portTickType ) 0xc8 )
132
 
133
#define comMAX_CONSECUTIVE_ERRORS       ( 2 )
134
 
135
#define comSTACK_SIZE                           ( ( unsigned short ) 256 )
136
 
137
#define comRX_RELATIVE_PRIORITY         ( 1 )
138
 
139
/* Handle to the com port used by both tasks. */
140
static xComPortHandle xPort;
141
 
142
/* The transmit function as described at the top of the file. */
143
static void vComTxTask( void *pvParameters );
144
 
145
/* The receive function as described at the top of the file. */
146
static void vComRxTask( void *pvParameters );
147
 
148
/* The semaphore test function as described at the top of the file. */
149
static void vSemTestTask( void * pvParameters );
150
 
151
/* The string that is repeatedly transmitted. */
152
const char * const pcMessageToExchange =        "Send this message over and over again to check communications interrupts. "
153
                                                                                                "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
154
 
155
/* Variables that are incremented on each cycle of each task.  These are used to
156
check that both tasks are still executing. */
157
volatile short sTxCount = 0, sRxCount = 0, sSemCount = 0;
158
 
159
/* The handle to the semaphore test task. */
160
static xTaskHandle xSemTestTaskHandle = NULL;
161
 
162
/*-----------------------------------------------------------*/
163
 
164
void vStartComTestTasks( unsigned portBASE_TYPE uxPriority, eCOMPort ePort, eBaud eBaudRate )
165
{
166
const unsigned portBASE_TYPE uxBufferLength = 255;
167
 
168
        /* Initialise the com port then spawn both tasks. */
169
        xPort = xSerialPortInit( ePort, eBaudRate, serNO_PARITY, serBITS_8, serSTOP_1, uxBufferLength );
170
        xTaskCreate( vComTxTask, "COMTx", comSTACK_SIZE, NULL, uxPriority, NULL );
171
        xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority + comRX_RELATIVE_PRIORITY, NULL );
172
        xTaskCreate( vSemTestTask, "ISRSem", comSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xSemTestTaskHandle );
173
}
174
/*-----------------------------------------------------------*/
175
 
176
static void vComTxTask( void *pvParameters )
177
{
178
const char * const pcTaskStartMsg = "COM Tx task started.\r\n";
179
portTickType xTimeToWait;
180
 
181
        /* Stop warnings. */
182
        ( void ) pvParameters;
183
 
184
        /* Queue a message for printing to say the task has started. */
185
        vPrintDisplayMessage( &pcTaskStartMsg );
186
 
187
        for( ;; )
188
        {
189
                /* Send the string to the serial port. */
190
                vSerialPutString( xPort, pcMessageToExchange, strlen( pcMessageToExchange ) );
191
 
192
                /* We have posted all the characters in the string - increment the variable
193
                used to check that this task is still running, then wait before re-sending
194
                the string. */
195
                sTxCount++;
196
 
197
                xTimeToWait = xTaskGetTickCount();
198
 
199
                /* Make sure we don't wait too long... */
200
                xTimeToWait %= comTX_MAX_BLOCK_TIME;
201
 
202
                /* ...but we do want to wait. */
203
                if( xTimeToWait < comTX_MIN_BLOCK_TIME )
204
                {
205
                        xTimeToWait = comTX_MIN_BLOCK_TIME;
206
                }
207
 
208
                vTaskDelay( xTimeToWait );
209
        }
210
} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */
211
/*-----------------------------------------------------------*/
212
 
213
static void vComRxTask( void *pvParameters )
214
{
215
const char * const pcTaskStartMsg = "COM Rx task started.\r\n";
216
const char * const pcTaskErrorMsg = "COM read error\r\n";
217
const char * const pcTaskRestartMsg = "COM resynced\r\n";
218
const char * const pcTaskTimeoutMsg = "COM Rx timed out\r\n";
219
const portTickType xBlockTime = ( portTickType ) 0xffff / portTICK_RATE_MS;
220
const char *pcExpectedChar;
221
portBASE_TYPE xGotChar;
222
char cRxedChar;
223
short sResyncRequired, sConsecutiveErrors, sLatchedError;
224
 
225
        /* Stop warnings. */
226
        ( void ) pvParameters;
227
 
228
        /* Queue a message for printing to say the task has started. */
229
        vPrintDisplayMessage( &pcTaskStartMsg );
230
 
231
        /* The first expected character is the first character in the string. */
232
        pcExpectedChar = pcMessageToExchange;
233
        sResyncRequired = pdFALSE;
234
        sConsecutiveErrors = 0;
235
        sLatchedError = pdFALSE;
236
 
237
        for( ;; )
238
        {
239
                /* Receive a message from the com port interrupt routine.  If a message is
240
                not yet available the call will block the task. */
241
                xGotChar = xSerialGetChar( xPort, &cRxedChar, xBlockTime );
242
                if( xGotChar == pdTRUE )
243
                {
244
                        if( sResyncRequired == pdTRUE )
245
                        {
246
                                /* We got out of sequence and are waiting for the start of the next
247
                                transmission of the string. */
248
                                if( cRxedChar == '\n' )
249
                                {
250
                                        /* This is the end of the message so we can start again - with
251
                                        the first character in the string being the next thing we expect
252
                                        to receive. */
253
                                        pcExpectedChar = pcMessageToExchange;
254
                                        sResyncRequired = pdFALSE;
255
 
256
                                        /* Queue a message for printing to say that we are going to try
257
                                        again. */
258
                                        vPrintDisplayMessage( &pcTaskRestartMsg );
259
 
260
                                        /* Stop incrementing the check variable, if consecutive errors occur. */
261
                                        sConsecutiveErrors++;
262
                                        if( sConsecutiveErrors >= comMAX_CONSECUTIVE_ERRORS )
263
                                        {
264
                                                sLatchedError = pdTRUE;
265
                                        }
266
                                }
267
                        }
268
                        else
269
                        {
270
                                /* We have received a character, but is it the expected character? */
271
                                if( cRxedChar != *pcExpectedChar )
272
                                {
273
                                        /* This was not the expected character so post a message for
274
                                        printing to say that an error has occurred.  We will then wait
275
                                        to resynchronise. */
276
                                        vPrintDisplayMessage( &pcTaskErrorMsg );
277
                                        sResyncRequired = pdTRUE;
278
                                }
279
                                else
280
                                {
281
                                        /* This was the expected character so next time we will expect
282
                                        the next character in the string.  Wrap back to the beginning
283
                                        of the string when the null terminator has been reached. */
284
                                        pcExpectedChar++;
285
                                        if( *pcExpectedChar == '\0' )
286
                                        {
287
                                                pcExpectedChar = pcMessageToExchange;
288
 
289
                                                /* We have got through the entire string without error. */
290
                                                sConsecutiveErrors = 0;
291
                                        }
292
                                }
293
                        }
294
 
295
                        /* Increment the count that is used to check that this task is still
296
                        running.  This is only done if an error has never occurred. */
297
                        if( sLatchedError == pdFALSE )
298
                        {
299
                                sRxCount++;
300
                        }
301
                }
302
                else
303
                {
304
                        vPrintDisplayMessage( &pcTaskTimeoutMsg );
305
                }
306
        }
307
} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */
308
/*-----------------------------------------------------------*/
309
 
310
static void vSemTestTask( void * pvParameters )
311
{
312
const char * const pcTaskStartMsg = "ISR Semaphore test started.\r\n";
313
portBASE_TYPE xError = pdFALSE;
314
 
315
        /* Stop warnings. */
316
        ( void ) pvParameters;
317
 
318
        /* Queue a message for printing to say the task has started. */
319
        vPrintDisplayMessage( &pcTaskStartMsg );
320
 
321
        for( ;; )
322
        {
323
                if( xSerialWaitForSemaphore( xPort ) )
324
                {
325
                        if( xError == pdFALSE )
326
                        {
327
                                sSemCount++;
328
                        }
329
                }
330
                else
331
                {
332
                        xError = pdTRUE;
333
                }
334
        }
335
} /*lint !e715 !e830 !e818 pvParameters not used but function prototype must be standard for task function. */
336
/*-----------------------------------------------------------*/
337
 
338
/* This is called to check that all the created tasks are still running. */
339
portBASE_TYPE xAreComTestTasksStillRunning( void )
340
{
341
static short sLastTxCount = 0, sLastRxCount = 0, sLastSemCount = 0;
342
portBASE_TYPE xReturn;
343
 
344
        /* Not too worried about mutual exclusion on these variables as they are 16
345
        bits and we are only reading them.  We also only care to see if they have
346
        changed or not. */
347
 
348
        if( ( sTxCount == sLastTxCount ) || ( sRxCount == sLastRxCount ) || ( sSemCount == sLastSemCount ) )
349
        {
350
                xReturn = pdFALSE;
351
        }
352
        else
353
        {
354
                xReturn = pdTRUE;
355
        }
356
 
357
        sLastTxCount = sTxCount;
358
        sLastRxCount = sRxCount;
359
        sLastSemCount = sSemCount;
360
 
361
        return xReturn;
362
}
363
/*-----------------------------------------------------------*/
364
 
365
void vComTestUnsuspendTask( void )
366
{
367
        /* The task that is suspended on the semaphore will be referenced from the
368
        Suspended list as it is blocking indefinitely.  This call just checks that
369
        the kernel correctly detects this and does not attempt to unsuspend the
370
        task. */
371
        xTaskResumeFromISR( xSemTestTaskHandle );
372
}

powered by: WebSVN 2.1.0

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