移植uboot2010.06到TQ2440开发板详解之一
??????? 最近在学习uboot的移植,也看过很多文章,但多多少少都有些不尽人意的地方,自己手动移植也出现过种种问题。尤其是不能对移植的过程有很好的理解,基于这个原因,我打算深入学习一下uboot的移植过程,并对移植过程详细记录,方便那些想学习uboot移植确找不到门路的新手。 ??????? 鉴于本人也是新手,文章难免有疏漏之处,也有自己不是很明白的地方,已经标记出来,还望各位多多指教。如果觉得好想转载,请注明出处。 一、建立自己的开发板并测试编译 1、建立自己的板文件(夹): 1)???????首先找到uboot源码包,进入uboot目录。 找到与开发板最相近的一个目标板,在此基础上进行修改。我们选择SMDK2410: [root@local 02:53/home/zhang]# cd uboot-2010.06/board/samsung/ [root@local 02:53/home/zhang/uboot-2010.06/board/samsung]# ls goni? smdk2400?smdk2410? smdk6400? smdkc100 2)???????建立自己的目标板文件(夹): [root@local 02:53/home/zhang/uboot-2010.06/board/samsung]# cp -R smdk2410/ tq2440 [root@local 02:56/home/zhang/uboot-2010.06/board/samsung]# ls goni? smdk2400?smdk2410? smdk6400? smdkc100?tq2440 ?? 修改文件名: [root@local 03:00/home/zhang/uboot-2010.06/board/samsung/tq2440]# mv smdk2410.c tq2440.c [root@local 03:00/home/zhang/uboot-2010.06/board/samsung/tq2440]# ls config.mk? flash.c?lowlevel_init.S? Makefile? tq2440.c ?? 修改Makefile,如下图: ?? 建立头文件,在include/configs/目录下: [root@local 03:05/home/zhang/uboot-2010.06/include/configs]# cp smdk2410.h tq2440.h 3)???????修改根目录下的Makefile文件,添加配置: 复制smdk2410的配置,添加tq2440的两行配置,如下图: 说明: arm:CPU的体系架构,对应uboot/arch/arm目录 arm920t: CPU的类型,对应uboot/arch/arm/cpu/arm920t/目录(每个版本uboot位置不尽相同) tq2440: 自己的板文件目录 samsung: 自己的板文件目录的上级目录,如果是在uboot/board目录下,则设置为NULL s3c24x0: CPU型号,SOC片上系统 指定交叉编译工具,如下图: 4)???????测试编译: [root@local 03:22/home/zhang/uboot-2010.06]# make distclean [root@local 03:23 /home/zhang/uboot-2010.06]# maketq2440_config Configuring fortq2440 board... [root@local 03:25 /home/zhang/uboot-2010.06]# make all 如果没有错误就说明uboot和交叉编译工具基本上没问题了,这时候生成了uboot.bin。但是这时候实际生成的是针对smdk2410的uboot,下面对其进行修改,以适应tq2440。 二、Uboot启动过程分析 ???? 这一阶段本来打算写的,由于自己还没有弄的很明白,怕写出来出错会误导很多人,所以干脆就不写了,推荐大家去看一下韦东山的视频第9课,专门讲uboot的,能获取很大帮助。这里给出下载网址:http://dl.dbank.com/c03o1ebwlo三、修改Uboot启动TQ2440开发板 1、修改SDRAM的配置 修改board/samsung/tq2440/lowlevel_init.S文件,这里是ARM的几个Bank(片选)总线宽度以及是否是能wait、UB/LB功能,需要参考硬件原理图的连接配置方式 : 54 #define B1_BWSCON?????????????? (DW16) //(DW32) ?55 #define B2_BWSCON?????????????? (DW16) ?56 #define B3_BWSCON?????????????? (DW16 + WAIT + UBLB) ?57 #define B4_BWSCON?????????????? (DW16) ?58 #defineB5_BWSCON?????????????? (DW8)? //)(DW16) ?59 #define B6_BWSCON?????????????? (DW32) ?60 #define B7_BWSCON?????????????? (DW32) 还有126行,SDRAM refresh control register,REFRESH,时钟刷新寄存器,根据具体情况需要修改其中某些位,这里仅修改了Refresh count位: REFRESH[10:0]: SDRAMrefresh count value. Refer to chapter 6 SDRAM refresh controller bus prioritysection. Refresh period = (211-refresh_count+1)/HCLK Ex) Ifrefresh period is 7.8 us and HCLK is 100MHz,the refresh count is as follows: Refreshcount = 211 + 1 - 100x7.8 = 1269(0x4F5)。page210 ? ?126 #define REFCNT? 0x4f4 /*period=7.8125us,HCLK=100Mhz,(2048+1-7.8125*100)=0x4F4*/ 2、时钟一些概念与原理 1)???????时钟比的概念 经常会看到这么一个时钟关系:FCLK:HCLK:PCLK=1:4:8,其意义是:HCLK=FCLK/4,PCLK=FCLK/8,在手册242页定义: FCLK: FCLK is usedby ARM920T. 内核时钟,即主频 HCLK: HCLK is usedfor AHB bus,which is used by the ARM920T,the memory controller,the interruptcontroller,the LCD. 总线时钟,包括USB总线时钟。 PCLK: PCLK is usedfor APB bus,which is used by the peripherals such as WDT,IIS,I2C,PWM timer,MMC interface ADC,UART,GPIO,RTC and SPI. IO接口时钟,例如串口的时钟就是从这里来的。 ? 2)???????时钟寄存器配置,page254 MPLL ControlRegister: MPLL = (2 * m *Fin) / (p * 2s) m = (MDIV + 8),p= (PDIV + 2),s = SDIV UPLL ControlRegister: UPLL = (m * Fin) /(p * 2s) m = (MDIV + 8),s = SDIV 其中MDIV、PDIV、SDIV是MPLLCON、UPLLCON寄存器的分频因子。由于计算比较复杂,手册上一般都会给出几种常见的分频值,pege255。 例如:
即: MPLLCON[19:12] =0x7f MPLLCON[9:4] = 2 MPLLCON[1:0] = 1 未指明的位清零,由此计算出:MPLLCON=0x7F021,UPLLCON=0x38022 NOTE: Whenyou set MPLL&UPLL values,you have to set the UPLL value first and then theMPLL value. (Needs intervals approximately 7 NOP)。先配置UPLLCON后配置MPLLCON。 ? 3)???????时钟比的控制 设置好了FCLK=405MHZ,USB PLLCLK=48MHZ,设置FCLK:HCLK:PCLK=1:4:8,即HCLK=FCLK/4,PCLK=FCLK/8,时钟频率按照第二步计算,由此可以推算出: CLKDIVN寄存器的值为:0x5。 CAMDIVN[9] = 0(HCLK4_HALF,由于HCLK=FCLK/4),该位初始值为0 HDIVN=2,page242。 NOTE:If HDIVN is not 0,the CPU bus mode has tobe changed from the fast bus mode to the asynchronous bus mode using followinginstructions(S3C2440 does not support synchronous bus mode). MMU_SetAsyncBusMode mrc p15,r0,c1,c0,0 orr r0,#R1_nF:OR:R1_iA mcr p15,0 If HDIVN isnot 0 and the CPU bus mode is the fast bus mode,the CPU will operate by theHCLK. Thisfeature can be used to change the CPU frequency as a half or more withoutaffecting the HCLK and PCLK. 在手册上没找到关于#R1_nF:OR:R1_iA 意义,参考:http://www.voidcn.com/article/p-ondkyjan-wb.html nF和iA是哪个寄存器的[31:30]比特位,置1表示时钟的模式为:Asynchronous,将#R1_nF:OR:R1_iA替换为0xC0000000. 3、修改时钟配置 1)???????修改cpu/arm920t/start.S文件中的时钟部分: 首先屏蔽掉原来的时钟设置: 164 #if 0?? 165????????/* FCLK:HCLK:PCLK = 1:2:4 */ 166????????/* default FCLK is 120 MHz ! */ 167????????ldr???? r0,=CLKDIVN 168????????mov???? r1,#3 169????????str???? r1,[r0] 170 #endif?????????????? 添加如下代码: 172 #defineMPLLCON 0x4C000004 /*寄存器地址*/ 173 #defineUPLLCON 0x4C000008 174?????? ?mrc p15,r1,0 /*设置时钟(总线?)模式为Asynchronous.read ctrl register*/ 175???????? orr r1,#0xc0000000????? /*Asynchronous*/ 176???????? mcr p15,0????? /*write ctrl register*/ 177???????? ldr????r0,=CLKDIVN?????? /*设置时钟分频寄存器*/ 178???? ????mov????r1,#5 179???????? str????r1,[r0] 180???????? nop 181???????? nop 182???????? nop 183???????? nop 184???????? nop 185???????? ldr????r0,=UPLLCON /*设置USB时钟*/ 186???????? ldr????r1,=0x38022 187???????? str????r1,[r0] 188???????? nop 189?????? ??nop 190???????? nop 191???????? nop 192???????? nop 193???????? nop 194???????? nop 195???????? ldr????r0,=MPLLCON /*设置主频405MHZ*/ 196???????? ldr????r1,=0x7f021 197???????? str????r1,[r0] 2)???????然后修改board/samsung/tq2440/tq2440.c文件中的board_init 函数 107????????/* arch number of SMDK2410-Board */ 108????????//gd->bd->bi_arch_number = MACH_TYPE_SMDK2410; 109????????gd->bd->bi_arch_number =MACH_TYPE_S3C2440; 3)???????修改arch/arm/cpu/arm920t/s3c24x0/speed.c文件,里面也有时钟设置部分: 首先修改get_PLLCLK函数,该函数返回主频时钟,公式为:MPLL = (2 * m * Fin) / (p * 2s) 67????????//return (CONFIG_SYS_CLK_FREQ * m) / (p << s); 68????????return (CONFIG_SYS_CLK_FREQ * m*2) / (p <<s); ?? 其次,修改get_HCLK函数,HCLK由寄存器CLKDIVN[2:1]和CAMDIVN[9]决定:
根据手册上的定义,修改get_HCLK如下: 修改arch/arm/include/asm/arch-s3c24x0/s3c24x0.h,在结构体struct s3c24x0_clock_power添加最后一个成员,CAMDIVN,原理不多说,CAMDIVN寄存器紧挨着CLKDIVN寄存器,地址上增加4,添加在CLKDIVN之后能起到地址增4的效果,从而可以读器硬件寄存器的内容: 118 struct s3c24x0_clock_power { 119????????u32???? LOCKTIME; 120????????u32???? MPLLCON; 121????????u32???? UPLLCON; 122????????u32???? CLKCON; 123????????u32???? CLKSLOW; 124????????u32???? CLKDIVN; 125????????u32????CAMDIVN; 126 }; 接着就可以修改arch/arm/cpu/arm920t/s3c24x0/speed.c文件中的get_HCLK函数了: 78 ulong get_HCLK(void) ?79 { ?80????????struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); ?81????????ulong r,hdivn,hclkn,hdiv; ?82????????r = readl(&clk_power->CLKDIVN); ?83????????hdivn = r & 0x6; ?84????????r = readl(&clk_power->CAMDIVN); ?85????????switch(hdivn) ?86????????{? //hdiv、hclkn为从硬件寄存器中读出的时钟分频因子,参考芯片手册 ?87???????????case 0x0: hdiv = 1;break; ?88???????????case 0x2: hdiv = 2;break; ?89???????????case 0x4: ?90??????????????? hclkn = (r & 0x200)>> 9; ?91??????????????? hdiv = (hclkn == 1)? 8:4; ?92??????????????? break; ?93???????????case 0x6: ?94??????????????? hclkn = (r & 0x100)>> 8; ?95??????????????? hdiv = (hclkn == 1)? 6:3; ?96??????????????? break; ?97????????} ?98????????return get_FCLK() / hdiv; ?99????????//return (readl(&clk_power->CLKDIVN) & 2) ? get_FCLK() / 2 :get_FCLK(); 100 } 再修改get_PCLK函数(可不修改?): 103 ulong get_PCLK(void) 104 { 105????????struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); 106? ???????ulongr,pdivn,pdiv; 107 108????????r = readl(&clk_power->CLKDIVN); 109????????pdivn = r & 0x1; 110????????pdiv = (pdivn == 1)? 2:1; 111????????return get_HCLK()/pdiv; 112 113????????//return (readl(&clk_power->CLKDIVN) & 1) ? get_HCLK() / 2 :get_HCLK(); 114 } 最后增加Uboot启动时的时钟打印信息(可选): 121 int print_cpuinfo(void) 122 { 123????????printf("TQ2440 CLK: Fclk = %luMHz,Hclk = %luMHz,Pclk = %luMHzn", 124??????????????? get_FCLK() / 1000000,get_HCLK() / 1000000,get_PCLK() / 1000000); 125 }??????????? 并在include/configs/tq2440.h增加宏定义: 32 #define CONFIG_DISPLAY_CPUINFO 小窍门:???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?? ? ?????? 开启Uboot时的打印信息都是在Uboot启动的第二阶段,即arch/arm/lib/board.c文件,通过查看该文件定义的函数和宏定义的用法,可以获知如何修改已增加相应的打印信息。?? ?????? 例如,搜索DRAM:可以找到打印这个的信息的文件和函数,在:?????????????????????????????????? ??? Board.c ?(archarmlib)?? puts("DRAM:? "); ??????????????????????????????????????????????????????????????????????????????????? ???? ?????? 跳转过去可以发现:?????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? static int display_dram_config (void)?????????????????????????????????????????????????????????????????????????????????????????????? ??? {???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? ?????? int i;??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? #ifdef DEBUG??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? ?? puts("RAM Configuration:n");???????????????????????????????????????????????????????????????????????????????????????????????????? ??? ?????? for(i=0;i<CONFIG_NR_DRAM_BANKS; i++) {??????????????????????????????????????????????????????????????????????????? ??? ????????????? printf("Bank #%d: %08lx ",i,gd->bd->bi_dram[i].start);????????????????????????????????????????????????? ??? ?????? print_size(gd->bd->bi_dram[i].size,"n");??????????????????????????????????????????????????????????????????????????????? ??? ?????? }????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? #else????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? ?????? ulongsize = 0;?????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????? ??? ?????? for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) {?????????????????????????????????????????????????????????????????????????? ??? ????????????? size+= gd->bd->bi_dram[i].size;??????????????????????????????????????????????????????????????????????????????????????? ??? ?????? }????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? ?????? puts("DRAM:? ");??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????? print_size(size,"n");???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? #endif???????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????? ??? ??? return (0);???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? }???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? ?? 再寻找调用函数display_dram_config的位置,类似的增加其他的函数调用。??????????????? ??? ?? 发现是在下面的一些列初始化列表中:??????????????????????????????????????????????????????????????????????????????? ??? init_fnc_t *init_sequence[] = {??????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? ……????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? ?????? display_dram_config,?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? ?????? NULL,????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? };???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? ? 4)???????修改uboot下的板子提示符: 打开include/configs/tq2440.h,修改117行如下: 117 #defineCONFIG_SYS_PROMPT??? "TQ2440 #"???? /* Monitor Command Prompt */ ? 5)???????修改arch/arm/cpu/arm920t/start.S文件: 206 #ifndefCONFIG_SKIP_LOWLEVEL_INIT 207???????? @bl???? cpu_init_crit 208 #endif 意义?注释掉cpu的初始化? 6)???????编译并下载到RAM运行: [root@local 21:12/home/zhang/uboot-2010.06]# make distclean [root@local 21:12 /home/zhang/uboot-2010.06]# maketq2440_config [root@local 21:12/home/zhang/uboot-2010.06]# make all ?? 生成uboot.bin文件,将其下载到ram中执行,得到如下结果,如下图: 四、支持NorFlash 现在还无法通过U-Boot命令烧写Nor Flash。本开发板中的Nor Flash型号为EN29LV160AB,而配置文件include/configs/dong2440.h中默认型号为AM29LV400。因为本开发板Nor Flash为2MB,和AM29LV800 很相似,所以对Nor Flash配置修改如下: ? 161 #if0 162#define CONFIG_AMD_LV400??????? 1? ?/* uncomment this if you have a LV400 flash */ 163#endif 164#define CONFIG_AMD_LV800??????? 1? ?/* uncomment this if you have a LV800 flash */ 165 166 #defineCONFIG_SYS_MAX_FLASH_BANKS???????? 1??????????? /* max number of memory banks */ 167 #ifdefCONFIG_AMD_LV800 168 #definePHYS_FLASH_SIZE???????? 0x00200000 ? /*2MB */ 169 #defineCONFIG_SYS_MAX_FLASH_SECT???? (19) ????? /* max number of sectors on one chip */ 170 #defineCONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x1F0000)/*addrof environment */ 171 #endif 172 #ifdefCONFIG_AMD_LV400 173 #definePHYS_FLASH_SIZE???????? 0x00080000??? /* 512KB */ 174 #defineCONFIG_SYS_MAX_FLASH_SECT ?? (11)??? /* max number of sectors on one chip */ 175 #defineCONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x070000)/*addr of environment */ 176 #endif 177 178 /* timeoutvalues are in ticks */ 179 #defineCONFIG_SYS_FLASH_ERASE_TOUT (5*CONFIG_SYS_HZ)/* Timeout for Flash Erase */ 180 #defineCONFIG_SYS_FLASH_WRITE_TOUT (5*CONFIG_SYS_HZ)/* Timeout for Flash Write */ 181 182 #defineCONFIG_ENV_IS_IN_FLASH? 1 183 #defineCONFIG_ENV_SIZE??????? ?0x20000 /*Total Size of Environment Sector */ 编译后烧写进RAM运行,Flash变成2MiB,表示对Flash已经支持,如下图: 五、支持Nand读写 增加Nand的读写支持,只需要实现board_nand_init函数即可。Nand Flash的初始化过程为: start_armboot(arch/arm/lib/board.c)->nand_init()(drivers/mtd/nand/nand.c)->nand_init_chip(),nand_init_chip首先调用board_nand_init()(需要自己实现,下面会看到我们在nand_flash.c文件实现)函数,如果初始化成功,就会调用nand_scan()函数,它调用nand_scan_ident()函数,这个函数会调用nand_get_flash_type()函数读取硬件ID。nand_get_flash_type()调用结构体struct nand_chip *chip中的chip->cmdfunc和chip->read_byte函数进行发送命令/地址和读取数据。其中chip->cmdfunc根据情况被赋值,调用了需要自己实现的函数s3c2440_hwcontrol()。chip->read_byte根据情况调用了它所在文件的nand_read_byte函数,去读取NFDATA寄存器中的数据。 1、修改,增加Nand结构体: 1)???????增加NAND结构体: 为什么在这个文件添加?我们要增加一些函数或变量来实现相应的功能时,如果这些变量或函数与平台相关,就找到uboot中平台相关的文件,在里面进行添加。如果与开发板相关,就找到相应的开发板目录进行添加。 在文件arch/arm/include/asm/arch-s3c24x0/s3c24x0.h增加S3C2440 NAND控制器的寄存器结构体。该结构体的成员是S3C2440的Nand Flash控制器的一系列寄存器,按照顺序依次存放,这样在获取到第一个寄存器NFCONF的地址之后(整个结构体的起始地址),后续的寄存器就会按照地址依次增4个字节的形式确定自己的地址,与S3C2440芯片手册给出的Nand一系列的寄存器地址正好能对应上。 165typedef struct s3c2440_nand{ 166???????? u32 NFCONF; 167???????? u32 NFCONT; 168???????? u32 NFCMD; 169???????? u32 NFADDR; 170???????? u32 NFDATA; 171???????? u32 NFMECCD0; 172???????? u32 NFMECCD1; 173???????? u32 NFSECCD; 174???????? u32 NFSTAT; 175???????? u32 NFESTAT0; 176???????? u32 NFESTAT1; 177???????? u32 NFMECC0; 178???????? u32 NFMECC1; 179???????? u32 NFSECC; 180???????? u32 NFSBLK; 181???????? u32 NFEBLK; 182 }S3C2440_NAND; 2)???????增加获取NAND结构基地址函数 在arch/arm/include/asm/arch-s3c24x0/s3c2410.h增加获取Nand控制器物理基地址的函数: 首先增加宏定义,0x4E000000是S3C2440的Nand控制器相关寄存器的起始物理地址: 54 #define S3C2410_NAND_BASE?????????????? 0x4E000000 55 #define S3C2440_NAND_BASE?????????????? 0x4E000000 再次增加函数: 103 static inline struct s3c2410_nand*s3c2410_get_base_nand(void) 104 { 105????????return (struct s3c2410_nand *)S3C2410_NAND_BASE; 106 } 107 108 static inline structs3c2440_nand *s3c2440_get_base_nand(void) 109 { 110???????? return (struct s3c2440_nand*)S3C2440_NAND_BASE; 111 } 2、增加NAND读写支持: 1)???????添加nand_flash.c函数。 (u-boot-1.1.6是在arch/arm/cpu/arm920t/s3c24x0目录下增加NAND读写的支持的) 这里应该在哪个文件添加呢? 拷贝文件drivers/mtd/nand/s3c2410_nand.c到目录arch/arm/cpu/arm920t/s3c24x0/下,并重命名为nand_flash.c,删除一部分不用的内容,将其修改如下: ? #include<common.h> #include<nand.h> #include<asm/arch/s3c24x0_cpu.h> #include<asm/io.h> ? #define S3C2440_NFCONT_nCE (1<<1) #define S3C2440_ADDR_NALE 0x0C #define S3C2440_ADDR_NCLE 0x08 ? #ifdefCONFIG_NAND_SPL ? /*in the early stage of NAND flash booting,printf() is not available */ #defineprintf(fmt,args...) ? staticvoid nand_read_buf(struct mtd_info *mtd,u_char *buf,int len) { ?????? int i; ?????? struct nand_chip *this = mtd->priv; ? ?????? for (i = 0; i < len; i++) ????????????? buf[i] =readb(this->IO_ADDR_R); } #endif /*2410全部改为2440,没有标记红色的也是*/ staticvoid s3c2440_hwcontrol(struct mtd_info *mtd,intcmd,unsigned int ctrl) { ?????? struct nand_chip *chip = mtd->priv; ?????? structs3c2440_nand *nand = s3c2440_get_base_nand(); ? ?????? debugX(1,"hwcontrol(): 0x%02x0x%02xn",cmd,ctrl); ? ?????? if (ctrl & NAND_CTRL_CHANGE) { ????????????? ulong IO_ADDR_W = (ulong)nand; ? ????????????? if ((ctrl& NAND_CLE)) ???????????????????? IO_ADDR_W |=S3C2440_ADDR_NCLE; ????????????? else if ((ctrl &NAND_ALE)) ???????????????????? IO_ADDR_W |=S3C2440_ADDR_NALE; ????????????? else ???????????????????? IO_ADDR_W |=0x10; ? ????????????? chip->IO_ADDR_W = (void*)IO_ADDR_W; ? ????????????? if (ctrl & NAND_NCE) ???????????????????? writel(readl(&nand->NFCONT) & ~S3C2440_NFCONT_nCE, ???????????????????? ?????? &nand->NFCONT); ????????????? else ???????????????????? writel(readl(&nand->NFCONT) | S3C2440_NFCONT_nCE, ???????????????????? ?????? &nand->NFCONT); ?????? } ????????????? if (cmd != NAND_CMD_NONE) ????????????? writeb(cmd,chip->IO_ADDR_W); } ? staticint s3c2440_dev_ready(struct mtd_info *mtd) { ?????? struct s3c2440_nand *nand =s3c2440_get_base_nand(); ?????? return readl(&nand->NFSTAT) &0x01; } ? intboard_nand_init(struct nand_chip *nand) { ?????? u_int32_t cfg; ?????? u_int8_t tacls,twrph0,twrph1; ?????? struct s3c24x0_clock_power *clk_power =s3c24x0_get_base_clock_power(); ?????? struct s3c2440_nand *nand_reg =s3c2440_get_base_nand(); ? ?????? writel(readl(&clk_power->CLKCON) |(1 << 4),&clk_power->CLKCON); ? ?????? /* initialize hardware */ ?????? twrph0 = 4; ?????? twrph1 = 2; ?????? tacls = 0; ?????? cfg =(tacls<<12) | (twrph0<<8) | (twrph1<<4); ?????? writel(cfg,&nand_reg->NFCONF); ? ?????? cfg = (1<<4) |(0<<1) | (1<<0); ?????? writel(cfg,&nand_reg->NFCONT); ? ?????? /* initialize nand_chip data structure */ ?????? nand->IO_ADDR_R = nand->IO_ADDR_W =(void *)&nand_reg->NFDATA; ? ?????? nand->select_chip = NULL; ? ?????? /* read_buf and write_buf are default */ ?????? /* read_byte and write_byte are default*/ #ifdefCONFIG_NAND_SPL ?????? nand->read_buf = nand_read_buf; #endif ? ?????? /* hwcontrol always must be implemented*/ ?????? nand->cmd_ctrl = s3c2440_hwcontrol; ?????? nand->dev_ready = s3c2440_dev_ready; ?????? nand->options = 0; //设置位宽为8 ?????? nand->ecc.mode = NAND_ECC_SOFT; // 软件ECC校验 ? ?????? debugX(1,"end ofnand_initn"); ?????? return 0; } 2)???????修改Makefile文件: 修改该目录下的Makefile增加对nand_flash.c的编译: 28 COBJS-$(CONFIG_USE_IRQ) += interrupts.o 29 COBJS-y += speed.o 30 COBJS-y += timer.o 31 COBJS-y += usb.o 32 COBJS-y += usb_ohci.o 33 COBJS-y += nand_flash.o ? 3)???????修改板子头文件 修改include/configs/tq2440.h文件,增加/修改以下内容: ? 34 #define CONFIG_SAVEENV??????? //saveenv相关命令 35 #define CONFIG_CMD_NAND?? //NAND相关命令 36 #define CONFIG_CMDLINE_EDITING 37 38 #ifdef CONFIG_CMDLINE_EDITING 39 #undef CONFIG_AUTO_COMPLETE 40 #else 41 #define CONFIG_AUTO_COMPLETE 42 #endif …… 193 //#define?????? CONFIG_ENV_IS_IN_FLASH? 1 194 #defineCONFIG_ENV_IS_IN_NAND?? 1 195 #define CONFIG_ENV_SIZE???????? 0x40000/* Total Size of Environment Sector */ 196 #define CONFIG_ENV_OFFSET0x40000 197 198 #define CONFIG_SYS_NAND_BASE0x4E000000 199 #defineCONFIG_SYS_MAX_NAND_DEVICE? 1 200 #define NAND_MAX_CHIPS 1 CONFIG_ENV_SIZE的大小如何确定? 下载到RAM运行,如下图: 可以看到找到NAND为256MiB。 接下来还要做网卡DM9000,从nand启动,加载内核等,由于我还没做到这一步,所以暂且写到这里,等做完之后,再回来写。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |