您的位置:首页 > 其它

移植Uboot-2010.06到TQ2440开发板详解之三

2013-09-12 19:45 344 查看
七、支持从NAND启动

1、修改start.S文件

1)       设置好C语言要用的栈

修改arch/arm/cpu/arm920t/start.S,将stack_setup 子程序搬到relocate 子程序之前(在调用C函数之前设置好栈),并修改之前调用设置栈的函数为清除BSS段,这是因为之前的源码程序调用beq stack_setup之后接着执行了清除BSS段的子程序clear_bss,把stack_setup搬移到上面之后,应该确保会执行clear_bss子函数,跟之前的效果一样。修改后的代码如下:
 
209stack_setup:
210         ldr    r0, _TEXT_BASE          /* upper128 KiB: relocated uboot   */
211         sub    r0, r0, #CONFIG_SYS_MALLOC_LEN  /*malloc area              */
212         sub    r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo                 */
213 #ifdefCONFIG_USE_IRQ
214         sub    r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
215#endif 
216         sub    sp, r0, #12             /* leave 3words for abort-stack    */
217         bic    sp, sp, #7              /* 8-bytealignment for ABI compliance */
218        
219 #ifndefCONFIG_SKIP_RELOCATE_UBOOT
220relocate:                              /* relocate U-Boot to RAM          */
221         adr    r0, _start              /* r0<- current position of code   */
222         ldr    r1, _TEXT_BASE          /* test ifwe run from flash or RAM */
223         cmp    r0, r1                  /* don'treloc during debug         */
224         /*beq  stack_setup */         
225         beq    clear_bss
226        
227         ldr    r2, _armboot_start
228         ldr    r3, _bss_start
229         sub    r2, r3, r2              /* r2<- size of armboot            */
230         add    r2, r0, r2              /* r2<- source end address         */
2)       修改代码搬移程序

在relocate子程序中屏蔽掉原来的拷贝函数,增加自己用C语言实现的拷贝函数:

 

219 #ifndefCONFIG_SKIP_RELOCATE_UBOOT

220 relocate:                               /* relocate U-Boot to RAM           */

221         adr    r0, _start              /* r0<- current position of code   */

222         ldr    r1, _TEXT_BASE          /* test ifwe run from flash or RAM */

223         cmp    r0, r1                  /* don't reloc during debug         */

224         /*beq  stack_setup */         

225         beq    clear_bss

226        

227         ldr    r2, _armboot_start

228         ldr    r3, _bss_start

229         sub    r2, r3, r2              /* r2<- size of armboot            */

230 #if1  

231         bl CopyCode2Ram

232#else

233         add    r2, r0, r2              /* r2<- source end address         */

234        

235 copy_loop:

236         ldmia  r0!, {r3-r10}           /* copyfrom source address [r0]    */

237         stmia  r1!, {r3-r10}           /* copyto   target address [r1]    */

238         cmp    r0, r2                  /* untilsource end addreee [r2]    */

239         ble    copy_loop

240#endif

241 #endif  /* CONFIG_SKIP_RELOCATE_UBOOT */

2、实现代码拷贝函数

   在board/samsung/tq2440/目录下增加一个文件nand_start.c,实现Nand的操作:

 

#include<common.h>

//#include<s3c2410.h>

#include<asm/arch/s3c24x0_cpu.h>

 

#defineGSTATUS1        (*(volatile unsigned int*)0x560000B0)

#defineBUSY            1

 

#defineNAND_SECTOR_SIZE   512

#defineNAND_BLOCK_MASK   (NAND_SECTOR_SIZE - 1)

 

#defineNAND_SECTOR_SIZE_LP   2048

#defineNAND_BLOCK_MASK_LP   (NAND_SECTOR_SIZE_LP- 1)

 

charbLARGEBLOCK;         //HJ_add 20090807

charb128MB;            //HJ_add 20090807

 

/* 供外部调用的函数 */

voidnand_init_ll(void);

intnand_read_ll(unsigned char *buf, unsigned long start_addr, int size);

intnand_read_ll_lp(unsigned char *buf, unsigned long start_addr, int size);

 

/* NAND Flash操作的总入口, 它们将调用S3C2410或S3C2440的相应函数 */

static voidnand_reset(void);

static voidwait_idle(void);

static voidnand_select_chip(void);

static voidnand_deselect_chip(void);

static voidwrite_cmd(int cmd);

static voidwrite_addr(unsigned int addr);

static voidwrite_addr_lp(unsigned int addr);

static unsignedchar read_data(void);

intNF_ReadID(void);            //HJ_add20090807

 

/* S3C2440的NAND Flash处理函数 */

static voids3c2440_nand_reset(void);

static voids3c2440_wait_idle(void);

static voids3c2440_nand_select_chip(void);

static voids3c2440_nand_deselect_chip(void);

static voids3c2440_write_cmd(int cmd);

static voids3c2440_write_addr(unsigned int addr);

static voids3c2440_write_addr_lp(unsigned int addr);

static unsignedchar s3c2440_read_data(void);

 

/* S3C2440的NAND Flash操作函数 */

 

/* 复位 */

static voids3c2440_nand_reset(void)

{

   s3c2440_nand_select_chip();

   s3c2440_write_cmd(0xff);  // 复位命令

   s3c2440_wait_idle();

   s3c2440_nand_deselect_chip();

}

 

/* 等待NAND Flash就绪 */

static voids3c2440_wait_idle(void)

{

   int i;

   S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

   volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFSTAT;

 

   while(!(*p & BUSY))

        for(i=0; i<10; i++);

}

 

/* 发出片选信号 */

static voids3c2440_nand_select_chip(void)

{

   int i;

   S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

 

   s3c2440nand->NFCONT &= ~(1<<1);

   for(i=0; i<10; i++);   

}

 

/* 取消片选信号 */

static voids3c2440_nand_deselect_chip(void)

{

   S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

 

  s3c2440nand->NFCONT |= (1<<1);

}

 

/* 发出命令 */

static voids3c2440_write_cmd(int cmd)

{

   S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

 

   volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFCMD;

   *p = cmd;

}

 

/* 发出地址 */

static voids3c2440_write_addr(unsigned int addr)

{

   int i;

   S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

   volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFADDR;

   

   *p = addr & 0xff;

   for(i=0; i<10; i++);

   *p = (addr >> 9) & 0xff;

   for(i=0; i<10; i++);

   *p = (addr >> 17) & 0xff;

   for(i=0; i<10; i++);

   *p = (addr >> 25) & 0xff;

   for(i=0; i<10; i++);

}

 

 

/* 发出地址 */

static voids3c2440_write_addr_lp(unsigned int addr)

{

   int i;

   S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

   volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFADDR;

   int col, page;

 

   col = addr & NAND_BLOCK_MASK_LP;

   page = addr / NAND_SECTOR_SIZE_LP;

  

   *p = col & 0xff;         /* Column Address A0~A7 */

   for(i=0; i<10; i++);     

   *p = (col >> 8) & 0x0f;      /* Column Address A8~A11 */

   for(i=0; i<10; i++);

   *p = page & 0xff;         /* Row Address A12~A19 */

   for(i=0; i<10; i++);

   *p = (page >> 8) & 0xff;   /* Row Address A20~A27 */

   for(i=0; i<10; i++);

if (b128MB ==0)

   *p = (page >> 16) & 0x03;   /* Row Address A28~A29 */

   for(i=0; i<10; i++);

}

 

/* 读取数据 */

static unsignedchar s3c2440_read_data(void)

{

   S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

  
de8d
volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFDATA;

   return *p;

}

 

 

/* 在第一次使用NAND Flash前,复位一下NAND Flash */

static voidnand_reset(void)

{

   s3c2440_nand_reset();

}

 

static voidwait_idle(void)

{

   s3c2440_wait_idle();

}

 

static voidnand_select_chip(void)

{

   int i;

  

   s3c2440_nand_select_chip();

  

   for(i=0; i<10; i++);

}

 

static voidnand_deselect_chip(void)

{

   s3c2440_nand_deselect_chip();

}

 

static voidwrite_cmd(int cmd)

{

   s3c2440_write_cmd(cmd);

}

static voidwrite_addr(unsigned int addr)

{

   s3c2440_write_addr(addr);

}

 

static voidwrite_addr_lp(unsigned int addr)

{

   s3c2440_write_addr_lp(addr);

}

 

static unsignedchar read_data(void)

{

   return s3c2440_read_data();

}

 

/* 初始化NAND Flash */

voidnand_init_ll(void)

{

   S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

 

   #define TACLS   0

   #define TWRPH0  3

   #define TWRPH1  0

 

   /* 设置时序 */

   s3c2440nand->NFCONF =(TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);

   /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */

   s3c2440nand->NFCONT =(1<<4)|(1<<1)|(1<<0);

 

   /* 复位NAND Flash */

   nand_reset();

}

#if 1

intNF_ReadID(void)

{

   char pMID;

   char pDID;

   int nBuff;

   char  n4thcycle;

   int i;

   S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

   volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFADDR;

 

   b128MB = 1;

   n4thcycle = nBuff = 0;

 

   nand_init_ll();

   nand_select_chip();

   write_cmd(0x90);   // read id command

   *p=0x00 & 0xff;

   for ( i = 0; i < 100; i++ );

 

   pMID = read_data();

   pDID = read_data();

   nBuff = read_data();

   n4thcycle = read_data();

 

   nand_deselect_chip();

  

   if (pDID >= 0xA0)

   {

      b128MB = 0;

   }

 

   return (pDID);

}

#endif

 

/* 读函数 */

intnand_read_ll(unsigned char *buf, unsigned long start_addr, int size)

{

   int i, j;

   char dat;

   S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

   volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFADDR;

 

   

   if ((start_addr & NAND_BLOCK_MASK) ||(size & NAND_BLOCK_MASK))

   {

      return -1;    /* 地址或长度不对齐 */

   }

 

   /* 选中芯片 */

   nand_select_chip();

 

   for(i=start_addr; i < (start_addr +size);)

   {

/* Check BadBlock */

if(1){

      /* 发出READ0命令 */

      write_cmd(0x50);

 

      *p = 5;

      for(j=0; j<10; j++);

      *p = (i >> 9) & 0xff;

      for(j=0; j<10; j++);

      *p = (i >> 17) & 0xff;

      for(j=0; j<10; j++);

      *p = (i >> 25) & 0xff;

      for(j=0; j<10; j++);

      wait_idle();

      dat = read_data();

      write_cmd(0);

     

      /* 取消片选信号 */

      nand_deselect_chip();

      if(dat != 0xff)

         i += 16384;      // 1 Block = 512*32= 16384

/* Read Page */

      /* 选中芯片 */

      nand_select_chip();

}

      /* 发出READ0命令 */

      write_cmd(0);

 

      /* Write Address */

      write_addr(i);

      wait_idle();

 

      for(j=0; j < NAND_SECTOR_SIZE; j++,i++)

      {

         *buf = read_data();

         buf++;

      }

   }

 

   /* 取消片选信号 */

   nand_deselect_chip();

 

   return 0;

}

 

/* 读函数

 * Large Page

 */

intnand_read_ll_lp(unsigned char *buf, unsigned long start_addr, int size)

