Chinaunix首页 | 论坛 | 博客
  • 博客访问: 218668
  • 博文数量: 48
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 258
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-22 23:45
文章分类

全部博文(48)

文章存档

2015年(4)

2014年(34)

2013年(10)

分类: LINUX

2015-06-08 21:46:42

        之前编译出来的二进制,能用nandflash加载吗?不能,是吧,这就对啦。为什么不能呢?因为,代码中没有加从nandflash启动所需要的代码。因此,这就是我们今天码字的由来。
       1.先修改cpu/arm1176/start.S文件,修改代码如下:

点击(此处)折叠或打开

  1. #ifndef CONFIG_NAND_SPL
  2.     /*
  3.      * flush v4 I/D caches
  4.      */
  5.     mov r0, #0
  6.     mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
  7.     mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */

  8.     /*
  9.      * disable MMU stuff and caches
  10.      */
  11.     mrc p15, 0, r0, c1, c0, 0
  12.     bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
  13.     bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
  14.     orr r0, r0, #0x00000002 @ set bit 2 (A) Align
  15.     orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
  16.     /* Prepare to disable the MMU */
  17.     adr r1, mmu_disable_phys
  18.     /* We presume we're within the first 1024 bytes */
  19.     and r1, r1, #0x3fc
  20.     ldr r2, _TEXT_PHY_BASE
  21.     ldr r3, =0xfff00000
  22.     and r2, r2, r3
  23.     orr r2, r2, r1
  24.     b mmu_disable

  25.     .align 5
  26.     /* Run in a single cache-line */
  27. mmu_disable:
  28.     mcr p15, 0, r0, c1, c0, 0
  29.     nop
  30.     nop
  31.     mov pc, r2
  32. #endif
更改为:

点击(此处)折叠或打开

  1. #ifndef CONFIG_NAND_SPL
  2.     /*
  3.      * flush v4 I/D caches
  4.      */
  5.     mov r0, #0
  6.     mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
  7.     mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */

  8.     /*
  9.      * disable MMU stuff and caches
  10.      */
  11.     mrc p15, 0, r0, c1, c0, 0
  12.     bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
  13.     bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
  14.     orr r0, r0, #0x00000002 @ set bit 2 (A) Align
  15.     orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
  16. #if 0
  17.     /* Prepare to disable the MMU */
  18.     adr r1, mmu_disable_phys
  19.     /* We presume we're within the first 1024 bytes */
  20.     and r1, r1, #0x3fc
  21.     ldr r2, _TEXT_PHY_BASE
  22.     ldr r3, =0xfff00000
  23.     and r2, r2, r3
  24.     orr r2, r2, r1
  25.     b mmu_disable

  26.     .align 5
  27.     /* Run in a single cache-line */
  28. mmu_disable:
  29.     mcr p15, 0, r0, c1, c0, 0
  30.     nop
  31.     nop
  32.     mov pc, r2
  33. #endif
  34. #endif
找到lowlevel_init在其下面添加如下代码:

点击(此处)折叠或打开

  1. bl lowlevel_init /* go setup pll,mux,memory */
  2. /*
  3.  * When we already run in ram, we don't need to relocate U-Boot
  4.  * and actually, memory controller mest to configured before U-Boot
  5.  * is running in ram.
  6.  */
  7.     ldr r0, =0xff000fff
  8.     bic r1, pc, r0 /*r0 <- current base addr of code*/
  9.     ldr r2, _TEXT_BASE /*r1 <- original base addr in ram*/
  10.     bic r2, r2 ,r0 /*ro <- current base addr of code*/
  11.     cmp r1, r2 /*compare r1 , r2*/
  12.     beq after_copy /* if r1 == r2 then skip flash copy*/

  13. #ifdef CONFIG_BOOT_NAND
  14.     mov r0, #0x1000
  15.     bl copy_from_nand
  16. #endif
简述一下:
bic是位清除指令:就是r0中的值取反与pc值相与存入r1,且r1值为0;此时,_TEXT_BASE的值不是0x57e00000就是0xc7e00000;那么执行完bic r2, r2, r0之后r2就为0x00e00000;然后比较r1,r2如果相等则跳转到after_copy;很显然不相等,执行下面的函数copy_from_nand;这个就是从nandflash中拷贝到内存的函数。


点击(此处)折叠或打开

  1. #ifdef CONFIG_ENABLE_MMU
  2. _mmu_table_base:
  3.     .word mmu_table
  4. #endif
上面这些代码的下面加上如下代码:

点击(此处)折叠或打开

  1. #ifndef CONFIG_NAND_SPL
  2. /*
  3.  * we assume that cache operation is done before. (eg. cleanup_before_linux())
  4.  * actually, we don't need to do anything about cache if not use d-cache in
  5.  * U-Boot. So, in this function we clean only MMU. by scsuh
  6.  *
  7.  * void theLastJump(void *kernel, int arch_num, uint boot_params);
  8.  */
  9.  /*
  10.  * copy U-Boot to SDRAM and jump to ram (from NAND or OneNAND)
  11.  * r0: size to be compared
  12.  * Load 1'st 2blocks to RAM because U-boot's size is larger than 1block(128k) size
  13.  */
  14.  .globl copy_from_nand
  15.  copy_from_nand:
  16.     mov r10, lr /* save return address */
  17.     mov r9, r0
  18.  /* get ready to call C functions */
  19.     ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer */
  20.     sub sp, sp, #12
  21.     mov fp, #0 /* no previous frame, so fp=0 */
  22.     mov r9, #0x1000
  23.     bl copy_uboot_to_ram
  24.  3: tst r0, #0x0
  25.     bne copy_failed
  26.     ldr r0, =0x0c000000
  27.     ldr r1, _TEXT_PHY_BASE
  28.  1: ldr r3, [r0], #4
  29.     ldr r4, [r1], #4
  30.     teq r3, r4
  31.     bne compare_failed /* not matched */
  32.     subs r9, r9, #4
  33.     bne 1b
  34.  4: mov lr, r10 /* all is OK */
  35.     mov pc, lr
  36.     copy_failed:
  37.     nop /* copy from nand failed */
  38.     b copy_failed
  39. compare_failed:
  40.     nop /* compare failed */
  41.     b compare_failed
2.在cpu/arm1176/目录下面添加文件nand_cp.c。文件内容如下:

点击(此处)折叠或打开

  1. #include <common.h>

  2. #ifdef CONFIG_S3C64XX
  3. #include <asm/io.h>
  4. #include <linux/mtd/nand.h>
  5. #include <asm/arch/s3c6410.h>

  6. static int nandll_read_page(uchar *buf, ulong addr, int large_block)
  7. {
  8.     int i;
  9.     int page_size = 512;

  10.     if (large_block == 1)
  11.     {
  12.         page_size = 2048;
  13.     }

  14.     if(large_block == 2)
  15.     {
  16.         page_size = 4096;
  17.     }

  18.     NAND_ENABLE_CE();
  19.     NFCMD_REG = NAND_CMD_READ0;
  20.     NFADDR_REG = 0; /*Write address*/

  21.     if(large_block)
  22.     {
  23.         NFADDR_REG = 0;
  24.     }

  25.     NFADDR_REG = addr & 0xff;
  26.     NFADDR_REG = (addr >> 8) & 0xff;
  27.     NFADDR_REG = (addr >> 16) & 0xff;
  28.     if (large_block)
  29.     {
  30.         NFCMD_REG = NAND_CMD_READSTART;
  31.     }
  32.     NF_TRANSRnB();
  33.     for(i=0; i < page_size; i++)
  34.     {
  35.         *buf++ = NFDATA8_REG;
  36.     }
  37.     NAND_DISABLE_CE();
  38.     return 0;
  39. }
  40. static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block)
  41. {
  42.     uchar *buf = (uchar *)dst_addr;
  43.     int i;
  44.     uint page_shift = 9;
  45.     if (large_block==1)
  46.         page_shift = 11;
  47.         /* Read pages */
  48.     if(large_block==2)
  49.         page_shift = 12;
  50.     if(large_block == 2)
  51.     {
  52.         /* Read pages */
  53.         for (i = 0; i < 4; i++, buf+=(1<<(page_shift-1)))
  54.         {
  55.             nandll_read_page(buf, i, large_block);
  56.         }
  57.         /* Read pages */
  58.         for (i = 4; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift))
  59.         {
  60.             nandll_read_page(buf, i, large_block);
  61.         }
  62.     }
  63.     else
  64.     {
  65.         for (i = 0; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift))
  66.         {
  67.             nandll_read_page(buf, i, large_block);
  68.         }

  69.     }
  70.     return 0;
  71. }
  72. int copy_uboot_to_ram(void)
  73. {
  74.     int large_block = 0;
  75.     int i;
  76.     vu_char id;

  77.     /*
  78.     NFCONT_REG = ( *( (volatile u32 *) (0x70200004) ) )
  79.     NFCONT 0x70200004 读/写NAND Flash 控制寄存器
  80.     [0]1:NAND Flash 控制器使能
  81.     */
  82.     NAND_ENABLE_CE();

  83.     NFCMD_REG = NAND_CMD_READID;

  84.     /*
  85.     NFADDR_REG = ( *( (volatile u32 *) (0x7020000C) ) )
  86.     NFADDR 0x7020000C NAND Flash 地址设置寄存器 */
  87.     NFADDR_REG = 0x00;


  88.     /*
  89.     NFDATA8_REG = ( *( (vu_char *) (0x70200010) ) )
  90.     NFDATA 0x70200010 读/写NAND Flash 数据寄存器
  91.     NAND Flash 读/烧写数据值用于I/O
  92.     */
  93.     /* wait for a while */
  94.     for (i=0; i<200; i++);
  95.     id = NFDATA8_REG;
  96.     id = NFDATA8_REG;
  97.     if (id > 0x80)
  98.         large_block = 1;
  99.         if(id == 0xd5)
  100.             large_block = 2;
  101.             /* read NAND Block.
  102.             * 128KB ->240KB because of U-Boot size increase. by scsuh
  103.             * So, read 0x3c000 bytes not 0x20000(128KB).
  104.             */
  105.             /*CONFIG_SYS_PHY_UBOOT_BASE = 0x57e0 0000
  106.             0x3 c000 = 1M
  107.             */
  108.     return nandll_read_blocks(CONFIG_SYS_PHY_UBOOT_BASE, 0x3c000, large_block);
  109. }
  110. #endif
