2 FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 ***************************************************************************
\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
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
19 ***************************************************************************
\r
21 This file is part of the FreeRTOS distribution.
\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
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
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
39 ***************************************************************************
\r
41 * Having a problem? Start by reading the FAQ "My application does *
\r
42 * not run, what could be wrong?" *
\r
44 * http://www.FreeRTOS.org/FAQHelp.html *
\r
46 ***************************************************************************
\r
48 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
49 license and Real Time Engineers Ltd. contact details.
\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
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
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
67 * NOTE: This file uses a third party USB CDC driver.
\r
70 /* Standard includes. */
\r
74 /* FreeRTOS includes. */
\r
75 #include "FreeRTOS.h"
\r
79 /* Driver includes. */
\r
81 #include "cdcuser.h"
\r
83 #include "usbuser.h"
\r
85 /* Example includes. */
\r
86 #include "FreeRTOS_CLI.h"
\r
87 #include "CDCCommandConsole.h"
\r
89 /* Dimensions the buffer into which input characters are placed. */
\r
90 #define cmdMAX_INPUT_SIZE 50
\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
95 /*-----------------------------------------------------------*/
\r
98 * The task that implements the command console processing.
\r
100 static void prvCDCCommandConsoleTask( void *pvParameters );
\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
106 char cGetCDCChar( void );
\r
109 * Initialise the third party virtual comport files driver
\r
111 static void prvSetupUSBDrivers( void );
\r
113 /*-----------------------------------------------------------*/
\r
115 /* 'Given' by the CDC interrupt to unblock the receiving task when new data
\r
117 static xSemaphoreHandle xNewDataSemaphore = NULL;
\r
119 /* Used to guard access to the CDC output, which is used by more than one
\r
121 static xSemaphoreHandle xCDCMutex = NULL;
\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
128 /*-----------------------------------------------------------*/
\r
130 void vCDCCommandConsoleStart( uint16_t usStackSize, UBaseType_t uxPriority )
\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
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
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
151 /*-----------------------------------------------------------*/
\r
153 static void prvCDCCommandConsoleTask( void *pvParameters )
\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
161 ( void ) pvParameters;
\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
168 /* Initialise the virtual com port (CDC) interface. */
\r
169 prvSetupUSBDrivers();
\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
177 /* No characters received yet for the current input string. */
\r
180 /* Only interested in reading one character at a time. */
\r
181 cRxedChar = cGetCDCChar();
\r
183 if( xSemaphoreTake( xCDCMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )
\r
185 /* Echo the character back. */
\r
186 USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) &cRxedChar, sizeof( uint8_t ) );
\r
188 /* Was it the end of the line? */
\r
189 if( cRxedChar == '\n' || cRxedChar == '\r' )
\r
191 /* Just to space the output from the input. */
\r
192 USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcNewLine, strlen( pcNewLine ) );
\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
198 /* Copy the last command back into the input string. */
\r
199 strcpy( cInputString, cLastInputString );
\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
208 /* Get the next output string from the command interpreter. */
\r
209 xReturned = FreeRTOS_CLIProcessCommand( cInputString, pcOutputString, configCOMMAND_INT_MAX_OUTPUT_SIZE );
\r
211 /* Write the generated string to the CDC. */
\r
212 USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcOutputString, strlen( pcOutputString ) );
\r
215 } while( xReturned != pdFALSE );
\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
223 memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
\r
225 USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcEndOfOutputMessage, strlen( pcEndOfOutputMessage ) );
\r
229 if( cRxedChar == '\r' )
\r
231 /* Ignore the character. */
\r
233 else if( cRxedChar == '\b' )
\r
235 /* Backspace was pressed. Erase the last character in the
\r
236 string - if any. */
\r
237 if( ucInputIndex > 0 )
\r
240 cInputString[ ucInputIndex ] = '\0';
\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
250 if( ucInputIndex < cmdMAX_INPUT_SIZE )
\r
252 cInputString[ ucInputIndex ] = cRxedChar;
\r
259 /* Must ensure to give the mutex back. */
\r
260 xSemaphoreGive( xCDCMutex );
\r
264 /*-----------------------------------------------------------*/
\r
266 void vOutputString( const char * const pcMessage )
\r
268 if( xSemaphoreTake( xCDCMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )
\r
270 USB_WriteEP( CDC_DEP_IN, ( uint8_t * ) pcMessage, strlen( pcMessage ) );
\r
271 xSemaphoreGive( xCDCMutex );
\r
274 /*-----------------------------------------------------------*/
\r
276 char cGetCDCChar( void )
\r
278 int32_t lAvailableBytes, xBytes = 0;
\r
283 /* Are there any characters already available? */
\r
284 CDC_OutBufAvailChar( &lAvailableBytes );
\r
285 if( lAvailableBytes > 0 )
\r
287 if( xSemaphoreTake( xCDCMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )
\r
289 /* Attempt to read one character. */
\r
291 xBytes = CDC_RdOutBuf( &cInputChar, &xBytes );
\r
293 xSemaphoreGive( xCDCMutex );
\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
304 } while( xBytes == 0 );
\r
308 /*-----------------------------------------------------------*/
\r
310 /* Callback function executed by the USB interrupt when new data arrives. */
\r
311 void vCDCNewDataNotify( void )
\r
313 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
315 configASSERT( xNewDataSemaphore );
\r
317 /* 'Give' the semaphore that signals the arrival of new data to the command
\r
319 xSemaphoreGiveFromISR( xNewDataSemaphore, &xHigherPriorityTaskWoken );
\r
320 portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
\r
322 /*-----------------------------------------------------------*/
\r
324 static void prvSetupUSBDrivers( void )
\r
326 LPC_USBDRV_INIT_T xUSBCallback;
\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
336 /* Initialise then connect the USB. */
\r
337 USB_Init( &xUSBCallback );
\r
338 USB_Connect( pdTRUE );
\r