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

📄 flash.c

📁 Embest EudKit-II教学系统配Samsung S3C44B0处理器的部分测试程序。
💻 C
字号:
/*********************************************************************************************
* File:	flash.c
* Author:	embest
* Desc:	AT49BV1614A & AM29LV160DB Flash program code
* History:	
*********************************************************************************************/
#include "flash.h"


#define OS_CRITICAL_METHOD	0
#define OS_CPU_SR			unsigned int
#define OS_ENTER_CRITICAL()
#define OS_EXIT_CRITICAL()


/*
 * Flash ID
 */
static unsigned short id_man, id_dev, id_ade;


/*
 * delay function
 */
static void Flash_Delay(void)
{
	volatile unsigned int i;
	/* delay about 70 us */
	for(i=0; i<231; i++);
}


/*
 * AT49BV1614A
 */
static void FlashID_AT49BV1614A(unsigned int base_addr)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
	base_addr &= ~AT49BV1614A_FLASH_MASK;

	OS_ENTER_CRITICAL();
	/* enter read ID mode */
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
	*(volatile unsigned short *)(base_addr + (0xAAA<<1)) = 0x55;
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0x90;
	/* read ID */
	id_man = *(volatile unsigned short *)(base_addr + (0x00<<1));
	id_dev = *(volatile unsigned short *)(base_addr + (0x01<<1));
	id_ade = *(volatile unsigned short *)(base_addr + (0x03<<1));
	/* exit read ID mode */
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
	*(volatile unsigned short *)(base_addr + (0xAAA<<1)) = 0x55;
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xF0;
	OS_EXIT_CRITICAL();
}


/*
 * AT49BV1614A
 */
static void FlashEraseSector_AT49BV1614A(unsigned int base_addr)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
	unsigned int i, sector_addr;

 	sector_addr = (base_addr & AT49BV1614A_FLASH_MASK);
	sector_addr >>= 1;
	sector_addr <<= 1;
	base_addr &= ~AT49BV1614A_FLASH_MASK;

	OS_ENTER_CRITICAL();
	/* enter erase sector mode */
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
	*(volatile unsigned short *)(base_addr + (0xAAA<<1)) = 0x55;
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0x80;
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
	*(volatile unsigned short *)(base_addr + (0xAAA<<1)) = 0x55;
	*(volatile unsigned short *)(base_addr + (sector_addr)) = 0x30;
	/* delay about 420 ms */
	for(i=0; i<6000; i++)
		Flash_Delay();
	OS_EXIT_CRITICAL();
}


/*
 * AT49BV1614A
 */
static void FlashProgram_AT49BV1614A(unsigned int base_addr, unsigned short *data_addr, unsigned int bytes)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
	unsigned int i, word_addr;

 	word_addr = (base_addr & AT49BV1614A_FLASH_MASK);
	base_addr &= ~AT49BV1614A_FLASH_MASK;

	if(bytes % 2)
		bytes += 1;
	bytes >>= 1;

	/* enter program mode */
	for(i=0; i<bytes; i++)
	{
		OS_ENTER_CRITICAL();
		*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
		*(volatile unsigned short *)(base_addr + (0xAAA<<1)) = 0x55;
		*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xA0;
		*(volatile unsigned short *)(base_addr + (word_addr)) = data_addr[i];
		/* delay 50 us */
		Flash_Delay();
		word_addr += sizeof(unsigned short);
		OS_EXIT_CRITICAL();
	}
}


static unsigned int FlashSectorSize_AT49BV1614A(unsigned int base_addr)
{
	unsigned int sector_addr = (base_addr & AT49BV1614A_FLASH_MASK);

	if(sector_addr >= 0x00 && sector_addr < 0x10000)
		return (8*1024);
	else if(sector_addr >= 0x10000 && sector_addr < 0x200000)
		return (64*1024);
	else
		return 0;
}


/*
 * AM29LV160B/DB
 */
static void FlashID_AM29LV160DB(unsigned int base_addr)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
	base_addr &= ~AM29LV160DB_FLASH_MASK;

	OS_ENTER_CRITICAL();
	/* enter read man_ID mode */
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
	*(volatile unsigned short *)(base_addr + (0x2AA<<1)) = 0x55;
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0x90;
	/* read man_ID */
	id_man = *(volatile unsigned short *)(base_addr + (0x00<<1));
	/* enter read dev_ID mode */
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
	*(volatile unsigned short *)(base_addr + (0x2AA<<1)) = 0x55;
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0x90;
	/* read dev_ID */
	id_dev = *(volatile unsigned short *)(base_addr + (0x01<<1));
	id_ade = AM29LV160DB_ADE_ID;
	OS_EXIT_CRITICAL();
}


/*
 * AM29LV160B/DB
 */
static void FlashEraseSector_AM29LV160DB(unsigned int base_addr)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
	unsigned int i, sector_addr;

 	sector_addr = (base_addr & AM29LV160DB_FLASH_MASK);
	sector_addr >>= 1;
	sector_addr <<= 1;
	base_addr &= ~AM29LV160DB_FLASH_MASK;

	OS_ENTER_CRITICAL();
	/* enter erase sector mode */
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
	*(volatile unsigned short *)(base_addr + (0x2AA<<1)) = 0x55;
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0x80;
	*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
	*(volatile unsigned short *)(base_addr + (0x2AA<<1)) = 0x55;
	*(volatile unsigned short *)(base_addr + (sector_addr)) = 0x30;
	/* delay about 700 ms */
	for(i=0; i<10000; i++)
		Flash_Delay();
	OS_EXIT_CRITICAL();
}


/*
 * AM29LV160B/DB
 */
static void FlashProgram_AM29LV160DB(unsigned int base_addr, unsigned short *data_addr, unsigned int bytes)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr;
#endif
	unsigned int i, word_addr;

 	word_addr = (base_addr & AM29LV160DB_FLASH_MASK);
	base_addr &= ~AM29LV160DB_FLASH_MASK;

	if(bytes % 2)
		bytes += 1;
	bytes >>= 1;

	/* enter programe mode */
	for(i=0; i<bytes; i++)
	{
		OS_ENTER_CRITICAL();
		*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xAA;
		*(volatile unsigned short *)(base_addr + (0x2AA<<1)) = 0x55;
		*(volatile unsigned short *)(base_addr + (0x555<<1)) = 0xA0;
		*(volatile unsigned short *)(base_addr + (word_addr)) = data_addr[i];
		/* delay 50 us */
		Flash_Delay();
		word_addr += sizeof(unsigned short);
		OS_EXIT_CRITICAL();
	}
}


static unsigned int FlashSectorSize_AM29LV160DB(unsigned int base_addr)
{
	unsigned int sector_addr = (base_addr & AM29LV160DB_FLASH_MASK);

	if(sector_addr >= 0x00 && sector_addr < 0x4000)
		return (16*1024);
	else if(sector_addr >= 0x4000 && sector_addr < 0x6000)
		return (8*1024);
	else if(sector_addr >= 0x6000 && sector_addr < 0x8000)
		return (8*1024);
	else if(sector_addr >= 0x8000 && sector_addr < 0x10000)
		return (32*1024);
	else if(sector_addr >= 0x10000 && sector_addr < 0x200000)
		return (64*1024);
	else
		return 0;
}


/*
 * Flash ID
 */
int FlashID(unsigned int base_addr)
{
	/* read AT49BV1614A flash ID */
	FlashID_AT49BV1614A(base_addr);

	if(	id_man == AT49BV1614A_MAN_ID &&
		id_dev == AT49BV1614A_DEV_ID &&
		id_ade == AT49BV1614A_ADE_ID )
	{
		return 1;
	}

	/* read AM29LV160B/DB flash ID */
	FlashID_AM29LV160DB(base_addr);
	if(	id_man == AM29LV160DB_MAN_ID &&
		id_dev == AM29LV160DB_DEV_ID &&
		id_ade == AM29LV160DB_ADE_ID )
	{
		return 1;
	}

	return 0;
}


/*
 * Erase Sector
 */
void FlashEraseSector(unsigned int base_addr)
{
	/* AT49BV1614A */
	if(	id_man == AT49BV1614A_MAN_ID &&
		id_dev == AT49BV1614A_DEV_ID &&
		id_ade == AT49BV1614A_ADE_ID )
	{
		FlashEraseSector_AT49BV1614A(base_addr);
	}

	/* AM29LV160B/DB */
	else if(id_man == AM29LV160DB_MAN_ID &&
		id_dev == AM29LV160DB_DEV_ID &&
		id_ade == AM29LV160DB_ADE_ID )
	{
		FlashEraseSector_AM29LV160DB(base_addr);
	}
}


/*
 * Program Flash
 */
void FlashProgram(unsigned int base_addr, unsigned short *data_addr, unsigned int bytes)
{
	/* AT49BV1614A */
	if(	id_man == AT49BV1614A_MAN_ID &&
		id_dev == AT49BV1614A_DEV_ID &&
		id_ade == AT49BV1614A_ADE_ID )
	{
		FlashProgram_AT49BV1614A(base_addr, data_addr, bytes);
	}

	/* AM29LV160B/DB */
	else if(id_man == AM29LV160DB_MAN_ID &&
		id_dev == AM29LV160DB_DEV_ID &&
		id_ade == AM29LV160DB_ADE_ID )
	{
		FlashProgram_AM29LV160DB(base_addr, data_addr, bytes);
	}
}


/*
 * Flash sector's size
 */
unsigned int FlashSectorSize(unsigned int base_addr)
{
	unsigned int size = 0;
	
	/* AT49BV1614A */
	if(	id_man == AT49BV1614A_MAN_ID &&
		id_dev == AT49BV1614A_DEV_ID &&
		id_ade == AT49BV1614A_ADE_ID )
	{
		size = FlashSectorSize_AT49BV1614A(base_addr);
	}

	/* AM29LV160B/DB */
	else if(id_man == AM29LV160DB_MAN_ID &&
		id_dev == AM29LV160DB_DEV_ID &&
		id_ade == AM29LV160DB_ADE_ID )
	{
		size = FlashSectorSize_AM29LV160DB(base_addr);
	}

	return size;
}


/*
 * Flash sector's backup
 */
unsigned int FlashSectorBackup(unsigned int base_addr, unsigned char *buf)
{
	unsigned int size;

	size = FlashSectorSize(base_addr);

	if(size > 0)
	{
		unsigned int i;
		unsigned char *ptr;

		ptr = (unsigned char *)(base_addr & (0 - size));
		for(i=0; i<size; i++)
			buf[i] = *ptr++;
	}

	return size;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -