TQ2440 u-boot-2012.10移植二支持NAND啓動

五一就要勞動,寫點代碼與大家分享哈哈。繼 u-boot-2012.10移植一串口正常輸出,繼續修改代碼支持單板NAND啓動。最後直接用NOR Flash裏的u-boot燒寫自己移植的u-boot到NAND,方便電腦沒有並口或手上沒有openjtag,照樣能移植u-boot,當然有openjtag更方便。

開發環境:
系統:ubuntu 10.04.4
單板:tq2440
NAND FLASH:K9F1216U0A 256MB
NOR Flash:AM29LV160A 2MB
SDRAM:HY57V561620 x2 64MB
NET:DM9000AEP
編譯器:arm-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
搭建開發環境詳見ubuntu 10.04.4開發環境配置。
目標:
1.支持NOR Flash啓動,串口正常輸出
2.支持NAND啓動
3.支持DM9000網卡
4.添加u-boot菜單
5.裁剪u-boot及製作補丁

NOR Flash是內存接口,能直接運行程序,但是NAND Flash地址線都沒有,是不能直接跑程序的。熟悉三星片子的人都知道s3c2440 NAND啓動時,CPU會自動從NAND Flash讀取前4KB到SRAM,同時把這段片內SRAM映射到nGCS0片選空間即0x0000 0000。而ARM架構的CPU第一條指令是從0地址開始執行的。相當於片內SRAM充當一個載體,把NAND前4KB映射到0地址,CPU開始執行NAND前4KB內容。

change@change:~$ cd Si/TQ2440/u-boot-2012.10/
change@change:~/Si/TQ2440/u-boot-2012.10$ ls u-boot.bin -l
-rw-r--r-- 1 change change 368508 2013-04-30 21:49 u-boot.bin
change@change:~/Si/TQ2440/u-boot-2012.10$ 

看到生成的u-boot.bin有360KB左右,這個放在NOR Flash裏能直接啓動,但是不利於NAND啓動。u-boot運行後,不管是NNAD還是NOR Flash啓動,都會進行重定位,即把代碼拷到內存運行,就像PC機一樣程序都是在內存運行的。那麼支持NAND啓動的u-boot,重定位之前代碼必須小於4KB,才能跑起來。分析現在較新的u-boot源碼(以後在另外文章分析),代碼連接時加-pie選項,重定位成位置無關代碼,搞的很高級,不利於像S3C2440這樣片內SRAM十分有限的SOC跑。這裏修改重定位代碼,支持NAND啓動。

1.去掉-pie選項,不需要附加“*(.rel*)”、“*(.dynsm)”等信息

change@change:~/Si/TQ2440/u-boot-2012.10$ grep "\-pie" * -nR
arch/x86/config.mk:43:LDFLAGS_FINAL += --gc-sections -pie
arch/arm/config.mk:88:LDFLAGS_u-boot += -pie
doc/README.arm-relocation:3:At arch level: add linker flag -pie
change@change:~/Si/TQ2440/u-boot-2012.10$  vim arch/arm/config.mk

去掉88行LDFLAGS_u-boot += -pie

2.參考以前update寫的start.S init.c修改代碼

在arch/arm/cpu/arm920t/start.S:205行增加如下代碼

[plain] view plaincopy
  1. ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)/*sp =30000f80*/  
  2. bic sp, sp, #7 /* 8-byte alignment for ABI compliance */  
  3.   
  4. bl nand_init_ll  
  5. mov r0, #0  
  6. //ldr r1, =_start  
  7. ldr r1, _TEXT_BASE  
  8. //dr r2, =__bss_start  
  9. //sub r2, r2, r1  
  10. ldr r2, _bss_start_ofs  
  11. bl copy_code_to_sdram  
  12. bl clear_bss  
  13.   
  14. ldr pc, =call_board_init_f  

arch/arm/cpu/arm920t/start.S221:註釋掉下面2行

//ldr  sp, =(CONFIG_SYS_INIT_SP_ADDR)
//bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

在arch/arm/cpu/arm920t/start.S:226行增加如下代碼

/*unsigned int id */
ldr r1, _TEXT_BASE//*link addres
ldr sp, base_sp 

bl board_init_r//*the second step

用自己的重定位代碼,去掉u-boot自帶的arch/arm/cpu/arm920t/start.S 231:

