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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [ARM7_AT91SAM7S64_IAR/] [USB/] [USBSample.c] - Blame information for rev 577

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 577 jeremybenn
/*
2
    FreeRTOS V6.1.1 - Copyright (C) 2011 Real Time Engineers Ltd.
3
 
4
    ***************************************************************************
5
    *                                                                         *
6
    * If you are:                                                             *
7
    *                                                                         *
8
    *    + New to FreeRTOS,                                                   *
9
    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
10
    *    + Looking for basic training,                                        *
11
    *    + Wanting to improve your FreeRTOS skills and productivity           *
12
    *                                                                         *
13
    * then take a look at the FreeRTOS books - available as PDF or paperback  *
14
    *                                                                         *
15
    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
16
    *                  http://www.FreeRTOS.org/Documentation                  *
17
    *                                                                         *
18
    * A pdf reference manual is also available.  Both are usually delivered   *
19
    * to your inbox within 20 minutes to two hours when purchased between 8am *
20
    * and 8pm GMT (although please allow up to 24 hours in case of            *
21
    * exceptional circumstances).  Thank you for your support!                *
22
    *                                                                         *
23
    ***************************************************************************
24
 
25
    This file is part of the FreeRTOS distribution.
26
 
27
    FreeRTOS is free software; you can redistribute it and/or modify it under
28
    the terms of the GNU General Public License (version 2) as published by the
29
    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
30
    ***NOTE*** The exception to the GPL is included to allow you to distribute
31
    a combined work that includes FreeRTOS without being obliged to provide the
32
    source code for proprietary components outside of the FreeRTOS kernel.
33
    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
34
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
36
    more details. You should have received a copy of the GNU General Public
37
    License and the FreeRTOS license exception along with FreeRTOS; if not it
38
    can be viewed here: http://www.freertos.org/a00114.html and also obtained
39
    by writing to Richard Barry, contact details for whom are available on the
40
    FreeRTOS WEB site.
41
 
42
    1 tab == 4 spaces!
43
 
44
    http://www.FreeRTOS.org - Documentation, latest information, license and
45
    contact details.
46
 
47
    http://www.SafeRTOS.com - A version that is certified for use in safety
48
    critical systems.
49
 
50
    http://www.OpenRTOS.com - Commercial support, development, porting,
51
    licensing and training services.
52
*/
53
 
54
/*
55
        Sample interrupt driven USB device driver.  This is a minimal implementation
56
        for demonstration only.  Although functional, it is not a full and compliant
57
        implementation.
58
 
59
        The USB device enumerates as a simple 3 axis joystick, and once configured
60
        transmits 3 axis of data which can be viewed from the USB host machine.
61
 
62
        This file implements the USB interrupt service routine, and a demo FreeRTOS
63
        task.  The interrupt service routine handles the USB hardware - taking a
64
        snapshot of the USB status at the point of the interrupt.  The task receives
65
        the status information from the interrupt for processing at the task level.
66
 
67
        See the FreeRTOS.org WEB documentation for more information.
68
*/
69
 
70
/*
71
        Changes from V2.5.5
72
 
73
        + Descriptors that have a length that is an exact multiple of usbFIFO_LENGTH
74
          can now be transmitted.  To this end an extra parameter has been
75
          added to the prvSendControlData() function, and the state
76
          eSENDING_EVEN_DESCRIPTOR has been introduced.  Thanks to Scott Miller for
77
          assisting with this contribution.
78
 
79
        Changes from V2.6.0
80
 
81
        + Replaced the duplicated RX_DATA_BK0 in the interrupt mask with the
82
          RX_DATA_BK1.
83
*/
84
 
85
/* Standard includes. */
86
#include <string.h>
87
 
88
/* Demo board includes. */
89
#include "board.h"
90
 
91
/* Scheduler includes. */
92
#include "FreeRTOS.h"
93
#include "task.h"
94
#include "queue.h"
95
 
96
 
97
/* Descriptor type definitions. */
98
#define usbDESCRIPTOR_TYPE_DEVICE                       ( 0x01 )
99
#define usbDESCRIPTOR_TYPE_CONFIGURATION        ( 0x02 )
100
#define usbDESCRIPTOR_TYPE_STRING                       ( 0x03 )
101
 
102
/* USB request type definitions. */
103
#define usbGET_REPORT_REQUEST                           ( 0x01 )
104
#define usbGET_IDLE_REQUEST                                     ( 0x02 )
105
#define usbGET_PROTOCOL_REQUEST                         ( 0x03 )
106
#define usbSET_REPORT_REQUEST                           ( 0x09 )
107
#define usbSET_IDLE_REQUEST                                     ( 0x0A )
108
#define usbSET_PROTOCOL_REQUEST                         ( 0x0B )
109
#define usbGET_CONFIGURATION_REQUEST            ( 0x08 )
110
#define usbGET_STATUS_REQUEST                           ( 0x00 )
111
#define usbCLEAR_FEATURE_REQUEST                        ( 0x01 )
112
#define usbSET_FEATURE_REQUEST                          ( 0x03 )
113
#define usbSET_ADDRESS_REQUEST                          ( 0x05 )
114
#define usbGET_DESCRIPTOR_REQUEST                       ( 0x06 )
115
#define usbSET_CONFIGURATION_REQUEST            ( 0x09 )
116
#define usbGET_INTERFACE_REQUEST                        ( 0x0A )
117
#define usbSET_INTERFACE_REQUEST                        ( 0x0B )
118
 
119
 
120
/* Misc USB definitions. */
121
#define usbDEVICE_CLASS_VENDOR_SPECIFIC         ( 0xFF )
122
#define usbBUS_POWERED                                          ( 0x80 )
123
#define usbHID_REPORT_DESCRIPTOR                        ( 0x22 )
124
#define AT91C_UDP_TRANSCEIVER_ENABLE                    ( *( ( unsigned long * ) 0xfffb0074 ) )
125
 
126
/* Index to the various string. */
127
#define usbLANGUAGE_STRING                                      ( 0 )
128
#define usbMANUFACTURER_STRING                          ( 1 )
129
#define usbPRODUCT_STRING                                       ( 2 )
130
#define usbCONFIGURATION_STRING                         ( 3 )
131
#define usbINTERFACE_STRING                                     ( 4 )
132
 
133
/* Data indexes for reading the request from the xISRStatus.ucFifoData[]
134
into xUSB_REQUEST.  The data order is designed for speed - so looks a
135
little odd. */
136
#define usbREQUEST_TYPE_INDEX                           ( 7 )
137
#define usbREQUEST_INDEX                                        ( 6 )
138
#define usbVALUE_HIGH_BYTE                                      ( 4 )
139
#define usbVALUE_LOW_BYTE                                       ( 5 )
140
#define usbINDEX_HIGH_BYTE                                      ( 2 )
141
#define usbINDEX_LOW_BYTE                                       ( 3 )
142
#define usbLENGTH_HIGH_BYTE                                     ( 0 )
143
#define usbLENGTH_LOW_BYTE                                      ( 1 )
144
 
145
/* Misc application definitions. */
146
#define usbINTERRUPT_PRIORITY                           ( 3 )
147
#define usbQUEUE_LENGTH                                         ( 0x3 ) /* Must have all bits set! */
148
#define usbFIFO_LENGTH                                          ( ( unsigned long ) 8 )
149
#define usbEND_POINT_0                                          ( 0 )
150
#define usbEND_POINT_1                                          ( 1 )
151
#define usbXUP                                                          ( 1 )
152
#define usbXDOWN                                                        ( 2 )
153
#define usbYUP                                                          ( 3 )
154
#define usbYDOWN                                                        ( 4 )
155
#define usbMAX_COORD                                            ( 120 )
156
#define usbMAX_TX_MESSAGE_SIZE                          ( 128 )
157
#define usbRX_COUNT_MASK                                        ( ( unsigned long ) 0x7ff )
158
#define AT91C_UDP_STALLSENT                                     AT91C_UDP_ISOERROR
159
#define usbSHORTEST_DELAY                                       ( ( portTickType ) 1 )
160
#define usbINIT_DELAY                                           ( ( portTickType ) 500 / portTICK_RATE_MS )
161
#define usbSHORT_DELAY                                          ( ( portTickType ) 50 / portTICK_RATE_MS )
162
#define usbEND_POINT_RESET_MASK                         ( ( unsigned long ) 0x0f )
163
#define usbDATA_INC                                                     ( ( char ) 5 )
164
#define usbEXPECTED_NUMBER_OF_BYTES                     ( ( unsigned long ) 8 )
165
 
166
/* Control request types. */
167
#define usbSTANDARD_DEVICE_REQUEST                      ( 0 )
168
#define usbSTANDARD_INTERFACE_REQUEST           ( 1 )
169
#define usbSTANDARD_END_POINT_REQUEST           ( 2 )
170
#define usbCLASS_INTERFACE_REQUEST                      ( 5 )
171
 
172
/*-----------------------------------------------------------*/
173
 
174
/* Structure used to take a snapshot of the USB status from within the ISR. */
175
typedef struct X_ISR_STATUS
176
{
177
        unsigned long ulISR;
178
        unsigned long ulCSR0;
179
        unsigned char ucFifoData[ 8 ];
180
} xISRStatus;
181
 
182
/* Structure used to hold the received requests. */
183
typedef struct
184
{
185
        unsigned char ucReqType;
186
        unsigned char ucRequest;
187
        unsigned short usValue;
188
        unsigned short usIndex;
189
        unsigned short usLength;
190
} xUSB_REQUEST;
191
 
192
typedef enum
193
{
194
        eNOTHING,
195
        eJUST_RESET,
196
        eJUST_GOT_CONFIG,
197
        eJUST_GOT_ADDRESS,
198
        eSENDING_EVEN_DESCRIPTOR,
199
        eREADY_TO_SEND
200
} eDRIVER_STATE;
201
 
202
/* Structure used to control the data being sent to the host. */
203
typedef struct
204
{
205
        unsigned char ucTxBuffer[ usbMAX_TX_MESSAGE_SIZE ];
206
        unsigned long ulNextCharIndex;
207
        unsigned long ulTotalDataLength;
208
} xTX_MESSAGE;
209
 
210
/*-----------------------------------------------------------*/
211
 
212
/*
213
 * The USB interrupt service routine.  This takes a snapshot of the USB
214
 * device at the time of the interrupt, clears the interrupts, and posts
215
 * the data to the USB processing task.
216
 */
217
__arm void vUSB_ISR( void );
218
 
219
/*
220
 * Called after the bus reset interrupt - this function readies all the
221
 * end points for communication.
222
 */
223
static void prvResetEndPoints( void );
224
 
225
/*
226
 * Setup the USB hardware, install the interrupt service routine and
227
 * initialise all the state variables.
228
 */
229
static void vInitUSBInterface( void );
230
 
231
/*
232
 * Decode and act upon an interrupt generated by the control end point.
233
 */
234
static void prvProcessEndPoint0Interrupt( xISRStatus *pxMessage );
235
 
236
/*
237
 * For simplicity requests are separated into device, interface, class
238
 * interface and end point requests.
239
 *
240
 * Decode and handle standard device requests originating on the control
241
 * end point.
242
 */
243
static void prvHandleStandardDeviceRequest( xUSB_REQUEST *pxRequest );
244
 
245
/*
246
 * For simplicity requests are separated into device, interface, class
247
 * interface and end point requests.
248
 *
249
 * Decode and handle standard interface requests originating on the control
250
 * end point.
251
 */
252
static void prvHandleStandardInterfaceRequest( xUSB_REQUEST *pxRequest );
253
 
254
/*
255
 * For simplicity requests are separated into device, interface, class
256
 * interface and end point requests.
257
 *
258
 * Decode and handle standard end point requests originating on the control
259
 * end point.
260
 */
261
static void prvHandleStandardEndPointRequest( xUSB_REQUEST *pxRequest );
262
 
263
/*
264
 * For simplicity requests are separated into device, interface, class
265
 * interface and end point requests.
266
 *
267
 * Decode and handle the class interface requests.
268
 */
269
static void prvHandleClassInterfaceRequest( xUSB_REQUEST *pxRequest );
270
 
271
/*
272
 * Setup the Tx buffer to send data in response to a control request.
273
 *
274
 * The data to be transmitted is buffered, the state variables are updated,
275
 * then prvSendNextSegment() is called to start the transmission off.  Once
276
 * the first segment has been sent the remaining segments are transmitted
277
 * in response to TXCOMP interrupts until the entire buffer has been
278
 * sent.
279
 */
280
static void prvSendControlData( unsigned char *pucData, unsigned short usRequestedLength, unsigned long ulLengthLeftToSend, long lSendingDescriptor );
281
 
282
/*
283
 * Examine the Tx buffer to see if there is any more data to be transmitted.
284
 *
285
 * If there is data to be transmitted then send the next segment.  A segment
286
 * can have a maximum of 8 bytes (this is defined as the maximum for the end
287
 * point by the descriptor).  The final segment may be less than 8 bytes if
288
 * the total data length was not an exact multiple of 8.
289
 */
290
static void prvSendNextSegment( void );
291
 
292
/*
293
 * A stall condition is forced each time the host makes a request that is not
294
 * supported by this minimal implementation.
295
 *
296
 * A stall is forced by setting the appropriate bit in the end points control
297
 * and status register.
298
 */
299
static void prvSendStall( void );
300
 
301
/*
302
 * A NULL (or zero length packet) is transmitted in acknowledge the reception
303
 * of certain events from the host.
304
 */
305
static void prvUSBTransmitNull( void );
306
 
307
/*
308
 * When the host requests a descriptor this function is called to determine
309
 * which descriptor is being requested and start its transmission.
310
 */
311
static void prvGetStandardInterfaceDescriptor( xUSB_REQUEST *pxRequest );
312
 
313
/*
314
 * This demo USB device enumerates as a simple 3 axis joystick.  Once
315
 * configured this function is periodically called to generate some sample
316
 * joystick data.
317
 *
318
 * The x and y axis are made to move in a square.  The z axis is made to
319
 * repeatedly increment up to its maximum.
320
 */
321
static void prvTransmitSampleValues( void );
322
 
323
/*
324
 * The created task to handle the USB demo functionality.
325
 */
326
void vUSBDemoTask( void *pvParameters );
327
 
328
/*-----------------------------------------------------------*/
329
 
330
/*
331
        - DESCRIPTOR DEFINITIONS -
332
*/
333
 
334
/* String descriptors used during the enumeration process.
335
These take the form:
336
 
337
{
338
        Length of descriptor,
339
        Descriptor type,
340
        Data
341
}
342
*/
343
const char pxLanguageStringDescriptor[] =
344
{
345
        4,
346
        usbDESCRIPTOR_TYPE_STRING,
347
        0x09, 0x04
348
};
349
 
350
const char pxManufacturerStringDescriptor[] =
351
{
352
        18,
353
        usbDESCRIPTOR_TYPE_STRING,
354
 
355
        'F', 0x00,
356
        'r', 0x00,
357
        'e', 0x00,
358
        'e', 0x00,
359
        'R', 0x00,
360
        'T', 0x00,
361
        'O', 0x00,
362
        'S', 0x00
363
};
364
 
365
const char pxProductStringDescriptor[] =
366
{
367
        44,
368
        usbDESCRIPTOR_TYPE_STRING,
369
 
370
        'F', 0x00,
371
        'r', 0x00,
372
        'e', 0x00,
373
        'e', 0x00,
374
        'R', 0x00,
375
        'T', 0x00,
376
        'O', 0x00,
377
        'S', 0x00,
378
        '.', 0x00,
379
        'o', 0x00,
380
        'r', 0x00,
381
        'g', 0x00,
382
        ' ', 0x00,
383
        'J', 0x00,
384
        'o', 0x00,
385
        'y', 0x00,
386
        's', 0x00,
387
        't', 0x00,
388
        'i', 0x00,
389
        'c', 0x00,
390
        'k', 0x00
391
};
392
 
393
const char pxConfigurationStringDescriptor[] =
394
{
395
        38,
396
        usbDESCRIPTOR_TYPE_STRING,
397
 
398
        'C', 0x00,
399
        'o', 0x00,
400
        'n', 0x00,
401
        'f', 0x00,
402
        'i', 0x00,
403
        'g', 0x00,
404
        'u', 0x00,
405
        'r', 0x00,
406
        'a', 0x00,
407
        't', 0x00,
408
        'i', 0x00,
409
        'o', 0x00,
410
        'n', 0x00,
411
        ' ', 0x00,
412
        'N', 0x00,
413
        'a', 0x00,
414
        'm', 0x00,
415
        'e', 0x00
416
};
417
 
418
const char pxInterfaceStringDescriptor[] =
419
{
420
        30,
421
        usbDESCRIPTOR_TYPE_STRING,
422
 
423
        'I', 0x00,
424
        'n', 0x00,
425
        't', 0x00,
426
        'e', 0x00,
427
        'r', 0x00,
428
        'f', 0x00,
429
        'a', 0x00,
430
        'c', 0x00,
431
        'e', 0x00,
432
        ' ', 0x00,
433
        'N', 0x00,
434
        'a', 0x00,
435
        'm', 0x00,
436
        'e', 0x00
437
};
438
 
439
/* Enumeration descriptors. */
440
const char pxReportDescriptor[] =
441
{
442
         0x05,  0x01,   /* USAGE_PAGE (Generic Desktop)         */
443
         0x09,  0x04,   /* USAGE (Joystick)                                     */
444
         0xa1,  0x01,   /* COLLECTION (Application)                     */
445
         0x05,  0x01,   /*   USAGE_PAGE (Generic Desktop)       */
446
         0x09,  0x01,   /*   USAGE (Pointer)                            */
447
         0xa1,  0x00,   /*   COLLECTION (Physical)                      */
448
         0x09,  0x30,   /*     USAGE (X)                                        */
449
         0x09,  0x31,   /*     USAGE (Y)                                        */
450
         0x09,  0x32,   /*     USAGE (Z)                                        */
451
         0x15,  0x81,   /*     LOGICAL_MINIMUM (-127)           */
452
         0x25,  0x7f,   /*     LOGICAL_MAXIMUM (127)            */
453
         0x75,  0x08,   /*     REPORT_SIZE (8)                          */
454
         0x95,  0x03,   /*     REPORT_COUNT (3)                         */
455
         0x81,  0x02,   /*     INPUT (Data,Var,Abs)                     */
456
         0xc0,                  /*   END_COLLECTION                                     */
457
         0xc0                   /* END_COLLECTION                                       */
458
};
459
 
460
const char pxDeviceDescriptor[] =
461
{
462
        /* Device descriptor */
463
        0x12,                                                           /* bLength                              */
464
        0x01,                                                           /* bDescriptorType              */
465
        0x10, 0x01,                                                     /* bcdUSBL                              */
466
        usbDEVICE_CLASS_VENDOR_SPECIFIC,        /* bDeviceClass:                */
467
        0x00,                                                           /* bDeviceSubclass:             */
468
        0x00,                                                           /* bDeviceProtocol:             */
469
        0x08,                                                           /* bMaxPacketSize0              */
470
        0xFF, 0xFF,                                                     /* idVendorL                    */
471
        0x01, 0x00,                                                     /* idProductL                   */
472
        0x00, 0x01,                                                     /* bcdDeviceL                   */
473
        usbMANUFACTURER_STRING,                         /* iManufacturer                */
474
        usbPRODUCT_STRING,                                      /* iProduct                             */
475
        0x00,                                                           /* SerialNumber                 */
476
        0x01                                                            /* bNumConfigs                  */
477
};
478
 
479
const char pxConfigDescriptor[] = {
480
        /* Configuration 1 descriptor */
481
        0x09,                   /* CbLength                                                                     */
482
        0x02,                   /* CbDescriptorType                                                     */
483
        0x22, 0x00,             /* CwTotalLength 2 EP + Control                         */
484
        0x01,                   /* CbNumInterfaces                                                      */
485
        0x01,                   /* CbConfigurationValue                                         */
486
        usbCONFIGURATION_STRING,/* CiConfiguration                                      */
487
        usbBUS_POWERED, /* CbmAttributes Bus powered + Remote Wakeup*/
488
        0x32,                   /* CMaxPower: 100mA                                                     */
489
 
490
        /* Joystick Interface Descriptor Requirement */
491
        0x09,                   /* bLength                                                                      */
492
        0x04,                   /* bDescriptorType                                                      */
493
        0x00,                   /* bInterfaceNumber                                                     */
494
        0x00,                   /* bAlternateSetting                                            */
495
        0x01,                   /* bNumEndpoints                                                        */
496
        0x03,                   /* bInterfaceClass: HID code                            */
497
        0x00,                   /* bInterfaceSubclass                                           */
498
        0x00,                   /* bInterfaceProtocol                                           */
499
        usbINTERFACE_STRING,/* iInterface                                                       */
500
 
501
        /* HID Descriptor */
502
        0x09,                   /* bLength                                                                      */
503
        0x21,                   /* bDescriptor type: HID Descriptor Type        */
504
        0x00, 0x01,             /* bcdHID                                                                       */
505
        0x00,                   /* bCountryCode                                                         */
506
        0x01,                   /* bNumDescriptors                                                      */
507
        usbHID_REPORT_DESCRIPTOR,         /* bDescriptorType                    */
508
        sizeof( pxReportDescriptor ), 0x00, /* wItemLength                      */
509
 
510
        /* Endpoint 1 descriptor */
511
        0x07,                   /* bLength                                                                      */
512
        0x05,                   /* bDescriptorType                                                      */
513
        0x81,                   /* bEndpointAddress, Endpoint 01 - IN           */
514
        0x03,                   /* bmAttributes      INT                                        */
515
        0x03, 0x00,             /* wMaxPacketSize: 3 bytes (x, y, z)            */
516
        0x0A                    /* bInterval                                                            */
517
};
518
 
519
/*-----------------------------------------------------------*/
520
 
521
/* File scope state variables. */
522
static unsigned char ucUSBConfig = ( unsigned char ) 0;
523
static unsigned long ulReceivedAddress = ( unsigned long ) 0;
524
static eDRIVER_STATE eDriverState = eNOTHING;
525
 
526
/* Array in which the USB interrupt status is passed between the ISR and task. */
527
static xISRStatus xISRMessages[ usbQUEUE_LENGTH + 1 ];
528
 
529
/* Structure used to control the characters being sent to the host. */
530
static xTX_MESSAGE pxCharsForTx;
531
 
532
/* Queue used to pass messages between the ISR and the task. */
533
static xQueueHandle xUSBInterruptQueue;
534
 
535
/* ISR entry has to be written in the asm file as we want a context switch
536
to occur from within the ISR.  See the port documentation on the FreeRTOS.org
537
WEB site for more information. */
538
extern void vUSBISREntry( void );
539
 
540
/*-----------------------------------------------------------*/
541
 
542
/* Macros to manipulate the control and status registers.  These registers
543
cannot be accessed using a direct read modify write operation outside of the
544
ISR as some bits are left unchanged by writing with a 0, and some are left
545
unchanged by writing with a 1. */
546
 
547
#define usbINT_CLEAR_MASK       (AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP | AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 )
548
 
549
#define usbCSR_SET_BIT( pulValueNow, ulBit )                                                                                    \
550
{                                                                                                                                                                               \
551
        /* Set TXCOMP, RX_DATA_BK0, RXSETUP, */                                                                                         \
552
        /* STALLSENT and RX_DATA_BK1 to 1 so the */                                                                                     \
553
        /* write has no effect. */                                                                                                                      \
554
        ( * ( ( unsigned long * ) pulValueNow ) ) |= ( unsigned long ) 0x4f;            \
555
                                                                                                                                                                                \
556
        /* Clear the FORCE_STALL and TXPKTRDY bits */                                                                           \
557
        /* so the write has no effect. */                                                                                                       \
558
        ( * ( ( unsigned long * ) pulValueNow ) ) &= ( unsigned long ) 0xffffffcf;      \
559
                                                                                                                                                                                \
560
        /* Set whichever bit we want set. */                                                                                            \
561
        ( * ( ( unsigned long * ) pulValueNow ) ) |= ( ulBit );                                                 \
562
}
563
 
564
#define usbCSR_CLEAR_BIT( pulValueNow, ulBit )                                                                                  \
565
{                                                                                                                                                                               \
566
        /* Set TXCOMP, RX_DATA_BK0, RXSETUP, */                                                                                         \
567
        /* STALLSENT and RX_DATA_BK1 to 1 so the */                                                                                     \
568
        /* write has no effect. */                                                                                                                      \
569
        ( * ( ( unsigned long * ) pulValueNow ) ) |= ( unsigned long ) 0x4f;            \
570
                                                                                                                                                                                \
571
        /* Clear the FORCE_STALL and TXPKTRDY bits */                                                                           \
572
        /* so the write has no effect. */                                                                                                       \
573
        ( * ( ( unsigned long * ) pulValueNow ) ) &= ( unsigned long ) 0xffffffcf;      \
574
                                                                                                                                                                                \
575
        /* Clear whichever bit we want clear. */                                                                                        \
576
        ( * ( ( unsigned long * ) pulValueNow ) ) &= ( ~ulBit );                                                \
577
}
578
 
579
/*-----------------------------------------------------------*/
580
 
581
__arm void vUSB_ISR( void )
582
{
583
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
584
static volatile unsigned long ulNextMessage = 0;
585
xISRStatus *pxMessage;
586
unsigned long ulTemp, ulRxBytes;
587
 
588
        /* Take the next message from the queue.  Note that usbQUEUE_LENGTH *must*
589
        be all 1's, as in 0x01, 0x03, 0x07, etc. */
590
        pxMessage = &( xISRMessages[ ( ulNextMessage & usbQUEUE_LENGTH ) ] );
591
        ulNextMessage++;
592
 
593
        /* Take a snapshot of the current USB state for processing at the task
594
        level. */
595
        pxMessage->ulISR = AT91C_BASE_UDP->UDP_ISR;
596
        pxMessage->ulCSR0 = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
597
 
598
        /* Clear the interrupts from the ICR register.  The bus end interrupt is
599
        cleared separately as it does not appear in the mask register. */
600
        AT91C_BASE_UDP->UDP_ICR = AT91C_BASE_UDP->UDP_IMR | AT91C_UDP_ENDBUSRES;
601
 
602
        /* If there are bytes in the FIFO then we have to retrieve them here.
603
        Ideally this would be done at the task level.  However we need to clear the
604
        RXSETUP interrupt before leaving the ISR, and this may cause the data in
605
        the FIFO to be overwritten.  Also the DIR bit has to be changed before the
606
        RXSETUP bit is cleared (as per the SAM7 manual). */
607
        ulTemp = pxMessage->ulCSR0;
608
 
609
        /* Are there any bytes in the FIFO? */
610
        ulRxBytes = ulTemp >> 16;
611
        ulRxBytes &= usbRX_COUNT_MASK;
612
 
613
        /* With this minimal implementation we are only interested in receiving
614
        setup bytes on the control end point. */
615
        if( ( ulRxBytes > 0 ) && ( ulTemp & AT91C_UDP_RXSETUP ) )
616
        {
617
                /* Take off 1 for a zero based index. */
618
                while( ulRxBytes > 0 )
619
                {
620
                        ulRxBytes--;
621
                        pxMessage->ucFifoData[ ulRxBytes ] = AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_0 ];
622
                }
623
 
624
                /* The direction must be changed first. */
625
                usbCSR_SET_BIT( &ulTemp, ( AT91C_UDP_DIR ) );
626
                AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulTemp;
627
        }
628
 
629
        /* Must write zero's to TXCOMP, STALLSENT, RXSETUP, and the RX DATA
630
        registers to clear the interrupts in the CSR register. */
631
        usbCSR_CLEAR_BIT( &ulTemp, usbINT_CLEAR_MASK );
632
        AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulTemp;
633
 
634
        /* Also clear the interrupts in the CSR1 register. */
635
        ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];
636
        usbCSR_CLEAR_BIT( &ulTemp, usbINT_CLEAR_MASK );
637
        AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulTemp;
638
 
639
        /* The message now contains the entire state and optional data from
640
        the USB interrupt.  This can now be posted on the Rx queue ready for
641
        processing at the task level. */
642
        xQueueSendFromISR( xUSBInterruptQueue, &pxMessage, &xHigherPriorityTaskWoken );
643
 
644
        /* We may want to switch to the USB task, if this message has made
645
        it the highest priority task that is ready to execute. */
646
        portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
647
 
648
        /* Clear the AIC ready for the next interrupt. */
649
        AT91C_BASE_AIC->AIC_EOICR = 0;
650
}
651
/*-----------------------------------------------------------*/
652
 
653
void vUSBDemoTask( void *pvParameters )
654
{
655
xISRStatus *pxMessage;
656
 
657
        /* The parameters are not used in this task. */
658
        ( void ) pvParameters;
659
 
660
    /* Init USB device */
661
    portENTER_CRITICAL();
662
            vInitUSBInterface();
663
    portEXIT_CRITICAL();
664
 
665
        /* Process interrupts as they arrive.   The ISR takes a snapshot of the
666
        interrupt status then posts the information on this queue for processing
667
        at the task level.  This simple demo implementation only processes
668
        a few interrupt sources. */
669
        for( ;; )
670
        {
671
                if( xQueueReceive( xUSBInterruptQueue, &pxMessage, usbSHORT_DELAY ) )
672
                {
673
                        if( pxMessage->ulISR & AT91C_UDP_EPINT0 )
674
                        {
675
                                /* Process end point 0 interrupt. */
676
                                prvProcessEndPoint0Interrupt( pxMessage );
677
                        }
678
 
679
                        if( pxMessage->ulISR & AT91C_UDP_ENDBUSRES )
680
                        {
681
                                /* Process an end of bus reset interrupt. */
682
                                prvResetEndPoints();
683
                        }
684
                }
685
                else
686
                {
687
                        /* The ISR did not post any data for us to process on the queue, so
688
                        just generate and send some sample data. */
689
                        if( eDriverState == eREADY_TO_SEND )
690
                        {
691
                                prvTransmitSampleValues();
692
                        }
693
                }
694
        }
695
}
696
/*-----------------------------------------------------------*/
697
 
698
static void prvTransmitSampleValues( void )
699
{
700
unsigned long ulStatus;
701
static long lState = usbXUP;
702
 
703
/* Variables to hold dummy x, y and z joystick axis data. */
704
static signed char x = 0, y = 0, z = 0;
705
 
706
        /* Generate some sample data in the x and y axis - draw a square. */
707
        switch( lState )
708
        {
709
                case usbXUP     :       x += usbDATA_INC;
710
                                                if( x >= usbMAX_COORD )
711
                                                {
712
                                                        lState = usbYUP;
713
                                                }
714
                                                break;
715
 
716
                case usbXDOWN : x -= usbDATA_INC;
717
                                                if( x <= -usbMAX_COORD )
718
                                                {
719
                                                        lState = usbYDOWN;
720
                                                }
721
                                                break;
722
 
723
                case usbYUP :   y += usbDATA_INC;
724
                                                if( y >= usbMAX_COORD )
725
                                                {
726
                                                        lState = usbXDOWN;
727
                                                }
728
                                                break;
729
 
730
                case usbYDOWN : y -= usbDATA_INC;
731
                                                if( y <= -usbMAX_COORD )
732
                                                {
733
                                                        lState = usbXUP;
734
                                                }
735
                                                break;
736
        }
737
 
738
        /* Just make the z axis go up and down. */
739
        z += usbDATA_INC;
740
 
741
        /* Can we place data in the fifo? */
742
        if( !( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] & AT91C_UDP_TXPKTRDY ) )
743
        {
744
                /* Write our sample data to the fifo. */
745
                AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_1 ] = x;
746
                AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_1 ] = y;
747
                AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_1 ] = z;
748
 
749
                /* Send the data. */
750
                portENTER_CRITICAL();
751
                {
752
                        ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];
753
                        usbCSR_SET_BIT( &ulStatus, ( AT91C_UDP_TXPKTRDY ) );
754
                        AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulStatus;
755
                }
756
                portEXIT_CRITICAL();
757
        }
758
}
759
/*-----------------------------------------------------------*/
760
 
761
static void prvUSBTransmitNull( void )
762
{
763
unsigned long ulStatus;
764
 
765
        /* Wait until the FIFO is free - even though we are not going to use it.
766
        THERE IS NO TIMEOUT HERE! */
767
        while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_TXPKTRDY )
768
        {
769
                vTaskDelay( usbSHORTEST_DELAY );
770
        }
771
 
772
        portENTER_CRITICAL();
773
        {
774
                /* Set the length of data to send to equal the index of the next byte
775
                to send.  This will prevent the ACK to this NULL packet causing any
776
                further data transmissions. */
777
                pxCharsForTx.ulTotalDataLength = pxCharsForTx.ulNextCharIndex;
778
 
779
                /* Set the TXPKTRDY bit to cause a transmission with no data. */
780
                ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
781
                usbCSR_SET_BIT( &ulStatus, ( AT91C_UDP_TXPKTRDY ) );
782
                AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
783
        }
784
        portEXIT_CRITICAL();
785
}
786
/*-----------------------------------------------------------*/
787
 
788
static void prvSendStall( void )
789
{
790
unsigned long ulStatus;
791
 
792
        portENTER_CRITICAL();
793
        {
794
                /* Force a stall by simply setting the FORCESTALL bit in the CSR. */
795
                ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
796
                usbCSR_SET_BIT( &ulStatus, AT91C_UDP_FORCESTALL );
797
                AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
798
        }
799
        portEXIT_CRITICAL();
800
}
801
/*-----------------------------------------------------------*/
802
 
803
static void prvResetEndPoints( void )
804
{
805
unsigned long ulTemp;
806
 
807
        eDriverState = eJUST_RESET;
808
 
809
        /* Reset all the end points. */
810
        AT91C_BASE_UDP->UDP_RSTEP  = usbEND_POINT_RESET_MASK;
811
        AT91C_BASE_UDP->UDP_RSTEP  = ( unsigned long ) 0x00;
812
 
813
        /* Enable data to be sent and received. */
814
        AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
815
 
816
        /* Repair the configuration end point. */
817
        portENTER_CRITICAL();
818
        {
819
                ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
820
                usbCSR_SET_BIT( &ulTemp, ( ( unsigned long ) ( AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL ) ) );
821
                AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulTemp;
822
                AT91F_UDP_EnableIt( AT91C_BASE_UDP, AT91C_UDP_EPINT0 );
823
        }
824
        portEXIT_CRITICAL();
825
}
826
/*-----------------------------------------------------------*/
827
 
