📄 drv_flash.c
字号:
/*********************************************************************** * MODULE: drv_flash.c * Description: Flash Driver * Runtime Env: ARM * Company: * Change History: * 03-28-02 Create (Yadong Wang) ***********************************************************************/#include <stdio.h>
#include "common_types.h"
#include "samsung4510.h"
#include "main.h"
#define MAX_SECT_NUM 40
typedef struct
{
// Chips Info
tU32 BaseAddr; // Base Address
tU32 NumOfSec;
tU32 SectAddr[MAX_SECT_NUM];
tU32 SectSize[MAX_SECT_NUM];
tU16 DevID;
tU16 BusWidth;
} FLASH_INFO;
FLASH_INFO FlashInfo;
#define AMD_FLASH_WRITE_SETUP 0x01
#define AMD_FLASH_WRITE_RESET 0x02
#define AMD_FLASH_ERASE_CMD 0x03
#define AMD_FLASH_ERASE_RESET 0x04
#define AMD_FLASH_LOCK 0x05
static tU16 DrvFlashInit(tU16 DevID, tU32 DestAddr);
static tU16 DrvFlashErase(tU32 Addr0, tU32 Size);
static tU16 DrvFlashWrite(tU32 src, tU32 StartAddr, tU32 Size);
static tU32 DrvFlashIoCtl(UINT32 cmd, UINT32 Data);
static tU16 DrvFlashPoll(void *Addr, tU16 Data, tU32 delay);
static tU16 Addr2Sector(tU32 Addr);
tU16 AppFlashWrite(tU8 DevId, tU32 SrcAddr, tU32 DestAddr, tU32 Size)
{
// Check ID
if (DevId != 0 && DevId != 1)
{
Print("ERROR: Invalid Flash ID\n");
return 1;
}
// Init the Flash Driver
if (DrvFlashInit(DevId, DestAddr))
{
Print("ERROR: Flash Driver Init.\n");
return 1;
}
// Erase
if (DrvFlashErase(DestAddr, Size))
{
Print("ERROR: Flash Erase.\n");
return 1;
}
// Write
if (DrvFlashWrite(SrcAddr, DestAddr, Size))
{
Print("ERROR: Flash Write.\n");
return 1;
}
return 0;
}
/***********************************************************************
* DevFlashInit
***********************************************************************/
static tU16 DrvFlashInit(tU16 DevID, tU32 DestAddr)
{
tU16 i;
if (DestAddr >= 0x2000000)
FlashInfo.BaseAddr = 0x2000000;
else if (DestAddr >= 0x1000000)
FlashInfo.BaseAddr = 0x1000000;
else
return 1;
FlashInfo.DevID = DevID;
if (DevID == 0)
{
FlashInfo.NumOfSec = 8;
for(i=0; i<FlashInfo.NumOfSec; i++)
{
FlashInfo.SectAddr[i] = FlashInfo.BaseAddr+i*0x10000;
FlashInfo.SectSize[i] = 64 * 1024;
}
FlashInfo.BusWidth = 8;
}
else
{
FlashInfo.NumOfSec = 35;
for(i=0; i<FlashInfo.NumOfSec; i++)
{
// Address and size info
switch (i)
{
case 0:
FlashInfo.SectAddr[i] = FlashInfo.BaseAddr+0x00000;
FlashInfo.SectSize[i] = 16 * 1024;
break;
case 1:
FlashInfo.SectAddr[i] = FlashInfo.BaseAddr+0x04000;
FlashInfo.SectSize[i] = 8 * 1024;
break;
case 2:
FlashInfo.SectAddr[i] = FlashInfo.BaseAddr+0x06000;
FlashInfo.SectSize[i] = 8 * 1024;
break;
case 3:
FlashInfo.SectAddr[i] = FlashInfo.BaseAddr+0x08000;
FlashInfo.SectSize[i] = 32 * 1024;
break;
default:
FlashInfo.SectAddr[i] = FlashInfo.BaseAddr+(i-4)*0x10000 + 0x10000;
FlashInfo.SectSize[i] = 64 * 1024;
break;
}
}
FlashInfo.BusWidth = 8;
}
return 0;
}
/***********************************************************************
* DevFlashWrite
***********************************************************************/
tU16 DrvFlashWrite(tU32 SrcAddr, tU32 DestAddr, tU32 Size)
{
tU16 error = 0, i;
tU32 data[2], n;
tS8 s[100];
// Write Setup
data[0] = DestAddr;
data[1] = DestAddr + Size - 1;
error = DrvFlashIoCtl(AMD_FLASH_WRITE_SETUP, 0);
if(error)
{
sprintf(s, "ERROR: AMD_FLASH_WRITE_SETUP (%04x)\n", error);
Print(s);
return error;
}
// Write the Data to Flash
if (FlashInfo.BusWidth == 8)
{
tREG8 *bp, *bps;
if (SYSCFG & 0x00000002)
{
bp = (tREG8 *) (DestAddr + 0x4000000);
bps = (tREG8 *) (SrcAddr + 0x4000000);
}
else
{
bp = (tREG8 *) DestAddr;
bps = (tREG8 *) SrcAddr;
}
for(n=0; n < Size && !error; n++, bp++, bps++)
{
// Display Message
if (n && (n % 0xFFFF==0))
{
sprintf(s, "Write %7lu Bytes of %7lu Bytes\n", n, Size);
Print(s);
}
// skip the 0xFFFF pattern
if(*bps == 0xff)
continue;
// write the flash command for flash memory
*bp = 0xA0;
// Write the data
*bp = *bps;
// Check if the write is done
for(i=0; i<0xff; i++);
error = DrvFlashPoll((void*)bp, *bps, 0);
if (error)
{
sprintf(s, "ERROR: Write Polling loop (%04x)\n", error);
Print(s);
break;
}
}
}
else
{
tREG16 *wp, *wps;
wp = (volatile tU16 *) DestAddr;
wps = (volatile tU16 *) SrcAddr;
for(n=0; n < Size && !error; n+=2, wp++, wps++)
{
// Display Message
if (n && (n % 0xFFFF==0))
{
sprintf(s, "Write %7lu Bytes of %7lu Bytes\n", n, Size);
Print(s);
}
// skip the 0xFFFF pattern
if(*wps == 0xffff)
continue;
// write the flash command for flash memory
*wp = 0x00A0;
// Write the data
*wp = *wps;
// Check if the write is done
for(i=0; i<0xff; i++);
error = DrvFlashPoll((void*)wp, *wps, 0);
}
}
if (!error)
{
sprintf(s, "Write %7lu Bytes of %7lu Bytes\n", Size, Size);
Print(s);
}
// Reset the Flash Mode to read
error = DrvFlashIoCtl(AMD_FLASH_WRITE_RESET, 0);
if(error)
{
sprintf(s, "ERROR: AMD_FLASH_WRITE_RESET (%04x)\n", error);
Print(s);
}
Print("Flash Done!\n");
return error;
}
/***********************************************************************
* DevFlashErase
***********************************************************************/
static tU16 DrvFlashErase(tU32 Addr0, tU32 Size)
{
tU32 Addr1 = Addr0 + Size-1;
tU16 error = 0, i;
tU8 Blk0, Blkn;
char s[80];
// Get the Sector info
Blk0 = Addr2Sector(Addr0);
Blkn = Addr2Sector(Addr1);
// Erase, ...
if (Blkn < FlashInfo.NumOfSec && Blk0 <= Blkn)
{
// Send the command to the Flash
sprintf(s, "Erase Flash #%u Sectors [%2d - %2d] ...\n", FlashInfo.DevID, Blk0, Blkn);
Print(s);
for(i=Blk0; i<=Blkn && !error; i++)
{
if (SYSCFG & 0x00000002)
{
DrvFlashIoCtl(AMD_FLASH_ERASE_CMD, FlashInfo.SectAddr[i]+0x4000000);
error = DrvFlashPoll((void *)(FlashInfo.SectAddr[i]+0x4000000), 0xFFFF, 10000);
}
else
{
DrvFlashIoCtl(AMD_FLASH_ERASE_CMD, FlashInfo.SectAddr[i]);
error = DrvFlashPoll((void *)FlashInfo.SectAddr[i], 0xFFFF, 10000);
}
if(error)
{
sprintf(s, "ERROR: Erase Polling loop (%04x)\n", error);
Print(s);
break;
}
else
{
sprintf(s, "Erase Sector %2d at address %08lx done\n", i, FlashInfo.SectAddr[i]);
Print(s);
}
}
}
else
error = 0x4000;
return error;
}
/***********************************************************************
* DevFlashPoll
***********************************************************************/
static tU16 DrvFlashPoll(void *Addr, tU16 Data, tU32 delay)
{
tU32 i;
tU16 error = 0, FlashData;
if (FlashInfo.BusWidth == 8)
{
tREG8 *FlashPtr;
tU8 DQ7 = 0x80, DQ5 = 0x20;
FlashPtr = (tREG8*)Addr;
Data = Data & 0xFF;
for(i=0; i<20000; i++)
{
// Read the Data
FlashData = *FlashPtr;
// DQ7 = Data?
if ((FlashData & DQ7) == (Data & DQ7))
break;
// Check Timeout (DQ5==1)
if(FlashData & DQ5)
{
// Read the Data
FlashData = *FlashPtr;
// DQ7 = Data?
if (!((FlashData & DQ7) == (Data & DQ7)))
error = 1;
break;
}
Delay(delay);
}
// Check the data
if (!error)
{
// Read the Data
FlashData = *FlashPtr;
if (FlashData != Data)
error = 2;
}
}
else
{
tU16 *FlashPtr, DQ7 = 0x8080, DQ5 = 0x2020;
FlashPtr = (tU16*)Addr;
for(i=0; i<20000; i++)
{
// Read the Data
FlashData = *FlashPtr;
// DQ7 = Data?
if ((FlashData & DQ7) == (Data & DQ7))
break;
// Check Timeout (DQ5==1)
if(FlashData & DQ5)
{
// Read the Data
FlashData = *FlashPtr;
// DQ7 = Data?
if (!((FlashData & DQ7) == (Data & DQ7)))
error = 1;
break;
}
Delay(delay);
}
// Check the data
if (!error)
{
// Read the Data
FlashData = *FlashPtr;
if (FlashData != Data)
error = 2;
}
}
// error update
if (i==20000)
error = 3;
return error;
}
/***********************************************************************
* Dev IO Commands
***********************************************************************/
static tU32 DrvFlashIoCtl(UINT32 cmd, UINT32 Data)
{
tU32 BaseAddr = FlashInfo.BaseAddr;
tU16 error = 0;
if (SYSCFG & 0x00000002)
BaseAddr += 0x4000000;
switch(cmd)
{
case AMD_FLASH_WRITE_SETUP:
if (FlashInfo.DevID == 0)
{
*((volatile tU8 *)(BaseAddr+0x555)) = 0xAA;
*((volatile tU8 *)(BaseAddr+0x2aa)) = 0x55;
*((volatile tU8 *)(BaseAddr+0x555)) = 0x20;
}
else
{
if (FlashInfo.BusWidth == 8)
{
*((volatile tU8 *)(BaseAddr+0xAAA)) = 0xAA;
*((volatile tU8 *)(BaseAddr+0x555)) = 0x55;
*((volatile tU8 *)(BaseAddr+0xAAA)) = 0x20;
}
else
{
*((volatile tU16 *)(BaseAddr+0x555*2)) = 0x00AA;
*((volatile tU16 *)(BaseAddr+0x2AA*2)) = 0x0055;
*((volatile tU16 *)(BaseAddr+0x555*2)) = 0x0020;
}
}
break;
case AMD_FLASH_WRITE_RESET:
if (FlashInfo.BusWidth == 8)
{
*((volatile tU8 *)(BaseAddr)) = 0x90;
*((volatile tU8 *)(BaseAddr)) = 0x00;
}
else
{
*((volatile tU16 *)(BaseAddr)) = 0x0090;
*((volatile tU16 *)(BaseAddr)) = 0x0000;
}
break;
case AMD_FLASH_ERASE_CMD:
if (FlashInfo.DevID == 0)
{
*((volatile tU8 *)(BaseAddr+0x555)) = 0xAA;
*((volatile tU8 *)(BaseAddr+0x2aa)) = 0x55;
*((volatile tU8 *)(BaseAddr+0x555)) = 0x80;
*((volatile tU8 *)(BaseAddr+0x555)) = 0xAA;
*((volatile tU8 *)(BaseAddr+0x2aa)) = 0x55;
*((volatile tU8 *)(Data)) = 0x30;
}
else
{
if (FlashInfo.BusWidth == 8)
{
*((volatile tU8 *)(BaseAddr+0xAAA)) = 0xAA;
*((volatile tU8 *)(BaseAddr+0x555)) = 0x55;
*((volatile tU8 *)(BaseAddr+0xAAA)) = 0x80;
*((volatile tU8 *)(BaseAddr+0xAAA)) = 0xAA;
*((volatile tU8 *)(BaseAddr+0x555)) = 0x55;
*((volatile tU8 *)(Data)) = 0x30;
}
else
{
*((volatile tU16 *)(BaseAddr+0x555*2)) = 0x00AA;
*((volatile tU16 *)(BaseAddr+0x2AA*2)) = 0x0055;
*((volatile tU16 *)(BaseAddr+0x555*2)) = 0x0080;
*((volatile tU16 *)(BaseAddr+0x555*2)) = 0x00AA;
*((volatile tU16 *)(BaseAddr+0x2AA*2)) = 0x0055;
*((volatile tU16 *)(Data)) = 0x0030;
}
}
break;
case AMD_FLASH_ERASE_RESET:
if (FlashInfo.BusWidth == 8)
*((volatile tU8 *)(BaseAddr)) = 0xF0;
else
*((volatile tU16 *)(BaseAddr)) = 0x00F0;
break;
case AMD_FLASH_LOCK:
default:
break;
}
return error;
}
static tU16 Addr2Sector(tU32 Addr)
{
tU16 i;
for (i=0; i<FlashInfo.NumOfSec; i++)
{
if (Addr >= FlashInfo.SectAddr[i] &&
Addr <= (FlashInfo.SectAddr[i]+FlashInfo.SectSize[i]-1))
break;
}
if (i != FlashInfo.NumOfSec)
return i;
else
return 0xFFFF;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -