]> git.sur5r.net Git - freertos/commitdiff
Add simple USB CDC task.
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Fri, 7 Aug 2009 15:30:18 +0000 (15:30 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Fri, 7 Aug 2009 15:30:18 +0000 (15:30 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@835 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

15 files changed:
Demo/CORTEX_LPC1768_GCC_Rowley/FreeRTOSConfig.h
Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/USB_CDC.c [new file with mode: 0644]
Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/type.h [new file with mode: 0644]
Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbapi.h [new file with mode: 0644]
Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbcontrol.c [new file with mode: 0644]
Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbdebug.h [new file with mode: 0644]
Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.c [new file with mode: 0644]
Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.c.bak [new file with mode: 0644]
Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.h [new file with mode: 0644]
Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbinit.c [new file with mode: 0644]
Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbstdreq.c [new file with mode: 0644]
Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbstruct.h [new file with mode: 0644]
Demo/CORTEX_LPC1768_GCC_Rowley/RTOSDemo.hzp
Demo/CORTEX_LPC1768_GCC_Rowley/RTOSDemo.hzs
Demo/CORTEX_LPC1768_GCC_Rowley/main.c

index a8793481462779ceb59ba2b663557db0b4242ec4..f0d90fdf440a0b391afe745e72741623f2673ce1 100644 (file)
@@ -64,7 +64,7 @@
 #define configUSE_IDLE_HOOK                    0\r
 #define configMAX_PRIORITIES           ( ( unsigned portBASE_TYPE ) 5 )\r
 #define configUSE_TICK_HOOK                    1\r
-#define configCPU_CLOCK_HZ                     ( ( unsigned portLONG ) 64000000 )\r
+#define configCPU_CLOCK_HZ                     ( ( unsigned portLONG ) 99000000 )\r
 #define configTICK_RATE_HZ                     ( ( portTickType ) 1000 )\r
 #define configMINIMAL_STACK_SIZE       ( ( unsigned portSHORT ) 80 )\r
 #define configTOTAL_HEAP_SIZE          ( ( size_t ) ( 19 * 1024 ) )\r
@@ -133,9 +133,12 @@ to exclude the API function. */
 #define configMAX_SYSCALL_INTERRUPT_PRIORITY   ( 5 << (8 - configPRIO_BITS) )\r
 \r
 /* Priorities passed to NVIC_SetPriority() do not require shifting as the\r
-function does the shifting itself. */\r
+function does the shifting itself.  Note these priorities need to be equal to\r
+or lower than configMAX_SYSCALL_INTERRUPT_PRIORITY - therefore the numeric\r
+value needs to be equal to or greater than 5 (on the Cortex M3 the lower the\r
+numeric value the higher the interrupt priority). */\r
 #define configEMAC_INTERRUPT_PRIORITY          5\r
-\r
+#define configUSB_INTERRUPT_PRIORITY           6\r
 \r
 \r
 \r
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/USB_CDC.c b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/USB_CDC.c
new file mode 100644 (file)
index 0000000..8b88bef
--- /dev/null
@@ -0,0 +1,459 @@
+/*\r
+       LPCUSB, an USB device driver for LPC microcontrollers   \r
+       Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)\r
+\r
+       Redistribution and use in source and binary forms, with or without\r
+       modification, are permitted provided that the following conditions are met:\r
+\r
+       1. Redistributions of source code must retain the above copyright\r
+          notice, this list of conditions and the following disclaimer.\r
+       2. Redistributions in binary form must reproduce the above copyright\r
+          notice, this list of conditions and the following disclaimer in the\r
+          documentation and/or other materials provided with the distribution.\r
+       3. The name of the author may not be used to endorse or promote products\r
+          derived from this software without specific prior written permission.\r
+\r
+       THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+       IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, \r
+       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
+       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+       THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*/\r
+\r
+/*\r
+       Minimal implementation of a USB serial port, using the CDC class.\r
+       This example application simply echoes everything it receives right back\r
+       to the host.\r
+\r
+       Windows:\r
+       Extract the usbser.sys file from .cab file in C:\WINDOWS\Driver Cache\i386\r
+       and store it somewhere (C:\temp is a good place) along with the usbser.inf\r
+       file. Then plug in the LPC176x and direct windows to the usbser driver.\r
+       Windows then creates an extra COMx port that you can open in a terminal\r
+       program, like hyperterminal. [Note for FreeRTOS users - the required .inf\r
+       file is included in the project directory.]\r
+\r
+       Linux:\r
+       The device should be recognised automatically by the cdc_acm driver,\r
+       which creates a /dev/ttyACMx device file that acts just like a regular\r
+       serial port.\r
+\r
+*/\r
+\r
+#include "FreeRTOS.h"\r
+#include "queue.h"\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#include "usbapi.h"\r
+#include "usbdebug.h"\r
+#include "usbstruct.h"\r
+\r
+#include "LPC17xx.h"\r
+\r
+#define usbMAX_SEND_BLOCK              ( 20 / portTICK_RATE_MS )\r
+#define usbBUFFER_LEN                  ( 20 )\r
+\r
+#define INCREMENT_ECHO_BY 1\r
+#define BAUD_RATE      115200\r
+\r
+#define INT_IN_EP              0x81\r
+#define BULK_OUT_EP            0x05\r
+#define BULK_IN_EP             0x82\r
+\r
+#define MAX_PACKET_SIZE        64\r
+\r
+#define LE_WORD(x)             ((x)&0xFF),((x)>>8)\r
+\r
+// CDC definitions\r
+#define CS_INTERFACE                   0x24\r
+#define CS_ENDPOINT                            0x25\r
+\r
+#define        SET_LINE_CODING                 0x20\r
+#define        GET_LINE_CODING                 0x21\r
+#define        SET_CONTROL_LINE_STATE  0x22\r
+\r
+// data structure for GET_LINE_CODING / SET_LINE_CODING class requests\r
+typedef struct {\r
+       unsigned long           dwDTERate;\r
+       unsigned char           bCharFormat;\r
+       unsigned char           bParityType;\r
+       unsigned char           bDataBits;\r
+} TLineCoding;\r
+\r
+static TLineCoding LineCoding = {115200, 0, 0, 8};\r
+static unsigned char abBulkBuf[64];\r
+static unsigned char abClassReqData[8];\r
+\r
+static xQueueHandle xRxedChars = NULL, xCharsForTx = NULL;\r
+\r
+// forward declaration of interrupt handler\r
+void USBIntHandler(void);\r
+\r
+static const unsigned char abDescriptors[] = {\r
+\r
+// device descriptor\r
+       0x12,\r
+       DESC_DEVICE,\r
+       LE_WORD(0x0101),                        // bcdUSB\r
+       0x02,                                           // bDeviceClass\r
+       0x00,                                           // bDeviceSubClass\r
+       0x00,                                           // bDeviceProtocol\r
+       MAX_PACKET_SIZE0,                       // bMaxPacketSize\r
+       LE_WORD(0xFFFF),                        // idVendor\r
+       LE_WORD(0x0005),                        // idProduct\r
+       LE_WORD(0x0100),                        // bcdDevice\r
+       0x01,                                           // iManufacturer\r
+       0x02,                                           // iProduct\r
+       0x03,                                           // iSerialNumber\r
+       0x01,                                           // bNumConfigurations\r
+\r
+// configuration descriptor\r
+       0x09,\r
+       DESC_CONFIGURATION,\r
+       LE_WORD(67),                            // wTotalLength\r
+       0x02,                                           // bNumInterfaces\r
+       0x01,                                           // bConfigurationValue\r
+       0x00,                                           // iConfiguration\r
+       0xC0,                                           // bmAttributes\r
+       0x32,                                           // bMaxPower\r
+// control class interface\r
+       0x09,\r
+       DESC_INTERFACE,\r
+       0x00,                                           // bInterfaceNumber\r
+       0x00,                                           // bAlternateSetting\r
+       0x01,                                           // bNumEndPoints\r
+       0x02,                                           // bInterfaceClass\r
+       0x02,                                           // bInterfaceSubClass\r
+       0x01,                                           // bInterfaceProtocol, linux requires value of 1 for the cdc_acm module\r
+       0x00,                                           // iInterface\r
+// header functional descriptor\r
+       0x05,\r
+       CS_INTERFACE,\r
+       0x00,\r
+       LE_WORD(0x0110),\r
+// call management functional descriptor\r
+       0x05,\r
+       CS_INTERFACE,\r
+       0x01,\r
+       0x01,                                           // bmCapabilities = device handles call management\r
+       0x01,                                           // bDataInterface\r
+// ACM functional descriptor\r
+       0x04,\r
+       CS_INTERFACE,\r
+       0x02,\r
+       0x02,                                           // bmCapabilities\r
+// union functional descriptor\r
+       0x05,\r
+       CS_INTERFACE,\r
+       0x06,\r
+       0x00,                                           // bMasterInterface\r
+       0x01,                                           // bSlaveInterface0\r
+// notification EP\r
+       0x07,\r
+       DESC_ENDPOINT,\r
+       INT_IN_EP,                                      // bEndpointAddress\r
+       0x03,                                           // bmAttributes = intr\r
+       LE_WORD(8),                                     // wMaxPacketSize\r
+       0x0A,                                           // bInterval\r
+// data class interface descriptor\r
+       0x09,\r
+       DESC_INTERFACE,\r
+       0x01,                                           // bInterfaceNumber\r
+       0x00,                                           // bAlternateSetting\r
+       0x02,                                           // bNumEndPoints\r
+       0x0A,                                           // bInterfaceClass = data\r
+       0x00,                                           // bInterfaceSubClass\r
+       0x00,                                           // bInterfaceProtocol\r
+       0x00,                                           // iInterface\r
+// data EP OUT\r
+       0x07,\r
+       DESC_ENDPOINT,\r
+       BULK_OUT_EP,                            // bEndpointAddress\r
+       0x02,                                           // bmAttributes = bulk\r
+       LE_WORD(MAX_PACKET_SIZE),       // wMaxPacketSize\r
+       0x00,                                           // bInterval\r
+// data EP in\r
+       0x07,\r
+       DESC_ENDPOINT,\r
+       BULK_IN_EP,                                     // bEndpointAddress\r
+       0x02,                                           // bmAttributes = bulk\r
+       LE_WORD(MAX_PACKET_SIZE),       // wMaxPacketSize\r
+       0x00,                                           // bInterval\r
+       \r
+       // string descriptors\r
+       0x04,\r
+       DESC_STRING,\r
+       LE_WORD(0x0409),\r
+\r
+       0x0E,\r
+       DESC_STRING,\r
+       'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0,\r
+\r
+       0x14,\r
+       DESC_STRING,\r
+       'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0,\r
+\r
+       0x12,\r
+       DESC_STRING,\r
+       'D', 0, 'E', 0, 'A', 0, 'D', 0, 'C', 0, '0', 0, 'D', 0, 'E', 0,\r
+\r
+// terminating zero\r
+       0\r
+};\r
+\r
+\r
+/**\r
+       Local function to handle incoming bulk data\r
+               \r
+       @param [in] bEP\r
+       @param [in] bEPStatus\r
+ */\r
+static void BulkOut(unsigned char bEP, unsigned char bEPStatus)\r
+{\r
+       int i, iLen;\r
+       long lHigherPriorityTaskWoken = pdFALSE;\r
+\r
+       ( void ) bEPStatus;\r
+       \r
+       // get data from USB into intermediate buffer\r
+       iLen = USBHwEPRead(bEP, abBulkBuf, sizeof(abBulkBuf));\r
+       for (i = 0; i < iLen; i++) {\r
+               // put into queue\r
+               xQueueSendFromISR( xRxedChars, &( abBulkBuf[ i ] ), &lHigherPriorityTaskWoken ); \r
+       }\r
+       \r
+       portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );\r
+}\r
+\r
+\r
+/**\r
+       Local function to handle outgoing bulk data\r
+               \r
+       @param [in] bEP\r
+       @param [in] bEPStatus\r
+ */\r
+static void BulkIn(unsigned char bEP, unsigned char bEPStatus)\r
+{\r
+       int i, iLen;\r
+       long lHigherPriorityTaskWoken = pdFALSE;\r
+\r
+       ( void ) bEPStatus;\r
+       \r
+       if (uxQueueMessagesWaitingFromISR( xCharsForTx ) == 0) {\r
+               // no more data, disable further NAK interrupts until next USB frame\r
+               USBHwNakIntEnable(0);\r
+               return;\r
+       }\r
+\r
+       // get bytes from transmit FIFO into intermediate buffer\r
+       for (i = 0; i < MAX_PACKET_SIZE; i++) {\r
+               if( xQueueReceiveFromISR( xCharsForTx, ( &abBulkBuf[i] ), &lHigherPriorityTaskWoken ) != pdPASS )\r
+               {\r
+                       break;\r
+               }\r
+       }\r
+       iLen = i;\r
+       \r
+       // send over USB\r
+       if (iLen > 0) {\r
+               USBHwEPWrite(bEP, abBulkBuf, iLen);\r
+       }\r
+       \r
+       portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );\r
+}\r
+\r
+\r
+/**\r
+       Local function to handle the USB-CDC class requests\r
+               \r
+       @param [in] pSetup\r
+       @param [out] piLen\r
+       @param [out] ppbData\r
+ */\r
+static BOOL HandleClassRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)\r
+{\r
+       switch (pSetup->bRequest) {\r
+\r
+       // set line coding\r
+       case SET_LINE_CODING:\r
+DBG("SET_LINE_CODING\n");\r
+               memcpy((unsigned char *)&LineCoding, *ppbData, 7);\r
+               *piLen = 7;\r
+DBG("dwDTERate=%u, bCharFormat=%u, bParityType=%u, bDataBits=%u\n",\r
+       LineCoding.dwDTERate,\r
+       LineCoding.bCharFormat,\r
+       LineCoding.bParityType,\r
+       LineCoding.bDataBits);\r
+               break;\r
+\r
+       // get line coding\r
+       case GET_LINE_CODING:\r
+DBG("GET_LINE_CODING\n");\r
+               *ppbData = (unsigned char *)&LineCoding;\r
+               *piLen = 7;\r
+               break;\r
+\r
+       // set control line state\r
+       case SET_CONTROL_LINE_STATE:\r
+               // bit0 = DTR, bit = RTS\r
+DBG("SET_CONTROL_LINE_STATE %X\n", pSetup->wValue);\r
+               break;\r
+\r
+       default:\r
+               return FALSE;\r
+       }\r
+       return TRUE;\r
+}\r
+\r
+\r
+/**\r
+       Writes one character to VCOM port\r
+       \r
+       @param [in] c character to write\r
+       @returns character written, or EOF if character could not be written\r
+ */\r
+int VCOM_putchar(int c)\r
+{\r
+char cc = ( char ) c;\r
+\r
+       if( xQueueSend( xCharsForTx, &cc, usbMAX_SEND_BLOCK ) == pdPASS )\r
+       {\r
+               return c;\r
+       }\r
+       else\r
+       {\r
+               return EOF;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+       Reads one character from VCOM port\r
+       \r
+       @returns character read, or EOF if character could not be read\r
+ */\r
+int VCOM_getchar(void)\r
+{\r
+       unsigned char c;\r
+       \r
+       /* Block the task until a character is available. */\r
+       xQueueReceive( xRxedChars, &c, portMAX_DELAY );\r
+       return c;\r
+}\r
+\r
+\r
+/**\r
+       Interrupt handler\r
+       \r
+       Simply calls the USB ISR\r
+ */\r
+//void USBIntHandler(void)\r
+void USB_IRQHandler(void)\r
+{\r
+       USBHwISR();\r
+}\r
+\r
+\r
+static void USBFrameHandler(unsigned short wFrame)\r
+{\r
+       ( void ) wFrame;\r
+       \r
+       if( uxQueueMessagesWaitingFromISR( xCharsForTx ) > 0 )\r
+       {\r
+               // data available, enable NAK interrupt on bulk in\r
+               USBHwNakIntEnable(INACK_BI);\r
+       }\r
+}\r
+\r
+// CodeRed - added CPUcpsie\r
+\r
+unsigned long CPUcpsie(void)\r
+{\r
+    unsigned long ulRet;\r
+\r
+    //\r
+    // Read PRIMASK and enable interrupts.\r
+    //\r
+    __asm("    mrs     %0, PRIMASK\n"\r
+          "    cpsie   i\n"\r
+          "    bx      lr\n"\r
+          : "=r" (ulRet));\r
+\r
+    //\r
+    // The return is handled in the inline assembly, but the compiler will\r
+    // still complain if there is not an explicit return here (despite the fact\r
+    // that this does not result in any code being produced because of the\r
+    // naked attribute).\r
+    //\r
+    return(ulRet);\r
+}\r
+\r
+void vUSBTask( void *pvParameters )\r
+{\r
+       int c;\r
+       \r
+       /* Just to prevent compiler warnings about the unused parameter. */\r
+       ( void ) pvParameters;\r
+       DBG("Initialising USB stack\n");\r
+\r
+       xRxedChars = xQueueCreate( usbBUFFER_LEN, sizeof( char ) );\r
+       xCharsForTx = xQueueCreate( usbBUFFER_LEN, sizeof( char ) );\r
+\r
+       if( ( xRxedChars == NULL ) || ( xCharsForTx == NULL ) )\r
+       {\r
+               /* Not enough heap available to create the buffer queues, can't do\r
+               anything so just delete ourselves. */\r
+               vTaskDelete( NULL );\r
+       }\r
+       \r
+       \r
+       // initialise stack\r
+       USBInit();\r
+\r
+       // register descriptors\r
+       USBRegisterDescriptors(abDescriptors);\r
+\r
+       // register class request handler\r
+       USBRegisterRequestHandler(REQTYPE_TYPE_CLASS, HandleClassRequest, abClassReqData);\r
+\r
+       // register endpoint handlers\r
+       USBHwRegisterEPIntHandler(INT_IN_EP, NULL);\r
+       USBHwRegisterEPIntHandler(BULK_IN_EP, BulkIn);\r
+       USBHwRegisterEPIntHandler(BULK_OUT_EP, BulkOut);\r
+       \r
+       // register frame handler\r
+       USBHwRegisterFrameHandler(USBFrameHandler);\r
+\r
+       // enable bulk-in interrupts on NAKs\r
+       USBHwNakIntEnable(INACK_BI);\r
+\r
+       DBG("Starting USB communication\n");\r
+\r
+       NVIC_SetPriority( USB_IRQn, configUSB_INTERRUPT_PRIORITY );\r
+       NVIC_EnableIRQ( USB_IRQn );\r
+               \r
+       // connect to bus\r
+               \r
+       DBG("Connecting to USB bus\n");\r
+       USBHwConnect(TRUE);\r
+\r
+       // echo any character received (do USB stuff in interrupt)\r
+       for( ;; )\r
+       {\r
+               c = VCOM_getchar();\r
+               if (c != EOF) \r
+               {\r
+                       // Echo character back with INCREMENT_ECHO_BY offset, so for example if\r
+                       // INCREMENT_ECHO_BY is 1 and 'A' is received, 'B' will be echoed back.\r
+                       VCOM_putchar(c + INCREMENT_ECHO_BY );\r
+               }\r
+       }\r
+}\r
+\r
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/type.h b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/type.h
new file mode 100644 (file)
index 0000000..89d3685
--- /dev/null
@@ -0,0 +1,38 @@
+/*****************************************************************************\r
+ *   type.h:  Type definition Header file for NXP LPC17xx Family \r
+ *   Microprocessors\r
+ *\r
+ *   Copyright(C) 2008, NXP Semiconductor\r
+ *   All rights reserved.\r
+ *\r
+ *   History\r
+ *   2008.08.21  ver 1.00    Prelimnary version, first Release\r
+ *\r
+******************************************************************************/\r
+#ifndef __TYPE_H__\r
+#define __TYPE_H__\r
+\r
+#ifndef NULL\r
+#define NULL    ((void *)0)\r
+#endif\r
+\r
+#ifndef FALSE\r
+#define FALSE   (0)\r
+#endif\r
+\r
+#ifndef TRUE\r
+#define TRUE    (1)\r
+#endif\r
+\r
+typedef unsigned char  BYTE;\r
+typedef unsigned short WORD;\r
+typedef unsigned long  DWORD;\r
+typedef unsigned int   BOOL;\r
+\r
+typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;\r
+typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;\r
+\r
+/* Pointer to Function returning Void (any number of parameters) */\r
+typedef void (*PFV)();\r
+\r
+#endif  /* __TYPE_H__ */\r
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbapi.h b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbapi.h
new file mode 100644 (file)
index 0000000..050f0d9
--- /dev/null
@@ -0,0 +1,118 @@
+/*\r
+       LPCUSB, an USB device driver for LPC microcontrollers   \r
+       Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)\r
+\r
+       Redistribution and use in source and binary forms, with or without\r
+       modification, are permitted provided that the following conditions are met:\r
+\r
+       1. Redistributions of source code must retain the above copyright\r
+          notice, this list of conditions and the following disclaimer.\r
+       2. Redistributions in binary form must reproduce the above copyright\r
+          notice, this list of conditions and the following disclaimer in the\r
+          documentation and/or other materials provided with the distribution.\r
+       3. The name of the author may not be used to endorse or promote products\r
+          derived from this software without specific prior written permission.\r
+\r
+       THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+       IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, \r
+       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
+       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+       THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*/\r
+\r
+/**\r
+       @file\r
+*/\r
+\r
+#include "usbstruct.h"         // for TSetupPacket\r
+\r
+/*************************************************************************\r
+       USB configuration\r
+**************************************************************************/\r
+\r
+#define MAX_PACKET_SIZE0       64              /**< maximum packet size for EP 0 */\r
+\r
+/*************************************************************************\r
+       USB hardware interface\r
+**************************************************************************/\r
+\r
+// endpoint status sent through callback\r
+#define EP_STATUS_DATA         (1<<0)          /**< EP has data */\r
+#define EP_STATUS_STALLED      (1<<1)          /**< EP is stalled */\r
+#define EP_STATUS_SETUP                (1<<2)          /**< EP received setup packet */\r
+#define EP_STATUS_ERROR                (1<<3)          /**< EP data was overwritten by setup packet */\r
+#define EP_STATUS_NACKED       (1<<4)          /**< EP sent NAK */\r
+\r
+// device status sent through callback\r
+#define DEV_STATUS_CONNECT             (1<<0)  /**< device just got connected */\r
+#define DEV_STATUS_SUSPEND             (1<<2)  /**< device entered suspend state */\r
+#define DEV_STATUS_RESET               (1<<4)  /**< device just got reset */\r
+\r
+// interrupt bits for NACK events in USBHwNakIntEnable\r
+// (these bits conveniently coincide with the LPC176x USB controller bit)\r
+#define INACK_CI               (1<<1)                  /**< interrupt on NACK for control in */\r
+#define INACK_CO               (1<<2)                  /**< interrupt on NACK for control out */\r
+#define INACK_II               (1<<3)                  /**< interrupt on NACK for interrupt in */\r
+#define INACK_IO               (1<<4)                  /**< interrupt on NACK for interrupt out */\r
+#define INACK_BI               (1<<5)                  /**< interrupt on NACK for bulk in */\r
+#define INACK_BO               (1<<6)                  /**< interrupt on NACK for bulk out */\r
+\r
+BOOL USBHwInit                 (void);\r
+void USBHwISR                  (void);\r
+\r
+void USBHwNakIntEnable (unsigned char bIntBits);\r
+\r
+void USBHwConnect              (BOOL fConnect);\r
+\r
+void USBHwSetAddress   (unsigned char bAddr);\r
+void USBHwConfigDevice (BOOL fConfigured);\r
+\r
+// endpoint operations\r
+void USBHwEPConfig             (unsigned char bEP, unsigned short wMaxPacketSize);\r
+int  USBHwEPRead               (unsigned char bEP, unsigned char *pbBuf, int iMaxLen);\r
+int     USBHwEPWrite           (unsigned char bEP, unsigned char *pbBuf, int iLen);\r
+void USBHwEPStall              (unsigned char bEP, BOOL fStall);\r
+unsigned char   USBHwEPGetStatus       (unsigned char bEP);\r
+\r
+/** Endpoint interrupt handler callback */\r
+typedef void (TFnEPIntHandler) (unsigned char bEP, unsigned char bEPStatus);\r
+void USBHwRegisterEPIntHandler (unsigned char bEP, TFnEPIntHandler *pfnHandler);\r
+\r
+/** Device status handler callback */\r
+typedef void (TFnDevIntHandler)        (unsigned char bDevStatus);\r
+void USBHwRegisterDevIntHandler        (TFnDevIntHandler *pfnHandler);\r
+\r
+/** Frame event handler callback */\r
+typedef void (TFnFrameHandler)(unsigned short wFrame);\r
+void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler);\r
+\r
+\r
+/*************************************************************************\r
+       USB application interface\r
+**************************************************************************/\r
+\r
+// initialise the complete stack, including HW\r
+BOOL USBInit(void);\r
+\r
+/** Request handler callback (standard, vendor, class) */\r
+typedef BOOL (TFnHandleRequest)(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData);\r
+void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, unsigned char *pbDataStore);\r
+void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler);\r
+\r
+/** Descriptor handler callback */\r
+typedef BOOL (TFnGetDescriptor)(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData);\r
+\r
+/** Default standard request handler */\r
+BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData);\r
+\r
+/** Default EP0 handler */\r
+void USBHandleControlTransfer(unsigned char bEP, unsigned char bEPStat);\r
+\r
+/** Descriptor handling */\r
+void USBRegisterDescriptors(const unsigned char *pabDescriptors);\r
+BOOL USBGetDescriptor(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData);\r
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbcontrol.c b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbcontrol.c
new file mode 100644 (file)
index 0000000..18ff180
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+       LPCUSB, an USB device driver for LPC microcontrollers   
+       Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are met:
+
+       1. Redistributions of source code must retain the above copyright
+          notice, this list of conditions and the following disclaimer.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, this list of conditions and the following disclaimer in the
+          documentation and/or other materials provided with the distribution.
+       3. The name of the author may not be used to endorse or promote products
+          derived from this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+       IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
+       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+       THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/** @file
+       Control transfer handler.
+       
+       This module handles control transfers and is normally installed on the
+       endpoint 0 callback.
+       
+       Control transfers can be of the following type:
+       0 Standard;
+       1 Class;
+       2 Vendor;
+       3 Reserved.
+
+       A callback can be installed for each of these control transfers using
+       USBRegisterRequestHandler.
+       When an OUT request arrives, data is collected in the data store provided
+       with the USBRegisterRequestHandler call. When the transfer is done, the
+       callback is called.
+       When an IN request arrives, the callback is called immediately to either
+       put the control transfer data in the data store, or to get a pointer to
+       control transfer data. The data is then packetised and sent to the host.
+*/
+
+#include "usbdebug.h"
+
+#include "usbstruct.h"
+#include "usbapi.h"
+
+
+
+#define        MAX_CONTROL_SIZE        128     /**< maximum total size of control transfer data */
+#define        MAX_REQ_HANDLERS        4       /**< standard, class, vendor, reserved */
+
+static TSetupPacket            Setup;  /**< setup packet */
+
+static unsigned char                           *pbData;        /**< pointer to data buffer */
+static int                             iResidue;       /**< remaining bytes in buffer */
+static int                             iLen;           /**< total length of control transfer */
+
+/** Array of installed request handler callbacks */
+static TFnHandleRequest *apfnReqHandlers[4] = {NULL, NULL, NULL, NULL};
+/** Array of installed request data pointers */
+static unsigned char                           *apbDataStore[4] = {NULL, NULL, NULL, NULL};
+
+/**
+       Local function to handle a request by calling one of the installed
+       request handlers.
+               
+       In case of data going from host to device, the data is at *ppbData.
+       In case of data going from device to host, the handler can either
+       choose to write its data at *ppbData or update the data pointer.
+               
+       @param [in]             pSetup          The setup packet
+       @param [in,out] *piLen          Pointer to data length
+       @param [in,out] ppbData         Data buffer.
+
+       @return TRUE if the request was handles successfully
+ */
+static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
+{
+       TFnHandleRequest *pfnHandler;
+       int iType;
+       
+       iType = REQTYPE_GET_TYPE(pSetup->bmRequestType);
+       pfnHandler = apfnReqHandlers[iType];
+       if (pfnHandler == NULL) {
+               DBG("No handler for reqtype %d\n", iType);
+               return FALSE;
+       }
+
+       return pfnHandler(pSetup, piLen, ppbData);
+}
+
+
+/**
+       Local function to stall the control endpoint
+       
+       @param [in]     bEPStat Endpoint status
+ */
+static void StallControlPipe(unsigned char bEPStat)
+{
+       unsigned char   *pb;
+       int     i;
+
+       USBHwEPStall(0x80, TRUE);
+
+// dump setup packet
+       DBG("STALL on [");
+       pb = (unsigned char *)&Setup;
+       for (i = 0; i < 8; i++) {
+               DBG(" %02x", *pb++);
+       }
+       DBG("] stat=%x\n", bEPStat);
+}
+
+
+/**
+       Sends next chunk of data (possibly 0 bytes) to host
+ */
+static void DataIn(void)
+{
+       int iChunk;
+
+       if( MAX_PACKET_SIZE0 < iResidue )
+       {
+               iChunk = MAX_PACKET_SIZE0;
+       }
+       else
+       {
+               iChunk = iResidue;
+       }
+
+       USBHwEPWrite(0x80, pbData, iChunk);
+       pbData += iChunk;
+       iResidue -= iChunk;
+}
+
+
+/**
+ *     Handles IN/OUT transfers on EP0
+ *
+ *     @param [in]     bEP             Endpoint address
+ *     @param [in]     bEPStat Endpoint status
+ */
+void USBHandleControlTransfer(unsigned char bEP, unsigned char bEPStat)
+{
+       int iChunk, iType;
+
+       if (bEP == 0x00) {
+               // OUT transfer
+               if (bEPStat & EP_STATUS_SETUP) {
+                       // setup packet, reset request message state machine
+                       USBHwEPRead(0x00, (unsigned char *)&Setup, sizeof(Setup));
+                       DBG("S%x", Setup.bRequest);
+
+                       // defaults for data pointer and residue
+                       iType = REQTYPE_GET_TYPE(Setup.bmRequestType);
+                       pbData = apbDataStore[iType];
+                       iResidue = Setup.wLength;
+                       iLen = Setup.wLength;
+
+                       if ((Setup.wLength == 0) ||
+                               (REQTYPE_GET_DIR(Setup.bmRequestType) == REQTYPE_DIR_TO_HOST)) {
+                               // ask installed handler to process request
+                               if (!_HandleRequest(&Setup, &iLen, &pbData)) {
+                                       DBG("_HandleRequest1 failed\n");
+                                       StallControlPipe(bEPStat);
+                                       return;
+                               }
+                               // send smallest of requested and offered length
+                               if( iLen < Setup.wLength )
+                               {
+                                       iResidue = iLen;
+                               }
+                               else
+                               {
+                                       iResidue = Setup.wLength;
+                               }
+
+                               // send first part (possibly a zero-length status message)
+                               DataIn();
+                       }
+               }
+               else {          
+                       if (iResidue > 0) {
+                               // store data
+                               iChunk = USBHwEPRead(0x00, pbData, iResidue);
+                               if (iChunk < 0) {
+                                       StallControlPipe(bEPStat);
+                                       return;
+                               }
+                               pbData += iChunk;
+                               iResidue -= iChunk;
+                               if (iResidue == 0) {
+                                       // received all, send data to handler
+                                       iType = REQTYPE_GET_TYPE(Setup.bmRequestType);
+                                       pbData = apbDataStore[iType];
+                                       if (!_HandleRequest(&Setup, &iLen, &pbData)) {
+                                               DBG("_HandleRequest2 failed\n");
+                                               StallControlPipe(bEPStat);
+                                               return;
+                                       }
+                                       // send status to host
+                                       DataIn();
+                               }
+                       }
+                       else {
+                               // absorb zero-length status message
+                               iChunk = USBHwEPRead(0x00, NULL, 0);
+                               DBG(iChunk > 0 ? "?" : "");
+                       }
+               }
+       }
+       else if (bEP == 0x80) {
+               // IN transfer
+               // send more data if available (possibly a 0-length packet)
+               DataIn();
+       }
+       else {
+               ASSERT(FALSE);
+       }
+}
+
+
+/**
+       Registers a callback for handling requests
+               
+       @param [in]     iType                   Type of request, e.g. REQTYPE_TYPE_STANDARD
+       @param [in]     *pfnHandler             Callback function pointer
+       @param [in]     *pbDataStore    Data storage area for this type of request
+ */
+void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, unsigned char *pbDataStore)
+{
+       ASSERT(iType >= 0);
+       ASSERT(iType < 4);
+       apfnReqHandlers[iType] = pfnHandler;
+       apbDataStore[iType] = pbDataStore;
+}
+
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbdebug.h b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbdebug.h
new file mode 100644 (file)
index 0000000..4a14862
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+       LPCUSB, an USB device driver for LPC microcontrollers   
+       Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are met:
+
+       1. Redistributions of source code must retain the above copyright
+          notice, this list of conditions and the following disclaimer.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, this list of conditions and the following disclaimer in the
+          documentation and/or other materials provided with the distribution.
+       3. The name of the author may not be used to endorse or promote products
+          derived from this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+       IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
+       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+       THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// CodeRed - comment out this printf, as will use real one from stdio.h
+// to implement output via semihosting
+
+//int printf(const char *format, ...);
+# include <stdio.h>
+
+#ifdef _DEBUG
+#define DBG    printf
+#define ASSERT(x)      if(!(x)){DBG("\nAssertion '%s' failed in %s:%s#%d!\n",#x,__FILE__,__FUNCTION__,__LINE__);while(1);}
+#else
+#define DBG(x ...)
+#define ASSERT(x)
+#endif
+
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.c b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.c
new file mode 100644 (file)
index 0000000..e9bd460
--- /dev/null
@@ -0,0 +1,521 @@
+/*\r
+       LPCUSB, an USB device driver for LPC microcontrollers\r
+       Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)\r
+\r
+       Redistribution and use in source and binary forms, with or without\r
+       modification, are permitted provided that the following conditions are met:\r
+\r
+       1. Redistributions of source code must retain the above copyright\r
+          notice, this list of conditions and the following disclaimer.\r
+       2. Redistributions in binary form must reproduce the above copyright\r
+          notice, this list of conditions and the following disclaimer in the\r
+          documentation and/or other materials provided with the distribution.\r
+       3. The name of the author may not be used to endorse or promote products\r
+          derived from this software without specific prior written permission.\r
+\r
+       THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+       IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
+       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+       THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*/\r
+\r
+\r
+/** @file\r
+       USB hardware layer\r
+ */\r
+\r
+\r
+#include "usbdebug.h"\r
+#include "usbhw_lpc.h"\r
+#include "usbapi.h"\r
+\r
+/** Installed device interrupt handler */\r
+static TFnDevIntHandler *_pfnDevIntHandler = NULL;\r
+/** Installed endpoint interrupt handlers */\r
+static TFnEPIntHandler *_apfnEPIntHandlers[16];\r
+/** Installed frame interrupt handlers */\r
+static TFnFrameHandler *_pfnFrameHandler = NULL;\r
+\r
+/** convert from endpoint address to endpoint index */\r
+#define EP2IDX(bEP)    ((((bEP)&0xF)<<1)|(((bEP)&0x80)>>7))\r
+/** convert from endpoint index to endpoint address */\r
+#define IDX2EP(idx)    ((((idx)<<7)&0x80)|(((idx)>>1)&0xF))\r
+\r
+\r
+\r
+/**\r
+       Local function to wait for a device interrupt (and clear it)\r
+\r
+       @param [in]     dwIntr          Bitmask of interrupts to wait for\r
+ */\r
+static void Wait4DevInt(unsigned long dwIntr)\r
+{\r
+       // wait for specific interrupt\r
+       while ((USB->USBDevIntSt & dwIntr) != dwIntr);\r
+       // clear the interrupt bits\r
+       USB->USBDevIntClr = dwIntr;\r
+}\r
+\r
+\r
+/**\r
+       Local function to send a command to the USB protocol engine\r
+\r
+       @param [in]     bCmd            Command to send\r
+ */\r
+static void USBHwCmd(unsigned char bCmd)\r
+{\r
+       // clear CDFULL/CCEMTY\r
+       USB->USBDevIntClr = CDFULL | CCEMTY;\r
+       // write command code\r
+       USB->USBCmdCode = 0x00000500 | (bCmd << 16);\r
+       Wait4DevInt(CCEMTY);\r
+}\r
+\r
+\r
+/**\r
+       Local function to send a command + data to the USB protocol engine\r
+\r
+       @param [in]     bCmd            Command to send\r
+       @param [in]     bData           Data to send\r
+ */\r
+static void USBHwCmdWrite(unsigned char bCmd, unsigned short bData)\r
+{\r
+       // write command code\r
+       USBHwCmd(bCmd);\r
+\r
+       // write command data\r
+       USB->USBCmdCode = 0x00000100 | (bData << 16);\r
+       Wait4DevInt(CCEMTY);\r
+}\r
+\r
+\r
+/**\r
+       Local function to send a command to the USB protocol engine and read data\r
+\r
+       @param [in]     bCmd            Command to send\r
+\r
+       @return the data\r
+ */\r
+static unsigned char USBHwCmdRead(unsigned char bCmd)\r
+{\r
+       // write command code\r
+       USBHwCmd(bCmd);\r
+\r
+       // get data\r
+       USB->USBCmdCode = 0x00000200 | (bCmd << 16);\r
+       Wait4DevInt(CDFULL);\r
+       return USB->USBCmdData;\r
+}\r
+\r
+\r
+/**\r
+       'Realizes' an endpoint, meaning that buffer space is reserved for\r
+       it. An endpoint needs to be realised before it can be used.\r
+\r
+       From experiments, it appears that a USB reset causes USBReEP to\r
+       re-initialise to 3 (= just the control endpoints).\r
+       However, a USB bus reset does not disturb the USBMaxPSize settings.\r
+\r
+       @param [in]     idx                     Endpoint index\r
+       @param [in] wMaxPSize   Maximum packet size for this endpoint\r
+ */\r
+static void USBHwEPRealize(int idx, unsigned short wMaxPSize)\r
+{\r
+       USB->USBReEP |= (1 << idx);\r
+       USB->USBEpInd = idx;\r
+       USB->USBMaxPSize = wMaxPSize;\r
+       Wait4DevInt(EP_RLZED);\r
+}\r
+\r
+\r
+/**\r
+       Enables or disables an endpoint\r
+\r
+       @param [in]     idx             Endpoint index\r
+       @param [in]     fEnable TRUE to enable, FALSE to disable\r
+ */\r
+static void USBHwEPEnable(int idx, BOOL fEnable)\r
+{\r
+       USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fEnable ? 0 : EP_DA);\r
+}\r
+\r
+\r
+/**\r
+       Configures an endpoint and enables it\r
+\r
+       @param [in]     bEP                             Endpoint number\r
+       @param [in]     wMaxPacketSize  Maximum packet size for this EP\r
+ */\r
+void USBHwEPConfig(unsigned char bEP, unsigned short wMaxPacketSize)\r
+{\r
+       int idx;\r
+\r
+       idx = EP2IDX(bEP);\r
+\r
+       // realise EP\r
+       USBHwEPRealize(idx, wMaxPacketSize);\r
+\r
+       // enable EP\r
+       USBHwEPEnable(idx, TRUE);\r
+}\r
+\r
+\r
+/**\r
+       Registers an endpoint event callback\r
+\r
+       @param [in]     bEP                             Endpoint number\r
+       @param [in]     pfnHandler              Callback function\r
+ */\r
+void USBHwRegisterEPIntHandler(unsigned char bEP, TFnEPIntHandler *pfnHandler)\r
+{\r
+       int idx;\r
+\r
+       idx = EP2IDX(bEP);\r
+\r
+       ASSERT(idx<32);\r
+\r
+       /* add handler to list of EP handlers */\r
+       _apfnEPIntHandlers[idx / 2] = pfnHandler;\r
+\r
+       /* enable EP interrupt */\r
+       USB->USBEpIntEn |= (1 << idx);\r
+       USB->USBDevIntEn |= EP_SLOW;\r
+\r
+       DBG("Registered handler for EP 0x%x\n", bEP);\r
+}\r
+\r
+\r
+/**\r
+       Registers an device status callback\r
+\r
+       @param [in]     pfnHandler      Callback function\r
+ */\r
+void USBHwRegisterDevIntHandler(TFnDevIntHandler *pfnHandler)\r
+{\r
+       _pfnDevIntHandler = pfnHandler;\r
+\r
+       // enable device interrupt\r
+       USB->USBDevIntEn |= DEV_STAT;\r
+\r
+       DBG("Registered handler for device status\n");\r
+}\r
+\r
+\r
+/**\r
+       Registers the frame callback\r
+\r
+       @param [in]     pfnHandler      Callback function\r
+ */\r
+void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler)\r
+{\r
+       _pfnFrameHandler = pfnHandler;\r
+\r
+       // enable device interrupt\r
+       USB->USBDevIntEn |= FRAME;\r
+\r
+       DBG("Registered handler for frame\n");\r
+}\r
+\r
+\r
+/**\r
+       Sets the USB address.\r
+\r
+       @param [in]     bAddr           Device address to set\r
+ */\r
+void USBHwSetAddress(unsigned char bAddr)\r
+{\r
+       USBHwCmdWrite(CMD_DEV_SET_ADDRESS, DEV_EN | bAddr);\r
+}\r
+\r
+\r
+/**\r
+       Connects or disconnects from the USB bus\r
+\r
+       @param [in]     fConnect        If TRUE, connect, otherwise disconnect\r
+ */\r
+void USBHwConnect(BOOL fConnect)\r
+{\r
+       USBHwCmdWrite(CMD_DEV_STATUS, fConnect ? CON : 0);\r
+}\r
+\r
+\r
+/**\r
+       Enables interrupt on NAK condition\r
+\r
+       For IN endpoints a NAK is generated when the host wants to read data\r
+       from the device, but none is available in the endpoint buffer.\r
+       For OUT endpoints a NAK is generated when the host wants to write data\r
+       to the device, but the endpoint buffer is still full.\r
+\r
+       The endpoint interrupt handlers can distinguish regular (ACK) interrupts\r
+       from NAK interrupt by checking the bits in their bEPStatus argument.\r
+\r
+       @param [in]     bIntBits        Bitmap indicating which NAK interrupts to enable\r
+ */\r
+void USBHwNakIntEnable(unsigned char bIntBits)\r
+{\r
+       USBHwCmdWrite(CMD_DEV_SET_MODE, bIntBits);\r
+}\r
+\r
+\r
+/**\r
+       Gets the status from a specific endpoint.\r
+\r
+       @param [in]     bEP             Endpoint number\r
+       @return Endpoint status byte (containing EP_STATUS_xxx bits)\r
+ */\r
+unsigned char  USBHwEPGetStatus(unsigned char bEP)\r
+{\r
+       int idx = EP2IDX(bEP);\r
+\r
+       return USBHwCmdRead(CMD_EP_SELECT | idx);\r
+}\r
+\r
+\r
+/**\r
+       Sets the stalled property of an endpoint\r
+\r
+       @param [in]     bEP             Endpoint number\r
+       @param [in]     fStall  TRUE to stall, FALSE to unstall\r
+ */\r
+void USBHwEPStall(unsigned char bEP, BOOL fStall)\r
+{\r
+       int idx = EP2IDX(bEP);\r
+\r
+       USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fStall ? EP_ST : 0);\r
+}\r
+\r
+\r
+/**\r
+       Writes data to an endpoint buffer\r
+\r
+       @param [in]     bEP             Endpoint number\r
+       @param [in]     pbBuf   Endpoint data\r
+       @param [in]     iLen    Number of bytes to write\r
+\r
+       @return TRUE if the data was successfully written or <0 in case of error.\r
+*/\r
+int USBHwEPWrite(unsigned char bEP, unsigned char *pbBuf, int iLen)\r
+{\r
+       int idx;\r
+\r
+       idx = EP2IDX(bEP);\r
+\r
+       // set write enable for specific endpoint\r
+       USB->USBCtrl = WR_EN | ((bEP & 0xF) << 2);\r
+\r
+       // set packet length\r
+       USB->USBTxPLen = iLen;\r
+\r
+       // write data\r
+       while (USB->USBCtrl & WR_EN) {\r
+               USB->USBTxData = (pbBuf[3] << 24) | (pbBuf[2] << 16) | (pbBuf[1] << 8) | pbBuf[0];\r
+               pbBuf += 4;\r
+       }\r
+\r
+       // select endpoint and validate buffer\r
+       USBHwCmd(CMD_EP_SELECT | idx);\r
+       USBHwCmd(CMD_EP_VALIDATE_BUFFER);\r
+\r
+       return iLen;\r
+}\r
+\r
+\r
+/**\r
+       Reads data from an endpoint buffer\r
+\r
+       @param [in]     bEP             Endpoint number\r
+       @param [in]     pbBuf   Endpoint data\r
+       @param [in]     iMaxLen Maximum number of bytes to read\r
+\r
+       @return the number of bytes available in the EP (possibly more than iMaxLen),\r
+       or <0 in case of error.\r
+ */\r
+int USBHwEPRead(unsigned char bEP, unsigned char *pbBuf, int iMaxLen)\r
+{\r
+       unsigned int i, idx;\r
+       unsigned long   dwData, dwLen;\r
+\r
+       idx = EP2IDX(bEP);\r
+\r
+       // set read enable bit for specific endpoint\r
+       USB->USBCtrl = RD_EN | ((bEP & 0xF) << 2);\r
+\r
+       // wait for PKT_RDY\r
+       do {\r
+               dwLen = USB->USBRxPLen;\r
+       } while ((dwLen & PKT_RDY) == 0);\r
+\r
+       // packet valid?\r
+       if ((dwLen & DV) == 0) {\r
+               return -1;\r
+       }\r
+\r
+       // get length\r
+       dwLen &= PKT_LNGTH_MASK;\r
+\r
+       // get data\r
+       dwData = 0;\r
+       for (i = 0; i < dwLen; i++) {\r
+               if ((i % 4) == 0) {\r
+                       dwData = USB->USBRxData;\r
+               }\r
+               if ((pbBuf != NULL) && ((int)i < iMaxLen)) {\r
+                       pbBuf[i] = dwData & 0xFF;\r
+               }\r
+               dwData >>= 8;\r
+       }\r
+\r
+       // make sure RD_EN is clear\r
+       USB->USBCtrl = 0;\r
+\r
+       // select endpoint and clear buffer\r
+       USBHwCmd(CMD_EP_SELECT | idx);\r
+       USBHwCmd(CMD_EP_CLEAR_BUFFER);\r
+\r
+       return dwLen;\r
+}\r
+\r
+\r
+/**\r
+       Sets the 'configured' state.\r
+\r
+       All registered endpoints are 'realised' and enabled, and the\r
+       'configured' bit is set in the device status register.\r
+\r
+       @param [in]     fConfigured     If TRUE, configure device, else unconfigure\r
+ */\r
+void USBHwConfigDevice(BOOL fConfigured)\r
+{\r
+       // set configured bit\r
+       USBHwCmdWrite(CMD_DEV_CONFIG, fConfigured ? CONF_DEVICE : 0);\r
+}\r
+\r
+\r
+/**\r
+       USB interrupt handler\r
+\r
+       @todo Get all 11 bits of frame number instead of just 8\r
+\r
+       Endpoint interrupts are mapped to the slow interrupt\r
+ */\r
+void USBHwISR(void)\r
+{\r
+       unsigned long   dwStatus;\r
+       unsigned long dwIntBit;\r
+       unsigned char   bEPStat, bDevStat, bStat;\r
+       int i;\r
+       unsigned short  wFrame;\r
+\r
+       // handle device interrupts\r
+       dwStatus = USB->USBDevIntSt;\r
+\r
+       // frame interrupt\r
+       if (dwStatus & FRAME) {\r
+               // clear int\r
+               USB->USBDevIntClr = FRAME;\r
+               // call handler\r
+               if (_pfnFrameHandler != NULL) {\r
+                       wFrame = USBHwCmdRead(CMD_DEV_READ_CUR_FRAME_NR);\r
+                       _pfnFrameHandler(wFrame);\r
+               }\r
+       }\r
+\r
+       // device status interrupt\r
+       if (dwStatus & DEV_STAT) {\r
+               /*      Clear DEV_STAT interrupt before reading DEV_STAT register.\r
+                       This prevents corrupted device status reads, see\r
+                       LPC2148 User manual revision 2, 25 july 2006.\r
+               */\r
+               USB->USBDevIntClr = DEV_STAT;\r
+               bDevStat = USBHwCmdRead(CMD_DEV_STATUS);\r
+               if (bDevStat & (CON_CH | SUS_CH | RST)) {\r
+                       // convert device status into something HW independent\r
+                       bStat = ((bDevStat & CON) ? DEV_STATUS_CONNECT : 0) |\r
+                                       ((bDevStat & SUS) ? DEV_STATUS_SUSPEND : 0) |\r
+                                       ((bDevStat & RST) ? DEV_STATUS_RESET : 0);\r
+                       // call handler\r
+                       if (_pfnDevIntHandler != NULL) {\r
+                               _pfnDevIntHandler(bStat);\r
+                       }\r
+               }\r
+       }\r
+\r
+       // endpoint interrupt\r
+       if (dwStatus & EP_SLOW) {\r
+               // clear EP_SLOW\r
+               USB->USBDevIntClr = EP_SLOW;\r
+               // check all endpoints\r
+               for (i = 0; i < 32; i++) {\r
+                       dwIntBit = (1 << i);\r
+                       if (USB->USBEpIntSt & dwIntBit) {\r
+                               // clear int (and retrieve status)\r
+                               USB->USBEpIntClr = dwIntBit;\r
+                               Wait4DevInt(CDFULL);\r
+                               bEPStat = USB->USBCmdData;\r
+                               // convert EP pipe stat into something HW independent\r
+                               bStat = ((bEPStat & EPSTAT_FE) ? EP_STATUS_DATA : 0) |\r
+                                               ((bEPStat & EPSTAT_ST) ? EP_STATUS_STALLED : 0) |\r
+                                               ((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) |\r
+                                               ((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) |\r
+                                               ((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0);\r
+                               // call handler\r
+                               if (_apfnEPIntHandlers[i / 2] != NULL) {\r
+                                       _apfnEPIntHandlers[i / 2](IDX2EP(i), bStat);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+\r
+\r
+/**\r
+       Initialises the USB hardware\r
+\r
+\r
+       @return TRUE if the hardware was successfully initialised\r
+ */\r
+BOOL USBHwInit(void)\r
+{\r
+       // P2.9 -> USB_CONNECT\r
+       PINCON->PINSEL4 &= ~0x000C0000;\r
+       PINCON->PINSEL4 |= 0x00040000;\r
+\r
+       // P1.18 -> USB_UP_LED\r
+       // P1.30 -> VBUS\r
+       PINCON->PINSEL3 &= ~0x30000030;\r
+       PINCON->PINSEL3 |= 0x20000010;\r
+\r
+       // P0.29 -> USB_D+\r
+       // P0.30 -> USB_D-\r
+       PINCON->PINSEL1 &= ~0x3C000000;\r
+       PINCON->PINSEL1 |= 0x14000000;\r
+\r
+       // enable PUSB\r
+       SC->PCONP |= (1 << 31);\r
+\r
+       USB->OTGClkCtrl = 0x12;                   /* Dev clock, AHB clock enable  */\r
+       while ((USB->OTGClkSt & 0x12) != 0x12);\r
+\r
+       // disable/clear all interrupts for now\r
+       USB->USBDevIntEn = 0;\r
+       USB->USBDevIntClr = 0xFFFFFFFF;\r
+       USB->USBDevIntPri = 0;\r
+\r
+       USB->USBEpIntEn = 0;\r
+       USB->USBEpIntClr = 0xFFFFFFFF;\r
+       USB->USBEpIntPri = 0;\r
+\r
+       // by default, only ACKs generate interrupts\r
+       USBHwNakIntEnable(0);\r
+\r
+       return TRUE;\r
+}\r
+\r
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.c.bak b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.c.bak
new file mode 100644 (file)
index 0000000..29de3de
--- /dev/null
@@ -0,0 +1,521 @@
+/*\r
+       LPCUSB, an USB device driver for LPC microcontrollers\r
+       Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)\r
+\r
+       Redistribution and use in source and binary forms, with or without\r
+       modification, are permitted provided that the following conditions are met:\r
+\r
+       1. Redistributions of source code must retain the above copyright\r
+          notice, this list of conditions and the following disclaimer.\r
+       2. Redistributions in binary form must reproduce the above copyright\r
+          notice, this list of conditions and the following disclaimer in the\r
+          documentation and/or other materials provided with the distribution.\r
+       3. The name of the author may not be used to endorse or promote products\r
+          derived from this software without specific prior written permission.\r
+\r
+       THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+       IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
+       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+       THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*/\r
+\r
+\r
+/** @file\r
+       USB hardware layer\r
+ */\r
+\r
+\r
+#include "usbdebug.h"\r
+#include "usbhw_lpc.h"\r
+#include "usbapi.h"\r
+\r
+/** Installed device interrupt handler */\r
+static TFnDevIntHandler *_pfnDevIntHandler = NULL;\r
+/** Installed endpoint interrupt handlers */\r
+static TFnEPIntHandler *_apfnEPIntHandlers[16];\r
+/** Installed frame interrupt handlers */\r
+static TFnFrameHandler *_pfnFrameHandler = NULL;\r
+\r
+/** convert from endpoint address to endpoint index */\r
+#define EP2IDX(bEP)    ((((bEP)&0xF)<<1)|(((bEP)&0x80)>>7))\r
+/** convert from endpoint index to endpoint address */\r
+#define IDX2EP(idx)    ((((idx)<<7)&0x80)|(((idx)>>1)&0xF))\r
+\r
+\r
+\r
+/**\r
+       Local function to wait for a device interrupt (and clear it)\r
+\r
+       @param [in]     dwIntr          Bitmask of interrupts to wait for\r
+ */\r
+static void Wait4DevInt(unsigned long dwIntr)\r
+{\r
+       // wait for specific interrupt\r
+       while ((USB->USBDevIntSt & dwIntr) != dwIntr);\r
+       // clear the interrupt bits\r
+       USB->USBDevIntClr = dwIntr;\r
+}\r
+\r
+\r
+/**\r
+       Local function to send a command to the USB protocol engine\r
+\r
+       @param [in]     bCmd            Command to send\r
+ */\r
+static void USBHwCmd(unsigned char bCmd)\r
+{\r
+       // clear CDFULL/CCEMTY\r
+       USB->USBDevIntClr = CDFULL | CCEMTY;\r
+       // write command code\r
+       USB->USBCmdCode = 0x00000500 | (bCmd << 16);\r
+       Wait4DevInt(CCEMTY);\r
+}\r
+\r
+\r
+/**\r
+       Local function to send a command + data to the USB protocol engine\r
+\r
+       @param [in]     bCmd            Command to send\r
+       @param [in]     bData           Data to send\r
+ */\r
+static void USBHwCmdWrite(unsigned char bCmd, unsigned short bData)\r
+{\r
+       // write command code\r
+       USBHwCmd(bCmd);\r
+\r
+       // write command data\r
+       USB->USBCmdCode = 0x00000100 | (bData << 16);\r
+       Wait4DevInt(CCEMTY);\r
+}\r
+\r
+\r
+/**\r
+       Local function to send a command to the USB protocol engine and read data\r
+\r
+       @param [in]     bCmd            Command to send\r
+\r
+       @return the data\r
+ */\r
+static unsigned char USBHwCmdRead(unsigned char bCmd)\r
+{\r
+       // write command code\r
+       USBHwCmd(bCmd);\r
+\r
+       // get data\r
+       USB->USBCmdCode = 0x00000200 | (bCmd << 16);\r
+       Wait4DevInt(CDFULL);\r
+       return USB->USBCmdData;\r
+}\r
+\r
+\r
+/**\r
+       'Realizes' an endpoint, meaning that buffer space is reserved for\r
+       it. An endpoint needs to be realised before it can be used.\r
+\r
+       From experiments, it appears that a USB reset causes USBReEP to\r
+       re-initialise to 3 (= just the control endpoints).\r
+       However, a USB bus reset does not disturb the USBMaxPSize settings.\r
+\r
+       @param [in]     idx                     Endpoint index\r
+       @param [in] wMaxPSize   Maximum packet size for this endpoint\r
+ */\r
+static void USBHwEPRealize(int idx, unsigned short wMaxPSize)\r
+{\r
+       USB->USBReEP |= (1 << idx);\r
+       USB->USBEpInd = idx;\r
+       USB->USBMaxPSize = wMaxPSize;\r
+       Wait4DevInt(EP_RLZED);\r
+}\r
+\r
+\r
+/**\r
+       Enables or disables an endpoint\r
+\r
+       @param [in]     idx             Endpoint index\r
+       @param [in]     fEnable TRUE to enable, FALSE to disable\r
+ */\r
+static void USBHwEPEnable(int idx, BOOL fEnable)\r
+{\r
+       USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fEnable ? 0 : EP_DA);\r
+}\r
+\r
+\r
+/**\r
+       Configures an endpoint and enables it\r
+\r
+       @param [in]     bEP                             Endpoint number\r
+       @param [in]     wMaxPacketSize  Maximum packet size for this EP\r
+ */\r
+void USBHwEPConfig(unsigned char bEP, unsigned short wMaxPacketSize)\r
+{\r
+       int idx;\r
+\r
+       idx = EP2IDX(bEP);\r
+\r
+       // realise EP\r
+       USBHwEPRealize(idx, wMaxPacketSize);\r
+\r
+       // enable EP\r
+       USBHwEPEnable(idx, TRUE);\r
+}\r
+\r
+\r
+/**\r
+       Registers an endpoint event callback\r
+\r
+       @param [in]     bEP                             Endpoint number\r
+       @param [in]     pfnHandler              Callback function\r
+ */\r
+void USBHwRegisterEPIntHandler(unsigned char bEP, TFnEPIntHandler *pfnHandler)\r
+{\r
+       int idx;\r
+\r
+       idx = EP2IDX(bEP);\r
+\r
+       ASSERT(idx<32);\r
+\r
+       /* add handler to list of EP handlers */\r
+       _apfnEPIntHandlers[idx / 2] = pfnHandler;\r
+\r
+       /* enable EP interrupt */\r
+       USB->USBEpIntEn |= (1 << idx);\r
+       USB->USBDevIntEn |= EP_SLOW;\r
+\r
+       DBG("Registered handler for EP 0x%x\n", bEP);\r
+}\r
+\r
+\r
+/**\r
+       Registers an device status callback\r
+\r
+       @param [in]     pfnHandler      Callback function\r
+ */\r
+void USBHwRegisterDevIntHandler(TFnDevIntHandler *pfnHandler)\r
+{\r
+       _pfnDevIntHandler = pfnHandler;\r
+\r
+       // enable device interrupt\r
+       USB->USBDevIntEn |= DEV_STAT;\r
+\r
+       DBG("Registered handler for device status\n");\r
+}\r
+\r
+\r
+/**\r
+       Registers the frame callback\r
+\r
+       @param [in]     pfnHandler      Callback function\r
+ */\r
+void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler)\r
+{\r
+       _pfnFrameHandler = pfnHandler;\r
+\r
+       // enable device interrupt\r
+       USB->USBDevIntEn |= FRAME;\r
+\r
+       DBG("Registered handler for frame\n");\r
+}\r
+\r
+\r
+/**\r
+       Sets the USB address.\r
+\r
+       @param [in]     bAddr           Device address to set\r
+ */\r
+void USBHwSetAddress(unsigned char bAddr)\r
+{\r
+       USBHwCmdWrite(CMD_DEV_SET_ADDRESS, DEV_EN | bAddr);\r
+}\r
+\r
+\r
+/**\r
+       Connects or disconnects from the USB bus\r
+\r
+       @param [in]     fConnect        If TRUE, connect, otherwise disconnect\r
+ */\r
+void USBHwConnect(BOOL fConnect)\r
+{\r
+       USBHwCmdWrite(CMD_DEV_STATUS, fConnect ? CON : 0);\r
+}\r
+\r
+\r
+/**\r
+       Enables interrupt on NAK condition\r
+\r
+       For IN endpoints a NAK is generated when the host wants to read data\r
+       from the device, but none is available in the endpoint buffer.\r
+       For OUT endpoints a NAK is generated when the host wants to write data\r
+       to the device, but the endpoint buffer is still full.\r
+\r
+       The endpoint interrupt handlers can distinguish regular (ACK) interrupts\r
+       from NAK interrupt by checking the bits in their bEPStatus argument.\r
+\r
+       @param [in]     bIntBits        Bitmap indicating which NAK interrupts to enable\r
+ */\r
+void USBHwNakIntEnable(unsigned char bIntBits)\r
+{\r
+       USBHwCmdWrite(CMD_DEV_SET_MODE, bIntBits);\r
+}\r
+\r
+\r
+/**\r
+       Gets the status from a specific endpoint.\r
+\r
+       @param [in]     bEP             Endpoint number\r
+       @return Endpoint status byte (containing EP_STATUS_xxx bits)\r
+ */\r
+unsigned char  USBHwEPGetStatus(unsigned char bEP)\r
+{\r
+       int idx = EP2IDX(bEP);\r
+\r
+       return USBHwCmdRead(CMD_EP_SELECT | idx);\r
+}\r
+\r
+\r
+/**\r
+       Sets the stalled property of an endpoint\r
+\r
+       @param [in]     bEP             Endpoint number\r
+       @param [in]     fStall  TRUE to stall, FALSE to unstall\r
+ */\r
+void USBHwEPStall(unsigned char bEP, BOOL fStall)\r
+{\r
+       int idx = EP2IDX(bEP);\r
+\r
+       USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fStall ? EP_ST : 0);\r
+}\r
+\r
+\r
+/**\r
+       Writes data to an endpoint buffer\r
+\r
+       @param [in]     bEP             Endpoint number\r
+       @param [in]     pbBuf   Endpoint data\r
+       @param [in]     iLen    Number of bytes to write\r
+\r
+       @return TRUE if the data was successfully written or <0 in case of error.\r
+*/\r
+int USBHwEPWrite(unsigned char bEP, unsigned char *pbBuf, int iLen)\r
+{\r
+       int idx;\r
+\r
+       idx = EP2IDX(bEP);\r
+\r
+       // set write enable for specific endpoint\r
+       USB->USBCtrl = WR_EN | ((bEP & 0xF) << 2);\r
+\r
+       // set packet length\r
+       USB->USBTxPLen = iLen;\r
+\r
+       // write data\r
+       while (USB->USBCtrl & WR_EN) {\r
+               USB->USBTxData = (pbBuf[3] << 24) | (pbBuf[2] << 16) | (pbBuf[1] << 8) | pbBuf[0];\r
+               pbBuf += 4;\r
+       }\r
+\r
+       // select endpoint and validate buffer\r
+       USBHwCmd(CMD_EP_SELECT | idx);\r
+       USBHwCmd(CMD_EP_VALIDATE_BUFFER);\r
+\r
+       return iLen;\r
+}\r
+\r
+\r
+/**\r
+       Reads data from an endpoint buffer\r
+\r
+       @param [in]     bEP             Endpoint number\r
+       @param [in]     pbBuf   Endpoint data\r
+       @param [in]     iMaxLen Maximum number of bytes to read\r
+\r
+       @return the number of bytes available in the EP (possibly more than iMaxLen),\r
+       or <0 in case of error.\r
+ */\r
+int USBHwEPRead(unsigned char bEP, unsigned char *pbBuf, int iMaxLen)\r
+{\r
+       unsigned int i, idx;\r
+       unsigned long   dwData, dwLen;\r
+\r
+       idx = EP2IDX(bEP);\r
+\r
+       // set read enable bit for specific endpoint\r
+       USB->USBCtrl = RD_EN | ((bEP & 0xF) << 2);\r
+\r
+       // wait for PKT_RDY\r
+       do {\r
+               dwLen = USB->USBRxPLen;\r
+       } while ((dwLen & PKT_RDY) == 0);\r
+\r
+       // packet valid?\r
+       if ((dwLen & DV) == 0) {\r
+               return -1;\r
+       }\r
+\r
+       // get length\r
+       dwLen &= PKT_LNGTH_MASK;\r
+\r
+       // get data\r
+       dwData = 0;\r
+       for (i = 0; i < dwLen; i++) {\r
+               if ((i % 4) == 0) {\r
+                       dwData = USB->USBRxData;\r
+               }\r
+               if ((pbBuf != NULL) && (i < iMaxLen)) {\r
+                       pbBuf[i] = dwData & 0xFF;\r
+               }\r
+               dwData >>= 8;\r
+       }\r
+\r
+       // make sure RD_EN is clear\r
+       USB->USBCtrl = 0;\r
+\r
+       // select endpoint and clear buffer\r
+       USBHwCmd(CMD_EP_SELECT | idx);\r
+       USBHwCmd(CMD_EP_CLEAR_BUFFER);\r
+\r
+       return dwLen;\r
+}\r
+\r
+\r
+/**\r
+       Sets the 'configured' state.\r
+\r
+       All registered endpoints are 'realised' and enabled, and the\r
+       'configured' bit is set in the device status register.\r
+\r
+       @param [in]     fConfigured     If TRUE, configure device, else unconfigure\r
+ */\r
+void USBHwConfigDevice(BOOL fConfigured)\r
+{\r
+       // set configured bit\r
+       USBHwCmdWrite(CMD_DEV_CONFIG, fConfigured ? CONF_DEVICE : 0);\r
+}\r
+\r
+\r
+/**\r
+       USB interrupt handler\r
+\r
+       @todo Get all 11 bits of frame number instead of just 8\r
+\r
+       Endpoint interrupts are mapped to the slow interrupt\r
+ */\r
+void USBHwISR(void)\r
+{\r
+       unsigned long   dwStatus;\r
+       unsigned long dwIntBit;\r
+       unsigned char   bEPStat, bDevStat, bStat;\r
+       int i;\r
+       unsigned short  wFrame;\r
+\r
+       // handle device interrupts\r
+       dwStatus = USB->USBDevIntSt;\r
+\r
+       // frame interrupt\r
+       if (dwStatus & FRAME) {\r
+               // clear int\r
+               USB->USBDevIntClr = FRAME;\r
+               // call handler\r
+               if (_pfnFrameHandler != NULL) {\r
+                       wFrame = USBHwCmdRead(CMD_DEV_READ_CUR_FRAME_NR);\r
+                       _pfnFrameHandler(wFrame);\r
+               }\r
+       }\r
+\r
+       // device status interrupt\r
+       if (dwStatus & DEV_STAT) {\r
+               /*      Clear DEV_STAT interrupt before reading DEV_STAT register.\r
+                       This prevents corrupted device status reads, see\r
+                       LPC2148 User manual revision 2, 25 july 2006.\r
+               */\r
+               USB->USBDevIntClr = DEV_STAT;\r
+               bDevStat = USBHwCmdRead(CMD_DEV_STATUS);\r
+               if (bDevStat & (CON_CH | SUS_CH | RST)) {\r
+                       // convert device status into something HW independent\r
+                       bStat = ((bDevStat & CON) ? DEV_STATUS_CONNECT : 0) |\r
+                                       ((bDevStat & SUS) ? DEV_STATUS_SUSPEND : 0) |\r
+                                       ((bDevStat & RST) ? DEV_STATUS_RESET : 0);\r
+                       // call handler\r
+                       if (_pfnDevIntHandler != NULL) {\r
+                               _pfnDevIntHandler(bStat);\r
+                       }\r
+               }\r
+       }\r
+\r
+       // endpoint interrupt\r
+       if (dwStatus & EP_SLOW) {\r
+               // clear EP_SLOW\r
+               USB->USBDevIntClr = EP_SLOW;\r
+               // check all endpoints\r
+               for (i = 0; i < 32; i++) {\r
+                       dwIntBit = (1 << i);\r
+                       if (USB->USBEpIntSt & dwIntBit) {\r
+                               // clear int (and retrieve status)\r
+                               USB->USBEpIntClr = dwIntBit;\r
+                               Wait4DevInt(CDFULL);\r
+                               bEPStat = USB->USBCmdData;\r
+                               // convert EP pipe stat into something HW independent\r
+                               bStat = ((bEPStat & EPSTAT_FE) ? EP_STATUS_DATA : 0) |\r
+                                               ((bEPStat & EPSTAT_ST) ? EP_STATUS_STALLED : 0) |\r
+                                               ((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) |\r
+                                               ((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) |\r
+                                               ((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0);\r
+                               // call handler\r
+                               if (_apfnEPIntHandlers[i / 2] != NULL) {\r
+                                       _apfnEPIntHandlers[i / 2](IDX2EP(i), bStat);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+\r
+\r
+/**\r
+       Initialises the USB hardware\r
+\r
+\r
+       @return TRUE if the hardware was successfully initialised\r
+ */\r
+BOOL USBHwInit(void)\r
+{\r
+       // P2.9 -> USB_CONNECT\r
+       PINCON->PINSEL4 &= ~0x000C0000;\r
+       PINCON->PINSEL4 |= 0x00040000;\r
+\r
+       // P1.18 -> USB_UP_LED\r
+       // P1.30 -> VBUS\r
+       PINCON->PINSEL3 &= ~0x30000030;\r
+       PINCON->PINSEL3 |= 0x20000010;\r
+\r
+       // P0.29 -> USB_D+\r
+       // P0.30 -> USB_D-\r
+       PINCON->PINSEL1 &= ~0x3C000000;\r
+       PINCON->PINSEL1 |= 0x14000000;\r
+\r
+       // enable PUSB\r
+       SC->PCONP |= (1 << 31);\r
+\r
+       USB->OTGClkCtrl = 0x12;                   /* Dev clock, AHB clock enable  */\r
+       while ((USB->OTGClkSt & 0x12) != 0x12);\r
+\r
+       // disable/clear all interrupts for now\r
+       USB->USBDevIntEn = 0;\r
+       USB->USBDevIntClr = 0xFFFFFFFF;\r
+       USB->USBDevIntPri = 0;\r
+\r
+       USB->USBEpIntEn = 0;\r
+       USB->USBEpIntClr = 0xFFFFFFFF;\r
+       USB->USBEpIntPri = 0;\r
+\r
+       // by default, only ACKs generate interrupts\r
+       USBHwNakIntEnable(0);\r
+\r
+       return TRUE;\r
+}\r
+\r
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.h b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbhw_lpc.h
new file mode 100644 (file)
index 0000000..2a4de79
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+       LPCUSB, an USB device driver for LPC microcontrollers   
+       Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are met:
+
+       1. Redistributions of source code must retain the above copyright
+          notice, this list of conditions and the following disclaimer.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, this list of conditions and the following disclaimer in the
+          documentation and/or other materials provided with the distribution.
+       3. The name of the author may not be used to endorse or promote products
+          derived from this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+       IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
+       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+       THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/**
+       Hardware definitions for the LPC176x USB controller
+
+       These are private to the usbhw module
+*/
+
+// CodeRed - pull in defines from NXP header file
+//#include "NXP\LPC17xx\LPC17xx.h"
+#include "LPC17xx.h"
+
+
+// CodeRed - these registers have been renamed on LPC176x
+#define USBReEP USBReEp
+#define OTG_CLK_CTRL USBClkCtrl
+#define OTG_CLK_STAT USBClkSt
+
+/* USBIntSt bits */
+#define USB_INT_REQ_LP                         (1<<0)
+#define USB_INT_REQ_HP                         (1<<1)
+#define USB_INT_REQ_DMA                                (1<<2)
+#define USB_need_clock                         (1<<8)
+#define EN_USB_BITS                                    (1<<31)
+
+/* USBDevInt... bits */
+#define FRAME                                          (1<<0)
+#define EP_FAST                                                (1<<1)
+#define EP_SLOW                                                (1<<2)
+#define DEV_STAT                                       (1<<3)
+#define CCEMTY                                         (1<<4)
+#define CDFULL                                         (1<<5)
+#define RxENDPKT                                       (1<<6)
+#define TxENDPKT                                       (1<<7)
+#define EP_RLZED                                       (1<<8)
+#define ERR_INT                                                (1<<9)
+
+/* USBRxPLen bits */
+#define PKT_LNGTH                                      (1<<0)
+#define PKT_LNGTH_MASK                         0x3FF
+#define DV                                                     (1<<10)
+#define PKT_RDY                                                (1<<11)
+
+/* USBCtrl bits */
+#define RD_EN                                          (1<<0)
+#define WR_EN                                          (1<<1)
+#define LOG_ENDPOINT                           (1<<2)
+
+/* protocol engine command codes */
+       /* device commands */
+#define CMD_DEV_SET_ADDRESS                    0xD0
+#define CMD_DEV_CONFIG                         0xD8
+#define CMD_DEV_SET_MODE                       0xF3
+#define CMD_DEV_READ_CUR_FRAME_NR      0xF5
+#define CMD_DEV_READ_TEST_REG          0xFD
+#define CMD_DEV_STATUS                         0xFE            /* read/write */
+#define CMD_DEV_GET_ERROR_CODE         0xFF
+#define CMD_DEV_READ_ERROR_STATUS      0xFB
+       /* endpoint commands */
+#define CMD_EP_SELECT                          0x00
+#define CMD_EP_SELECT_CLEAR                    0x40
+#define CMD_EP_SET_STATUS                      0x40
+#define CMD_EP_CLEAR_BUFFER                    0xF2
+#define CMD_EP_VALIDATE_BUFFER         0xFA
+
+/* set address command */
+#define DEV_ADDR                                       (1<<0)
+#define DEV_EN                                         (1<<7)
+
+/* configure device command */
+#define CONF_DEVICE                                    (1<<0)
+
+/* set mode command */
+#define AP_CLK                                         (1<<0)
+#define INAK_CI                                                (1<<1)
+#define INAK_CO                                                (1<<2)
+#define INAK_II                                                (1<<3)
+#define INAK_IO                                                (1<<4)
+#define INAK_BI                                                (1<<5)
+#define INAK_BO                                                (1<<6)
+
+/* set get device status command */
+#define CON                                                    (1<<0)
+#define CON_CH                                         (1<<1)
+#define SUS                                                    (1<<2)
+#define SUS_CH                                         (1<<3)
+#define RST                                                    (1<<4)
+
+/* get error code command */
+// ...
+
+/* Select Endpoint command read bits */
+#define EPSTAT_FE                                      (1<<0)
+#define EPSTAT_ST                                      (1<<1)
+#define EPSTAT_STP                                     (1<<2)
+#define EPSTAT_PO                                      (1<<3)
+#define EPSTAT_EPN                                     (1<<4)
+#define EPSTAT_B1FULL                          (1<<5)
+#define EPSTAT_B2FULL                          (1<<6)
+
+/* CMD_EP_SET_STATUS command */
+#define EP_ST                                          (1<<0)
+#define EP_DA                                          (1<<5)
+#define EP_RF_MO                                       (1<<6)
+#define EP_CND_ST                                      (1<<7)
+
+/* read error status command */
+#define PID_ERR                                                (1<<0)
+#define UEPKT                                          (1<<1)
+#define DCRC                                           (1<<2)
+#define TIMEOUT                                                (1<<3)
+#define EOP                                                    (1<<4)
+#define B_OVRN                                         (1<<5)
+#define BTSTF                                          (1<<6)
+#define TGL_ERR                                                (1<<7)
+
+
+
+
+
+
+
+
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbinit.c b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbinit.c
new file mode 100644 (file)
index 0000000..8bb7183
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+       LPCUSB, an USB device driver for LPC microcontrollers   
+       Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are met:
+
+       1. Redistributions of source code must retain the above copyright
+          notice, this list of conditions and the following disclaimer.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, this list of conditions and the following disclaimer in the
+          documentation and/or other materials provided with the distribution.
+       3. The name of the author may not be used to endorse or promote products
+          derived from this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+       IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
+       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+       THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/** @file
+       USB stack initialisation
+ */
+
+
+#include "usbdebug.h"
+#include "usbapi.h"
+
+
+/** data storage area for standard requests */
+static unsigned char   abStdReqData[8];
+
+
+/**
+       USB reset handler
+       
+       @param [in] bDevStatus  Device status
+ */
+static void HandleUsbReset(unsigned char bDevStatus)
+{
+       if (bDevStatus & DEV_STATUS_RESET) {
+               DBG("\n!");
+       }
+}
+
+
+/**
+       Initialises the USB hardware and sets up the USB stack by
+       installing default callbacks.
+       
+       @return TRUE if initialisation was successful
+ */
+BOOL USBInit(void)
+{
+       // init hardware
+       USBHwInit();
+       
+       // register bus reset handler
+       USBHwRegisterDevIntHandler(HandleUsbReset);
+       
+       // register control transfer handler on EP0
+       USBHwRegisterEPIntHandler(0x00, USBHandleControlTransfer);
+       USBHwRegisterEPIntHandler(0x80, USBHandleControlTransfer);
+       
+       // setup control endpoints
+       USBHwEPConfig(0x00, MAX_PACKET_SIZE0);
+       USBHwEPConfig(0x80, MAX_PACKET_SIZE0);
+       
+       // register standard request handler
+       USBRegisterRequestHandler(REQTYPE_TYPE_STANDARD, USBHandleStandardRequest, abStdReqData);
+
+       return TRUE;
+}
+
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbstdreq.c b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbstdreq.c
new file mode 100644 (file)
index 0000000..05e58b4
--- /dev/null
@@ -0,0 +1,430 @@
+/*\r
+       LPCUSB, an USB device driver for LPC microcontrollers   \r
+       Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)\r
+\r
+       Redistribution and use in source and binary forms, with or without\r
+       modification, are permitted provided that the following conditions are met:\r
+\r
+       1. Redistributions of source code must retain the above copyright\r
+          notice, this list of conditions and the following disclaimer.\r
+       2. Redistributions in binary form must reproduce the above copyright\r
+          notice, this list of conditions and the following disclaimer in the\r
+          documentation and/or other materials provided with the distribution.\r
+       3. The name of the author may not be used to endorse or promote products\r
+          derived from this software without specific prior written permission.\r
+\r
+       THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+       IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, \r
+       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
+       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+       THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*/\r
+\r
+\r
+/** @file\r
+       Standard request handler.\r
+       \r
+       This modules handles the 'chapter 9' processing, specifically the\r
+       standard device requests in table 9-3 from the universal serial bus\r
+       specification revision 2.0\r
+       \r
+       Specific types of devices may specify additional requests (for example\r
+       HID devices add a GET_DESCRIPTOR request for interfaces), but they\r
+       will not be part of this module.\r
+\r
+       @todo some requests have to return a request error if device not configured:\r
+       @todo GET_INTERFACE, GET_STATUS, SET_INTERFACE, SYNCH_FRAME\r
+       @todo this applies to the following if endpoint != 0:\r
+       @todo SET_FEATURE, GET_FEATURE \r
+*/\r
+\r
+#include "usbdebug.h"\r
+#include "usbstruct.h"\r
+#include "usbapi.h"\r
+\r
+#define MAX_DESC_HANDLERS      4               /**< device, interface, endpoint, other */\r
+\r
+\r
+/* general descriptor field offsets */\r
+#define DESC_bLength                                   0       /**< length offset */\r
+#define DESC_bDescriptorType                   1       /**< descriptor type offset */  \r
+\r
+/* config descriptor field offsets */\r
+#define CONF_DESC_wTotalLength                 2       /**< total length offset */\r
+#define CONF_DESC_bConfigurationValue  5       /**< configuration value offset */      \r
+#define CONF_DESC_bmAttributes                 7       /**< configuration characteristics */\r
+\r
+/* interface descriptor field offsets */\r
+#define INTF_DESC_bAlternateSetting            3       /**< alternate setting offset */\r
+\r
+/* endpoint descriptor field offsets */\r
+#define ENDP_DESC_bEndpointAddress             2       /**< endpoint address offset */\r
+#define ENDP_DESC_wMaxPacketSize               4       /**< maximum packet size offset */\r
+\r
+\r
+/** Currently selected configuration */\r
+static unsigned char                           bConfiguration = 0;\r
+/** Installed custom request handler */\r
+static TFnHandleRequest        *pfnHandleCustomReq = NULL;\r
+/** Pointer to registered descriptors */\r
+static const unsigned char                     *pabDescrip = NULL;\r
+\r
+\r
+/**\r
+       Registers a pointer to a descriptor block containing all descriptors\r
+       for the device.\r
+\r
+       @param [in]     pabDescriptors  The descriptor byte array\r
+ */\r
+void USBRegisterDescriptors(const unsigned char *pabDescriptors)\r
+{\r
+       pabDescrip = pabDescriptors;\r
+}\r
+\r
+\r
+/**\r
+       Parses the list of installed USB descriptors and attempts to find\r
+       the specified USB descriptor.\r
+               \r
+       @param [in]             wTypeIndex      Type and index of the descriptor\r
+       @param [in]             wLangID         Language ID of the descriptor (currently unused)\r
+       @param [out]    *piLen          Descriptor length\r
+       @param [out]    *ppbData        Descriptor data\r
+       \r
+       @return TRUE if the descriptor was found, FALSE otherwise\r
+ */\r
+BOOL USBGetDescriptor(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData)\r
+{\r
+       unsigned char   bType, bIndex;\r
+       unsigned char   *pab;\r
+       int iCurIndex;\r
+       \r
+       ASSERT(pabDescrip != NULL);\r
+\r
+       bType = GET_DESC_TYPE(wTypeIndex);\r
+       bIndex = GET_DESC_INDEX(wTypeIndex);\r
+       \r
+       pab = (unsigned char *)pabDescrip;\r
+       iCurIndex = 0;\r
+       \r
+       while (pab[DESC_bLength] != 0) {\r
+               if (pab[DESC_bDescriptorType] == bType) {\r
+                       if (iCurIndex == bIndex) {\r
+                               // set data pointer\r
+                               *ppbData = pab;\r
+                               // get length from structure\r
+                               if (bType == DESC_CONFIGURATION) {\r
+                                       // configuration descriptor is an exception, length is at offset 2 and 3\r
+                                       *piLen =        (pab[CONF_DESC_wTotalLength]) |\r
+                                                               (pab[CONF_DESC_wTotalLength + 1] << 8);\r
+                               }\r
+                               else {\r
+                                       // normally length is at offset 0\r
+                                       *piLen = pab[DESC_bLength];\r
+                               }\r
+                               return TRUE;\r
+                       }\r
+                       iCurIndex++;\r
+               }\r
+               // skip to next descriptor\r
+               pab += pab[DESC_bLength];\r
+       }\r
+       // nothing found\r
+       DBG("Desc %x not found!\n", wTypeIndex);\r
+       return FALSE;\r
+}\r
+\r
+\r
+/**\r
+       Configures the device according to the specified configuration index and\r
+       alternate setting by parsing the installed USB descriptor list.\r
+       A configuration index of 0 unconfigures the device.\r
+               \r
+       @param [in]             bConfigIndex    Configuration index\r
+       @param [in]             bAltSetting             Alternate setting number\r
+       \r
+       @todo function always returns TRUE, add stricter checking?\r
+       \r
+       @return TRUE if successfully configured, FALSE otherwise\r
+ */\r
+static BOOL USBSetConfiguration(unsigned char bConfigIndex, unsigned char bAltSetting)\r
+{\r
+       unsigned char   *pab;\r
+       unsigned char   bCurConfig, bCurAltSetting;\r
+       unsigned char   bEP;\r
+       unsigned short  wMaxPktSize;\r
+       \r
+       ASSERT(pabDescrip != NULL);\r
+\r
+       if (bConfigIndex == 0) {\r
+               // unconfigure device\r
+               USBHwConfigDevice(FALSE);\r
+       }\r
+       else {\r
+               // configure endpoints for this configuration/altsetting\r
+               pab = (unsigned char *)pabDescrip;\r
+               bCurConfig = 0xFF;\r
+               bCurAltSetting = 0xFF;\r
+\r
+               while (pab[DESC_bLength] != 0) {\r
+\r
+                       switch (pab[DESC_bDescriptorType]) {\r
+\r
+                       case DESC_CONFIGURATION:\r
+                               // remember current configuration index\r
+                               bCurConfig = pab[CONF_DESC_bConfigurationValue];\r
+                               break;\r
+\r
+                       case DESC_INTERFACE:\r
+                               // remember current alternate setting\r
+                               bCurAltSetting = pab[INTF_DESC_bAlternateSetting];\r
+                               break;\r
+\r
+                       case DESC_ENDPOINT:\r
+                               if ((bCurConfig == bConfigIndex) &&\r
+                                       (bCurAltSetting == bAltSetting)) {\r
+                                       // endpoint found for desired config and alternate setting\r
+                                       bEP = pab[ENDP_DESC_bEndpointAddress];\r
+                                       wMaxPktSize =   (pab[ENDP_DESC_wMaxPacketSize]) |\r
+                                                                       (pab[ENDP_DESC_wMaxPacketSize + 1] << 8);\r
+                                       // configure endpoint\r
+                                       USBHwEPConfig(bEP, wMaxPktSize);\r
+                               }\r
+                               break;\r
+\r
+                       default:\r
+                               break;\r
+                       }\r
+                       // skip to next descriptor\r
+                       pab += pab[DESC_bLength];\r
+               }\r
+               \r
+               // configure device\r
+               USBHwConfigDevice(TRUE);\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
+\r
+/**\r
+       Local function to handle a standard device request\r
+               \r
+       @param [in]             pSetup          The setup packet\r
+       @param [in,out] *piLen          Pointer to data length\r
+       @param [in,out] ppbData         Data buffer.\r
+\r
+       @return TRUE if the request was handled successfully\r
+ */\r
+static BOOL HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)\r
+{\r
+       unsigned char   *pbData = *ppbData;\r
+\r
+       switch (pSetup->bRequest) {\r
+       \r
+       case REQ_GET_STATUS:\r
+               // bit 0: self-powered\r
+               // bit 1: remote wakeup = not supported\r
+               pbData[0] = 0;\r
+               pbData[1] = 0;\r
+               *piLen = 2;\r
+               break;\r
+               \r
+       case REQ_SET_ADDRESS:\r
+               USBHwSetAddress(pSetup->wValue);\r
+               break;\r
+\r
+       case REQ_GET_DESCRIPTOR:\r
+               DBG("D%x", pSetup->wValue);\r
+               return USBGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData);\r
+\r
+       case REQ_GET_CONFIGURATION:\r
+               // indicate if we are configured\r
+               pbData[0] = bConfiguration;\r
+               *piLen = 1;\r
+               break;\r
+\r
+       case REQ_SET_CONFIGURATION:\r
+               if (!USBSetConfiguration(pSetup->wValue & 0xFF, 0)) {\r
+                       DBG("USBSetConfiguration failed!\n");\r
+                       return FALSE;\r
+               }\r
+               // configuration successful, update current configuration\r
+               bConfiguration = pSetup->wValue & 0xFF; \r
+               break;\r
+\r
+       case REQ_CLEAR_FEATURE:\r
+       case REQ_SET_FEATURE:\r
+               if (pSetup->wValue == FEA_REMOTE_WAKEUP) {\r
+                       // put DEVICE_REMOTE_WAKEUP code here\r
+               }\r
+               if (pSetup->wValue == FEA_TEST_MODE) {\r
+                       // put TEST_MODE code here\r
+               }\r
+               return FALSE;\r
+\r
+       case REQ_SET_DESCRIPTOR:\r
+               DBG("Device req %d not implemented\n", pSetup->bRequest);\r
+               return FALSE;\r
+\r
+       default:\r
+               DBG("Illegal device req %d\n", pSetup->bRequest);\r
+               return FALSE;\r
+       }\r
+       \r
+       return TRUE;\r
+}\r
+\r
+\r
+/**\r
+       Local function to handle a standard interface request\r
+               \r
+       @param [in]             pSetup          The setup packet\r
+       @param [in,out] *piLen          Pointer to data length\r
+       @param [in]             ppbData         Data buffer.\r
+\r
+       @return TRUE if the request was handled successfully\r
+ */\r
+static BOOL HandleStdInterfaceReq(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)\r
+{\r
+       unsigned char   *pbData = *ppbData;\r
+\r
+       switch (pSetup->bRequest) {\r
+\r
+       case REQ_GET_STATUS:\r
+               // no bits specified\r
+               pbData[0] = 0;\r
+               pbData[1] = 0;\r
+               *piLen = 2;\r
+               break;\r
+\r
+       case REQ_CLEAR_FEATURE:\r
+       case REQ_SET_FEATURE:\r
+               // not defined for interface\r
+               return FALSE;\r
+       \r
+       case REQ_GET_INTERFACE: // TODO use bNumInterfaces\r
+        // there is only one interface, return n-1 (= 0)\r
+               pbData[0] = 0;\r
+               *piLen = 1;\r
+               break;\r
+       \r
+       case REQ_SET_INTERFACE: // TODO use bNumInterfaces\r
+               // there is only one interface (= 0)\r
+               if (pSetup->wValue != 0) {\r
+                       return FALSE;\r
+               }\r
+               *piLen = 0;\r
+               break;\r
+\r
+       default:\r
+               DBG("Illegal interface req %d\n", pSetup->bRequest);\r
+               return FALSE;\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
+\r
+/**\r
+       Local function to handle a standard endpoint request\r
+               \r
+       @param [in]             pSetup          The setup packet\r
+       @param [in,out] *piLen          Pointer to data length\r
+       @param [in]             ppbData         Data buffer.\r
+\r
+       @return TRUE if the request was handled successfully\r
+ */\r
+static BOOL HandleStdEndPointReq(TSetupPacket  *pSetup, int *piLen, unsigned char **ppbData)\r
+{\r
+       unsigned char   *pbData = *ppbData;\r
+\r
+       switch (pSetup->bRequest) {\r
+       case REQ_GET_STATUS:\r
+               // bit 0 = endpointed halted or not\r
+               pbData[0] = (USBHwEPGetStatus(pSetup->wIndex) & EP_STATUS_STALLED) ? 1 : 0;\r
+               pbData[1] = 0;\r
+               *piLen = 2;\r
+               break;\r
+               \r
+       case REQ_CLEAR_FEATURE:\r
+               if (pSetup->wValue == FEA_ENDPOINT_HALT) {\r
+                       // clear HALT by unstalling\r
+                       USBHwEPStall(pSetup->wIndex, FALSE);\r
+                       break;\r
+               }\r
+               // only ENDPOINT_HALT defined for endpoints\r
+               return FALSE;\r
+       \r
+       case REQ_SET_FEATURE:\r
+               if (pSetup->wValue == FEA_ENDPOINT_HALT) {\r
+                       // set HALT by stalling\r
+                       USBHwEPStall(pSetup->wIndex, TRUE);\r
+                       break;\r
+               }\r
+               // only ENDPOINT_HALT defined for endpoints\r
+               return FALSE;\r
+\r
+       case REQ_SYNCH_FRAME:\r
+               DBG("EP req %d not implemented\n", pSetup->bRequest);\r
+               return FALSE;\r
+\r
+       default:\r
+               DBG("Illegal EP req %d\n", pSetup->bRequest);\r
+               return FALSE;\r
+       }\r
+       \r
+       return TRUE;\r
+}\r
+\r
+\r
+/**\r
+       Default handler for standard ('chapter 9') requests\r
+       \r
+       If a custom request handler was installed, this handler is called first.\r
+               \r
+       @param [in]             pSetup          The setup packet\r
+       @param [in,out] *piLen          Pointer to data length\r
+       @param [in]             ppbData         Data buffer.\r
+\r
+       @return TRUE if the request was handled successfully\r
+ */\r
+BOOL USBHandleStandardRequest(TSetupPacket     *pSetup, int *piLen, unsigned char **ppbData)\r
+{\r
+       // try the custom request handler first\r
+       if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq(pSetup, piLen, ppbData)) {\r
+               return TRUE;\r
+       }\r
+       \r
+       switch (REQTYPE_GET_RECIP(pSetup->bmRequestType)) {\r
+       case REQTYPE_RECIP_DEVICE:              return HandleStdDeviceReq(pSetup, piLen, ppbData);\r
+       case REQTYPE_RECIP_INTERFACE:   return HandleStdInterfaceReq(pSetup, piLen, ppbData);\r
+       case REQTYPE_RECIP_ENDPOINT:    return HandleStdEndPointReq(pSetup, piLen, ppbData);\r
+       default:                                                return FALSE;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+       Registers a callback for custom device requests\r
+       \r
+       In USBHandleStandardRequest, the custom request handler gets a first\r
+       chance at handling the request before it is handed over to the 'chapter 9'\r
+       request handler.\r
+       \r
+       This can be used for example in HID devices, where a REQ_GET_DESCRIPTOR\r
+       request is sent to an interface, which is not covered by the 'chapter 9'\r
+       specification.\r
+               \r
+       @param [in]     pfnHandler      Callback function pointer\r
+ */\r
+void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler)\r
+{\r
+       pfnHandleCustomReq = pfnHandler;\r
+}\r
+\r
diff --git a/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbstruct.h b/Demo/CORTEX_LPC1768_GCC_Rowley/LPCUSB/usbstruct.h
new file mode 100644 (file)
index 0000000..113e2fe
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+       LPCUSB, an USB device driver for LPC microcontrollers   
+       Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are met:
+
+       1. Redistributions of source code must retain the above copyright
+          notice, this list of conditions and the following disclaimer.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, this list of conditions and the following disclaimer in the
+          documentation and/or other materials provided with the distribution.
+       3. The name of the author may not be used to endorse or promote products
+          derived from this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+       IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+       OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+       IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
+       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+       THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/**
+       Definitions of structures of standard USB packets
+*/
+
+#ifndef _USBSTRUCT_H_
+#define _USBSTRUCT_H_
+
+// CodeRed - include the LPCUSB type.h file rather than NXP one directly
+#include "type.h"
+
+/** setup packet definitions */
+typedef struct {
+       unsigned char   bmRequestType;                  /**< characteristics of the specific request */
+       unsigned char   bRequest;                               /**< specific request */
+       unsigned short  wValue;                                 /**< request specific parameter */
+       unsigned short  wIndex;                                 /**< request specific parameter */
+       unsigned short  wLength;                                /**< length of data transfered in data phase */
+} TSetupPacket;
+
+
+#define REQTYPE_GET_DIR(x)             (((x)>>7)&0x01)
+#define REQTYPE_GET_TYPE(x)            (((x)>>5)&0x03)
+#define REQTYPE_GET_RECIP(x)   ((x)&0x1F)
+
+#define REQTYPE_DIR_TO_DEVICE  0
+#define REQTYPE_DIR_TO_HOST            1
+
+#define REQTYPE_TYPE_STANDARD  0
+#define REQTYPE_TYPE_CLASS             1
+#define REQTYPE_TYPE_VENDOR            2
+#define REQTYPE_TYPE_RESERVED  3
+
+#define REQTYPE_RECIP_DEVICE   0
+#define REQTYPE_RECIP_INTERFACE        1
+#define REQTYPE_RECIP_ENDPOINT 2
+#define REQTYPE_RECIP_OTHER            3
+
+/* standard requests */
+#define        REQ_GET_STATUS                  0x00
+#define REQ_CLEAR_FEATURE              0x01
+#define REQ_SET_FEATURE                        0x03
+#define REQ_SET_ADDRESS                        0x05
+#define REQ_GET_DESCRIPTOR             0x06
+#define REQ_SET_DESCRIPTOR             0x07
+#define REQ_GET_CONFIGURATION  0x08
+#define REQ_SET_CONFIGURATION  0x09
+#define REQ_GET_INTERFACE              0x0A
+#define REQ_SET_INTERFACE              0x0B
+#define REQ_SYNCH_FRAME                        0x0C
+
+/* class requests HID */
+#define HID_GET_REPORT                 0x01
+#define HID_GET_IDLE                   0x02
+#define HID_GET_PROTOCOL               0x03
+#define HID_SET_REPORT                 0x09
+#define HID_SET_IDLE                   0x0A
+#define HID_SET_PROTOCOL               0x0B
+
+/* feature selectors */
+#define FEA_ENDPOINT_HALT              0x00
+#define FEA_REMOTE_WAKEUP              0x01
+#define FEA_TEST_MODE                  0x02
+
+/*
+       USB descriptors
+*/
+
+/** USB descriptor header */
+typedef struct {
+       unsigned char   bLength;                        /**< descriptor length */
+       unsigned char   bDescriptorType;        /**< descriptor type */
+} TUSBDescHeader;
+
+#define DESC_DEVICE                            1
+#define DESC_CONFIGURATION             2
+#define DESC_STRING                            3
+#define DESC_INTERFACE                 4
+#define DESC_ENDPOINT                  5
+#define DESC_DEVICE_QUALIFIER  6
+#define DESC_OTHER_SPEED               7
+#define DESC_INTERFACE_POWER   8
+
+#define DESC_HID_HID                   0x21
+#define DESC_HID_REPORT                        0x22
+#define DESC_HID_PHYSICAL              0x23
+
+#define GET_DESC_TYPE(x)               (((x)>>8)&0xFF)
+#define GET_DESC_INDEX(x)              ((x)&0xFF)
+
+#endif /* _USBSTRUCT_H_ */
+
index 3b534ea89b55861c4137d8c3c69e41ecd5e741e2..d7e1a85171a17999e576d4251a658e8257cedda7 100644 (file)
@@ -1,7 +1,7 @@
 <!DOCTYPE CrossStudio_Project_File>
 <solution Name="RTOSDemo" version="2">
   <project Name="RTOSDemo">
-    <configuration Name="Common" Target="LPC1768" arm_architecture="v7M" arm_core_type="Cortex-M3" arm_linker_heap_size="128" arm_linker_process_stack_size="0" arm_linker_stack_size="128" arm_simulator_memory_simulation_filename="$(TargetsDir)/LPC1000/LPC1000SimulatorMemory.dll" arm_simulator_memory_simulation_parameter="0x80000;0x8000;0x8000" arm_target_debug_interface_type="ADIv5" arm_target_loader_parameter="12000000" c_enforce_ansi_checking="No" c_only_additional_options="-Wall;-Wextra" c_preprocessor_definitions="PACK_STRUCT_END=__attribute((packed));ALIGN_STRUCT_END=__attribute((aligned(4)))" c_user_include_directories="$(TargetsDir)/LPC1000/include;../../Source/include;../Common/include;../../Source/portable/GCC/ARM_CM3;../Common/ethernet/uIP/uip-1.0/uip;.;./webserver;./USBHost/Include" link_include_startup_code="No" linker_additional_files="$(TargetsDir)/LPC1000/lib/liblpc1000$(LibExt)$(LIB);$(TargetsDir)/LPC1000/lib/cmsis$(LibExt)$(LIB)" linker_memory_map_file="$(TargetsDir)/LPC1000/LPC1768_MemoryMap.xml" linker_printf_fmt_level="int" linker_printf_width_precision_supported="No" linker_section_placement_file="$(ProjectDir)/flash_placement.xml" oscillator_frequency="12MHz" project_directory="" project_type="Executable" property_groups_file_path="$(TargetsDir)/LPC1000/propertyGroups.xml"/>
+    <configuration Name="Common" Target="LPC1768" arm_architecture="v7M" arm_core_type="Cortex-M3" arm_linker_heap_size="128" arm_linker_process_stack_size="0" arm_linker_stack_size="128" arm_simulator_memory_simulation_filename="$(TargetsDir)/LPC1000/LPC1000SimulatorMemory.dll" arm_simulator_memory_simulation_parameter="0x80000;0x8000;0x8000" arm_target_debug_interface_type="ADIv5" arm_target_loader_parameter="12000000" c_enforce_ansi_checking="No" c_only_additional_options="-Wall;-Wextra" c_preprocessor_definitions="PACK_STRUCT_END=__attribute((packed));ALIGN_STRUCT_END=__attribute((aligned(4)));CONFIGURE_USB;FULL_SPEED" c_user_include_directories="$(TargetsDir)/LPC1000/include;../../Source/include;../Common/include;../../Source/portable/GCC/ARM_CM3;../Common/ethernet/uIP/uip-1.0/uip;.;./webserver;./LPCUSB" link_include_startup_code="No" linker_additional_files="$(TargetsDir)/LPC1000/lib/liblpc1000$(LibExt)$(LIB);$(TargetsDir)/LPC1000/lib/cmsis$(LibExt)$(LIB)" linker_memory_map_file="$(TargetsDir)/LPC1000/LPC1768_MemoryMap.xml" linker_printf_fmt_level="int" linker_printf_width_precision_supported="No" linker_section_placement_file="$(ProjectDir)/flash_placement.xml" oscillator_frequency="12MHz" project_directory="" project_type="Executable" property_groups_file_path="$(TargetsDir)/LPC1000/propertyGroups.xml"/>
     <configuration Name="RAM" Placement="RAM" linker_section_placement_file="$(StudioDir)/targets/Cortex_M/ram_placement.xml" target_reset_script="SRAMReset()"/>
     <configuration Name="Flash" Placement="Flash" arm_target_flash_loader_file_path="$(TargetsDir)/LPC1000/Release/Loader_rpc.elf" arm_target_flash_loader_type="LIBMEM RPC Loader" linker_patch_build_command="$(StudioDir)/bin/crossscript &quot;load(\&quot;$(TargetsDir)/LPC1000/LPC1000_LinkPatch.js\&quot;);patch(\&quot;$(TargetPath)\&quot;);&quot;" linker_section_placement_file="$(ProjectDir)/flash_placement.xml" target_reset_script="FLASHReset()"/>
     <folder Name="Source Files">
       </folder>
       <file file_name="ParTest.c"/>
       <file file_name="printf-stdarg.c"/>
+      <folder Name="LPCUSB">
+        <file file_name="LPCUSB/usbstdreq.c"/>
+        <file file_name="LPCUSB/USB_CDC.c"/>
+        <file file_name="LPCUSB/usbcontrol.c"/>
+        <file file_name="LPCUSB/usbhw_lpc.c"/>
+        <file file_name="LPCUSB/usbinit.c"/>
+      </folder>
     </folder>
     <folder Name="System Files">
       <file file_name="$(StudioDir)/source/thumb_crt0.s"/>
index feca371486888b84c8601c0b2d9c7d7a5f0129f1..5cc8daec4479884c8b260a8defbfaa234e1e8ee3 100644 (file)
@@ -22,6 +22,9 @@
   <ProjectSessionItem path="RTOSDemo" name="unnamed" />
   <ProjectSessionItem path="RTOSDemo;RTOSDemo" name="unnamed" />
   <ProjectSessionItem path="RTOSDemo;RTOSDemo;Source Files" name="unnamed" />
+  <ProjectSessionItem path="RTOSDemo;RTOSDemo;Source Files;FreeRTOS" name="unnamed" />
+  <ProjectSessionItem path="RTOSDemo;RTOSDemo;Source Files;LPCUSB" name="unnamed" />
+  <ProjectSessionItem path="RTOSDemo;RTOSDemo;System Files" name="unnamed" />
  </Project>
  <Register1>
   <RegisterWindow openNodes="CPU;CPU/xPSR;CPU/CFBP;CPU/CFBP/CONTROL[0];CPU/CFBP/CONTROL[1]" binaryNodes="" unsignedNodes="" visibleGroups="CPU" decimalNodes="" octalNodes="" asciiNodes="" />
@@ -52,7 +55,7 @@
   <Watches active="0" update="Never" />
  </Watch4>
  <Files>
-  <SessionOpenFile useTextEdit="1" useBinaryEdit="0" codecName="Latin1" x="10" debugPath="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\main.c" y="304" path="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\main.c" left="0" selected="1" name="unnamed" top="0" />
+  <SessionOpenFile useTextEdit="1" useBinaryEdit="0" codecName="Latin1" x="0" debugPath="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\main.c" y="141" path="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\main.c" left="0" selected="1" name="unnamed" top="138" />
  </Files>
- <ARMCrossStudioWindow activeProject="RTOSDemo" autoConnectTarget="USB CrossConnect for ARM" debugSearchFileMap="" fileDialogInitialDirectory="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\UsbHost\Uart" fileDialogDefaultFilter="*.*" autoConnectCapabilities="388991" debugSearchPath="" buildConfiguration="THUMB Flash Debug" />
+ <ARMCrossStudioWindow activeProject="RTOSDemo" autoConnectTarget="USB CrossConnect for ARM" debugSearchFileMap="" fileDialogInitialDirectory="C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_LPC1768_GCC_Rowley\LPCUSB" fileDialogDefaultFilter="*.*" autoConnectCapabilities="388991" debugSearchPath="" buildConfiguration="THUMB Flash Debug" />
 </session>
index c8c8a2b55d5c659265aa0a5ec91447c1045052dd..529b498fc2ee612dbf3e1fc80c8b69cbb6acfdc5 100644 (file)
  *\r
  * "uIP" task -  This is the task that handles the uIP stack.  All TCP/IP\r
  * processing is performed in this task.\r
+ * \r
+ * "USB" task - Enumerates the USB device as a CDC class, then echoes back all\r
+ * received characters with a configurable offset (for example, if the offset\r
+ * is 1 and 'A' is received then 'B' will be sent back).  A dumb terminal such\r
+ * as Hyperterminal can be used to talk to the USB task.\r
  */\r
 \r
 /* Scheduler includes. */\r
@@ -116,6 +121,11 @@ static void prvSetupHardware( void );
  */\r
 extern void vuIP_Task( void *pvParameters );\r
 \r
+/*\r
+ * The task that handles the USB stack.\r
+ */\r
+extern void vUSBTask( void *pvParameters );\r
+\r
 /*\r
  * Simply returns the current status message for display on served WEB pages.\r
  */\r
@@ -145,6 +155,9 @@ int main( void )
     vStartRecursiveMutexTasks();\r
        vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY );\r
 \r
+    /* Create the USB task. */\r
+    xTaskCreate( vUSBTask, ( signed char * ) "USB", configMINIMAL_STACK_SIZE, ( void * ) NULL, tskIDLE_PRIORITY, NULL );\r
+       \r
        /* Create the uIP task.  The WEB server runs in this task. */\r
     xTaskCreate( vuIP_Task, ( signed char * ) "uIP", mainBASIC_WEB_STACK_SIZE, ( void * ) NULL, mainUIP_TASK_PRIORITY, NULL );\r
 \r
@@ -228,49 +241,6 @@ void prvSetupHardware( void )
        /* Disable TPIU. */\r
        PINCON->PINSEL10 = 0;\r
 \r
-       /* Disconnect the main PLL. */\r
-       SC->PLL0CON &= ~PLLCON_PLLC;\r
-       SC->PLL0FEED = PLLFEED_FEED1;\r
-       SC->PLL0FEED = PLLFEED_FEED2;\r
-       while ((SC->PLL0STAT & PLLSTAT_PLLC) != 0);\r
-\r
-       /* Turn off the main PLL. */\r
-       SC->PLL0CON &= ~PLLCON_PLLE;\r
-       SC->PLL0FEED = PLLFEED_FEED1;\r
-       SC->PLL0FEED = PLLFEED_FEED2;\r
-       while ((SC->PLL0STAT & PLLSTAT_PLLE) != 0);\r
-\r
-       /* No CPU clock divider. */\r
-       SC->CCLKCFG = 0;\r
-\r
-       /* OSCEN. */\r
-       SC->SCS = 0x20;\r
-       while ((SC->SCS & 0x40) == 0);\r
-\r
-       /* Use main oscillator. */\r
-       SC->CLKSRCSEL = 1;\r
-       SC->PLL0CFG = (PLLCFG_MUL16 | PLLCFG_DIV1);\r
-\r
-       SC->PLL0FEED = PLLFEED_FEED1;\r
-       SC->PLL0FEED = PLLFEED_FEED2;\r
-\r
-       /*  Activate the PLL by turning it on then feeding the correct\r
-       sequence of bytes. */\r
-       SC->PLL0CON  = PLLCON_PLLE;\r
-       SC->PLL0FEED = PLLFEED_FEED1;\r
-       SC->PLL0FEED = PLLFEED_FEED2;\r
-\r
-       /* 6x CPU clock divider (64 MHz) */\r
-       SC->CCLKCFG = 5;\r
-\r
-       /*  Wait for the PLL to lock. */\r
-       while ((SC->PLL0STAT & PLLSTAT_PLOCK) == 0);\r
-\r
-       /*  Connect the PLL. */\r
-       SC->PLL0CON  = PLLCON_PLLC | PLLCON_PLLE;\r
-       SC->PLL0FEED = PLLFEED_FEED1;\r
-       SC->PLL0FEED = PLLFEED_FEED2;\r
-\r
        /*  Setup the peripheral bus to be the same as the PLL output (64 MHz). */\r
        SC->PCLKSEL0 = 0x05555555;\r
 \r