移植新(2012.04.01) U-Boot 到S3C2440之中
date: 2018年1月23日
简述:相关知识点可以参考视频教程的附带文档,本文主要是写出每一步的操作过程;
修改时钟,配置新板
建立单板
- board/samsung/smdk2440
cd ./board/samsung
cp -rf smdk2410 smdk2440
cd smdk2440; mv smdk2410.c smdk2440.c;
vim Makefile;
- COBJS := smdk2410.o
+ COBJS := smdk2440.o
- include/config/smdk2440.h
cd ./include/config
cp smdk2410.h smdk2440.h
- boards.cfg
vim boards.cfg
+ smdk2440 arm arm920t - samsung s3c24x0
(参考smdk2410的书写规范即可)
修改源代码使得u-boot可以在s3c2440上启动
- 调整时钟
原因:UBOOT以60MHZ的时钟参数计算参数设置内存控制器,但是MPLL还未设置。所以第一步
将MPLL的设置转移至 start.S 中,注释掉 board_early_init_f 中的 MPLL 的设置
/* ./arch/arm/cpu/arm920t/start.S */
line: 170
- /* FCLK:HCLK:PCLK = 1:2:4 */
- /* default FCLK is 120 MHz ! */
- ldr r0, =CLKDIVN
- mov r1, #3
- str r1, [r0]
+ /* FCLK:HCLK:PCLK = 1:4:8 */
+ /* default FCLK is 400 MHz ! */
+ /* 2. 设置时钟 */
+ ldr r0, =0x4c000014
+ // mov r1, #3 // FCLK:HCLK:PCLK= 1:2:4
+ mov r1, #5 // FCLK:HCLK:PCLK= 1:4:8
+ str r1, [r0]
+
+ /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
+ mrc p15, 0, r1, c1, c0, 0 /* 读出控制寄存器 */
+ orr r1, r1, #0xc0000000 /* 设置为“asynchronous bus mode” */
+ mcr p15, 0, r1, c1, c0, 0 /* 写入控制寄存器 */
+
+ #define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
+
+ /* MPLLCON = S3C2440_MPLL_200MHZ */
+ ldr r0, =0x4c000004
+ ldr r1, =S3C2440_MPLL_400MHZ /* 尽早进行时钟初始化,有利于提高效率 */
+ str r1, [r0]
+
+ /* 启动ICACHE */
+ mrc p15, 0, r0, c1, c0, 0 @ read control reg
+ orr r0, r0, #(1<<12) @ r0 = r0 | (1<<12)
+ mcr p15, 0, r0, c1, c0, 0 @ write it back
/* board/samsung/smdk2440/smdk2440.c */
line76:
- /* 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);
- 设置内存
/* board/samsung/smdk2440/lowlevel_init.S */
line 155:
- .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
+ .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 0x008C04F4 // REFRESH
+ .long 0x000000B1 //BANKSIZE
+ .long 0x00000030 //MRSRB6
+ .long 0x00000030 //MRSRB7
- 解决乱码问题 ( 串口波特率没有正确配置 )
原因:查看波特率设置(arch/arc/cpu/arm920t/s3c24x0/speed.c) 中配置get_HCLK里没有定义
CONFIG_S3C2440;解决方法:在 ./include/configs/smdk2440.h 中定义这个变量
/* ./include/configs/smdk2440.h */
line38:
- #define CONFIG_S3C2410
+ #define CONFIG_S3C2440
- 解决报错:s3c2410_nand.c 中报错
s3c2410_nand.c: In function 's3c2410_hwcontrol':
s3c2410_nand.c:57: warning: implicit declaration of function 's3c2410_get_base_nand'
s3c2410_nand.c:57: warning: initialization makes pointer from integer without a cast
s3c2410_nand.c:72: error: dereferencing pointer to incomplete type
s3c2410_nand.c:72: error: dereferencing pointer to incomplete type
s3c2410_nand.c:75: error: dereferencing pointer to incomplete type
s3c2410_nand.c:75: error: dereferencing pointer to incomplete type
原因:因为上步中注释掉了CONFIG_S3C2410 宏,而这个文件里需要的结构体是在这个宏定义的前提下使用,所以现在先将 nand 移除,不进行编译
/* ./include/configs/smdk2440.h */
line103:
- #define CONFIG_CMD_NAND
修改原有代码来支持 nand flash 启动
- 拷贝自己写的 init.c 到 u-boot 中来简化我们的操作
注意对 init.c 中的代码进行修改,修改有一下几个方面:
- 更改函数名,对于 nand_read , nand_init 之类存在外部调用的,将名字改的更具辨识度
- 对于nand_cmd, IsBootFromNor 之类的函数只存在文件内的调用,通过函数定义前添加
static 来限制函数的生效空间。- 删去代码中多余的部分;
cp /path/to/init.c/ ./board/samsung/smdk2440
vim Makefile
line 28:
- COBJS := smdk2440.o
+ COBJS := smdk2440.o init.o
- ./arch/arm/cpu/arm920t/start.S 中的修改
/* 1. ./arch/arm/cpu/arm920t/start.S */
line 182:
bl cpu_init_crit
#endif
+ ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) /* sp = 30000f80 */
+ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
+ bl nand_init_s3c2440
+ mov r0, #0
+ ldr r1, _TEXT_BASE
+ ldr r2, _bss_start_ofs
+ bl copy_code_to_sdram
+ bl clear_bss
+ ldr pc, =call_board_init_f
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
- ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
- bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r0,=0x00000000
bl board_init_f
+ /* unsigned int 的值正好存在r0里,正好给board_init_r */
+ ldr r1,=_TEXT_BASE
+ /* 调用第2阶段的代码 */
+ bl board_init_r
/* 2. 删除line:192-281; 重定位和clear_bss我们已经完成了 */
- /*--------------------------------------------------------------*/
- /*
- * void relocate_code (addr_sp, gd, addr_moni)
- * This "function" does not return, instead it continues in RAM
- * after relocating the monitor code.
- */
......
- clbss_l:str r2, [r0] /* clear loop... */
- add r0, r0, #4
- cmp r0, r1
- bne clbss_l
- bl coloured_LED_init
- bl red_led_on
- #endif
- 修改 CONFIG_SYS_INIT_SP_ADDR 的值
/* ./include/configs/smdk2440.h */
line: 43
- #define CONFIG_SYS_INIT_SP_ADDR 0x0
+ #define CONFIG_SYS_INIT_SP_ADDR 0x33f00000
- 修改board_init_f
/* 1. ./arch/arm/lib/board.c */
line 438:
- relocate_code(addr_sp, id, addr);
+ return (unsigned int)id;
line 259
- void board_init_f(ulong bootflag)
+ unsigned int board_init_f(ulong bootflag)
line 372
- addr -= gd->mon_len;
- addr &= ~(4096 - 1);
+ addr = CONFIG_SYS_TEXT_BASE;
/* 2. ./include/common.h */
line : 276
- void board_init_f (ulong) __attribute__ ((noreturn));
- void board_init_r (gd_t *, ulong) __attribute__ ((noreturn));
+ unsigned int board_init_f (ulong);
+ void board_init_r (gd_t *, unlong);
- 修改连接脚本,Makefile 去掉 '-pie'
"-pie" --- 生成位置无关码; 原来的代码中带有此选项导致最后生成的 u-boot.bin 过大,不适合在
nand 中启动;
/* 1. 修改Makefile ./arch/arm/config.mk */
line 75:
- LDFLAGS_u-boot += -pie
/* 2. 修改连接脚本,将start.S, init.c, lowlevel_init.S等文件放在最前面
* ./arch/arm/cpu/u-boot.lds
*/
line 38
+ board/samsung/smdk2440/libsmdk2440.o (.text)
- yaffs2部分报错
/* ./include/configs/smdk2440.h */
line: 228
- #define CONFIG_YAFFS2
目前为止所有修改过的文件:
- board/samsung/smdk2440/smdk2440.c
- arch/arm/cpu/arm920t/start.S
- board/samsung/smdk2440/lowlevel_init.S
- include/configs/smdk2440.h
- board/samsung/smdk2440/init.c
- arch/arm/lib/board.c
- include/common.h
- board/samsung/smdk2440/Makefile
- arch/arm/config.mk
- arch/arm/cpu/u-boot.lds
修改源码支持NorFlash
- 去掉 源码自带的Flash检测死循环
/* arch/arm/lib/board.c line 527: */
- puts(failed);
- hang();
+ puts("0KB\n\r");
- 在 cfi_flash.c 中打开调试开关以供分析
/* drivers/mtd/cfi_flash.c line 45 */
+ #define DEBUG 1
+ #define _DEBUG 1
// 最后记得把标志注释掉!!!!
- 添加我们自己的设备信息结构体
/* drivers/mtd/jedec_flash.c line 370 */
+ {
+ .mfr_id = (u16)MX_MANUFACT,
+ .dev_id = MX29LV160,
+ .name = "MXIC MX29LV160",
+ .uaddr = {
+ [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
+ },
+ .DevSize = SIZE_2MiB,
+ .CmdSet = P_ID_AMD_STD,
+ .NumEraseRegions= 4,
+ .regions = {
+ ERASEINFO(16 * 1024, 1),
+ ERASEINFO(8 * 1024, 2),
+ ERASEINFO(32 * 1024, 1),
+ ERASEINFO(64 * 1024, 31),
+ }
+ },
/* drivers/mtd/jedec_flash.c line 77 */
+ #define MX29LV160 0x2249
- 报错 too many flash sectors
/* include/configs/smdk2440.h line 190 */
- #define CONFIG_SYS_MAX_FLASH_SECT (19)
+ #define CONFIG_SYS_MAX_FLASH_SECT (128)
- 经过NORFlash 读写实验得出,u-boot 中的栈的设置不准确
/* arch/arm/cpu/arm920t/start.S line 113 */
/* 定义一个可以与C语言进行数据交换的变量
+ .globl base_sp
+ base_sp:
+ .long 0
/* arch/arm/cpu/arm920t/start.S line 232 */
+ ldr sp, base_sp /* 重新设置栈 */
/* arch/arm/lib/board.c line 265 */
+ extern ulong base_sp; /* 声明变量 */
/* arch/arm/lib/board.c line 439 */
+ base_sp = addr_sp;
目前为止所有修改过的文件:
- arch/arm/lib/board.c
- drivers/mtd/cfi_flash.c
- drivers/mtd/jedec_flash.c
- include/configs/smdk2440.h
- arch/arm/cpu/arm920t/start.S
- arch/arm/lib/board.c
修改源码支持NANDFlash
- 加上刚开始为了编译而注释掉的NAND的宏
/* ./include/configs/smdk2440.h */
line103:
+ #define CONFIG_CMD_NAND
- 创建对应于 S3C2440 的 NANDFlash 操作文件(s3c2440_nand.c)
# 1. 创建s3c2440_nand.c
cd drivers/mtd/nand
cp s3c2410_nand.c s3c2440_nand.c
# 2. 将s3c2440_nand.c 加入编译之中
/* 2.1 include/configs/smdk2440.h line 211 */
+ #ifdef CONFIG_S3C2410
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
+ #else
+ #define CONFIG_NAND_S3C2440
+ #define CONFIG_SYS_S3C2440_NAND_HWECC
+ #endif
# 2.2
cd drivers/mtd/nand
vim Makefile # line 61
+ COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
- 修改s3c2440_nand.c
/* drivers/mtd/nand/s3c2440_nand.c */
1. line 129:
- struct s3c2410_nand *nand_reg = s3c2410_get_base_nand();
+ struct s3c2440_nand *nand_reg = s3c2440_get_base_nand();
2. line 146
+ #if 0
cfg = S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
+ #endif
+ /* 初始化时序 */
+ cfg = ((tacls-1)<<12)|((twrph0-1)<<8)|((twrph1-1)<<4);
+ /* 使能NAND Flash控制器,初始化ECC,禁止片选 */
+ writel((1<<4)|(1<<1)|(1<<0), &nand_reg->nfcont);
3. line 90 - line 122 有关于ECC的部分删除
4. 替换 s3c2440_nand.c 中 所有s3c2410的函数名为s3c2440;
5. line 71:
- if (ctrl & NAND_NCE) /* 使能选中 */
- writel(readl(&nand->nfcont) & ~S3C2410_NFCONF_nFCE,
- &nand->nfconf);
- else /* 取消选中 */
- writel(readl(&nand->nfcont) | S3C2410_NFCONF_nFCE,
- &nand->nfconf);
+ if (ctrl & NAND_NCE) /* 使能选中 */
+ writel(readl(&nand->nfcont) & ~(1<<1),
+ &nand->nfcont);
+ else /* 取消选中 */
+ writel(readl(&nand->nfcont) | (1<<1),
+ &nand->nfcont);
6. 自己添加 s3c2440_nand_select 的函数
/* line 130 */
- nand->select_chip = NULL;
+ nand->select_chop = s3c2440_nand_select;
删除 函数 s3c2440_hwcontrol 的原有内容,自己重新完成
+ struct s3c2440_nand *nand = s3c2440_get_base_nand();
+ if (ctrl & NAND_CLE) {
+ /* 发命令 */
+ writeb (dat, &nand->nfcmd);
+ } else if (ctrl & NAND_ALE) {
+ /* 发地址 */
+ writeb (dat, &nand->nfaddr);
+ }
完成的s3c2440_nand_select函数
static void s3c2440_nand_select(struct mtd_info *mtd, int chipnr)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
switch (chipnr) {
case -1: /* 取消选中 */
nand->nfcont |= (1<<1);
break;
case 0: /* 选中 */
nand->nfcont &= ~(1<<1);
break;
default:
BUG();
}
}
目前为止所有修改过的文件:
- include/configs/smdk2440.h
- drivers/mtd/nand/s3c2440_nand.c
- drivers/mtd/nand/Makefile // 直接在u-boot 中进行修改注意检查
修改源码支持DM9000
u-boot 的代码有DM9000的网卡的代码,只需要修改配置文件编译即可
/* include/configs/smdk2440.h line 59 */
+ #if 0
#define CONFIG_CS8900 /* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE 0x19000300
#define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */
+ #else
+ #define CONFIG_DRIVER_DM9000
+ #endif
/* board/samsung/smdk2440/lowlevel_init.S line 160 */
- .long 0x00000700 //BANKCON4
+ .long 0x00000740 //BANKCON4
/* board/samsung/smdk2440/smdk2440.c line 141 */
+ #ifdef CONFIG_DRIVER_DM9000
+ rc = dm9000_initialize(bis);
+ #endif
- 测试未连通,*** ERROR: `ethaddr' not set
# 不要执行save,因为还没有设置参数存放地址
set ipaddr 192.168.1.17
set ethaddr 00:0c:29:b2:67:65 (不设置这个就会出现上述报错)
目前为止所有修改过的文件:
- include/configs/smdk2440.h
- board/samsung/smdk2440/lowlevel_init.S
- board/samsung/smdk2440/smdk2440.c
裁剪和设置环境变量,让u-boot更易用
1. 一些完善性的修改
- 传给内核的启动参数
/* include/configs/smdk2440.h line 162 */
#define CONFIG_BOOTARGS "console=ttySAC0,115200 root=/dev/mtdblock3"
#define CONFIG_BOOTCOMMAND "nand read 30000000; bootm 30000000 "
/* board/samsung/smdk2440.c line 116 */
- gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
+ gd->bd->bi_arch_number = MACH_TYPE_S3C2440;
/* include/configs/smdk2440.h line 123 */
- #define CONFIG_IPADDR 10.0.0.110
- #define CONFIG_SERVERIP 10.0.0.1
+ #define CONFIG_IPADDR 192.168.1.17
+ #define CONFIG_SERVERIP 192.168.1.25
+ #define CONFIG_ETHADDR 00:0c:29:b2:67:66
2. 删减
/* include/configs/smdk2440.h */
1. line 77 - 80 USB 部分
2. line 85 RTC 部分
3. line 93 - 96 BOOTP 部分
4. line 105, 106, 111
// #define CONFIG_CMD_DATE
// #define CONFIG_CMD_DHCP
// #define CONFIG_CMD_USB
5. line 237 - 245 文件系统部分
3. 分区
- 注释掉原有的环境变量设置: include/configs/smdk2440.h line 202 - 207
- 重设自己的环境变量宏:
/* include/configs/smdk2440.h line 210 */
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET 0x00040000
#define CONFIG_ENV_SIZE 0x00020000
#define CONFIG_ENV_RANGE CONFIG_ENV_SIZE
- 添加分区命令 mtdparts 至编译队列之中
/* include/configs/smdk2440.h line 215 */
+ #define CONFIG_CMD_MTDPARTS
+ #define CONFIG_MTD_DEVICE
+ #define MTDIDS_DEFAULT "nand0=jz2440-0" /* 哪一个设备 */
+ #define MTDPARTS_DEFAULT "mtdparts=jz2440-0:256k(u-boot)," \
+ "128k(params)," \
+ "3m(kernel)," \
+ "-(rootfs)" \
- 在 board.c 中设置分区
/* arch/arm/lib/board.c line 654 */
+ run_command ("mtdparts default", 0);
- 修改配置文件添加 yaffs2 支持
/* include/configs/smdk2440.h line 163 */
+ #define CONFIG_CMD_NAND_YAFFS
/* driver/mtd/nand/nand_util.c line 556 */
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OOB_RAW;
/* driver/mtd/nand/nand_util.c line 567 */
- if(!rval)
+ if (rval) /* 错误修改 */
目前为止所有修改过的文件:
- include/configs/smdk2440.h
- board/samsung/smdk2440/lowlevel_init.S
- board/samsung/smdk2440/smdk2440.c
- arch/arm/lib/board.c
- driver/mtd/nand/nand_util.c
制作补丁
diff -urN u-boot-2012.04.01 u-boot-2012.04.01_100ask > u-boot-2012.04.01_100ask.patch
补充: DNW下载方式操作
对于课程自带的 u-boot1.1.6 来说,u-boot 界面集成了dnw下载的快捷连接
选择相应选项,然后再用dnw下载文件即可。不过对于通过 u-boot1.1.6 来下载
u-boot2012.04.01 这种情况是无法使用现有选项的,因为bootloader的分区太小
放不下新版的u-boot
1. 对于下载到NORFlash的操作
# q 退出u-boot 的选择菜单
1. usb 1 30000000 # 连接usb, 此时可以通过dnw开始下载文件
2. protect off all # 关闭NORFlash 的写保护
3. erase 0 7FFFF # 擦出指定空间,第一个参数是起始地址,第二个参数是偏移量
4. cp.b 30000000 0 80000 # 拷贝文件到指定位置,第一个参数是源文件的首地址,第二个参数是目标地址,第三个参数是大小
2. 对于下载到NANDFlash的操作
# q 退出u-boot 的选择菜单
1. usb 1 30000000 # 连接usb, 此时可以通过dnw开始下载文件
2. nand erase 0 7FFFF # 擦出指定空间,第一个参数是起始地址,第二个参数是偏移量
3. nand write 30000000 0 80000 # 拷贝文件到指定位置,第一个参数是源文件的首地址,第二个参数是目标地址,第三个参数是大小