u-boot-2012.04.01移植到TQ2440(六):支持NAND FLASH啓動

一、    支持NAND FLASH啓動

新版u-boot在鏈接時加了“-pie”選項

-pie

           Produce a position independentexecutable on targets which support it. For predictable results, you must also specify the same set of optionsthat were used to generate code (-fpie, -fPIE, or model suboptions) when youspecify this option.

產生的代碼中,沒有絕對地址,全部使用相對地址,故而代碼可以被加載器加載到內存的任意

位置,都可以正確的執行。

最終u-boot.bin中多了這些段

.rel.dyn : {

         __rel_dyn_start = .;

         *(.rel*)

         __rel_dyn_end = .;

  }

 

  .dynsym : {

         __dynsym_start = .;

         *(.dynsym)

  }

從NOR FLASH把代碼複製到SDRAM,程序的鏈接地址是0,訪問全局變量、靜態變量、調用函數時是使用基於0地址編譯得到的地址,現在把程序複製到了SDRAM(0x3000000),需要修改代碼,把原來的地址改爲新地址。這樣太複雜了,我還是使用老版本的方法。

去掉“-pie”選項,在u-boot源碼搜索“-pie”

root@zjh:/home/work/u-boot-2012.04.01#grep "\-pie" . -nR

./doc/README.arm-relocation:3:Atarch level: add linker flag -pie

./arch/x86/config.mk:43:LDFLAGS_FINAL+= --gc-sections -pie

./arch/arm/config.mk:75:LDFLAGS_u-boot+= -pie

去除arch/arm/config.mk:75:LDFLAGS_u-boot += -pie中的“-pie”

# needed for relocation

ifndef CONFIG_NAND_SPL

#LDFLAGS_u-boot +=-pie

endif

修改配置文件include\configs\tq2440.h,給u-boot分配512KB

#define CONFIG_SYS_TEXT_BASE 0x33f80000

增加文件board\tq2440\nand_read_ll.c並修改相應的Makefile

COBJS   := tq2440.onand_read_ll.o

Nand_read_ll.c文件內容如下:

/* NAND FLASH控制器 */

#define NFCONF(*((volatile unsigned long *)0x4E000000))

#define NFCONT(*((volatile unsigned long *)0x4E000004))

#define NFCMMD(*((volatile unsigned char *)0x4E000008))

#define NFADDR(*((volatile unsigned char *)0x4E00000C))

#define NFDATA(*((volatile unsigned char *)0x4E000010))

#define NFSTAT(*((volatile unsigned char *)0x4E000020))

 

static intisBootFromNorFlash(void)

{

  volatile int *p = (volatile int *)0;

  int val;

 

  val = *p;

  *p = 0x12345678;

  if (*p == 0x12345678) {

         /* 寫成功,nand啓動 */

         *p = val;

         return 0;

  } else {

         /* NOR不能像內存一樣寫 */

         return 1;

  }

}

 

voidclear_bss(void)

{

  extern int __bss_start, __bss_end__;

  int *p = &__bss_start;

 

  for (; p < &__bss_end__; p++)

         *p = 0;

}

 

void nand_init_ll(void)

{

#define TACLS   0

#defineTWRPH0  1

#defineTWRPH1  0

  /* 設置時序 */

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

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

  NFCONT =(1<<4)|(1<<1)|(1<<0);    

}

 

static voidnand_select(void)

{

  NFCONT &= ~(1<<1);

}

 

static voidnand_deselect(void)

{

  NFCONT |= (1<<1);    

}

 

static voidnand_cmd(unsigned char cmd)

{

  volatile int i;

  NFCMMD = cmd;

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

}

 

static voidnand_addr(unsigned int addr)

{

  unsigned int col  = addr % 2048;

  unsigned int page = addr / 2048;

  volatile int i;

 

  NFADDR = col & 0xff;

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

  NFADDR = (col >> 8) & 0xff;

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

 

  NFADDR = page & 0xff;

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

  NFADDR = (page >> 8) & 0xff;

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

  NFADDR = (page >> 16) & 0xff;

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

}

 

static voidnand_wait_ready(void)

{

  while (!(NFSTAT & 1));

}

 

static unsignedchar nand_data(void)

{

  return NFDATA;

}

 

voidnand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len)

{

  int col = addr % 2048;

  int i = 0;

        

  /* 1. 選中 */

  nand_select();

 

  while (i < len) {

         /* 2. 發出讀命令00h */

         nand_cmd(0x00);

 

         /* 3. 發出地址(5步發出) */

         nand_addr(addr);

 

         /* 4. 發出讀命令30h */

         nand_cmd(0x30);

 

         /* 5. 判斷狀態 */

         nand_wait_ready();

 

         /* 6. 讀數據 */

         for (; (col < 2048) && (i< len); col++) {

                buf[i] = nand_data();

                i++;

                addr++;

         }

        

         col = 0;

  }

 

  /* 7. 取消選中 */           

  nand_deselect();

}

 

voidcopy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)

{

  int i = 0;

 

  /* 如果是NOR啓動 */

  if (isBootFromNorFlash()) {

         while (i < len) {

                dest[i] = src[i];

                i++;

         }

  } else {

         nand_init_ll();

         nand_read_ll((unsigned int)src, dest,len);

  }

}

修改arch\arm\cpu\arm920t\start.S

call_board_init_f:

    ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)

    bic sp, sp, #7 /* 8-byte alignment for ABIcompliance */

    ldr r0,=0x00000000

    ldr r1, _TEXT_BASE

    ldr r2, _bss_start_ofs

    bl copy_code_to_sdram

    bl clear_bss

    ldr pc, = board_init_f  /* 跳轉到SDRAM */

.globl second

second:

/* 調用第2階段的代碼 */

       bl board_init_r

註釋掉以下代碼

#if 0

       .globl    relocate_code

relocate_code:

       mov      r4, r0   /* save addr_sp */

       mov      r5, r1   /* save addr of gd */

       mov      r6, r2   /* save addr of destination */

 

       /* Set up the stack                                              */

stack_setup:

       mov      sp, r4

 

       adr r0, _start

       cmp      r0, r6

       beq       clear_bss          /* skip relocation */

       mov      r1, r6                 /* r1 <- scratch forcopy_loop */

       ldr  r3, _bss_start_ofs

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

 

copy_loop:

       ldmia    r0!, {r9-r10}            /* copy from source address[r0]    */

       stmia    r1!, {r9-r10}            /* copy to   target address [r1]    */

       cmp      r0, r2                 /* until source end address[r2]    */

       blo copy_loop

 

#ifndef CONFIG_SPL_BUILD

       /*

        * fix .rel.dynrelocations

        */

       ldr  r0, _TEXT_BASE            /* r0 <- Text base */

       sub       r9, r6, r0           /* r9 <- relocation offset */

       ldr  r10,_dynsym_start_ofs   /* r10 <- sym tableofs */

       add       r10, r10, r0             /* r10 <- sym table in FLASH */

       ldr  r2,_rel_dyn_start_ofs      /* r2 <- reldyn start ofs */

       add       r2, r2, r0           /* r2 <- rel dyn start in FLASH */

       ldr  r3, _rel_dyn_end_ofs       /* r3 <- rel dyn end ofs */

       add       r3, r3, r0           /* r3 <- rel dyn end in FLASH */

fixloop:

       ldr  r0, [r2]              /* r0 <- location to fix up, INFLASH! */

       add       r0, r0, r9           /* r0 <- location to fix up in RAM*/

       ldr  r1, [r2, #4]

       and       r7, r1, #0xff

       cmp      r7, #23                     /* relative fixup? */

       beq       fixrel

       cmp      r7, #2                 /* absolute fixup? */

       beq       fixabs

       /* ignore unknown type of fixup */

       b     fixnext

fixabs:

       /* absolute fix: set location to (offset) symbol value */

       mov      r1, r1, LSR #4         /* r1 <- symbol index in .dynsym */

       add       r1, r10, r1        /* r1 <- address of symbol in table*/

       ldr  r1, [r1, #4]              /* r1 <- symbol value */

       add       r1, r1, r9           /* r1 <- relocated sym addr */

       b     fixnext

fixrel:

       /* relative fix: increase location by offset */

       ldr  r1, [r0]

       add       r1, r1, r9

fixnext:

       str  r1, [r0]

       add       r2, r2, #8          /* each rel.dyn entry is 8 bytes */

       cmp      r2, r3

       blo fixloop

#endif

 

clear_bss:

#ifndef CONFIG_SPL_BUILD

       ldr  r0, _bss_start_ofs

       ldr  r1, _bss_end_ofs

       mov      r4, r6                 /* reloc addr */

       add       r0, r0, r4

       add       r1, r1, r4

       mov      r2, #0x00000000         /* clear                         */

 

clbss_l:str  r2, [r0]              /*clear loop...                  */

       add       r0, r0, #4

       cmp      r0, r1

       bne       clbss_l

 

       bl coloured_LED_init

       bl red_led_on

#endif

#endif

修改arch\arm\lib\board.c中的函數board_init_f

//addr -=gd->mon_len;

//addr &=~(4096 - 1);

addr =CONFIG_SYS_TEXT_BASE;

注視最後的重定位,並跳轉到剛纔定義的second

//relocate_code(addr_sp,id, addr);

second(id, addr);

修改鏈接腳本arch\arm\cpu\u-boot.lds把start.o、nand_read_ll.o、lowlevel_init.o編譯到前面4k

CPUDIR/start.o (.text)

board/tq2440/libtq2440.o(.text)

重新編譯,燒到NAND FLASH

TQ2440 # nand erase 040000;tftp 32000000 u-boot.bin;nand write 32000000 0 40000

 

NAND erase: device 0 offset0x0, size 0x40000

Erasing at 0x20000 -- 100%complete.

OK

dm9000 i/o: 0x20000000, id:0x90000a46

DM9000: running in 16 bitmode

MAC: 00:0c:29:4d:e4:f4

Using dm9000 device

TFTP from server172.28.12.60; our IP address is 172.28.12.10

Filename 'u-boot.bin'.

Load address: 0x32000000

Loading: T ###############

done

Bytes transferred = 208508(32e7c hex)

 

NAND write: device 0 offset0x0, size 0x40000

 262144 bytes written: OK

TQ2440 #

從NAND FLASH啓動

U-Boot 2012.04.01 (Dec 312012 - 11:57:16)

 

CPUID: 32440001

FCLK:      400 MHz

HCLK:      100 MHz

PCLK:       50 MHz

DRAM:  64 MiB

WARNING: Caches not enabled

Flash: *** failed ***

### ERROR ### Please RESETthe board ###

由於從NAND啓動,CPU檢測不到NOR FLASH,具體代碼如下arch\arm\lib\board.c

#if!defined(CONFIG_SYS_NO_FLASH)

  puts("Flash: ");

 

  flash_size = flash_init();

  if (flash_size > 0) {

# ifdefCONFIG_SYS_FLASH_CHECKSUM

         char *s = getenv("flashchecksum");

 

         print_size(flash_size, "");

         /*

          * Compute and printflash CRC if flashchecksum is set to 'y'

          *

          * NOTE: Maybe weshould add some WATCHDOG_RESET()? XXX

          */

         if (s && (*s == 'y')) {

                printf(" CRC: %08X", crc32(0,

                       (const unsigned char *) CONFIG_SYS_FLASH_BASE,

                       flash_size));

         }

         putc('\n');

# else     /* !CONFIG_SYS_FLASH_CHECKSUM */

         print_size(flash_size, "\n");

# endif /*CONFIG_SYS_FLASH_CHECKSUM */

  } else {

         puts(failed);

         hang();

  }

#endif

void hang(void)

{

  puts("### ERROR ### Please RESET the board ###\n");

  for (;;);

}

我們直接註釋掉上面的hang();

# endif /*CONFIG_SYS_FLASH_CHECKSUM */

  } else {

         puts(failed);

         //hang();

  }

#endif

重新編譯,燒到NAND FLASH,從NAND啓動

U-Boot 2012.04.01 (Dec 31 2012- 12:27:20)

 

CPUID: 32440001

FCLK:      400 MHz

HCLK:      100 MHz

PCLK:       50 MHz

DRAM:  64 MiB

WARNING: Caches not enabled

Flash: *** failed ***

NAND:  256 MiB

卡在這裏,檢查後發現修改start.S的時候調用第二階段代碼沒有重新設置棧指針,做如下修改

board.c中的board_init_f函數

//relocate_code(addr_sp, id,addr);

  second(id, addr, addr_sp);

start.S

second:

  mov sp, r2 /*重新設置棧指針 */

/* 調用第2階段的代碼 */

  bl board_init_r

重新編譯,燒到NAND,從NAND啓動

U-Boot 2012.04.01 (Dec 312012 - 12:31:58)

 

CPUID: 32440001

FCLK:      400 MHz

HCLK:      100 MHz

PCLK:       50 MHz

DRAM:  64 MiB

WARNING: Caches not enabled

Flash: *** failed ***

NAND:  256 MiB

In:    serial

Out:   serial

Err:   serial

Net:   dm9000

TQ2440 #

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章