📄 spl.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 + -