用DeviceIoControl实现在线下载固件

硬件环境:Cypress公司的EZ-USB2.0芯片CY7C68013-128AC.

主要程序:

#include "stdafx.h"
#include "ConfigSensor.h"
#include <iostream.h>
int iMaxOpsPending = 3; //max count of pending
char strBlkBuf[MAX_FILE_SIZE]; //the data to be written
int iDataLen;     //the len of the data
int iDataOffset;    //the offset of the data
int iAutoHoldRun = 1;   //allow auto hold or run
int bHoldOrRun;
HANDLE ghDevice;
int LoadFile(CString strDldFile)
{
 unsigned char* pbuf = (unsigned char *) strBlkBuf;
// unsigned char* pVenbuf = (unsigned char *)((CEzMrFrame*)GetParentFrame())->VenBuf;
// strDldFile.MakeLower(); // case insensitive compare


 if(strDldFile.Find(".hex") != -1) //intel hex format
 {
  FILE *fp = fopen(strDldFile, "rb");
  if(fp)
  {
    char endianConversion = 0;    // Mask for endian conversion
    DWORD offset = 0;           // Offset -- set to -1 to get offset from srec or hex file


    TMemCache mMemCache;
    TMemImg mMemImg;
    mMemCache.pImg = &mMemImg;
    int result = intel_in(fp, &mMemCache, offset, endianConversion, FALSE);
          fclose(fp);

/*    for(int k=0; k<mMemCache.nSeg; k++)
    { //check for high mem first; load loader first if necessary
   if(mMemCache.pSeg[k].TAddr >= 0x2000)
   {
    if((!theApp.m_nUseUserDefinedLoader) && (!theApp.m_nUseNoLoader))
    {
      if(theApp.m_nTarg)
      { // if Fx2
     TRACE("loading Fx2 loader/n");
     Ezusb_DownloadIntelHex(Vend_Ax_Fx2);
     break;
      }
      else
      { // if Ezusb
     TRACE("loading Ezusb loader/n");
     Ezusb_DownloadIntelHex(Vend_Ax);
     break;
      }
    }
   }
    }

    for(int i=0; i<theApp.m_MemCache.nSeg; i++)
    { //load all high mem first
   if(theApp.m_MemCache.pSeg[i].TAddr >= 0x2000)
   {
    char text[80];
    memcpy(pVenbuf, theApp.m_MemCache.pSeg[i].pData, theApp.m_MemCache.pSeg[i].Size);
    SendOp(OP_VEND_REQST);
   }
   if( ( m_nOpsPending ) >= theApp.m_nMaxOpsPending)
    break;
    }*/
    if(result == -1)
     return result; //error
    if(iAutoHoldRun)
   On_8051_HOLD();

    for(int j=0; j < mMemCache.nSeg; j++)
    { //load all low mem last
   if(mMemCache.pSeg[j].TAddr < 0x2000)
   {
    memcpy(pbuf, mMemCache.pSeg[j].pData, mMemCache.pSeg[j].Size);
    iDataLen = mMemCache.pSeg[j].Size;
    iDataOffset = mMemCache.pSeg[j].TAddr;
    SendOp(OP_ANCHOR_DLD);
   }
    }
    if(iAutoHoldRun)
      On_8051_RUN();
    return result;
  }
  else
  {
          AfxMessageBox("Error opening Input file.");
    return -1;
  }
 }
 else
  return -1;
}
void SendOp(int OpNum)
{  
 OperationProc(OpNum);
}
void OperationProc(int OpNum)
{
 BOOLEAN bResult                         = FALSE;
 int     nBytes                          = 0;
 HANDLE  hDevice;
 char pcDriverName[]      = "EZUSB-0";
 switch(OpNum)
 {
  case OP_ANCHOR_DLD:
  {
   int numread = 0;
   char                   temp[64]  = "";
   ANCHOR_DOWNLOAD_CONTROL downloadControl;
    
   unsigned char* buffer;
   downloadControl.Offset = (USHORT) iDataOffset;
   buffer = (unsigned char*) strBlkBuf;
   numread = iDataLen;

   wsprintf (temp, "Anchor Download %d bytes: addr=%x",numread, downloadControl.Offset);
   cout<<temp<<endl;
    
   // Open the driver
   if (bOpenDriver (&hDevice, pcDriverName) != TRUE)
   {
    cout<<"Failed to Open Driver"<<endl;
    hDevice = NULL;
   }
   
   if (hDevice != NULL)
   {
    if(iDataOffset < 0x2000)
    {
     bResult = DeviceIoControl (hDevice,
      IOCTL_EZUSB_ANCHOR_DOWNLOAD,
      &downloadControl,
      sizeof(ANCHOR_DOWNLOAD_CONTROL),
      buffer,
      numread,
      (unsigned long *)&nBytes,
      NULL);
     if(!bResult)
      cout<<"Download error!"<<endl;
    }
    else
    {
     VENDOR_OR_CLASS_REQUEST_CONTROL myRequest;
     myRequest.request = (BYTE) 0xA3;
     myRequest.value = (WORD) iDataOffset;
     myRequest.index = (WORD) 0x00;
     myRequest.direction = 0;
     myRequest.requestType = 2;
     myRequest.recepient = 0;
      
     bResult = DeviceIoControl (hDevice,
      IOCTL_EZUSB_VENDOR_OR_CLASS_REQUEST,
      &myRequest,
      sizeof(VENDOR_OR_CLASS_REQUEST_CONTROL),
      buffer,
      numread,
      (unsigned long *)&nBytes,
      NULL);
     
     if (bResult==TRUE)
     {
      /*if(theApp.m_nVerbose)
       DumpBuffer(buffer,nBytes,hOutputBox);*/
     }
     else
     {
      cout<<"Vendor Request failed"<<endl;
     }
    }
   }/* if valid driver handle */
    
   if (bResult==TRUE)
   {
    // do nothin
   }
   else
   {
    cout<<"Anchor Download failed"<<endl;
   }
    
   CloseHandle (hDevice); // Close the handle
    
  }
  break;
  case OP_8051__HOLD:
  case OP_8051___RUN:
  {
   VENDOR_REQUEST_IN myRequest;
   cout<<"Toggle 8051 Reset"<<endl;
   bool bFX2 = true;    //use fx2
    
   // Open the driver
   if (bOpenDriver (&hDevice, pcDriverName) != TRUE)
   {
    cout<<"Failed to Open Driver"<<endl;
    hDevice = NULL;
   }
   
   myRequest.bRequest = 0xA0;
   if(bFX2)
     myRequest.wValue = 0xE600; // using CPUCS.0 in FX2
   else
     myRequest.wValue = 0x7F92;
   myRequest.wIndex = 0x00;
   myRequest.wLength = 0x01;
   myRequest.bData = (bHoldOrRun == OP_8051__HOLD) ? 1 : 0;
   myRequest.direction = 0x00;
    
   if (hDevice != NULL)
   {// Perform the Get-Descriptor IOCTL
    bResult = DeviceIoControl (hDevice,
     IOCTL_Ezusb_VENDOR_REQUEST,
     &myRequest,
     sizeof(VENDOR_REQUEST_IN),
     NULL,
     0,
     (unsigned long *)&nBytes,
     NULL);
     
   }/* if valid driver handle */
   
   if (bResult==TRUE)
   {
    // do nothin
   }
   else
   {
    cout<<"Reset Failed"<<endl;
   }
   
   // Close the handle
   CloseHandle (hDevice);
  }
   
  break;
 }// end of switch
   
}
void On_8051_HOLD()
{  //TPMDo: Add m_wndTBarVen manually
 bHoldOrRun = OP_8051__HOLD;
 SendOp(OP_8051__HOLD);
}
void On_8051_RUN()
{  //TPMDo: Add m_wndTBarVen manually
 bHoldOrRun = OP_8051___RUN;
 SendOp(OP_8051___RUN);
}
#define MAXSTR 256 // Maximum length of Intel Hex file string
int intel_in(FILE *fpIn, TMemCache* pMemCache, DWORD &ioOffset,
      char endianFlags, BOOLEAN spaces)
{
 int i;
 char str[MAXSTR];
 unsigned byte;
 
 int curSeg = 0;   // current seg record
 int recType;
 unsigned addr;
 int cnt;
 unsigned int totalRead = 0;
 int CNTFIELD ;
 int ADDRFIELD;
 int RECFIELD ;
 int DATAFIELD;
 
 // offsets of fields within record -- may change later due to "spaces" setting
 CNTFIELD    = 1;
 ADDRFIELD   = 3;
 RECFIELD    = 7;
 DATAFIELD   = 9;
 
 if (!fpIn)
  return(0);
 
 addr = 0;
 
 pMemCache->nSeg = 0;
 while(fgets(str,MAXSTR,fpIn))
 {
  TRACE("dldhex:%s", str);
  if(str[0]!=':')
  {
   return(-1);
  }
  
  /* get the record type */
  if (spaces || str[1] == ' ')
  {
   CNTFIELD    = 1 + 1;
   ADDRFIELD   = 3 + 2;
   RECFIELD    = 7 + 3;
   DATAFIELD   = 9 + 4;
  }
  
  sscanf(str+RECFIELD,"%2x",&recType);
  
  PCHAR ptr = pMemCache->pImg->data;
  switch(recType)
  {
  case 2: /*seg record*/
   sscanf(str+DATAFIELD,"%4x",&curSeg);
   curSeg *= 0x10;
   break;
   
  case 0: /*data record*/
   sscanf(str+CNTFIELD,"%2x",&cnt);
   sscanf(str+ADDRFIELD,"%4x",&addr);
   if(addr >= TGT_IMG_SIZE)
   {
    cout<<"Error loading file: address out of range/n";
    return(totalRead);
   }
   ptr += addr; // get pointer to location in image
   
   if(pMemCache->nSeg &&
    (pMemCache->pSeg[pMemCache->nSeg-1].TAddr ==
    addr - pMemCache->pSeg[pMemCache->nSeg-1].Size) &&
    (pMemCache->pSeg[pMemCache->nSeg-1].Size + cnt <= MAX_EP0_XFER_SIZE) )
   { // if the segment is contiguous to the last segment, and it's not too big yet
    pMemCache->pSeg[pMemCache->nSeg-1].Size += cnt; // append to previous segment
   }
   else
   { // start a new segment
    pMemCache->pSeg[pMemCache->nSeg].TAddr = addr;
    pMemCache->pSeg[pMemCache->nSeg].Size = cnt;
    pMemCache->pSeg[pMemCache->nSeg].pData = ptr;
    pMemCache->nSeg++;
   }
   
   
   for(i=0; i<cnt; i++)
   {
    sscanf(str+DATAFIELD+i*2,"%2x",&byte);
    *(ptr + i) = byte;
    totalRead++;
   }
   break;
   
  case 1: /*end record*/
   return(totalRead);
   break;
   
  default:
   break;
  }
 }
 return(-1);  // missing end record
}
void Ezusb_DownloadIntelHex(PINTEL_HEX_RECORD pHexRecord)
{
   PINTEL_HEX_RECORD ptr = pHexRecord;
 unsigned char* pbuf = (unsigned char *)strBlkBuf;
 unsigned char* ptmp = NULL;

 ptr = pHexRecord;
 On_8051_HOLD();

 while (ptr->Type == 0)
 { //load low mem
  if((ptmp != NULL) &&
   (iDataOffset+iDataLen == ptr->Address) &&
   ((iDataLen+ptr->Length) <= MAX_EP0_XFER_SIZE) )
  { // continue a segment
   memcpy(ptmp, ptr->Data, ptr->Length);
   iDataLen += ptr->Length;
   ptmp += ptr->Length;
  }
  else
  { // start a new segment
   if(ptmp != NULL)
   { // send prev segment first
    SendOp(OP_ANCHOR_DLD);
   }
   ptmp = pbuf;
   memcpy(ptmp, ptr->Data, ptr->Length);
   iDataLen = ptr->Length;
   iDataOffset = ptr->Address;
   ptmp += ptr->Length;
  }
        ptr++;
 }
 if(ptmp != NULL)
 { // send final segment
  SendOp(OP_ANCHOR_DLD);
 }

 On_8051_RUN();
}
BOOLEAN bOpenDriver(HANDLE * phDeviceHandle, PCHAR devname)
{
    char completeDeviceName[64] = "";
    char pcMsg[64] = "";

    strcat (completeDeviceName,
            "////.//"
            );
    strcat (completeDeviceName,
      devname
      );
    *phDeviceHandle = CreateFile(   completeDeviceName,
                              GENERIC_WRITE,
                              FILE_SHARE_WRITE,
                              NULL,
                              OPEN_EXISTING,
                              0,
                              NULL);

    if (*phDeviceHandle == INVALID_HANDLE_VALUE)
 {
        return (FALSE);
    }
 else
 {
        return (TRUE);
    } /*else*/


}//OpenDevice
BOOLEAN ConnectDevice()
{
 HANDLE  hDevice = NULL;
 char    DeviceName[MAX_DRIVER_NAME]   = "EZUSB-0";
 
 if (bOpenDriver (&hDevice, DeviceName) != TRUE)
 {
  cout<<"Failed to Open Device/n";
  return false;
 }

// ghDevice = hDevice;
 CloseHandle(hDevice);
 return true;
}//ConnectDevice

你可能感兴趣的:(File,null,buffer,download,byte,hex)