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

📄 spl.c

📁 mx21的NAND Flash Bootloader源代码
💻 C
字号:
/*************************************************************************Title:   	Filename:   $Header:$Hardware:   MX21Summay:License:    The contents of this file are subject to the Mozilla Public            License Version 1.1 (the "License"); you may not use this file            except in compliance with the License. You may obtain a copy of            the License at http://www.mozilla.org/MPL/Author:   Company:    Freescale Suzhou Design Center====================Change Log========================$Log:$********************************************************************************//// @ingroup    NAND_BOOTLOADER/// @file       spl.c/// @brief	This main file of boot loader.//////		Spl Concept comes from DOC(M-System).///		It copy Kernel from NAND to SDRAM and jump to Kernel.///		It includes some tool to program NAND flash and debug./// /// @remarks	Spl Size must be below 14k\n///		linkscript is spllink.lds\n///		init asm code is splstartup.S/// @author     /// @bug        /// @version    $Version$//<<<<<Include#ifndef _STANDALONE_#define _STANDALONE_#endif #include "mx2.h"#include "nfc.h"#include "uart.h"#include "usb.h"//>>>>>Include//<<<<<< Private Macro#define	CMD_LINE_LEN		80#define	DELAY_LOOP_COUNT 	0x20000    		///< When Bootloader Wait Input,System Delay. ///Linux Boot Argument.///@remark 	If you want to rootdisk writable, you must add @b rw to cmdline. char  cmdLine[] = "root=/dev/mtdblock/6 rw mem=48M";/// Kernel Start Address In SDRAM.#define KERNEL_START_ADDRESS 0xc0008000	/// Kernel Command Line Address.////// Before Jump to Kernel, Bootloader will copy cmdline to this address.#define KERNEL_CMDLINE       0xc03FF000		/// Kernel Max Size (Unit is Page)#define KERNEL_SIZE	     (0x200000/NAND_FLASH_PAGE_MAIN_SIZE)/// Kernel Partition start page of NAND Flash #define NAND_KERNEL_START    (0x100000/NAND_FLASH_PAGE_MAIN_SIZE)//>>>>>> Private Macro//<<<<<< Private Structure//>>>>>> Private Structure//<<<<<< Global Variable//>>>>>> Global Variable//<<<<<Private Function Declearation//>>>>>Private Function Declearation//<<<<<Body///Set Systme to AsynchMode.void SetAsynchMode(void){/*	__asm__(    	"mrc p15,0,r0,c1,c0,0\n\t"    	"mov r2, #0xC0000000\n\t"    	"orr r0,r2,r0\n\t"    	"mcr p15,0,r0,c1,c0,0\n\t"	);*/}///Init Mx2 Hardware. //////Init CS0,CS1,CS3, Call SetAsynchMode()void init(){    	 int dummy,reg;		    // burst-flash initialization    //comment # CS0 Initialization (Async Mode)     //comment # 32-bit, ?? wait states              //setmem 0xDF001000 0x00003E00 32//setmem 0xDF001004 0x00000E01 32	_reg_WEIM_CSU(0) = 0x00003E00;	_reg_WEIM_CSL(0) = 0x00000E01; //comment # Setting for Memory Map IO Port//comment # CS1 Initialization (Async Mode)//comment # 16-bit, D0..15, ?? wait states//setmem 0xDF001008 0x00002000 32//setmem 0xDF00100C 0x11118501 32	_reg_WEIM_CSU(1)=0x00002000 ;	_reg_WEIM_CSL(1)=0x11118501 ;//comment # CS3 Initialization (Async Mode)//comment # 32-bit, ?? wait states//setmem 0xDF001018 0x00003E00 32//setmem 0xDF00101C 0x11110601 32	_reg_WEIM_CSU(3)=0x00003E00 ;	_reg_WEIM_CSL(3)=0x11110601 ;//comment # Config MUX for pin PF18->CS1//comment # Clear PTF_GIUSE //setmem 0x10015520 0x00000000 32	_reg_GPIO_GIUS(GPIOF)&=~0x40000;//comment # Clear PTF_GPR//setmem 0x10015538 0x00000000 32	_reg_GPIO_GPR(GPIOF)&=~0x40000;//comment # FMCR Register//comment # Select CS3/CSD0 Pin as CS3 only.//setmem 0x10027814 0xFFFFFFC9 32	_reg_SYS_FMCR=0xFFFFFFC9;   // Initialize all peripheral in AIPI1 PSR[1:0] => 10=32bit, 01=16bit, 00=8bit	 _reg_AIPI1_PSR0 = 0x00040304;	 _reg_AIPI1_PSR1 = 0xFFFBFCFB;    // Initialize all peripheral in AIPI1 PSR[1:0] => 10=32bit, 01=16bit, 00=8bit	_reg_AIPI2_PSR0 = 0x0;	_reg_AIPI2_PSR1 = 0xFFFFFFFF; 	//write to the FMCR [31:24] (CLKMODE[1:0]) in order to get the write enable signal active 	_reg_SYS_FMCR |= 0xAA000000;	SetAsynchMode();    }/// Copy Kernel From NAND Flash to SDRAMvoid CopyKernelToMem(){	char 	*pDest = (char*)KERNEL_START_ADDRESS;	char 	spare[NAND_FLASH_PAGE_SPARE_SIZE];	int	i;	int	j;	for(i=NAND_KERNEL_START;i<NAND_KERNEL_START+KERNEL_SIZE;i++)	{#ifdef NAND_ECC	    // Check for bad block	    if(i%32==0) //One block	    {		if(nfc_read_page(i,0,(u32*)spare))		{		    EUARTputString("Read OOB Data Error\n");		    return;		}		if(spare[9]!=0xFF)		{		    //Bad Block		    EUARTputString("A Bad Block\n");		    i+=31;		    continue;		}	    }#endif	    // Read one page	    nfc_read_page(i, (u32*)((u32)pDest + (i-NAND_KERNEL_START)*NAND_FLASH_PAGE_MAIN_SIZE), (u32*)spare);	    if(i%256==0)		EUARTputString(".");	}}/// Get boot opition when system boot./// @return 	boot option code:///		@li 0 	Program bootloader image///		@li 1	Program kernel image///		@li 2	Program root-disk image///		@li 3	Download kernel and boot from RAM	(this version don't suppport)///		@li 4	Download kernel and boot with ver 0.1.x bootloader format (this version don't suppport)///		@li 5	Boot a ver0.1.x kernel (this version don't suppport)///		@li 6	Boot with a different command line(this version don't suppport)///		@li 7	Command Shell(this version don't suppport)#define __PLL_CHOICE__int GetBootOption(){	int countDown;	int bootOption = 0;	int delayCount ;	while (EUARTdataReady()) EUARTgetData();	// clear input buffer	EUARTputString("Press any key for alternate boot-up options ...   ");	countDown = 2;	bootOption = 0;	while ((countDown) && (!bootOption))	{		EUARTputString("\b\b");		// two back spaces		EUARTputHex(countDown);		delayCount = 0;		do		{			delayCount++;			if (EUARTdataReady()) bootOption = 1;		} while ((delayCount < DELAY_LOOP_COUNT) && (!bootOption));		--countDown;	}		EUARTputString("\b\b");		// two back spaces	EUARTputHex(countDown);	EUARTputString("\n\n");	if (bootOption)	{		while (EUARTdataReady()) EUARTgetData();	// clear input buffer		// print options		EUARTputString("0. Program bootloader image\n");		EUARTputString("1. Program kernel image\n");		EUARTputString("2. Program root-disk image\n");		//EUARTputString("3. Download kernel and boot from RAM\n");		//EUARTputString("4. Download kernel and boot with ver 0.1.x bootloader format\n");		//EUARTputString("5. Boot a ver0.1.x kernel\n");		EUARTputString("6. Boot with a different command line\n");		//EUARTputString("7. Command Shell\n");#ifdef __PLL_CHOICE__		EUARTputString("8. Booting with different fclk/bclk \n");#endif		EUARTputString("\n   Please enter selection ->  ");		do		{			while (!EUARTdataReady());		// wait for key press			bootOption = EUARTgetData();			if (bootOption >= 0x20)			{				EUARTputData('\b');				EUARTputData(bootOption);			}		} while ((bootOption  < '0') || (bootOption >= '9'));		EUARTputString("\n\n");		return bootOption;		}	return -1;}/// @brief   Program NAND FLASH////// @param   pSource         SDRAM Source Address/// @param   size            Size to program/// @param   choice          The choice to program bootloader or kernel or rootdisk///			     @li 0  bootloader///			     @li 1  kernel///			     @li 2  rootdiskvoid ProgramFlash(IN int pSource,IN int size,IN int choice){	int	startPage, page;	char	spare[NAND_FLASH_PAGE_SPARE_SIZE];	int*	p = (int*)pSource;	int erase_over = 0;	int	nBadBlock = 0;#ifdef NAND_ECC	int	i, isFirstPageOfaBlock = 0;#endif	if(choice == 0)	    startPage = 0x0;	else if(choice == 1)	    startPage = 0x100000/512;	else	    startPage = 0x300000/512;#ifdef NAND_ECC	for(i=0;i<NAND_FLASH_PAGE_SPARE_SIZE;i++)		spare[i]=0;#endif	EUARTputString("\n");	for(page = startPage; size>(page-startPage-nBadBlock*32)*512; page++)	{		if(page%32==0) //one block		{#ifdef NAND_ECC		    // choice == 0 need no bad block check		    if(choice && nfc_read_page(page,0,(u32*)spare))		    {			EUARTputString("Read OOB Data Error\n");			return;		    }		    // 0xFF is the setting from factory		    // but after eraseall, the value will change to be 0x00		    if(choice && (spare[9] != 0xFF) && (spare[9] != 0x00))		    {			EUARTputString("A bad block, just skip it\n");			nBadBlock++;			page+=32;			if(size<(page-startPage-nBadBlock*32)*512)				return;			continue;		    }		    else		    {#endif			if(nfc_erase(page))			{				EUARTputString("Erase Error\n");				return;			}			EUARTputString(".");#ifdef NAND_ECC			isFirstPageOfaBlock = 1;		    }#endif		}#ifdef NAND_ECC		if(isFirstPageOfaBlock)		{		    //First page of a block		    spare[10] = 0x03;		    spare[11] = 0x20;		    spare[12] = 0x08;		    spare[13] = 0x00;		    spare[14] = 0x00;		    spare[15] = 0x00;		    isFirstPageOfaBlock = 0;		}#endif		// Write one page		if( nfc_write_page(page, (u32*)((u32)p + (page-startPage)*NAND_FLASH_PAGE_MAIN_SIZE), (u32*)spare) )		{			EUARTputString("Program Error\n");			return;		}	}	if(choice == 2)	{		EUARTputString("go on erasing unused blocks \n");		while(1)		{			if(page%32 == 0)			{				if(nfc_erase(page))				{					EUARTputString("Erase Error\n");					return;				}				EUARTputString(".");			}			page++;			if(page >= (0x1000000/512 -31))			{				erase_over = 1;				EUARTputString("Erase complete\n");			}			if(erase_over == 1)				return;		}	}	return;}void mx21_module_init(){	//comment ### Master Priority Register for Slave Port 3	// Keep LCDC as the highest priority	_reg_SYS_PCSR = 0;	_reg_MAX_SLV_MPR(3) = 0x00123056;	_reg_MAX_SLV_SGPCR(3) = 0;//comment # enable user mode CSI access//setmem 0x10027818 0x6000e 32        _reg_SYS_GPCR = 0x6000e;}///The Main Functionint main(){	char	*pCmdLine;	char    *pMem;	int 	i;	int	bootOption;	int	fileSize;#ifdef __PLL_CHOICE__	int mpll[3];	int MFI,MFN,MFD;	unsigned long mpll_value,fout;	unsigned long presc,bclkdiv,ipdiv,fref;	int fout_trial;	signed long deviation;	unsigned long temp;	int redundant = 0;	//stat data	char c;	char  freq = '7';//default setting, mpll 266,fclk 266, bclk 88.	#endif	init();	//Set this for NAND Flash work rightly	_reg_CRM_PCDR0=(_reg_CRM_PCDR0&0xffff0fff)|0x00009000;	for(i=0;i<100000;i++);	MX21_UartSetting();	MX21_InitInternalUART();		EUARTputString("\n\nDBMX21 Linux 16-Bit NAND Flash Bootloader ver mx21_to3_rel3.2\n");	EUARTputString("Copyright (C) 2005 Freescale Semiconductors Suzhou Ltd.\n\n");   	EUARTputString((char *)cmdLine);   	EUARTputString("\n\n");	EUARTputString("MPLL = 266, FCLK = 266, BCLK = 133\n\n");	// Read id		nfc_readid(&i);	EUARTputString("NAND Flash ID:");	EUARTputHex(i);EUARTputHex(i>>16);	EUARTputString("\n");	//Copy Kernel to Memory	bootOption=GetBootOption();	if(bootOption==-1)	{boot_kernel:		EUARTputString("Copy Kernel to Memory\n");			CopyKernelToMem();			//Copy Command Line		pMem = (char *)KERNEL_CMDLINE;		pCmdLine = (char *)&cmdLine;		while ((*(pMem++)=*(pCmdLine++)) != 0);		EUARTputString("\nJump To Kernel\n");		mx21_module_init();		//JumpToKernel((void *)KERNEL_START_ADDRESS, KERNEL_CMDLINE);		return KERNEL_START_ADDRESS;		}		// process boot option	if ((bootOption >= '0') && (bootOption <= '2'))		// i.e. flash programming	{		fileSize=usbrx();		EUARTputString("\n");		switch (bootOption)		{			case '0':	// i.e. program bootloader					EUARTputString("Program BootLoader\n");					EUARTputString("Please Plug USB Cable\n");					ProgramFlash(USB_DISK_START+0x9A00,fileSize,0);					break;			case '1':	// i.e. program kernel image					EUARTputString("Program Kernel Image\n");					EUARTputString("Please Plug USB Cable\n");					ProgramFlash(USB_DISK_START+0x9A00,fileSize,1);					break;			case '2':	// i.e. program root-disk					EUARTputString("Program RootDisk\n");					EUARTputString("Please Plug USB Cable\n");					ProgramFlash(USB_DISK_START+0x9A00,fileSize,2);					break;		}		EUARTputString("\nPress RESET button on ADS board ...");		while (1);	// infinite loop	}	if (bootOption == '6')	// i.e. boot with a different command line	{		EUARTputString("New command line: ");		i = 0;		do		{			while (!EUARTdataReady());		// wait for key press			c = EUARTgetData();			if (c != '\r')			{				if (c == '\b')				{					if (i > 0)					{						// erase the character						EUARTputData('\b');						EUARTputData(' ');						EUARTputData('\b');						--i;					}				}				else				{					EUARTputData(c);					cmdLine[i++] = c;				}			}		} while ((c != '\r') && (i < CMD_LINE_LEN-1));		if (i > 0)			cmdLine[i] = 0;		// mark end of string		EUARTputData('\n');		goto boot_kernel;	}	#ifdef __PLL_CHOICE__	if(bootOption == '8')	{		//now it is mpll266,presc 0, bclkdiv 2,ipdiv 1.		//get input mpll				EUARTputString("Please enter your settings mpll(MHz)... \n ");		i = 0;		do		{			while (!EUARTdataReady());		// wait for key press			c = EUARTgetData();			if (c != '\r')			{				EUARTputData(c);				c = c - '0';				mpll[i++] = c;			}		} while ((c != '\r') && (i<3));		mpll_value = mpll[0]*100 + (mpll[1])*10 + mpll[2];		EUARTputString("\n");		//get input presc value				EUARTputString("Please enter your settings PRESC(0~3)... \n ");		while (!EUARTdataReady());		// wait for key press		c = EUARTgetData();		if (c != '\r')		{			EUARTputData(c);			c = c - '0';			presc = c;		}		EUARTputString("\n");				//get input bclkdiv value				EUARTputString("Please enter your settings BCLKDIV(00~15)... \n ");		i = 0;		do		{			while (!EUARTdataReady());		// wait for key press			c = EUARTgetData();			if (c != '\r')			{				EUARTputData(c);				c = c - '0';				mpll[i++] = c;			}		} while ((c != '\r') && (i <2));		bclkdiv = mpll[0]*10+mpll[1];		EUARTputString("\n");		//get input ipdiv value				EUARTputString("Please enter your settings ipdiv(0~1)... \n ");		while (!EUARTdataReady());		// wait for key press		c = EUARTgetData();		if (c != '\r')		{			EUARTputData(c);			c = c - '0';			ipdiv = c;		}				_reg_CRM_MPCTL0 = mpll_value | (presc<<10) | (bclkdiv<<16) | (ipdiv<<26);		EUARTputString("\n");	}	goto boot_kernel;#endif	return 0;}//>>>>>Body

⌨️ 快捷键说明

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