]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC/Examples/USB_CDC/CDCCommandConsole.c
3eabbd22dc01660a63c98ba291052897f24c3650
[freertos] / FreeRTOS-Plus / Demo / FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC / Examples / USB_CDC / CDCCommandConsole.c
1 /*\r
2     FreeRTOS V8.1.0 - Copyright (C) 2014 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     ***************************************************************************\r
8      *                                                                       *\r
9      *    FreeRTOS provides completely free yet professionally developed,    *\r
10      *    robust, strictly quality controlled, supported, and cross          *\r
11      *    platform software that has become a de facto standard.             *\r
12      *                                                                       *\r
13      *    Help yourself get started quickly and support the FreeRTOS         *\r
14      *    project by purchasing a FreeRTOS tutorial book, reference          *\r
15      *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
16      *                                                                       *\r
17      *    Thank you!                                                         *\r
18      *                                                                       *\r
19     ***************************************************************************\r
20 \r
21     This file is part of the FreeRTOS distribution.\r
22 \r
23     FreeRTOS is free software; you can redistribute it and/or modify it under\r
24     the terms of the GNU General Public License (version 2) as published by the\r
25     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
26 \r
27     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
28     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
29     >>!   obliged to provide the source code for proprietary components     !<<\r
30     >>!   outside of the FreeRTOS kernel.                                   !<<\r
31 \r
32     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
33     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
34     FOR A PARTICULAR PURPOSE.  Full license text is available from the following\r
35     link: http://www.freertos.org/a00114.html\r
36 \r
37     1 tab == 4 spaces!\r
38 \r
39     ***************************************************************************\r
40      *                                                                       *\r
41      *    Having a problem?  Start by reading the FAQ "My application does   *\r
42      *    not run, what could be wrong?"                                     *\r
43      *                                                                       *\r
44      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
45      *                                                                       *\r
46     ***************************************************************************\r
47 \r
48     http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
49     license and Real Time Engineers Ltd. contact details.\r
50 \r
51     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
52     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
53     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
54 \r
55     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
56     Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
57     licenses offer ticketed support, indemnification and middleware.\r
58 \r
59     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
60     engineered and independently SIL3 certified version for use in safety and\r
61     mission critical applications that require provable dependability.\r
62 \r
63     1 tab == 4 spaces!\r
64 */\r
65 \r
66 /*\r
67  * NOTE:  This file uses a third party USB CDC driver.\r
68  */\r
69 \r
70 /* Standard includes. */\r
71 #include "string.h"\r
72 #include "stdio.h"\r
73 \r
74 /* FreeRTOS includes. */\r
75 #include "FreeRTOS.h"\r
76 #include "task.h"\r
77 #include "semphr.h"\r
78 \r
79 /* Driver includes. */\r
80 #include "usbhw.h"\r
81 #include "cdcuser.h"\r
82 #include "usbcfg.h"\r
83 #include "usbuser.h"\r
84 \r
85 /* Example includes. */\r
86 #include "FreeRTOS_CLI.h"\r
87 #include "CDCCommandConsole.h"\r
88 \r
89 /* Dimensions the buffer into which input characters are placed. */\r
90 #define cmdMAX_INPUT_SIZE               50\r
91 \r
92 /* The maximum time in ticks to wait for the CDC access mutex. */\r
93 #define cmdMAX_MUTEX_WAIT               ( 200 / portTICK_RATE_MS )\r
94 \r
95 /*-----------------------------------------------------------*/\r
96 \r
97 /*\r
98  * The task that implements the command console processing.\r
99  */\r
100 static void prvCDCCommandConsoleTask( void *pvParameters );\r
101 \r
102 /*\r
103  * Obtain a character from the CDC input.  The calling task will be held in the\r
104  * Blocked state (so other tasks can execute) until a character is avilable.\r
105  */\r
106 char cGetCDCChar( void );\r
107 \r
108 /*\r
109  * Initialise the third party virtual comport files driver\r
110  */\r
111 static void prvSetupUSBDrivers( void );\r
112 \r
113 /*-----------------------------------------------------------*/\r
114 \r
115 /* 'Given' by the CDC interrupt to unblock the receiving task when new data\r
116 is available. */\r
117 static xSemaphoreHandle xNewDataSemaphore = NULL;\r
118 \r
119 /* Used to guard access to the CDC output, which is used by more than one\r
120 task. */\r
121 static xSemaphoreHandle xCDCMutex = NULL;\r
122 \r
123 /* Const messages output by the command console. */\r
124 static const char * const pcWelcomeMessage = "FreeRTOS command server.\r\nType Help to view a list of registered commands.\r\n\r\n>";\r
125 static const char * const pcEndOfOutputMessage = "\r\n[Press ENTER to execute the previous command again]\r\n>";\r
126 static const char * const pcNewLine = "\r\n";\r
127 \r
128 /*-----------------------------------------------------------*/\r
129 \r
130 void vCDCCommandConsoleStart( uint16_t usStackSize, UBaseType_t uxPriority )\r
131 {\r
132         /* Create the semaphores and mutexes used by the CDC to task interface. */\r
133         xCDCMutex = xSemaphoreCreateMutex();\r
134         vSemaphoreCreateBinary( xNewDataSemaphore );\r
135         configASSERT( xCDCMutex );\r
136         configASSERT( xNewDataSemaphore );\r
137 \r
138         /* Add the semaphore and mutex to the queue registry for viewing in the\r
139         kernel aware state viewer. */\r
140         vQueueAddToRegistry( xCDCMutex, "CDCMu" );\r
141         vQueueAddToRegistry( xNewDataSemaphore, "CDCDat" );\r
142 \r
143         /* Create that task that handles the console itself. */\r
144         xTaskCreate(    prvCDCCommandConsoleTask,       /* The task that implements the command console. */\r
145                                         "CDCCmd",                                       /* Text name assigned to the task.  This is just to assist debugging.  The kernel does not use this name itself. */\r
146                                         usStackSize,                            /* The size of the stack allocated to the task. */\r
147                                         NULL,                                           /* The parameter is not used, so NULL is passed. */\r
148                                         uxPriority,                                     /* The priority allocated to the task. */\r
149                                         NULL );                                         /* A handle is not required, so just pass NULL. */\r
150 }\r
151 /*-----------------------------------------------------------*/\r
152 \r
153 static void prvCDCCommandConsoleTask( void *pvParameters )\r
154 {\r
155 char cRxedChar;\r
156 uint8_t ucInputIndex = 0;\r
157 char *pcOutputString;\r
158 static char cInputString[ cmdMAX_INPUT_SIZE ], cLastInputString[ cmdMAX_INPUT_SIZE ];\r
159 BaseType_t xReturned;\r
160 \r
161         ( void ) pvParameters;\r
162 \r
163         /* Obtain the address of the output buffer.  Note there is no mutual\r
164         exclusion on this buffer as it is assumed only one command console\r
165         interface will be used at any one time. */\r
166         pcOutputString = FreeRTOS_CLIGetOutputBuffer();\r
167 \r
168         /* Initialise the virtual com port (CDC) interface. */\r
169         prvSetupUSBDrivers();\r
170 \r
171         /* Send the welcome message.  This probably won't be seen as the console\r
172         will not have been connected yet. */\r
173         USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcWelcomeMessage, strlen( pcWelcomeMessage ) );\r
174 \r
175         for( ;; )\r
176         {\r
177                 /* No characters received yet for the current input string. */\r
178                 cRxedChar = 0;\r
179 \r
180                 /* Only interested in reading one character at a time. */\r
181                 cRxedChar = cGetCDCChar();\r
182 \r
183                 if( xSemaphoreTake( xCDCMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )\r
184                 {\r
185                         /* Echo the character back. */\r
186                         USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) &cRxedChar, sizeof( uint8_t ) );\r
187 \r
188                         /* Was it the end of the line? */\r
189                         if( cRxedChar == '\n' || cRxedChar == '\r' )\r
190                         {\r
191                                 /* Just to space the output from the input. */\r
192                                 USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcNewLine, strlen( pcNewLine ) );\r
193 \r
194                                 /* See if the command is empty, indicating that the last command is\r
195                                 to be executed again. */\r
196                                 if( ucInputIndex == 0 )\r
197                                 {\r
198                                         /* Copy the last command back into the input string. */\r
199                                         strcpy( cInputString, cLastInputString );\r
200                                 }\r
201 \r
202                                 /* Pass the received command to the command interpreter.  The\r
203                                 command interpreter is called repeatedly until it returns pdFALSE\r
204                                 (indicating there is no more output) as it might generate more than\r
205                                 one string. */\r
206                                 do\r
207                                 {\r
208                                         /* Get the next output string from the command interpreter. */\r
209                                         xReturned = FreeRTOS_CLIProcessCommand( cInputString, pcOutputString, configCOMMAND_INT_MAX_OUTPUT_SIZE );\r
210 \r
211                                         /* Write the generated string to the CDC. */\r
212                                         USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcOutputString, strlen( pcOutputString ) );\r
213                                         vTaskDelay( 1 );\r
214 \r
215                                 } while( xReturned != pdFALSE );\r
216 \r
217                                 /* All the strings generated by the input command have been sent.\r
218                                 Clear the input string ready to receive the next command.  Remember\r
219                                 the command that was just processed first in case it is to be\r
220                                 processed again. */\r
221                                 strcpy( cLastInputString, cInputString );\r
222                                 ucInputIndex = 0;\r
223                                 memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );\r
224 \r
225                                 USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcEndOfOutputMessage, strlen( pcEndOfOutputMessage ) );\r
226                         }\r
227                         else\r
228                         {\r
229                                 if( cRxedChar == '\r' )\r
230                                 {\r
231                                         /* Ignore the character. */\r
232                                 }\r
233                                 else if( cRxedChar == '\b' )\r
234                                 {\r
235                                         /* Backspace was pressed.  Erase the last character in the\r
236                                         string - if any. */\r
237                                         if( ucInputIndex > 0 )\r
238                                         {\r
239                                                 ucInputIndex--;\r
240                                                 cInputString[ ucInputIndex ] = '\0';\r
241                                         }\r
242                                 }\r
243                                 else\r
244                                 {\r
245                                         /* A character was entered.  Add it to the string\r
246                                         entered so far.  When a \n is entered the complete\r
247                                         string will be passed to the command interpreter. */\r
248                                         if( ( cRxedChar >= ' ' ) && ( cRxedChar <= '~' ) )\r
249                                         {\r
250                                                 if( ucInputIndex < cmdMAX_INPUT_SIZE )\r
251                                                 {\r
252                                                         cInputString[ ucInputIndex ] = cRxedChar;\r
253                                                         ucInputIndex++;\r
254                                                 }\r
255                                         }\r
256                                 }\r
257                         }\r
258 \r
259                         /* Must ensure to give the mutex back. */\r
260                         xSemaphoreGive( xCDCMutex );\r
261                 }\r
262         }\r
263 }\r
264 /*-----------------------------------------------------------*/\r
265 \r
266 void vOutputString( const char * const pcMessage )\r
267 {\r
268         if( xSemaphoreTake( xCDCMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )\r
269         {\r
270                 USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcMessage, strlen( pcMessage ) );\r
271                 xSemaphoreGive( xCDCMutex );\r
272         }\r
273 }\r
274 /*-----------------------------------------------------------*/\r
275 \r
276 char cGetCDCChar( void )\r
277 {\r
278 int32_t lAvailableBytes, xBytes = 0;\r
279 char cInputChar;\r
280 \r
281         do\r
282         {\r
283                 /* Are there any characters already available? */\r
284                 CDC_OutBufAvailChar( &lAvailableBytes );\r
285                 if( lAvailableBytes > 0 )\r
286                 {\r
287                         if( xSemaphoreTake( xCDCMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )\r
288                         {\r
289                                 /* Attempt to read one character. */\r
290                                 xBytes = 1;\r
291                                 xBytes = CDC_RdOutBuf( &cInputChar, &xBytes );\r
292 \r
293                                 xSemaphoreGive( xCDCMutex );\r
294                         }\r
295                 }\r
296 \r
297                 if( xBytes == 0 )\r
298                 {\r
299                         /* A character was not available.  Wait until signalled by the\r
300                         CDC Rx callback function that new data has arrived. */\r
301                         xSemaphoreTake( xNewDataSemaphore, portMAX_DELAY );\r
302                 }\r
303 \r
304         } while( xBytes == 0 );\r
305 \r
306         return cInputChar;\r
307 }\r
308 /*-----------------------------------------------------------*/\r
309 \r
310 /* Callback function executed by the USB interrupt when new data arrives. */\r
311 void vCDCNewDataNotify( void )\r
312 {\r
313 BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
314 \r
315         configASSERT( xNewDataSemaphore );\r
316 \r
317         /* 'Give' the semaphore that signals the arrival of new data to the command\r
318         console task. */\r
319         xSemaphoreGiveFromISR( xNewDataSemaphore, &xHigherPriorityTaskWoken );\r
320         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
321 }\r
322 /*-----------------------------------------------------------*/\r
323 \r
324 static void prvSetupUSBDrivers( void )\r
325 {\r
326 LPC_USBDRV_INIT_T xUSBCallback;\r
327 \r
328         /* Initialise the callback structure. */\r
329         memset( ( void * ) &xUSBCallback, 0, sizeof( LPC_USBDRV_INIT_T ) );\r
330         xUSBCallback.USB_Reset_Event = USB_Reset_Event;\r
331         xUSBCallback.USB_P_EP[ 0 ] = USB_EndPoint0;\r
332         xUSBCallback.USB_P_EP[ 1 ] = USB_EndPoint1;\r
333         xUSBCallback.USB_P_EP[ 2 ] = USB_EndPoint2;\r
334         xUSBCallback.ep0_maxp = USB_MAX_PACKET0;\r
335 \r
336         /* Initialise then connect the USB. */\r
337         USB_Init( &xUSBCallback );\r
338         USB_Connect( pdTRUE );\r
339 }\r