U-BOOT移植是一个比较繁琐的事情,这里记录一下尽量简短的可用移植

 

1. 环境:

1.1. 开发板:JZ2440 V3(很老的一款开发板)

1.2. U-BOOT版本:u-boot-2009.11

1.3 Linux OS:Ubuntu20.04

1.4 交叉编译工具:arm-linux-gcc-3.4.5-glibc-2.3.6

 

2. 主要移植内容

2.1 串口

2.2 系统时钟

2.3 nand flash:K9F2G08U0C

2.4 网卡:DM9000CEP

2.5 U-BOOT环境参数配置

 

3. 准备工作

3.1 以SMDK210为基础

3.2 复制board\samsung\smdk2410为board\samsung\my2440,并将board\samsung\my2440\smdk2410.c改名为board\samsung\my2440\my2440.c

3.3 复制include\configs\smdk2410.h为include\configs\my2440.h

 

4. 建立my2440配置

4.1 在顶层Makefile中增加my2440的配置

JZ2440 U-BOOT移植_串口

4.2 在board\samsung\my2440\Makefile中修改要编译的文件

JZ2440 U-BOOT移植_初始化_02

4.3 执行命令(非必须,4.3&4.4旨在通过编译,阶段性检查有误错误):make my2440_config

4.4 执行命令(非必须,4.3&4.4旨在通过编译,阶段性检查有误错误,若一切顺利,根目录下会生成bin文件):make

 

5. 对cpu\arm920t\start.S文件的修改

5.1 将板级相关的中断、看门狗、时钟的初始化代码移至board\samsung\my2440\lowlevel_init.S中,这里暂且剪切到一个txt文件中保存,实际上改动也比较大

JZ2440 U-BOOT移植_3c_03JZ2440 U-BOOT移植_3c_04
 1 #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
 2     /* turn off the watchdog */
 3 
 4 # if defined(CONFIG_S3C2400)
 5 #  define pWTCON    0x15300000
 6 #  define INTMSK    0x14400008    /* Interupt-Controller base addresses */
 7 #  define CLKDIVN    0x14800014    /* clock divisor register */
 8 #else
 9 #  define pWTCON    0x53000000
10 #  define INTMSK    0x4A000008    /* Interupt-Controller base addresses */
11 #  define INTSUBMSK    0x4A00001C
12 #  define CLKDIVN    0x4C000014    /* clock divisor register */
13 # endif
14 
15     ldr    r0, =pWTCON
16     mov    r1, #0x0
17     str    r1, [r0]
18 
19     /*
20      * mask all IRQs by setting all bits in the INTMR - default
21      */
22     mov    r1, #0xffffffff
23     ldr    r0, =INTMSK
24     str    r1, [r0]
25 # if defined(CONFIG_S3C2410)
26     ldr    r1, =0x3ff
27     ldr    r0, =INTSUBMSK
28     str    r1, [r0]
29 # endif
30 
31     /* FCLK:HCLK:PCLK = 1:2:4 */
32     /* default FCLK is 120 MHz ! */
33     ldr    r0, =CLKDIVN
34     mov    r1, #3
35     str    r1, [r0]
36 #endif    /* CONFIG_S3C2400 || CONFIG_S3C2410 */
View Code

5.2 将cpu_init_crit函数的代码拷贝到bl cpu_init_crit位置,并去掉如下两条返回语句,避免在还没有初始化栈的情况下,减少调用的深度,从而减少额外的寄存器使用

JZ2440 U-BOOT移植_初始化_05

 

6. 对board\samsung\my2440\lowlevel_init.S文件的修改

6.1 在lowlevel_init.S中增加pre_lowlevel_init函数,此函数实现看门狗的关闭、中断屏蔽

JZ2440 U-BOOT移植_3c_03JZ2440 U-BOOT移植_3c_04
 1 pre_lowlevel_init:
 2     #define pWTCON    0x53000000
 3      #define INTMSK    0x4A000008    /* Interupt-Controller base addresses */
 4      #define INTSUBMSK    0x4A00001C
 5      #define CLKDIVN    0x4C000014    /* clock divisor register */
 6 
 7     /*关闭看门狗*/
 8     ldr    r0, =pWTCON
 9     mov    r1, #0x0
10     str    r1, [r0]
11 
12     /*关闭中断/
13     mov    r1, #0xffffffff
14     ldr    r0, =INTMSK
15     str    r1, [r0]
16 
17     ldr    r1, =0x7fff
18     ldr    r0, =INTSUBMSK
19     str    r1, [r0]
20 
21     /*函数返回*/
22     mov pc ,lr
View Code

6.2 在lowlevel_init.S中增加system_clock_init函数,此函数实现时钟初始化

JZ2440 U-BOOT移植_3c_03JZ2440 U-BOOT移植_3c_04
 1 system_clock_init:
 2     #define CLKDIVN    0x4C000014    
 3     #define CLK_CTL_BASE    0x4C000000    
 4     #define MDIV_400M    0x5C << 12    /*根据数据手册设置,这里主频设置400MHz*/
 5     #define PDIV_400M    0x1 << 4    /*根据数据手册设置,这里主频设置400MHz*/
 6     #define SDIV_400M    0x1            /*根据数据手册设置,这里主频设置400MHz*/
 7     #define CLKDIV 0x5   /* FCLK:HCLK:PCLK = 1:4:8 */
 8 
 9     ldr    r0, =CLKDIVN 
10     mov    r1, #CLKDIV
11     str    r1, [r0]
12 
13     /*异步时钟模式设置,暂未明白此处代码*/
14     mrc    p15, 0, r1, c1, c0, 0    
15     orr    r1, r1, #0xc0000000        
16     mcr    p15, 0, r1, c1, c0, 0    
17 
18     mov    r1, #CLK_CTL_BASE    
19     mov    r2, #MDIV_400M
20     add    r2, r2, #PDIV_400M
21     add    r2, r2, #SDIV_400M
22     
23     str    r2, [r1, #0x04]        /* MPLLCON  */
24     
25     /*函数返回*/
26     mov    pc, lr
View Code

6.3 在lowlevel_init.S中增加mem_ctrl_asm_init函数,此函数实现内存控制器初始化,就是原本的此文件中的代码,封装成一个函数

JZ2440 U-BOOT移植_3c_03JZ2440 U-BOOT移植_3c_04
 1 mem_ctrl_asm_init:
 2     ldr     r0, =SMRDATA
 3     ldr    r1, _TEXT_BASE
 4     sub    r0, r0, r1
 5     ldr    r1, =BWSCON    /* Bus Width Status Controller */
 6     add     r2, r0, #13*4
 7 0:
 8     ldr     r3, [r0], #4
 9     str     r3, [r1], #4
10     cmp     r2, r0
11     bne     0b
12     
13     /*函数返回*/
14     mov    pc, lr
View Code

6.4 修改SDRAM存储器的刷新值

JZ2440 U-BOOT移植_#include_12

6. 5 在lowlevel_init函数中增加pre_lowlevel_init、system_clock_init、mem_ctrl_asm_init的调用

JZ2440 U-BOOT移植_#include_13

 

7. 系统时钟移植

7.1 在include\configs\my2440.h中将2410的宏改为2440,此处的修改需要在多个文件中增加对这两个宏的支持

JZ2440 U-BOOT移植_初始化_14

 7.2 在board\samsung\my2440\my2440.c中,增加时钟分频系数宏的定义

JZ2440 U-BOOT移植_#include_15

7.3 在cpu\arm920t\s3c24x0\speed.c中,在CONFIG_S3C2410宏条件处,增加对CONFIG_S3C2440的支持

JZ2440 U-BOOT移植_#include_16

7.4 在cpu\arm920t\s3c24x0\speed.c的get_PLLCLK函数内,增加S3C2440A MPLL时钟的获取

JZ2440 U-BOOT移植_#include_17

7.5 在cpu\arm920t\s3c24x0\speed.c的get_HCLK函数内,增加S3C2440A MPLL时钟的获取

JZ2440 U-BOOT移植_3c_03JZ2440 U-BOOT移植_3c_04
 1 ulong get_HCLK(void)
 2 {
 3     struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
 4 
 5     #if defined(CONFIG_S3C2440)
 6         u32 hdivn = (readl(&clk_power->CLKDIVN) >> 1) & 0x3; 
 7     if (hdivn == 0x0) 
 8         return (get_FCLK());
 9     else if (hdivn == 0x1)
10         return (get_FCLK()/2);
11     else if (hdivn == 0x2)
12         return ((readl(&clk_power->CAMDIVN) & 0x200) ? get_FCLK()/8 : get_FCLK()/4);
13     else  /* hdivn == 0x3 */ 
14         return ((readl(&clk_power->CAMDIVN) & 0x100) ? get_FCLK()/6 : get_FCLK()/3);
15 
16     #else
17         return (readl(&clk_power->CLKDIVN) & 2) ? get_FCLK() / 2 : get_FCLK();
18     #endif
19 }
View Code

JZ2440 U-BOOT移植_串口_20

7.6 在include\s3c24x0.h增加摄像头时钟分频器CAMDIVN

JZ2440 U-BOOT移植_#include_21

 

 8. 在如下文件中增加对CONFIG_S3C2440&CONFIG_MY2440宏的支持,即在CONFIG_S3C2410、CONFIG_SMDK2410处都增加这两个宏,即在其后增加  || defined(CONFIG_S3C2440),或者|| defined(CONFIG_MY2440)

8.1 串口部分,此部分代码与S3C2410共用,common\serial.c(共两处);include\serial.h(共一处);drivers\serial\serial_s3c24x0.c(共一处)

8.2 时钟获取函数,include\common.h(共一处);

8.3 寄存器结构体,include\s3c24x0.h(共六处)

8.4 RTC驱动,drivers\rtc\s3c24x0_rtc.c(共一处)

8.5 定时器,cpu\arm920t\s3c24x0\timer.c(共三处,其中一处为CONFIG_SMDK2410需要增加CONFIG_MY2440宏的支持)

 

9. 执行命令:make---非必要,只是阶段性大概验证有没有错误的地方,以免大量错误留到最后来修改,如果顺利的话,此时编译的bin文件,可以在JZ2440的板子上启动(NOR FLASH方式),如下,只是还不完整,需要继续下面的移植动作

JZ2440 U-BOOT移植_#include_22

 

10. 串口移植

10.1 串口的初始化函数在lib_arm\board.c文件中start_armboot函数调用serial_initialize进行初始化,这部分的代码完全相同,所以不用修改

10.2 默认的串口为UART1,115200bps,可以在include\configs\my2440.h进行配置修改

JZ2440 U-BOOT移植_初始化_23

 

11. 系统时钟移植,这部分已在步骤6.2、7中完成

 

12. NAND Flash移植

12.1 在cpu\arm920t\start.S栈初始化调用语句beq stack_setup后面增加copy_to_ram_from_nand函数调用

JZ2440 U-BOOT移植_初始化_24

 12.2 在board\samsung\my2440\lowlevel_init.S中,增加nand_asm_init函数调用即实现

JZ2440 U-BOOT移植_3c_03JZ2440 U-BOOT移植_3c_04
 1 nand_asm_init:
 2     #define S3C2440_NAND_BASE    0x4E000000
 3     #define NFCONF_OFFSET 0x0
 4     #define NFCONT_OFFSET 0x4
 5 
 6     ldr r0, =S3C2440_NAND_BASE
 7     ldr r1, =0x001210       /*TACLS、TWROPH0、TWRPH1值的设置,结合S3C2440A&NAND FLASH数据手册计算一个比较合理的值*/
 8     str r1, [r0, #NFCONF_OFFSET]
 9     
10     mov r1, #0x3
11     str r1, [r0, #NFCONT_OFFSET]
12 
13     /*函数返回*/
14     mov pc, lr
View Code

JZ2440 U-BOOT移植_#include_27

12.3 在board\samsung\my2440目录下,新建一个nand_flash_cp.c文件,并添加如下代码

JZ2440 U-BOOT移植_3c_03JZ2440 U-BOOT移植_3c_04
  1 #include <common.h>
  2 #include <linux/mtd/nand.h>
  3 #include <s3c2410.h>
  4 #include <asm/io.h>  /*为了使用writeb,readb函数*/
  5 
  6 #define NF_CMD(nand, cmd)   writeb(cmd, &nand->NFCMD)
  7 #define NF_ADDR(nand, addr)  writeb(addr, &nand->NFADDR)
  8 #define NF_RDDATA8(nand)    readb(&nand->NFDATA)
  9 #define NF_ENABLE_CE(nand)  writel(readl(&nand->NFCONT) & ~(1<<1), &nand->NFCONT)
 10 #define NF_DISABLE_CE(nand) writel(readl(&nand->NFCONT) | (1<<1), &nand->NFCONT)
 11 #define NF_CLEAR_RB(nand)   writel(readl(&nand->NFSTAT) | (1<<2), &nand->NFSTAT)
 12 #define NF_DETECT_RB(nand) do{while(!(readl(&nand->NFSTAT) & (1<<2))); }while(0)
 13 
 14 static void nandll_reset(void)
 15 {
 16     struct s3c2410_nand *nand = s3c2410_get_base_nand();
 17 
 18     NF_ENABLE_CE(nand);  
 19     NF_CLEAR_RB(nand);
 20     NF_CMD(nand, NAND_CMD_RESET);
 21     NF_DETECT_RB(nand);
 22     NF_DISABLE_CE(nand);
 23 
 24 }
 25 
 26 
 27 
 28 static int nandll_read_page(uchar *buf, ulong addr, int large_block)
 29 {
 30     int i;
 31     int page_size = 512;     //默认小页
 32     struct s3c2410_nand *nand = s3c2410_get_base_nand();
 33 
 34     if(large_block)  //如果是大页
 35         page_size = 2048;
 36 
 37     NF_ENABLE_CE(nand);
 38     NF_CLEAR_RB(nand);
 39     NF_CMD(nand, NAND_CMD_READ0);
 40 
 41     //大页五个周期,两个列地址(页内地址),三个行地址(页地址);小页四个周期;此项操作可参考nand flash的数据手册
 42     NF_ADDR(nand, 0x0); 
 43     if(large_block)
 44         NF_ADDR(nand, 0x0);
 45     NF_ADDR(nand, addr & 0xff);
 46     NF_ADDR(nand, (addr >> 8) & 0xff);
 47     NF_ADDR(nand, (addr >> 16) & 0xff);
 48 
 49     if(large_block)
 50         NF_CMD(nand, NAND_CMD_READSTART);
 51     NF_DETECT_RB(nand);
 52 
 53     for(i = 0; i < page_size; i++)
 54         buf[i] = NF_RDDATA8(nand);
 55     
 56     NF_DISABLE_CE(nand);
 57 
 58     return 0;
 59 
 60 }
 61 
 62 
 63 static int nandll_read_blocks(ulong dst_addr, ulong size, int large_block)
 64 {
 65     int i;
 66     uchar *buf = (uchar *)dst_addr;
 67     uint page_shift = 9;  //小页
 68 
 69     if(large_block)
 70         page_shift = 11;  //大页
 71     
 72     //size表示有多少个块,读取的内容全部存到buf中
 73     for(i = 0; i < (size >> page_shift); i++, buf += (1 << page_shift))
 74         nandll_read_page(buf, i, large_block);
 75     
 76     return 0;
 77 
 78 }
 79 
 80 
 81 int copy_to_ram_from_nand(void)
 82 {
 83     int large_block = 0;
 84     int i;
 85     vu_char id;
 86     
 87     struct s3c2410_nand *nand = s3c2410_get_base_nand();
 88 
 89     NF_ENABLE_CE(nand);
 90     NF_CMD(nand, NAND_CMD_READID);
 91     NF_ADDR(nand, 0x0);
 92     for(i = 0; i < 200; i++);  //为了保证命令已经写入到nand flash中?
 93 
 94     id = NF_RDDATA8(nand);
 95     id = NF_RDDATA8(nand);
 96 
 97     nandll_reset();
 98 
 99     if(id > 0x80)
100         large_block = 1;
101 
102     //TEXT_BASE,SDRAM的地址,即要拷贝到内存中的哪个起始地址
103     return nandll_read_blocks(TEXT_BASE, CONFIG_UBOOT_SIZE, large_block);
104 
105 }
View Code

12.4 在board\samsung\my2440\Makefile中增加nand_flash_cp.c的编译

JZ2440 U-BOOT移植_初始化_30

12.5 在顶层链接文件u-boot.lds中,将nand_flash_cp.o、lowlevel_init.o尽量靠前放置,因为S3C2440内部垫脚石(SRAM)程序只能拷贝NAND FLASH中的前4KB的代码,后面的代码只能靠U-BOOT自身拷贝,所以U-BOOT中的拷贝代码的实现要放在前4KB内,而这部分代码的实现又是nand_flash_cp.c中实现

JZ2440 U-BOOT移植_3c_31

 12.6 在include\configs\my2440.h中,增加对NAND FLASH支持的宏配置,宏名需要根据lib_arm\board.c对nand_init函数的宏控制一致

JZ2440 U-BOOT移植_#define_32

JZ2440 U-BOOT移植_串口_33

12.7 在include\s3c24x0.h文件中增加S3C2440A NAND控制器的结构体

JZ2440 U-BOOT移植_3c_03JZ2440 U-BOOT移植_3c_04
 1 #if defined(CONFIG_S3C2410)
 2 struct s3c2410_nand {
 3     S3C24X0_REG32    NFCONF;
 4     S3C24X0_REG32    NFCMD;
 5     S3C24X0_REG32    NFADDR;
 6     S3C24X0_REG32    NFDATA;
 7     S3C24X0_REG32    NFSTAT;
 8     S3C24X0_REG32    NFECC;
 9 };
10 #elif defined(CONFIG_S3C2440)
11 struct s3c2410_nand {
12     S3C24X0_REG32    NFCONF;
13     S3C24X0_REG32    NFCONT;
14     S3C24X0_REG32    NFCMD;
15     S3C24X0_REG32    NFADDR;
16     S3C24X0_REG32    NFDATA;
17     S3C24X0_REG32    NFMECCD0;
18     S3C24X0_REG32    NFMECCD1;
19     S3C24X0_REG32    NFSECCD;
20     S3C24X0_REG32    NFSTAT;
21     S3C24X0_REG32    NFESTAT0;
22     S3C24X0_REG32    NFESTAT1;
23     S3C24X0_REG32    NFMECC0;
24     S3C24X0_REG32    NFMECC1;
25     S3C24X0_REG32    NFSECC;
26     S3C24X0_REG32    NFSBLK;
27     S3C24X0_REG32    NFEBLK;
28 };
29 #endif
View Code

JZ2440 U-BOOT移植_初始化_36

12.8 在drivers\mtd\nand目录下,新建s3c2440_nand.c文件,并增加如下代码,主要是对NAND FLASH的控制器的初始化,可参考s3c2410_nand.c进行修改

JZ2440 U-BOOT移植_3c_03JZ2440 U-BOOT移植_3c_04
  1 /*
  2  *  drivers/mtd/nand/s3c2440_nand.c
  3  *  Copyright (C) 2009-2012 Richard Fan (Guo Qian)
  4  *  
  5  *  s3c2410/s3c2440 nand flash driver, available for 
  6  *  SLC 512/1024/2048 bytes page size.
  7  */
  8 #include <common.h>
  9 
 10 #include <nand.h>
 11 #include <s3c2410.h>
 12 #include <asm/io.h>
 13 
 14 #include <asm/errno.h>
 15 #define NFCONT_EN          (1<<0)
 16 #define NFCONT_INITECC     (1<<4)
 17 #define NFCONT_nFCE        (1<<1)
 18 #define NFCONT_MAINECCLOCK (1<<5)
 19 #define NFCONF_TACLS(x)    ((x)<<12)
 20 #define NFCONF_TWRPH0(x)   ((x)<<8)
 21 #define NFCONF_TWRPH1(x)   ((x)<<4)
 22 
 23 
 24 
 25 static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 26 {
 27     struct s3c2410_nand *nand = s3c2410_get_base_nand();
 28 
 29     if (ctrl & NAND_CTRL_CHANGE) {
 30         if (ctrl & NAND_NCE)
 31             writel(readl(&nand->NFCONT) & ~NFCONT_nFCE,
 32                    &nand->NFCONT);
 33         else
 34             writel(readl(&nand->NFCONT) | NFCONT_nFCE,
 35                    &nand->NFCONT);
 36     }
 37 
 38     if (cmd != NAND_CMD_NONE) {
 39         if (ctrl & NAND_CLE)
 40             writeb(cmd, &nand->NFCMD);
 41         else if (ctrl & NAND_ALE)
 42             writeb(cmd, &nand->NFADDR);
 43     }               
 44 }
 45 
 46 static int s3c2410_dev_ready(struct mtd_info *mtd)
 47 {
 48     struct s3c2410_nand *nand = s3c2410_get_base_nand();
 49     debugX(1, "dev_ready\n");
 50     return readl(&nand->NFSTAT) & 0x01;
 51 }
 52 
 53 #ifdef CONFIG_S3C2410_NAND_HWECC
 54 void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 55 {
 56     struct s3c2410_nand *nand = s3c2410_get_base_nand();
 57     debugX(1, "s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode);
 58     writel(readl(&nand->NFCONF) | S3C2410_NFCONF_INITECC, &nand->NFCONF);
 59 }
 60 
 61 static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 62                       u_char *ecc_code)
 63 {
 64     ecc_code[0] = NFECC0;
 65     ecc_code[1] = NFECC1;
 66     ecc_code[2] = NFECC2;
 67     debugX(1, "s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n",
 68            mtd , ecc_code[0], ecc_code[1], ecc_code[2]);
 69 
 70     return 0;
 71 }
 72 
 73 static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 74                      u_char *read_ecc, u_char *calc_ecc)
 75 {
 76     if (read_ecc[0] == calc_ecc[0] &&
 77         read_ecc[1] == calc_ecc[1] &&
 78         read_ecc[2] == calc_ecc[2])
 79         return 0;
 80 
 81     printf("s3c2410_nand_correct_data: not implemented\n");
 82     return -1;
 83 }
 84 #endif
 85 
 86 int board_nand_init(struct nand_chip *nand)
 87 {
 88     u_int32_t cfg;
 89     u_int8_t tacls, twrph0, twrph1;
 90     struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
 91     struct s3c2410_nand *nand_reg = s3c2410_get_base_nand();
 92 
 93     debugX(1, "board_nand_init()\n");
 94 
 95     writel(readl(&clk_power->CLKCON) | (1 << 4), &clk_power->CLKCON);
 96 
 97     /* initialize hardware */
 98     twrph0 = 2;
 99     twrph1 = 1;
100     tacls = 1;
101 
102     cfg = 0;
103     cfg |= NFCONF_TACLS(tacls - 1);
104     cfg |= NFCONF_TWRPH0(twrph0 - 1);
105     cfg |= NFCONF_TWRPH1(twrph1 - 1);
106     writel(cfg, &nand_reg->NFCONF);
107 
108     cfg = (1<<4) | (0<<1) | (1<<0);
109     writel(cfg, &nand_reg->NFCONT);
110 
111 
112     /* initialize nand_chip data structure */
113     nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)&nand_reg->NFDATA;
114 
115     /* read_buf and write_buf are default */
116     /* read_byte and write_byte are default */
117 
118     /* hwcontrol always must be implemented */
119     nand->cmd_ctrl = s3c2410_hwcontrol;
120 
121     nand->dev_ready = s3c2410_dev_ready;
122 
123 #ifdef  CONFIG_NAND_HWECC
124     nand->ecc.mode = NAND_ECC_HW;
125 
126     nand->ecc.hwctl = s3c_nand_enable_hwecc;
127     nand->ecc.calculate = s3c_nand_calculate_ecc;
128     nand->ecc.correct = s3c_nand_correct_data;
129 
130     nand->ecc.size = 512;
131     nand->ecc.bytes = 4;
132 
133     nand->ecc.read_page = s3c_nand_read_page;
134     nand->ecc.write_page = s3c_nand_write_page;
135     nand->ecc.read_oob = s3c_nand_read_oob;
136     nand->ecc.write_oob = s3c_nand_write_oob;
137 
138     nand->cmd_ctrl(0, NAND_CMD_READID, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
139     nand->cmd_ctrl(0, 0x00, NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE);
140     nand->dev_ready(0);
141 
142     readb(nand->IO_ADDR_R);
143     if(readb(nand->IO_ADDR_R) > 0x80)
144         nand->ecc.layout = &s3c_nand_oob_64;
145     else
146         nand->ecc.layout = &s3c_nand_oob_16;
147         
148 #else
149     nand->ecc.mode = NAND_ECC_SOFT;
150 
151 #endif
152 
153 #ifdef CONFIG_S3C2410_NAND_BBT
154     nand->options = NAND_USE_FLASH_BBT;
155 #else
156     nand->options = NAND_SKIP_BBTSCAN;
157 #endif
158 
159     debugX(1, "end of nand_init\n");
160 
161     return 0;
162 }
View Code

12.9 在drivers\mtd\nand\Makefile中,增加s3c2440_nand.c文件的编译

JZ2440 U-BOOT移植_初始化_39

12.10 执行命令:make---非必要,只是阶段性大概验证有没有错误的地方,以免大量错误留到最后来修改,如果顺利的话,此时编译的bin文件,可以在JZ2440的板子上启动(NAND FLASH方式),如下,只是还不完整,需要继续下面的移植动作

JZ2440 U-BOOT移植_#include_40

 

13. 网卡移植

13.1 在include\configs\my2440.h中,增加或修改如下宏

JZ2440 U-BOOT移植_串口_41

JZ2440 U-BOOT移植_初始化_42

13.2 在include\configs\my2440.h中,增加如下标记宏,提供给内核

JZ2440 U-BOOT移植_#include_43

13.3 在board\samsung\my2440\lowlevel_init.S中,修改网卡所在BANK的时序控制寄存器值

JZ2440 U-BOOT移植_#define_44

13.4 在board\samsung\my2440\my2440.c中,增加或修改如下

JZ2440 U-BOOT移植_串口_45

JZ2440 U-BOOT移植_串口_46

13.5 在drivers\net\dm9000x.c  dm9000_get_enetaddr函数中增加如下代码

JZ2440 U-BOOT移植_3c_03JZ2440 U-BOOT移植_3c_04
 1 static void dm9000_get_enetaddr(struct eth_device *dev)
 2 {
 3 #if !defined(CONFIG_DM9000_NO_SROM)
 4     int i;
 5     for (i = 0; i < 3; i++)
 6         dm9000_read_srom_word(i, dev->enetaddr + (2 * i));
 7 #else
 8     u8 i;
 9     char *s,*e;
10     s = getenv("ethaddr");
11     for(i = 0; i < 6; i++)
12     {
13         dev->enetaddr[i] = s ? simple_strtoul(s,&e,16):0;
14         if(s)
15             s = (*e) ? e + 1 : e;
16     }
17     
18 #endif
19 }
View Code

JZ2440 U-BOOT移植_串口_49

13.6 在drivers\net\dm9000x.c dm9000_init函数中增加如下代码

 JZ2440 U-BOOT移植_#define_50

13. 7 在include\configs\my2440.h中,增加或修改如下宏

JZ2440 U-BOOT移植_#include_51

 

 14. U-BOOT环境参数配置,此部分其实在上面的移植中,基本已经差不多了,是剩下一小部分配置,如内核启动参数

14.1 在include\configs\my2440.h中增加如下宏,支持内核自启动

JZ2440 U-BOOT移植_#include_52

14.2 在include\configs\my2440.h中,修改加载地址

JZ2440 U-BOOT移植_#define_53

14.3 在board\samsung\my2440\my2440.c中,修改机器类型码,此值需要跟内核的机器类型码一致,这里可以先自行定义一个宏

JZ2440 U-BOOT移植_#define_54

14.4 在include\asm-arm\mach-types.h中,增加机器类型码(include\asm-arm\mach-types.h&include\asm\mach-types.h这两个文件内容是一样的,修改任何一个,另外一个都会跟着变),

JZ2440 U-BOOT移植_#define_55

 

 15. 执行命令:make,如有内核则会有如下信息,内核通过tftp会自动加载,如下

 JZ2440 U-BOOT移植_3c_56

 

 总结:

1. 时钟、NAND FLASH的初始化,在汇编阶段和C语言阶段都需要进行同样的操作

2. NAND FLASH拷贝到SDRAM的代码,应该是可以通用的,后面的其他产品移植,同样可以参考使用

3. 在调用C语言前,汇编阶段一定要先初始化栈,并且给予一定的运行空间,如mov sp,#0x1000

4. 串口的初始化,从代码来看,可以完全放到C语言阶段

5. 驱动的移植一定要结合实际的电路物理连接、CPU、外围芯片来进行移植

6. 串口的波特率设置有点奇怪,有时改不过来的样子,如在include\configs\my2440.h配置文件中将CONFIG_BAUDRATE参数115200bps改成57600bps,这是个很奇怪的问题,为了对照,这里上传一个移植OK的U-BOOT

 

按照上述步骤移植OK的U-BOOT&电路图&芯片数据手册:

链接:https://pan.baidu.com/s/1KwSqaFgi5FI_Odz4CLe7Dw
提取码:qkkm