⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drv_flash.c

📁 S3C4510B的例程
💻 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 + -