[plain] view plaincopy
  1. /*------------------------------------------------------------------------------*/  
  2.   
  3. /*  
  4.  * void relocate_code (addr_sp, gd, addr_moni)  
  5.  *  
  6.  * This "function" does not return, instead it continues in RAM  
  7.  * after relocating the monitor code.  
  8.  *  
  9.  */  
  10.     .globl  relocate_code  
  11. relocate_code:  
  12.     mov r4, r0  /* save addr_sp */  
  13.     mov r5, r1  /* save addr of gd */  
  14.     mov r6, r2  /* save addr of destination */  
  15.   
  16.     /* Set up the stack                         */  
  17. stack_setup:  
  18.     mov sp, r4  
  19.   
  20.     adr r0, _start  
  21.     cmp r0, r6  
  22.     moveq   r9, #0      /* no relocation. relocation offset(r9) = 0 */  
  23.     beq clear_bss       /* skip relocation */  
  24.     mov r1, r6          /* r1 <- scratch for copy_loop */  
  25.     ldr r3, _bss_start_ofs  
  26.     add r2, r0, r3      /* r2 <- source end address      */  
  27.   
  28. copy_loop:  
  29.     ldmia   r0!, {r9-r10}       /* copy from source address [r0]    */  
  30.     stmia   r1!, {r9-r10}       /* copy to   target address [r1]    */  
  31.     cmp r0, r2          /* until source end address [r2]    */  
  32.     blo copy_loop  
  33.   
  34. #ifndef CONFIG_SPL_BUILD  
  35.     /*  
  36.      * fix .rel.dyn relocations  
  37.      */  
  38.     ldr r0, _TEXT_BASE      /* r0 <- Text base */  
  39.     sub r9, r6, r0      /* r9 <- relocation offset */  
  40.     ldr r10, _dynsym_start_ofs  /* r10 <- sym table ofs */  
  41.     add r10, r10, r0        /* r10 <- sym table in FLASH */  
  42.     ldr r2, _rel_dyn_start_ofs  /* r2 <- rel dyn start ofs */  
  43.     add r2, r2, r0      /* r2 <- rel dyn start in FLASH */  
  44.     ldr r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */  
  45.     add r3, r3, r0      /* r3 <- rel dyn end in FLASH */  
  46. fixloop:  
  47.     ldr r0, [r2]        /* r0 <- location to fix up, IN FLASH! */  
  48.     add r0, r0, r9      /* r0 <- location to fix up in RAM */  
  49.     ldr r1, [r2, #4]  
  50.     and r7, r1, #0xff  
  51.     cmp r7, #23         /* relative fixup? */  
  52.     beq fixrel  
  53.     cmp r7, #2          /* absolute fixup? */  
  54.     beq fixabs  
  55.     /* ignore unknown type of fixup */  
  56.     b   fixnext  
  57. fixabs:  
  58.     /* absolute fix: set location to (offset) symbol value */  
  59.     mov r1, r1, LSR #4      /* r1 <- symbol index in .dynsym */  
  60.     add r1, r10, r1     /* r1 <- address of symbol in table */  
  61.     ldr r1, [r1, #4]        /* r1 <- symbol value */  
  62.     add r1, r1, r9      /* r1 <- relocated sym addr */  
  63.     b   fixnext  
  64. fixrel:  
  65.     /* relative fix: increase location by offset */  
  66.     ldr r1, [r0]  
  67.     add r1, r1, r9  
  68. fixnext:  
  69.     str r1, [r0]  
  70.     add r2, r2, #8      /* each rel.dyn entry is 8 bytes */  
  71.     cmp r2, r3  
  72.     blo fixloop  
  73. #endif  
  74.   
  75. clear_bss:  
  76. #ifndef CONFIG_SPL_BUILD  
  77.     ldr r0, _bss_start_ofs  
  78.     ldr r1, _bss_end_ofs  
  79.     mov r4, r6          /* reloc addr */  
  80.     add r0, r0, r4  
  81.     add r1, r1, r4  
  82.     mov r2, #0x00000000     /* clear                */  
  83.   
  84. clbss_l:cmp r0, r1          /* clear loop... */  
  85.     bhs clbss_e         /* if reached end of bss, exit */  
  86.     str r2, [r0]  
  87.     add r0, r0, #4  
  88.     b   clbss_l  
  89. clbss_e:  
  90.   
  91.     bl coloured_LED_init  
  92.     bl red_led_on  
  93. #endif  
以上代碼全部去掉,在之前已重定位
接着在board/samsung/TQ2440/目錄下增加init.c文件,board/samsung/TQ2440/init.c:

[plain] view plaincopy
  1. /* NAND FLASH控制器 */  
  2. #define NFCONF (*((volatile unsigned long *)0x4E000000))  
  3. #define NFCONT (*((volatile unsigned long *)0x4E000004))  
  4. #define NFCMMD (*((volatile unsigned char *)0x4E000008))  
  5. #define NFADDR (*((volatile unsigned char *)0x4E00000C))  
  6. #define NFDATA (*((volatile unsigned char *)0x4E000010))  
  7. #define NFSTAT (*((volatile unsigned char *)0x4E000020))  
  8.   
  9. /* GPIO */  
  10. #define GPHCON              (*(volatile unsigned long *)0x56000070)  
  11. #define GPHUP               (*(volatile unsigned long *)0x56000078)  
  12.   
  13. /* UART registers*/  
  14. #define ULCON0              (*(volatile unsigned long *)0x50000000)  
  15. #define UCON0               (*(volatile unsigned long *)0x50000004)  
  16. #define UFCON0              (*(volatile unsigned long *)0x50000008)  
  17. #define UMCON0              (*(volatile unsigned long *)0x5000000c)  
  18. #define UTRSTAT0            (*(volatile unsigned long *)0x50000010)  
  19. #define UTXH0               (*(volatile unsigned char *)0x50000020)  
  20. #define URXH0               (*(volatile unsigned char *)0x50000024)  
  21. #define UBRDIV0             (*(volatile unsigned long *)0x50000028)  
  22.   
  23. #define TXD0READY   (1<<2)  
  24.   
  25.   
  26. void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len);  
  27.   
  28.   
  29. static int isBootFromNorFlash(void)  
  30. {  
  31.     volatile int *p = (volatile int *)0;  
  32.     int val;  
  33.   
  34.     val = *p;  
  35.     *p = 0x12345678;  
  36.     if (*p == 0x12345678)  
  37.     {  
  38.         /* 寫成功, 是nand啓動 */  
  39.         *p = val;  
  40.         return 0;  
  41.     }  
  42.     else  
  43.     {  
  44.         /* NOR不能像內存一樣寫 */  
  45.         return 1;  
  46.     }  
  47. }  
  48.   
  49. void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)  
  50. {     
  51.     int i = 0;  
  52.       
  53.     /* 如果是NOR啓動 */  
  54.     if (isBootFromNorFlash())  
  55.     {  
  56.         while (i < len)  
  57.         {  
  58.             dest[i] = src[i];  
  59.             i++;  
  60.         }  
  61.     }  
  62.     else  
  63.     {  
  64.         //nand_init();  
  65.         nand_read_ll((unsigned int)src, dest, len);  
  66.     }  
  67. }  
  68.   
  69. void clear_bss(void)  
  70. {  
  71.     extern int __bss_start, __bss_end__;  
  72.     int *p = &__bss_start;  
  73.       
  74.     for (; p < &__bss_end__; p++)  
  75.         *p = 0;  
  76. }  
  77.   
  78. void nand_init_ll(void)  
  79. {  
  80. #define TACLS   0  
  81. #define TWRPH0  1  
  82. #define TWRPH1  0  
  83.     /* 設置時序 */  
  84.     NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);  
  85.     /* 使能NAND Flash控制器, 初始化ECC, 禁止片選 */  
  86.     NFCONT = (1<<4)|(1<<1)|(1<<0);      
  87. }  
  88.   
  89. static void nand_select(void)  
  90. {  
  91.     NFCONT &= ~(1<<1);      
  92. }  
  93.   
  94. static void nand_deselect(void)  
  95. {  
  96.     NFCONT |= (1<<1);   
  97. }  
  98.   
  99. static void nand_cmd(unsigned char cmd)  
  100. {  
  101.     volatile int i;  
  102.     NFCMMD = cmd;  
  103.     for (i = 0; i < 10; i++);  
  104. }  
  105.   
  106. static void nand_addr(unsigned int addr)  
  107. {  
  108.     unsigned int col  = addr % 2048;  
  109.     unsigned int page = addr / 2048;  
  110.     volatile int i;  
  111.   
  112.     NFADDR = col & 0xff;  
  113.     for (i = 0; i < 10; i++);  
  114.     NFADDR = (col >> 8) & 0xff;  
  115.     for (i = 0; i < 10; i++);  
  116.       
  117.     NFADDR  = page & 0xff;  
  118.     for (i = 0; i < 10; i++);  
  119.     NFADDR  = (page >> 8) & 0xff;  
  120.     for (i = 0; i < 10; i++);  
  121.     NFADDR  = (page >> 16) & 0xff;  
  122.     for (i = 0; i < 10; i++);      
  123. }  
  124.   
  125. static void nand_wait_ready(void)  
  126. {  
  127.     while (!(NFSTAT & 1));  
  128. }  
  129.   
  130. static unsigned char nand_data(void)  
  131. {  
  132.     return NFDATA;  
  133. }  
  134.   
  135. void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len)  
  136. {  
  137.     int col = addr % 2048;  
  138.     int i = 0;  
  139.           
  140.     /* 1. 選中 */  
  141.     nand_select();  
  142.   
  143.     while (i < len)  
  144.     {  
  145.         /* 2. 發出讀命令00h */  
  146.         nand_cmd(0x00);  
  147.   
  148.         /* 3. 發出地址(分5步發出) */  
  149.         nand_addr(addr);  
  150.   
  151.         /* 4. 發出讀命令30h */  
  152.         nand_cmd(0x30);  
  153.   
  154.         /* 5. 判斷狀態 */  
  155.         nand_wait_ready();  
  156.   
  157.         /* 6. 讀數據 */  
  158.         for (; (col < 2048) && (i < len); col++)  
  159.         {  
  160.             buf[i] = nand_data();  
  161.             i++;  
  162.             addr++;  
  163.         }  
  164.           
  165.         col = 0;  
  166.     }  
  167.   
  168.     /* 7. 取消選中 */         
  169.     nand_deselect();  
  170. }  
同時修改該目錄下的在Makfile,board/samsung/TQ2440/Makefile:

COBJS := smdk2410.o 改爲 COBJS:= smdk2410.o init.o 

其中lowlevel_init.S定義_TEXT_BASE:     .word  CONFIG_SYS_TEXT_BASE,是u-boot的重定位地址,搜索定義在TQ2440.h42:

//#define CONFIG_SYS_TEXT_BASE 0x0
#define CONFIG_SYS_TEXT_BASE 0x33f80000

arch/arm/lib/board.c274:增加extern ulong base_sp;//**add

arch/arm/lib/board.c448:修改如下

: base_sp = addr_sp;//**add
//relocate_code(addr_sp, id, addr);
return (unsigned int) id;// add it

arch/arm/lib/board.c382:修改如下

//addr -= gd->mon_len;
//addr &= ~(4096 - 1);
addr = _TEXT_BASE;//**add return sp to start.s

代碼部分修改的差不多了,接下來還要修改鏈接腳本,確保重定位之前的代碼編譯在最前面

在arch/arm/cpu/u-boot.lds 38:增加如下

board/samsung/TQ2440/libTQ2440.o(.text)

3.重新配置、編譯

change@change:~/Si/TQ2440/u-boot-2012.10$ make distclean 
change@change:~/Si/TQ2440/u-boot-2012.10$ make TQ2440 CROSSS_COMPILE=arm-none-linux-gnueabi- 

/bin/bash: arm-linux-gcc: command not found
make[1]: *** [lib/asm-offsets.s] Error 127
make[1]: Leaving directory `/home/change/Si/TQ2440/u-boot-2012.10'
make: *** [TQ2440] Error 2

老出現這個問題,我都指定編譯器arm-none-linux-gnueabi- ,還是報/bin/bash: arm-linux-gcc: command not found,算啦換回arm-linux-gcc-4.3.2,並設置爲默認交叉編譯鏈,其它不變

change@change:~/Si/TQ2440/u-boot-2012.10$ make distclean 
change@change:~/Si/TQ2440/u-boot-2012.10$ make TQ2440_config 
Configuring for TQ2440 board...
change@change:~/Si/TQ2440/u-boot-2012.10$ make

start.S:228: Error: internal_relocation (type: OFFSET_IMM) not fixed up
make[1]: *** [start.o] Error 1
make[1]: Leaving directory `/home/change/Si/TQ2440/u-boot-2012.10/arch/arm/cpu/arm920t'
make: *** [arch/arm/cpu/arm920t/start.o] Error 2

有錯誤,說start.S:228有錯誤,打開忘記定義了,修改如下arch/arm/cpu/arm920t/start.S112:增加

.globl base_sp
base_sp:
.long 0

change@change:~/Si/TQ2440/u-boot-2012.10$ make

ok問題解決,編譯通過,看看現在的u-boot.bin多大

change@change:~/Si/TQ2440/u-boot-2012.10$ la u-boot.bin -l
-rwxr-xr-x 1 change change 344336 2013-05-01 16:43 u-boot.bin

change@change:~/Si/TQ2440/u-boot-2012.10$ cp u-boot.bin /home/change/work/tftpboot/

4.燒寫、測試

記住這裏是燒到NAND,我用NOR Flash裏的u-boot燒寫,撥到NOR Flash啓動,設置串口 115200 8 n 1

U-Boot 2012.04.01 (Oct 25 2012 - 22:47:25)


CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB
WARNING: Caches not enabled
Flash: 0 KB
NAND:  256 MiB
*** Warning - bad CRC, using default environment


In:    serial
Out:   serial
Err:   serial
Net:   dm9000
Hit any key to stop autoboot:  0 
SMDK2410 # set ipaddr 172.16.1.111
SMDK2410 # set gatewayip 172.16.1.1
SMDK2410 # set serverip 172.16.1.132
SMDK2410 # tftp 0x32000000 u-boot.bin
dm9000 i/o: 0x20000000, id: 0x90000a46 
DM9000: running in 16 bit mode
MAC: 00:0c:29:4d:e4:f4
could not establish link
Using dm9000 device
TFTP from server 172.16.1.132; our IP address is 172.16.1.111
Filename 'u-boot.bin'.
Load address: 0x32000000
Loading: ########################
done
Bytes transferred = 344336 (54110 hex)
SMDK2410 # nand erase 0 0x80000

NAND erase: device 0 offset 0x0, size 0x80000
Erasing at 0x60000 -- 100% complete.
OK
SMDK2410 # nand write 0x32000000 0 0x80000

NAND write: device 0 offset 0x0, size 0x80000
 524288 bytes written: OK
SMDK2410 # 

單板斷電,設爲NAND啓動,串口輸出如下:

U-Boot 2012.10 (May 01 2013 - 17:20:57)


CPUID: 32440001
FCLK:  405.600 MHz
HCLK:  101.400 MHz
PCLK:   50.700 MHz
DRAM:  64 MiB

接着就卡死了,很奇怪的問題,先寫到這吧,既然串口都有輸出了,應該問題不大,下次再調調看。

發現問題了這個時鐘不是配置的,有問題,先解決時鐘問題。在board/samsung/tq2440/smdk2410.c去掉對時鐘MPLL的配置76:

 /* to reduce PLL lock time, adjust the LOCKTIME register */
 //writel(0xFFFFFF, &clk_power->locktime);

 /* configure MPLL */
 //writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
 //       &clk_power->mpllcon);

同時增加打印語句。arch/arm/lib/board.c 447:增加

puts("board_init_f over!\n");

再次編譯,燒寫輸出如下:

U-Boot 2012.10 (May 02 2013 - 15:12:15)

CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB
board_init_f over!

並且反覆重啓,時鐘是正常了,還是有問題。細細看代碼,調用u-boot第二階段代碼,需要出入參數id,但我們id是從board_init_f返回的,犯了個低級錯誤

arch/arm/lib/board.c 268:將void board_init_f(ulong bootflag)修改unsigned int board_init_f(ulong bootflag)

同時修改include/common.h 314:

void board_init_f  (ulong) __attribute__ ((noreturn));

改爲unsigned int board_init_f  (ulong);

修改後編譯OK,燒進去還是有問題,我再多加些打印語句試試。貌似問題有點怪了,加了打印語句發現bl board_init_r就沒跳轉過去,貌似運行完 board_init_f就卡死了。很鬱悶,立即換成u-boot-2012.04.01移植一遍又沒問題。再分析吧,哪位知道指點哈啊


http://blog.csdn.net/u010216127/article/details/8871525

發佈了15 篇原創文章 · 獲贊 14 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章