828
static void prvProcessEndPoint0Interrupt( xISRStatus *pxMessage )
829
{
830
        if( pxMessage->ulCSR0 & AT91C_UDP_RX_DATA_BK0 )
831
        {
832
                /* We only expect to receive zero length data here as ACK's.
833
                Set the data pointer to the end of the current Tx packet to
834
                ensure we don't send out any more data. */
835
                pxCharsForTx.ulNextCharIndex = pxCharsForTx.ulTotalDataLength;
836
        }
837
 
838
        if( pxMessage->ulCSR0 & AT91C_UDP_TXCOMP )
839
        {
840
                /* We received a TX complete interrupt.  What we do depends on
841
                what we sent to get this interrupt. */
842
 
843
                if( eDriverState == eJUST_GOT_CONFIG )
844
                {
845
                        /* We sent an acknowledgement of a SET_CONFIG request.  We
846
                        are now at the end of the enumeration. */
847
                        AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_CONFG;
848
 
849
                        /* Read the end point for data transfer. */
850
                        portENTER_CRITICAL();
851
                        {
852
                                unsigned long ulTemp;
853
 
854
                                ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];
855
                                usbCSR_SET_BIT( &ulTemp, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN );
856
                                AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulTemp;
857
                                AT91F_UDP_EnableIt( AT91C_BASE_UDP, AT91C_UDP_EPINT1 );
858
                        }
859
                        portEXIT_CRITICAL();
860
 
861
                        eDriverState = eREADY_TO_SEND;
862
                }
863
                else if( eDriverState == eJUST_GOT_ADDRESS )
864
                {
865
                        /* We sent an acknowledgement of a SET_ADDRESS request.  Move
866
                        to the addressed state. */
867
                        if( ulReceivedAddress != ( unsigned long ) 0 )
868
                        {
869
                                AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
870
                        }
871
                        else
872
                        {
873
                                AT91C_BASE_UDP->UDP_GLBSTATE = 0;
874
                        }
875
 
876
                        AT91C_BASE_UDP->UDP_FADDR = ( AT91C_UDP_FEN | ulReceivedAddress );
877
                        eDriverState = eNOTHING;
878
                }
879
                else
880
                {
881
                        /* The TXCOMP was not for any special type of transmission.  See
882
                        if there is any more data to send. */
883
                        prvSendNextSegment();
884
                }
885
        }
886
 
887
        if( pxMessage->ulCSR0 & AT91C_UDP_RXSETUP )
888
        {
889
                xUSB_REQUEST xRequest;
890
                unsigned char ucRequest;
891
                unsigned long ulRxBytes;
892
 
893
                /* A data packet is available. */
894
                ulRxBytes = pxMessage->ulCSR0 >> 16;
895
                ulRxBytes &= usbRX_COUNT_MASK;
896
 
897
                if( ulRxBytes >= usbEXPECTED_NUMBER_OF_BYTES )
898
                {
899
                        /* Create an xUSB_REQUEST variable from the raw bytes array. */
900
 
901
                        xRequest.ucReqType = pxMessage->ucFifoData[ usbREQUEST_TYPE_INDEX ];
902
                        xRequest.ucRequest = pxMessage->ucFifoData[ usbREQUEST_INDEX ];
903
 
904
                        /* NOT PORTABLE CODE! */
905
                        xRequest.usValue = pxMessage->ucFifoData[ usbVALUE_HIGH_BYTE ];
906
                        xRequest.usValue <<= 8;
907
                        xRequest.usValue |= pxMessage->ucFifoData[ usbVALUE_LOW_BYTE ];
908
 
909
                        xRequest.usIndex = pxMessage->ucFifoData[ usbINDEX_HIGH_BYTE ];
910
                        xRequest.usIndex <<= 8;
911
                        xRequest.usIndex |= pxMessage->ucFifoData[ usbINDEX_LOW_BYTE ];
912
 
913
                        xRequest.usLength = pxMessage->ucFifoData[ usbLENGTH_HIGH_BYTE ];
914
                        xRequest.usLength <<= 8;
915
                        xRequest.usLength |= pxMessage->ucFifoData[ usbLENGTH_LOW_BYTE ];
916
 
917
                        /* Manipulate the ucRequestType and the ucRequest parameters to
918
                        generate a zero based request selection.  This is just done to
919
                        break up the requests into subsections for clarity.  The
920
                        alternative would be to have more huge switch statement that would
921
                        be difficult to optimise. */
922
                        ucRequest = ( ( xRequest.ucReqType & 0x60 ) >> 3 );
923
                        ucRequest |= ( xRequest.ucReqType & 0x03 );
924
 
925
                        switch( ucRequest )
926
                        {
927
                                case usbSTANDARD_DEVICE_REQUEST:
928
                                                        /* Standard Device request */
929
                                                        prvHandleStandardDeviceRequest( &xRequest );
930
                                                        break;
931
 
932
                                case usbSTANDARD_INTERFACE_REQUEST:
933
                                                        /* Standard Interface request */
934
                                                        prvHandleStandardInterfaceRequest( &xRequest );
935
                                                        break;
936
 
937
                                case usbSTANDARD_END_POINT_REQUEST:
938
                                                        /* Standard Endpoint request */
939
                                                        prvHandleStandardEndPointRequest( &xRequest );
940
                                                        break;
941
 
942
                                case usbCLASS_INTERFACE_REQUEST:
943
                                                        /* Class Interface request */
944
                                                        prvHandleClassInterfaceRequest( &xRequest );
945
                                                        break;
946
 
947
                                default:        /* This is not something we want to respond to. */
948
                                                        prvSendStall();
949
                        }
950
                }
951
        }
952
}
953
/*-----------------------------------------------------------*/
954
 
955
static void prvGetStandardDeviceDescriptor( xUSB_REQUEST *pxRequest )
956
{
957
        /* The type is in the high byte.  Return whatever has been requested. */
958
        switch( ( pxRequest->usValue & 0xff00 ) >> 8 )
959
        {
960
            case usbDESCRIPTOR_TYPE_DEVICE:
961
                        prvSendControlData( ( unsigned char * ) &pxDeviceDescriptor, pxRequest->usLength, sizeof( pxDeviceDescriptor ), pdTRUE );
962
                    break;
963
 
964
            case usbDESCRIPTOR_TYPE_CONFIGURATION:
965
                        prvSendControlData( ( unsigned char * ) &( pxConfigDescriptor ), pxRequest->usLength, sizeof( pxConfigDescriptor ), pdTRUE );
966
                    break;
967
 
968
            case usbDESCRIPTOR_TYPE_STRING:
969
 
970
                        /* The index to the string descriptor is the lower byte. */
971
                    switch( pxRequest->usValue & 0xff )
972
                        {
973
                        case usbLANGUAGE_STRING:
974
                                        prvSendControlData( ( unsigned char * ) &pxLanguageStringDescriptor, pxRequest->usLength, sizeof(pxLanguageStringDescriptor), pdTRUE );
975
                                break;
976
 
977
                        case usbMANUFACTURER_STRING:
978
                                        prvSendControlData( ( unsigned char * ) &pxManufacturerStringDescriptor, pxRequest->usLength, sizeof( pxManufacturerStringDescriptor ), pdTRUE );
979
                                break;
980
 
981
                        case usbPRODUCT_STRING:
982
                                        prvSendControlData( ( unsigned char * ) &pxProductStringDescriptor, pxRequest->usLength, sizeof( pxProductStringDescriptor ), pdTRUE );
983
                                break;
984
 
985
                        case usbCONFIGURATION_STRING:
986
                                        prvSendControlData( ( unsigned char * ) &pxConfigurationStringDescriptor, pxRequest->usLength, sizeof( pxConfigurationStringDescriptor ), pdTRUE );
987
                                break;
988
 
989
                        case usbINTERFACE_STRING:
990
                                        prvSendControlData( ( unsigned char * ) &pxInterfaceStringDescriptor, pxRequest->usLength, sizeof( pxInterfaceStringDescriptor ), pdTRUE );
991
                                break;
992
 
993
                        default:
994
                                /* Don't know what this string is. */
995
                                        prvSendStall();
996
                                        break;
997
                        }
998
 
999
                        break;
1000
 
1001
            default:
1002
                        /* We are not responding to anything else. */
1003
                        prvSendStall();
1004
                    break;
1005
        }
1006
}
1007
/*-----------------------------------------------------------*/
1008
 
1009
static void prvHandleStandardDeviceRequest( xUSB_REQUEST *pxRequest )
1010
{
1011
unsigned short usStatus = 0;
1012
 
1013
        switch( pxRequest->ucRequest )
1014
        {
1015
            case usbGET_STATUS_REQUEST:
1016
                        /* Just send two byte dummy status. */
1017
                        prvSendControlData( ( unsigned char * ) &usStatus, sizeof( usStatus ), sizeof( usStatus ), pdFALSE );
1018
                    break;
1019
 
1020
            case usbGET_DESCRIPTOR_REQUEST:
1021
                        /* Send device descriptor */
1022
                    prvGetStandardDeviceDescriptor( pxRequest );
1023
                    break;
1024
 
1025
            case usbGET_CONFIGURATION_REQUEST:
1026
                        /* Send selected device configuration */
1027
                        prvSendControlData( ( unsigned char * ) &ucUSBConfig, sizeof( ucUSBConfig ), sizeof( ucUSBConfig ), pdFALSE );
1028
                    break;
1029
 
1030
                case usbSET_FEATURE_REQUEST:
1031
                    prvUSBTransmitNull();
1032
                    break;
1033
 
1034
            case usbSET_ADDRESS_REQUEST:
1035
 
1036
                        /* Acknowledge the SET_ADDRESS, but (according to the manual) we
1037
                        cannot actually move to the addressed state until we get a TXCOMP
1038
                        interrupt from this NULL packet.  Therefore we just remember the
1039
                        address and set our state so we know we have received the address. */
1040
                prvUSBTransmitNull();
1041
                        eDriverState = eJUST_GOT_ADDRESS;
1042
                        ulReceivedAddress = ( unsigned long ) pxRequest->usValue;
1043
                    break;
1044
 
1045
            case usbSET_CONFIGURATION_REQUEST:
1046
 
1047
                        /* Acknowledge the SET_CONFIGURATION, but (according to the manual)
1048
                        we cannot actually move to the configured state until we get a
1049
                        TXCOMP interrupt from this NULL packet.  Therefore we just remember the
1050
                        config and set our state so we know we have received the go ahead. */
1051
                        ucUSBConfig = ( unsigned char ) ( pxRequest->usValue & 0xff );
1052
                        eDriverState = eJUST_GOT_CONFIG;
1053
                        prvUSBTransmitNull();
1054
                    break;
1055
 
1056
            default:
1057
 
1058
                    /* We don't answer to anything else. */
1059
                        prvSendStall();
1060
                    break;
1061
        }
1062
}
1063
/*-----------------------------------------------------------*/
1064
 
1065
static void prvHandleClassInterfaceRequest( xUSB_REQUEST *pxRequest )
1066
{
1067
        switch( pxRequest->ucRequest )
1068
        {
1069
            case usbSET_IDLE_REQUEST:
1070
                prvUSBTransmitNull();
1071
                        break;
1072
 
1073
                /* This minimal implementation ignores these. */
1074
            case usbGET_REPORT_REQUEST:
1075
            case usbGET_IDLE_REQUEST:
1076
            case usbGET_PROTOCOL_REQUEST:
1077
            case usbSET_REPORT_REQUEST:
1078
            case usbSET_PROTOCOL_REQUEST:
1079
            default:
1080
 
1081
                        prvSendStall();
1082
                        break;
1083
        }
1084
}
1085
/*-----------------------------------------------------------*/
1086
 
1087
static void prvGetStandardInterfaceDescriptor( xUSB_REQUEST *pxRequest )
1088
{
1089
        switch( ( pxRequest->usValue & ( unsigned short ) 0xff00 ) >> 8 )
1090
        {
1091
            case usbHID_REPORT_DESCRIPTOR:
1092
                        prvSendControlData( ( unsigned char * ) pxReportDescriptor, pxRequest->usLength, sizeof( pxReportDescriptor ), pdTRUE );
1093
                    break;
1094
 
1095
            default:
1096
 
1097
                        /* Don't expect to send any others. */
1098
                        prvSendStall();
1099
                    break;
1100
        }
1101
}
1102
/*-----------------------------------------------------------*/
1103
 
1104
static void prvHandleStandardInterfaceRequest( xUSB_REQUEST *pxRequest )
1105
{
1106
unsigned short usStatus = 0;
1107
 
1108
        switch( pxRequest->ucRequest )
1109
        {
1110
            case usbGET_STATUS_REQUEST:
1111
                        /* Send dummy 2 bytes. */
1112
                        prvSendControlData( ( unsigned char * ) &usStatus, sizeof( usStatus ), sizeof( usStatus ), pdFALSE );
1113
                        break;
1114
 
1115
            case usbGET_DESCRIPTOR_REQUEST:
1116
                        prvGetStandardInterfaceDescriptor( pxRequest );
1117
                        break;
1118
 
1119
                /* This minimal implementation does not respond to these. */
1120
            case usbGET_INTERFACE_REQUEST:
1121
            case usbSET_FEATURE_REQUEST:
1122
            case usbSET_INTERFACE_REQUEST:
1123
 
1124
            default:
1125
                        prvSendStall();
1126
                        break;
1127
        }
1128
}
1129
/*-----------------------------------------------------------*/
1130
 
1131
static void prvHandleStandardEndPointRequest( xUSB_REQUEST *pxRequest )
1132
{
1133
        switch( pxRequest->ucRequest )
1134
        {
1135
                /* This minimal implementation does not expect to respond to these. */
1136
            case usbGET_STATUS_REQUEST:
1137
            case usbCLEAR_FEATURE_REQUEST:
1138
            case usbSET_FEATURE_REQUEST:
1139
 
1140
            default:
1141
                        prvSendStall();
1142
                        break;
1143
        }
1144
}
1145
/*-----------------------------------------------------------*/
1146
 
