root/webserver/example/freeRTOS/Demo/Common/Full/comtest.c

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