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

📄 stage1_boot.c

📁 一个非常有用的nand_flash的boot程序代码
💻 C
字号:

typedef unsigned int uint32;
typedef unsigned char uint8;
typedef unsigned short uint16;

#define NAND_NO_DATA
#include "SMC.h"

#define NAND_BUS_WIDTH		8
// #define NAND_CS_DONT_CARE


#define PAGE_COUNT	31
#define PAGE_SIZE	512

#define	GPIO_REG_OUTPUT		*(uint32*)(0xB1700008)
#define	NAND_FORCE_CE	15

//****************************************
//				Nand Registers			//
//#define NAND_PHYS_ADDR	0x20000000
#define NAND_PHYS_ADDR	0x08000000
#define NAND_CS			0xA8000000		//Mapped chip select address
#define NAND_REG_CMD	*(volatile short*)(NAND_CS + MEM_STNAND_CMD)
#define NAND_REG_ADDR	*(volatile short*)(NAND_CS + MEM_STNAND_ADDR)
#define NAND_REG_DATA	*(volatile short*)(NAND_CS + MEM_STNAND_DATA)
//****************************************

//****************************************
//				Nand Commands			//
#define NAND_CMD_AUTO_ERASE_SETUP	0x0060
#define NAND_CMD_ERASE				0x00D0
#define NAND_CMD_STATUS_READ1		0x0070
#define NAND_CMD_STATUS_READ2		0x0071
#define NAND_CMD_SEQ_DATA_INPUT		0x0080
#define NAND_CMD_PROGRAM			0x0010
#define NAND_CMD_READ1				0x0000
#define NAND_CMD_READ2				0x0001
#define NAND_CMD_READ3				0x0050
#define NAND_CMD_RESET				0x00FF
#define NAND_CMD_ID_READ1			0x0090
#define NAND_CMD_ID_READ2			0x0091
//****************************************

//****************************************
//				Nand Status				//
#define NAND_STATUS_PROGRAM_ERROR	0x01
#define NAND_STATUS_ERASE_ERROR		0x01


//****************************************
//		Nand Static Bus Configuration	//
//Timing values as described in databook, ns value stripped of lower 2 bits
#define NAND_T_H			(18 >> 2)
#define NAND_T_PUL			(30 >> 2)
#define NAND_T_SU			(30 >> 2)
#define NAND_T_WH			(30 >> 2)

//Bitfield shift amounts
#define NAND_T_H_SHIFT		0
#define NAND_T_PUL_SHIFT	4
#define NAND_T_SU_SHIFT		8
#define NAND_T_WH_SHIFT		12

#define NAND_TIMING			((NAND_T_H   & 0xF)	<< NAND_T_H_SHIFT)   | \
							((NAND_T_PUL & 0xF)	<< NAND_T_PUL_SHIFT) | \
							((NAND_T_SU  & 0xF)	<< NAND_T_SU_SHIFT)  | \
							((NAND_T_WH  & 0xF)	<< NAND_T_WH_SHIFT)

#define NAND_CTRL_BOOT			1
#define NAND_CTRL_INTERRUPT		(1<<8)
#define NAND_CTRL_CS_OVERIDE	0x20
#define NAND_STSTAT_RNB			0x01

//Static bus configuration registers
#define NAND_ADDR_SPACE_SIZE	0x3FF
#define NAND_SB_CSBA(n)			((n >> 4) & 0x0FFFC000)
#define NAND_SB_CSMASK(n)		(n<<4)
#define NAND_SB_ENABLE			(1<<28)
#define NAND_SB_REG_TIMING		*(uint32*)(SMC_PHYS_ADDRESS + SMC_MEMSTTIME1)
#define NAND_SB_REG_CONFIG		*(uint32*)(SMC_PHYS_ADDRESS + SMC_MEMSTCFG1)
#define NAND_SB_REG_ADDR		*(uint32*)(SMC_PHYS_ADDRESS + SMC_STADDR1)
#define NAND_SB_REG_CTRL		*(uint32*)(SMC_PHYS_ADDRESS + MEM_STNAND)
#define NAND_SB_REG_STSTAT		*(uint32*)(SMC_PHYS_ADDRESS + MEM_STSTAT)
//****************************************

static void __inline configure_nand()
{
	//Enable Nand Force GPIO
	GPIO_REG_OUTPUT = (1 << (16 + NAND_FORCE_CE)) | (1 << NAND_FORCE_CE);

	//Configure Static Bus
	NAND_SB_REG_CTRL   = 0;		// Disable nand BOOT bit
	NAND_SB_REG_CONFIG = SMC_NAND;
	NAND_SB_REG_TIMING = NAND_TIMING;
	NAND_SB_REG_ADDR   = NAND_SB_ENABLE | NAND_SB_CSBA(NAND_PHYS_ADDR) | NAND_SB_CSMASK(NAND_ADDR_SPACE_SIZE);
}

static void __inline set_address(uint16 block, uint8 page, uint8 column)
{
	NAND_REG_ADDR = column;			 
	NAND_REG_ADDR = page | ((block&(0x7)) << 5);	//A9-A16
	NAND_REG_ADDR = (block >> 3);					//A17-A25
	NAND_REG_ADDR = (block >> 11);					//A25
}

static void __inline wait_busy()
{
	int i;
	for(i = 0; i < 10000000; ++i)
	{
		if(i > 1000 && (NAND_SB_REG_STSTAT & NAND_STSTAT_RNB))
		{
			return;
		}
	}
}

static void __inline read_stage2()
{
	extern uint32 _stage2;
	#if NAND_BUS_WIDTH == 8
		char* dest = (char*) &_stage2;
	#elif NAND_BUS_WIDTH == 16
		short* dest = (short*) &_stage2;
	#endif

	int page, bytes;
	NAND_REG_CMD = NAND_CMD_READ1;

	#ifndef NAND_CS_DONT_CARE
		NAND_SB_REG_CTRL = NAND_CTRL_CS_OVERIDE; //Manually assert CS
	#endif

	for(page = 1; page < PAGE_COUNT; ++page)
	{
		set_address(0, page, 0);
		wait_busy();
		
		for(bytes = 0; bytes < PAGE_SIZE; bytes += (NAND_BUS_WIDTH / 8))
			*dest++ = NAND_REG_DATA;
	}

	#ifndef NAND_CS_DONT_CARE
		NAND_SB_REG_CTRL = 0;
	#endif
}

void __attribute__((section(".stage1"))) load_stage2()
{
//	*((uint32*)0xADC00000) = 1;
	configure_nand();
//	*((uint32*)0xADC00000) = 2;
	read_stage2();
}

⌨️ 快捷键说明

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