📄 fburncmd.c
字号:
/*
********************************************************************
* (C) COPYRIGHT TEXAS INSTRUMENTS, INC. 2000, 2001
* FlashBurn Programming Functions
* for FBTC54
*
* $Log: FBurnCmd.c,v $
* Revision 1.11 2001/06/27 17:55:13 heeschen
* v00.32 Beta Prep
* Capturing all files to prepare for Beta Release
*
* Revision 1.10 2001/04/19 18:56:34 heeschen
* v00.30 Alpha - Updated comments
*
* Revision 1.9 2001/04/19 16:29:01 heeschen
* v00.30 Snapshot
* Saving this stuff after massive redesign to remove RTDX dependency.
* Next step is to clean up, fix comments, and do unit testing.
*
*/
#include <stdio.h>
#include "fbtc54.h"
#include <board.h>
#include "fbcmd.h"
extern u16 theMessage[];
/* --------------------------
* EXTERNAL MEMORY ADDRESSING
* HELPERS
* --------------------------
*/
/* Used by the checksum calculator funcs.
*/
static unsigned long cksum = 0;
/* Non-zero if flash is erasing.
* Changes to zero when we determine
* that erasure is complete.
*/
static int ErsStatus = 0;
/* flashstart and flashnext are used to track
* where we are in a "flat" Flash memory.
* Paging, etc. are handled by helper funcs.
* flashbaseoverride is 0 normally, but changes
* if Host sends the Change FLASHSTART Address command.
* Thus if it's not 0xffffffff, then it should be used
* instead of the FLBASE value.
*/
static unsigned long flashstart = FLBASE;
static unsigned long flashnext = FLBASE;
/* These are "override" values, in case the
* Host has sent new flash base addr and size.
*/
static unsigned long flashbaseov = 0xffffffffL;
static unsigned long flashsizeov = 0xffffffffL;
/* Set and get the flash base address
*/
void SetFlashBase(unsigned long val)
{
flashbaseov = val;
}
unsigned long GetFlashBase(void)
{
return flashbaseov != 0xffffffffL ? flashbaseov : FLBASE;
}
/* Set and get the flash size
*/
void SetFlashSize(unsigned long val)
{
flashsizeov = val;
}
unsigned long GetFlashSize(void)
{
return flashsizeov != 0xffffffffL ? flashsizeov : FLSIZEBYTES;
}
/* Set the External Memory Page Register
*/
void SetPage(u16 pnum)
{
port2 = pnum & 0x1f;
}
/* Flash memory addressing on the 54x
* ----------------------------------
* Pages are 32K words, starting at 0x8000.
* Comm Protocol uses a logical address in a
* "flat" address space. Host also uses
* 8-bit byte counts instead of word counts.
*
* Thus when Host wants 256 bytes written at
* logical address 0x20004, we need to convert
* from 0x20004 to page and address within page:
* 0x20004 = Page 4, addr 4
*/
/* Returns page number given "flat" address.
*/
u16 GetPageNum(unsigned long addr)
{
return (u16)((addr - GetFlashBase()) / FLPAGELEN);
}
/* Returns the on-page address for a given "flat" address.
*/
u16 *GetPageAddr(unsigned long addr)
{
unsigned long myoffset = addr - GetFlashBase();
return (u16 *)(GetFlashBase() + (myoffset % FLPAGELEN));
}
/* Returns the remaining # of MAUs
* on the page for a given "flat" address.
*/
u16 GetPageMAURemaining(unsigned long addr)
{
unsigned long myoffset = addr - GetFlashBase();
return FLPAGELEN - (myoffset % FLPAGELEN);
}
/* --------------------------------
* Flash memory handlers
* --------------------------------
*/
void InitFlash(void)
{
flashstart = GetFlashBase();
flashnext = flashstart;
}
void SetFlashAddr(unsigned long addr)
{
flashstart = addr;
flashnext = flashstart;
}
volatile u16 *GetNextFlashAddr(void)
{
return (volatile u16 *)flashnext;
}
/* Flash is accesed via external memory
* pages.
* For the STMicro Flash (M29W400),
* we must program 1 word at a time.
*/
void BurnFlash(u16 *data, u16 nBytes)
{
/* Convenient pointers for sending
* commands to flash chip.
*/
volatile u16 *p5 = (u16 *)(GetFlashBase()+0x5555UL);
volatile u16 *pA = (u16 *)(GetFlashBase()+0x2AAAUL);
volatile u16 *pBurn;
u16 page, pagelast;
unsigned long timeoutcount;
int nWords = nBytes >> 1;
if(nWords <= 0)
return;
/* Set paging and enable flash access
*/
page = GetPageNum(flashnext);
pagelast = GetPageNum(flashnext + nWords - 1);
FlashEnable();
if(pagelast == page)
{
/* All words to be written are
* within the same page.
*/
pBurn = GetPageAddr(flashnext);
flashnext += nWords; /* For next time */
while(nWords-- > 0)
{
SetPage(0);
*p5 = 0xaa;
*pA = 0x55;
*p5 = 0xa0;
SetPage(page);
*pBurn = *data;
timeoutcount = 0;
do timeoutcount += 1;
while(*pBurn != *data && timeoutcount < 0xffff);
if(timeoutcount == 0xffff)
break;
pBurn++;
data++;
}
}
else
{
/* Programming crosses at least
* one page boundary.
*/
while(nWords-- > 0)
{
page = GetPageNum(flashnext);
pBurn = GetPageAddr(flashnext);
SetPage(0);
*p5 = 0xaa;
*pA = 0x55;
*p5 = 0xa0;
SetPage(page);
*pBurn = *data;
timeoutcount = 0;
do timeoutcount += 1;
while(*pBurn != *data && timeoutcount != 0xffff);
if(timeoutcount == 0xffff)
break;
data++;
flashnext++;
}
}
SetPage(0);
FlashDisable();
}
void CheckFlashErase(void)
{
while(ErsStatus != 0)
{
FlashEnable();
SetPage(0);
if(*((u16 *)GetFlashBase()) == 0xffff)
{
ErsStatus = 0;
}
FlashDisable();
}
}
void EraseFlash(void)
{
volatile u16 *p5 = (u16 *)(GetFlashBase()+0x5555UL);
volatile u16 *pA = (u16 *)(GetFlashBase()+0x2AAAUL);
InitFlash();
/* Set page to 0 and enable flash access
*/
FlashEnable();
SetPage(0);
/* Erase chip
* It takes about 2.5 secs for this,
* according to specs for the STMicro
* M29W400.
*/
*p5 = 0xAA;
*pA = 0x55;
*p5 = 0x80;
*p5 = 0xAA;
*pA = 0x55;
*p5 = 0x10;
FlashDisable();
ErsStatus = 1;
CheckFlashErase(); // returns when erase is done
}
/* This is not used by FlashBurn. In fact, it hasn't
* even been tested...
*/
void EraseFlashSector(u16 sector)
{
volatile u16 *p5 = (u16 *)(GetFlashBase()+0x5555UL);
volatile u16 *pA = (u16 *)(GetFlashBase()+0x2AAAUL);
volatile u16 *pBase = (u16 *)GetFlashBase();
unsigned long timeoutcount;
if(sector > 7)
return;
InitFlash();
/* Set page to 0 and enable flash access
*/
FlashEnable();
SetPage(0);
/* Erase sector
* It takes about ?? secs for this,
* according to specs for the STMicro
* M29W400.
*/
*p5 = 0xAA;
*pA = 0x55;
*p5 = 0x80;
*p5 = 0xAA;
*pA = 0x55;
SetPage(sector);
*pBase = 0x30;
/* Simpleminded (and possibly dangerous)
* delay to wait for erasure to complete.
*/
timeoutcount = 0;
do
{
timeoutcount += 1;
}
while(*pBase != 0xffff && timeoutcount < 0xfffff);
SetPage(0);
FlashDisable();
return;
}
/* ------------------
* Checksum Functions
* ------------------
*/
void CKSSet(u16 val)
{
cksum = val;
}
u16 CKSGet(void)
{
return (u16)cksum;
}
/* bufptr is start address in flash memory,
* len is length in 8-bit Bytes!
*/
u16 CKSAccumBuf(unsigned long bufptr, unsigned long len)
{
u16 page;
u16 *pPage;
long n;
len /= BYTESPERMAU; // MAUs
while(len > 0)
{
/* How many bytes can I read from this page?
*/
page = GetPageNum(bufptr);
n = GetPageMAURemaining(bufptr);
if(n > len)
{
n = len;
}
len -= n; /* for next time thru */
/* Set paging and enable flash access
*/
pPage = GetPageAddr(bufptr);
bufptr += n;
SetPage(page);
FlashEnable();
/* Accumulate bytes into the checksum
*/
while(n-- > 0)
{
unsigned long val = *pPage++;
cksum += val >> 8; //MSB
if(cksum >= 65536)
{
cksum += 1;
cksum &= 0xffff;
}
cksum += val & 0x000000ff; // LSB
if(cksum >= 65536)
{
cksum += 1;
cksum &= 0xffff;
}
}
SetPage(0);
FlashDisable();
}
return (u16)cksum;
}
u16 GetFlashVal(unsigned long addr)
{
u16 myval;
FlashEnable();
SetPage(GetPageNum(addr));
myval = *GetPageAddr(addr);
FlashDisable();
return myval;
}
void SendFlashBufToHost(u16 cmd, unsigned long addr, u16 bytecount)
{
u16 *pagememptr;
u16 pagestart, pagelast;
u16 i, n;
pagestart = GetPageNum(addr);
pagelast = GetPageNum(addr+bytecount/BYTESPERMAU-1);
// Prepare the response message header
theMessage[CMDINDEX] = cmd;
theMessage[ARGINDEX+0] = bytecount;
FlashEnable();
if(pagestart == pagelast)
{
// All desired data are in same page.
SetPage(pagestart);
pagememptr = GetPageAddr(addr);
n = bytecount / 2;
for(i=0; i<n; i+=1)
{
theMessage[DATAINDEX+i] = *pagememptr++;
}
}
else
{
// Desired data cross at least one
// page boundary
u16 len = bytecount / 2;
u16 n;
u16 *dataptr;
dataptr = &theMessage[DATAINDEX];
while(len > 0)
{
/* How many bytes can I read from this page?
*/
pagestart = GetPageNum(addr);
n = GetPageMAURemaining(addr);
if(n > len)
{
n = len;
}
len -= n; /* for next time thru */
/* Set paging and enable flash access
*/
pagememptr = GetPageAddr(addr);
addr += n; /* also for next time thru */
SetPage(pagestart);
while(n-- > 0)
{
*dataptr++ = *pagememptr++;
}
}
}
SetPage(0);
FlashDisable();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -