]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_LM3S316_IAR/commstest.c
e9e0b08f2d31eff5efd87fe99b686173fdc46742
[freertos] / FreeRTOS / Demo / CORTEX_LM3S316_IAR / commstest.c
1 /*\r
2     FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 /*\r
71  * The comms test Rx and Tx task and co-routine.  See the comments at the top\r
72  * of main.c for full information.\r
73  */\r
74 \r
75 \r
76 /* Scheduler include files. */\r
77 #include "FreeRTOS.h"\r
78 #include "task.h"\r
79 #include "queue.h"\r
80 #include "croutine.h"\r
81 \r
82 /* Demo application include files. */\r
83 #include "partest.h"\r
84 \r
85 /* Library include files. */\r
86 #include "DriverLib.h"\r
87 \r
88 /* The LED's toggled by the various tasks. */\r
89 #define commsFAIL_LED                   ( 7 )\r
90 #define commsRX_LED                     ( 6 )\r
91 #define commsTX_LED                     ( 5 )\r
92 \r
93 /* The length of the queue used to pass received characters to the Comms Rx\r
94 task. */\r
95 #define commsRX_QUEUE_LEN                       ( 5 )\r
96 \r
97 /* The baud rate used by the UART comms tasks/co-routine. */\r
98 #define commsBAUD_RATE                          ( 57600 )\r
99 \r
100 /* FIFO setting for the UART.  The FIFO is not used to create a better test. */\r
101 #define commsFIFO_SET                           ( 0x10 )\r
102 \r
103 /* The string that is transmitted on the UART contains sequentially the\r
104 characters from commsFIRST_TX_CHAR to commsLAST_TX_CHAR. */\r
105 #define commsFIRST_TX_CHAR '0'\r
106 #define commsLAST_TX_CHAR 'z'\r
107 \r
108 /* Just used to walk through the program memory in order that some random data\r
109 can be generated. */\r
110 #define commsTOTAL_PROGRAM_MEMORY ( ( unsigned long * ) ( 8 * 1024 ) )\r
111 #define commsFIRST_PROGRAM_BYTES ( ( unsigned long * ) 4 )\r
112 \r
113 /* The time between transmissions of the string on UART 0.   This is pseudo\r
114 random in order to generate a bit or randomness to when the interrupts occur.*/\r
115 #define commsMIN_TX_DELAY                       ( 40 / portTICK_PERIOD_MS )\r
116 #define commsMAX_TX_DELAY                       ( ( TickType_t ) 0x7f )\r
117 #define commsOFFSET_TIME                        ( ( TickType_t ) 3 )\r
118 \r
119 /* The time the Comms Rx task should wait to receive a character.  This should\r
120 be slightly longer than the time between transmissions.  If we do not receive\r
121 a character after this time then there must be an error in the transmission or\r
122 the timing of the transmission. */\r
123 #define commsRX_DELAY                   ( commsMAX_TX_DELAY + 20 )\r
124 \r
125 \r
126 static unsigned portBASE_TYPE uxCommsErrorStatus = pdPASS;\r
127 \r
128 /* The queue used to pass characters out of the ISR. */\r
129 static QueueHandle_t xCommsQueue;\r
130 \r
131 /* The next character to transmit. */\r
132 static char cNextChar;\r
133 \r
134 /*-----------------------------------------------------------*/\r
135 \r
136 void vSerialInit( void )\r
137 {\r
138         /* Create the queue used to communicate between the UART ISR and the Comms\r
139         Rx task. */\r
140         xCommsQueue = xQueueCreate( commsRX_QUEUE_LEN, sizeof( char ) );\r
141 \r
142         /* Enable the UART.  GPIOA has already been initialised. */\r
143         SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);\r
144 \r
145         /* Set GPIO A0 and A1 as peripheral function.  They are used to output the\r
146         UART signals. */\r
147         GPIODirModeSet( GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_DIR_MODE_HW );\r
148 \r
149         /* Configure the UART for 8-N-1 operation. */\r
150         UARTConfigSetExpClk( UART0_BASE, SysCtlClockGet(), commsBAUD_RATE, UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE );\r
151 \r
152         /* We dont want to use the fifo.  This is for test purposes to generate\r
153         as many interrupts as possible. */\r
154         HWREG( UART0_BASE + UART_O_LCR_H ) &= ~commsFIFO_SET;\r
155 \r
156         /* Enable both Rx and Tx interrupts. */\r
157         HWREG( UART0_BASE + UART_O_IM ) |= ( UART_INT_TX | UART_INT_RX );\r
158         IntPrioritySet( INT_UART0, configKERNEL_INTERRUPT_PRIORITY );\r
159         IntEnable( INT_UART0 );\r
160 }\r
161 /*-----------------------------------------------------------*/\r
162 \r
163 void vSerialTxCoRoutine( CoRoutineHandle_t xHandle, unsigned portBASE_TYPE uxIndex )\r
164 {\r
165 TickType_t xDelayPeriod;\r
166 static unsigned long *pulRandomBytes = commsFIRST_PROGRAM_BYTES;\r
167 \r
168         /* Co-routine MUST start with a call to crSTART. */\r
169         crSTART( xHandle );\r
170 \r
171         for(;;)\r
172     {   \r
173                 /* Was the previously transmitted string received correctly? */\r
174                 if( uxCommsErrorStatus != pdPASS )\r
175                 {\r
176                         /* An error was encountered so set the error LED. */\r
177                         vParTestSetLED( commsFAIL_LED, pdTRUE );\r
178                 }\r
179 \r
180                 /* The next character to Tx is the first in the string. */\r
181                 cNextChar = commsFIRST_TX_CHAR;\r
182 \r
183                 UARTIntDisable( UART0_BASE, UART_INT_TX );\r
184                 {\r
185                         /* Send the first character. */\r
186                         if( !( HWREG( UART0_BASE + UART_O_FR ) & UART_FR_TXFF ) )\r
187                         {\r
188                                 HWREG( UART0_BASE + UART_O_DR ) = cNextChar;\r
189                         }\r
190 \r
191                         /* Move the variable to the char to Tx on so the ISR transmits\r
192                         the next character in the string once this one has completed. */\r
193                         cNextChar++;\r
194                 }\r
195                 UARTIntEnable(UART0_BASE, UART_INT_TX);\r
196 \r
197                 /* Toggle the LED to show a new string is being transmitted. */\r
198         vParTestToggleLED( commsTX_LED );\r
199 \r
200                 /* Delay before we start the string off again.  A pseudo-random delay\r
201                 is used as this will provide a better test. */\r
202                 xDelayPeriod = xTaskGetTickCount() + ( *pulRandomBytes );\r
203 \r
204                 pulRandomBytes++;\r
205                 if( pulRandomBytes > commsTOTAL_PROGRAM_MEMORY )\r
206                 {\r
207                         pulRandomBytes = commsFIRST_PROGRAM_BYTES;\r
208                 }\r
209 \r
210                 /* Make sure we don't wait too long... */\r
211                 xDelayPeriod &= commsMAX_TX_DELAY;\r
212 \r
213                 /* ...but we do want to wait. */\r
214                 if( xDelayPeriod < commsMIN_TX_DELAY )\r
215                 {\r
216                         xDelayPeriod = commsMIN_TX_DELAY;\r
217                 }\r
218 \r
219                 /* Block for the random(ish) time. */\r
220                 crDELAY( xHandle, xDelayPeriod );\r
221     }\r
222 \r
223         /* Co-routine MUST end with a call to crEND. */\r
224         crEND();\r
225 }\r
226 /*-----------------------------------------------------------*/\r
227 \r
228 void vUART_ISR( void )\r
229 {\r
230 unsigned long ulStatus;\r
231 char cRxedChar;\r
232 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
233 \r
234         /* What caused the interrupt. */\r
235         ulStatus = UARTIntStatus( UART0_BASE, pdTRUE );\r
236 \r
237         /* Clear the interrupt. */\r
238         UARTIntClear( UART0_BASE, ulStatus );\r
239 \r
240         /* Was an Rx interrpt pending? */\r
241         if( ulStatus & UART_INT_RX )\r
242         {\r
243                 if( ( HWREG(UART0_BASE + UART_O_FR ) & UART_FR_RXFF ) )\r
244                 {\r
245                         /* Get the char from the buffer and post it onto the queue of\r
246                         Rxed chars.  Posting the character should wake the task that is\r
247                         blocked on the queue waiting for characters. */\r
248                         cRxedChar = ( char ) HWREG( UART0_BASE + UART_O_DR );\r
249                         xQueueSendFromISR( xCommsQueue, &cRxedChar, &xHigherPriorityTaskWoken );\r
250                 }               \r
251         }\r
252 \r
253         /* Was a Tx interrupt pending? */\r
254         if( ulStatus & UART_INT_TX )\r
255         {\r
256                 /* Send the next character in the string.  We are not using the FIFO. */\r
257                 if( cNextChar <= commsLAST_TX_CHAR )\r
258                 {\r
259                         if( !( HWREG( UART0_BASE + UART_O_FR ) & UART_FR_TXFF ) )\r
260                         {\r
261                                 HWREG( UART0_BASE + UART_O_DR ) = cNextChar;\r
262                         }\r
263                         cNextChar++;\r
264                 }\r
265         }\r
266         \r
267         /* If a task was woken by the character being received then we force\r
268         a context switch to occur in case the task is of higher priority than\r
269         the currently executing task (i.e. the task that this interrupt\r
270         interrupted.) */\r
271         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
272 }\r
273 /*-----------------------------------------------------------*/\r
274 \r
275 void vCommsRxTask( void * pvParameters )\r
276 {\r
277 static char cRxedChar, cExpectedChar;\r
278 \r
279         /* Set the char we expect to receive to the start of the string. */\r
280         cExpectedChar = commsFIRST_TX_CHAR;\r
281 \r
282         for( ;; )\r
283         {\r
284                 /* Wait for a character to be received. */\r
285                 xQueueReceive( xCommsQueue, ( void * ) &cRxedChar, commsRX_DELAY );\r
286 \r
287                 /* Was the character recived (if any) the expected character. */\r
288                 if( cRxedChar != cExpectedChar )\r
289                 {\r
290                         /* Got an unexpected character.  This can sometimes occur when\r
291                         reseting the system using the debugger leaving characters already\r
292                         in the UART regsters. */\r
293                         uxCommsErrorStatus = pdFAIL;\r
294 \r
295                         /* Resync by waiting for the end of the current string. */\r
296                         while( cRxedChar != commsLAST_TX_CHAR )\r
297                         {\r
298                                 while( !xQueueReceive( xCommsQueue, ( void * ) &cRxedChar, portMAX_DELAY ) );\r
299                         }\r
300 \r
301                         /* The next expected character is the start of the string again. */\r
302                         cExpectedChar = commsFIRST_TX_CHAR;\r
303                 }\r
304                 else\r
305                 {\r
306                         if( cExpectedChar == commsLAST_TX_CHAR )\r
307                         {\r
308                                 /* We have reached the end of the string - we now expect to\r
309                                 receive the first character in the string again.   The LED is\r
310                                 toggled to indicate that the entire string was received without\r
311                                 error. */\r
312                                 vParTestToggleLED( commsRX_LED );\r
313                                 cExpectedChar = commsFIRST_TX_CHAR;\r
314                         }\r
315                         else\r
316                         {\r
317                                 /* We got the expected character, we now expect to receive the\r
318                                 next character in the string. */\r
319                                 cExpectedChar++;\r
320                         }\r
321                 }\r
322         }\r
323 }\r
324 /*-----------------------------------------------------------*/\r
325 \r
326 unsigned portBASE_TYPE uxGetCommsStatus( void )\r
327 {\r
328         return uxCommsErrorStatus;\r
329 }\r