3.修改cpu/arm1176/makefile文件中

点击(此处)折叠或打开

  1. COBJS = cpu.o nand_cp.o
    4.修改cpu/arm1176/u-boot.lds文件中

点击(此处)折叠或打开

  1. .text :
  2.     {
  3.         cpu/arm1176/start.o (.text)
  4.         cpu/arm1176/s3c64xx/cpu_init.o (.text)
  5.         board/samsung/smdk6410/lowlevel_init.o (.text)
  6.         cpu/arm1176/nand_cp.o (.text)
  7.         lib_arm/board.o (.text)
  8.         *(.text)
  9.     }
    5.修改board/samsung/smdk6410/u-boot-nand.lds文件中

点击(此处)折叠或打开

  1. .text :
  2.     {
  3.       cpu/arm1176/start.o (.text)
  4.       cpu/arm1176/s3c64xx/cpu_init.o (.text)
  5.       board/samsung/smdk6410/lowlevel_init.o (.text)
  6.       cpu/arm1176/nand_cp.o (.text)
  7.       lib_arm/board.o (.text)
  8.       *(.text)
  9.     }
    6.修改nand_spl/board/samsung/smdk6410/Makefile文件中

点击(此处)折叠或打开

  1. # from SoC directory
  2. $(obj)cpu_init.S:
  3.     @rm -f $@
  4.     @ln -s $(TOPDIR)/cpu/arm1176/s3c64xx/cpu_init.S $@

  5. # from from cpu directory
  6. $(obj)nand_cp.c:
  7.     @rm -f $@
  8.     @ln -s $(TOPDIR)/cpu/arm1176/nand_cp.c $@
    7.修改根目录下u-boot.lds文件

点击(此处)折叠或打开

  1. .text :
  2.  {
  3.    cpu/arm1176/start.o (.text)
  4.    cpu/arm1176/s3c64xx/cpu_init.o (.text)
  5.    board/samsung/smdk6410/lowlevel_init.o (.text)
  6.    cpu/arm1176/nand_cp.o (.text)
  7.    lib_arm/board.o (.text)
  8.    *(.text)
  9.  }
    8.修改include/configs/sdmk6410.h文件

点击(此处)折叠或打开

  1. #if !defined(CONFIG_NAND_SPL) && (TEXT_BASE >= 0xc0000000)
  2. #define CONFIG_ENABLE_MMU
  3. #ifdef CONFIG_ENABLE_MMU
  4. #define virt_to_phys(x) virt_to_phy_smdk6410(x)
  5. #else
  6. #define virt_to_phys(x) (x)
  7. #endif
  8. #endif
    添加nand_pc.c中用到的那些宏定义

点击(此处)折叠或打开

  1. #define NAND_DISABLE_CE() (NFCONT_REG |= (1 << 1))
  2. #define NAND_ENABLE_CE() (NFCONT_REG &= ~(1 << 1))
  3. #define NF_TRANSRnB() do { while(!(NFSTAT_REG & (1 << 0))); } while(0)
  4. #define CFG_PHY_UBOOT_BASE CONFIG_SYS_PHY_UBOOT_BASE
    9.再次编译。使用make smdk6410_config; make ;生成u-boot-nand.bin,放到开发板上。
   这次能够从nandflash启动了。^@^
附加:通过网络烧写到nandflash;
tftp 50000000 u-boot-nand.bin;
nand erase;/*擦除nandflash*/
nand scrub;/*标记坏块*/
nand write 50000000 0 40000 /*写在0~40000 地址之间*/















阅读(1993) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~