📄 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 "mx2_nand.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; for(i=NAND_KERNEL_START;i<NAND_KERNEL_START+KERNEL_SIZE;i++) { if(i%32==0) //One block { if(NAND_Read_OOB(0,i,spare,16)) { EUARTputString("Read OOB Data Error\n"); return; } if(spare[5]!=0xFF) { //Bad Block EUARTputString("A Bad Block\n"); //i+=31; i+=32; continue; } } if(NAND_Read_OnePage(i, pDest, spare)) { EUARTputString("Read Data Error\n"); return; } if(i%256==0) EUARTputString("."); pDest+=NAND_FLASH_PAGE_MAIN_SIZE; }}/// 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("9. Restore bad block bits\n"); 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 write_over = 0; int erase_over = 0; int isFirstPageOfaBlock = 0,badBlockPos; int i, last = 512, nBadBlock = 0; if(choice == 0) startPage = 0x0; else if(choice == 1) startPage = 0x100000/512; else startPage = 0x300000/512; page = startPage; for(i=0;i<NAND_FLASH_PAGE_SPARE_SIZE;i++) spare[i]=0xff; EUARTputString("\n"); while(1) { if(page%32==0) //one block { badBlockPos =page; // choice == 0 need no bad block check if(choice && NAND_Read_OOB(0,page,spare,16)) { 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[5] != 0xFF) && (spare[5] != 0x00)) if(choice && (spare[5] != 0xFF)) { EUARTputString("A bad block, just skip it\n"); nBadBlock++; page+=32; if(size<(page-startPage-nBadBlock*32)*512) return; continue; } else { if(NAND_Erase(page)) { EUARTputString("Erase Error\n"); FoundBadBlock(page); return; } EUARTputString("."); isFirstPageOfaBlock = 1; } } // ECC handle before write a page last = size-(page-startPage-nBadBlock*32)*512 < 512 ? size-(page-startPage-nBadBlock*32)*512 : 512; //mx2_write_ecc((char*)p, spare, last); if(isFirstPageOfaBlock) //First page of a block { /* spare[8] = 0x85;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -