]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC/Examples/USB_CDC/CDCCommandConsole.c
Update LPC18xx FreeRTOS+UDP demo to use LPCOpen USB and Ethernet drivers.
[freertos] / FreeRTOS-Plus / Demo / FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC / Examples / USB_CDC / CDCCommandConsole.c
1 /*\r
2     FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.\r
3 \r
4 \r
5     ***************************************************************************\r
6      *                                                                       *\r
7      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
8      *    Complete, revised, and edited pdf reference manuals are also       *\r
9      *    available.                                                         *\r
10      *                                                                       *\r
11      *    Purchasing FreeRTOS documentation will not only help you, by       *\r
12      *    ensuring you get running as quickly as possible and with an        *\r
13      *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
14      *    the FreeRTOS project to continue with its mission of providing     *\r
15      *    professional grade, cross platform, de facto standard solutions    *\r
16      *    for microcontrollers - completely free of charge!                  *\r
17      *                                                                       *\r
18      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
19      *                                                                       *\r
20      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
21      *                                                                       *\r
22     ***************************************************************************\r
23 \r
24 \r
25     This file is part of the FreeRTOS distribution.\r
26 \r
27     FreeRTOS is free software; you can redistribute it and/or modify it under\r
28     the terms of the GNU General Public License (version 2) as published by the\r
29     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
30     >>>NOTE<<< The modification to the GPL is included to allow you to\r
31     distribute a combined work that includes FreeRTOS without being obliged to\r
32     provide the source code for proprietary components outside of the FreeRTOS\r
33     kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
34     WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
35     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
36     more details. You should have received a copy of the GNU General Public\r
37     License and the FreeRTOS license exception along with FreeRTOS; if not it\r
38     can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
39     by writing to Richard Barry, contact details for whom are available on the\r
40     FreeRTOS WEB site.\r
41 \r
42     1 tab == 4 spaces!\r
43 \r
44     http://www.FreeRTOS.org - Documentation, latest information, license and\r
45     contact details.\r
46 \r
47     http://www.SafeRTOS.com - A version that is certified for use in safety\r
48     critical systems.\r
49 \r
50     http://www.OpenRTOS.com - Commercial support, development, porting,\r
51     licensing and training services.\r
52 */\r
53 \r
54 /*\r
55  * NOTE:  This file uses a third party USB CDC driver.\r
56  */\r
57 \r
58 /* Standard includes. */\r
59 #include "string.h"\r
60 #include "stdio.h"\r
61 #include "limits.h"\r
62 \r
63 /* FreeRTOS includes. */\r
64 #include "FreeRTOS.h"\r
65 #include "task.h"\r
66 #include "semphr.h"\r
67 \r
68 /* LPCUSB includes. */\r
69 #include "USB.h"\r
70 #include "Descriptors.h"\r
71 \r
72 /* Example includes. */\r
73 #include "FreeRTOS_CLI.h"\r
74 #include "CDCCommandConsole.h"\r
75 \r
76 /* Dimensions the buffer into which input characters are placed. */\r
77 #define cmdMAX_INPUT_SIZE               50\r
78 \r
79 /* The maximum time in ticks to wait for the CDC access mutex. */\r
80 #define cmdMAX_MUTEX_WAIT               ( 200 / portTICK_RATE_MS )\r
81 \r
82 /*-----------------------------------------------------------*/\r
83 \r
84 /*\r
85  * The task that implements the command console processing.\r
86  */\r
87 static void prvCDCCommandConsoleTask( void *pvParameters );\r
88 \r
89 /*\r
90  * Some USB processing is deferred from LPCUSB interrupt service routines to\r
91  * LPCUSB functions that are called from a FreeRTOS task.\r
92  * prvNotifyTaskofUSBEvent() is used from interrupt event callback functions.\r
93  * It uses a semaphore to unblock the handling task whenever task level\r
94  * processing might be required.\r
95  */\r
96 static void prvNotifyTaskOfUSBEvent( void );\r
97 \r
98 /*-----------------------------------------------------------*/\r
99 \r
100 /* 'Given' by the CDC interrupt to unblock the command console task when CDC\r
101 events are potentially waiting to be processed. */\r
102 static xSemaphoreHandle xCDCEventSemaphore = NULL;\r
103 \r
104 /* Used to guard access to the CDC output, which is used by more than one\r
105 task. */\r
106 static xSemaphoreHandle xCDCMutex = NULL;\r
107 \r
108 /* Const messages output by the command console. */\r
109 static const char * const pcWelcomeMessage = "FreeRTOS command server.\r\nType Help to view a list of registered commands.\r\n\r\n>";\r
110 static const char * const pcEndOfOutputMessage = "\r\n[Press ENTER to execute the previous command again]\r\n>";\r
111 static const char * const pcNewLine = "\r\n";\r
112 \r
113 /* LPCUSBlib CDC Class driver interface configuration and state information. */\r
114 static USB_ClassInfo_CDC_Device_t xVirtualCOMPort = {\r
115         .Config = {\r
116                 .ControlInterfaceNumber         = 0,\r
117 \r
118                 .DataINEndpointNumber           = CDC_TX_EPNUM,\r
119                 .DataINEndpointSize             = CDC_TXRX_EPSIZE,\r
120                 .DataINEndpointDoubleBank       = false,\r
121 \r
122                 .DataOUTEndpointNumber          = CDC_RX_EPNUM,\r
123                 .DataOUTEndpointSize            = CDC_TXRX_EPSIZE,\r
124                 .DataOUTEndpointDoubleBank      = false,\r
125 \r
126                 .NotificationEndpointNumber     = CDC_NOTIFICATION_EPNUM,\r
127                 .NotificationEndpointSize       = CDC_NOTIFICATION_EPSIZE,\r
128                 .NotificationEndpointDoubleBank = false,\r
129                 .PortNumber                             = 0,\r
130         },\r
131 };\r
132 \r
133 /*-----------------------------------------------------------*/\r
134 \r
135 void vCDCCommandConsoleStart( uint16_t usStackSize, unsigned portBASE_TYPE uxPriority )\r
136 {\r
137         /* Create the semaphores and mutexes used by the CDC to task interface. */\r
138         xCDCMutex = xSemaphoreCreateMutex();\r
139         xCDCEventSemaphore = xSemaphoreCreateCounting( UINT_MAX, 0 );\r
140         configASSERT( xCDCMutex );\r
141         configASSERT( xCDCEventSemaphore );\r
142 \r
143         /* Add the semaphore and mutex to the queue registry for viewing in the\r
144         kernel aware state viewer. */\r
145         vQueueAddToRegistry( xCDCMutex, ( signed char * ) "CDCMu" );\r
146         vQueueAddToRegistry( xCDCEventSemaphore, ( signed char * ) "CDCDat" );\r
147 \r
148         /* Create that task that handles the console itself. */\r
149         xTaskCreate(    prvCDCCommandConsoleTask,                       /* The task that implements the command console. */\r
150                                         ( const int8_t * const ) "CDCCmd",      /* Text name assigned to the task.  This is just to assist debugging.  The kernel does not use this name itself. */\r
151                                         usStackSize,                                            /* The size of the stack allocated to the task. */\r
152                                         NULL,                                                           /* The parameter is not used, so NULL is passed. */\r
153                                         uxPriority,                                                     /* The priority allocated to the task. */\r
154                                         NULL );                                                         /* A handle is not required, so just pass NULL. */\r
155 }\r
156 /*-----------------------------------------------------------*/\r
157 \r
158 static void prvCDCCommandConsoleTask( void *pvParameters )\r
159 {\r
160 char cRxedChar, *pcOutputString;\r
161 static char cInputString[ cmdMAX_INPUT_SIZE ], cLastInputString[ cmdMAX_INPUT_SIZE ];\r
162 portBASE_TYPE xReturned, xInputIndex = 0;\r
163 \r
164         /* Just to avoid warnings about unused parameters. */\r
165         ( void ) pvParameters;\r
166 \r
167         /* Initialise LPCUSB CDC driver. */\r
168         USB_Init( xVirtualCOMPort.Config.PortNumber, USB_MODE_Device );\r
169 \r
170         /* Obtain the address of the output buffer.  Note there is no mutual\r
171         exclusion on this buffer as it is assumed only one command console\r
172         interface will be used at any one time. */\r
173         pcOutputString = ( char * ) FreeRTOS_CLIGetOutputBuffer();\r
174 \r
175         /* Send the welcome message.  This probably won't be seen as the console\r
176         will not have been connected yet (the console cannot be connected until the\r
177         virtual COM port has enumerated). */\r
178         CDC_Device_SendData( &xVirtualCOMPort, pcWelcomeMessage, strlen( ( const char * ) pcWelcomeMessage ) );\r
179 \r
180         for( ;; )\r
181         {\r
182                 /* Wait for new events to originate from the LPCUSB interrupts. */\r
183 //              xSemaphoreTake( xCDCEventSemaphore, 100 );\r
184 \r
185                 /* LPCUSB function to process events latched by the USB interrupts. */\r
186                 CDC_Device_USBTask( &xVirtualCOMPort );\r
187                 USB_USBTask( xVirtualCOMPort.Config.PortNumber, USB_MODE_Device );\r
188 \r
189                 /* Ensure no other tasks are using the COM port. */\r
190                 if( xSemaphoreTake( xCDCMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )\r
191                 {\r
192                         /* Have any characters been received? */\r
193                         if( CDC_Device_BytesReceived( &xVirtualCOMPort ) != 0 )\r
194                         {\r
195                                 /* Only interested in reading one character at a time. */\r
196                                 cRxedChar = CDC_Device_ReceiveByte( &xVirtualCOMPort );\r
197 \r
198                                 /* Echo the character back. */\r
199                                 CDC_Device_SendData( &xVirtualCOMPort, &cRxedChar, sizeof( uint8_t ) );\r
200 \r
201                                 /* Was it an end of line character? */\r
202                                 if( cRxedChar == '\n' || cRxedChar == '\r' )\r
203                                 {\r
204                                         /* Just to space the output from the input. */\r
205                                         CDC_Device_SendData( &xVirtualCOMPort, pcNewLine, strlen( ( const char * ) pcNewLine ) );\r
206 \r
207                                         /* See if the command is empty, indicating that the last\r
208                                         command is to be executed again. */\r
209                                         if( xInputIndex == 0 )\r
210                                         {\r
211                                                 /* Copy the last command back into the input string. */\r
212                                                 strcpy( ( char * ) cInputString, ( char * ) cLastInputString );\r
213                                         }\r
214 \r
215                                         /* Pass the received command to the command interpreter.\r
216                                         The     command interpreter is called repeatedly until it\r
217                                         returns pdFALSE (indicating there is no more output) as it\r
218                                         might generate more than one string. */\r
219                                         do\r
220                                         {\r
221                                                 /* Get the next output string from the command\r
222                                                 interpreter. */\r
223                                                 xReturned = FreeRTOS_CLIProcessCommand( ( const int8_t * const ) cInputString, ( int8_t * ) pcOutputString, configCOMMAND_INT_MAX_OUTPUT_SIZE );\r
224 \r
225                                                 /* Write the generated string to the CDC. */\r
226                                                 CDC_Device_SendData( &xVirtualCOMPort, pcOutputString, strlen( ( const char * ) pcOutputString ) );\r
227 \r
228                                         } while( xReturned != pdFALSE );\r
229 \r
230                                         /* All the strings generated by the input command have been\r
231                                         sent.  Clear the input string ready to receive the next\r
232                                         command.  Remember the command that was just processed first\r
233                                         in case it is to be     processed again. */\r
234                                         strcpy( ( char * ) cLastInputString, ( char * ) cInputString );\r
235                                         xInputIndex = 0;\r
236                                         memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );\r
237 \r
238                                         CDC_Device_SendData( &xVirtualCOMPort, pcEndOfOutputMessage, strlen( ( const char * ) pcEndOfOutputMessage ) );\r
239                                 }\r
240                                 else\r
241                                 {\r
242                                         if( cRxedChar == '\r' )\r
243                                         {\r
244                                                 /* Ignore the character. */\r
245                                         }\r
246                                         else if( cRxedChar == '\b' )\r
247                                         {\r
248                                                 /* Backspace was pressed.  Erase the last character in\r
249                                                 thestring - if any. */\r
250                                                 if( xInputIndex > 0 )\r
251                                                 {\r
252                                                         xInputIndex--;\r
253                                                         cInputString[ xInputIndex ] = '\0';\r
254                                                 }\r
255                                         }\r
256                                         else\r
257                                         {\r
258                                                 /* A character was entered.  Add it to the string\r
259                                                 entered so far.  When a \n is entered the complete\r
260                                                 string will be passed to the command interpreter. */\r
261                                                 if( ( cRxedChar >= ' ' ) && ( cRxedChar <= '~' ) )\r
262                                                 {\r
263                                                         if( xInputIndex < cmdMAX_INPUT_SIZE )\r
264                                                         {\r
265                                                                 cInputString[ xInputIndex ] = cRxedChar;\r
266                                                                 xInputIndex++;\r
267                                                         }\r
268                                                 }\r
269                                         }\r
270                                 }\r
271                         }\r
272 \r
273                         /* Must ensure to give the mutex back. */\r
274                         xSemaphoreGive( xCDCMutex );\r
275                 }\r
276         }\r
277 }\r
278 /*-----------------------------------------------------------*/\r
279 \r
280 void vOutputString( const uint8_t * const pucMessage )\r
281 {\r
282         if( xSemaphoreTake( xCDCMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )\r
283         {\r
284                 CDC_Device_SendData( &xVirtualCOMPort, ( const char * const ) pucMessage, strlen( ( const char * ) pucMessage ) );\r
285                 xSemaphoreGive( xCDCMutex );\r
286         }\r
287 }\r
288 /*-----------------------------------------------------------*/\r
289 \r
290 static void prvNotifyTaskOfUSBEvent( void )\r
291 {\r
292 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
293 \r
294         /* 'Give' the semaphore that signals the arrival of new data to the command\r
295         console task. */\r
296         configASSERT( xCDCEventSemaphore );\r
297         xSemaphoreGiveFromISR( xCDCEventSemaphore, &xHigherPriorityTaskWoken );\r
298         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
299 }\r
300 /*-----------------------------------------------------------*/\r
301 \r
302 /* Standard LPCUSB event handler. */\r
303 void EVENT_USB_Device_ConfigurationChanged( void )\r
304 {\r
305         CDC_Device_ConfigureEndpoints( &xVirtualCOMPort );\r
306         prvNotifyTaskOfUSBEvent();\r
307 }\r
308 /*-----------------------------------------------------------*/\r
309 \r
310 /* Standard LPCUSB event handler. */\r
311 void EVENT_USB_Device_ControlRequest( void )\r
312 {\r
313         CDC_Device_ProcessControlRequest( &xVirtualCOMPort );\r
314         prvNotifyTaskOfUSBEvent();\r
315 }\r
316 /*-----------------------------------------------------------*/\r
317 \r
318 /* Standard LPCUSB event handler. */\r
319 void EVENT_USB_Device_Connect(void)\r
320 {\r
321         prvNotifyTaskOfUSBEvent();\r
322 }\r
323 /*-----------------------------------------------------------*/\r
324 \r
325 /* Standard LPCUSB event handler. */\r
326 void EVENT_USB_Device_Disconnect(void)\r
327 {\r
328         prvNotifyTaskOfUSBEvent();\r
329 }\r
330 /*-----------------------------------------------------------*/\r
331 \r
332 /* Standard LPCUSB event handler. */\r
333 void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t *const CDCInterfaceInfo)\r
334 {\r
335         prvNotifyTaskOfUSBEvent();\r
336 }\r
337 /*-----------------------------------------------------------*/\r
338 \r
339 /* Standard LPCUSB event handler. */\r
340 void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t *const CDCInterfaceInfo)\r
341 {\r
342         prvNotifyTaskOfUSBEvent();\r
343 }\r
344 \r