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

📄 flash_amd29lv800.c

📁 ALTERA的NIOS处理器!文件直接可以打开直接选择器件重新编译!
💻 C
字号:
/*
	file: flash_AMD29LV800.c

	contents: implementation of flash routines
	          for the AMD part.

        author: Aaron Ferrucci
*/


#include "nios.h"

// ---------------------------------------------
// Private Routines

// Wait for the given address to contain 0xFFFF.
// Return value: 1 on success, 0 on timeout failure.

static int await_erase_complete(int entire_chip, volatile unsigned short *addr)
	{
	int iTimeout = 20;

	// The "typical" time for an erase command is 0.7 seconds.
	// Empirically (as expected), it takes longer to erase the entire
	// chip than a single sector.	Give a generous timeout for a single
	// sector, and even more for the entire chip.

	if (entire_chip)
		iTimeout = 120;

	while (iTimeout)
		{
		nr_delay(100); // Wait 100 ms.
		if (0xFFFF == *addr)
			return 0;

		iTimeout--;
		}

	// Timeout error.
	return -1;
	}

// This routine actually takes about 3 us on a 33.333MHz Nios32.

static wait_at_least_1_us(void)
	{
	volatile unsigned long iTimeout = nasys_clock_freq_1000 / 8250;
	while (iTimeout--)
		{
		;
		}
	}

// Unlock bypass mode, enabling fast writes.

static void unlock_bypass_mode(volatile unsigned short *flash_base)
	{
	flash_base[0x555] = 0xAA;
	flash_base[0x2AA] = 0x55;
	flash_base[0x555] = 0x20;
	}

// Turn bypass mode off, disabling fast writes and enabling normal function.
static void reset_bypass_mode(volatile unsigned short *flash_base)
	{
	*flash_base = 0x90;
	*flash_base = 0x0;
	}

// Read the given address until two successive reads yield the
// same value.
// Return value: 0 on success, -1 on timeout failure.
static int await_write_complete(volatile unsigned short *addr,unsigned short correct_value)
	{
	unsigned long iTimeout = 40;
	unsigned short us1;

	// The "typical" time for a word write is 11 us.

	// Set a timeout of about 4 times "typical".

	while (iTimeout)
		{
		wait_at_least_1_us();

		// While the flash is occupied with a task, it toggles data
		// bit 6 on each read.	When the flash is idle, data bit 6
		// stops toggling.	So, read twice and compare - there's no
		// need for bit masking.

		us1 = *addr;

		if (us1 == correct_value)
			return 0;
		iTimeout--;
		}

	return -1;
	}

static int erase_flash_single_command(volatile unsigned short *flash_base)
	{
	int result;

	// Erase the entire flash in one command.
	flash_base[0x555] = 0xAA;
	flash_base[0x2AA] = 0x55;
	flash_base[0x555] = 0x80;
	flash_base[0x555] = 0xAA;
	flash_base[0x2AA] = 0x55;
	flash_base[0x555] = 0x10;

	result = await_erase_complete(1, flash_base);
	}


// Write val to the given flash address, in bypass mode (assumes
// that bypass mode has been enabled already).
// Return value: 0 on success, -1 on failure.
static int nr_flash_write_bypass(volatile unsigned short *flash_base,
	unsigned short *addr, unsigned short val)
	{
	unsigned short us1, us2;
	int iTimeout;
	int result = 0;

	*flash_base = 0xA0;
	*addr = val;

	result = await_write_complete(addr,val);
	if(result)
		return result;

	us1 = *addr;

	if (us1 != val)
		result = -1;

	return result;
	}

// ---------------------------------------------
// Public Routines

// Erase the flash sector at sector_address.
// Return value: 0 on success, -1 on failure.

int nr_flash_erase_sector
		(
		unsigned short *flash_base,
		unsigned short *sector_address
		)
	{
	volatile unsigned short *fb = flash_base;
	int result;

#ifdef nasys_main_flash
	if (-1 == (int)fb)
		fb = nasys_main_flash;
#endif // nasys_main_flash

	fb[0x555] = 0xAA;
	fb[0x2AA] = 0x55;
	fb[0x555] = 0x80;
	fb[0x555] = 0xAA;
	fb[0x2AA] = 0x55;

	*sector_address = 0x30;

	// Loop until the data reads as 0xFFFF.

	result = await_erase_complete(0, sector_address);
	return result;
	}


// Erase the entire flash.
// Return value: 0 on success, -1 on failure.

int nr_flash_erase(unsigned short *flash_base)
	{
	volatile unsigned short *fb = flash_base;
	int result = 0;

#if __nios32__
#define ALLSECTORERASE 1
#if ALLSECTORERASE
#ifdef nasys_main_flash
	if (-1 == (int)fb)
		{
		fb = nasys_main_flash;
		}
#endif // nasys_main_flash

	result = erase_flash_single_command(fb);
	return result;

#else // !ALLSECTORERASE

	int i;

	// For nios32, the 29LV800B is divided into sectors as follows:
	// [0, 0x4000)
	// [0x4000, 0x6000)
	// [0x6000, 0x8000)
	// [0x8000, 0x10000)
	// [0x10000, 0x20000)
	// [0x20000, 0x30000)
	// ...
	int sectorOffset[] = {
		0, 0x4000, 0x6000, 0x8000, 0x10000, 0x20000, 0x30000, 0x40000,
		0x50000, 0x60000, 0x70000, 0x80000, 0x90000, 0xA0000, 0xB0000,
		0xC0000, 0xD0000, 0xE0000, 0xF0000,
	};

	if (-1 == (int)fb)
		fb = nasys_main_flash;

	// Erase each sector in turn.

	for (i = 0; i < sizeof(sectorOffset) / sizeof(*sectorOffset); ++i)
		{
		int sector = (int)fb + sectorOffset[i];

		result = nr_flash_erase_sector(fb, (unsigned short*)sector);
		if(result)
			break;
		}
	return result;

#endif // ALLSECTORERASE
#else // !__nios32__
#ifdef nasys_main_flash
	if (-1 == (int)fb)
		fb = nasys_main_flash;
#endif // nasys_main_flash

	result =  erase_flash_single_command(fb);
	return result;

#endif // __nios32__
}

// Write val to the given flash address.
// Return value: 1 on success, 0 on failure.
int nr_flash_write
		(
		unsigned short *flash_base,
		unsigned short *addr,
		unsigned short val
		)
{
	volatile unsigned short *fb = flash_base;
	volatile unsigned short *a = addr;
	unsigned short us1, us2;
	int result = 0;

#ifdef nasys_main_flash
	if (-1 == (int)fb)
		fb = nasys_main_flash;
#endif // nasys_main_flash

	fb[0x555] = 0xAA;
	fb[0x2AA] = 0x55;
	fb[0x555] = 0xA0;

	*a = val;

	result = await_write_complete(a,val);
	if(result)
		return result;

	us1 = *a;
	if (us1 != val)
		result = -1;

	return result;
}


// Write a buffer of data to the flash, using bypass mode.
// Return value: 1 on success, 0 on failure.
int nr_flash_write_buffer
		(
		unsigned short *flash_base,
		unsigned short *start_address,
		unsigned short *buffer,
		int size
		)
	{
	volatile unsigned short *fb = flash_base;
	int i;
	int result = 0;

#ifdef nasys_main_flash
	if (-1 == (int)fb)
		fb = nasys_main_flash;
#endif // nasys_main_flash

	unlock_bypass_mode(fb);
	for (i = 0; i < size; ++i)
		{
		result = nr_flash_write_bypass(fb, start_address + i, buffer[i]);
		if(result)
			break;

		}
	reset_bypass_mode(fb);

	return result;
	}


⌨️ 快捷键说明

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