📄 flashwriternor.c
字号:
// Notes:
// Callable from C. Registers r0-r3 are *not* preserved.
//
///////////////////////////////////////////////////////////////////////////////
void AMD_Soft_Reset_Flash(ULONG addr)
{
// Reset Flash to be in Read Array Mode
*((vHwdptr) addr) = AMD_DEVICE_RESET;
// return to caller
}
///////////////////////////////////////////////////////////////////////////////
//
// AMD Flash Erase Block
//
// Description:
// This routine erases the AMD Page specified by the input parameter
// address. This routine is common for both the AM29LV017B device and
// the AM29DL800B device.
//
// Arguments:
// address - address in chip select to be erased
//
// Assumptions:
// The AM29LV017B device won't become confused when the addresses required
// by the AM29DL800B are used.
//
///////////////////////////////////////////////////////////////////////////////
void AMD_Flash_Erase_Block(ULONG blockaddress)
{
volatile USHORT *address_cs;
ULONG tmp_ptr;
tmp_ptr = (ULONG) blockaddress;
address_cs = (USHORT *) (tmp_ptr & AMD_ADDRESS_CS_MASK);
*(address_cs + AMD_CMD0_ADDR) = AMD_ERASE_BLK_CMD0;
*(address_cs + AMD_CMD1_ADDR) = AMD_ERASE_BLK_CMD1;
*(address_cs + AMD_CMD2_ADDR) = AMD_ERASE_BLK_CMD2;
*(address_cs + AMD_CMD0_ADDR) = AMD_ERASE_BLK_CMD3;
*(address_cs + AMD_CMD1_ADDR) = AMD_ERASE_BLK_CMD4;
*((vHwdptr) blockaddress) = AMD_ERASE_BLK_CMD5;
while (*((vHwdptr)blockaddress) != AMD_ERASE_DONE);
}
///////////////////////////////////////////////////////////////////////////////
//
// AMD Flash Erase All
//
// Description:
// This routine erases the entire AMD Chip.
// This routine is common for both the AM29LV017B device and
// the AM29DL800B device.
//
// Arguments:
// address - chip select address to be erased
//
// Assumptions:
// The AM29LV017B device won't become confused when the addresses required
// by the AM29DL800B are used.
//
///////////////////////////////////////////////////////////////////////////////
void AMD_Flash_Erase_All(ULONG address)
{
volatile USHORT *psAddress;
volatile USHORT *address_cs;
ULONG tmp_ptr;
USHORT tmp;
psAddress = (USHORT *)address;
tmp_ptr = (ULONG) address;
address_cs = (USHORT *) (tmp_ptr & AMD_ADDRESS_CS_MASK);
*(address_cs + AMD_CMD0_ADDR) = AMD_ERASE_CMD0;
*(address_cs + AMD_CMD1_ADDR) = AMD_ERASE_CMD1;
*(address_cs + AMD_CMD2_ADDR) = AMD_ERASE_CMD2;
*(address_cs + AMD_CMD0_ADDR) = AMD_ERASE_CMD3;
*(address_cs + AMD_CMD1_ADDR) = AMD_ERASE_CMD4;
*(address_cs + AMD_CMD2_ADDR) = AMD_ERASE_CMD5;
while (1)
{
tmp = *psAddress;
if(tmp & BIT7)
{
break;
} else
{
if(tmp & BIT5) // Exceeded Time Limit
{
tmp = *psAddress;
if(tmp & BIT7)
{
break;
} else
{
AMD_Soft_Reset_Flash((ULONG) psAddress);
}
}
}
}
}
///////////////////////////////////////////////////////////////////////////////
//
// AMD Flash Write
//
// Description:
// This routine writes data to flash memory starting at the specified
// parameter address.
//
// Arguments:
// plAddress - address to be erased
// ulData - data to be written
///////////////////////////////////////////////////////////////////////////////
int AMD_Flash_Write( ULONG *plAddress, USHORT ulData )
{
volatile USHORT *psAddress;
volatile USHORT *address_cs;
USHORT tmp;
ULONG tmp_ptr;
// Lower WORD.
psAddress = (USHORT *)plAddress;
tmp_ptr = (ULONG) plAddress;
address_cs = (USHORT *) (tmp_ptr & AMD_ADDRESS_CS_MASK);
*((vHwdptr)address_cs + AMD_CMD0_ADDR) = AMD_PROG_CMD0;
*((vHwdptr)address_cs + AMD_CMD1_ADDR) = AMD_PROG_CMD1;
*((vHwdptr)address_cs + AMD_CMD2_ADDR) = AMD_PROG_CMD2;
*psAddress = ulData;
// Wait for ready.
while (1)
{
tmp = *psAddress;
if( (tmp & BIT7) == (ulData & BIT7))
{
break;
}
else
{
if(tmp & BIT5) // Exceeded Time Limit
{
tmp = *psAddress;
if( (tmp & BIT7) == (ulData & BIT7))
{
break;
}
else
{
AMD_Soft_Reset_Flash((ULONG) psAddress);
return 1;
}
}
}
}
// Return Read Mode
AMD_Soft_Reset_Flash((ULONG) psAddress);
// Verify the data.
if (*psAddress != ulData)
{
return 1;
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////
//
// AMD Flash Optimized Write
//
// Description:
// This routine writes an array of data to flash memory starting beginning
// at the specified parameter address.
//
// Arguments:
// plAddress - address to begin writing
// ulData[] - data array to be written
// length - length of data array
//
// Return:
// int - 0 Success
// - 1 Fail
//
///////////////////////////////////////////////////////////////////////////////
int AMD_Flash_Optimized_Write(ULONG *plAddress, USHORT ulData[], ULONG ullength )
{
volatile USHORT *psAddress; //
volatile USHORT *address_cs; //
volatile USHORT *psBlockAddress;
volatile USHORT *psPollingAddress; //
USHORT usPollingData; //
USHORT tmp; //
ULONG tmp_ptr;
USHORT i;
// Adjust the timings for Writes
tmp_ptr = (ULONG) plAddress;
psAddress = (USHORT *)plAddress;
address_cs = (USHORT *) (tmp_ptr & AMD_ADDRESS_CS_MASK);
// Block Address WORD.
psBlockAddress = (USHORT *)(tmp_ptr &= 0xFFFF0000); // 64KB Sectors
// Write the Write Buffer Load command
*((vHwdptr)address_cs + AMD_CMD0_ADDR) = AMD_WRT_BUF_LOAD_CMD0;
*((vHwdptr)address_cs + AMD_CMD1_ADDR) = AMD_WRT_BUF_LOAD_CMD1;
*((vHwdptr)address_cs + AMD_CMD2_ADDR) = AMD_WRT_BUF_LOAD_CMD2;
// Write Length
*psBlockAddress = (USHORT) (ullength-1);
// Write Data
for(i=0; i<ullength; i++)
{
*psAddress = ulData[i];
usPollingData = ulData[i]; // store polling data
psPollingAddress = psAddress; // store polling address
psAddress++;
}
// Program Buffer to Flash Confirm Write
*psBlockAddress = AMD_WRT_BUF_CONF_CMD0;
psAddress = psPollingAddress; // set polling address to last loaded location
// (minimizes edits to "borrowed" polling routine)s
// Wait for ready.
while (1)
{
tmp = *psAddress;
if((tmp & BIT7) == (usPollingData & BIT7))
{
break;
} else
{
if(tmp & BIT5) // Exceeded Time Limit
{
tmp = *psAddress;
if( (tmp & BIT7) == (usPollingData & BIT7))
{
break;
} else
{
AMD_Soft_Reset_Flash((ULONG) psAddress);
return 1;
}
}
if(tmp & BIT1) // Write Buffer Loaded Incorrectly
{
tmp = *psAddress;
if( (tmp & BIT7) == (usPollingData & BIT7))
{
break;
} else
{
AMD_Write_Buf_Abort_Reset_Flash ((ULONG) psAddress);
return 1;
}
}
}
}
// Put chip back into read array mode.
AMD_Soft_Reset_Flash((ULONG) psBlockAddress);
// Verify Written Data
psAddress = (USHORT *)plAddress;
for(i=0; i<ullength; i++)
{
if(*psAddress != ulData[i])
{
return 1;
}
psAddress++;
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////
//
// AMD Write Buf Abort Reset Flash
//
// Description:
// Resets the flash device when in a write buffer abort state.
//
// C Syntax:
// void AMD_Soft_Reset_Flash(ULONG addr);
//
// Arguments:
// r0: Any valid address in a flash memory sector.
//
// Notes:
// Callable from C. Registers r0-r3 are *not* preserved.
//
///////////////////////////////////////////////////////////////////////////////
void AMD_Write_Buf_Abort_Reset_Flash( ULONG plAddress )
{
volatile USHORT *address_cs;
ULONG tmp_ptr;
// Lower WORD.
tmp_ptr = (ULONG) plAddress;
address_cs = (USHORT *) (tmp_ptr & AMD_ADDRESS_CS_MASK);
// Reset Flash to be in Read Array Mode
*((vHwdptr)address_cs + AMD_CMD0_ADDR) = AMD_WRT_BUF_ABORT_RESET_CMD0;
*((vHwdptr)address_cs + AMD_CMD1_ADDR) = AMD_WRT_BUF_ABORT_RESET_CMD1;
*((vHwdptr)address_cs + AMD_CMD2_ADDR) = AMD_WRT_BUF_ABORT_RESET_CMD2;
// return to caller
return;
}
///////////////////////////////////////////////////////////////////////////////
//
// Enable Flash Write Protection
//
// Description:
// Wiggles the EMIFS WP# signal high to write to Flash devices
// Control for older EVM's and TEB's also included
///////////////////////////////////////////////////////////////////////////////
void Enable_Flash_WP(void)
{
ULONG nMIFConfReg;
ULONG volatile *pMIFConfReg = (ULONG volatile *) MIF_CONFIG_REG;
// Enable write protection in the Memory Interface, bit 0 low.
nMIFConfReg = *pMIFConfReg;
nMIFConfReg &= 0xFFFFFFFE;
*pMIFConfReg = nMIFConfReg;
return;
}
///////////////////////////////////////////////////////////////////////////////
//
// Disable Flash Write Protection
//
///////////////////////////////////////////////////////////////////////////////
void Disable_Flash_WP(void)
{
ULONG nMIFConfReg;
ULONG volatile *pMIFConfReg = (ULONG volatile *) MIF_CONFIG_REG;
// Disable write protection in FPGA, bit 2 high.
#if (TICFG_PROC_VER!=HELENDC_V1) // HelenDC
#ifdef TICFG_EVM_PRESENT
unsigned char volatile *pDIPSwitchReg = (unsigned char volatile *) FPGA_DIP_SWITCH_REG;
unsigned char nDIPSwitchReg;
nDIPSwitchReg = *pDIPSwitchReg;
nDIPSwitchReg |= 0x04;
*pDIPSwitchReg = nDIPSwitchReg;
#endif
#endif
// Disable write protection in TC, bit 0 high.
nMIFConfReg = *pMIFConfReg;
nMIFConfReg |= 0x00000001;
*pMIFConfReg = nMIFConfReg;
return;
}
///////////////////////////////////////////////////////////////////////////////
//
// DownloadToNORFlash
//
// Description:
// Copies RAM Memory region to Flash region
//
// Arguments:
// ULONG *startWriteAddress - Base address of the data to be copied
// USHORT *startReadAddress - Base address of the destination address
// ULONG size - Number of bytes to copy
//
// Return:
// Flash Programming Status
//
// Assumptions:
// Flash addresses are always on a halfword boundary, and the byte count
// is always even.
//
///////////////////////////////////////////////////////////////////////////////
void DownloadToNORFlash(ULONG startWriteAddress, //R0 Intel Strata Address
ULONG startReadAddress, //R1 SDRAM Address
ULONG size, //R2
ULONG statusAddress, //R3 status address
enum NORFlashType flash_id)
{
ULONG flash_addr;
long SizeInBytes;
ULONG sdram_src;
USHORT flash_data;
USHORT opt_array[16]; //For buffered writes to specific devices
ULONG i;
SizeInBytes = size;
flash_addr = startWriteAddress;
sdram_src = startReadAddress;
//Print what flash type was found
// Disable flash write protection
Disable_Flash_WP();
// Erase the flash where the image will sit
EraseNORFlash(flash_addr, SizeInBytes, flash_id);
//Write to the Flash in this loop
printf("Writing the Flash\n");
while (SizeInBytes > 0)
{
if((User_Flash_Optimized_Write ==
(int (*)(ULONG *, USHORT[], ULONG)) Flash_Do_Nothing)
|| (SizeInBytes < 32) || (flash_addr%32))
{
flash_data = *((USHORT *) sdram_src);
(*User_Flash_Write)((ULONG *) flash_addr, flash_data);
SizeInBytes -= 2;
flash_addr += 2;
sdram_src += 2;
}
else
{
for(i = 0; i<16; i++) // <- *** INTEL Specific
{
opt_array[i] = *((USHORT *) sdram_src);
sdram_src += 2;
}
(*User_Flash_Optimized_Write)((ULONG *)flash_addr, opt_array, i);
SizeInBytes -= (i*2);
flash_addr += (i*2);
}
if ((flash_addr & 0xFFFC0000) == flash_addr)
{
printf("Flashed 0x%08X bytes of 0x%08X total bytes\n", (flash_addr - startWriteAddress), size);
}
}
// Enable flash write protection
Enable_Flash_WP();
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
//Main
//
// Purpose:
// Generates some messaging about the tool, Detects Flash devices, Detects OMAP device,
/////////////////////////////////////////////////////////////////////////////////////////////////
ULONG main(void)
{
ULONG flash_base_addr = (gp_vars->WriteAddress & 0xFFC00000); // Round to 4MB Boundaries
enum NORFlashType nor_flash_id;
//point REad Address at whereever the image section is mapped into
gp_vars->ReadAddress = (ULONG) ℑ
printinfo(gp_vars->Size, gp_vars->ReadAddress, gp_vars->WriteAddress);
//Try to ID as a NOR Flash first, then a NAND if a NOR can't be found at our address
nor_flash_id = IdentifyNORFlash(flash_base_addr);
if(nor_flash_id == FLASH_NOT_FOUND) //Try to find a NAND Flash
{
printf("No Flash devices have been found\n");
} else //Found a NOR device
{
printNORflashtype(nor_flash_id);
DownloadToNORFlash(gp_vars->WriteAddress,
gp_vars->ReadAddress,
gp_vars->Size,
(ULONG) gp_vars,
nor_flash_id);
printf("Flash writing completed!\n");
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -