📄 flash.c
字号:
/*
* The content of this file or document is CONFIDENTIAL and PROPRIETARY
* to Jade Technologies Co., Ltd. It is subjected to the terms of a
* License Agreement between Licensee and Jade Technologies Co., Ltd.
* restricting among other things, the use, reproduction, distribution
* and transfer. Each of the embodiments, including this information
* and any derivative work shall retain this copyright notice.
*
* Copyright (c) 2004 - 2005 Jade Technologies Co., Ltd.
* All rights reserved.
*/
// ----------------------------------------------------------------
// File: flash.c,v
// Revision: 1.0
// ----------------------------------------------------------------
// $
//
#include <windows.h>
#include <halether.h>
#include <platform.h>
#include <flash_lib.h>
#include <sizes.h>
#include <cdefs.h>
//#include <apcharlcd.h>
#include "eboot.h"
//
// Physical address of the NK image in RAM (when not in flash)
// NOTE: This must match the config.bib settings
//
#define NK_RAM_BASE 0x00070000
//
// Download file cache used when flashing an image - use RAM image space.
// NOTE: Must match eboot.bib setting.
//
#define FCACHE NK_RAM_BASE
//
// Intel 28F256L30 flash commands and status definitions.
//
#define PROGRAM_COMMAND 0x1010
#define PROGRAM_VERIFY 0xD0D0
#define READ_STATUS 0x7070
#define CLEAR_STATUS 0x5050
#define READ_ARRAY 0xFFFF
#define BLOCK_ERASE 0x2020
#define BLOCK_WRITE_MODE 0xE8E8
#define BLOCK_LOCK_SETUP 0x6060
#define BLOCK_LOCK 0x0101
#define BLOCK_UNLOCK 0xD0D0
#define CFI_QUERY_COMMAND 0x9898
#define STATUS_READY 0x0080
#define STATUS_LOCKED 0x0001
#define STATUS_LOCK_ERROR 0x0010
#define STATUS_ERASE_ERROR 0x0020
// Maximum flash write buffer in words
#define MAX_WRITE_BUFF 0x20
#define BLOCK_ERASE_STEP 3
//
// Helper macros.
//
#define TOTAL_FLASH_BLOCKS (ARMVPB_FLASH_SIZE / ARMVPB_FLASH_BLOCK_SIZE)
#define BLOCK_ADDR(i) (PHYS_FLASH_BASE + (i * ARMVPB_FLASH_BLOCK_SIZE))
#define BLOCK_NUM(i) ((i - PHYS_FLASH_BASE) / ARMVPB_FLASH_BLOCK_SIZE)
//
// Flash block variables used for block erasure.
//
ULONG gnStartBlock;
ULONG gnEndBlock;
ULONG gnBlocks;
ULONG gnBlockCount;
// Boot loader settings
extern BLDR_SETTINGS g_BldrSettings;
//
// Function prototypes.
//
void OEMWriteDebugByte(UCHAR ch);
int32 CFI_Lock_Bit_Set(unsigned16 *address);
int32 CFI_Lock_Bit_Clear(unsigned16 *address);
int32 CFI_Check_Status( volatile unsigned16 *vflash );
///////////////////////////////////////////////////////////////////
// Intel 28F256L30 Flash Routines
//
static int32 CFI_Check_Status( volatile unsigned16 *vflash )
{
volatile unsigned16 s_reg;
/* Check Status Register bit 7 for correct write */
do
{
*vflash = READ_STATUS;
s_reg = *vflash;
} while ((s_reg & STATUS_READY) != STATUS_READY);
s_reg &= ~STATUS_READY;
if( s_reg!=0 )
{
*vflash = CLEAR_STATUS;
}
*vflash=READ_ARRAY;
if(s_reg!=0)
return -1;
else
return 0;
}
static int32 CFI_Lock_Bit_Set( unsigned16 *address )
{
int32 iRet = PASS;
volatile unsigned16 *vflash = (volatile unsigned16*)address;
/* Set block lock bit at block address */
*vflash = BLOCK_LOCK_SETUP;
// Confirm Block lock bit at block address
*vflash = BLOCK_LOCK;
if (CFI_Check_Status(vflash)==-1) iRet = FAIL;
/* Reset for Read operation */
*vflash = READ_ARRAY;
return (iRet);
}
static int32 CFI_Lock_Bit_Clear( unsigned16 *address )
{
int32 iRet = PASS;
volatile unsigned16 *vflash = (volatile unsigned16*)address;
/* Clear lock bits */
*vflash = BLOCK_LOCK_SETUP;
/* Confirm action */
*vflash = BLOCK_UNLOCK;
if (CFI_Check_Status(vflash)==-1) iRet = FAIL;
/* Reset for Read operation */
*vflash = READ_ARRAY;
return (iRet);
}
int32 CFI_Write_Word (unsigned16 *address, unsigned16 data)
{
int32 iRet = PASS;
volatile unsigned16 *vflash = (volatile unsigned16*)address;
CFI_Lock_Bit_Clear( address );
/* CFI routine for Intel is firstly issue program command 0x10 (word)
* and address of data
*/
*vflash = PROGRAM_COMMAND;
/* Write required word to required address */
*vflash = data;
if (CFI_Check_Status(vflash)==-1) iRet = FAIL;
CFI_Lock_Bit_Set( address );
return(iRet);
}
int32 CFI_Write_Block(unsigned16 *address, unsigned16 *data,
unsigned32 size)
{
int32 iRet = PASS;
volatile unsigned16 *vflash = (volatile unsigned16*)address;
volatile unsigned16 s_reg;
int n, nWords = 0;
unsigned32 bytesWritten = 0, bytesLeft = size;
if (0 != ((unsigned16)address & 0x1))
{
EdbgOutputDebugString("ERROR: CFI_Write_Block - address must fall on a block-aligned boundary (0x%x).\r\n",
(unsigned32)address);
return(FAIL);
}
CFI_Lock_Bit_Clear( address );
while ( bytesLeft > 0 && iRet == PASS)
{
/* buffer available? */
do
{
/* Start write to buffer */
*vflash = BLOCK_WRITE_MODE;
/* Read status */
s_reg = *vflash;
} while((s_reg & STATUS_READY) != STATUS_READY);
/* Generate the number of words to write */
/* Remember that size is in bytes so divide by 4 for word accesses */
if ((bytesLeft / 2) < MAX_WRITE_BUFF)
{
nWords = (bytesLeft / 2);
}
else
{
nWords = MAX_WRITE_BUFF;
}
/* Write word count minus one (flash starts at word 0) */
*vflash = ((nWords-1));
/* Write data */
for( n = nWords; n > 0; n-- )
{
*vflash++ = *data++;
}
// Show something to indicate progress...
if (!(bytesWritten % 8192))
{
EdbgOutputDebugString(".");
OEMWriteDebugByte(0x20); // Space
OEMWriteDebugByte(0x8); // Backspace
}
/* Confirm write - using the address of the last word written
* This makes sure we confirm the write to the same block as we
* wrote the data to.
*/
*(vflash - 1) = PROGRAM_VERIFY;
s_reg = CFI_Check_Status(vflash);
if( s_reg ==-1 )
{
EdbgOutputDebugString("FLASH ERROR: Block write failed (%08x). %d bytes written\r\n", s_reg, bytesWritten);
iRet = FAIL;
}
/* Advance pointers - in bytes */
bytesLeft -= (nWords * 2);
bytesWritten += (nWords * 2);
// Check for wrap round error
if( bytesLeft > size )
{
EdbgOutputDebugString("FLASH ERROR: Too many bytes written. Size = %d, Written = %d\r\n", size, bytesWritten);
iRet = FAIL;
}
}
// EdbgOutputDebugString("Size: %d, Written: %d, left: %d\r\n", size, bytesWritten, bytesLeft);
EdbgOutputDebugString("\r\n");
/* reset to read mode */
*vflash = READ_ARRAY;
CFI_Lock_Bit_Set( address );
return(iRet);
}
int32 CFI_Read_Word (unsigned16 *address, unsigned16 *value)
{
/* just read the address */
*value = *address;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -