?? ezusb_lib.c
字號(hào):
/**************************************************************
* File - ezusb_lib.c
*
* Library for accessing EZ-USB devices.
* The library accesses the hardware via WinDriver functions.
*
* Copyright (c) 2003 - 2006 Jungo Ltd. http://www.jungo.com
**************************************************************/
#include <stdio.h>
#include "wdu_lib.h"
#include "status_strings.h"
#include "utils.h"
#include "ezusb_lib.h"
/* Implementation of the Firmware download starts here. */
#include "Vend_Ax.h"
#if !defined(ERR)
#define ERR printf
#endif
#if !defined(TRACE)
#define TRACE printf
#endif
#define MAX_FILE_SIZE 1024 * 8
#define TGT_IMG_SIZE 0x10000 /* 64KB (65,536 Byte) target image */
#define TGT_SEG_SIZE 16 /* 16 byte segments */
#define DEFAULT_TIMEOUT 10000
static BYTE BlkBuf[MAX_FILE_SIZE];
static BYTE VenBuf[MAX_FILE_SIZE];
static DWORD Offset, Len;
char sInfoString[4000];
typedef struct
{
DWORD TAddr; /* Target Address */
DWORD HAddr; /* Host Address */
DWORD Size; /* block size */
DWORD Stat; /* status */
PCHAR pData; /* data bytes */
} MemSeg;
typedef struct
{
CHAR data[TGT_IMG_SIZE]; /* target image store */
} TMemImg;
typedef struct
{
TMemImg *pImg;
int nSeg; /* segment count */
MemSeg pSeg[TGT_IMG_SIZE/TGT_SEG_SIZE]; /* info about segments */
} TMemCache;
static int FileToString(TMemCache* pMemCache, CHAR *pHexFileName);
static BOOL DownloadIntelHex(HANDLE hDev, BOOL IsFx2);
static BOOL DownLoadBuf(HANDLE hDev, DWORD address, DWORD length, void *buffer,
BYTE bRequest);
static DWORD ResetBit(HANDLE hDev, int DoReset, BOOL IsFx2);
BOOL DownloadFirmware(HANDLE hDev, PCHAR pHexFileName, BOOL IsFx2)
{
BYTE *pbuf = BlkBuf;
BYTE *pVenbuf = VenBuf;
TMemCache *pMemCache;
DWORD dwNumRead;
BOOL rc = FALSE;
int i;
sInfoString[0] = '\0';
pMemCache = (TMemCache *)malloc(sizeof(TMemCache));
if (!pMemCache)
{
sprintf(sInfoString, "DownloadFirmware: Insufficient resources\n");
goto Exit;
}
pMemCache->pImg = (TMemImg *)malloc(TGT_IMG_SIZE);
if (!pMemCache->pImg)
{
sprintf(sInfoString, "DownloadFirmware: Insufficient resources\n");
goto Exit;
}
dwNumRead = FileToString(pMemCache, pHexFileName);
if (!dwNumRead)
goto Exit;
/* check for high mem first, load loader first if necessary */
for (i=0; i<pMemCache->nSeg; i++)
{
if (pMemCache->pSeg[i].TAddr >= 0x2000)
{
if (!DownloadIntelHex(hDev, IsFx2))
goto Exit;
break;
}
}
/* load all high mem first */
for (i=0; i<pMemCache->nSeg; i++)
{
if (pMemCache->pSeg[i].TAddr >= 0x2000)
{
memcpy(pVenbuf, pMemCache->pSeg[i].pData, pMemCache->pSeg[i].Size);
if (!DownLoadBuf(hDev, pMemCache->pSeg[i].TAddr,
pMemCache->pSeg[i].Size, pVenbuf, 0xA3))
{
goto Exit;
}
}
}
ResetBit(hDev, 1, IsFx2);
/* load all low mem last */
for (i=0; i<pMemCache->nSeg; i++)
{
if (pMemCache->pSeg[i].TAddr < 0x2000)
{
memcpy(pbuf, pMemCache->pSeg[i].pData, pMemCache->pSeg[i].Size);
Len = pMemCache->pSeg[i].Size;
Offset = pMemCache->pSeg[i].TAddr;
if (!DownLoadBuf(hDev, Offset, Len, pbuf, 0xA0))
goto Exit;
}
}
ResetBit(hDev, 0, IsFx2);
rc = TRUE;
Exit:
if (pMemCache)
{
if (pMemCache->pImg)
free(pMemCache->pImg);
free(pMemCache);
}
return rc;
}
#define MAXSTR 256 /* Maximum length of Intel Hex file string */
/* 4K Control EP0 transfer limit imposed by OS */
#define MAX_EP0_XFER_SIZE (1024*4)
static int FileToString(TMemCache* pMemCache, CHAR *pHexFileName)
{
FILE *fp;
int i, curSeg, recType, cnt;
int CNTFIELD, ADDRFIELD, RECFIELD, DATAFIELD;
CHAR str[MAXSTR];
DWORD byte, addr, totalRead;
PCHAR ptr;
fp = fopen(pHexFileName, "rb");
if (!fp)
{
sprintf(sInfoString, "Can't open %s file.\n"
"Please make sure that the file exists in the specified location\n",
pHexFileName);
return 0;
}
/* offsets of fields within record -- may change later due to "spaces"
* setting */
CNTFIELD = 1;
ADDRFIELD = 3;
RECFIELD = 7;
DATAFIELD = 9;
addr = 0;
curSeg = 0;
totalRead = 0;
pMemCache->nSeg = 0;
while (fgets(str, MAXSTR, fp))
{
if (str[0]!=':')
return 0;
if (str[1]==' ') /* get the record type */
{
CNTFIELD = 1 + 1;
ADDRFIELD = 3 + 2;
RECFIELD = 7 + 3;
DATAFIELD = 9 + 4;
}
sscanf(str+RECFIELD, "%2x", &recType);
ptr = (PCHAR)pMemCache->pImg;
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, "%4lx", &addr);
if (addr>=TGT_IMG_SIZE)
{
sprintf(sInfoString, "Error loading file: address out of "
"range\n");
return 0;
}
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 append to previous segment */
pMemCache->pSeg[pMemCache->nSeg-1].Size += cnt;
}
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, "%2lx", &byte);
*(ptr + i) = (CHAR)byte;
totalRead++;
}
break;
case 1: /* end record */
fclose(fp);
return totalRead;
default:
break;
}
}
if (fp)
fclose(fp);
return 0; /* missing end record */
}
static BOOL DownloadIntelHex(HANDLE hDev, BOOL IsFx2)
{
BYTE* pbuf = BlkBuf;
BYTE* ptmp = NULL;
PINTEL_HEX_RECORD ptr = IsFx2 ? Vend_Ax_Fx2 : Vend_Ax;
ResetBit(hDev, 1, IsFx2);
while (ptr->Type==0) /* load low mem */
{
if (ptmp && /* continue a segment */
Offset+Len==(DWORD)ptr->Address &&
Len+ptr->Length<=MAX_EP0_XFER_SIZE)
{
memcpy(ptmp, ptr->Data, ptr->Length);
Len += ptr->Length;
ptmp += ptr->Length;
}
else /* start a new segment */
{
if (ptmp) /* send previous segment first */
{
if (!DownLoadBuf(hDev, Offset, Len, pbuf, 0xA0))
return FALSE;
}
ptmp = pbuf;
memcpy(ptmp, ptr->Data, ptr->Length);
Len = ptr->Length;
Offset = ptr->Address;
ptmp += ptr->Length;
}
ptr++;
}
if (ptmp) /* send final segment */
{
if (!DownLoadBuf(hDev, Offset, Len, pbuf, 0xA0))
return FALSE;
}
ResetBit(hDev, 0, IsFx2);
return TRUE;
}
/* The download will be split into CHUNK_SIZE pieces and downloaded with
* multiple setup transfers. CHUNK_SIZE should not exceed 64 bytes, as larger
* transfers can result in data corruption when other USB devices are
* present. */
#define CHUNK_SIZE 64
static BOOL DownLoadBuf(HANDLE hDev, DWORD address, DWORD length, void *buffer,
BYTE bRequest)
{
BYTE SetupPacket[8];
DWORD dwBytesTransferred, i, size, chunkCount;
DWORD dwStatus = 0, dwOptions = 0;
void *cur;
chunkCount = (length + CHUNK_SIZE - 1) / CHUNK_SIZE;
for (i=0; i<chunkCount; i++)
{
if (i==chunkCount-1 && length % CHUNK_SIZE)
size = length % CHUNK_SIZE;
else
size = CHUNK_SIZE;
SetupPacket[0] = 0x40;
SetupPacket[1] = bRequest;
SetupPacket[2] = (BYTE)((address + i*CHUNK_SIZE) & 0xFF);
SetupPacket[3] = (BYTE)(((address + i*CHUNK_SIZE) & 0xFF00) >> 8);
SetupPacket[4] = 0;
SetupPacket[5] = 0;
SetupPacket[6] = (BYTE) size & 0xFF;
SetupPacket[7] = (BYTE) ((size & 0xFF00) >> 8);
cur = (PVOID)((DWORD)buffer + i*CHUNK_SIZE);
dwStatus = WDU_TransferDefaultPipe(hDev, FALSE, dwOptions, cur, size,
&dwBytesTransferred, SetupPacket, DEFAULT_TIMEOUT);
}
if (dwStatus)
{
sprintf(sInfoString, "DownLoadBuf: WDU_TransferDefaultPipe failed with status 0x%lx - %s\n",
dwStatus, Stat2Str(dwStatus));
return FALSE;
}
return TRUE;
}
#define CPUCS_REG_EZUSB 0x7F92
#define CPUCS_REG_FX2 0xE600
static DWORD ResetBit(HANDLE hDev, int DoReset, BOOL IsFx2)
{
BYTE reset = (BYTE)DoReset;
BYTE SetupPacket[8];
DWORD dwBytesTransferred;
DWORD dwCpucs = IsFx2 ? CPUCS_REG_FX2 : CPUCS_REG_EZUSB;
sInfoString[0] = '\0';
SetupPacket[0] = 0x40;
SetupPacket[1] = 0xA0;
SetupPacket[2] = (BYTE)(dwCpucs & 0xFF);
SetupPacket[3] = (BYTE)((dwCpucs & 0xFF00) >> 8);
SetupPacket[4] = 0;
SetupPacket[5] = 0;
SetupPacket[6] = 1;
SetupPacket[7] = 0;
return WDU_TransferDefaultPipe(hDev, FALSE, 0, &reset, 1,
&dwBytesTransferred, SetupPacket, DEFAULT_TIMEOUT);
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -