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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [ARM7_AT91SAM7X256_Eclipse/] [RTOSDemo/] [USB/] [USBSample.c] - Blame information for rev 609

Go to most recent revision | 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 mouse device driver.  This is a minimal implementation
56
        for demonstration only.  Although functional, it may not be a fully and
57
        compliant implementation.  The small joystick on the SAM7X EK can be used to
58
        move the mouse cursor, pressing the joystick transmits mouse clicks.  Note
59
        that it might be necessary to run the demo stand along (without the
60
        debugger) in order for the USB device to be recognised by the host computer.
61
 
62
        The interrupt handler itself is contained within USB_ISR.c.
63
 
64
        See the FreeRTOS.org online documentation for more information.
65
*/
66
 
67
/* Standard includes. */
68
#include <string.h>
69
 
70
/* Scheduler includes. */
71
#include "FreeRTOS.h"
72
#include "task.h"
73
#include "queue.h"
74
 
75
/* Demo application includes. */
76
#include "USBSample.h"
77
 
78
/* Joystick inputs used to move the 'mouse' cursor. */
79
#define usbSW1  ( 1 << 21 )     /* PA21 */
80
#define usbSW2  ( 1 << 22 )     /* PA22 */
81
#define usbSW3  ( 1 << 23 )     /* PA23 */
82
#define usbSW4  ( 1 << 24 )     /* PA24 */
83
#define usbSW_CLICK     ( 1 << 25 ) /* PA25 */
84
 
85
/* Descriptor type definitions. */
86
#define usbDESCRIPTOR_TYPE_DEVICE                       ( 0x01 )
87
#define usbDESCRIPTOR_TYPE_CONFIGURATION        ( 0x02 )
88
#define usbDESCRIPTOR_TYPE_STRING                       ( 0x03 )
89
 
90
/* USB request type definitions. */
91
#define usbGET_REPORT_REQUEST                           ( 0x01 )
92
#define usbGET_IDLE_REQUEST                                     ( 0x02 )
93
#define usbGET_PROTOCOL_REQUEST                         ( 0x03 )
94
#define usbSET_REPORT_REQUEST                           ( 0x09 )
95
#define usbSET_IDLE_REQUEST                                     ( 0x0A )
96
#define usbSET_PROTOCOL_REQUEST                         ( 0x0B )
97
#define usbGET_CONFIGURATION_REQUEST            ( 0x08 )
98
#define usbGET_STATUS_REQUEST                           ( 0x00 )
99
#define usbCLEAR_FEATURE_REQUEST                        ( 0x01 )
100
#define usbSET_FEATURE_REQUEST                          ( 0x03 )
101
#define usbSET_ADDRESS_REQUEST                          ( 0x05 )
102
#define usbGET_DESCRIPTOR_REQUEST                       ( 0x06 )
103
#define usbSET_CONFIGURATION_REQUEST            ( 0x09 )
104
#define usbGET_INTERFACE_REQUEST                        ( 0x0A )
105
#define usbSET_INTERFACE_REQUEST                        ( 0x0B )
106
 
107
 
108
/* Misc USB definitions. */
109
#define usbDEVICE_CLASS_VENDOR_SPECIFIC         ( 0xFF )
110
#define usbBUS_POWERED                                          ( 0x80 )
111
#define usbHID_REPORT_DESCRIPTOR                        ( 0x22 )
112
#define AT91C_UDP_TRANSCEIVER_ENABLE                    ( *( ( unsigned long * ) 0xfffb0074 ) )
113
 
114
/* Index to the various string. */
115
#define usbLANGUAGE_STRING                                      ( 0 )
116
#define usbMANUFACTURER_STRING                          ( 1 )
117
#define usbPRODUCT_STRING                                       ( 2 )
118
#define usbCONFIGURATION_STRING                         ( 3 )
119
#define usbINTERFACE_STRING                                     ( 4 )
120
 
121
/* Data indexes for reading the request from the xISRStatus.ucFifoData[]
122
into xUSB_REQUEST.  The data order is designed for speed - so looks a
123
little odd. */
124
#define usbREQUEST_TYPE_INDEX                           ( 7 )
125
#define usbREQUEST_INDEX                                        ( 6 )
126
#define usbVALUE_HIGH_BYTE                                      ( 4 )
127
#define usbVALUE_LOW_BYTE                                       ( 5 )
128
#define usbINDEX_HIGH_BYTE                                      ( 2 )
129
#define usbINDEX_LOW_BYTE                                       ( 3 )
130
#define usbLENGTH_HIGH_BYTE                                     ( 0 )
131
#define usbLENGTH_LOW_BYTE                                      ( 1 )
132
 
133
/* Misc application definitions. */
134
#define usbINTERRUPT_PRIORITY                           ( 3 )
135
#define usbFIFO_LENGTH                                          ( ( unsigned long ) 8 )
136
#define usbXUP                                                          ( 1 )
137
#define usbXDOWN                                                        ( 2 )
138
#define usbYUP                                                          ( 3 )
139
#define usbYDOWN                                                        ( 4 )
140
#define usbMAX_COORD                                            ( 120 )
141
#define usbMAX_TX_MESSAGE_SIZE                          ( 128 )
142
#define usbSHORTEST_DELAY                                       ( ( portTickType ) 1 )
143
#define usbINIT_DELAY                                           ( ( portTickType ) 1000 / portTICK_RATE_MS )
144
#define usbSHORT_DELAY                                          ( ( portTickType ) 50 / portTICK_RATE_MS )
145
#define usbEND_POINT_RESET_MASK                         ( ( unsigned long ) 0x0f )
146
#define usbDATA_INC                                                     ( ( char ) 5 )
147
#define usbEXPECTED_NUMBER_OF_BYTES                     ( ( unsigned long ) 8 )
148
 
149
/* Control request types. */
150
#define usbSTANDARD_DEVICE_REQUEST                      ( 0 )
151
#define usbSTANDARD_INTERFACE_REQUEST           ( 1 )
152
#define usbSTANDARD_END_POINT_REQUEST           ( 2 )
153
#define usbCLASS_INTERFACE_REQUEST                      ( 5 )
154
 
155
/* Structure used to hold the received requests. */
156
typedef struct
157
{
158
        unsigned char ucReqType;
159
        unsigned char ucRequest;
160
        unsigned short usValue;
161
        unsigned short usIndex;
162
        unsigned short usLength;
163
} xUSB_REQUEST;
164
 
165
typedef enum
166
{
167
        eNOTHING,
168
        eJUST_RESET,
169
        eJUST_GOT_CONFIG,
170
        eJUST_GOT_ADDRESS,
171
        eSENDING_EVEN_DESCRIPTOR,
172
        eREADY_TO_SEND
173
} eDRIVER_STATE;
174
 
175
/* Structure used to control the data being sent to the host. */
176
typedef struct
177
{
178
        unsigned char ucTxBuffer[ usbMAX_TX_MESSAGE_SIZE ];
179
        unsigned long ulNextCharIndex;
180
        unsigned long ulTotalDataLength;
181
} xTX_MESSAGE;
182
 
183
/*-----------------------------------------------------------*/
184
 
185
/*
186
 * The USB interrupt service routine.  This takes a snapshot of the USB
187
 * device at the time of the interrupt, clears the interrupts, and posts
188
 * the data to the USB processing task.  This is implemented in USB_ISR.c.
189
 */
190
extern void vUSB_ISR_Wrapper( void );
191
 
192
/*
193
 * Called after the bus reset interrupt - this function readies all the
194
 * end points for communication.
195
 */
196
static void prvResetEndPoints( void );
197
 
198
/*
199
 * Setup the USB hardware, install the interrupt service routine and
200
 * initialise all the state variables.
201
 */
202
static void vInitUSBInterface( void );
203
 
204
/*
205
 * Decode and act upon an interrupt generated by the control end point.
206
 */
207
static void prvProcessEndPoint0Interrupt( xISRStatus *pxMessage );
208
 
209
/*
210
 * For simplicity requests are separated into device, interface, class
211
 * interface and end point requests.
212
 *
213
 * Decode and handle standard device requests originating on the control
214
 * end point.
215
 */
216
static void prvHandleStandardDeviceRequest( xUSB_REQUEST *pxRequest );
217
 
218
/*
219
 * For simplicity requests are separated into device, interface, class
220
 * interface and end point requests.
221
 *
222
 * Decode and handle standard interface requests originating on the control
223
 * end point.
224
 */
225
static void prvHandleStandardInterfaceRequest( xUSB_REQUEST *pxRequest );
226
 
227
/*
228
 * For simplicity requests are separated into device, interface, class
229
 * interface and end point requests.
230
 *
231
 * Decode and handle standard end point requests originating on the control
232
 * end point.
233
 */
234
static void prvHandleStandardEndPointRequest( xUSB_REQUEST *pxRequest );
235
 
236
/*
237
 * For simplicity requests are separated into device, interface, class
238
 * interface and end point requests.
239
 *
240
 * Decode and handle the class interface requests.
241
 */
242
static void prvHandleClassInterfaceRequest( xUSB_REQUEST *pxRequest );
243
 
244
/*
245
 * Setup the Tx buffer to send data in response to a control request.
246
 *
247
 * The data to be transmitted is buffered, the state variables are updated,
248
 * then prvSendNextSegment() is called to start the transmission off.  Once
249
 * the first segment has been sent the remaining segments are transmitted
250
 * in response to TXCOMP interrupts until the entire buffer has been
251
 * sent.
252
 */
253
static void prvSendControlData( unsigned char *pucData, unsigned short usRequestedLength, unsigned long ulLengthLeftToSend, long lSendingDescriptor );
254
 
255
/*
256
 * Examine the Tx buffer to see if there is any more data to be transmitted.
257
 *
258
 * If there is data to be transmitted then send the next segment.  A segment
259
 * can have a maximum of 8 bytes (this is defined as the maximum for the end
260
 * point by the descriptor).  The final segment may be less than 8 bytes if
261
 * the total data length was not an exact multiple of 8.
262
 */
263
static void prvSendNextSegment( void );
264
 
265
/*
266
 * A stall condition is forced each time the host makes a request that is not
267
 * supported by this minimal implementation.
268
 *
269
 * A stall is forced by setting the appropriate bit in the end points control
270
 * and status register.
271
 */
272
static void prvSendStall( void );
273
 
274
/*
275
 * A NULL (or zero length packet) is transmitted in acknowledge the reception
276
 * of certain events from the host.
277
 */
278
static void prvUSBTransmitNull( void );
279
 
280
/*
281
 * When the host requests a descriptor this function is called to determine
282
 * which descriptor is being requested and start its transmission.
283
 */
284
static void prvGetStandardInterfaceDescriptor( xUSB_REQUEST *pxRequest );
285
 
286
/*
287
 * Transmit movement and clicks on the EK joystick as mouse inputs.
288
 */
289
static void prvTransmitSampleValues( void );
290
 
291
/*
292
 * The created task to handle the USB demo functionality.
293
 */
294
static void vUSBDemoTask( void *pvParameters );
295
 
296
/*
297
 * Simple algorithm to ramp up the mouse cursor speed to make it easier to
298
 * use.
299
 */
300
static void prvControlCursorSpeed( signed char *cVal, unsigned long ulInput, unsigned long ulSwitch1, unsigned long ulSwitch2 );
301
/*-----------------------------------------------------------*/
302
 
303
/*
304
        - DESCRIPTOR DEFINITIONS -
305
*/
306
 
307
/* String descriptors used during the enumeration process.
308
These take the form:
309
 
310
{
311
        Length of descriptor,
312
        Descriptor type,
313
        Data
314
}
315
*/
316
const char pxLanguageStringDescriptor[] =
317
{
318
        4,
319
        usbDESCRIPTOR_TYPE_STRING,
320
        0x09, 0x04
321
};
322
 
323
const char pxManufacturerStringDescriptor[] =
324
{
325
        18,
326
        usbDESCRIPTOR_TYPE_STRING,
327
 
328
        'F', 0x00,
329
        'r', 0x00,
330
        'e', 0x00,
331
        'e', 0x00,
332
        'R', 0x00,
333
        'T', 0x00,
334
        'O', 0x00,
335
        'S', 0x00
336
};
337
 
338
const char pxProductStringDescriptor[] =
339
{
340
        38,
341
        usbDESCRIPTOR_TYPE_STRING,
342
 
343
        'F', 0x00,
344
        'r', 0x00,
345
        'e', 0x00,
346
        'e', 0x00,
347
        'R', 0x00,
348
        'T', 0x00,
349
        'O', 0x00,
350
        'S', 0x00,
351
        '.', 0x00,
352
        'o', 0x00,
353
        'r', 0x00,
354
        'g', 0x00,
355
        ' ', 0x00,
356
        'M', 0x00,
357
        'o', 0x00,
358
        'u', 0x00,
359
        's', 0x00,
360
        'e', 0x00
361
};
362
 
363
const char pxConfigurationStringDescriptor[] =
364
{
365
        38,
366
        usbDESCRIPTOR_TYPE_STRING,
367
 
368
        'C', 0x00,
369
        'o', 0x00,
370
        'n', 0x00,
371
        'f', 0x00,
372
        'i', 0x00,
373
        'g', 0x00,
374
        'u', 0x00,
375
        'r', 0x00,
376
        'a', 0x00,
377
        't', 0x00,
378
        'i', 0x00,
379
        'o', 0x00,
380
        'n', 0x00,
381
        ' ', 0x00,
382
        'N', 0x00,
383
        'a', 0x00,
384
        'm', 0x00,
385
        'e', 0x00
386
};
387
 
388
const char pxInterfaceStringDescriptor[] =
389
{
390
        30,
391
        usbDESCRIPTOR_TYPE_STRING,
392
 
393
        'I', 0x00,
394
        'n', 0x00,
395
        't', 0x00,
396
        'e', 0x00,
397
        'r', 0x00,
398
        'f', 0x00,
399
        'a', 0x00,
400
        'c', 0x00,
401
        'e', 0x00,
402
        ' ', 0x00,
403
        'N', 0x00,
404
        'a', 0x00,
405
        'm', 0x00,
406
        'e', 0x00
407
};
408
 
409
/* Enumeration descriptors. */
410
const char pxReportDescriptor[] =
411
{
412
        0x05, 0x01,                                             /* USAGE_PAGE (Generic Desktop)                 */
413
        0x09, 0x02,                                             /* USAGE (Mouse)                                                */
414
        0xa1, 0x01,                                             /* COLLECTION (Application)                             */
415
        0x09, 0x01,                                             /*   USAGE (Pointer)                                    */
416
        0xa1, 0x00,                                             /*   COLLECTION (Physical)                              */
417
        0x95, 0x03,                                             /*     REPORT_COUNT (3)                                 */
418
        0x75, 0x01,                                             /*     REPORT_SIZE (1)                                  */
419
        0x05, 0x09,                                             /*     USAGE_PAGE (Button)                              */
420
        0x19, 0x01,                                             /*     USAGE_MINIMUM (Button 1)                 */
421
        0x29, 0x03,                                             /*     USAGE_MAXIMUM (Button 3)                 */
422
        0x15, 0x00,                                             /*     LOGICAL_MINIMUM (0)                              */
423
        0x25, 0x01,                                             /*     LOGICAL_MAXIMUM (1)                              */
424
        0x81, 0x02,                                             /*     INPUT (Data,Var,Abs)                             */
425
        0x95, 0x01,                                             /*     REPORT_COUNT (1)                                 */
426
        0x75, 0x05,                                             /*     REPORT_SIZE (5)                                  */
427
        0x81, 0x01,                                             /*     INPUT (Cnst,Ary,Abs)                             */
428
        0x75, 0x08,                                             /*     REPORT_SIZE (8)                                  */
429
        0x95, 0x02,                                             /*     REPORT_COUNT (2)                                 */
430
        0x05, 0x01,                                             /*     USAGE_PAGE (Generic Desktop)             */
431
        0x09, 0x30,                                             /*     USAGE (X)                                                */
432
        0x09, 0x31,                                             /*     USAGE (Y)                                                */
433
        0x15, 0x81,                                             /*     LOGICAL_MINIMUM (-127)                   */
434
        0x25, 0x7f,                                             /*     LOGICAL_MAXIMUM (127)                    */
435
        0x81, 0x06,                                             /*     INPUT (Data,Var,Rel)                             */
436
        0xc0,                                                   /*   END_COLLECTION                                             */
437
        0xc0                                                    /* END_COLLECTION                                               */
438
};
439
 
440
 
441
 
442
const char pxDeviceDescriptor[] =
443
{
444
        /* Device descriptor */
445
        0x12,                                                           /* bLength                              */
446
        0x01,                                                           /* bDescriptorType              */
447
        0x10, 0x01,                                                     /* bcdUSBL                              */
448
        usbDEVICE_CLASS_VENDOR_SPECIFIC,        /* bDeviceClass:                */
449
        0x00,                                                           /* bDeviceSubclass:             */
450
        0x00,                                                           /* bDeviceProtocol:             */
451
        0x08,                                                           /* bMaxPacketSize0              */
452
        0xFF, 0xFF,                                                     /* idVendorL                    */
453
        0x02, 0x00,                                                     /* idProductL                   */
454
        0x00, 0x01,                                                     /* bcdDeviceL                   */
455
        usbMANUFACTURER_STRING,                         /* iManufacturer                */
456
        usbPRODUCT_STRING,                                      /* iProduct                             */
457
        0x00,                                                           /* SerialNumber                 */
458
        0x01                                                            /* bNumConfigs                  */
459
};
460
 
461
 
462
const char pxConfigDescriptor[] = {
463
        /* Configuration 1 descriptor */
464
        0x09,                   /* CbLength                                                                     */
465
        0x02,                   /* CbDescriptorType                                                     */
466
        0x22, 0x00,             /* CwTotalLength 2 EP + Control                         */
467
        0x01,                   /* CbNumInterfaces                                                      */
468
        0x01,                   /* CbConfigurationValue                                         */
469
        usbCONFIGURATION_STRING,/* CiConfiguration                                      */
470
        usbBUS_POWERED, /* CbmAttributes Bus powered + Remote Wakeup*/
471
        0x32,                   /* CMaxPower: 100mA                                                     */
472
 
473
        /* Mouse Interface Descriptor Requirement */
474
        0x09,                   /* bLength                                                                      */
475
        0x04,                   /* bDescriptorType                                                      */
476
        0x00,                   /* bInterfaceNumber                                                     */
477
        0x00,                   /* bAlternateSetting                                            */
478
        0x01,                   /* bNumEndpoints                                                        */
479
        0x03,                   /* bInterfaceClass: HID code                            */
480
        0x01,                   /* bInterfaceSubclass boot                                      */
481
        0x02,                   /* bInterfaceProtocol mouse boot                        */
482
        usbINTERFACE_STRING,/* iInterface                                                       */
483
 
484
        /* HID Descriptor */
485
        0x09,                   /* bLength                                                                      */
486
        0x21,                   /* bDescriptor type: HID Descriptor Type        */
487
        0x00, 0x01,             /* bcdHID                                                                       */
488
        0x00,                   /* bCountryCode                                                         */
489
        0x01,                   /* bNumDescriptors                                                      */
490
        usbHID_REPORT_DESCRIPTOR,         /* bDescriptorType                    */
491
        sizeof( pxReportDescriptor ), 0x00, /* wItemLength                      */
492
 
493
        /* Endpoint 1 descriptor */
494
        0x07,                   /* bLength                                                                      */
495
        0x05,                   /* bDescriptorType                                                      */
496
        0x81,                   /* bEndpointAddress, Endpoint 01 - IN           */
497
        0x03,                   /* bmAttributes      INT                                        */
498
        0x08, 0x00,             /* wMaxPacketSize: 8?                                           */
499
        0x0A                    /* bInterval                                                            */
500
};
501
 
502
/*-----------------------------------------------------------*/
503
 
504
/* File scope state variables. */
505
static unsigned char ucUSBConfig = ( unsigned char ) 0;
506
static unsigned long ulReceivedAddress = ( unsigned long ) 0;
507
static eDRIVER_STATE eDriverState = eNOTHING;
508
 
509
/* Structure used to control the characters being sent to the host. */
510
static xTX_MESSAGE pxCharsForTx;
511
 
512
/* Queue used to pass messages between the ISR and the task. */
513
xQueueHandle xUSBInterruptQueue;
514
 
515
/*-----------------------------------------------------------*/
516
 
517
void vStartUSBTask( unsigned portBASE_TYPE uxPriority )
518
{
519
        /* Create the queue used to communicate between the USB ISR and task. */
520
        xUSBInterruptQueue = xQueueCreate( usbQUEUE_LENGTH + 1, sizeof( xISRStatus * ) );
521
 
522
        /* Create the task itself. */
523
        xTaskCreate( vUSBDemoTask, "USB", configMINIMAL_STACK_SIZE, NULL, uxPriority, NULL );
524
}
525
/*-----------------------------------------------------------*/
526
 
527
static void vUSBDemoTask( void *pvParameters )
528
{
529
xISRStatus *pxMessage;
530
 
531
        /* The parameters are not used in this task. */
532
        ( void ) pvParameters;
533
 
534
    /* Init USB device */
535
    portENTER_CRITICAL();
536
            vInitUSBInterface();
537
    portEXIT_CRITICAL();
538
 
539
        /* Process interrupts as they arrive.   The ISR takes a snapshot of the
540
        interrupt status then posts the information on this queue for processing
541
        at the task level.  This simple demo implementation only processes
542
        a few interrupt sources. */
543
        for( ;; )
544
        {
545
                if( xQueueReceive( xUSBInterruptQueue, &pxMessage, usbSHORT_DELAY ) )
546
                {
547
                        if( pxMessage->ulISR & AT91C_UDP_EPINT0 )
548
                        {
549
                                /* Process end point 0 interrupt. */
550
                                prvProcessEndPoint0Interrupt( pxMessage );
551
                        }
552
 
553
                        if( pxMessage->ulISR & AT91C_UDP_ENDBUSRES )
554
                        {
555
                                /* Process an end of bus reset interrupt. */
556
                                prvResetEndPoints();
557
                        }
558
                }
559
                else
560
                {
561
                        /* The ISR did not post any data for us to process on the queue, so
562
                        just generate and send some sample data. */
563
                        if( eDriverState == eREADY_TO_SEND )
564
                        {
565
                                prvTransmitSampleValues();
566
                        }
567
                }
568
        }
569
}
570
/*-----------------------------------------------------------*/
571
 
572
static void prvControlCursorSpeed( signed char *cVal, unsigned long ulInput, unsigned long ulSwitch1, unsigned long ulSwitch2 )
573
{
574
const char cSpeed = 20;
575
 
576
        if( !( ulInput & ulSwitch1 ) )
577
        {
578
                /* We are going in the decreasing y direction. */
579
                if( *cVal > 0 )
580
                {
581
                        /* We have changed direction since last time so start from
582
 
583
                        *cVal = 0;
584
                }
585
 
586
                if( *cVal > -cSpeed )
587
                {
588
                        /* Ramp y down to the max speed. */
589
                        (*cVal)--;
590
                }
591
        }
592
        else if( !( ulInput & ulSwitch2 ) )
593
        {
594
                /* We are going in the increasing y direction. */
595
                if( *cVal < 0 )
596
                {
597
                        /* We have changed direction since last time, so start from
598
 
599
                        *cVal = 0;
600
                }
601
 
602
                if( *cVal < cSpeed )
603
                {
604
                        /* Ramp y up to the max speed again. */
605
                        (*cVal)++;
606
                }
607
        }
608
        else
609
        {
610
                *cVal = 0;
611
        }
612
}
613
/*-----------------------------------------------------------*/
614
 
615
static void prvTransmitSampleValues( void )
616
{
617
/* Variables to hold dummy x, y and z joystick axis data. */
618
static signed char x = 0, y = 0, z = 0;
619
unsigned long ulStatus;
620
 
621
        ulStatus =      AT91C_BASE_PIOA->PIO_PDSR;
622
 
623
        prvControlCursorSpeed( &y, ulStatus, ( unsigned long ) usbSW1, ( unsigned long ) usbSW2 );
624
        prvControlCursorSpeed( &x, ulStatus, ( unsigned long ) usbSW3, ( unsigned long ) usbSW4 );
625
 
626
        /* Just make the z axis go up and down. */
627
        z = ( ( ulStatus & usbSW_CLICK ) == 0 );
628
 
629
        /* Can we place data in the fifo? */
630
        if( !( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] & AT91C_UDP_TXPKTRDY ) )
631
        {
632
                /* Write our sample data to the fifo. */
633
                AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_1 ] = z;
634
                AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_1 ] = x;
635
                AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_1 ] = y;
636
 
637
                /* Send the data. */
638
                portENTER_CRITICAL();
639
                {
640
                        ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];
641
                        usbCSR_SET_BIT( &ulStatus, ( AT91C_UDP_TXPKTRDY ) );
642
                        AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulStatus;
643
                }
644
                portEXIT_CRITICAL();
645
        }
646
}
647
/*-----------------------------------------------------------*/
648
 
649
static void prvUSBTransmitNull( void )
650
{
651
unsigned long ulStatus;
652
 
653
        /* Wait until the FIFO is free - even though we are not going to use it.
654
        THERE IS NO TIMEOUT HERE! */
655
        while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_TXPKTRDY )
656
        {
657
                vTaskDelay( usbSHORTEST_DELAY );
658
        }
659
 
660
        portENTER_CRITICAL();
661
        {
662
                /* Set the length of data to send to equal the index of the next byte
663
                to send.  This will prevent the ACK to this NULL packet causing any
664
                further data transmissions. */
665
                pxCharsForTx.ulTotalDataLength = pxCharsForTx.ulNextCharIndex;
666
 
667
                /* Set the TXPKTRDY bit to cause a transmission with no data. */
668
                ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
669
                usbCSR_SET_BIT( &ulStatus, ( AT91C_UDP_TXPKTRDY ) );
670
                AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
671
        }
672
        portEXIT_CRITICAL();
673
}
674
/*-----------------------------------------------------------*/
675
 
676
static void prvSendStall( void )
677
{
678
unsigned long ulStatus;
679
 
680
        portENTER_CRITICAL();
681
        {
682
                /* Force a stall by simply setting the FORCESTALL bit in the CSR. */
683
                ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
684
                usbCSR_SET_BIT( &ulStatus, AT91C_UDP_FORCESTALL );
685
                AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
686
        }
687
        portEXIT_CRITICAL();
688
}
689
/*-----------------------------------------------------------*/
690
 
691
static void prvResetEndPoints( void )
692
{
693
unsigned long ulTemp;
694
 
695
        eDriverState = eJUST_RESET;
696
 
697
        /* Reset all the end points. */
698
        AT91C_BASE_UDP->UDP_RSTEP  = usbEND_POINT_RESET_MASK;
699
        AT91C_BASE_UDP->UDP_RSTEP  = ( unsigned long ) 0x00;
700
 
701
        /* Enable data to be sent and received. */
702
        AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
703
 
704
        /* Repair the configuration end point. */
705
        portENTER_CRITICAL();
706
        {
707
                ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
708
                usbCSR_SET_BIT( &ulTemp, ( ( unsigned long ) ( AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL ) ) );
709
                AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulTemp;
710
                AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT0;
711
        }
712
        portEXIT_CRITICAL();
713
}
714
/*-----------------------------------------------------------*/
715
 
716
static void prvProcessEndPoint0Interrupt( xISRStatus *pxMessage )
717
{
718
        if( pxMessage->ulCSR0 & AT91C_UDP_RX_DATA_BK0 )
719
        {
720
                /* We only expect to receive zero length data here as ACK's.
721
                Set the data pointer to the end of the current Tx packet to
722
                ensure we don't send out any more data. */
723
                pxCharsForTx.ulNextCharIndex = pxCharsForTx.ulTotalDataLength;
724
        }
725
 
726
        if( pxMessage->ulCSR0 & AT91C_UDP_TXCOMP )
727
        {
728
                /* We received a TX complete interrupt.  What we do depends on
729
                what we sent to get this interrupt. */
730
 
731
                if( eDriverState == eJUST_GOT_CONFIG )
732
                {
733
                        /* We sent an acknowledgement of a SET_CONFIG request.  We
734
                        are now at the end of the enumeration. */
735
                        AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_CONFG;
736
 
737
                        /* Read the end point for data transfer. */
738
                        portENTER_CRITICAL();
739
                        {
740
                                unsigned long ulTemp;
741
 
742
                                ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];
743
                                usbCSR_SET_BIT( &ulTemp, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN );
744
                                AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulTemp;
745
                                AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT1;
746
                        }
747
                        portEXIT_CRITICAL();
748
 
749
                        eDriverState = eREADY_TO_SEND;
750
                }
751
                else if( eDriverState == eJUST_GOT_ADDRESS )
752
                {
753
                        /* We sent an acknowledgement of a SET_ADDRESS request.  Move
754
                        to the addressed state. */
755
                        if( ulReceivedAddress != ( unsigned long ) 0 )
756
                        {
757
                                AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
758
                        }
759
                        else
760
                        {
761
                                AT91C_BASE_UDP->UDP_GLBSTATE = 0;
762
                        }
763
 
764
                        AT91C_BASE_UDP->UDP_FADDR = ( AT91C_UDP_FEN | ulReceivedAddress );
765
                        eDriverState = eNOTHING;
766
                }
767
                else
768
                {
769
                        /* The TXCOMP was not for any special type of transmission.  See
770
                        if there is any more data to send. */
771
                        prvSendNextSegment();
772
                }
773
        }
774
 
775
        if( pxMessage->ulCSR0 & AT91C_UDP_RXSETUP )
776
        {
777
                xUSB_REQUEST xRequest;
778
                unsigned char ucRequest;
779
                unsigned long ulRxBytes;
780
 
781
                /* A data packet is available. */
782
                ulRxBytes = pxMessage->ulCSR0 >> 16;
783
                ulRxBytes &= usbRX_COUNT_MASK;
784
 
785
                if( ulRxBytes >= usbEXPECTED_NUMBER_OF_BYTES )
786
                {
787
                        /* Create an xUSB_REQUEST variable from the raw bytes array. */
788
 
789
                        xRequest.ucReqType = pxMessage->ucFifoData[ usbREQUEST_TYPE_INDEX ];
790
                        xRequest.ucRequest = pxMessage->ucFifoData[ usbREQUEST_INDEX ];
791
 
792
                        /* NOT PORTABLE CODE! */
793
                        xRequest.usValue = pxMessage->ucFifoData[ usbVALUE_HIGH_BYTE ];
794
                        xRequest.usValue <<= 8;
795
                        xRequest.usValue |= pxMessage->ucFifoData[ usbVALUE_LOW_BYTE ];
796
 
797
                        xRequest.usIndex = pxMessage->ucFifoData[ usbINDEX_HIGH_BYTE ];
798
                        xRequest.usIndex <<= 8;
799
                        xRequest.usIndex |= pxMessage->ucFifoData[ usbINDEX_LOW_BYTE ];
800
 
801
                        xRequest.usLength = pxMessage->ucFifoData[ usbLENGTH_HIGH_BYTE ];
802
                        xRequest.usLength <<= 8;
803
                        xRequest.usLength |= pxMessage->ucFifoData[ usbLENGTH_LOW_BYTE ];
804
 
805
                        /* Manipulate the ucRequestType and the ucRequest parameters to
806
                        generate a zero based request selection.  This is just done to
807
                        break up the requests into subsections for clarity.  The
808
                        alternative would be to have more huge switch statement that would
809
                        be difficult to optimise. */
810
                        ucRequest = ( ( xRequest.ucReqType & 0x60 ) >> 3 );
811
                        ucRequest |= ( xRequest.ucReqType & 0x03 );
812
 
813
                        switch( ucRequest )
814
                        {
815
                                case usbSTANDARD_DEVICE_REQUEST:
816
                                                        /* Standard Device request */
817
                                                        prvHandleStandardDeviceRequest( &xRequest );
818
                                                        break;
819
 
820
                                case usbSTANDARD_INTERFACE_REQUEST:
821
                                                        /* Standard Interface request */
822
                                                        prvHandleStandardInterfaceRequest( &xRequest );
823
                                                        break;
824
 
825
                                case usbSTANDARD_END_POINT_REQUEST:
826
                                                        /* Standard Endpoint request */
827
                                                        prvHandleStandardEndPointRequest( &xRequest );
828
                                                        break;
829
 
830
                                case usbCLASS_INTERFACE_REQUEST:
831
                                                        /* Class Interface request */
832
                                                        prvHandleClassInterfaceRequest( &xRequest );
833
                                                        break;
834
 
835
                                default:        /* This is not something we want to respond to. */
836
                                                        prvSendStall();
837
                        }
838
                }
839
        }
840
}
841
/*-----------------------------------------------------------*/
842
 
843
static void prvGetStandardDeviceDescriptor( xUSB_REQUEST *pxRequest )
844
{
845
        /* The type is in the high byte.  Return whatever has been requested. */
846
        switch( ( pxRequest->usValue & 0xff00 ) >> 8 )
847
        {
848
            case usbDESCRIPTOR_TYPE_DEVICE:
849
                        prvSendControlData( ( unsigned char * ) &pxDeviceDescriptor, pxRequest->usLength, sizeof( pxDeviceDescriptor ), pdTRUE );
850
                    break;
851
 
852
            case usbDESCRIPTOR_TYPE_CONFIGURATION:
853
                        prvSendControlData( ( unsigned char * ) &( pxConfigDescriptor ), pxRequest->usLength, sizeof( pxConfigDescriptor ), pdTRUE );
854
                    break;
855
 
856
            case usbDESCRIPTOR_TYPE_STRING:
857
 
858
                        /* The index to the string descriptor is the lower byte. */
859
                    switch( pxRequest->usValue & 0xff )
860
                        {
861
                        case usbLANGUAGE_STRING:
862
                                        prvSendControlData( ( unsigned char * ) &pxLanguageStringDescriptor, pxRequest->usLength, sizeof(pxLanguageStringDescriptor), pdTRUE );
863
                                break;
864
 
865
                        case usbMANUFACTURER_STRING:
866
                                        prvSendControlData( ( unsigned char * ) &pxManufacturerStringDescriptor, pxRequest->usLength, sizeof( pxManufacturerStringDescriptor ), pdTRUE );
867
                                break;
868
 
869
                        case usbPRODUCT_STRING:
870
                                        prvSendControlData( ( unsigned char * ) &pxProductStringDescriptor, pxRequest->usLength, sizeof( pxProductStringDescriptor ), pdTRUE );
871
                                break;
872
 
873
                        case usbCONFIGURATION_STRING:
874
                                        prvSendControlData( ( unsigned char * ) &pxConfigurationStringDescriptor, pxRequest->usLength, sizeof( pxConfigurationStringDescriptor ), pdTRUE );
875
                                break;
876
 
877
                        case usbINTERFACE_STRING:
878
                                        prvSendControlData( ( unsigned char * ) &pxInterfaceStringDescriptor, pxRequest->usLength, sizeof( pxInterfaceStringDescriptor ), pdTRUE );
879
                                break;
880
 
881
                        default:
882
                                /* Don't know what this string is. */
883
                                        prvSendStall();
884
                                        break;
885
                        }
886
 
887
                        break;
888
 
889
            default:
890
                        /* We are not responding to anything else. */
891
                        prvSendStall();
892
                    break;
893
        }
894
}
895
/*-----------------------------------------------------------*/
896
 
897
static void prvHandleStandardDeviceRequest( xUSB_REQUEST *pxRequest )
898
{
899
unsigned short usStatus = 0;
900
 
901
        switch( pxRequest->ucRequest )
902
        {
903
            case usbGET_STATUS_REQUEST:
904
                        /* Just send two byte dummy status. */
905
                        prvSendControlData( ( unsigned char * ) &usStatus, sizeof( usStatus ), sizeof( usStatus ), pdFALSE );
906
                    break;
907
 
908
            case usbGET_DESCRIPTOR_REQUEST:
909
                        /* Send device descriptor */
910
                    prvGetStandardDeviceDescriptor( pxRequest );
911
                    break;
912
 
913
            case usbGET_CONFIGURATION_REQUEST:
914
                        /* Send selected device configuration */
915
                        prvSendControlData( ( unsigned char * ) &ucUSBConfig, sizeof( ucUSBConfig ), sizeof( ucUSBConfig ), pdFALSE );
916
                    break;
917
 
918
                case usbSET_FEATURE_REQUEST:
919
                    prvUSBTransmitNull();
920
                    break;
921
 
922
            case usbSET_ADDRESS_REQUEST:
923
 
924
                        /* Acknowledge the SET_ADDRESS, but (according to the manual) we
925
                        cannot actually move to the addressed state until we get a TXCOMP
926
                        interrupt from this NULL packet.  Therefore we just remember the
927
                        address and set our state so we know we have received the address. */
928
                prvUSBTransmitNull();
929
                        eDriverState = eJUST_GOT_ADDRESS;
930
                        ulReceivedAddress = ( unsigned long ) pxRequest->usValue;
931
                    break;
932
 
933
            case usbSET_CONFIGURATION_REQUEST:
934
 
935
                        /* Acknowledge the SET_CONFIGURATION, but (according to the manual)
936
                        we cannot actually move to the configured state until we get a
937
                        TXCOMP interrupt from this NULL packet.  Therefore we just remember the
938
                        config and set our state so we know we have received the go ahead. */
939
                        ucUSBConfig = ( unsigned char ) ( pxRequest->usValue & 0xff );
940
                        eDriverState = eJUST_GOT_CONFIG;
941
                        prvUSBTransmitNull();
942
                    break;
943
 
944
            default:
945
 
946
                    /* We don't answer to anything else. */
947
                        prvSendStall();
948
                    break;
949
        }
950
}
951
/*-----------------------------------------------------------*/
952
 
953
static void prvHandleClassInterfaceRequest( xUSB_REQUEST *pxRequest )
954
{
955
        switch( pxRequest->ucRequest )
956
        {
957
            case usbSET_IDLE_REQUEST:
958
                prvUSBTransmitNull();
959
                        break;
960
 
961
                /* This minimal implementation ignores these. */
962
            case usbGET_REPORT_REQUEST:
963
            case usbGET_IDLE_REQUEST:
964
            case usbGET_PROTOCOL_REQUEST:
965
            case usbSET_REPORT_REQUEST:
966
            case usbSET_PROTOCOL_REQUEST:
967
            default:
968
 
969
                        prvSendStall();
970
                        break;
971
        }
972
}
973
/*-----------------------------------------------------------*/
974
 
975
static void prvGetStandardInterfaceDescriptor( xUSB_REQUEST *pxRequest )
976
{
977
        switch( ( pxRequest->usValue & ( unsigned short ) 0xff00 ) >> 8 )
978
        {
979
            case usbHID_REPORT_DESCRIPTOR:
980
                        prvSendControlData( ( unsigned char * ) pxReportDescriptor, pxRequest->usLength, sizeof( pxReportDescriptor ), pdTRUE );
981
                    break;
982
 
983
            default:
984
 
985
                        /* Don't expect to send any others. */
986
                        prvSendStall();
987
                    break;
988
        }
989
}
990
/*-----------------------------------------------------------*/
991
 
992
static void prvHandleStandardInterfaceRequest( xUSB_REQUEST *pxRequest )
993
{
994
unsigned short usStatus = 0;
995
 
996
        switch( pxRequest->ucRequest )
997
        {
998
            case usbGET_STATUS_REQUEST:
999
                        /* Send dummy 2 bytes. */
1000
                        prvSendControlData( ( unsigned char * ) &usStatus, sizeof( usStatus ), sizeof( usStatus ), pdFALSE );
1001
                        break;
1002
 
1003
            case usbGET_DESCRIPTOR_REQUEST:
1004
                        prvGetStandardInterfaceDescriptor( pxRequest );
1005
                        break;
1006
 
1007
                /* This minimal implementation does not respond to these. */
1008
            case usbGET_INTERFACE_REQUEST:
1009
            case usbSET_FEATURE_REQUEST:
1010
            case usbSET_INTERFACE_REQUEST:
1011
 
1012
            default:
1013
                        prvSendStall();
1014
                        break;
1015
        }
1016
}
1017
/*-----------------------------------------------------------*/
1018
 
1019
static void prvHandleStandardEndPointRequest( xUSB_REQUEST *pxRequest )
1020
{
1021
        switch( pxRequest->ucRequest )
1022
        {
1023
                /* This minimal implementation does not expect to respond to these. */
1024
            case usbGET_STATUS_REQUEST:
1025
            case usbCLEAR_FEATURE_REQUEST:
1026
            case usbSET_FEATURE_REQUEST:
1027
 
1028
            default:
1029
                        prvSendStall();
1030
                        break;
1031
        }
1032
}
1033
/*-----------------------------------------------------------*/
1034
 
1035
static void vInitUSBInterface( void )
1036
{
1037
volatile unsigned long ulTemp;
1038
 
1039
        /* Initialise a few state variables. */
1040
        pxCharsForTx.ulNextCharIndex = ( unsigned long ) 0;
1041
        ucUSBConfig = ( unsigned char ) 0;
1042
        eDriverState = eNOTHING;
1043
 
1044
        /* HARDWARE SETUP */
1045
 
1046
    /* Set the PLL USB Divider */
1047
    AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1;
1048
 
1049
    /* Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock. */
1050
    AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
1051
    AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
1052
 
1053
    /* Setup the PIO for the USB pull up resistor. */
1054
    AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16;
1055
    AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16;
1056
 
1057
 
1058
    /* Start without the pullup - this will get set at the end of this
1059
        function. */
1060
    AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA16;
1061
 
1062
        /* When using the USB debugger the peripheral registers do not always get
1063
        set to the correct default values.  To make sure set the relevant registers
1064
        manually here. */
1065
        AT91C_BASE_UDP->UDP_IDR = ( unsigned long ) 0xffffffff;
1066
        AT91C_BASE_UDP->UDP_ICR = ( unsigned long ) 0xffffffff;
1067
        AT91C_BASE_UDP->UDP_CSR[ 0 ] = ( unsigned long ) 0x00;
1068
        AT91C_BASE_UDP->UDP_CSR[ 1 ] = ( unsigned long ) 0x00;
1069
        AT91C_BASE_UDP->UDP_GLBSTATE = 0;
1070
        AT91C_BASE_UDP->UDP_FADDR = 0;
1071
 
1072
        /* Enable the transceiver. */
1073
        AT91C_UDP_TRANSCEIVER_ENABLE = 0;
1074
 
1075
        /* Enable the USB interrupts - other interrupts get enabled as the
1076
        enumeration process progresses. */
1077
        AT91F_AIC_ConfigureIt( AT91C_ID_UDP, usbINTERRUPT_PRIORITY, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vUSB_ISR_Wrapper );
1078
        AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_UDP;
1079
 
1080
        /* Wait a short while before making our presence known. */
1081
        vTaskDelay( usbINIT_DELAY );
1082
        AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA16;
1083
}
1084
/*-----------------------------------------------------------*/
1085
 
1086
static void prvSendControlData( unsigned char *pucData, unsigned short usRequestedLength, unsigned long ulLengthToSend, long lSendingDescriptor )
1087
{
1088
        if( ( ( unsigned long ) usRequestedLength < ulLengthToSend ) )
1089
        {
1090
                /* Cap the data length to that requested. */
1091
                ulLengthToSend = ( unsigned short ) usRequestedLength;
1092
        }
1093
        else if( ( ulLengthToSend < ( unsigned long ) usRequestedLength ) && lSendingDescriptor )
1094
        {
1095
                /* We are sending a descriptor.  If the descriptor is an exact
1096
                multiple of the FIFO length then it will have to be terminated
1097
                with a NULL packet.  Set the state to indicate this if
1098
                necessary. */
1099
                if( ( ulLengthToSend % usbFIFO_LENGTH ) == 0 )
1100
                {
1101
                        eDriverState = eSENDING_EVEN_DESCRIPTOR;
1102
                }
1103
        }
1104
 
1105
        /* Here we assume that the previous message has been sent.  THERE IS NO
1106
        BUFFER OVERFLOW PROTECTION HERE.
1107
 
1108
        Copy the data to send into the buffer as we cannot send it all at once
1109
        (if it is greater than 8 bytes in length). */
1110
        memcpy( pxCharsForTx.ucTxBuffer, pucData, ulLengthToSend );
1111
 
1112
        /* Reinitialise the buffer index so we start sending from the start of
1113
        the data. */
1114
        pxCharsForTx.ulTotalDataLength = ulLengthToSend;
1115
        pxCharsForTx.ulNextCharIndex = ( unsigned long ) 0;
1116
 
1117
        /* Send the first 8 bytes now.  The rest will get sent in response to
1118
        TXCOMP interrupts. */
1119
        prvSendNextSegment();
1120
}
1121
/*-----------------------------------------------------------*/
1122
 
1123
static void prvSendNextSegment( void )
1124
{
1125
volatile unsigned long ulNextLength, ulStatus, ulLengthLeftToSend;
1126
 
1127
        /* Is there any data to send? */
1128
        if( pxCharsForTx.ulTotalDataLength > pxCharsForTx.ulNextCharIndex )
1129
        {
1130
                ulLengthLeftToSend = pxCharsForTx.ulTotalDataLength - pxCharsForTx.ulNextCharIndex;
1131
 
1132
                /* We can only send 8 bytes to the fifo at a time. */
1133
                if( ulLengthLeftToSend > usbFIFO_LENGTH )
1134
                {
1135
                        ulNextLength = usbFIFO_LENGTH;
1136
                }
1137
                else
1138
                {
1139
                        ulNextLength = ulLengthLeftToSend;
1140
                }
1141
 
1142
                /* Wait until we can place data in the fifo.  THERE IS NO TIMEOUT
1143
                HERE! */
1144
                while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_TXPKTRDY )
1145
                {
1146
                        vTaskDelay( usbSHORTEST_DELAY );
1147
                }
1148
 
1149
                /* Write the data to the FIFO. */
1150
                while( ulNextLength > ( unsigned long ) 0 )
1151
                {
1152
                        AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_0 ] = pxCharsForTx.ucTxBuffer[ pxCharsForTx.ulNextCharIndex ];
1153
 
1154
                        ulNextLength--;
1155
                        pxCharsForTx.ulNextCharIndex++;
1156
                }
1157
 
1158
                /* Start the transmission. */
1159
                portENTER_CRITICAL();
1160
                {
1161
                        ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
1162
                        usbCSR_SET_BIT( &ulStatus, ( ( unsigned long ) 0x10 ) );
1163
                        AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
1164
                }
1165
                portEXIT_CRITICAL();
1166
        }
1167
        else
1168
        {
1169
                /* There is no data to send.  If we were sending a descriptor and the
1170
                descriptor was an exact multiple of the max packet size then we need
1171
                to send a null to terminate the transmission. */
1172
                if( eDriverState == eSENDING_EVEN_DESCRIPTOR )
1173
                {
1174
                        prvUSBTransmitNull();
1175
                        eDriverState = eNOTHING;
1176
                }
1177
        }
1178
}
1179
 
1180
 
1181
 

powered by: WebSVN 2.1.0

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