upsd3400_usb_app.c

来自「upsd34xx系列单片机keil环境中的开发例程」· C语言 代码 · 共 1,128 行 · 第 1/3 页

C
1,128
字号
/*------------------------------------------------------------------------------
upsd3400_usb_app.c

Version:
March 22, 2005 - Version 1.0 - Initial Release.

Description:  USB Mass Storage Class application module. 


Copyright (c) 2005 STMicroelectronics Inc.

This example demo code is provided as is and has no warranty,
implied or otherwise.  You are free to use/modify any of the provided
code at your own risk in your applications with the expressed limitation
of liability (see below) so long as your product using the code contains
at least one uPSD product (device).

LIMITATION OF LIABILITY:   NEITHER STMicroelectronics NOR ITS VENDORS OR 
AGENTS SHALL BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
------------------------------------------------------------------------------*/

#pragma NOAREGS

#include "upsd3400.h"
#include "upsd3400_hardware.h"
#include "upsd3400_usb.h"
#include "upsd3400_upsd_usb.h"
#include "upsd3400_usb_app.h"


#define USB_MS_SectorSize 512
#define USB_MS_UnitSize   (USB_MS_SectorSize*9*64)


extern xdata PSD_REGS UPSD_xreg;

data unsigned      char gbCBWCB[16];
data unsigned long  int gdwCBWTag;
data unsigned long  int gdwCBWDataTransferLength;
data unsigned      char gbCBWFlags;
data unsigned      char gbCBWLUN;
data unsigned      char gbCBWCBLength;
data unsigned      char gbCSWStatus;
data unsigned      char gbBulkPipeStage;

static data unsigned int TransferLength;
static data unsigned int PhysicalDataAddr;



extern unsigned char data usbState, ep0state, ep1state;
extern setup_buffer setupPacket;





#define USB_FIFO ((unsigned char volatile xdata *) USB_BASE_ADDR)

#define UMSC_IN_ENDPOINT SELEP1
#define UMSC_OUT_ENDPOINT SELEP3

#define UMSC_MASK_IN_ENDPOINT IN1F
#define UMSC_MASK_OUT_ENDPOINT OUT3F

















void ReturnCSW(void)
/******************************************************************************
  Function   : void ReturnCSW(void)
  Parameters : none
  Description: Handle CSW package.
               Command Status Wrapper (CSW) shall start on a packet boundary
               and shall end as a short packet with exactly 13 (0Dh) bytes
               transferred. Fields appear aligned to byte offsets equal to
               a multiple of their byte size. All CSW transfers shall
               be ordered with the LSB (byte 0) first (little endian).
               Refer to the USB Specification Terms and Abbreviations
               for clarification.
  ******************************************************************************/
 {
  USEL  = INDIR | UMSC_IN_ENDPOINT;          //Select EP1 IN

/*dCSWSignature:
  Signature that helps identify this data packet as a CSW. The signature field
  shall contain the value 53425355h (little endian), indicating CSW. */
  USB_FIFO[ 0] = 0x55;                       // dCSWSignature
  USB_FIFO[ 1] = 0x53;
  USB_FIFO[ 2] = 0x42;
  USB_FIFO[ 3] = 0x53;
/*dCSWTag:
  The device shall set this field to the value received in the dCBWTag
  of the associated CBW.*/
  USB_FIFO[ 4] = *((uchar *)&gdwCBWTag+3);   // dCSWTag, LSB read first
  USB_FIFO[ 5] = *((uchar *)&gdwCBWTag+2);
  USB_FIFO[ 6] = *((uchar *)&gdwCBWTag+1);
  USB_FIFO[ 7] = *((uchar *)&gdwCBWTag+0);
/*dCSWDataResidue:
  For Data-Out the device shall report in the dCSWDataResidue the difference
  between
  the amount of data expected as stated in the dCBWDataTransferLength,
  and the actual amount of data processed by the device.
  For Data-In the device shall report in the dCSWDataResidue the difference
  between the amount of data expected as stated in the dCBWDataTransferLength
  and the actual amount of relevant data sent by the device.
  The dCSWDataResidue shall not exceed the value sent in the dCBWDataTransferLength.
  We return always zero, it is simple.
  */
  USB_FIFO[ 8] = 0x00;                       // dCSWDataResidue
  USB_FIFO[ 9] = 0x00;
  USB_FIFO[10] = 0x00;
  USB_FIFO[11] = 0x00;
/*bCSWStatus:
  bCSWStatus indicates the success or failure of the command.
  The device shall set this byte to zero if the command completed successfully.
  A non-zero value shall indicate a failure during command execution according
  to the following table:
  00h Command Passed ("good status")
  01h Command Failed
  02h Phase Error
  03h and 04h Reserved (Obsolete)
  05h to FFh Reserved
  */
  USB_FIFO[12] = gbCSWStatus;                // bCSWStatus

  USIZE = 0x0D;                              // fire !

  gbBulkPipeStage = BS_CSW_DONE_PHASE;
 }















void SpecificIncrementSectorAddress(void)
/******************************************************************************
 Function   : void SpecificIncrementSectorAddress(void)
 Parameters : none
 Description: Increments PhysicalDataAddr of 512b (1 sector),
              adjust PAGE and TransferLength.
              Used in Read and Write Commands
 ******************************************************************************/
 {
  PhysicalDataAddr   += 64;                  // next sector physical address
  if (PhysicalDataAddr < 0x8000)
   {
    PhysicalDataAddr += 0x8000;        // adjust address to the top half of memory
    UPSD_xreg.PAGE   += 1;                   // adjust PAGE
   }
  TransferLength--;                          // decrement sector counter
 }







void WriteBufferToFlash(void)
/******************************************************************************
 Function   : void WriteBufferToFlash()
 Parameters : (none)
 Description: Receives (writes) sectors
 ******************************************************************************/
 {

  if (TransferLength != 0)
   {
      UIF2 &= ~UMSC_MASK_OUT_ENDPOINT;       // clear INT Flag

#ifdef __RC51__                              //Compiler: Raisonance
      #pragma asm
        ;The following equates are also defined in usb.h
        ; and should be the same in both places.
		;The following EQUates are only needed when using RIDE. 
              USB_BASE_ADDR    EQU 7000H    ;USB FIFO mapped in XDATA space
              INDIR            EQU 0
              SELEP1           EQU 1
              UMSC_IN_ENDPOINT EQU SELEP1
      #pragma endasm
#endif
      #pragma asm
              mov    DPTM,#0
              mov    DPTC,#1
              mov    DPTR,#USB_BASE_ADDR
              mov    DPTC,#0
              mov    DPH,PhysicalDataAddr+0
              mov    DPL,PhysicalDataAddr+1
              mov    DPTC,#64+1
              mov    DPTM,#10
              mov    B,#8
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              djnz   B,$-16
              mov    DPTM,#0
              mov    DPTC,#0
      #pragma endasm

      UCON |= EPFIFO_BSY;                 // release buffer, new OUT data can come

    SpecificIncrementSectorAddress();
   }

  if (TransferLength == 0)
   {
    ReturnCSW();                             // return status
   }
 }







void ReadBufferFromFlash(void)
/******************************************************************************
 Function   : void ReadBufferFromFlash()
 Parameters : (none)
 Description: Reads (sends) sectors to a host
 ******************************************************************************/
 {


  if (TransferLength == 0)
   {
    ReturnCSW();                             // return status
   }
  else
   {


    #pragma asm
              mov    DPTM,#0
              mov    DPTC,#1
              mov    DPH,PhysicalDataAddr+0
              mov    DPL,PhysicalDataAddr+1
              mov    DPTM,#10
              mov    USEL,#INDIR+UMSC_IN_ENDPOINT
              mov    DPTC,#0
              mov    DPTR,#USB_BASE_ADDR
              mov    DPTC,#64+1
              mov    B,#8
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              movx   A,@DPTR
              movx   @DPTR,A
              djnz   B,$-16
              mov    USIZE,#64                                         ; FIRE!
              mov    DPTM,#0
              mov    DPTC,#0
    #pragma endasm

    SpecificIncrementSectorAddress();
/*gbCSWStatus = FAIL;*/
   }
}








void DoReadWrite(void)
/*--------------------------------------------------------------------
  Function   : void DoReadWrite()
  Parameters : none
  Description: Handler for READ and WRITE command
  ---------------------------------------------------------------------*/
 {
  data unsigned long LogicalBlockAddr;

/* Decode the Command Descriptor Block (CDB)
  Byte 0 OPERATION CODE
  Byte 1 Reserved
  Byte 2,3,4,5 (MSB) LOGICAL BLOCK ADDRESS (LSB)
  Byte 6 Reserved
  Byte 7 (MSB)
  Byte 8 TRANSFER LENGTH (LSB)
  Byte 9 CONTROL = 00h
  The LOGICAL BLOCK ADDRESS field specifies the first logical block of the range
  of logical blocks that shall be read.
  The TRANSFER LENGTH field specifies the number of contiguous logical blocks of
  data that shall be transferred. A TRANSFER LENGTH of zero indicates that no logical
  blocks shall be transferred. This condition shall not be considered an error.
  Any other value indicates the number of logical blocks that shall be transferred.
  */
  LogicalBlockAddr  = *(unsigned long int *)&gbCBWCB[2];

  PhysicalDataAddr =  ((unsigned int )(LogicalBlockAddr << 9)) | 0x8000;
  UPSD_xreg.PAGE   =   (unsigned char)(LogicalBlockAddr >> 6);
  TransferLength   =  *(unsigned int *)&gbCBWCB[7];
  TransferLength   = TransferLength*8;

  gbBulkPipeStage  = BS_DATA_PHASE;

  if (gbCBWFlags & 0x80)                     // READ command
   {
    ReadBufferFromFlash();
   }
 }




















⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?