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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [CORTEX_LPC1768_GCC_RedSuite/] [src/] [LPCUSB/] [USB_CDC.c] - Blame information for rev 581

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 "queue.h"
50
 
51
#include <stdio.h>
52
#include <string.h>
53
 
54
#include "usbapi.h"
55
#include "usbdebug.h"
56
#include "usbstruct.h"
57
 
58
#include "LPC17xx.h"
59
 
60
#define usbMAX_SEND_BLOCK               ( 20 / portTICK_RATE_MS )
61
#define usbBUFFER_LEN                   ( 20 )
62
 
63
#define INCREMENT_ECHO_BY 1
64
#define BAUD_RATE       115200
65
 
66
#define INT_IN_EP               0x81
67
#define BULK_OUT_EP             0x05
68
#define BULK_IN_EP              0x82
69
 
70
#define MAX_PACKET_SIZE 64
71
 
72
#define LE_WORD(x)              ((x)&0xFF),((x)>>8)
73
 
74
// CDC definitions
75
#define CS_INTERFACE                    0x24
76
#define CS_ENDPOINT                             0x25
77
 
78
#define SET_LINE_CODING                 0x20
79
#define GET_LINE_CODING                 0x21
80
#define SET_CONTROL_LINE_STATE  0x22
81
 
82
// data structure for GET_LINE_CODING / SET_LINE_CODING class requests
83
typedef struct {
84
        unsigned long           dwDTERate;
85
        unsigned char           bCharFormat;
86
        unsigned char           bParityType;
87
        unsigned char           bDataBits;
88
} TLineCoding;
89
 
90
static TLineCoding LineCoding = {115200, 0, 0, 8};
91
static unsigned char abBulkBuf[64];
92
static unsigned char abClassReqData[8];
93
 
94
static xQueueHandle xRxedChars = NULL, xCharsForTx = NULL;
95
 
96
// forward declaration of interrupt handler
97
void USBIntHandler(void);
98
 
99
static const unsigned char abDescriptors[] = {
100
 
101
// device descriptor
102
        0x12,
103
        DESC_DEVICE,
104
        LE_WORD(0x0101),                        // bcdUSB
105
        0x02,                                           // bDeviceClass
106
        0x00,                                           // bDeviceSubClass
107
        0x00,                                           // bDeviceProtocol
108
        MAX_PACKET_SIZE0,                       // bMaxPacketSize
109
        LE_WORD(0xFFFF),                        // idVendor
110
        LE_WORD(0x0005),                        // idProduct
111
        LE_WORD(0x0100),                        // bcdDevice
112
        0x01,                                           // iManufacturer
113
        0x02,                                           // iProduct
114
        0x03,                                           // iSerialNumber
115
        0x01,                                           // bNumConfigurations
116
 
117
// configuration descriptor
118
        0x09,
119
        DESC_CONFIGURATION,
120
        LE_WORD(67),                            // wTotalLength
121
        0x02,                                           // bNumInterfaces
122
        0x01,                                           // bConfigurationValue
123
        0x00,                                           // iConfiguration
124
        0xC0,                                           // bmAttributes
125
        0x32,                                           // bMaxPower
126
// control class interface
127
        0x09,
128
        DESC_INTERFACE,
129
        0x00,                                           // bInterfaceNumber
130
        0x00,                                           // bAlternateSetting
131
        0x01,                                           // bNumEndPoints
132
        0x02,                                           // bInterfaceClass
133
        0x02,                                           // bInterfaceSubClass
134
        0x01,                                           // bInterfaceProtocol, linux requires value of 1 for the cdc_acm module
135
        0x00,                                           // iInterface
136
// header functional descriptor
137
        0x05,
138
        CS_INTERFACE,
139
        0x00,
140
        LE_WORD(0x0110),
141
// call management functional descriptor
142
        0x05,
143
        CS_INTERFACE,
144
        0x01,
145
        0x01,                                           // bmCapabilities = device handles call management
146
        0x01,                                           // bDataInterface
147
// ACM functional descriptor
148
        0x04,
149
        CS_INTERFACE,
150
        0x02,
151
        0x02,                                           // bmCapabilities
152
// union functional descriptor
153
        0x05,
154
        CS_INTERFACE,
155
        0x06,
156
        0x00,                                           // bMasterInterface
157
        0x01,                                           // bSlaveInterface0
158
// notification EP
159
        0x07,
160
        DESC_ENDPOINT,
161
        INT_IN_EP,                                      // bEndpointAddress
162
        0x03,                                           // bmAttributes = intr
163
        LE_WORD(8),                                     // wMaxPacketSize
164
        0x0A,                                           // bInterval
165
// data class interface descriptor
166
        0x09,
167
        DESC_INTERFACE,
168
        0x01,                                           // bInterfaceNumber
169
        0x00,                                           // bAlternateSetting
170
        0x02,                                           // bNumEndPoints
171
        0x0A,                                           // bInterfaceClass = data
172
        0x00,                                           // bInterfaceSubClass
173
        0x00,                                           // bInterfaceProtocol
174
        0x00,                                           // iInterface
175
// data EP OUT
176
        0x07,
177
        DESC_ENDPOINT,
178
        BULK_OUT_EP,                            // bEndpointAddress
179
        0x02,                                           // bmAttributes = bulk
180
        LE_WORD(MAX_PACKET_SIZE),       // wMaxPacketSize
181
        0x00,                                           // bInterval
182
// data EP in
183
        0x07,
184
        DESC_ENDPOINT,
185
        BULK_IN_EP,                                     // bEndpointAddress
186
        0x02,                                           // bmAttributes = bulk
187
        LE_WORD(MAX_PACKET_SIZE),       // wMaxPacketSize
188
        0x00,                                           // bInterval
189
 
190
        // string descriptors
191
        0x04,
192
        DESC_STRING,
193
        LE_WORD(0x0409),
194
 
195
        0x0E,
196
        DESC_STRING,
197
        'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0,
198
 
199
        0x14,
200
        DESC_STRING,
201
        'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0,
202
 
203
        0x12,
204
        DESC_STRING,
205
        'D', 0, 'E', 0, 'A', 0, 'D', 0, 'C', 0, '0', 0, 'D', 0, 'E', 0,
206
 
207
// terminating zero
208
 
209
};
210
 
211
 
212
/**
213
        Local function to handle incoming bulk data
214
 
215
        @param [in] bEP
216
        @param [in] bEPStatus
217
 */
218
static void BulkOut(unsigned char bEP, unsigned char bEPStatus)
219
{
220
        int i, iLen;
221
        long lHigherPriorityTaskWoken = pdFALSE;
222
 
223
        ( void ) bEPStatus;
224
 
225
        // get data from USB into intermediate buffer
226
        iLen = USBHwEPRead(bEP, abBulkBuf, sizeof(abBulkBuf));
227
        for (i = 0; i < iLen; i++) {
228
                // put into queue
229
                xQueueSendFromISR( xRxedChars, &( abBulkBuf[ i ] ), &lHigherPriorityTaskWoken );
230
        }
231
 
232
        portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
233
}
234
 
235
 
236
/**
237
        Local function to handle outgoing bulk data
238
 
239
        @param [in] bEP
240
        @param [in] bEPStatus
241
 */
242
static void BulkIn(unsigned char bEP, unsigned char bEPStatus)
243
{
244
        int i, iLen;
245
        long lHigherPriorityTaskWoken = pdFALSE;
246
 
247
        ( void ) bEPStatus;
248
 
249
        if (uxQueueMessagesWaitingFromISR( xCharsForTx ) == 0) {
250
                // no more data, disable further NAK interrupts until next USB frame
251
                USBHwNakIntEnable(0);
252
                return;
253
        }
254
 
255
        // get bytes from transmit FIFO into intermediate buffer
256
        for (i = 0; i < MAX_PACKET_SIZE; i++) {
257
                if( xQueueReceiveFromISR( xCharsForTx, ( &abBulkBuf[i] ), &lHigherPriorityTaskWoken ) != pdPASS )
258
                {
259
                        break;
260
                }
261
        }
262
        iLen = i;
263
 
264
        // send over USB
265
        if (iLen > 0) {
266
                USBHwEPWrite(bEP, abBulkBuf, iLen);
267
        }
268
 
269
        portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
270
}
271
 
272
 
273
/**
274
        Local function to handle the USB-CDC class requests
275
 
276
        @param [in] pSetup
277
        @param [out] piLen
278
        @param [out] ppbData
279
 */
280
static BOOL HandleClassRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
281
{
282
        switch (pSetup->bRequest) {
283
 
284
        // set line coding
285
        case SET_LINE_CODING:
286
DBG("SET_LINE_CODING\n");
287
                memcpy((unsigned char *)&LineCoding, *ppbData, 7);
288
                *piLen = 7;
289
DBG("dwDTERate=%u, bCharFormat=%u, bParityType=%u, bDataBits=%u\n",
290
        LineCoding.dwDTERate,
291
        LineCoding.bCharFormat,
292
        LineCoding.bParityType,
293
        LineCoding.bDataBits);
294
                break;
295
 
296
        // get line coding
297
        case GET_LINE_CODING:
298
DBG("GET_LINE_CODING\n");
299
                *ppbData = (unsigned char *)&LineCoding;
300
                *piLen = 7;
301
                break;
302
 
303
        // set control line state
304
        case SET_CONTROL_LINE_STATE:
305
                // bit0 = DTR, bit = RTS
306
DBG("SET_CONTROL_LINE_STATE %X\n", pSetup->wValue);
307
                break;
308
 
309
        default:
310
                return FALSE;
311
        }
312
        return TRUE;
313
}
314
 
