mini2440移植uboot 2014.04(一)


最新版的uboot添加了很多新功能,我決定在最新版代碼基礎上重新移植一遍加深理解。

我修改的代碼已經上傳到github上,地址:https://github.com/qiaoyuguo/u-boot-2014.04-mini2440.git

參考文檔: s3c2440手冊(下載地址) mini2440電路圖(下載地址

參考我的兩篇博文:

mini2440移植uboot 2011.03(上)

mini2440移植uboot 2011.03(下)

還有其他幾篇文章:

u-boot2012.04.01移植到mini2440

一步一步將uboot移植到mini2440(-)

DM9000驅動在MINI2440上的移植學習筆記

 

操作系統: debian 7.4

uboot:   u-boot-2014.04(下載地址

交叉編譯器:arm-linux-gcc 4.4.3(下載地址

 

在移植之前,最好對uboot的代碼執行流程有基本的了解,可以參考我的三篇博文:

uboot 2013.01 代碼簡析(1)開發板配置

uboot 2013.01 代碼簡析(2)第一階段初始化

uboot 2013.01 代碼簡析(3)第二階段初始化

 

(一)將smdk2410的文件夾拷貝成mini2440,步驟如下:

host@debian:~/soft/mini2440/u-boot-2014.04$ vim boards.cfg 
添加一行:
Active arm arm920t s3c24x0 friendlyarm -       mini2440         -         Qiao<qiaoyuguo2012@gmail.com>
host@debian:~/soft/mini2440/u-boot-2014.04$ mkdir board/friendlyarm
host@debian:~/soft/mini2440/u-boot-2014.04$ cp -r board/samsung/smdk2410/ board/friendlyarm/mini2440
host@debian:~/soft/mini2440/u-boot-2014.04$ mv board/friendlyarm/mini2440/smdk2410.c  board/friendlyarm/mini2440/mini2440.c
host@debian:~/soft/mini2440/u-boot-2014.04$ vim board/friendlyarm/mini2440/Makefile
將其中smdk2410.o替換成mini2440.o
host@debian:~/soft/mini2440/u-boot-2014.04$ cp include/configs/smdk2410.h  include/configs/mini2440.h

然后進行編譯:

host@debian:~/soft/mini2440/u-boot-2014.04$ make mini2440_config
host@debian:~/soft/mini2440/u-boot-2014.04$ make  CROSS_COMPILE=arm-linux-

編譯過程中最后部分的輸出信息:

  OBJCOPY u-boot.srec
  OBJCOPY u-boot.bin

(二)添加SDRAM支持

host@debian:~/soft/mini2440/u-boot-2014.04$ vim include/configs/mini2440.h 
刪除三行:
#define CONFIG_S3C2410 /* specifically a SAMSUNG S3C2410 SoC */ #define CONFIG_SMDK2410 /* on a SAMSUNG SMDK2410 Board */
#define CONFIG_SYS_TEXT_BASE 0x0
添加四行: #define CONFIG_S3C2440 /* specifically a SAMSUNG S3C2440 SoC */ #define CONFIG_MINI2440 /* on a FriendlyArm MINI2440 Board */ #define CONFIG_SKIP_LOWLEVEL_INIT
#define CONFIG_SYS_TEXT_BASE 0x33f80000

arch/arm/cpu/arm920t/start.S中的包含有看門狗、中斷以及時鍾的配置,而s3c2410和s3c2440的部分配置不一樣,所以需要適當的進行修改

首先需要禁止看門狗,根據s3c2440芯片手冊(下載地址) ,看門狗寄存器地址如下:

WTCON 0x53000000 Watchdog timer control
WTDAT 0x53000004 Watchdog timer data WTCNT 0x53000008 Watchdog timer count

我們只需要禁止看門狗,這樣就只需要考慮WTCON寄存器就可以,從手冊的462頁中可以看到WTCON詳細信息

當前的uboot代碼已經滿足了禁止看門狗的功能,其代碼如下(忽略無關的宏定義,僅列出我們所關心的代碼,下同):

define pWTCON    0x53000000
    ldr    r0, =pWTCON
    mov    r1, #0x0
    str    r1, [r0]

這段代碼將0加載到0x53000000處,從而禁止了看門狗(詳細每位數據的含義可以查看手冊)。

接着是關於中斷的配置,根據s3c2440芯片手冊56頁,中斷相關寄存器地址如下:

復制代碼
SRCPND 0X4A000000 R/W Interrupt request status
INTMOD 0X4A000004 W Interrupt mode control
INTMSK 0X4A000008 R/W Interrupt mask control
PRIORITY 0X4A00000C W IRQ priority control 
INTPND 0X4A000010 R/W Interrupt request status
INTOFFSET 0X4A000014 R Interrupt request source offset
SUBSRCPND 0X4A000018 R/W Sub source pending INTSUBMSK 0X4A00001C R/W Interrupt sub mask
復制代碼

我們需要配置中斷屏蔽寄存器(INTMSK,見手冊388-389頁)和子中斷屏蔽寄存器(INTSUBMSK,見手冊395頁),可以看到當前代碼如下:

復制代碼
#  define INTMSK    0x4A000008    /* Interrupt-Controller base addresses */
#  define INTSUBMSK    0x4A00001C
        mov    r1, #0xffffffff
        ldr    r0, =INTMSK
        str    r1, [r0]
# if defined(CONFIG_S3C2410)
      ldr r1, =0x3ff ldr r0, =INTSUBMSK str r1, [r0] # endif
復制代碼

該代碼中斷屏蔽寄存器的代碼仍然使用於s3c2440,但是需要添加子中斷屏蔽寄存器的代碼,可以在s3c2410相關代碼中添加elseif語句:

#elseif defined(CONFIG_S3C2440)
       ldr     r1, =0x7fff
       ldr     r0, =INTSUBMSK
       str     r1, [r0]

根據手冊,s3c2440中子中斷屏蔽寄存器有效位數是低15位,所以我們用0x7fff,使得低15位為1(1表示屏蔽該中斷,0表示該中斷可用).

接着是時鍾分頻配置,現有代碼如下:

#  define CLKDIVN   0x4C000014  /* clock divisor register */

/* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0]

上面代碼中提到了FCLK、HCLK、PCLK(參見手冊242頁),FCLK用於arm920T,HCLK用於AHB,可以用於USB、DMA、LCD、中斷和內存控制器等。

PCLK用於APB,可以用於看門狗、IIS、I2C、SPI、ADC、UART、GPIO、RTC等。

當前代碼默認采用1:2:4的分頻配置,但是mini2440我們要將cpu頻率配置成400MHz。

根據手冊33頁,FCLK最大只能是400MHz,HCLK最大只能是136MHz,PCLK最大只能是68MHz。

要滿足時鍾頻率的限制,可以將分頻配置成1:4:8,那么FCLK=400MHz,HCLK等於100MHz,PCLK等於50MHz,都能滿足要求。

關於CLKDIVN寄存器的定義,可以查看手冊258頁,給出了下面的信息:

CLKDIVN 0x4C000014 R/W Clock divider control register 

HDIVN [2:1] 10 : HCLK = FCLK/4 when CAMDIVN[9] = 0,HCLK= FCLK/8 when CAMDIVN[9] = 1.
PDIVN [0]  如果為0: PCLK has the clock same as the HCLK/1 如果為1: PCLK has the clock same as the HCLK/2.

而CAMDIVN寄存器定義可以查看手冊259頁,能看到默認所有位等於0,這樣只需要配置HDIVN為10,PDIVN為1既可。CLKDIVN的值應該是0x101=5

手冊243頁中提到如果HDIVN不是0,那么需要將cpu總線模式從"fast bus mode"改成“asynchronous bus mode"

然后需要對PLL進行配置,才能得到405MHz的輸出頻率,根據手冊255頁,可以得到PLL相關寄存器信息:

復制代碼
MPLLCON 0x4C000004 R/W MPLL configuration register 0x00096030
UPLLCON 0x4C000008 R/W UPLL configuration register 0x0004d030

PLLCON Bit   Description
MDIV [19:12] Main divider control 
PDIV [9:4] Pre-divider control 
SDIV [1:0] Post divider control
input freq output freq  MDIV      PDIV   SDIV
12.0000MHz 48.00 MHz   56(0x38)  2      2
12.0000MHz 405.00 MHz   127(0x7f) 2      1
復制代碼

此處MPLL和UPLL分別用於系統時鍾和USB時鍾,我們將MPLL輸出設定成405MHz, UPLL輸出設定成48MHz.

手冊255頁中還提到,當寫入UPLL和MPLL時,需要先寫UPLL后寫MPLL。

 

 我修改后的代碼內容如下:

復制代碼
#if defined(CONFIG_S3C2440)
    /* FCLK:HCLK:PCLK = 1:4:8 */
    ldr    r0, =CLKDIVN
    mov    r1, #5
    str    r1, [r0]

    /* change bus mode from "fast bus mode" to "asynchronous bus mode" */
    mrc p15, 0, r1, c1, c0, 0 /*read ctrl regester*/
    orr r1, r1, #0xc0000000 /*asynchronous*/
    mcr p15, 0, r1, c1, c0, 0 /*write ctrl register*/

#define S3C2440_MPLL_400MHZ (0x7f<<12 | 0x2<<4 | 0x1) /* refer to s3c2440.pdf page 255 */
#define S3C2440_UPLL_48MHZ  (0x38<<12 | 0x2<<4 | 0x2)
#define MPLLCON 0x4c000004
#define UPLLCON 0x4c000008
    ldr r0, =UPLLCON
    ldr r1, =S3C2440_UPLL_48MHZ 
    str r1, [r0]

    ldr r0, =MPLLCON
    ldr r1, =S3C2440_MPLL_400MHZ 
    str r1, [r0]
#else
    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr    r0, =CLKDIVN
    mov    r1, #3
    str    r1, [r0]
#endif

如果沒有定義CONFIG_SKIP_LOWLEVEL_INIT, 在執行完這部分代碼后會跳轉到start.S中的cpu_init_crit,

然后又跳轉到board/friendlyarm/mini2440/lowlevel_init.S中的lowlevel_init函數,該函數中包含對sdram連接的BANK0-BANk7

以及SDRAM刷新頻率進行配置(可以參考2440手冊203-210頁)。

但是我們當前代碼中定義了CONFIG_SKIP_LOWLEVEL_INIT,所以cpu_init_crit不會執行,暫時也不需要考慮這部分代碼。

 

接着調用_main,_main位於arch/arm/lib/crt0.S文件中,它會依次調用board_init_f和relocate_code.

在relocate_code中執行重定位代碼,然后會根據其lr寄存器中的here地址跳轉回arch/arm/lib/crt0.S,執行here標簽下的內容(主要是board_init_r函數).

修改mini2440.c中的時鍾頻率,跟上面的匯編代碼保持一致:

host@debian:~/soft/mini2440/u-boot-2014.04$ vim board/friendlyarm/mini2440/mini2440.c 
host@debian:~/soft/mini2440/u-boot-2011.03$ vim board/friendlyarm/mini2440/mini2440.c
#define FCLK_SPEED 2

#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1
#elif FCLK_SPEED==2 /* Fout = 405MHz */
#define M_MDIV 0x7F
#define M_PDIV 0x2
#define M_SDIV 0x1
#endif
 
#define USB_CLOCK 2

#elif USB_CLOCK==1
#define U_M_MDIV 0x48
#define U_M_PDIV 0x3
#define U_M_SDIV 0x2
#elif USB_CLOCK==2 /* Fout = 48MHz */
#define U_M_MDIV 0x38
#define U_M_PDIV 0x2
#define U_M_SDIV 0x2
#endif
 
int board_init (void)
{
     ......
     gd->bd->bi_arch_number = MACH_TYPE_MINI2440;
     ......
}

此時,執行編譯命令:

make CROSS_COMPILE=arm-linux-

會出來很多編譯錯誤:

復制代碼
drivers/mtd/nand/s3c2410_nand.c: In function 's3c2410_hwcontrol':
drivers/mtd/nand/s3c2410_nand.c:44: warning: implicit declaration of function 's3c2410_get_base_nand'
drivers/mtd/nand/s3c2410_nand.c:44: warning: initialization makes pointer from integer without a cast
drivers/mtd/nand/s3c2410_nand.c:59: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c:59: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c:62: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c:62: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c: In function 's3c2410_dev_ready':
drivers/mtd/nand/s3c2410_nand.c:72: warning: initialization makes pointer from integer without a cast
drivers/mtd/nand/s3c2410_nand.c:74: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c: In function 'board_nand_init':
drivers/mtd/nand/s3c2410_nand.c:116: warning: initialization makes pointer from integer without a cast
drivers/mtd/nand/s3c2410_nand.c:137: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c:140: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c:141: error: dereferencing pointer to incomplete type
make[1]: *** [drivers/mtd/nand/s3c2410_nand.o] 錯誤 1
復制代碼

查看代碼可以知道是因為從board_init_r->nand_init經過一長串的調用后調用s3c2410_hwcontrol。

當前代碼中在include/configs/mini2440.h中定義了CONFIG_NAND_S3C2410,所以使用了drivers/mtd/nand/s3c2410_nand.c中的代碼。

上面的錯誤是因為未定義s3c2410_get_base_nand引起的,而該函數定義位於arch/arm/include/asm/arch-s3c24x0/s3c2410.h中,

在arch/arm/include/asm/arch-s3c24x0/s3c24x0_cpu.h中有下面內容:

  #elif defined CONFIG_S3C2440
     #include <asm/arch/s3c2440.h>

實際上當前代碼中包含的文件是arch/arm/include/asm/s3c24x0/s3c2440.h,該頭文件中沒有 s3c2410_get_base_nand函數的定義,由於s3c2410.h和s3c2440.h中代碼基本一致,直接包含將代碼中 s3c2440.h修改成s3c2410.h即可。

另外幾個錯誤是因為s3c2410_nand未定義引起的,可以在arch/arm/include/asm/arch-s3c24x0/s3c24x0.h中將s3c2440_nand修改成s3c2410_nand即可。

然后重新編譯:

make CROSS_COMPILE=arm-linux-

參考《openocd+jlink為mini2440調試u-boot》配置好openocd,然后打開串口:

sudo minicom

在另一個控制台執行下面命令:

sudo openocd -f interface/jlink.cfg  -f board/mini2440.cfg
telnet localhost 4444
halt
init_2440
load_image /home/host/soft/mini2440/u-boot-2014.04/u-boot.bin 0x33f80000 bin 
resume 0x33f80000

其中/home/host/soft/mini2440/u-boot-2014.04/u-boot.bin是我的uboot存放路徑,根據自己的需要改成自己電腦上的路徑即可。

得到下面的輸出信息:

U-Boot 2014.04-gf5f2cb1-dirty (Jun 04 2014 - 13:55:36)

CPUID: 32440001
FCLK:      405 MHz
HCLK:  101.250 MHz
PCLK:   50.625 MHz
DRAM:  64 MiB

之后沒有進入uboot命令行就重啟cpu了。

雖然這里能檢測到DRAM,這也說明了DRAM的配置是基本上正確的。從s3c2440手冊194頁和mini2440原理圖第5頁可以看到DRAM連接nGCS6,

所以其對應基地址是0x30000000,與include/configs/mini2440.h中的PHYS_SDRAM_1的值一模一樣。

(三)調試bug(未進入uboot重啟cpu)

在include/configs/mini2440.h中添加一行:

#define DEBUG

然后按照上面的步驟將進行編譯並將生成u-boot.bin加載到mini2440,從控制台可以得到輸出:

U-Boot 2014.04-g0e7a234-dirty (Jun 04 2014 - 14:22:23)

U-Boot code: 33F80000 -> 33FF9F84  BSS: -> 340489D0
CPUID: 32440001
FCLK:      405 MHz
HCLK:  101.250 MHz
PCLK:   50.625 MHz
monitor len: 000C89D0
ramsize: 04000000
TLB table from 33ff0000 to 33ff4000
Top of RAM usable for U-Boot at: 33ff0000
Reserving 802k for U-Boot at: 33f27000
Reserving 4160k for malloc() at: 33b17000
Reserving 32 Bytes for Board Info at: 33b16fe0
Reserving 160 Bytes for Global Data at: 33b16f40
New Stack Pointer is: 33b16f30
RAM Configuration:
Bank #0: 30000000 64 MiB
relocation Offset is: fffa7000

然后就凍結在這個地方,不再有任何輸出。

我在board_init_f函數中debug("relocation Offset is: %08lx\n", gd->reloc_off)之前添加了一行代碼:

debug("addr=%08lx,_start=%08lx\n", addr,(ulong)&_start);

重新編譯加載到mini2440后得到的輸出信息如下:

U-Boot 2014.04-g0e7a234-dirty (Jun 04 2014 - 14:35:37)

U-Boot code: 33F80000 -> 33FF9FB4  BSS: -> 340489D0
CPUID: 32440001
FCLK:      405 MHz
HCLK:  101.250 MHz
PCLK:   50.625 MHz
monitor len: 000C89D0
ramsize: 04000000
TLB table from 33ff0000 to 33ff4000
Top of RAM usable for U-Boot at: 33ff0000
Reserving 802k for U-Boot at: 33f27000
Reserving 4160k for malloc() at: 33b17000
Reserving 32 Bytes for Board Info at: 33b16fe0
Reserving 160 Bytes for Global Data at: 33b16f40
New Stack Pointer is: 33b16f30
RAM Configuration:
Bank #0: 30000000 64 MiB
addr=33f27000,_start=33f80000
relocation Offset is: fffa7000

從調試信息可以看出addr < _start,但是gd_reloc_off=addr-(ulong)&_start,明顯得到的結果溢出了。

這是因為我們配置的CONFIG_SYS_TEXT_BASE的問題,將其值修改成0x33F00000。

然后重新編譯加載到mini2440(但命令中的0x33f80000都要替換成0x33f00000),得到下面的輸出:

U-Boot 2014.04-g0e7a234-dirty (Jun 04 2014 - 14:48:22)

U-Boot code: 33F00000 -> 33F79FB4  BSS: -> 33FC89D0
CPUID: 32440001
FCLK:      405 MHz
HCLK:  101.250 MHz
PCLK:   50.625 MHz
monitor len: 000C89D0
ramsize: 04000000
TLB table from 33ff0000 to 33ff4000
Top of RAM usable for U-Boot at: 33ff0000
Reserving 802k for U-Boot at: 33f27000
Reserving 4160k for malloc() at: 33b17000
Reserving 32 Bytes for Board Info at: 33b16fe0
Reserving 160 Bytes for Global Data at: 33b16f40
New Stack Pointer is: 33b16f30
RAM Configuration:
Bank #0: 30000000 64 MiB
addr=33f27000,_start=33f00000
relocation Offset is: 00027000

 雖然沒有溢出,但是仍然是停留在這個位置不繼續執行了。

我將CONFIG_SYS_TEXT_BASE改成了0x33e80000,然后重新編譯並加載到mini2440內存中(命令中的地址也相應修改為0x33e80000),得到下面的輸出:

U-Boot 2014.04-g0e7a234-dirty (Jun 04 2014 - 15:25:46)

U-Boot code: 33E80000 -> 33EF9FA8  BSS: -> 33F489D0
CPUID: 32440001
FCLK:      405 MHz
HCLK:  101.250 MHz
PCLK:   50.625 MHz
monitor len: 000C89D0
ramsize: 04000000
TLB table from 33ff0000 to 33ff4000
Top of RAM usable for U-Boot at: 33ff0000
Reserving 802k for U-Boot at: 33f27000
Reserving 4160k for malloc() at: 33b17000
Reserving 32 Bytes for Board Info at: 33b16fe0
Reserving 160 Bytes for Global Data at: 33b16f40
New Stack Pointer is: 33b16f30
RAM Configuration:
Bank #0: 30000000 64 MiB
addr=33f27000,_start=33e80000
relocation Offset is: 000a7000
WARNING: Caches not enabled
monitor flash len: 000847B0
Now running in RAM - U-Boot at: 33f27000
Flash: fwc addr 00000000 cmd f0 00f0 16bit x 16 bit
fwc addr 0000aaaa cmd aa 00aa 16bit x 16 bit
fwc addr 00005554 cmd 55 0055 16bit x 16 bit
fwc addr 0000aaaa cmd 90 0090 16bit x 16 bit
fwc addr 00000000 cmd f0 00f0 16bit x 16 bit
JEDEC PROBE: ID f0 ea00 0
fwc addr 00000000 cmd ff 00ff 16bit x 16 bit
fwc addr 00000000 cmd 90 0090 16bit x 16 bit
fwc addr 00000000 cmd ff 00ff 16bit x 16 bit
JEDEC PROBE: ID 90 ea00 0
*** failed ***
### ERROR ### Please RESET the board ###

從輸出信息上看sdram已經通過了,但是flash中存在問題,接下來解決這個問題。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM