OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [CORTEX_LPC1768_IAR/] [LPCUSB/] [USB_CDC.c] - Blame information for rev 597

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 581 jeremybenn
/*
2
        LPCUSB, an USB device driver for LPC microcontrollers
3
        Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
4
 
5
        Redistribution and use in source and binary forms, with or without
6
        modification, are permitted provided that the following conditions are met:
7
 
8
        1. Redistributions of source code must retain the above copyright
9
           notice, this list of conditions and the following disclaimer.
10
        2. Redistributions in binary form must reproduce the above copyright
11
           notice, this list of conditions and the following disclaimer in the
12
           documentation and/or other materials provided with the distribution.
13
        3. The name of the author may not be used to endorse or promote products
14
           derived from this software without specific prior written permission.
15
 
16
        THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
        IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
        OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
        IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
        INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
        NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
        DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
        THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
        (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
        THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
*/
27
 
28
/*
29
        Minimal implementation of a USB serial port, using the CDC class.
30
        This example application simply echoes everything it receives right back
31
        to the host.
32
 
33
        Windows:
34
        Extract the usbser.sys file from .cab file in C:\WINDOWS\Driver Cache\i386
35
        and store it somewhere (C:\temp is a good place) along with the usbser.inf
36
        file. Then plug in the LPC176x and direct windows to the usbser driver.
37
        Windows then creates an extra COMx port that you can open in a terminal
38
        program, like hyperterminal. [Note for FreeRTOS users - the required .inf
39
        file is included in the project directory.]
40
 
41
        Linux:
42
        The device should be recognised automatically by the cdc_acm driver,
43
        which creates a /dev/ttyACMx device file that acts just like a regular
44
        serial port.
45
 
46
*/
47
 
48
#include "FreeRTOS.h"
49
#include "task.h"
50
#include "queue.h"
51
 
52
#include <stdio.h>
53
#include <string.h>
54
 
55
#include "usbapi.h"
56
#include "usbdebug.h"
57
#include "usbstruct.h"
58
 
59
#include "LPC17xx.h"
60
 
61
#define usbMAX_SEND_BLOCK               ( 20 / portTICK_RATE_MS )
62
#define usbBUFFER_LEN                   ( 20 )
63
 
64
#define INCREMENT_ECHO_BY 1
65
#define BAUD_RATE       115200
66
 
67
#define INT_IN_EP               0x81
68
#define BULK_OUT_EP             0x05
69
#define BULK_IN_EP              0x82
70
 
71
#define MAX_PACKET_SIZE 64
72
 
73
#define LE_WORD(x)              ((x)&0xFF),((x)>>8)
74
 
75
// CDC definitions
76
#define CS_INTERFACE                    0x24
77
#define CS_ENDPOINT                             0x25
78
 
79
#define SET_LINE_CODING                 0x20
80
#define GET_LINE_CODING                 0x21
81
#define SET_CONTROL_LINE_STATE  0x22
82
 
83
// data structure for GET_LINE_CODING / SET_LINE_CODING class requests
84
typedef struct {
85
        unsigned long           dwDTERate;
86
        unsigned char           bCharFormat;
87
        unsigned char           bParityType;
88
        unsigned char           bDataBits;
89
} TLineCoding;
90
 
91
static TLineCoding LineCoding = {115200, 0, 0, 8};
92
static unsigned char abBulkBuf[64];
93
static unsigned char abClassReqData[8];
94
 
95
static xQueueHandle xRxedChars = NULL, xCharsForTx = NULL;
96
 
97
// forward declaration of interrupt handler
98
void USBIntHandler(void);
99
 
100
static const unsigned char abDescriptors[] = {
101
 
102
// device descriptor
103
        0x12,
104
        DESC_DEVICE,
105
        LE_WORD(0x0101),                        // bcdUSB
106
        0x02,                                           // bDeviceClass
107
        0x00,                                           // bDeviceSubClass
108
        0x00,                                           // bDeviceProtocol
109
        MAX_PACKET_SIZE0,                       // bMaxPacketSize
110
        LE_WORD(0xFFFF),                        // idVendor
111
        LE_WORD(0x0005),                        // idProduct
112
        LE_WORD(0x0100),                        // bcdDevice
113
        0x01,                                           // iManufacturer
114
        0x02,                                           // iProduct
115
        0x03,                                           // iSerialNumber
116
        0x01,                                           // bNumConfigurations
117
 
118
// configuration descriptor
119
        0x09,
120
        DESC_CONFIGURATION,
121
        LE_WORD(67),                            // wTotalLength
122
        0x02,                                           // bNumInterfaces
123
        0x01,                                           // bConfigurationValue
124
        0x00,                                           // iConfiguration
125
        0xC0,                                           // bmAttributes
126
        0x32,                                           // bMaxPower
127
// control class interface
128
        0x09,
129
        DESC_INTERFACE,
130
        0x00,                                           // bInterfaceNumber
131
        0x00,                                           // bAlternateSetting
132
        0x01,                                           // bNumEndPoints
133
        0x02,                                           // bInterfaceClass
134
        0x02,                                           // bInterfaceSubClass
135
        0x01,                                           // bInterfaceProtocol, linux requires value of 1 for the cdc_acm module
136
        0x00,                                           // iInterface
137
// header functional descriptor
138
        0x05,
139
        CS_INTERFACE,
140
        0x00,
141
        LE_WORD(0x0110),
142
// call management functional descriptor
143
        0x05,
144
        CS_INTERFACE,
145
        0x01,
146
        0x01,                                           // bmCapabilities = device handles call management
147
        0x01,                                           // bDataInterface
148
// ACM functional descriptor
149
        0x04,
150
        CS_INTERFACE,
151
        0x02,
152
        0x02,                                           // bmCapabilities
153
// union functional descriptor
154
        0x05,
155
        CS_INTERFACE,
156
        0x06,
157
        0x00,                                           // bMasterInterface
158
        0x01,                                           // bSlaveInterface0
159
// notification EP
160
        0x07,
161
        DESC_ENDPOINT,
162
        INT_IN_EP,                                      // bEndpointAddress
163
        0x03,                                           // bmAttributes = intr
164
        LE_WORD(8),                                     // wMaxPacketSize
165
        0x0A,                                           // bInterval
166
// data class interface descriptor
167
        0x09,
168
        DESC_INTERFACE,
169
        0x01,                                           // bInterfaceNumber
170
        0x00,                                           // bAlternateSetting
171
        0x02,                                           // bNumEndPoints
172
        0x0A,                                           // bInterfaceClass = data
173
        0x00,                                           // bInterfaceSubClass
174
        0x00,                                           // bInterfaceProtocol
175
        0x00,                                           // iInterface
176
// data EP OUT
177
        0x07,
178
        DESC_ENDPOINT,
179
        BULK_OUT_EP,                            // bEndpointAddress
180
        0x02,                                           // bmAttributes = bulk
181
        LE_WORD(MAX_PACKET_SIZE),       // wMaxPacketSize
182
        0x00,                                           // bInterval
183
// data EP in
184
        0x07,
185
        DESC_ENDPOINT,
186
        BULK_IN_EP,                                     // bEndpointAddress
187
        0x02,                                           // bmAttributes = bulk
188
        LE_WORD(MAX_PACKET_SIZE),       // wMaxPacketSize
189
        0x00,                                           // bInterval
190
 
191
        // string descriptors
192
        0x04,
193
        DESC_STRING,
194
        LE_WORD(0x0409),
195
 
196
        0x0E,
197
        DESC_STRING,
198
        'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0,
199
 
200
        0x14,
201
        DESC_STRING,
202
        'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0,
203
 
204
        0x12,
205
        DESC_STRING,
206
        'D', 0, 'E', 0, 'A', 0, 'D', 0, 'C', 0, '0', 0, 'D', 0, 'E', 0,
207
 
208
// terminating zero
209
 
210
};
211
 
212
 
213
/**
214
        Local function to handle incoming bulk data
215
 
216
        @param [in] bEP
217
        @param [in] bEPStatus
218
 */
219
static void BulkOut(unsigned char bEP, unsigned char bEPStatus)
220
{
221
        int i, iLen;
222
        long lHigherPriorityTaskWoken = pdFALSE;
223
 
224
        ( void ) bEPStatus;
225
 
226
        // get data from USB into intermediate buffer
227
        iLen = USBHwEPRead(bEP, abBulkBuf, sizeof(abBulkBuf));
228
        for (i = 0; i < iLen; i++) {
229
                // put into queue
230
                xQueueSendFromISR( xRxedChars, &( abBulkBuf[ i ] ), &lHigherPriorityTaskWoken );
231
        }
232
 
233
        portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
234
}
235
 
236
 
237
/**
238
        Local function to handle outgoing bulk data
239
 
240
        @param [in] bEP
241
        @param [in] bEPStatus
242
 */
243
static void BulkIn(unsigned char bEP, unsigned char bEPStatus)
244
{
245
        int i, iLen;
246
        long lHigherPriorityTaskWoken = pdFALSE;
247
 
248
        ( void ) bEPStatus;
249
 
250
        if (uxQueueMessagesWaitingFromISR( xCharsForTx ) == 0) {
251
                // no more data, disable further NAK interrupts until next USB frame
252
                USBHwNakIntEnable(0);
253
                return;
254
        }
255
 
256
        // get bytes from transmit FIFO into intermediate buffer
257
        for (i = 0; i < MAX_PACKET_SIZE; i++) {
258
                if( xQueueReceiveFromISR( xCharsForTx, ( &abBulkBuf[i] ), &lHigherPriorityTaskWoken ) != pdPASS )
259
                {
260
                        break;
261
                }
262
        }
263
        iLen = i;
264
 
265
        // send over USB
266
        if (iLen > 0) {
267
                USBHwEPWrite(bEP, abBulkBuf, iLen);
268
        }
269
 
270
        portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
271
}
272
 
273
 
274
/**
275
        Local function to handle the USB-CDC class requests
276
 
277
        @param [in] pSetup
278
        @param [out] piLen
279
        @param [out] ppbData
280
 */
281
static BOOL HandleClassRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
282
{
283
        switch (pSetup->bRequest) {
284
 
285
        // set line coding
286
        case SET_LINE_CODING:
287
DBG("SET_LINE_CODING\n");
288
                memcpy((unsigned char *)&LineCoding, *ppbData, 7);
289
                *piLen = 7;
290
DBG("dwDTERate=%u, bCharFormat=%u, bParityType=%u, bDataBits=%u\n",
291
        LineCoding.dwDTERate,
292
        LineCoding.bCharFormat,
293
        LineCoding.bParityType,
294
        LineCoding.bDataBits);
295
                break;
296
 
297
        // get line coding
298
        case GET_LINE_CODING:
299
DBG("GET_LINE_CODING\n");
300
                *ppbData = (unsigned char *)&LineCoding;
301
                *piLen = 7;
302
                break;
303
 
304
        // set control line state
305
        case SET_CONTROL_LINE_STATE:
306
                // bit0 = DTR, bit = RTS
307
DBG("SET_CONTROL_LINE_STATE %X\n", pSetup->wValue);
308
                break;
309
 
310
        default:
311
                return FALSE;
312
        }
313
        return TRUE;
314
}
315
 
316
 
317
/**
318
        Writes one character to VCOM port
319
 
320
        @param [in] c character to write
321
        @returns character written, or EOF if character could not be written
322
 */
323
int VCOM_putchar(int c)
324
{
325
char cc = ( char ) c;
326
 
327
        if( xQueueSend( xCharsForTx, &cc, usbMAX_SEND_BLOCK ) == pdPASS )
328
        {
329
                return c;
330
        }
331
        else
332
        {
333
                return EOF;
334
        }
335
}
336
 
337
 
338
/**
339
        Reads one character from VCOM port
340
 
341
        @returns character read, or EOF if character could not be read
342
 */
343
int VCOM_getchar(void)
344
{
345
        unsigned char c;
346
 
347
        /* Block the task until a character is available. */
348
        xQueueReceive( xRxedChars, &c, portMAX_DELAY );
349
        return c;
350
}
351
 
352
 
353
/**
354
        Interrupt handler
355
 
356
        Simply calls the USB ISR
357
 */
358
//void USBIntHandler(void)
359
void USB_IRQHandler(void)
360
{
361
        USBHwISR();
362
}
363
 
364
 
365
static void USBFrameHandler(unsigned short wFrame)
366
{
367
        ( void ) wFrame;
368
 
369
        if( uxQueueMessagesWaitingFromISR( xCharsForTx ) > 0 )
370
        {
371
                // data available, enable NAK interrupt on bulk in
372
                USBHwNakIntEnable(INACK_BI);
373
        }
374
}
375
 
376
void vUSBTask( void *pvParameters )
377
{
378
        int c;
379
 
380
        /* Just to prevent compiler warnings about the unused parameter. */
381
        ( void ) pvParameters;
382
        DBG("Initialising USB stack\n");
383
 
384
        xRxedChars = xQueueCreate( usbBUFFER_LEN, sizeof( char ) );
385
        xCharsForTx = xQueueCreate( usbBUFFER_LEN, sizeof( char ) );
386
 
387
        if( ( xRxedChars == NULL ) || ( xCharsForTx == NULL ) )
388
        {
389
                /* Not enough heap available to create the buffer queues, can't do
390
                anything so just delete ourselves. */
391
                vTaskDelete( NULL );
392
        }
393
 
394
 
395
        // initialise stack
396
        USBInit();
397
 
398
        // register descriptors
399
        USBRegisterDescriptors(abDescriptors);
400
 
401
        // register class request handler
402
        USBRegisterRequestHandler(REQTYPE_TYPE_CLASS, HandleClassRequest, abClassReqData);
403
 
404
        // register endpoint handlers
405
        USBHwRegisterEPIntHandler(INT_IN_EP, NULL);
406
        USBHwRegisterEPIntHandler(BULK_IN_EP, BulkIn);
407
        USBHwRegisterEPIntHandler(BULK_OUT_EP, BulkOut);
408
 
409
        // register frame handler
410
        USBHwRegisterFrameHandler(USBFrameHandler);
411
 
412
        // enable bulk-in interrupts on NAKs
413
        USBHwNakIntEnable(INACK_BI);
414
 
415
        DBG("Starting USB communication\n");
416
 
417
        NVIC_SetPriority( USB_IRQn, configUSB_INTERRUPT_PRIORITY );
418
        NVIC_EnableIRQ( USB_IRQn );
419
 
420
        // connect to bus
421
 
422
        DBG("Connecting to USB bus\n");
423
        USBHwConnect(TRUE);
424
 
425
        // echo any character received (do USB stuff in interrupt)
426
        for( ;; )
427
        {
428
                c = VCOM_getchar();
429
                if (c != EOF)
430
                {
431
                        // Echo character back with INCREMENT_ECHO_BY offset, so for example if
432
                        // INCREMENT_ECHO_BY is 1 and 'A' is received, 'B' will be echoed back.
433
                        VCOM_putchar(c + INCREMENT_ECHO_BY );
434
                }
435
        }
436
}
437
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.