315
 
316
/**
317
        Writes one character to VCOM port
318
 
319
        @param [in] c character to write
320
        @returns character written, or EOF if character could not be written
321
 */
322
int VCOM_putchar(int c)
323
{
324
char cc = ( char ) c;
325
 
326
        if( xQueueSend( xCharsForTx, &cc, usbMAX_SEND_BLOCK ) == pdPASS )
327
        {
328
                return c;
329
        }
330
        else
331
        {
332
                return EOF;
333
        }
334
}
335
 
336
 
337
/**
338
        Reads one character from VCOM port
339
 
340
        @returns character read, or EOF if character could not be read
341
 */
342
int VCOM_getchar(void)
343
{
344
        unsigned char c;
345
 
346
        /* Block the task until a character is available. */
347
        xQueueReceive( xRxedChars, &c, portMAX_DELAY );
348
        return c;
349
}
350
 
351
 
352
/**
353
        Interrupt handler
354
 
355
        Simply calls the USB ISR
356
 */
357
//void USBIntHandler(void)
358
void USB_IRQHandler(void)
359
{
360
        USBHwISR();
361
}
362
 
363
 
364
static void USBFrameHandler(unsigned short wFrame)
365
{
366
        ( void ) wFrame;
367
 
368
        if( uxQueueMessagesWaitingFromISR( xCharsForTx ) > 0 )
369
        {
370
                // data available, enable NAK interrupt on bulk in
371
                USBHwNakIntEnable(INACK_BI);
372
        }
373
}
374
 
375
// CodeRed - added CPUcpsie
376
 
377
unsigned long CPUcpsie(void)
378
{
379
    unsigned long ulRet;
380
 
381
    //
382
    // Read PRIMASK and enable interrupts.
383
    //
384
    __asm("    mrs     %0, PRIMASK\n"
385
          "    cpsie   i\n"
386
          "    bx      lr\n"
387
          : "=r" (ulRet));
388
 
389
    //
390
    // The return is handled in the inline assembly, but the compiler will
391
    // still complain if there is not an explicit return here (despite the fact
392
    // that this does not result in any code being produced because of the
393
    // naked attribute).
394
    //
395
    return(ulRet);
396
}
397
 
398
void vUSBTask( void *pvParameters )
399
{
400
        int c;
401
 
402
        /* Just to prevent compiler warnings about the unused parameter. */
403
        ( void ) pvParameters;
404
        DBG("Initialising USB stack\n");
405
 
406
        xRxedChars = xQueueCreate( usbBUFFER_LEN, sizeof( char ) );
407
        xCharsForTx = xQueueCreate( usbBUFFER_LEN, sizeof( char ) );
408
 
409
        if( ( xRxedChars == NULL ) || ( xCharsForTx == NULL ) )
410
        {
411
                /* Not enough heap available to create the buffer queues, can't do
412
                anything so just delete ourselves. */
413
                vTaskDelete( NULL );
414
        }
415
 
416
 
417
        // initialise stack
418
        USBInit();
419
 
420
        // register descriptors
421
        USBRegisterDescriptors(abDescriptors);
422
 
423
        // register class request handler
424
        USBRegisterRequestHandler(REQTYPE_TYPE_CLASS, HandleClassRequest, abClassReqData);
425
 
426
        // register endpoint handlers
427
        USBHwRegisterEPIntHandler(INT_IN_EP, NULL);
428
        USBHwRegisterEPIntHandler(BULK_IN_EP, BulkIn);
429
        USBHwRegisterEPIntHandler(BULK_OUT_EP, BulkOut);
430
 
431
        // register frame handler
432
        USBHwRegisterFrameHandler(USBFrameHandler);
433
 
434
        // enable bulk-in interrupts on NAKs
435
        USBHwNakIntEnable(INACK_BI);
436
 
437
        DBG("Starting USB communication\n");
438
 
439
        NVIC_SetPriority( USB_IRQn, configUSB_INTERRUPT_PRIORITY );
440
        NVIC_EnableIRQ( USB_IRQn );
441
 
442
        // connect to bus
443
 
444
        DBG("Connecting to USB bus\n");
445
        USBHwConnect(TRUE);
446
 
447
        // echo any character received (do USB stuff in interrupt)
448
        for( ;; )
449
        {
450
                c = VCOM_getchar();
451
                if (c != EOF)
452
                {
453
                        // Echo character back with INCREMENT_ECHO_BY offset, so for example if
454
                        // INCREMENT_ECHO_BY is 1 and 'A' is received, 'B' will be echoed back.
455
                        VCOM_putchar(c + INCREMENT_ECHO_BY );
456
                }
457
        }
458
}
459
 

powered by: WebSVN 2.1.0

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