天天看點

移植u-boot-2016.11到TQ2440開發闆全過程記錄

  • 移植前的準備
  1. 擷取并解壓源碼

SAMSUNG公司于2017年初停止了對S3C2410系列CPU的官方u-boot支援(可在最新版u-boot源碼中打開doc/README.scrapyard,搜尋關鍵字S3C2440檢視相關說明)。從http://ftp.denx.de/pub/u-boot/下載下傳支援S3C2410處理器的最後一版官方u-boot源碼u-boot-2016.11.tar.bz2,放到主控端的/opt/u-boot/下。

解壓源代碼并進入根目錄:

tar jxvf u-boot-2016.11.tar.bz2

cd u-boot-2016.11/

  1. 指定交叉編譯器

gedit Makefile

找到:

# set default to nothing for native builds

ifeq ($(HOSTARCH),$(ARCH))

CROSS_COMPILE ?=

endif

在下方新插入一行:

CROSS_COMPILE ?=arm-linux-

  1. 建立闆卡支援檔案

(1)建立闆卡支援檔案夾

拷貝官方smdk2410檔案夾進行修改:

cp -rf board/samsung/smdk2410/ board/samsung/tq2440

(2)修改闆卡硬體初始化檔案

gedit board/samsung/tq2440/lowlevel_init.S

修改s3c2410.S為tq2440.S,修改SMDK2410為TQ2440。

(3)修改闆卡進階初始化檔案

重命名該檔案夾下的smdk2410.c為tq2440.c:

mv board/samsung/tq2440/smdk2410.c board/samsung/tq2440/tq2440.c

編輯該檔案:

gedit board/samsung/tq2440/tq2440.c

替換所有SMDK2410為TQ2440,并添加編譯選項。

gedit board/samsung/tq2440/Makefile

修改smdk2410.o為tq2440.o

(4)修改闆卡配置檔案

編輯該檔案:

gedit board/samsung/tq2440/Kconfig

内容為:

if TARGET_TQ2440

config SYS_BOARD

       default "tq2440"

config SYS_VENDOR

       default "samsung"

config SYS_SOC

       default "s3c24x0"

config SYS_CONFIG_NAME

       default "tq2440"

endif

(5)添加闆卡支援檔案資訊

gedit arch/arm/Kconfig

找到

config TARGET_SMDK2410

       bool "Support smdk2410"

       select CPU_ARM920T

在下方插入:

config TARGET_TQ2440

       bool "Support tq2440"

       select CPU_ARM920T

找到:

source "board/samsung/smdk2410/Kconfig"

在下方插入:

source "board/samsung/tq2440/Kconfig"

(6)修改闆卡支援維護資訊

gedit board/samsung/tq2440/MAINTAINERS

修改内容為:

TQ2440 BOARD

M:   Lion <[email protected]>

S:    Maintained

F:    board/samsung/tq2440/

F:    include/configs/tq2440.h

F:    configs/tq2440_defconfig

(7)添加闆卡識别資訊

gedit arch/arm/include/asm/mach-types.h

找到:

#define MACH_TYPE_SMDK2410             193

在下方插入:

#define MACH_TYPE_TQ2440          168

找到:

#ifdef CONFIG_ARCH_SMDK2410

# ifdef machine_arch_type

#  undef machine_arch_type

#  define machine_arch_type __machine_arch_type

# else

#  define machine_arch_type MACH_TYPE_SMDK2410

# endif

# define machine_is_smdk2410()   (machine_arch_type == MACH_TYPE_SMDK2410)

#else

# define machine_is_smdk2410()   (0)

#endif

在下面插入一段:

#ifdef CONFIG_ARCH_TQ2440

# ifdef machine_arch_type

#  undef machine_arch_type

#  define machine_arch_type __machine_arch_type

# else

#  define machine_arch_type MACH_TYPE_TQ2440

# endif

# define machine_is_tq2440()  (machine_arch_type == MACH_TYPE_TQ2440)

#else

# define machine_is_tq2440()  (0)

#endif

  1. 建立闆卡配置頭檔案

cp include/configs/smdk2410.h include/configs/tq2440.h

編輯該檔案:

gedit include/configs/tq2440.h

替換S3C2410為S3C2440,替換SMDK2410為TQ2440

  1. 建立NAND Flash驅動檔案

cp drivers/mtd/nand/s3c2410_nand.c drivers/mtd/nand/s3c2440_nand.c

      編輯該檔案:

gedit drivers/mtd/nand/s3c2440_nand.c

      添加編譯選項:

gedit drivers/mtd/nand/Makefile

找到:

obj-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o

在下方插入一行:

obj-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o

  1. 建立預設編譯配置檔案

建立tq2440開發闆預設配置檔案:

cp configs/smdk2410_defconfig configs/tq2440_defconfig

編輯該檔案:

gedit configs/tq2440_defconfig

修改開發闆目标:

替換CONFIG_TARGET_SMDK2410=y為CONFIG_TARGET_TQ2440=y;

修改指令行字首:

替換CONFIG_SYS_PROMPT="SMDK2410 # "為CONFIG_SYS_PROMPT="TQ2440 # ";

  1. 測試編譯環境

(1)清理環境并重新編譯

make distclean

make tq2440_defconfig

make

編譯失敗,并提示” Not enough room for program headers, try linking with -N”錯誤:

移植u-boot-2016.11到TQ2440開發闆全過程記錄

錯誤資訊:

arm-linux-ld.bfd: u-boot: Not enough room for program headers, try linking with -N

arm-linux-ld.bfd: final link failed: Bad value

Makefile:1209: recipe for target 'u-boot' failed

make: *** [u-boot] Error 1

(2)根據網上資料,修改頂層配置檔案:

gedit Makefile

找到:

LDFLAGS_u-boot += $(LDFLAGS_FINAL)

在下面插入:

# Avoid 'Not enough room for program headers' error on binutils 2.28 onwards

LDFLAGS_u-boot += $(call ld-option, --no-dynamic-linker)

(3)重新編譯

make

在根目錄下生成了u-boot.bin檔案,但提示“Error: You must add new CONFIG options using Kconfig”錯誤

移植u-boot-2016.11到TQ2440開發闆全過程記錄

錯誤資訊:

Error: You must add new CONFIG options using Kconfig

The following new ad-hoc CONFIG options were detected:

CONFIG_NAND_S3C2440

CONFIG_SYS_S3C2440_NAND_HWECC

CONFIG_TQ2440

Please add these via Kconfig instead. Find a suitable Kconfig

file and add a 'config' or 'menuconfig' option.

Makefile:827: recipe for target 'all' failed

make: *** [all] Error 1

這一個錯誤産生的原因是修改了配置頭檔案中的預設宏定義而導緻配置檢查無法通過,如果根據消息提示手工在whitelist.txt檔案中添加相應宏,由于不知道whitelist.txt檔案中的排序規則,仍舊可能報錯。

(4)解決白名單校驗不通過問題

根據網上資料來看,目前切實有效的解決辦法是關閉該校驗功能。

gedit Makefile

找到:

       $(srctree)/scripts/check-config.sh u-boot.cfg \

              $(srctree)/scripts/config_whitelist.txt ${srctree} 1>&2

在開頭位置使用#屏蔽這兩行:

#     $(srctree)/scripts/check-config.sh u-boot.cfg \

#            $(srctree)/scripts/config_whitelist.txt ${srctree} 1>&2

  1. 建立自動編譯批處理腳本

(1)編寫自動編譯腳本

gedit auto_build.sh

添加如下内容:

#!/bin/bash 

echo "Clean Configuration File..." 

make distclean 

echo "Clean Obj..." 

make clean 

echo "Load Configuration File..." 

make tq2440_defconfig 

echo "make..." 

make CROSS_COMPILE=arm-linux-

echo "Copy bins to TFTP Folder...."

cp /opt/u-boot/u-boot-2016.11/u-boot.bin /opt/TFTP/u-boot.bin

cp /opt/u-boot/u-boot-2016.11/spl/u-boot-spl.bin /opt/TFTP/u-boot-spl.bin

(2)為自動編譯腳本檔案添加執行權限

sudo chmod +X auto_build.sh

(3)修改自動編譯腳本檔案所有者

sudo chown -R tq2440:root /opt/u-boot/u-boot-2016.11/auto_build.sh

(4)執行自動編譯腳本

bash ./auto_build.sh

編譯成功:

移植u-boot-2016.11到TQ2440開發闆全過程記錄
  1. 小結

至此,我們完成了u-boot-2016.11移植到TQ2440開發闆的前期準備工作。

  • 修改晶片初始化代碼
  1. 修改屏蔽中斷代碼

gedit arch/arm/cpu/arm920t/start.S

找到:

# if defined(CONFIG_S3C2410)

       ldr   r1, =0x3ff

       ldr   r0, =INTSUBMSK

       str   r1, [r0]

# endif

在下面為S3C2440晶片添加:

# if defined(CONFIG_S3C2440)

       ldr   r1, =0x7ff

       ldr   r0, =INTSUBMSK

       str   r1, [r0]

# endif

  1. 修改時鐘初始化代碼

(1)修改晶片時鐘初始化代碼

gedit arch/arm/cpu/arm920t/start.S

找到:

       ldr   r0, =CLKDIVN

       mov       r1, #3

       str   r1, [r0]

替換為:

#if defined(CONFIG_S3C2440)

#define CLK_CTL_BASE      0x4C000000

#define MDIV_405   0x7f<<12

#define PSDIV_405  0x21

       ldr   r0, =CLKDIVN

       mov       r1, #5

       str   r1, [r0]

       mrc p15, 0, r1, c1, c0, 0

       orr   r1, r1, #0xc0000000  

       mcr p15, 0, r1, c1, c0, 0

       mov       r1, #CLK_CTL_BASE

       mov       r2, #MDIV_405

       add r2, r2, #PSDIV_405

       str   r2, [r1, #0x04]

#else

       ldr   r0, =CLKDIVN

       mov       r1, #3

       str   r1, [r0]

#endif   

(2)修改闆卡時鐘初始化代碼

gedit board/samsung/tq2440/tq2440.c

添加一個新的FCLK配置模式,找到:

#define FCLK_SPEED 1

修改為:

#if !defined(CONFIG_S3C2440)

#define FCLK_SPEED 1

#else

#define FCLK_SPEED 2

#endif

找到對應的配置項:

#if (FCLK_SPEED == 0)       

#define M_MDIV      0xC3

#define M_PDIV 0x4

#define M_SDIV 0x1

#elif (FCLK_SPEED == 1)           

#define M_MDIV      0xA1

#define M_PDIV 0x3

#define M_SDIV 0x1

#endif

添加配置模式為2的分支選項:

#if (FCLK_SPEED == 0)       

#define M_MDIV      0xC3

#define M_PDIV 0x4

#define M_SDIV 0x1

#elif (FCLK_SPEED == 1)           

#define M_MDIV      0xA1

#define M_PDIV 0x3

#define M_SDIV 0x1

#elif (FCLK_SPEED == 2)           

#define M_MDIV      0x7f

#define M_PDIV 0x2

#define M_SDIV 0x1

#endif

添加一個新的UCLK配置模式,找到:

#define USB_CLOCK 1

替換為:

#if !defined(CONFIG_S3C2440)

#define USB_CLOCK 1

#else

#define USB_CLOCK 2

#endif

找到對應的配置項:

#if (USB_CLOCK == 0)

#define U_M_MDIV 0xA1

#define U_M_PDIV  0x3

#define U_M_SDIV  0x1

#elif (USB_CLOCK == 1)

#define U_M_MDIV 0x48

#define U_M_PDIV  0x3

#define U_M_SDIV  0x2

#endif

添加配置模式為2的分支選項:

#if (USB_CLOCK == 0)

#define U_M_MDIV 0xA1

#define U_M_PDIV  0x3

#define U_M_SDIV  0x1

#elif (USB_CLOCK == 1)

#define U_M_MDIV 0x48

#define U_M_PDIV  0x3

#define U_M_SDIV  0x2

#elif (USB_CLOCK == 2)

#define U_M_MDIV 0x38

#define U_M_PDIV  0x2

#define U_M_SDIV  0x2

#endif

  1. 啟動I/D CACHE

gedit arch/arm/cpu/arm920t/start.S

找到:

#endif   

在上一行插入:

#if defined(CONFIG_S3C2440)

       mrc p15, 0, r0, c1, c0, 0

       orr   r0, r0, #(1<<12)

       mcr p15, 0, r0, c1, c0, 0

#endif   

  1. 修改SDRAM初始化代碼

gedit board/samsung/tq2440/lowlevel_init.S

替換:

SMRDATA:

    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))

    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))

    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))

    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))

    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))

    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))

    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))

    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))

    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))

    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)

    .word 0x32

    .word 0x30

    .word 0x30

為:

SMRDATA:

       .long 0x22011110 @ BWSCON

       .long 0x00000700 @ BANKCON0

       .long 0x00000700 @ BANKCON1

       .long 0x00000700 @ BANKCON2

       .long 0x00000700 @ BANKCON3

       .long 0x00000700 @ BANKCON4

       .long 0x00000700 @ BANKCON5

       .long 0x00018005 @ BANKCON6

       .long 0x00018005 @ BANKCON7

       .long 0x008C07A3 @ REFRESH

       .long 0x000000B1 @ BANKSIZE

       .long 0x00000030 @ MRSRB6

       .long 0x00000030 @ MRSRB7

  1. 修改GPIO引腳初始化代碼

GPB共有11個引腳,有高到低依次為GPB10-GPB0。TQ2440開發闆的四個闆載LED分别位于GPB8-GPB5,由GPBCON、GPBUP和GPBDAT三個寄存器控制。

  1. GPBCON(0x56000010)每兩位控制一個引腳,為00時表示輸入引腳,為01時表示輸出引腳,為10時表示複用功能;
  2. GPBDAT(0x56000014)每一位表示一個引腳的輸入或輸出狀态;
  3. GPBUP(0x56000018)每一位控制一個引腳,為0時表示使用上拉電阻,為1表示禁用上拉電阻。

gedit board/samsung/tq2440/tq2440.c

可看到:

writel(0x00044555, &gpio->gpbcon);

則源代碼中GPB管腳配置情況如下:

GPB10 GPB9 GPB8 GPB7 GPB6 GPB5 GPB4 GPB3 GPB2 GPB1 GPB0
1 1 1 1 1 1 1 1
輸入 輸出 輸入 輸出 輸入 輸出 輸出 輸出 輸出 輸出 輸出

即源碼中闆卡初始化代碼将GPB10、GPB8和GPB6設定為輸入模式,其餘設定為輸出模式。

根據TQ2440開發闆原理圖來看:GPB0為蜂鳴器接口,GPB5~GPB8為LED接口,均設定為輸出模式,其他管腳設定為複用模式。

TQ2440開發闆GPB管腳配置情況如下:

GPB10 GPB9 GPB8 GPB7 GPB6 GPB5 GPB4 GPB3 GPB2 GPB1 GPB0
1 1 1 1 1 1 1 1 1 1 1
複用 輸出 輸出 輸出 輸出 輸出 複用 複用 複用 複用 複用

則修改該代碼為:

writel(0x002556A9, &gpio->gpbcon);

  1. 取消"WARNING: Caches not enabled "警告

gedit arch/arm/lib/cache.c

由于前面我們已經啟用了I/D Cache,是以這個警告是錯誤的,找到:

puts("WARNING: Caches not enabled\n");

用注釋掉。

  1. 小結

至此,我們完成了晶片級初始化和進階初始化代碼的修改。需要注意的是,在board/samsung/tq2440/tq2440.c的board_init函數中有一句:

       gd->bd->bi_boot_params = 0x30000100;

指定了在SDRAM中運作時環境變量儲存位址,後面再來研究。

  • 從SDRAM啟動
  1. 修改u-boot連接配接位址

TQ2440開發闆的SDRAM型号為K4S561632N,接BANK6,位址段為:0x3000_0000~0x33FF_FFFF,需要修改u-boot.bin檔案的連結位址到該區域。

gedit include/configs/tq2440.h

找到:

#define CONFIG_SYS_TEXT_BASE 0x0

替換為:

#define CONFIG_SYS_TEXT_BASE 30008000    

  1. 跳過底層初始化函數

根據u-boot的啟動流程來看,如果将u-boot燒寫到SDRAM中直接運作,需要在arch/arm/cpu/arm920t/start.S檔案中屏蔽掉對底層初始化函數lowlevel_init的調用(底層初始化函數位于board/Samsung/smdk2440/lowlevel_init.S檔案中),否則啟動過程中會對SDRAM重新進行初始化,破壞掉u-boot的代碼。

gedit arch/arm/cpu/arm920t/start.S

可以看到u-boot源碼中相應代碼,可以通過定義一個CONFIG_SKIP_LOWLEVEL_INIT宏來跳過對lowlevel_init函數的調用:

移植u-boot-2016.11到TQ2440開發闆全過程記錄

在配置頭檔案中添加該宏:

gedit include/configs/tq2440.h

在檔案開頭插入:

#define DEBUG                            

#define CONFIG_SKIP_LOWLEVEL_INIT          

  1. 修改SDRAM重新整理頻率

gedit board/samsung/tq2440/lowlevel_init.S

在start.S中設定了FCLK為405MHZ,分頻系數FCLK:HCLK:PCLK = 1:4:8。SDRAM使用HCLK,則頻率為101.25MHz,一個時鐘周期為1/101.25MHz=9.876ns。

S3C2440手冊中對于Trp參數的描述:0x00=2 clocks,0x01=3 clocks,0x10=4 clocks,11=Not。

SDRAM手冊知:最小時鐘周期為10ns,Row Precharge time最小值為20ns,則Trp=20/9.876=2個時鐘周期。

找到:

#define REFCNT                    1012     

替換為:

#define REFCNT                    999       

  1. 下載下傳到SDRAM中運作

(1)燒寫天嵌科技官方的u-boot到NOR Flash并啟動;

(2)在u-boot界面下連按兩次’q’進入指令行;

(3)設定網絡環境變量并儲存(首次使用官方u-boot時必須進行此操作);

set ethaddr 00:12:34:56:ab:cd

set ipaddr 192.168.1.11

set serverip 192.168.1.10

saveenv

(4)從TFTP下載下傳u-boot.bin到SDRAM中運作;

tftp 30008000 u-boot.bin;go 30008000

移植u-boot-2016.11到TQ2440開發闆全過程記錄

啟動時正确識别出SDRAM(記憶體)大小為64MiB,但之後就卡死了。按網上說法是因為u-boot執行到board.c中的board_init_r函數時,調用mem_malloc_init函數時出錯。

臨時解決辦法是:

gedit common/dlmalloc.c

找到mem_malloc_init中的:

#ifdef CONFIG_SYS_MALLOC_CLEAR_ON_INIT

       memset((void *)mem_malloc_start, 0x0, size);

#endif

替換為:

#ifdef CONFIG_SYS_MALLOC_CLEAR_ON_INIT

       memset((void *)mem_malloc_start, 0x0, size/2);

#endif

即将系統初始化階段開辟的緩存區大小減少為1/2後重新燒錄,啟動正常

移植u-boot-2016.11到TQ2440開發闆全過程記錄
  1. 小結

回頭再來研究初始化階段清空堆棧出錯的原因。

  • 移植DM9000網卡驅動

u-boot-2016.11版本自帶了DM9000網卡驅動程式,隻需要做簡單修改和調用即可使用。DM9000位于TQ2440的BANK4,則對應基位址為0x20000000;使用LADDR2作為CMD信号,是以指令寄存器位址為0x20000004。

  1. 修改DM9000網卡相關宏和寄存器定義

gedit include/configs/tq2440.h

找到:

#define CONFIG_CS8900            

#define CONFIG_CS8900_BASE 0x19000300

#define CONFIG_CS8900_BUS16     

替換為

#define CONFIG_DRIVER_DM9000

#define CONFIG_DM9000_NO_SROM                 

#define CONFIG_DM9000_BASE 0x20000000            

#define DM9000_IO CONFIG_DM9000_BASE

#define DM9000_DATA (CONFIG_DM9000_BASE+4)      

設定預設的網絡配置資訊,找到:

#define CONFIG_NETMASK             255.255.255.0

#define CONFIG_IPADDR           10.0.0.110

#define CONFIG_SERVERIP       10.0.0.1

替換為:

#define CONFIG_NETMASK             255.255.255.0

#define CONFIG_IPADDR                  192.168.1.11

#define CONFIG_SERVERIP       192.168.1.10

#define CONFIG_ETHADDR       00:11:22:33:44:aa

  1. 調用DM9000網卡初始化函數

gedit board/samsung/tq2440/tq2440.c

找到board_eth_init函數,添加:

#ifdef CONFIG_DRIVER_DM9000

       rc = dm9000_initialize(bis);

#endif

解決新版u-boot中“could not establish link“提示

gedit drivers/net/dm9000x.c

找到dm9000_init函數,注釋掉網絡測試代碼:

#if 0

       i = 0;

       while (!(dm9000_phy_read(1) & 0x20)) {  

              udelay(1000);

              i++;

              if (i == 10000) {

                     printf("could not establish link\n");

                     return 0;

              }

       }

#endif

  1. 添加環境變量

(1)添加網卡位址到預設環境變量數組中

gedit include/env_default.h

找到:

#ifdef     CONFIG_SERVERIP

       "serverip="   __stringify(CONFIG_SERVERIP) "\0"

#endif

在下面添加:

#ifdef     CONFIG_ETHADDR

       "ethaddr="    __stringify(CONFIG_ETHADDR)       "\0"

#endif

  1. 網絡功能測試

(1)下載下傳到SDRAM運作

從TFTP下載下傳u-boot.bin到SDRAM中運作;

tftp 30008000 u-boot.bin;go 30008000

移植u-boot-2016.11到TQ2440開發闆全過程記錄

已經正确識别到DM9000網卡。

(2)ping測試

ping 192.168.1.10

移植u-boot-2016.11到TQ2440開發闆全過程記錄

(3)TFTP下載下傳功能測試

tftp 320000 u-boot.bin

移植u-boot-2016.11到TQ2440開發闆全過程記錄
  1. 小結

有空回來完善ethaddr環境變量儲存問題。

  • 從NOR Flash啟動
  1. 修改相關參數宏定義

gedit include/configs/tq2440.h

配置頭檔案中支援NOR FLASH的相關宏參數包括:

  1. CONFIG_SYS_FLASH_LEGACY_512Kx16:指明;
  2. CONFIG_SYS_MAX_FLASH_BANKS:指明系統中有幾個FLASH,TQ2440隻有1個;
  3. CONFIG_SYS_MAX_FLASH_SECT:指明該FLASH中有多少個段,根據晶片資料手冊可知,TQ2440用的NOR FLASH一共有35個段;
  4. CONFIG_ENV_ADDR:指明環境變量儲存位置;
  5. CONFIG_ENV_IS_IN_FLASH:指明環境變量儲存在NOR Flash中;
  6. CONFIG_ENV_SIZE:指明環境變量大小。

根據晶片手冊修改NOR Flash扇區數,找到:

#define CONFIG_SYS_MAX_FLASH_SECT (19)

修改為:

#define CONFIG_SYS_MAX_FLASH_SECT (35)

找到:

#define CONFIG_SYS_FLASH_LEGACY_512Kx16

修改為:

#define CONFIG_SYS_FLASH_LEGACY_1024Kx16

  1. 添加NOR Flash晶片資訊

gedit drivers/mtd/jedec_flash.c

找到jedec_table[]數組,在末尾};上一行添加:

#ifdef CONFIG_SYS_FLASH_LEGACY_1024Kx16

       {

              .mfr_id          = 0x1c,

              .dev_id         = 0x2249,

              .name            = "EON EN29LV160AB",

              .uaddr           = {

                     [1] = MTD_UADDR_0x0555_0x02AA

              },

              .DevSize              = SIZE_2MiB,

              .CmdSet              = P_ID_AMD_STD,

              .NumEraseRegions    = 4,

              .regions         = {

                     ERASEINFO(0x04000, 1),           

                     ERASEINFO(0x02000, 2),           

                     ERASEINFO(0x08000, 1),           

                     ERASEINFO(0x10000, 31),         

              }

       },

#endif

  1. NOR Flash讀寫功能測試

(1)從TFTP下載下傳u-boot.bin到SDRAM中啟動;

tftp 30008000 u-boot.bin;go 30008000

移植u-boot-2016.11到TQ2440開發闆全過程記錄
  1. 去掉NOR Flash寫保護

protect off all

  1. 擦除指定區域(避開u-boot所在區域)

erase 100000 +10000

(3)從SDRAM拷貝64K資料到NOR Flash

cp.b 30008000 100000 10000

  1. 從NOR Flash讀取64K資料到SDRAM

cp.b 100000 30108000 10000

(5)比較64K資料

cmp.b 30108000 30008000 10000

移植u-boot-2016.11到TQ2440開發闆全過程記錄
  1. 修改u-boot連接配接位址

TQ2440開發闆闆載NOR Flash為EON EN29LV160AB,2MB,挂載在0x0000_0000~0x001F_FFFF,2MB、16bit資料位寬,需要修改u-boot.bin檔案的連結位址到該區域。

gedit include/configs/tq2440.h

找到:

#define CONFIG_SYS_TEXT_BASE 0x30008000

替換為:

#define CONFIG_SYS_TEXT_BASE 0    

  1. 使能SDRAM初始化操作

從NOR Flash或者NAND Flash啟動時,需要在硬體初始化階段調用lowlevel_init初始化SDRAM。

gedit include/configs/tq2440.h

用屏蔽以下代碼:

  1. 燒錄到NOR Flash啟動

(1)下載下傳到NOR Flash運作

從TFTP下載下傳u-boot.bin到SDRAM中;

tftp 30008000 u-boot.bin

(2)去掉NOR Flash寫保護

protect off all

  1. 擦除NOR Flash

erase 0 +100000

  1. 拷貝到NOR Flash中(NOR Flash寫入較慢,約30秒)

cp.b 30008000 0 100000

(4)重新開機開發闆從NOR Flash啟動

reset

移植u-boot-2016.11到TQ2440開發闆全過程記錄

從NOR Flash啟動正常,但儲存環境變量之後無法啟動。

  1. 調整環境變量儲存位址

gedit include/configs/tq2440.h

找到:

#define CONFIG_ENV_ADDR                  (CONFIG_SYS_FLASH_BASE + 0x070000)

#define CONFIG_ENV_IS_IN_FLASH

#define CONFIG_ENV_SIZE              0x10000

從TFTP下載下傳時發現:

移植u-boot-2016.11到TQ2440開發闆全過程記錄

編譯後的u-boot.bin大小為516612位元組,占用了NOR Flash的0x0~0x07e204。而源碼中預設将環境變量儲存在NOR Flash基位址+0x070000位置,是以儲存環境變量時破壞了u-boot代碼。

修改:

#define CONFIG_ENV_ADDR                  (CONFIG_SYS_FLASH_BASE + 0x070000)

為:

#define CONFIG_ENV_ADDR                  (CONFIG_SYS_FLASH_BASE + 0x100000)

重新燒錄到NOR Flash後問題解決:

移植u-boot-2016.11到TQ2440開發闆全過程記錄
  • 移植NAND Flash驅動
  1. 修改S3C2440的NAND Flash控制器結構體

gedit arch/arm/include/asm/arch-s3c24x0/s3c24x0.h

找到:

struct s3c24x0_nand {

       u32 nfconf;

#ifndef CONFIG_S3C2410

       u32 nfcont;

#endif

       u32 nfcmd;

       u32 nfaddr;

       u32 nfdata;

#ifndef CONFIG_S3C2410

       u32 nfeccd0;

       u32 nfeccd1;

       u32 nfeccd;

#endif

       u32 nfstat;

#ifdef CONFIG_S3C2410

       u32 nfecc;

#else

       u32 nfstat0;

       u32 nfstat1;

       u32 nfmecc0;

       u32 nfmecc1;

       u32 nfsecc;

       u32 nfsblk;

       u32 nfeblk;

#endif

};

對照S3C2440晶片手冊,修改為:

struct s3c24x0_nand {

       u32 nfconf;

#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)  

       u32 nfcont;

#endif

       u32 nfcmd;

       u32 nfaddr;

       u32 nfdata;

#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)  

       u32 nfeccd0;

       u32 nfeccd1;

       u32 nfeccd;

#endif

       u32 nfstat;

#ifdef CONFIG_S3C2410

       u32 nfecc;

#elif defined(CONFIG_S3C2440)

       u32 nfstat0;

       u32 nfstat1;

#else

       u32 nfstat0;

       u32 nfstat1;

       u32 nfmecc0;

       u32 nfmecc1;

       u32 nfsecc;

       u32 nfsblk;

       u32 nfeblk;

#endif

};

  1. 修改NAND Flash讀寫時序

gedit drivers/mtd/nand/s3c2440_nand.c

在board_nand_init函數中找到:

#define S3C2440_NFCONF_EN          (1<<15)

#define S3C2440_NFCONF_512BYTE     (1<<14)

#define S3C2440_NFCONF_4STEP       (1<<13)

#define S3C2440_NFCONF_INITECC     (1<<12)

#define S3C2440_NFCONF_nFCE        (1<<11)

#define S3C2440_NFCONF_TACLS(x)    ((x)<<8)

#define S3C2440_NFCONF_TWRPH0(x)   ((x)<<4)

#define S3C2440_NFCONF_TWRPH1(x)   ((x)<<0)

#define S3C2440_ADDR_NALE 4

#define S3C2440_ADDR_NCLE 8

替換為S3C2440的相關寄存器定義:

#define S3C2440_NFCONT_SECCL         (1<<6)

#define S3C2440_NFCONT_MECCL        (1<<5)

#define S3C2440_NFCONT_INITECC             (1<<4)

#define S3C2440_NFCONT_nCE       (1<<1)

#define S3C2440_NFCONT_MODE          (1<<0)

#define S3C2440_NFCONF_TACLS(x)            ((x)<<12)

#define S3C2440_NFCONF_TWRPH0(x) ((x)<<8)

#define S3C2440_NFCONF_TWRPH1(x) ((x)<<4)

#define S3C2440_ADDR_NALE        0x08

#define S3C2440_ADDR_NCLE         0x0C

找到board_nand_init函數,替換其中的時序控制和初始化代碼:

#else

       tacls = 4;

       twrph0 = 8;

       twrph1 = 8;

#endif

       cfg = S3C2440_NFCONF_EN;

       cfg |= S3C2440_NFCONF_TACLS(tacls - 1);

       cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);

       cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);

       writel(cfg, &nand_reg->nfconf);

為:

#else

       tacls = 2;

       twrph0 = 3;

       twrph1 = 1;

#endif

        cfg = S3C2440_NFCONF_TACLS(tacls - 1);

        cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);

        cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);

        writel(cfg, &nand_reg->nfconf);

        cfg = S3C2440_NFCONT_SECCL;

        cfg |= S3C2440_NFCONT_MECCL;

        cfg |= S3C2440_NFCONT_MODE;

        writel(cfg,&nand_reg->nfcont);

  1. 修改NAND Flash硬體控制

找到s3c24x0_hwcontrol函數,替換寫指令和寫位址操作相關代碼,并在寫完指令和位址後把IO端口的位址重新設定為寄存器NFDATA,否則資料無法寫入(但仍顯示””OK”):

              if (!(ctrl & NAND_CLE))

                     IO_ADDR_W |= S3C2440_ADDR_NCLE;

              if (!(ctrl & NAND_ALE))

                     IO_ADDR_W |= S3C2440_ADDR_NALE;

為:

              if (!(ctrl & NAND_CLE))

                     IO_ADDR_W |= S3C2440_ADDR_NCLE;

              if (!(ctrl & NAND_ALE))

                     IO_ADDR_W |= S3C2440_ADDR_NALE;

              if(cmd ==NAND_CMD_NONE)

                     IO_ADDR_W = (long int) &nand->nfdata;

修改晶片選擇操作,找到:

              if (ctrl & NAND_NCE)

                     writel(readl(&nand->nfconf) & ~S3C2440_NFCONF_nFCE,

                            &nand->nfconf);

              else

                     writel(readl(&nand->nfconf) | S3C2440_NFCONF_nFCE,

                            &nand->nfconf);

替換為:

              if (ctrl & NAND_NCE)

                     writel(readl(&nand->nfcont) & ~S3C2440_NFCONT_nCE,

                            &nand->nfcont);

              else

                     writel(readl(&nand->nfcont) | S3C2440_NFCONT_nCE,

                     &nand->nfcont);

  • 實作硬體ECC功能
  1. 定義硬體ECC操作宏

gedit include/configs/tq2440.h

找到:

#define CONFIG_SYS_S3C2440_NAND_HWECC

在下面插入一行定義該宏:

#define CONFIG_S3C2440_NAND_HWECC

  1. 設定S3C2440處理器硬體ECC參數

找到:

#define CONFIG_S3C2440_NAND_HWECC

在下面插入S3C2440硬體ECC參數:

#define CONFIG_SYS_NAND_ECCSIZE       2048     

#define CONFIG_SYS_NAND_ECCBYTES   4    

  1. 修改ECC驅動程式

gedit drivers/mtd/nand/s3c2440_nand.c

找到s3c24x0_nand_enable_hwecc函數中的:

writel(readl(&nand->nfconf) | S3C2440_NFCONF_INITECC, &nand->nfconf);

替換為:

writel(readl(&nand->nfcont) | S3C2440_NFCONT_INITECC, &nand->nfcont);

找到s3c24x0_nand_calculate_ecc函數中的:

       struct s3c24x0_nand *nand = s3c24x0_get_base_nand();

       ecc_code[0] = readb(&nand->nfecc);

       ecc_code[1] = readb(&nand->nfecc + 1);

       ecc_code[2] = readb(&nand->nfecc + 2);

       debug("s3c24x0_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n",

             mtd , ecc_code[0], ecc_code[1], ecc_code[2]);

替換為:

       struct s3c24x0_nand *nand = s3c24x0_get_base_nand();

       unsigned int mecc0;

       writel(readl(&nand->nfcont)|S3C2440_NFCONT_MECCL,&nand->nfcont);

       mecc0 = readl(&nand->nfeccd);

       ecc_code[0] = mecc0 & 0xff;

       ecc_code[1] = (mecc0 >> 8) & 0xff;

       ecc_code[2] = (mecc0 >>16) & 0xff;

       ecc_code[3] = (mecc0 >>24) & 0xff;

       debug("s3c24x0_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x 0x%02x\n",

              mtd , ecc_code[0], ecc_code[1], ecc_code[2],ecc_code[3]);

找到s3c24x0_nand_correct_data函數中的:

       if (read_ecc[0] == calc_ecc[0] &&

           read_ecc[1] == calc_ecc[1] &&

           read_ecc[2] == calc_ecc[2])

              return 0;

       printf("s3c24x0_nand_correct_data: not implemented\n");

       return -1;

替換為:

       struct s3c24x0_nand *nand = s3c24x0_get_base_nand();

       u32 meccdata0,meccdata1,estat0,err_byte_addr;

       int ret=-1;

       u8 repaired;

       meccdata0 = (read_ecc[1] << 16) | read_ecc[0];

       meccdata1 = (read_ecc[3] << 16) | read_ecc[2];

       writel(meccdata0,&nand->nfeccd0);

       writel(meccdata1,&nand->nfeccd1);

       estat0 = readl(&nand->nfstat0);

       switch (estat0 &0x3){

       case 0:

              ret =0;

              break;

       case 1:

              err_byte_addr = (estat0 >>7 ) & 0x7ff;

              repaired = dat[err_byte_addr]^(1<<((estat0 >>4) & 0x7));

              printf("S3C NAND: 1 bit error detected at byte %ld.Correcting from 0x%02x to0x%02x...OK\n", (long int) err_byte_addr, dat[err_byte_addr],repaired);

              dat[err_byte_addr]= repaired;

              ret= 1;

              break;

       case  2:

       case  3:

              printf("S3C NAND: ECC uncorrectable errordetected.Not correctable.\n");

              ret= -1;

              break;

       }

       return ret;

  1. 實作軟體擦除壞塊功能

(1)開啟Nand Flash資料讀寫校驗功能

gedit include/configs/tq2440.h

在NAND configuration段添加:

#define CONFIG_MTD_NAND_VERIFY_WRITE 1    

(2)實作軟體擦除壞塊功能

gedit drivers/mtd/nand/nand_util.c

在nand_erase_opts函數定義前面(檔案開頭)插入:

static int nand_block_bad_scrub(struct mtd_info *mtd, loff_t ofs, int getchip)

{

       return 0;

}

(3)修改nand_erase_opts函數

找到:

int percent_complete = -1;

在下一行插入:

int (*nand_block_bad_old)(struct mtd_info *, loff_t, int) = NULL;

找到:

if (opts->scrub) {

              erase.scrub = opts->scrub;

下一行插入:

              nand_block_bad_old = chip->block_bad;

              chip->block_bad = nand_block_bad_scrub;

找到:

       if (opts->scrub)

上一行插入:

       if(nand_block_bad_old)

       {

              chip->block_bad=nand_block_bad_old;

       }

  1. 燒寫到NOR Flash運作

(1)下載下傳u-boot到NOR Flash中

從TFTP下載下傳u-boot.bin到SDRAM中;

tftp 30008000 u-boot.bin

(2)去掉NOR Flash寫保護

protect off all

(3)擦除NOR Flash

erase 0 +100000

(4)拷貝到NOR Flash中(NOR Flash寫入較慢,約30秒)

cp.b 30008000 0 100000

(5)重新開機開發闆從NOR Flash啟動

reset

移植u-boot-2016.11到TQ2440開發闆全過程記錄
  1. NAND Flash讀寫功能測試

(1)擦除測試

擦除Nand Flash中0x0開始的0x300000位元組空間

nand erase 0x0 0x300000

移植u-boot-2016.11到TQ2440開發闆全過程記錄

(2)寫操作測試

将SDRAM的0x32000000位址的0xff位元組資料寫到NAND FLASH的0位址

nand write 32000000 0 ff

移植u-boot-2016.11到TQ2440開發闆全過程記錄

(3)讀操作測試

從NAND FLASH的0位址讀0xff位元組資料到SDRAM的0x31000000位址

nand read 31000000 0 ff

移植u-boot-2016.11到TQ2440開發闆全過程記錄

(4)比較資料是否正确

cmp.b 31000000 32000000 ff

移植u-boot-2016.11到TQ2440開發闆全過程記錄

(5)檢視NAND Flash分區資訊

mtd

移植u-boot-2016.11到TQ2440開發闆全過程記錄
  • 建立MTD分區
  1. 定義MTD分區資訊

gedit include/configs/tq2440.h

确認CONFIG_CMD_MTDPARTS、CONFIG_MTD_DEVICE和CONFIG_MTD_PARTITIONS宏已打開,然後找到:

#ifdef CONFIG_CMD_NAND

#define CONFIG_NAND_S3C2440

#define CONFIG_SYS_S3C2440_NAND_HWECC

#define CONFIG_SYS_MAX_NAND_DEVICE     1

#define CONFIG_SYS_NAND_BASE       0x4E000000

#endif

在下方添加:

#define MTDIDS_DEFAULT "nand0=tq2440-nand.0"

#define MTDPARTS_DEFAULT "mtdparts=tq2440-nand.0:512k(u-boot-spl)," \

                                   "1m(u-boot)," \

                                   "256k(params)," \

                                   "4m(kernel)," \

                                   "-(rootfs)"

  1. 設定u-boot預設啟動參數和指令

在分區資訊下添加:

#define CONFIG_BOOTARGS "root=/dev/mtdblock4 rootfstype=yaffs2 init=/linuxrc console=ttySAC0,115200"

#define CONFIG_BOOTCOMMAND "nand read 32000000 kernel;bootm 32000000"

即啟動時将uImage燒到名為kernel的分區。

  • 儲存環境變量到NAND Flash
  1. 設定環境變量儲存位址

為防止儲存環境變量時将u-boot程式破壞掉,重新定義環境變量的偏移位址:

gedit include/configs/tq2440.h

找到:

define CONFIG_ENV_ADDR(CONFIG_SYS_FLASH_BASE + 0x070000)

#define CONFIG_ENV_IS_IN_FLASH

#define CONFIG_ENV_SIZE 0x10000

#define CONFIG_ENV_OVERWRITE

替換為:

#define CONFIG_ENV_IS_IN_NAND

#define CONFIG_ENV_OFFSET 0x00180000

#define CONFIG_ENV_SIZE 0x40000

#define CONFIG_ENV_RANGE CONFIG_ENV_SIZE

其中:

  1. CONFIG_ENV_OFFSET:環境變量的寫入位址,0x00180000表示前面預留了512k+1m作為spl和u-boot的分區;
  2. CONFIG_ENV_SIZE:預留的環境變量大小,0x40000表示環境變量分區大小為256K
  3. CONFIG_ENV_RANGE:環境變量擦除範圍,必須大于等于CONFIG_ENV_SIZE。
  1. 燒寫到NOR Flash運作

(1)下載下傳u-boot到NOR Flash中

從TFTP下載下傳u-boot.bin到SDRAM中;

setenv ethaddr 11:22:33:44:55:66;tftp 30008000 u-boot.bin

(2)擦除并拷貝到NOR Flash中(NOR Flash寫入較慢,約30秒)

protect off all;erase 0 +100000;cp.b 30008000 0 100000

(3)重新開機開發闆從NOR Flash啟動

reset

  1. 重新建立MTD分區

(1)擦除NAND Flash(非必須操作)

nand erase.chip

(2)加載預設MTD分區

mtd default

(3)檢視MTD分區資訊

mtd

移植u-boot-2016.11到TQ2440開發闆全過程記錄
  • 非SPL方式從NAND Flash啟動
  1. 取消連結時的PIE選項

在連結的時候,如果我們啟用了PIE功能,那麼程式中的變量就會被抽出來放到代碼段後面的一些特殊段,而這些變量的位址肯定超過了4K而無法再通路了,是以我們要去除這個PIE功能。

gedit arch/arm/config.mk

找到LDFLAGS_u-boot += -pie,用#号注釋掉。由于我們禁用了PIE選項,是以找到相對位置檢查的配置項ALL-y += checkarmreloc選項,用#号注釋掉。這樣,在後續程式中我們就不需要在重定位代碼後再去計算變量的相對位置。

  1. 建立一個自定義的初始化函數

gedit board/samsung/tq2440/init.c

内容如下:

#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)) 

#define GPHCON              (*(volatile unsigned long *)0x56000070) 

#define GPHUP               (*(volatile unsigned long *)0x56000078) 

#define ULCON0              (*(volatile unsigned long *)0x50000000) 

#define UCON0               (*(volatile unsigned long *)0x50000004) 

#define UFCON0              (*(volatile unsigned long *)0x50000008) 

#define UMCON0              (*(volatile unsigned long *)0x5000000c) 

#define UTRSTAT0            (*(volatile unsigned long *)0x50000010) 

#define UTXH0               (*(volatile unsigned char *)0x50000020) 

#define URXH0               (*(volatile unsigned char *)0x50000024) 

#define UBRDIV0             (*(volatile unsigned long *)0x50000028) 

#define TXD0READY   (1<<2) 

void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len);

static int isBootFromNorFlash(void) 

{

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

       int val;

       val = *p;

       *p = 0x12345678;

       if (*p == 0x12345678) 

       {

              *p = val;

              return 0;

       }

       else 

       {

       return 1;

       }

}

void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len) 

{  

       int i = 0;

       if (isBootFromNorFlash()) 

       {

              while (i < len) 

              {

                     dest[i] = src[i];

                     i++;

              }

       }

       else 

       {

              //nand_init();

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

       }

}

void clear_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 

#define TWRPH0  1 

#define TWRPH1  0 

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

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

}

static void nand_select(void) 

{

       NFCONT &= ~(1<<1);

}

static void nand_deselect(void) 

{

       NFCONT |= (1<<1);  

}

static void nand_cmd(unsigned char cmd) 

{

       volatile int i;

       NFCMMD = cmd;

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

}

static void nand_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 void nand_wait_ready(void) 

{

       while (!(NFSTAT & 1));

}

static unsigned char nand_data(void) 

{

       return NFDATA;

}

void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len) 

{

       int col = addr % 2048;

       int i = 0;

       nand_select();

       while (i < len) 

       {

              nand_cmd(0x00);

              nand_addr(addr);

              nand_cmd(0x30);

              nand_wait_ready();

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

              {

                     buf[i] = nand_data();

                     i++;

                     addr++;

              }

              col = 0;

       }

       nand_deselect();

}

  1. 修改啟動代碼

gedit arch/arm/lib/crt0.S

找到:

       mov       r0, sp

       bl    board_init_f_alloc_reserve

       mov       sp, r0

替換為:

       bl nand_init_ll

       mov       r0, #0

       ldr   r1, =_start

       ldr   r2, =__bss_start

       sub  r2, r2, r1

       ldr   r1, =CONFIG_SYS_TEXT_BASE

       bl    copy_code_to_sdram

       bl    clear_bss

       ldr   pc, =START_ON_RAM          //start run on RAM

START_ON_RAM:

       mov       r0, sp

       bl    board_init_f_alloc_reserve

       mov       sp, r0

找到:

       mov       r0, #0

       bl    board_init_f

在下面插入一行:

       str   r1, [r0]

找到:

       ldr   r0, [r9, #GD_RELOCADDR]       

       b     relocate_code

替換為:

       ldr   r0, [r9, #GD_RELOCADDR]       

       ldr   r2, =__rel_dyn_start

       ldr   r3, =__rel_dyn_end

找到:

       bl    relocate_vectors

       bl    c_runtime_cpu_setup

替換為:

#if 0

       bl    relocate_vectors

       bl    c_runtime_cpu_setup

#endif

找到:

       ldr   r0, =__bss_start  

在前面插入一行:

#if 0

找到:

       blo  clbss_l

在後面插入一行:

#endif

  1. 修改編譯連結選項

将crt0.c和vectors.c單獨編譯,不要連結到built-in.o

gedit arch/arm/lib/Makefile

找到:

obj-y      += vectors.o crt0.o

替換為:

extra-y   += vectors.o crt0.o

修改連接配接檔案,保證代碼拷貝函數編譯到前4K

gedit arch/arm/cpu/u-boot.lds

找到:

              CPUDIR/start.o (.text*)

在下面插入:

              arch/arm/lib/crt0.o (.text*)

              arch/arm/lib/vectors.o (.text*)

              board/samsung/tq2440/built-in.o (.text*)

  1. 修改連接配接位址

gedit include/configs/tq2440.h

找到:

#define CONFIG_SYS_TEXT_BASE 0x32000000

替換為:

#define CONFIG_SYS_TEXT_BASE 0x32000000

  1. 檢視NAND初始化和代碼拷貝函數編譯位置

arm-linux-objdump -D u-boot > u-boot.dis

gedit u-boot.dis

查找nand_init_ll

移植u-boot-2016.11到TQ2440開發闆全過程記錄

位址段為:330005b4~330005c8,而拷貝代碼的及位址為33000000,二者之差小于1000,是以在4k範圍内。

查找copy_code_to_sdram

移植u-boot-2016.11到TQ2440開發闆全過程記錄

也在前4K位址範圍内。

  1. 燒錄到NAND Flash運作

setenv ethaddr 11:22:33:44:55:66;set serverip 192.168.1.10;nand erase 0 0x100000;tftp 32000000 u-boot.bin;nand write 32000000 0 0x100000

移植u-boot-2016.11到TQ2440開發闆全過程記錄
  • 添加LCD支援
  1. 添加LCD配置

gedit include/configs/tq2440.h

在末尾添加:

#define CONFIG_LCD

#define LCD_BPP     LCD_COLOR16

#define CONFIG_LCD_LOGO   

#undef LCD_TEST_PATTERN

#define CONFIG_LCD_INFO     

#define CONFIG_LCD_INFO_BELOW_LOGO    

#define CONFIG_SYS_WHITE_ON_BLACK

#define CONFIG_SYS_CONSOLE_IS_IN_ENV

#define CONFIG_CONSOLE_SCROLL_LINES 16

#define CONFIG_TQ2440_LCD 

#define CONFIG_CONSOLE_MUX  

#define  CONFIG_TQ2440_LCD_VBPD   1

#define  CONFIG_TQ2440_LCD_VFPD   1

#define  CONFIG_TQ2440_LCD_VSPW  9

#define  CONFIG_TQ2440_LCD_HBPD   1

#define  CONFIG_TQ2440_LCD_HFPD   1

#define  CONFIG_TQ2440_LCD_HSPW  40

#define  CONFIG_TQ2440_LCD_CLKVAL    4

#define LCD_XSIZE_TFT     (480)

#define LCD_YSIZE_TFT     (272)

#define MVAL    (13)

#define MVAL_USED     (0)   //0=each frame   1=rate by MVAL

#define INVVDEN   (1)   //0=normal       1=inverted

#define BSWP    (0)   //Byte swap control

#define HWSWP (1)   //Half word swap control

  1. 利用LCD輸出歡迎資訊

gedit board/samsung/tq2440/tq2440.c

在開頭添加

#include <lcd.h>

#include <version.h>

在末尾添加:

#ifdef CONFIG_LCD_INFO

void lcd_show_board_info(void)

{

       lcd_printf ("%s (%s - %s)\n", U_BOOT_VERSION, U_BOOT_DATE, U_BOOT_TIME);

}

#endif

  1. 添加LCD初始化函數

gedit drivers/video/tq2440_fb.c

代碼如下:

#include <common.h>

#include <lcd.h>

#include <asm/system.h>

#include <asm/gpio.h>

#include <asm/arch/s3c24x0_cpu.h>

DECLARE_GLOBAL_DATA_PTR;

#define U32 unsigned int

#define M5D(n)  ( ( n ) & 0x1fffff ) // To get lower 21bits

#define SCR_XSIZE_TFT LCD_XSIZE_TFT

#define HOZVAL_TFT        ( LCD_XSIZE_TFT - 1 )

#define LINEVAL_TFT        ( LCD_YSIZE_TFT - 1 )

vidinfo_t panel_info = {

       .vl_col = LCD_XSIZE_TFT,  

       .vl_row = LCD_YSIZE_TFT,  

       .vl_bpix = LCD_BPP,       

};

//volatile unsigned short (*embedsky_LCD_BUFFER)[SCR_XSIZE_TFT] = (volatile unsigned short (*)[SCR_XSIZE_TFT])(gd->fb_base);

#define embedsky_LCD_BUFFER ((volatile unsigned short (*)[SCR_XSIZE_TFT])(gd->fb_base))

volatile char vbpd = 1, vfpd = 1, vspw = 1, hbpd = 1, hfpd = 1, hspw = 1, clkval_tft = 1 ;

void tq2440_lcd_ClearScr(U32 c)

{

       unsigned int x,y ;

       for( y = 0 ; y < LCD_YSIZE_TFT ; y++ )

       {

              for( x = 0 ; x < (SCR_XSIZE_TFT) ; x++ )

              {

                     embedsky_LCD_BUFFER[y][x] = c;

              }

       }  

}

void tq2440_lcd_PowerEnable(int invpwren , int pwren)

{

       struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio() ;

       struct s3c24x0_lcd * const lcd = s3c24x0_get_base_lcd() ;

       //GPG4 is setted as LCD_PWREN

       gpio -> gpgup = gpio -> gpgup & (( ~( 1 << 4) ) | ( 1 << 4) );        // Pull-up disable

       gpio -> gpgcon = gpio -> gpgcon & (( ~( 3 << 8) ) | ( 3 << 8) );        //GPG4=LCD_PWREN

       gpio -> gpgdat = gpio -> gpgdat | (1 << 4 ) ;

       //invpwren=pwren;

       //Enable LCD POWER ENABLE Function

       lcd -> lcdcon5 = lcd -> lcdcon5 & (( ~( 1 << 3 ) ) | ( pwren << 3 ) );    // PWREN

       lcd -> lcdcon5 = lcd -> lcdcon5 & (( ~( 1 << 5 ) ) | ( invpwren << 5 ) );    // INVPWREN

}

void lcd_ctrl_init(void *lcdbase)

{

       struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio() ;

       struct s3c24x0_lcd * const lcd = s3c24x0_get_base_lcd() ;

       char *s_lcd;

       lcd -> lcdsaddr1 = ( ( ( U32 ) embedsky_LCD_BUFFER >> 22 ) << 21 ) | M5D ( ( U32 ) embedsky_LCD_BUFFER >> 1 ) ;

       lcd -> lcdsaddr2 = M5D( ( ( U32) embedsky_LCD_BUFFER + ( SCR_XSIZE_TFT * LCD_YSIZE_TFT * 2 ) ) >> 1 ) ;

       lcd -> lcdsaddr3 = ( ( ( SCR_XSIZE_TFT - LCD_XSIZE_TFT ) / 1 ) << 11 ) | ( LCD_XSIZE_TFT /1 ) ;

       s_lcd = getenv ("dwVBPD");

       vbpd = s_lcd ? (int)simple_strtol(s_lcd, NULL, 10) : CONFIG_TQ2440_LCD_VBPD;

       s_lcd = getenv ("dwVFPD");

       vfpd = s_lcd ? (int)simple_strtol(s_lcd, NULL, 10) : CONFIG_TQ2440_LCD_VFPD;

       s_lcd = getenv ("dwVSPW");

       vspw = s_lcd ? (int)simple_strtol(s_lcd, NULL, 10) : CONFIG_TQ2440_LCD_VSPW;

       s_lcd = getenv ("dwHBPD");

       hbpd = s_lcd ? (int)simple_strtol(s_lcd, NULL, 10) : CONFIG_TQ2440_LCD_HBPD;

       s_lcd = getenv ("dwHFPD");

       hfpd = s_lcd ? (int)simple_strtol(s_lcd, NULL, 10) : CONFIG_TQ2440_LCD_HFPD;

       s_lcd = getenv ("dwHSPW");

       hspw = s_lcd ? (int)simple_strtol(s_lcd, NULL, 10) : CONFIG_TQ2440_LCD_HSPW;

       s_lcd = getenv ("dwCLKVAL");

       clkval_tft = s_lcd ? (int)simple_strtol(s_lcd, NULL, 10) : CONFIG_TQ2440_LCD_CLKVAL;

       tq2440_lcd_ClearScr( 0x0 ) ;

       gpio -> gpcup  = 0xffffffff ;

       gpio -> gpccon = 0xaaaaaaaa ;                        //Initialize VD[0:7]    

       gpio -> gpdup  = 0xffffffff ;

       gpio -> gpdcon = 0xaaaaaaaa ;                        //Initialize VD[15:8]

       lcd -> lcdcon1 = ( clkval_tft << 8 ) | ( MVAL_USED << 7 ) | (3 << 5 ) | ( 12 << 1 ) | 0 ;

       // TFT LCD panel,16bpp TFT,ENVID=off

       lcd -> lcdcon2 = ( vbpd << 24 ) | ( LINEVAL_TFT << 14 ) | ( vfpd << 6 ) | ( vspw ) ;

       lcd -> lcdcon3 = ( hbpd << 19 ) | ( HOZVAL_TFT << 8 ) | ( hfpd ) ;

       lcd -> lcdcon4 = ( MVAL << 8 ) | ( hspw ) ;

       lcd -> lcdcon5 = ( 1 << 11) | ( 0 << 10 ) | ( 1 << 9 ) | ( 1 << 8 ) | ( 0 << 7 ) | ( 0 << 6 ) | ( 1 << 3 ) | ( BSWP << 1 ) | ( HWSWP ) ;

       lcd -> lcdintmsk |= (3) ;                        // MASK LCD Sub Interrupt

       lcd -> lpcsel &= ( ~7 ) ;                        // Disable LPC3480

       lcd -> tpal = 0x0 ;                            // Disable Temp Palette

       tq2440_lcd_PowerEnable( 0, 1 ) ;

}

void lcd_enable(void)

{

       struct s3c24x0_lcd * const lcd = s3c24x0_get_base_lcd() ;

       lcd -> lcdcon1 |= 1 ;                        // ENVID=ON

}

添加編譯選項:

gedit drivers/video/Makefile

在其中添加:

obj-$(CONFIG_TQ2440_LCD) += tq2440_fb.o

  1. 将調試資訊同時定位到LCD和序列槽輸出

在u-boot啟動資訊中可看到,目前輸入輸出裝置均為serial。

移植u-boot-2016.11到TQ2440開發闆全過程記錄

使用coninifo指令檢視支援的終端:

移植u-boot-2016.11到TQ2440開發闆全過程記錄

使用setenv stdout 'lcd,serial'指令将輸出終端設定為LCD和序列槽,使用saveenv指令儲存。

  1. 燒錄到NAND Flash運作

setenv ethaddr 11:22:33:44:55:66;set serverip 192.168.1.10;nand erase 0 0x100000;tftp 32000000 u-boot.bin;nand write 32000000 0 0x100000