Statistics
| Branch: | Tag: | Revision:

amiro-blt / Target / Source / ARMCM3_STM32 / usb.c @ 9ed9243f

History | View | Annotate | Download (22.852 KB)

1
/************************************************************************************//**
2
* \file         Source\ARMCM3_STM32\usb.c
3
* \brief        Bootloader USB communication interface source file.
4
* \ingroup      Target_ARMCM3_STM32
5
* \internal
6
*----------------------------------------------------------------------------------------
7
*                          C O P Y R I G H T
8
*----------------------------------------------------------------------------------------
9
*   Copyright (c) 2011  by Feaser    http://www.feaser.com    All rights reserved
10
*
11
*----------------------------------------------------------------------------------------
12
*                            L I C E N S E
13
*----------------------------------------------------------------------------------------
14
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
15
* modify it under the terms of the GNU General Public License as published by the Free
16
* Software Foundation, either version 3 of the License, or (at your option) any later
17
* version.
18
*
19
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
20
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
21
* PURPOSE. See the GNU General Public License for more details.
22
*
23
* You should have received a copy of the GNU General Public License along with OpenBLT.
24
* If not, see <http://www.gnu.org/licenses/>.
25
*
26
* A special exception to the GPL is included to allow you to distribute a combined work 
27
* that includes OpenBLT without being obliged to provide the source code for any 
28
* proprietary components. The exception text is included at the bottom of the license
29
* file <license.html>.
30
* 
31
* \endinternal
32
****************************************************************************************/
33

    
34
/****************************************************************************************
35
* Include files
36
****************************************************************************************/
37
#include "boot.h"                                /* bootloader generic header          */
38
#if (BOOT_COM_USB_ENABLE > 0 || BOOT_GATE_USB_ENABLE > 0)
39
#include "usb_lib.h"                             /* USB library driver header          */
40
#include "usb_desc.h"                            /* USB descriptor header              */
41
#include "usb_pwr.h"                             /* USB power management header        */
42
#include "usb_istr.h"                            /* USB interrupt routine header       */
43

    
44

    
45
/****************************************************************************************
46
* Macro definitions
47
****************************************************************************************/
48
/** \brief Total number of fifo buffers. */
49
#define FIFO_MAX_BUFFERS         (2)
50
/** \brief Invalid value for a fifo buffer handle. */
51
#define FIFO_ERR_INVALID_HANDLE  (255)
52
/** \brief Number of bytes that fit in the fifo pipe. */
53
#define FIFO_PIPE_SIZE           (64)
54

    
55

    
56
/****************************************************************************************
57
* Type definitions
58
****************************************************************************************/
59
/** \brief Structure type for fifo control. */
60
typedef struct t_fifo_ctrl
61
{
62
  blt_int8u          *startptr;                    /**< pointer to start of buffer     */
63
  blt_int8u          *endptr;                      /**< pointer to end of buffer       */
64
  blt_int8u          *readptr;                     /**< pointer to next read location  */
65
  blt_int8u          *writeptr;                    /**< pointer to next free location  */
66
  blt_int8u           length;                      /**< number of buffer elements      */
67
  blt_int8u           entries;                     /**< # of full buffer elements      */
68
  blt_int8u           handle;                      /**< handle of the buffer           */ 
69
  struct t_fifo_ctrl *fifoctrlptr;                 /**< pointer to free buffer control */
70
} tFifoCtrl;
71

    
72
/** \brief Structure type for a fifo pipe. */
73
typedef struct
74
{
75
  blt_int8u handle;                                /**< fifo handle                    */
76
  blt_int8u data[FIFO_PIPE_SIZE];                  /**< fifo data buffer               */
77
} tFifoPipe;                                       /**< USB pipe fifo type             */
78

    
79

    
80
/****************************************************************************************
81
* Hook functions
82
****************************************************************************************/
83
extern void UsbEnterLowPowerModeHook(void);
84
extern void UsbLeaveLowPowerModeHook(void);
85
extern void UsbConnectHook(blt_bool connect);
86

    
87

    
88
/****************************************************************************************
89
* Function prototypes
90
****************************************************************************************/
91
static blt_bool  UsbReceiveByte(blt_int8u *data);
92
static blt_bool  UsbTransmitByte(blt_int8u data);
93
static void      UsbFifoMgrInit(void);
94
static blt_int8u UsbFifoMgrCreate(blt_int8u *buffer, blt_int8u length);
95
static blt_bool  UsbFifoMgrWrite(blt_int8u handle, blt_int8u data);
96
static blt_bool  UsbFifoMgrRead(blt_int8u handle, blt_int8u *data);
97
static blt_int8u UsbFifoMgrScan(blt_int8u handle);
98

    
99

    
100
/****************************************************************************************
101
* Local data declarations
102
****************************************************************************************/
103
/** \brief Local variable that holds the fifo control structures. */
104
static tFifoCtrl  fifoCtrl[FIFO_MAX_BUFFERS];
105
/** \brief Local pointer that points to the next free fifo control structure. */
106
static tFifoCtrl *fifoCtrlFree;
107
/** \brief Fifo pipe used for the bulk in endpoint. */
108
static tFifoPipe  fifoPipeBulkIN;
109
/** \brief Fifo pipe used for the bulk out endpoint. */
110
static tFifoPipe  fifoPipeBulkOUT;
111

    
112

    
113
/************************************************************************************//**
114
** \brief     Initializes the USB communication interface.
115
** \return    none.
116
**
117
****************************************************************************************/
118
void UsbInit(void)
119
{
120
  /* initialize the FIFO manager */
121
  UsbFifoMgrInit();
122
  /* place 2 buffers under FIFO management */
123
  fifoPipeBulkIN.handle  = UsbFifoMgrCreate(fifoPipeBulkIN.data,  FIFO_PIPE_SIZE);
124
  fifoPipeBulkOUT.handle = UsbFifoMgrCreate(fifoPipeBulkOUT.data, FIFO_PIPE_SIZE);
125
  /* validate fifo handles */
126
  ASSERT_RT( (fifoPipeBulkIN.handle  != FIFO_ERR_INVALID_HANDLE) && \
127
             (fifoPipeBulkOUT.handle != FIFO_ERR_INVALID_HANDLE) );
128
  /* initialize the low level USB driver */
129
  USB_Init();
130
} /*** end of UsbInit ***/
131

    
132

    
133
/************************************************************************************//**
134
** \brief     Releases the USB communication interface. 
135
** \return    none.
136
**
137
****************************************************************************************/
138
void UsbFree(void)
139
{
140
  /* disconnect the USB device from the USB host */
141
  UsbConnectHook(BLT_FALSE);
142
} /*** end of UsbFree ***/
143

    
144

    
145
/************************************************************************************//**
146
** \brief     Transmits a packet formatted for the communication interface.
147
** \param     data Pointer to byte array with data that it to be transmitted.
148
** \param     len  Number of bytes that are to be transmitted.
149
** \return    none.
150
**
151
****************************************************************************************/
152
void UsbTransmitPacket(blt_int8u *data, blt_int8u len)
153
{
154
  blt_int16u data_index;
155
  blt_bool result;
156

    
157
  /* verify validity of the len-paramenter */
158
  ASSERT_RT(len <= BOOT_COM_USB_TX_MAX_DATA);  
159

    
160
  /* first transmit the length of the packet */  
161
  result = UsbTransmitByte(len);
162
  ASSERT_RT(result == BLT_TRUE);  
163
  
164
  /* transmit all the packet bytes one-by-one */
165
  for (data_index = 0; data_index < len; data_index++)
166
  {
167
    /* keep the watchdog happy */
168
    CopService();
169
    /* write byte */
170
    result = UsbTransmitByte(data[data_index]);
171
    ASSERT_RT(result == BLT_TRUE);  
172
  }
173
} /*** end of UsbTransmitPacket ***/
174

    
175

    
176
/************************************************************************************//**
177
** \brief     Receives a communication interface packet if one is present.
178
** \param     data Pointer to byte array where the data is to be stored.
179
** \return    Length of message (if the message is invalid, the length will be 0).
180
**
181
****************************************************************************************/
182
blt_int8u UsbReceivePacket(blt_int8u *data)
183
{
184
  static blt_int8u xcpCtoReqPacket[BOOT_COM_USB_RX_MAX_DATA+1];  /* one extra for length */
185
  static blt_int8u xcpCtoRxLength;
186
  static blt_int8u xcpUsbDataLength;
187
  static blt_bool  xcpCtoRxInProgress = BLT_FALSE;
188

    
189
  /* poll USB interrupt flags to process USB related events */
190
  USB_Istr();
191

    
192
  /* start of cto packet received? */
193
  if (xcpCtoRxInProgress == BLT_FALSE)
194
  {
195
    /* store the message length when received */
196
    if (UsbReceiveByte(&xcpCtoReqPacket[0]) == BLT_TRUE)
197
    {
198
      /* save message length */
199
      xcpUsbDataLength = xcpCtoReqPacket[0];
200
      if (xcpCtoReqPacket[0] > 0)
201
      {
202
        /* indicate that a cto packet is being received */
203
        xcpCtoRxInProgress = BLT_TRUE;
204
        /* reset packet data count */
205
        xcpCtoRxLength = 0;
206
      }
207
    }
208
  }
209
  else
210
  {
211
    /* store the next packet byte */
212
    if (UsbReceiveByte(&xcpCtoReqPacket[xcpCtoRxLength+1]) == BLT_TRUE)
213
    {
214
      /* increment the packet data count */
215
      xcpCtoRxLength++;
216

    
217
      /* check to see if the entire packet was received */
218
      if (xcpCtoRxLength == xcpCtoReqPacket[0])
219
      {
220
        /* copy the packet data */
221
        CpuMemCopy((blt_int32u)data, (blt_int32u)&xcpCtoReqPacket[1], xcpCtoRxLength);        
222
        /* done with cto packet reception */
223
        xcpCtoRxInProgress = BLT_FALSE;
224

    
225
        /* packet reception complete */
226
//        return BLT_TRUE;
227
        return xcpUsbDataLength;
228
      }
229
    }
230
  }
231
  /* packet reception not yet complete */
232
//  return BLT_FALSE;
233
  return 0;
234
} /*** end of UsbReceivePacket ***/
235

    
236

    
237
/************************************************************************************//**
238
** \brief     Receives a communication interface byte if one is present.
239
** \param     data Pointer to byte where the data is to be stored.
240
** \return    BLT_TRUE if a byte was received, BLT_FALSE otherwise.
241
**
242
****************************************************************************************/
243
static blt_bool UsbReceiveByte(blt_int8u *data)
244
{
245
  blt_bool result;
246
 
247
  /* obtain data from the fifo */
248
  result = UsbFifoMgrRead(fifoPipeBulkOUT.handle, data);
249
  return result;
250
} /*** end of UsbReceiveByte ***/
251

    
252

    
253
/************************************************************************************//**
254
** \brief     Transmits a communication interface byte.
255
** \param     data Value of byte that is to be transmitted.
256
** \return    BLT_TRUE if the byte was transmitted, BLT_FALSE otherwise.
257
**
258
****************************************************************************************/
259
static blt_bool UsbTransmitByte(blt_int8u data)
260
{
261
  blt_bool result;
262
 
263
  /* write data from to fifo */
264
  result = UsbFifoMgrWrite(fifoPipeBulkIN.handle, data);
265
  return result;
266
} /*** end of UsbTransmitByte ***/
267

    
268

    
269
/************************************************************************************//**
270
** \brief     Power-off system clocks and power while entering suspend mode.
271
** \return    none.
272
**
273
****************************************************************************************/
274
void UsbEnterLowPowerMode(void)
275
{
276
  /* Set the device state to suspend */
277
  bDeviceState = SUSPENDED;
278
  /* power-off system clocks and power */
279
  UsbEnterLowPowerModeHook();
280
} /*** end of UsbEnterLowPowerMode ***/
281

    
282

    
283
/************************************************************************************//**
284
** \brief     Restores system clocks and power while exiting suspend mode.
285
** \return    none.
286
**
287
****************************************************************************************/
288
void UsbLeaveLowPowerMode(void)
289
{
290
  DEVICE_INFO *pInfo = &Device_Info;
291

    
292
  /* restore power and system clocks */
293
  UsbLeaveLowPowerModeHook();
294
  /* Set the device state to the correct state */
295
  if (pInfo->Current_Configuration != 0)
296
  {
297
    /* Device configured */
298
    bDeviceState = CONFIGURED;
299
  }
300
  else
301
  {
302
    bDeviceState = ATTACHED;
303
  }
304
} /*** end of UsbLeaveLowPowerMode ***/
305

    
306

    
307
/************************************************************************************//**
308
** \brief     Checks if there is still data left to transmit and if so submits it
309
**            for transmission with the USB endpoint.
310
** \return    none.
311
**
312
****************************************************************************************/
313
void UsbTransmitPipeBulkIN(void)
314
{
315
  /* USB_Tx_Buffer is static for run-time optimalization */
316
  static uint8_t USB_Tx_Buffer[BULK_DATA_SIZE];
317
  blt_int8u nr_of_bytes_for_tx_endpoint;
318
  blt_int8u byte_counter;
319
  blt_int8u byte_value;
320
  blt_bool  result;
321

    
322
  /* read how many bytes should be transmitted */
323
  nr_of_bytes_for_tx_endpoint = UsbFifoMgrScan(fifoPipeBulkIN.handle);
324
  /* only continue if there is actually data left to transmit */
325
  if (nr_of_bytes_for_tx_endpoint == 0)
326
  {
327
    return;
328
  }
329
  /* make sure to not transmit more than the USB endpoint can handle */
330
  if (nr_of_bytes_for_tx_endpoint > BULK_DATA_SIZE)
331
  {
332
    nr_of_bytes_for_tx_endpoint = BULK_DATA_SIZE;
333
  }
334
  /* copy the transmit data to the transmit buffer */
335
  for (byte_counter=0; byte_counter < nr_of_bytes_for_tx_endpoint; byte_counter++)
336
  {
337
    /* obtain data from the fifo */
338
    result = UsbFifoMgrRead(fifoPipeBulkIN.handle, &byte_value);
339
    ASSERT_RT(result == BLT_TRUE);
340
    /* store it in the endpoint's RAM */
341
    USB_Tx_Buffer[byte_counter] = byte_value; 
342
  }
343
  /* store it in the endpoint's RAM */
344
  UserToPMABufferCopy(&USB_Tx_Buffer[0], ENDP1_TXADDR, nr_of_bytes_for_tx_endpoint);
345
  /* set the number of bytes that need to be transmitted from this endpoint */
346
  SetEPTxCount(ENDP1, nr_of_bytes_for_tx_endpoint);
347
  /* inform the endpoint that it can start its transmission because the data is valid */
348
  SetEPTxValid(ENDP1); 
349
} /*** end of UsbTransmitPipeBulkIN ***/
350

    
351

    
352
/************************************************************************************//**
353
** \brief     Stores data that was received on the Bulk OUT pipe in the fifo.
354
** \return    none.
355
**
356
****************************************************************************************/
357
void UsbReceivePipeBulkOUT(void)
358
{
359
  /* USB_Rx_Buffer is static for run-time optimalization */
360
  static uint8_t USB_Rx_Buffer[BULK_DATA_SIZE];
361
  uint16_t USB_Rx_Cnt;
362
  uint16_t byte_counter;
363
  blt_bool result;
364
  
365
  /* Get the received data buffer and update the counter */
366
  USB_Rx_Cnt = USB_SIL_Read(EP1_OUT, USB_Rx_Buffer);
367
  
368
  /* USB data will be immediately processed, this allow next USB traffic being 
369
   * NAKed till the end of the USART Xfer 
370
   */
371
  for (byte_counter=0; byte_counter<USB_Rx_Cnt; byte_counter++)
372
  {
373
    /* add the data to the fifo */
374
    result = UsbFifoMgrWrite(fifoPipeBulkOUT.handle, USB_Rx_Buffer[byte_counter]);
375
    /* verify that the fifo wasn't full */
376
    ASSERT_RT(result == BLT_TRUE);
377
  }
378
  /* Enable the reception of data on EP1 */
379
  SetEPRxValid(ENDP1);
380
} /*** end of UsbReceivePipeBulkOUT ***/
381

    
382

    
383
/************************************************************************************//**
384
** \brief     Converts Hex 32Bits value into char.
385
** \param     value The hexadecimal value to convert.
386
** \param     pbuf  Pointer to where the resulting string should be stored.
387
** \param     len   Number of characters to convert.
388
** \return    none.
389
**
390
****************************************************************************************/
391
static void IntToUnicode (blt_int32u value , blt_int8u *pbuf , blt_int8u len)
392
{
393
  blt_int8u idx = 0;
394
  
395
  for( idx = 0 ; idx < len ; idx ++)
396
  {
397
    if( ((value >> 28)) < 0xA )
398
    {
399
      pbuf[ 2* idx] = (value >> 28) + '0';
400
    }
401
    else
402
    {
403
      pbuf[2* idx] = (value >> 28) + 'A' - 10; 
404
    }
405
    
406
    value = value << 4;
407
    
408
    pbuf[ 2* idx + 1] = 0;
409
  }
410
} /*** end of IntToUnicode ***/
411

    
412

    
413
/************************************************************************************//**
414
** \brief     Creates the serial number string descriptor.
415
** \return    none.
416
**
417
****************************************************************************************/
418
void UsbGetSerialNum(void)
419
{
420
  blt_int32u Device_Serial0, Device_Serial1, Device_Serial2;
421

    
422
  Device_Serial0 = *(volatile blt_int32u*)(0x1FFFF7E8);
423
  Device_Serial1 = *(volatile blt_int32u*)(0x1FFFF7EC);
424
  Device_Serial2 = *(volatile blt_int32u*)(0x1FFFF7F0);
425

    
426
  Device_Serial0 += Device_Serial2;
427

    
428
  if (Device_Serial0 != 0)
429
  {
430
    IntToUnicode(Device_Serial0, &Bulk_StringSerial[2] , 8);
431
    IntToUnicode(Device_Serial1, &Bulk_StringSerial[18], 4);
432
  }
433
} /*** end of UsbGetSerialNum ***/
434

    
435

    
436
/************************************************************************************//**
437
** \brief     Initializes the fifo manager. Each controlled fifo is assigned a
438
**            unique handle, which is the same as its index into fifoCtrl[]. Each
439
**            controlled fifo holds a pointer to the next free fifo control.
440
**            For the last fifo in fifoCtrl[] this one is set to a null-pointer as
441
**            an out of fifo control indicator. Function should be called once
442
**            before any of the other fifo management functions are called.
443
** \return    none.
444
**
445
****************************************************************************************/
446
static void UsbFifoMgrInit(void)
447
{
448
  blt_int8u i;
449
  tFifoCtrl *pbc1, *pbc2;
450

    
451
  pbc1 = &fifoCtrl[0];
452
  pbc2 = &fifoCtrl[1];
453
  /* assign fifo handles and pointer to next free fifo */
454
  for (i = 0; i < (FIFO_MAX_BUFFERS - 1); i++)
455
  {
456
    pbc1->handle = i;
457
    pbc1->fifoctrlptr = pbc2;
458
    pbc1++;
459
    pbc2++;
460
  }
461
  /* initialize handle for the last one and use null-pointer for the next free fifo  */
462
  pbc1->handle = i;
463
  pbc1->fifoctrlptr = (tFifoCtrl *)0;
464
  fifoCtrlFree = &fifoCtrl[0];
465
} /*** end of UsbFifoMgrInit ***/
466

    
467

    
468
/************************************************************************************//**
469
** \brief     Places a data storage array under fifo management control. A handle
470
**            for identifying the fifo in subsequent fifo management function
471
**            calls is returned, if successful.
472
** \param     buffer Pointer to the first element in the data storage fifo.
473
** \param     length Maximum number of data elements that can be stored in the fifo.
474
** \return    Fifo handle if successfull, or FIFO_ERR_INVALID_HANDLE.
475
**
476
****************************************************************************************/
477
static blt_int8u UsbFifoMgrCreate(blt_int8u *buffer, blt_int8u length)
478
{
479
  tFifoCtrl *pbc;
480

    
481
  /* first determine if these is still a free fifo control available */
482
  if (fifoCtrlFree == (tFifoCtrl *)0)
483
  {
484
    return FIFO_ERR_INVALID_HANDLE;
485
  }
486
  /* store pointer to free fifo and update pointer to next free one */
487
  pbc = fifoCtrlFree;
488
  fifoCtrlFree = pbc->fifoctrlptr;
489

    
490
  /* initialize the buffer control */
491
  pbc->length = length;
492
  pbc->readptr = buffer;
493
  pbc->writeptr = buffer;
494
  pbc->entries = 0;
495
  pbc->startptr = buffer;
496
  pbc->endptr = (blt_int8u*)(buffer + length - 1);
497

    
498
  /* return the handle to the successfully created fifo control */
499
  return pbc->handle;
500
} /*** end of UsbFifoMgrCreate ***/
501

    
502

    
503
/************************************************************************************//**
504
** \brief     Stores data in the fifo.
505
** \param     handle Identifies the fifo to write data to.
506
** \param     data   Pointer to the data that is to be written to the fifo.
507
** \return    BLT_TRUE if the data was successfully stored in the fifo, BLT_FALSE
508
**            otherwise.
509
**
510
****************************************************************************************/
511
static blt_bool UsbFifoMgrWrite(blt_int8u handle, blt_int8u data)
512
{
513
  /* check the validity of the handle parameter */
514
  ASSERT_RT(handle < FIFO_MAX_BUFFERS);
515
  /* check if fifo is full */
516
  if (fifoCtrl[handle].entries == fifoCtrl[handle].length)
517
  {
518
    return BLT_FALSE;
519
  }
520
  /* copy data to fifo */
521
  *fifoCtrl[handle].writeptr = data;
522
  /* data written so update number of entries */
523
  fifoCtrl[handle].entries++;
524
  /* update write pointer */
525
  fifoCtrl[handle].writeptr++;
526
  /* check end of fifo */
527
  if (fifoCtrl[handle].writeptr > fifoCtrl[handle].endptr)
528
  {
529
    /* set write pointer to start of the cyclic fifo */
530
    fifoCtrl[handle].writeptr = fifoCtrl[handle].startptr;
531
  }
532
  /* still here so all is okay */        
533
  return BLT_TRUE;
534
} /*** end of UsbFifoMgrWrite ***/
535

    
536

    
537
/************************************************************************************//**
538
** \brief     Retrieves data from the fifo.
539
** \param     handle Identifies the fifo to read data from.
540
** \param     data   Pointer to where the read data is to be stored.
541
** \return    BLT_TRUE if the data was successfully read from the fifo, BLT_FALSE
542
**            otherwise.
543
**
544
****************************************************************************************/
545
static blt_bool UsbFifoMgrRead(blt_int8u handle, blt_int8u *data)
546
{
547
  /* check the validity of the handle parameter */
548
  ASSERT_RT(handle < FIFO_MAX_BUFFERS);
549
  /* check if fifo is empty */
550
  if (fifoCtrl[handle].entries == 0)
551
  {
552
    return BLT_FALSE;
553
  }
554
  /* read the data */
555
  *data = *fifoCtrl[handle].readptr;
556
  /* data read so update number of entries */
557
  fifoCtrl[handle].entries--;
558
  /* update read pointer */
559
  fifoCtrl[handle].readptr++;
560
  /* check end of fifo */
561
  if (fifoCtrl[handle].readptr > fifoCtrl[handle].endptr)
562
  {
563
    /* set read pointer to start of the cyclic fifo */
564
    fifoCtrl[handle].readptr = fifoCtrl[handle].startptr;
565
  }
566
  /* still here so all is good */
567
  return BLT_TRUE;
568
} /*** end of UsbFifoMgrRead ***/
569

    
570

    
571
/************************************************************************************//**
572
** \brief     Returns the number of data entries currently present in the fifo.
573
** \param     handle Identifies the fifo that is to be scanned.
574
** \return    Number of data entries in the fifo if successful, otherwise 0.
575
**
576
****************************************************************************************/
577
static blt_int8u UsbFifoMgrScan(blt_int8u handle)
578
{
579
  /* check the validity of the handle parameter */
580
  ASSERT_RT(handle < FIFO_MAX_BUFFERS);
581
  /* read and return the number of data entries */
582
  return fifoCtrl[handle].entries;
583
} /*** end of UsbFifoMgrScan ***/
584
#endif /* BOOT_COM_USB_ENABLE > 0 || BOOT_GATE_USB_ENABLE > 0 */
585

    
586

    
587
/*********************************** end of usb.c **************************************/