2 FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
\r
5 ***************************************************************************
\r
7 * FreeRTOS tutorial books are available in pdf and paperback. *
\r
8 * Complete, revised, and edited pdf reference manuals are also *
\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
18 * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
\r
20 * Thank you for using FreeRTOS, and thank you for your support! *
\r
22 ***************************************************************************
\r
25 This file is part of the FreeRTOS distribution.
\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
44 http://www.FreeRTOS.org - Documentation, latest information, license and
\r
47 http://www.SafeRTOS.com - A version that is certified for use in safety
\r
50 http://www.OpenRTOS.com - Commercial support, development, porting,
\r
51 licensing and training services.
\r
55 * NOTE: This file uses a third party USB CDC driver.
\r
58 /* Standard includes. */
\r
63 /* FreeRTOS includes. */
\r
64 #include "FreeRTOS.h"
\r
68 /* LPCUSB includes. */
\r
70 #include "Descriptors.h"
\r
72 /* Example includes. */
\r
73 #include "FreeRTOS_CLI.h"
\r
74 #include "CDCCommandConsole.h"
\r
76 /* Dimensions the buffer into which input characters are placed. */
\r
77 #define cmdMAX_INPUT_SIZE 50
\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
82 /*-----------------------------------------------------------*/
\r
85 * The task that implements the command console processing.
\r
87 static void prvCDCCommandConsoleTask( void *pvParameters );
\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
96 static void prvNotifyTaskOfUSBEvent( void );
\r
98 /*-----------------------------------------------------------*/
\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
104 /* Used to guard access to the CDC output, which is used by more than one
\r
106 static xSemaphoreHandle xCDCMutex = NULL;
\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
113 /* LPCUSBlib CDC Class driver interface configuration and state information. */
\r
114 static USB_ClassInfo_CDC_Device_t xVirtualCOMPort = {
\r
116 .ControlInterfaceNumber = 0,
\r
118 .DataINEndpointNumber = CDC_TX_EPNUM,
\r
119 .DataINEndpointSize = CDC_TXRX_EPSIZE,
\r
120 .DataINEndpointDoubleBank = false,
\r
122 .DataOUTEndpointNumber = CDC_RX_EPNUM,
\r
123 .DataOUTEndpointSize = CDC_TXRX_EPSIZE,
\r
124 .DataOUTEndpointDoubleBank = false,
\r
126 .NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM,
\r
127 .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,
\r
128 .NotificationEndpointDoubleBank = false,
\r
133 /*-----------------------------------------------------------*/
\r
135 void vCDCCommandConsoleStart( uint16_t usStackSize, unsigned portBASE_TYPE uxPriority )
\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
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
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
156 /*-----------------------------------------------------------*/
\r
158 static void prvCDCCommandConsoleTask( void *pvParameters )
\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
164 /* Just to avoid warnings about unused parameters. */
\r
165 ( void ) pvParameters;
\r
167 /* Initialise LPCUSB CDC driver. */
\r
168 USB_Init( xVirtualCOMPort.Config.PortNumber, USB_MODE_Device );
\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
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
182 /* Wait for new events to originate from the LPCUSB interrupts. */
\r
183 // xSemaphoreTake( xCDCEventSemaphore, 100 );
\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
189 /* Ensure no other tasks are using the COM port. */
\r
190 if( xSemaphoreTake( xCDCMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )
\r
192 /* Have any characters been received? */
\r
193 if( CDC_Device_BytesReceived( &xVirtualCOMPort ) != 0 )
\r
195 /* Only interested in reading one character at a time. */
\r
196 cRxedChar = CDC_Device_ReceiveByte( &xVirtualCOMPort );
\r
198 /* Echo the character back. */
\r
199 CDC_Device_SendData( &xVirtualCOMPort, &cRxedChar, sizeof( uint8_t ) );
\r
201 /* Was it an end of line character? */
\r
202 if( cRxedChar == '\n' || cRxedChar == '\r' )
\r
204 /* Just to space the output from the input. */
\r
205 CDC_Device_SendData( &xVirtualCOMPort, pcNewLine, strlen( ( const char * ) pcNewLine ) );
\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
211 /* Copy the last command back into the input string. */
\r
212 strcpy( ( char * ) cInputString, ( char * ) cLastInputString );
\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
221 /* Get the next output string from the command
\r
223 xReturned = FreeRTOS_CLIProcessCommand( ( const int8_t * const ) cInputString, ( int8_t * ) pcOutputString, configCOMMAND_INT_MAX_OUTPUT_SIZE );
\r
225 /* Write the generated string to the CDC. */
\r
226 CDC_Device_SendData( &xVirtualCOMPort, pcOutputString, strlen( ( const char * ) pcOutputString ) );
\r
228 } while( xReturned != pdFALSE );
\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
236 memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
\r
238 CDC_Device_SendData( &xVirtualCOMPort, pcEndOfOutputMessage, strlen( ( const char * ) pcEndOfOutputMessage ) );
\r
242 if( cRxedChar == '\r' )
\r
244 /* Ignore the character. */
\r
246 else if( cRxedChar == '\b' )
\r
248 /* Backspace was pressed. Erase the last character in
\r
249 thestring - if any. */
\r
250 if( xInputIndex > 0 )
\r
253 cInputString[ xInputIndex ] = '\0';
\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
263 if( xInputIndex < cmdMAX_INPUT_SIZE )
\r
265 cInputString[ xInputIndex ] = cRxedChar;
\r
273 /* Must ensure to give the mutex back. */
\r
274 xSemaphoreGive( xCDCMutex );
\r
278 /*-----------------------------------------------------------*/
\r
280 void vOutputString( const uint8_t * const pucMessage )
\r
282 if( xSemaphoreTake( xCDCMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )
\r
284 CDC_Device_SendData( &xVirtualCOMPort, ( const char * const ) pucMessage, strlen( ( const char * ) pucMessage ) );
\r
285 xSemaphoreGive( xCDCMutex );
\r
288 /*-----------------------------------------------------------*/
\r
290 static void prvNotifyTaskOfUSBEvent( void )
\r
292 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
\r
294 /* 'Give' the semaphore that signals the arrival of new data to the command
\r
296 configASSERT( xCDCEventSemaphore );
\r
297 xSemaphoreGiveFromISR( xCDCEventSemaphore, &xHigherPriorityTaskWoken );
\r
298 portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
\r
300 /*-----------------------------------------------------------*/
\r
302 /* Standard LPCUSB event handler. */
\r
303 void EVENT_USB_Device_ConfigurationChanged( void )
\r
305 CDC_Device_ConfigureEndpoints( &xVirtualCOMPort );
\r
306 prvNotifyTaskOfUSBEvent();
\r
308 /*-----------------------------------------------------------*/
\r
310 /* Standard LPCUSB event handler. */
\r
311 void EVENT_USB_Device_ControlRequest( void )
\r
313 CDC_Device_ProcessControlRequest( &xVirtualCOMPort );
\r
314 prvNotifyTaskOfUSBEvent();
\r
316 /*-----------------------------------------------------------*/
\r
318 /* Standard LPCUSB event handler. */
\r
319 void EVENT_USB_Device_Connect(void)
\r
321 prvNotifyTaskOfUSBEvent();
\r
323 /*-----------------------------------------------------------*/
\r
325 /* Standard LPCUSB event handler. */
\r
326 void EVENT_USB_Device_Disconnect(void)
\r
328 prvNotifyTaskOfUSBEvent();
\r
330 /*-----------------------------------------------------------*/
\r
332 /* Standard LPCUSB event handler. */
\r
333 void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t *const CDCInterfaceInfo)
\r
335 prvNotifyTaskOfUSBEvent();
\r
337 /*-----------------------------------------------------------*/
\r
339 /* Standard LPCUSB event handler. */
\r
340 void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t *const CDCInterfaceInfo)
\r
342 prvNotifyTaskOfUSBEvent();
\r