📄 flash.c
字号:
/***************************************************************************
* File: flash.c
* Modified By: Naresh Gupta (nkgupta@hotmail.com)
* Organization: Hitachi Semiconductor America Inc.
* Date: Oct 29, 1999
***************************************************************************/
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1998 Hitachi,Ltd.
--*/
/***************************************************************************
* Synopsis:
* This file would contain the following:
* 1. Flash routines.
**************************************************************************/
#include "windows.h"
#include "platform.h"
#if ((SH_PLATFORM == PLATFORM_ASPEN)||(SH_PLATFORM==PLATFORM_BIGSUR))
#define DEBUG_SERIAL_ON 1
#if (SH_PLATFORM == PLATFORM_ASPEN)
#define UNLOCK_FLASH() (*((unsigned long *)0xa4040000) |= 1)
#define LOCK_FLASH() (*((unsigned long *)0xa4040000) &= ~1)
#elif (SH_PLATFORM == PLATFORM_BIGSUR)
#define UNLOCK_FLASH() (*((unsigned char *)BIGSUR_SW1) |= BIGSUR_SW1_FLWREN)
#define LOCK_FLASH() (*((unsigned char *)BIGSUR_SW1) &= ~BIGSUR_SW1_FLWREN)
#endif (SH_PLATFORM == PLATFORM_ASPEN)
static unsigned UnErased = 0; // Last Address erased in Flash
// #define DEBUG_FLASH
/*****************************************************************************
* Function: FlashReadRst
* Input: Address
* Output: None
* Purpose: Reset the Flash back to normal state.
****************************************************************************/
void FlashReadRst(volatile unsigned *addr)
{
// UNLOCK_FLASH();
addr[0] = 0x50505050;
addr[1] = 0x50505050;
addr[0] = 0xffffffff;
addr[1] = 0xffffffff;
// LOCK_FLASH();
}
/****************************************************************************
* Function: OEMFlashWrite
* Input: ulAddress: Address in Flash to write to (Must be dword aligned)
* ulValue: Dword value to write.
* Output 0: success
* non-zero: failure
/***************************************************************************/
unsigned int OEMFlashWrite(unsigned int ulAddress, unsigned int ulValue)
{
volatile unsigned *addr;
// UNLOCK_FLASH();
/* Check whether the address to which you are about to write to has been
* erased or not. */
if( (ulAddress & 0x00FFFFFF) >= UnErased) {
OutputFormatString("ERROR: attempt to write to unerased flash. ulAddress = 0x%x, UnErased = 0x%x\r\n", ulAddress, UnErased);
EraseFlash(ulAddress);
}
#ifdef DEBUG_FLASH
OutputFormatString("OemFlashWrite: ulAddress=0x%X, ulValue=0x%X\r\n", ulAddress, ulValue);
#endif DEBUG_FLASH
if (ulAddress & 3) {
OutputFormatString("ERROR: attempting to write on not word boundary at %Xh\r\n",ulAddress);
OutputFormatString("Skipping write to Flash \r\n");
return 1;
}
addr = (unsigned *) (ulAddress | FLASH_START);
*addr = 0x40404040;
while( FLASH_READY != (FLASH_READY & *(addr)) ) ;
*addr = ulValue;
while( FLASH_READY != (FLASH_READY & *(addr)) ) ;
// FlashReadRst is required only when you want to readback from Flash
FlashReadRst(addr);
if (*addr != ulValue) {
OutputFormatString("Error: OEMFlashWrite: Wrote 0x%x, read back 0x%x at address 0x%x\r\n", ulValue, *addr, addr);
return(1);
}
return 0;
}
/****************************************************************************
* Function: GetUnalignedDword
* Input: addr: Address to fetch dword from
* Output 0: success
* non-zero: failure
/***************************************************************************/
unsigned GetUnalignedDword(unsigned char *addr)
{
unsigned val;
#ifdef DEBUG_FLASH
OutputFormatString("+GetUnalignedDword(addr=%X, val=%B%B%B%B)\r\n", addr, *addr, *(addr+1), *(addr+2), *(addr+3));
#endif DEBUG_FLASH
val = *addr | (*(addr+1) << 8) | (*(addr+2)<<16) | (*(addr+3)<<24);
#ifdef DEBUG_FLASH
OutputFormatString("-GetUnalignedDword returning %X\r\n", val);
#endif DEBUG_FLASH
return val;
}
/****************************************************************************
* Function: OEMFlashWriteByte
* Input: ulAddress: Address in Flash to write to
* ulValue: byte value to write.
* Output 0: success
* non-zero: failure
/***************************************************************************/
unsigned OEMFlashWriteByte(unsigned ulAddress, unsigned char val)
{
unsigned ulValue;
unsigned addr;
#ifdef DEBUG_FLASH
OutputFormatString("+OEMFlashWriteByte(ulAddress=%X, val=%B)\r\n", ulAddress, val);
#endif DEBUG_FLASH
addr = ulAddress & ~3;
ulValue = *(volatile unsigned *)addr;
switch(ulAddress & 3) {
case 0:
ulValue = (ulValue & 0xFFFFFF00) | val;
break;
case 1:
ulValue = (ulValue & 0xFFFF00FF) | (val << 8);
break;
case 2:
ulValue = (ulValue & 0xFF00FFFF) | (val << 16);
break;
case 3:
ulValue = (ulValue & 0x00FFFFFF) | (val << 32);
break;
}
return OEMFlashWrite(addr, ulValue);
}
/****************************************************************************
* Function: OEMFlashWriteBuffer
* Input : dst : Destination Address
* : src : Buffer address
* : length : Number of bytes
* Output : Don't care
* Synopsis: Writes a buffer to Flash. It takes care of writes to unaligned
* boundaries.
/***************************************************************************/
unsigned OEMFlashWriteBuffer(unsigned char *dst, unsigned char *src, unsigned int length)
{
unsigned val;
#ifdef DEBUG_FLASH
OutputFormatString("+OEMFlashWriteBuffer(dst=%X, src=%X, length=%d)\r\n", dst, src, length);
#endif DEBUG_FLASH
// Write all unaligned bytes at beginning of dst.
while((unsigned)dst % 4) {
OEMFlashWriteByte((unsigned)dst++, *src++);
length --;
}
// Now dst is dword aligned. src may not be dword aligned.
// Write all dword aligned bytes.
while(length >= 4) {
// Get a dword from src, it may be unaligned.
val = GetUnalignedDword(src);
OEMFlashWrite((unsigned)dst, val);
src += 4; dst += 4; length -= 4;
}
// Now write the rest of the bytes.
while(length --) {
OEMFlashWriteByte((unsigned)dst++, *src++);
}
return 0;
}
/****************************************************************************
* Function: OEMFlashWriteBegin
* Input : ulPhysStart : Start of image
* : ulPhysLen : Length of image
: 0: Erase all Flash, if it's a flash image
* Output : FL_ADDRESS_ERROR : image is not for Flash.
* 0 : Image is for Flash.
* Synopsis: Selects whether the image would go to RAM or Flash. Incase it
* is for Flash, erase the required amount of Flash.
/***************************************************************************/
unsigned int OEMFlashWriteBegin(unsigned int ulPhysStart, unsigned int ulPhysLen)
{
unsigned int i;
unsigned int ulPhysEnd;
unsigned int ulFlashStart,ulFlashEnd, ulCurBlock;
unsigned int ulStartBlock, ulNumBlocks;
volatile unsigned *addr;
#ifdef DEBUG
OutputFormatString("OEMFlashWriteBegin called with 0x%x, 0x%x\n", ulPhysStart, ulPhysLen);
#endif DEBUG
ulPhysEnd=ulPhysStart+ulPhysLen;
#if 0
ulPhysEnd|=0x20000000;
ulPhysStart|=0x20000000;
#endif
/* Get all the addresses in same area (P0) for comparisons.*/
ulPhysEnd &= 0x0fffffff;
ulPhysStart &= 0x0fffffff;
ulFlashStart = FLASH_START&0x0fffffff;
ulFlashEnd = FLASH_END&0x0fffffff;
/* If it is a Flash image, it must be linked to Address between 0x00000000
* and 0x04000000 */
if ( (ulPhysStart >= 0) && (ulPhysStart <= 0x04000000) )
{
#if 0
if(ulPhysLen == 0) {
// This is a Flash image of unknown length.
// Erase all Flash
ulStartBlock = 0;
ulNumBlocks = FLASH_SIZE / FLASH_BLOCK_SIZE;
// ulNumBlocks = 2; // Temporary FLASH_SIZE / FLASH_BLOCK_SIZE;
}
else
#endif 0
{
/* compute starting block number and number of blocks*/
ulStartBlock = ulPhysStart / FLASH_BLOCK_SIZE;
ulNumBlocks = ulPhysLen / FLASH_BLOCK_SIZE;
if (ulPhysLen % FLASH_BLOCK_SIZE)
ulNumBlocks++;
}
}
else
return 1;
#if (SH_PLATFORM == PLATFORM_BIGSUR)
// Check to see whether you are permitted to write to Flash. S1-3 should
// be on.
if( ! ( BIGSUR_SW1_FLASH_PROT_N & REG8(BIGSUR_SW1, 0) ) ) {
// Can't write to Flash buddy. Switch OFF SW1 first.
OutputFormatString("Can't write to Flash. Switch off S1-3 to enable Flash writing\r\n\n");
return -1;
}
WriteOutput("MISCSW switch set, SW1 = 0x%x...\r\n\n", REG8(BIGSUR_SW1, 0));
#endif (SH_PLATFORM == PLATFORM_BIGSUR)
/* Erase the FLASH blocks which are required.*/
OutputFormatString("Erasing %d blocks starting at block %d ... ",ulNumBlocks,ulStartBlock);
UNLOCK_FLASH();
for(ulCurBlock = 0; ulCurBlock < ulNumBlocks; ulCurBlock++) {
OutputFormatString(".");
/* Erase at ulCurBlock + ulStartBlock*/
/* Don't forget this step. This is because the FLASH is*/
/* mapped to a different address in CMON.*/
addr = (unsigned *) (((ulCurBlock + ulStartBlock) << SECTOR_SHIFT) | FLASH_START);
addr[0] = 0x20202020;
addr[1] = 0x20202020;
while( FLASH_READY != (FLASH_READY & addr[0]) ) ;
while( FLASH_READY != (FLASH_READY & addr[1]) ) ;
addr[0] = 0xd0d0d0d0;
addr[1] = 0xd0d0d0d0;
while( FLASH_READY != (FLASH_READY & addr[0]) ) ;
while( FLASH_READY != (FLASH_READY & addr[1]) ) ;
#if 0
addr[0] = 0x50505050;
addr[1] = 0x50505050;
while( FLASH_READY != (FLASH_READY & addr[0]) ) ;
while( FLASH_READY != (FLASH_READY & addr[1]) ) ;
#endif 0
}
FlashReadRst(addr);
addr = (unsigned *) (((ulCurBlock + ulStartBlock) << SECTOR_SHIFT) | FLASH_START);
UnErased = (unsigned)addr & 0x00FFFFFF;
OutputFormatString("done\r\n",ulNumBlocks,ulStartBlock);
// OutputFormatString("OEFWB: UnErased = 0x%x, addr = 0x%x, ulCurBlock=0x%x\r\n",UnErased, addr, ulCurBlock);
// Do not LOCK Flash after erasing, so that the user can write data
// to it.
// LOCK_FLASH();
return 0;
}
/****************************************************************************
// OEMFlashWriteEnd
//
//
//**************************************************************************/
unsigned int OEMFlashWriteEnd(void)
{
LOCK_FLASH();
return 0;
}
/***************************************************************************
* Function: OEMFlashWriteStatus
* Input: Address to check out.
* returns - 0 flash address not ready for write
* 1 flash address ready for write
***************************************************************************/
unsigned int OEMFlashWriteStatus(unsigned int ulAddress)
{
/* Return 1 always for the time being, since the other routines make
* Sure that the Flash is in the ready state. */
return 1;
}
/****************************************************************************
* Function: EraseFlash
* Input : ulAddress : Erase a sector of Flash at specified address
* Output : FL_ADDRESS_ERROR : image is not for Flash.
* 0 : Image is for Flash.
* Synopsis: Erase a sector of Flash
/***************************************************************************/
unsigned int EraseFlash(unsigned int ulAddress)
{
unsigned int i;
unsigned int ulPhysEnd;
unsigned int ulFlashStart,ulFlashEnd, ulCurBlock;
unsigned int ulStartBlock, ulNumBlocks;
volatile unsigned *addr;
// No error checking is done initially.
addr = (unsigned *) ( ulAddress | FLASH_START );
addr[0] = 0x20202020;
addr[1] = 0x20202020;
while( FLASH_READY != (FLASH_READY & addr[0]) ) ;
while( FLASH_READY != (FLASH_READY & addr[1]) ) ;
addr[0] = 0xd0d0d0d0;
addr[1] = 0xd0d0d0d0;
while( FLASH_READY != (FLASH_READY & addr[0]) ) ;
while( FLASH_READY != (FLASH_READY & addr[1]) ) ;
UnErased = ulAddress + (1 << SECTOR_SHIFT);
#ifdef FLASH_DEBUG
OutputFormatString("EraseFlash Address:%X, UnErased=%X\r\n", ulAddress, UnErased);
#endif FLASH_DEBUG
FlashReadRst(addr);
#ifdef DEBUG_FLASH
OutputFormatString("done\r\n",ulNumBlocks,ulStartBlock);
#endif DEBUG_FLASH
return 0;
}
#endif ((SH_PLATFORM == PLATFORM_ASPEN)||(SH_PLATFORM==PLATFORM_BIGSUR))
#ifdef JUNK
#if 0
if (ulAddress & 3) {
OutputFormatString("ERROR: attempting to write on not word boundary at %Xh\r\n",ulAddress);
/* Assume that it would be at least 16 bit aligned */
if(ulAddress & 1) {
OutputFormatString("Skipping write to Flash \r\n");
return 1;
}
if(ulAddress & 2) {
ulValue = (ulValue << 16) | (*(volatile unsigned short *) (ulAddress - 2) );
}
else {
ulValue = (ulValue) | ( (*(volatile unsigned short *) (ulAddress + 2) ) << 16);
}
ulAddress &= 0xfffffff4;
}
#endif 0
#endif JUNK
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -