1.下载uboot2012.04.01,并尝试编译smdk2410
a.官网下载
b.tar解压
c.配置:make smdk2410_config
d.编译:make
遇到问题:
make: *** [u-boot] Error 139
编译器版本低
故:换arm-linux-gcc-4.3.2
e.再次编译:
遇到问题:
error trying to exec 'cc1': execvp: No such file or directory
编译器位置的问题
故:将编译器解压到 /
d.再次编译:编译成功,达到uboot.bin可执行文件
2.基于smdk2410创建单板目录和配置文件
a.创建jz2440 board目录
在u-boot-2012.04.01\board\samsung\ 目录下创建jz2440目录,并将同目录下smdk2410中的文件全部拷贝到jz2440
同时将smdk2410.c改成jz2440.c ,并在同目录下将Makefile 中的 COBJS := smdk2410.o 改为COBJS := jz2440.
b.创建jz2440.h配置文件
在u-boot-2012.04.01\include\configs中copy smdk2410.h文件并重命名为jz2440.h粘贴到该目录下。
c.在/board.cfg中添加:
jz2440 arm arm920t - samsung s3c2440
d./Makefile中:
添加:arm-linux-
目标:成功编译新board
make jz2440_config
make
(成功)
3.创建SI-project,分析启动流程,了解内存布局,及各关键部位
a.创建SI-project
b.分析启动流程
从arch/arm/cpu/arm920t/start.S开始:
start_code:
set the cpu to SVC32 mode -> .....详情见移植过程......
c.内存布局
d.各关键部位
4.修改时钟和存储控制器,与board适配,并debugSDRAM是否可用
step1:修改时钟和存储控制器
set the cpu to SVC32 mode
->#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) //delete 这部分
->turn off the watchdog //2410 2440看门狗继存器位置相同,不改动
->mask all IRQs by setting all bits in the INTMR - default //屏蔽IRQs INTSUBMSK 2440也有,将CONFIG_S3C2410换成 CONFIG_S3C2440 并将CONFIG_S3C2440在jz2440中定义
->第一个重要post1:时钟配置(MPLL){
MPLL和UPLL在board/sansung/jz2440.c中int board_early_init_f(void)有:
将以上MPLL注释,UPLL保留;在post1处手动添加MPLL的配置,如下:
a.set FCLK 和 Fin的关系
b.set FCLK、HCLK、PCLK三者关系
c.改变总线模式,使cpu核时钟使用FCLK(默认使用HCLK)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
->CONFIG_SKIP_LOWLEVEL_INIT jz2440不定义,bl cpu_init_crit
flush v4 I/D caches 、 disable MMU stuff and caches、bl lowlevel_init(执行存储控制器的配置)
->bl lowlevel_init:在jz2440/lowlevel.S中:
首先检查BWSCON 存储控制器寄存器组的基址:0x48000000 没错
分析配置过程,没错
更改SMRDATA:的值(与jz2440适配,注意时钟的变化,修改刷新reg)
step2:验证SDRAM是否可用:
使用JTAG物理调试(类似于gdb),采用openOCD作为上位机应用程序:
a.烧写一个移植好的uboot,采用dnw(win7) + usb + uboot 下载自己的uboot到Nor / Nand
b.在uboot启动过程中,q进入命名模式:
usb 1 30000000 //采用usb下载 1-一直等待至下载完成 30000000 下载目的地址
对Nor Flash:
protect off all //解除写保护
erase 0 7FFFF //擦除Nor 512K的大小(从0x0地址到0x7FFFF)
cp.b 30000000 0 80000 //从0x30000000处复制 0-0x80000内容到Nor
对Nand Flash:
nand erase 0 80000 //擦除nand 从0x0 到 0x80000
nand write 30000000 0 80000 //从0x30000000复制0-0x80000的内容写入nand
c.win7安装OpenOCD(包括驱动) + OpenJTAG + telent进行debug
d.打开telent功能(控制面板 - 程序与功能 - ... )
e.打开openocd,OPJTAG连接开发板和PC,启动开发板,connect,识别成功后telnet到cmd中:
reset halt
halt
step 0x0 //从0x0开始运行
step //单步运行 pc += 4
bp 0xb0 4 hw //在0xb0处设置断点,使其完成存储 控制器的配置
resume //继续运行到断点0xb0
mdw 0x30000000 //查看0x30000000处原来的值
mww 0x30000000 0x11112222 //向0x30000000写入0x11112222
mdw 0x30000000 //查看0x30000000处现在的值,若= 0x11112222则读写入成功(SDRAM可用)
小结:在start.S中配置MPLL,在lowlevel.S中配置存储控制器,并在jz2440.c中注释MPLL的配置,以及在s3c24x0.h中注释s3c2410的GPIO结构体,(下一步:在jz2440.h中添加CONFIG_S3C2440宏)
目标:MPLL配置成功,SDRAM可用,串口有输出(不配置CONFIG_S3C2440则为乱码)
(成功)
5.修改时钟获取函数(如get_PCLK()等),使baudrate正常,使串口能输出
->Set stackpointer in internal RAM to call board_init_f(在SDRAM中设置栈指针,并调用board_init_f 第一阶段的初始化工作)
->board_init_f:主要做一些第一阶段的初始化工作:
->serial_init源码追溯:
int serial_init(void)
{
return serial_init_dev(UART_NR);
}
static int serial_init_dev(const int dev_index)
{
//获得UART控制器基址
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
#ifdef CONFIG_HWFLOW //不管
hwflow = 0; /* turned off by default */
#endif
/* FIFO enable, Tx/Rx FIFO clear */
writel(0x07, &uart->ufcon);
writel(0x0, &uart->umcon);
/* Normal,No parity,1 stop,8 bit */ //8N1
writel(0x3, &uart->ulcon);
/*
* tx=level,rx=edge,disable timeout int.,enable rx error int.,
* normal,interrupt or polling
*/
writel(0x245, &uart->ucon); //interrupt or polling
#ifdef CONFIG_HWFLOW
writel(0x1, &uart->umcon); /* rts up */
#endif
/* FIXME: This is sooooooooooooooooooo ugly */
#if defined(CONFIG_ARCH_GTA02_v1) || defined(CONFIG_ARCH_GTA02_v2)
/* we need auto hw flow control on the gsm and gps port */
if (dev_index == 0 || dev_index == 1)
writel(0x10, &uart->umcon);
#endif
_serial_setbrg(dev_index);
return (0);
}
void _serial_setbrg(const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
unsigned int reg = 0;
int i;
/* value is calculated so : (int)(PCLK/16./baudrate) -1 */
reg = get_PCLK() / (16 * gd->baudrate) - 1;
writel(reg, &uart->ubrdiv);
for (i = 0; i < 100; i++)
/* Delay */ ;
}
/*划重点了*/
ulong get_PCLK(void)
{
struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
return (readl(&clk_power->clkdivn) & 1) ? get_HCLK() / 2 : get_HCLK();
}
ulong get_HCLK(void)
{
struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
#ifdef CONFIG_S3C2440 //需要定义这个宏,在include/configs/jz2440.h中
switch (readl(&clk_power->clkdivn) & 0x6) {
default:
case 0:
return get_FCLK();
case 2:
return get_FCLK() / 2;
case 4:
return (readl(&clk_power->camdivn) & (1 << 9)) ?
get_FCLK() / 8 : get_FCLK() / 4;
case 6:
return (readl(&clk_power->camdivn) & (1 << 8)) ?
get_FCLK() / 6 : get_FCLK() / 3;
}
#else
return (readl(&clk_power->clkdivn) & 2) ? get_FCLK() / 2 : get_FCLK();
#endif
}
串口的支持其实就是追溯到/arch/arm/cpu/arm920t/s3c24x0/speed.c中 影响get_PLLCLK函数和get_HCLK函数,并在自己的配置文件中添加宏定义CONFIG_S3C2440,
去掉CONFIG_S3C2410
->编译:
q1.在s3c2410_nand.c 中出错:
对照源码:
可见是因为把CONFIG_S3C2410这个宏去掉了,导致条件编译时没有生成struct s3c2410_nand结构体,后续的所有配置也就是错误的。
故:
暂时添加CONFIG_S3C2410这个宏,因为在speed.c中只要配置了CONFIG_S3C2440这个宏即可,其余问题后续再解决。
(解决)
q2:
大概是个结构体吧,对照源码:从cpu_info.c追溯到:s3c24x0_cpu.h
可以看出CONFIG_S3C2410 又在作怪了。。。
故:
那就将以上源码的CONFIG_S3C2440与CONFIG_S3C2410位置对换,且同时修改.h文件
(未解决,到s3c24x0.h中看:)
可见二者不能同时存在
故:
直接把2410的部分结构体成员注释把。
(解决)
q3:
以上未定义的函数,在s3c2410.h中定义。。。。。
故:
在/driver/mtd/nand/Makefile中修改如上,s3c2440.o备用
(解决)
q4:
故:暂时注释吧
终于:(编译成功)
小结:其实可以直接在jz2440.h中注释CONFIG_NAND_S3C2410 使得在/drivers/mtd/nand/Makefile中不编译s3c2410.o;然后注释掉2410的nand结构体。
也可以不注释CONFIG_S3C2410,直接添加CONFIG_S3C2440,并在s3c24x0.h中注释2410的GPIO结构体。因为串口获取时钟只要定义CONFIG_S3C2440即可。
->烧写、启动、观察串口输出:
这个结果其实很好得到,就是要注意MPLLCON的配置顺序!!!!
小结:
MPLL的配置;ICache开启;添加CONFIG_S3C2440(使得获取总线时钟函数获取到2440的正确时钟)才能使波特率正常。
6.修改启动方式之 支持Nand Flash启动
原本,uboot是默认Nor Flash启动,不管是*.lds中的链接地址还是重定位代码,都是针对Nor Flash;
现在,要支持Nand Flash启动,必然涉及修改*.lds中的链接地址和修改重定位方式,并去掉针对Nor 启动的-pie选项(-pie会导致在*.lds中生成一些关于已初始化全局变量和静态变量的段,可在arch/arm/config.mk中修改)
此外,要注意将重定位之前的代码和相关变量定位于前4K,/jz2440/Makefile中修改
1.将原来的nand_drv.c复制到jz2440/下,并在jz2440/Makefile中做对应修改(主要是nand_init 和nand_read 用于nand初始化和重定位uboot)
编译,烧写,测试:没问题
在board.c中定义_DEBUG,查看输出:
2.在进入第一阶段的初始前(调用board_init_f之前),进行nand_init 和 重定位代码
如下:
其中CONFIG_SYS_TEXT_BASE是原本在jz2440.h中定义为0x0,表示自动生成的uboot.lds中指定链接地址为0;
现在,修改为:(更改链接地址了)
这样不好!!!因为还没有重定位,在jz2440.h中定义的值可能编译器输出在4K之外,所以将上面的r1修改:
关于_TEXT_BASE和_bss_start_ofs在start.S中:
4.去掉针对Nor 启动的-pie选项;去掉针对Nor 启动的重定位相关代码
在/arch/arm/config.mk中:
在arch/arm/lib/board.c中:
在arch/arm/cpu/arm920t/start.S:
以上直接去掉,直到清bss段。
3.清bss段
篇外:
一个可执行程序有:text、data等段,bss段不在可执行文件里面。
bss段里面存的是为初始化的全局变量和静态变量,是一个个值。当从定位代码的时候,只重定位了text开始。。。bss_start,另外的bss段可以不重定位,直接在重定位后clear(初始化为0)。
所以,我们应该给程序留的最终大小应该是从text开始。。。bss_end。
uboot原本的:
是结合Nor 重定位的,直接自己写吧:
4.进入第二阶段的初始化工作(进入到board_init_r函数)
篇外:接clear_bss后的启动流程分析
经过以上,启动流程分析,走过了board_init_f,再经过一些Nor Flash的重定位和clear bss,进入到board_init_r第二阶段的初始化工作:
->board_init_r:这里面就超级重要了,主要是对外设的支持,比如Nand Flash、Nor Flash 、网卡、LCD等。
以及开启cache、设置parm参数地址 和 2410机器ID(需要修改)、环境变量重定位、设置栈等。
board_init_r有两个参数需要确定:
void board_init_r(gd_t *id, ulong dest_addr)
gd_t *id 在board_init_f中就确定了,直接使函数返回(返回值保存在r0中) //在函数定义和声明处(/include/common.h)更改返回值类型
ulong dest_addr就是链接地址:_TEXT_BASE
所以:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit //完成储存控制器的配置
#endif
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
bl nand_init_new //Nand Flash 控制器初始化
mov r0, #0x0
ldr r1, _TEXT_BASE
ldr r2, _bss_start_ofs
bl copy_bootcode_to_sdram //重定位nand中的uboot到SDRAM 0x33f00000
clear_bss:
ldr r0, _bss_start_ofs
ldr r1, _bss_end_ofs
mov r2, #0x00000000 /* clear */
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
ldr pc, = call_board_init_f //到SDRAM去执行
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr r0,=0x00000000
bl board_init_f //第一阶段的初始化,修改返回id参数,保存在r0
ldr r1, =_TEXT_BASE
bl board_init_r
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
#if 0 //都是针对Nor启动的代码
#ifdef CONFIG_NAND_SPL
ldr r0, _nand_boot_ofs
mov pc, r0
_nand_boot_ofs:
.word nand_boot
#else
ldr r0, _board_init_r_ofs
adr r1, _start
add lr, r0, r1
add lr, lr, r9
/* setup parameters for board_init_r */
mov r0, r5 /* gd_t */
mov r1, r6 /* dest_addr */
/* jump to it ... */
mov pc, lr
_board_init_r_ofs:
.word board_init_r - _start
#endif
_rel_dyn_start_ofs:
.word __rel_dyn_start - _start
_rel_dyn_end_ofs:
.word __rel_dyn_end - _start
_dynsym_start_ofs:
.word __dynsym_start - _start
#endif
5.修改jz2440/ 下的Makefile ,添加nand_drv.o
6.在arch/arm/cpu/在的uboot.lds中修改(将start.o、nand_drev.o、lowlevel.o等放到前4K的位置)
经编译后,在jz2440/下:没有对应的start.o、nand_drev.o、lowlevel.o,却有一个libjz2440.o,可见uboot将他们做成了一个库。
所以将arch/arm/cpu/下的uboot.lds:
修改为:
7.总结修改了哪些文件:
start.S jz2440/ jz2440.h /arch/arm/config.mk arch/arm/lib/board.c /include/common.h arch/arm/cpu/下的uboot.lds
8.编译:
q1:
(解决)
q2:
注意英文逗号。。。。。
(解决)
q3:
board前面没有/
(解决)
(编译成功)
9.烧写结果:
!!!!!不断重启或者Nor Flash哪里没有输