📄 upsd3400_usb_app.c
字号:
/*------------------------------------------------------------------------------
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 + -