1147
static void vInitUSBInterface( void )
1148
{
1149
volatile unsigned long ulTemp;
1150
 
1151
        /* Create the queue used to communicate between the USB ISR and task. */
1152
        xUSBInterruptQueue = xQueueCreate( usbQUEUE_LENGTH + 1, sizeof( xISRStatus * ) );
1153
 
1154
        /* Initialise a few state variables. */
1155
        pxCharsForTx.ulNextCharIndex = ( unsigned long ) 0;
1156
        ucUSBConfig = ( unsigned char ) 0;
1157
        eDriverState = eNOTHING;
1158
 
1159
        /* HARDWARE SETUP */
1160
 
1161
    /* Set the PLL USB Divider */
1162
    AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1;
1163
 
1164
    /* Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock. */
1165
    AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
1166
    AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
1167
 
1168
    /* Setup the PIO for the USB pull up resistor. */
1169
    AT91F_PIO_CfgOutput(AT91C_BASE_PIOA,AT91C_PIO_PA16);
1170
 
1171
    /* Start without the pullup - this will get set at the end of this
1172
        function. */
1173
    AT91F_PIO_SetOutput( AT91C_BASE_PIOA, AT91C_PIO_PA16 );
1174
 
1175
        /* When using the USB debugger the peripheral registers do not always get
1176
        set to the correct default values.  To make sure set the relevant registers
1177
        manually here. */
1178
        AT91C_BASE_UDP->UDP_IDR = ( unsigned long ) 0xffffffff;
1179
        AT91C_BASE_UDP->UDP_ICR = ( unsigned long ) 0xffffffff;
1180
        AT91C_BASE_UDP->UDP_CSR[ 0 ] = ( unsigned long ) 0x00;
1181
        AT91C_BASE_UDP->UDP_CSR[ 1 ] = ( unsigned long ) 0x00;
1182
        AT91C_BASE_UDP->UDP_GLBSTATE = 0;
1183
        AT91C_BASE_UDP->UDP_FADDR = 0;
1184
 
1185
        /* Enable the transceiver. */
1186
        AT91C_UDP_TRANSCEIVER_ENABLE = 0;
1187
 
1188
        /* Enable the USB interrupts - other interrupts get enabled as the
1189
        enumeration process progresses. */
1190
        AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, AT91C_ID_UDP, usbINTERRUPT_PRIORITY, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, ( void (*)( void ) ) vUSBISREntry );
1191
        AT91F_AIC_EnableIt( AT91C_BASE_AIC, AT91C_ID_UDP );
1192
 
1193
        /* Wait a short while before making our presence known. */
1194
        vTaskDelay( usbINIT_DELAY );
1195
    AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, AT91C_PIO_PA16 );
1196
}
1197
/*-----------------------------------------------------------*/
1198
 
1199
static void prvSendControlData( unsigned char *pucData, unsigned short usRequestedLength, unsigned long ulLengthToSend, long lSendingDescriptor )
1200
{
1201
        if( ( ( unsigned long ) usRequestedLength < ulLengthToSend ) )
1202
        {
1203
                /* Cap the data length to that requested. */
1204
                ulLengthToSend = ( unsigned short ) usRequestedLength;
1205
        }
1206
        else if( ( ulLengthToSend < ( unsigned long ) usRequestedLength ) && lSendingDescriptor )
1207
        {
1208
                /* We are sending a descriptor.  If the descriptor is an exact
1209
                multiple of the FIFO length then it will have to be terminated
1210
                with a NULL packet.  Set the state to indicate this if
1211
                necessary. */
1212
                if( ( ulLengthToSend % usbFIFO_LENGTH ) == 0 )
1213
                {
1214
                        eDriverState = eSENDING_EVEN_DESCRIPTOR;
1215
                }
1216
        }
1217
 
1218
        /* Here we assume that the previous message has been sent.  THERE IS NO
1219
        BUFFER OVERFLOW PROTECTION HERE.
1220
 
1221
        Copy the data to send into the buffer as we cannot send it all at once
1222
        (if it is greater than 8 bytes in length). */
1223
        memcpy( pxCharsForTx.ucTxBuffer, pucData, ulLengthToSend );
1224
 
1225
        /* Reinitialise the buffer index so we start sending from the start of
1226
        the data. */
1227
        pxCharsForTx.ulTotalDataLength = ulLengthToSend;
1228
        pxCharsForTx.ulNextCharIndex = ( unsigned long ) 0;
1229
 
1230
        /* Send the first 8 bytes now.  The rest will get sent in response to
1231
        TXCOMP interrupts. */
1232
        prvSendNextSegment();
1233
}
1234
/*-----------------------------------------------------------*/
1235
 
1236
static void prvSendNextSegment( void )
1237
{
1238
volatile unsigned long ulNextLength, ulStatus, ulLengthLeftToSend;
1239
 
1240
        /* Is there any data to send? */
1241
        if( pxCharsForTx.ulTotalDataLength > pxCharsForTx.ulNextCharIndex )
1242
        {
1243
                ulLengthLeftToSend = pxCharsForTx.ulTotalDataLength - pxCharsForTx.ulNextCharIndex;
1244
 
1245
                /* We can only send 8 bytes to the fifo at a time. */
1246
                if( ulLengthLeftToSend > usbFIFO_LENGTH )
1247
                {
1248
                        ulNextLength = usbFIFO_LENGTH;
1249
                }
1250
                else
1251
                {
1252
                        ulNextLength = ulLengthLeftToSend;
1253
                }
1254
 
1255
                /* Wait until we can place data in the fifo.  THERE IS NO TIMEOUT
1256
                HERE! */
1257
                while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_TXPKTRDY )
1258
                {
1259
                        vTaskDelay( usbSHORTEST_DELAY );
1260
                }
1261
 
1262
                /* Write the data to the FIFO. */
1263
                while( ulNextLength > ( unsigned long ) 0 )
1264
                {
1265
                        AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_0 ] = pxCharsForTx.ucTxBuffer[ pxCharsForTx.ulNextCharIndex ];
1266
 
1267
                        ulNextLength--;
1268
                        pxCharsForTx.ulNextCharIndex++;
1269
                }
1270
 
1271
                /* Start the transmission. */
1272
                portENTER_CRITICAL();
1273
                {
1274
                        ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
1275
                        usbCSR_SET_BIT( &ulStatus, ( ( unsigned long ) 0x10 ) );
1276
                        AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
1277
                }
1278
                portEXIT_CRITICAL();
1279
        }
1280
        else
1281
        {
1282
                /* There is no data to send.  If we were sending a descriptor and the
1283
                descriptor was an exact multiple of the max packet size then we need
1284
                to send a null to terminate the transmission. */
1285
                if( eDriverState == eSENDING_EVEN_DESCRIPTOR )
1286
                {
1287
                        prvUSBTransmitNull();
1288
                        eDriverState = eNOTHING;
1289
                }
1290
        }
1291
}
1292
 
1293
 
1294
 

powered by: WebSVN 2.1.0

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