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的配置
4.2 在board\samsung\my2440\Makefile中修改要编译的文件
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文件中保存,实际上改动也比较大
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位置,并去掉如下两条返回语句,避免在还没有初始化栈的情况下,减少调用的深度,从而减少额外的寄存器使用
6. 对board\samsung\my2440\lowlevel_init.S文件的修改
6.1 在lowlevel_init.S中增加pre_lowlevel_init函数,此函数实现看门狗的关闭、中断屏蔽
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 ,lrView Code
6.2 在lowlevel_init.S中增加system_clock_init函数,此函数实现时钟初始化
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, lrView Code
6.3 在lowlevel_init.S中增加mem_ctrl_asm_init函数,此函数实现内存控制器初始化,就是原本的此文件中的代码,封装成一个函数
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, lrView Code
6.4 修改SDRAM存储器的刷新值
6. 5 在lowlevel_init函数中增加pre_lowlevel_init、system_clock_init、mem_ctrl_asm_init的调用
7. 系统时钟移植
7.1 在include\configs\my2440.h中将2410的宏改为2440,此处的修改需要在多个文件中增加对这两个宏的支持
7.2 在board\samsung\my2440\my2440.c中,增加时钟分频系数宏的定义
7.3 在cpu\arm920t\s3c24x0\speed.c中,在CONFIG_S3C2410宏条件处,增加对CONFIG_S3C2440的支持
7.4 在cpu\arm920t\s3c24x0\speed.c的get_PLLCLK函数内,增加S3C2440A MPLL时钟的获取
7.5 在cpu\arm920t\s3c24x0\speed.c的get_HCLK函数内,增加S3C2440A MPLL时钟的获取
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
7.6 在include\s3c24x0.h增加摄像头时钟分频器CAMDIVN
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方式),如下,只是还不完整,需要继续下面的移植动作
10. 串口移植
10.1 串口的初始化函数在lib_arm\board.c文件中start_armboot函数调用serial_initialize进行初始化,这部分的代码完全相同,所以不用修改
10.2 默认的串口为UART1,115200bps,可以在include\configs\my2440.h进行配置修改
11. 系统时钟移植,这部分已在步骤6.2、7中完成
12. NAND Flash移植
12.1 在cpu\arm920t\start.S栈初始化调用语句beq stack_setup后面增加copy_to_ram_from_nand函数调用
12.2 在board\samsung\my2440\lowlevel_init.S中,增加nand_asm_init函数调用即实现
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, lrView Code
12.3 在board\samsung\my2440目录下,新建一个nand_flash_cp.c文件,并添加如下代码
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的编译
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中实现
12.6 在include\configs\my2440.h中,增加对NAND FLASH支持的宏配置,宏名需要根据lib_arm\board.c对nand_init函数的宏控制一致
12.7 在include\s3c24x0.h文件中增加S3C2440A NAND控制器的结构体
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 #endifView Code
12.8 在drivers\mtd\nand目录下,新建s3c2440_nand.c文件,并增加如下代码,主要是对NAND FLASH的控制器的初始化,可参考s3c2410_nand.c进行修改
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文件的编译
12.10 执行命令:make---非必要,只是阶段性大概验证有没有错误的地方,以免大量错误留到最后来修改,如果顺利的话,此时编译的bin文件,可以在JZ2440的板子上启动(NAND FLASH方式),如下,只是还不完整,需要继续下面的移植动作
13. 网卡移植
13.1 在include\configs\my2440.h中,增加或修改如下宏
13.2 在include\configs\my2440.h中,增加如下标记宏,提供给内核
13.3 在board\samsung\my2440\lowlevel_init.S中,修改网卡所在BANK的时序控制寄存器值
13.4 在board\samsung\my2440\my2440.c中,增加或修改如下
13.5 在drivers\net\dm9000x.c dm9000_get_enetaddr函数中增加如下代码
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
13.6 在drivers\net\dm9000x.c dm9000_init函数中增加如下代码
13. 7 在include\configs\my2440.h中,增加或修改如下宏
14. U-BOOT环境参数配置,此部分其实在上面的移植中,基本已经差不多了,是剩下一小部分配置,如内核启动参数
14.1 在include\configs\my2440.h中增加如下宏,支持内核自启动
14.2 在include\configs\my2440.h中,修改加载地址
14.3 在board\samsung\my2440\my2440.c中,修改机器类型码,此值需要跟内核的机器类型码一致,这里可以先自行定义一个宏
14.4 在include\asm-arm\mach-types.h中,增加机器类型码(include\asm-arm\mach-types.h&include\asm\mach-types.h这两个文件内容是一样的,修改任何一个,另外一个都会跟着变),
15. 执行命令:make,如有内核则会有如下信息,内核通过tftp会自动加载,如下
总结:
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