⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 upsd3400_usb_app.c

📁 uPSD34xx Disk driver
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------------
upsd3400_usb_app.c

Version:
September 13, 2005 Ver 1.1 - Updated disclaimer, renamed file.
March 22, 2005 - Version 1.0 - Initial Release.

Description:  USB Mass Storage Class application module. 

Compilers:
Raisonance, Keil

THIS INFORMATION (or THIS SOFTWARE or THIS DOCUMENT) IS FOR GUIDANCE ONLY. ST 
MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS 
SOFTWARE nor for any infringement of patents or other rights of third parties 
which may result from its use. ST MICROELECTRONICS SHALL NOT BE HELD LIABLE FOR 
ANY DIRECT, INDIRECT INCIDENTAL OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY 
CLAIMS ARISING IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, 
OR USE OF THIS SOFTWARE. Specifications mentioned in this publication are 
subject to change without notice. This publication supersedes and replaces all 
information previously supplied. STMicroelectronics products are not authorized 
for use as critical components in life support devices or systems without the 
express written approval of STMicroelectronics.
------------------------------------------------------------------------------*/

#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 SELEP1

#define UMSC_MASK_IN_ENDPOINT IN1F
#define UMSC_MASK_OUT_ENDPOINT OUT1F


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).
   ******************************************************************************/
 {
  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
 }

// Flash parameters
#define NVM_DATA_POLL     0x80              // flash status "data poll" bit at DQ7
#define NVM_DATA_TOGGLE   0x40            // flash status "toggle poll" bit at DQ6
#define NVM_ERROR         0x20               // flash status "error" bit at DQ5


BOOL EraseMainFlashSector(void)
/******************************************************************************
 Function   : BOOL EraseMainFlashSector()
 Parameters : (unsigned int addr,unsigned char wbyte)
 Description: Erases Main Flash Sector
 ******************************************************************************/
 {
  data unsigned char err,error,done;
  data unsigned char poll;

  done = FALSE;
  err = FALSE;

  ((unsigned char volatile xdata *) 0x8000)[0x0555] = 0xAA;
                                 // unlock main flash, write 0xAA to addess 0xX555
  ((unsigned char volatile xdata *) 0x8000)[0x0AAA] = 0x55;
                                 // unlock main flash, write 0x55 to addess 0xXAAA
  ((unsigned char volatile xdata *) 0x8000)[0x0555] = 0x80;
                                             // write 0x80 command to erase sector
  ((unsigned char volatile xdata *) 0x8000)[0x0555] = 0xAA;
                                             // continue unlock sequence
  ((unsigned char volatile xdata *) 0x8000)[0x0AAA] = 0x55;
                                             // continue unlock sequence
  ((unsigned char volatile xdata *) 0x8000)[0x0000] = 0x30;
                                          // write 0x30 to sector address to erase

  do                      // now use dat polling method to verify successful erase
   {
    poll = ((unsigned char volatile xdata *) 0x8000)[0x0000];
                                             // read flash status from any address
                                         // within the defined flash address space
    error = poll & NVM_ERROR;                // save timeout error bit at DQ5
    poll = poll & NVM_DATA_POLL;             // look at D7
    if (poll == NVM_DATA_POLL)               // compare DQ7
     {
      done = TRUE;             // bulk erase OK, indicate successful exit criteria
     }
    else if (error == NVM_ERROR)             // check for timeout error
     {
      err = TRUE;                            // indicate timeout error occurred
     }

   }
  while((done == FALSE) && (err == FALSE));


  if (err == TRUE)                  // make sure timeout error and dat poll didn't
                                             // occur simultaneously
   {
    poll = ((unsigned char volatile xdata *) 0x8000)[0x000];
                                             // Read flash status again
    poll = poll & NVM_DATA_POLL;           // get DQ7 of poll byte read from flash
    if (poll == NVM_DATA_POLL)               // compare DQ7
     {
      done = TRUE;                           // the flash erased OK at the same
                   // time timout error occured, indicate successful exit criteria
      err  = FALSE;
     }
    else
     {
      ((unsigned char volatile xdata *) 0x8000)[0x0555] = 0xF0;
                                // reset the flash array (short reset instruction)
     }
   }

  return err;
 }







BOOL WriteToMainFlash(unsigned int addr,unsigned char wdat)
/******************************************************************************
 Function   : BOOL WriteToMainFlash()
 Parameters : (unsigned int addr,unsigned char wbyte)
 Description: Writes 1 byte to Main Flash
 ******************************************************************************/
 {
  data unsigned char err,error,done;
  data unsigned char poll,dat;

  err = FALSE;

  if ( ((unsigned char volatile xdata *) 0)[addr] != wdat)
   {
    done = FALSE;
    ((unsigned char volatile xdata *) 0)[0x8555] = 0xAA;
                                 // unlock main flash, write 0xAA to addess 0xX555
    ((unsigned char volatile xdata *) 0)[0x8AAA] = 0x55;
                                 // unlock main flash, write 0x55 to addess 0xXAAA
    ((unsigned char volatile xdata *) 0)[0x8555] = 0xA0;
                                             // write 0xA0 command to program
    ((unsigned char volatile xdata *) 0)[addr] = wdat;
                                             // write byte to flash
    dat = wdat & NVM_DATA_POLL;              // get bit DQ7 of the original dat

    do                    // now use dat polling method to verify successful write
     {
      poll = ((unsigned char volatile xdata *) 0)[addr];
                                     // Read the location that was just programmed
      error = poll & NVM_ERROR;              // save timeout error bit at DQ5
      poll = poll & NVM_DATA_POLL;         // get DQ7 of poll byte read from flash

      if (dat == poll)                       // compare DQ7
       {
        done = TRUE;                         // dat byte programmed into flash OK,
                                             // indicate successful exit criteria
       }
      else if (error ==  NVM_ERROR )         // check for timeout error
       {
        err = TRUE;                          // indicate timeout error occurred
       }

     }
    while((done == FALSE) && (err == FALSE));

    if (err == TRUE)                // make sure timeout error and dat poll didn't
                                             // occur simultaneously
     {
      poll = ((unsigned char volatile xdata *) 0)[addr];
                                             // Read location in flash again
      poll = poll & NVM_DATA_POLL;         // get DQ7 of poll byte read from flash
      if (dat == poll)                       // compare DQ7
       {
        done = TRUE;             // data byte programmed into flash OK at the same
                   // time timout error occured, indicate successful exit criteria
        err  = FALSE;
       }
      else
       {
        ((unsigned char volatile xdata *) 0)[0x8555] = 0xF0;
                                // reset the flash array (short reset instruction)
       }
     }
   }
  return err;
 }







void WriteBufferToFlash(void)
/******************************************************************************
 Function   : void WriteBufferToFlash()
 Parameters : (none)
 Description: Receives (writes) TransferLength sectors with length of 512 Bytes

 How it works:
 This SW burns data into internal uPSD NOR FLASH. To save FLASH RW cycles,
 it is looking for empty sector part you are burning in.
 If the area is filled by 0xFF only, the sector part is assumed
 to be erased before, so only data are written directly to the selected flash
 sector.
 If not, the sector is copied to the last flash sector #8,
 erased afterwards and written back (with the updated data block).
 ******************************************************************************/
 {
  data unsigned char j,page;
  data unsigned int i,SectorEndPhysicalDataAddr;


  UPSD_xreg.DATAOUT_D = 0;                   // WRITE, RED LED ON !

  if (TransferLength != 0)
   {
                                             // Test the block (following 64B).
    USEL  = OUTDIR | UMSC_OUT_ENDPOINT;      // Select EP3 OUT

    i = PhysicalDataAddr;
    j = 0;
// now check whether is necessary to erase the block or not; it saves Flash RW cycles
    while (j<64)
     {
      if (( ( ((unsigned char volatile xdata *) 0)[i]) | USB_FIFO[j]) != 0xFF)
       {
        j = 255;
       }
      else
       {
        i++;
        j++;
       }
     }


    if (j == 255)             //check whether the sector needs to be erased or not
     {
      page = UPSD_xreg.PAGE;
      UPSD_xreg.PAGE = 7;

      EraseMainFlashSector();                //erase sector #8;
                                  //now calculate the max. FLASH area to be erased
           //TransferLength holds number of 64B packets to be received and written
      if ((TransferLength>=512) || ((PhysicalDataAddr+(TransferLength<<6))<0x8000))
       {
        SectorEndPhysicalDataAddr = 0xFFFF;  //the top of memory
       }
      else
       {
        SectorEndPhysicalDataAddr = PhysicalDataAddr+(((unsigned int)TransferLength)<<6)-1;
       }


      UPSD_xreg.PAGE = page;                 // the sector part needs to be erased
      i = 0x8000;               //now copy the FLASH sector to the flash sector #8
      while (i != 0)   //  copy only the area without the part we are updating now
       {
        if ((i<PhysicalDataAddr) || (i>SectorEndPhysicalDataAddr))    //write back
         {
          j = ((unsigned char volatile xdata *) 0)[i];
          if (j != 0xFF)                     // do not write 0xFF
           {
            UPSD_xreg.PAGE = 7;
            if (WriteToMainFlash(i,j) == TRUE)
             {
              gbCSWStatus = FAIL;          //error during write operation occured!
              i = 0xFFFF;
             }
            UPSD_xreg.PAGE = page;
           }
         }
        i++;                           // this area will be replaced by a new data
       }

      EraseMainFlashSector();                // erase sector


// now we have a copy of data in the sector #8 with the erase area we need to update

      i = 0x8000;
      while (i != 0)              //copy the rest of data back to the orig. sector
       {
        UPSD_xreg.PAGE = 7;
        j = ((unsigned char volatile xdata *) 0)[i];
        if (j != 0xFF)                       // do not write 0xFF, already present
         {
          UPSD_xreg.PAGE = page;
          if (WriteToMainFlash(i,j) == TRUE)
           {
            gbCSWStatus = FAIL;            //error during write operation occured!
            i = 0xFFFF;                      //end loop
           }
         }
        i++;
       }

      UPSD_xreg.PAGE = page;

⌨️ 快捷键说明

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