{

   int i, j;

   char dat;

   S3C2440_NAND * s3c2440nand = (S3C2440_NAND*)0x4e000000;

   volatile unsigned char *p = (volatileunsigned char *)&s3c2440nand->NFADDR;

 

   if ((start_addr & NAND_BLOCK_MASK_LP) ||(size & NAND_BLOCK_MASK_LP))

   {

      return -1;    /* 地址或长度不对齐 */

   }

 

   /* 选中芯片 */

   nand_select_chip();

 

   for(i=start_addr; i < (start_addr +size);)

   {

/* Check BadBlock */

if(1){

      int col, page;

 

      col = i & NAND_BLOCK_MASK_LP;

      page = i / NAND_SECTOR_SIZE_LP;

      /* 发出READ0命令 */

      write_cmd(0x00);

 

      *p = 5;

      for(j=0; j<10; j++);

      *p = 8;

      for(j=0; j<10; j++);

      *p = page & 0xff;      /* Row Address A12~A19 */

      for(j=0; j<10; j++);

      *p = (page >> 8) & 0xff;      /* Row Address A20~A27 */

      for(j=0; j<10; j++);

if (b128MB ==0)

      *p = (page >> 16) & 0x03;      /* Row Address A28~A29 */

      for(j=0; j<10; j++);

 

      write_cmd(0x30);

      wait_idle();

      dat = read_data();

     

      /* 取消片选信号 */

      nand_deselect_chip();

      if(dat != 0xff)

         i += 131072;      // 1 Block = 2048*64= 131072

/* Read Page */

      /* 选中芯片 */

      nand_select_chip();

}

      /* 发出READ0命令 */

      write_cmd(0);

 

      /* Write Address */

      write_addr_lp(i);

      write_cmd(0x30);

      wait_idle();

 

      for(j=0; j < NAND_SECTOR_SIZE_LP; j++,i++)

      {

         *buf = read_data();

         buf++;

      }

   }

 

   /* 取消片选信号 */

   nand_deselect_chip();

 

   return 0;

}

 

intbBootFrmNORFlash(void)

{

   volatile unsigned int *pdw = (volatileunsigned int *)0;

   unsigned int dwVal;

 

   /*

    * 无论是从NOR Flash还是从NAND Flash启动,

    * 地址0处为指令"b   Reset", 机器码为0xEA00000B,

    * 对于从NAND Flash启动的情况,其开始4KB的代码会复制到CPU内部4K内存中,

    * 对于从NOR Flash启动的情况,NOR Flash的开始地址即为0。

    * 对于NOR Flash,必须通过一定的命令序列才能写数据,

    * 所以可以根据这点差别来分辨是从NAND Flash还是NOR Flash启动:

    * 向地址0写入一个数据,然后读出来,如果没有改变的话就是NOR Flash

    */

 

   dwVal = *pdw;      

   *pdw = 0x12345678;

   if (*pdw != 0x12345678)

   {

      return 1;

   }

   else

   {

      *pdw = dwVal;

      return 0;

   }

}

 

intCopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)

{

   unsigned int *pdwDest;

   unsigned int *pdwSrc;

   int i;

 

   if (bBootFrmNORFlash())

   {

      pdwDest = (unsigned int *)buf;

      pdwSrc = (unsigned int *)start_addr;

      /* 从 NOR Flash启动 */

      for (i = 0; i < size / 4; i++)

      {

         pdwDest[i] = pdwSrc[i];

      }

      return 0;

   }

   else

   {

      /* 初始化NAND Flash */

      nand_init_ll();

 

      /* 从 NAND Flash启动 */

      if (NF_ReadID() == 0x76 )

         nand_read_ll(buf, start_addr, (size +NAND_BLOCK_MASK)&~(NAND_BLOCK_MASK));

      else

         nand_read_ll_lp(buf, start_addr, (size+ NAND_BLOCK_MASK_LP)&~(NAND_BLOCK_MASK_LP));

      return 0;

   }

}

3、修改board/samsung/tq2440/config.mk

      代码段

25 TEXT_BASE =0x33000000

26 //TEXT_BASE= 0x33F80000

 

 

 

4、修改Makefile

28 COBJS   := tq2440.o flash.o nand_start.o

5、修改连接脚本

    修改arch/arm/cpu/arm920t/u-boot.lds (由于这个函数是被第一阶段的汇编程序所调用)。

40         .text :

41         {

42                arch/arm/cpu/arm920t/start.o   (.text)

43                board/samsung/tq2440/nand_start.o (.text)

44                 *(.text)

45         }

6、将之前注释掉的初始化CPU的函数取消注释

    修改arch/arm/cpu/arm920t/start.S  第206行:

206         bl     cpu_init_crit

    它会调用lowlevel_init子函数(载lowlevel_init.S文件定义)进行CPU的初始化,包括总线宽度,时序响应等。

7、最重要的修改Makefile

       参见我的另一篇博文,u-boot-2010.06 移植到TQ2440从NAND启动不了以及lowlevel_init运行不过去的解决办法

编译烧写到Nand Flash,从Nand启动,可以看到启动信息。

八、修改uboot使得支持Linux内核启动

1、修改板子头文件include/configs/tq2440.h
43 /* for tag(s) to transfermessage to kernel */
44 #define CONFIG_SETUP_MEMORY_TAGS1
45 #define CONFIG_CMDLINE_TAG 1
46 #define CONFIG_INITRD_TAG 1
……
123 /*#define CONFIG_BOOTARGS       "root=ramfs devfs=mountconsole=ttySA0,9600" */
124 #define CONFIG_BOOTARGS"noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0"
……
131 /*#define CONFIG_BOOTCOMMAND    "tftp; bootm" */
132 #define CONFIG_BOOTCOMMAND"nand read 0x32000000 0x200000 0x300000; bootm 0x32000000"
 
2、修改机器码
   由于内核机器吗被改成了168,所以这里要改成跟内核一样,不然内核无法启动。在文件arch/arm/include/asm/mach-types.h中修改之前tq2440.c中赋值过的机器码:
(gd->bd->bi_arch_number = MACH_TYPE_S3C2440;)
 
375 //#defineMACH_TYPE_S3C2440              362
376 #defineMACH_TYPE_S3C2440              168
3、连接mkimage工具
   该工具在生成uImage的时候需要用到,它在编译好uboot之后就在tools文件夹下产生了,把他连接到PATH路径去(注意需要使用完整路径):
 
[root@arm 16:50 /home/zhang/uboot]# ln -sf/home/zhang/uboot-2010.06/tools/mkimage /usr/local/bin/mkimage
 
4、编译内核和根文件系统并下载
注意,如果出现文件系统启动之后,隔几秒系统就会自动重启的话,是因为应用层没有喂狗的程序。在文件系统中添加喂狗程序,重新生成文件系统之后就可以了。
Hit any key to stop autoboot:  0
TQ2440 #
TQ2440 # tftp 0x30000000 uImage
……
TQ2440 # bootm 0x30000000
……
这样就会看到内核启动,要是Nand中已经烧录好了根文件系统,就会正常启动。但是掉电之后就没了。
可以通过nand命令将其固化在Nand中,在运行bootm 0x30000000之前:
 
1)       下载uImage
 
TQ2440 # tftp0x30000000 uImage
dm9000 i/o: 0x20000000, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 10:23:45:67:89:ab
could not establish link
Using dm9000 device
TFTP from server 192.168.10.96; our IPaddress is 192.168.10.66
Filename 'uImage'.
Load address: 0x30000000
Loading:#################################################################
        #################################################################
        ############################
done
Bytes transferred = 2314780 (23521c hex)
 
2)       擦除NANDFLASH,擦除地址为0x200000,大小为0x300000 的NAND FLASH:
 
TQ2440 # nand erase0x200000 0x300000
 
NAND erase: device 0 offset 0x200000, size0x300000
Erasing at 0x4e0000 -- 100% complete.
OK
 
3)       写入NANDFLASH,将地址0x30000000 的SDRAM的数据写入到地址0x200000,大小0x300000 的NAND FLASH
 
TQ2440 # nand write0x30000000 0x200000 0x300000
 
NAND write: device 0 offset 0x200000, size0x300000
 3145728 bytes written: OK
TQ2440 #
 
   重新启动开发板就可以看到正常引导信息。
 
 
 
转自:http://blog.csdn.net/mkpci/article/details/7336520
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  uboot 移植 makefile
相关文章推荐