移植u-boot-2012.04.01到s3c2440

看了韦东山老师的u-boot-2012.04.01移植,然后把大概移植内容整理了一下,如下。

开发环境:

u-boot-2012.04.01

arm-linux-gcc-4.3.2.tar

1.环境配置:

老版本的gcc编译器编译时有问题,所以使用4.3.2

解压到根目录:

book@book-desktop:/work/tools$sudo tar xjf arm-linux-gcc-4.3.2.tar.bz2 -C /

查看环境变量:

book@book-desktop:/work/tools$echo $PATH
book@book-desktop:/work/tools$/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

设置环境变量:以下两种方法均可

1)book@book-desktop:/work/tools$export PATH=/usr/local/arm/4.3.2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

2)book@book-desktop:/work/tools$ sudo vi /etc/environment

需要用到的gcc编译器、u-boot-2012.04.01在以下地址:

http://download.youkuaiyun.com/detail/qq361294382/9501324

2.u-boot启动流程分析

2.1 自己写的精简版u-boot:

a.初始化硬件: 关看门狗、设置时钟、设置SDRAM、初始化NAND FLASH
b.如果bootloader比较大,要把它重定位到SDRAM
c.把内核从NAND FLASH读到SDRAM
d.设置“要传给内核的参数”
e.跳转执行内核

2.2新版u-boot

1 set the cpu to SVC32 mode
2 turn off the watchdog

3 mask all IRQS by setting all bits in the INTMR

4 设置时钟比例
5 设置内存控制器
6 设置栈,调用C函数board_init_f
7 调用函数数组init_sequence里的各个函数  board.c->board_init_f
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
7.1 board_early_init_f: 设置系统时钟、设置GPIO
可以修改配置文件,定义CONFIG_S3C2440
8 重定位代码:
arm-linux-ld --help | grep pie
  -pie, --pic-executable      Create a position independent executable
8.1 从NOR FLASH把代码复制到链接地址SDRAM中
8.2 程序的链接地址是0.访问全局变量、静态变量、调用函数时是使"基于0地址编译得到的地址"
现在把程序复制到了SDRAM
需要修改代码,把"基于0地址编译得到的地址“改为新地址
1) 复制到哪里?任选
2) 复制过去后,为何能执行:修改代码,改变里面的变量、函数  
8.3 程序里有些地址在链接是不能确定,要到运行前才能确定:fixabs
9 clear_bss  

10调用C函数board_init_r: 第二阶段的代码

看似差别挺大,其实原理相同,只是根据适应性不同,实现起来步骤有点差别。

3.修改u-boot-2012.04.01代码

3.1 新建一个单板
cd board/samsung/
cp smdk2410 smdk2440 -rf
cd ../../include/configs/
cp smdk2410.h smdk2440.h         
修改:boards.config                    
仿照:smdk2410   arm arm920t-samsungs3c24x0
添加:smdk2440   arm arm920t-samsungs3c24x0                                                      
make smdk2440_config
make 
3.2 烧写看结果

   阅读代码发现不足:UBOOT里先以60MHZ的时钟计算参数来设置内存控制器,但是MPLL还未设置
   处理措施: 把MPLL的设置放到start.S里,取消board_init_f->init_sequence->board_early_init_f里对MPLL的设置

乱码,查看串口波特率的设置,发现在get_HCLK里没有定义CONFIG_S3C2440
处理措施: 

include/configs/smdk2440.h  :去掉CONFIG_S3C2410     根据Makefile找到根据哪个宏编译模块,把对应的宏去掉即可                  去掉#define CONFIG_S3C2410
 添加#define CONFIG_S3C2440
 有错误,去掉下面#define CONFIG_CMD_NAND

3.3参考"毕业班第一课"的start.S、init.c来修改代码

把init.c放入board/samsung/smdk2440目录,修改Makefile 添加init.c  -> COBJS:= smdk2410.o init.o
修改init.c 函数+static
smdk2440.h: #define CONFIG_SYS_TEXT_BASE 0x33f80000//改  34000000 - 33f80000 = 512k 用于SDRAM中存放代码

start.S中修改时钟配置信息:

 ldr r0, =0x4c000014
  /* mov r1, #0x03;      FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1*/
  mov r1, #0x05;     /* 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)
 mcr p15, 0, r0, c1, c0, 0 @ write it back

 lowlevel_init.S   SDRAM配置信息改为以下

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 0x008C04F4  // REFRESH
 .long 0x000000B1  //BANKSIZE
 .long 0x00000030  //MRSRB6
 .long 0x00000030  //MRSRB7

然后就串口就可以正常打印信息了

3.4 修改board_init_f,把relocate_code去掉

去掉:  arch/arm/config.mk:75:LDFLAGS_u-boot += -pie

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

board/samsung/smdk2440/libsmdk2440.o (.text)

vi cpu/samsung/Makefile

自己定义sdram代码复制函数,跳转函数

start.S修改代码如下:

bl nand_init_ll();
/*设置cop_to_sdram参数*/
mov r0, #0 /*源*/
//ldr r1, =_start 
ldr r1, _TEXT_BASE/*目的0x33f80000*/
//ldr r2, =__bss_start
//sub r2,r2,r1
ldr r2, _bss_start_ofs  /*大小*/
bl copy_code_to_sdram/* 将启动代码copy到sdram */
bl clear_bss /* 清除bss段 */
ldr pc, = call_board_init_f
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr r0,=0x00000000
bl board_init_f

烧写到nor flash后效果:
U-Boot 2012.04.01 (Apr 22 2016 - 22:09:48)

CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB

此处有一个问题,导致代码无法继续执行

include/common.h中

unsigned int board_init_f  (ulong) __attribute__ ((noreturn));

__attribute__ ((noreturn)去掉,否则board_init_r无法取得需要的参数,导致程序不能正常运行。

3.5  修改UBOOT,支持NOR FLASH 

drivers\mtd\jedec_flash.c加上新的型号
#define CONFIG_SYS_MAX_FLASH_SECT (128)
修复了重定位时留下来的BUG: SP要重新设置
board.c:
flash_size = flash_init();
flash_detect_legacy
jedec_flash_match(info, info->start[0])
jedec_table :添加nor flash信息:

drivers\mtd\jedec_flash.c加上新的型号
#define CONFIG_SYS_MAX_FLASH_SECT (128)
修复了重定位时留下来的BUG: SP要重新设置
board.c:
flash_size = flash_init();
flash_detect_legacy
jedec_flash_match(info, info-
>start[0])
jedec_table :添加nor flash信息:
/* mini 2440 使用的是AM29LV160DB*/
{
.mfr_id = (u16)AMD_MANUFACT,  /*厂家ID 01 */
.dev_id =  0x2249, //AM29LV160DB/*设备ID*/
.name = "AMD AM29LV160DB",  /*芯片名称 自定义*/
.uaddr = {
[1] = MTD_UADDR_0x0555_0x02AA /* x16  解锁地址 */
},
.DevSize = SIZE_2MiB, 
.CmdSet = CFI_CMDSET_AMD_LEGACY,  
.NumEraseRegions= 4,
.regions = {
ERASEINFO(0x04000, 1), /*8K*/
ERASEINFO(0x02000, 2), /*4K*/
ERASEINFO(0x08000, 1), /*16K*/
ERASEINFO(0x10000, 31),/*32K*/ 
}

},

3.6 修改u-boot支持NAND Flash

把drivers\mtd\nand\s3c2410_nand.c 复制为s3c2440_nand.c
nand 初始化过程如下:
nand_init
nand_init_chip
board_nand_init
初始化时序,ECC,禁止片选
设置nand_chip结构体,提供底层的操作函数
nand_scan
nand_scan_ident
nand_set_defaults
chip->select_chip = nand_select_chip;
chip->cmd_func(mtd,NAND_CMD_RESET, -1, -1);
nand_command();
chip->cmd_ctrl
s3c2440_hwcontrol
chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
chip->IO_ADDR_R
nand->IO_ADDR_R = (void *)&nand_reg->nfdata;


nand_get_flash_type
chip->select_chip
chip->cmdfunc(mtd,NAND_CMD_RESET, -1, -1);
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
s3c2440_hwcontrol(,,,)//选中、取消选中、发命令、地址
既可以用来发送命令又可以发送地址
chip->cmdfunc(mtd,NAND_CMD_READIO, 0x00, -1);
*maf_id = chip->read_byte(mtd);
*dev_id = chip->read_byte(mtd);
按照结构修改board_nand_init、s3c2440_nand_select、s3c2440_hwcontrol

注意:s3c2440 时钟配置寄存器、nand使能控制器跟s3c2410有差别,需要修改



至此就完成了u-boot的nor与nand支持

接下来是添加DM9000网卡、文件系统的支持

3.7添加DM9000支持

DM9000初始化过程如下

eth_initialize
board_eth_init
dm9000_initialize

smdk中添加DM9000宏

#define CONFIG_DRIVER_DM9000  
#define CONFIG_DM9000_BASE              0x20000000
#define DM9000_IO                       CONFIG_DM9000_BASE
#define DM9000_DATA                     (CONFIG_DM9000_BASE + 4)

然后ping一下主机,ping不通,提示无ipaddr,*** ERROR: `ethaddr' not set

解决方法如下,一个临时,一个永久的,都可以:

1).

set ipaddr 10.170.41.110
set ethaddr 00:0c:29:4d:e4:f4
set serverip 10.170.62.44
set gatewayip 10.170.41.33

2)初始化时设置

/*下面的根据自己ip地址填写,仅供参考*/

#define CONFIG_NETMASK255.255.255.0
#define CONFIG_IPADDR 192.168.1.110
#define CONFIG_SERVERIP 192.168.1.44
#define CONFIG_ETHADDR 25:00:45:23:23:34

然后就可以使用tftp工具下载了

例如:利用原有u-boot更新u-boot

tftp 30000000 u-boot_new.bin
protect off all
erase 0 3ffff
cp.b 30000000 0 40000 


3.8 设置启动环境参数:

因为前面一直未划分flash分区,所以环境参数设置完不能直接保存。

划分分区之前,由于前面编译的u-boot.bin太大,400K左右,等下划分的u-boot分区大小256K,因此需要将不用的模块去掉:

smdk2440.h:

#define CONFIG_USB_OHCI
#define CONFIG_USB_KEYBOARD
#define CONFIG_USB_STORAGE
#define CONFIG_DOS_PARTITION

#define CONFIG_BOOTP_BOOTFILESIZE
#define CONFIG_BOOTP_BOOTPATH
#define CONFIG_BOOTP_GATEWAY
#define CONFIG_BOOTP_HOSTNAM

//#define CONFIG_CMD_DATE
//#define CONFIG_CMD_DHCP

//#define CONFIG_CMD_USB

#define CONFIG_ENV_ADDR(CONFIG_SYS_FLASH_BASE + 0x070000)
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SIZE 0x10000
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE

#define CONFIG_CMD_FAT
#define CONFIG_CMD_EXT2
#define CONFIG_CMD_UBI
#define CONFIG_CMD_UBIFS
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define CONFIG_MTD_PARTITIONS
#define CONFIG_YAFFS2
#define CONFIG_RBTREE

以上内容皆可去掉,剩下的可以根据自己需要适当裁剪。

下面划分分区:

smdk2440.h:

//环境变量参数存放地址

#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET 0x00040000
#define CONFIG_ENV_SIZE   0x20000

#define CONFIG_ENV_RANGECONFIG_ENV_SIZE
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define MTDIDS_DEFAULT "nand0=mini2440-0"/*哪一个设备*/

//u-boot、params、kernel、rootfs分区情况
#define MTDPARTS_DEFAULT "mtdparts=mini2440-0:256k(u-boot),"\
"128k(params),"\
"2m(kernel)," \
"-(rootfs)" \
//启动命令

#define CONFIG_BOOTARGS "console=ttySAC0 root=/dev/mtdblock3"
#define CONFIG_BOOTCOMMAND "nand read 30000000 kernel;bootm 30000000"

smdk2440.h:
内核打印出来的分区信息
0x00000000 - 0x00040000 : "bootloader"
0x00040000 - 0x00060000 : "params"
0x00060000 - 0x00260000 : "kernel"
0x00260000 - 0x10000000 : "root"

分区之后u-boot对分区操作就方便多了,前后对比如下:
未分区之前的指令:
nand erase 60000 200000   //擦除6000以后的2M空间
nand write 30000000 60000 200000  //将30000000开始的2M内容写到60000
需要执行mtdparts default  或者nand init后面添加 run_command
分区后指令:
tftp 30000000 uImage
nand erase.part kernel
nand write 30000000 kernel

可以直接设置保存环境参数
set bootcmd 'nand read 30000000 kernel;bootm 30000000'
save


3.9支持文件系统

3.9.1 jffs2

烧写jffs2文件系统

tftp 30000000 fs_mini_mdev.jffs2
nand erase.part rootfs
nand write.jffs2 30000000 0x00260000 3b8e30   (实际文件大小,否则烧写整个root分区)  

//设置启动参数,文件系统格式jffs2
set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2

3.9.2 yaffs2文件系统

smdk2440.h:
tftp 30000000 first_fs.yaffs2
nand erase.part rootfs
nand write.yaffs 30000000 0x260000 85ce00
问题:无write.yaffs
解决:
smdk2440.h:
添加#define CONFIG_CMD_NAND_YAFFS
将yaffs相关函数编译进u-boot


然后烧写yaffs2文件:
现象:不能正常启动,不能识别文件系统
原因:
1)nand_util.c中
  if (flags & WITH_YAFFS_OOB) {
if (!rval)  
break;}
判断有误,需要去掉!
2) ops.mode = MTD_OOB_AUTO;
改为:ops.mode = MTD_OOB_RAW;//
3) if (!need_skip && !(flags & WITH_DROP_FFS)) 
缺少判断条件:
改为:
if (!need_skip && !(flags & WITH_DROP_FFS) && !(flags &WITH_YAFFS_OOB))

我测试时第3条必须加,否则判断条件有误,直接将oob烧写到正常数据内存中。

然后编译烧写就可以进入系统了。

至此,u-boot移植基本完成。


4.制作补丁

diff -urN linux-3.4.2 linux-3.4.2_100ask > linux-3.4.2_100ask.patch
patch -p1 < ../linux-3.4.2_100ask.patch

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值