mini2440移植uboot 2014.04(一)
最新版的uboot添加了很多新功能,我决定在最新版代码基础上重新移植一遍加深理解。
我修改的代码已经上传到github上,地址:https://github.com/qiaoyuguo/u-boot-2014.04-mini2440.git
参考文档: s3c2440手册(下载地址) mini2440电路图(下载地址)
参考我的两篇博文:
还有其他几篇文章:
《u-boot2012.04.01移植到mini2440 》
操作系统: debian 7.4
uboot: u-boot-2014.04(下载地址)
交叉编译器:arm-linux-gcc 4.4.3(下载地址)
在移植之前,最好对uboot的代码执行流程有基本的了解,可以参考我的三篇博文:
《uboot 2013.01 代码简析(2)第一阶段初始化》
《uboot 2013.01 代码简析(3)第二阶段初始化》
(一)将smdk2410的文件夹拷贝成mini2440,步骤如下:
host@debian:~/soft/mini2440/u-boot-2014.04$ vim boards.cfg
添加一行:
Active arm arm920t s3c24x0 friendlyarm - mini2440 - Qiao<qiaoyuguo2012@gmail.com>
host@debian:~/soft/mini2440/u-boot-2014.04$ mkdir board/friendlyarm
host@debian:~/soft/mini2440/u-boot-2014.04$ cp -r board/samsung/smdk2410/ board/friendlyarm/mini2440
host@debian:~/soft/mini2440/u-boot-2014.04$ mv board/friendlyarm/mini2440/smdk2410.c board/friendlyarm/mini2440/mini2440.c
host@debian:~/soft/mini2440/u-boot-2014.04$ vim board/friendlyarm/mini2440/Makefile
将其中smdk2410.o替换成mini2440.o
host@debian:~/soft/mini2440/u-boot-2014.04$ cp include/configs/smdk2410.h include/configs/mini2440.h
然后进行编译:
host@debian:~/soft/mini2440/u-boot-2014.04$ make mini2440_config
host@debian:~/soft/mini2440/u-boot-2014.04$ make CROSS_COMPILE=arm-linux-
编译过程中最后部分的输出信息:
OBJCOPY u-boot.srec
OBJCOPY u-boot.bin
(二)添加SDRAM支持
host@debian:~/soft/mini2440/u-boot-2014.04$ vim include/configs/mini2440.h
删除三行:
#define CONFIG_S3C2410 /* specifically a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410 /* on a SAMSUNG SMDK2410 Board */
#define CONFIG_SYS_TEXT_BASE 0x0
添加四行:
#define CONFIG_S3C2440 /* specifically a SAMSUNG S3C2440 SoC */
#define CONFIG_MINI2440 /* on a FriendlyArm MINI2440 Board */
#define CONFIG_SKIP_LOWLEVEL_INIT
#define CONFIG_SYS_TEXT_BASE 0x33f80000
arch/arm/cpu/arm920t/start.S中的包含有看门狗、中断以及时钟的配置,而s3c2410和s3c2440的部分配置不一样,所以需要适当的进行修改
首先需要禁止看门狗,根据s3c2440芯片手册(下载地址) ,看门狗寄存器地址如下:
WTCON 0x53000000 Watchdog timer control
WTDAT 0x53000004 Watchdog timer data
WTCNT 0x53000008 Watchdog timer count
我们只需要禁止看门狗,这样就只需要考虑WTCON寄存器就可以,从手册的462页中可以看到WTCON详细信息
当前的uboot代码已经满足了禁止看门狗的功能,其代码如下(忽略无关的宏定义,仅列出我们所关心的代码,下同):
define pWTCON 0x53000000
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]
这段代码将0加载到0x53000000处,从而禁止了看门狗(详细每位数据的含义可以查看手册)。
接着是关于中断的配置,根据s3c2440芯片手册56页,中断相关寄存器地址如下:
SRCPND 0X4A000000 R/W Interrupt request status
INTMOD 0X4A000004 W Interrupt mode control
INTMSK 0X4A000008 R/W Interrupt mask control
PRIORITY 0X4A00000C W IRQ priority control
INTPND 0X4A000010 R/W Interrupt request status
INTOFFSET 0X4A000014 R Interrupt request source offset
SUBSRCPND 0X4A000018 R/W Sub source pending
INTSUBMSK 0X4A00001C R/W Interrupt sub mask
我们需要配置中断屏蔽寄存器(INTMSK,见手册388-389页)和子中断屏蔽寄存器(INTSUBMSK,见手册395页),可以看到当前代码如下:
# define INTMSK 0x4A000008 /* Interrupt-Controller base addresses */
# define INTSUBMSK 0x4A00001C
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
该代码中断屏蔽寄存器的代码仍然使用于s3c2440,但是需要添加子中断屏蔽寄存器的代码,可以在s3c2410相关代码中添加elseif语句:
#elseif defined(CONFIG_S3C2440)
ldr r1, =0x7fff
ldr r0, =INTSUBMSK
str r1, [r0]
根据手册,s3c2440中子中断屏蔽寄存器有效位数是低15位,所以我们用0x7fff,使得低15位为1(1表示屏蔽该中断,0表示该中断可用).
接着是时钟分频配置,现有代码如下:
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #
str r1, [r0]
上面代码中提到了FCLK、HCLK、PCLK(参见手册242页),FCLK用于arm920T,HCLK用于AHB,可以用于USB、DMA、LCD、中断和内存控制器等。
PCLK用于APB,可以用于看门狗、IIS、I2C、SPI、ADC、UART、GPIO、RTC等。
当前代码默认采用1:2:4的分频配置,但是mini2440我们要将cpu频率配置成400MHz。
根据手册33页,FCLK最大只能是400MHz,HCLK最大只能是136MHz,PCLK最大只能是68MHz。
要满足时钟频率的限制,可以将分频配置成1:4:8,那么FCLK=400MHz,HCLK等于100MHz,PCLK等于50MHz,都能满足要求。
关于CLKDIVN寄存器的定义,可以查看手册258页,给出了下面的信息:
CLKDIVN 0x4C000014 R/W Clock divider control register HDIVN [2:1] 10 : HCLK = FCLK/4 when CAMDIVN[9] = 0,HCLK= FCLK/8 when CAMDIVN[9] = 1.
PDIVN [0] 如果为0: PCLK has the clock same as the HCLK/1 如果为1: PCLK has the clock same as the HCLK/2.
而CAMDIVN寄存器定义可以查看手册259页,能看到默认所有位等于0,这样只需要配置HDIVN为10,PDIVN为1既可。CLKDIVN的值应该是0x101=5
手册243页中提到如果HDIVN不是0,那么需要将cpu总线模式从"fast bus mode"改成“asynchronous bus mode"
然后需要对PLL进行配置,才能得到405MHz的输出频率,根据手册255页,可以得到PLL相关寄存器信息:
MPLLCON 0x4C000004 R/W MPLL configuration register 0x00096030
UPLLCON 0x4C000008 R/W UPLL configuration register 0x0004d030 PLLCON Bit Description
MDIV [:] Main divider control
PDIV [:] Pre-divider control
SDIV [:] Post divider control
input freq output freq MDIV PDIV SDIV
12.0000MHz 48.00 MHz 56(0x38) 2 2
12.0000MHz 405.00 MHz 127(0x7f) 2 1
此处MPLL和UPLL分别用于系统时钟和USB时钟,我们将MPLL输出设定成405MHz, UPLL输出设定成48MHz.
手册255页中还提到,当写入UPLL和MPLL时,需要先写UPLL后写MPLL。
我修改后的代码内容如下:
#if defined(CONFIG_S3C2440)
/* FCLK:HCLK:PCLK = 1:4:8 */
ldr r0, =CLKDIVN
mov r1, #5
str r1, [r0] /* change bus mode from "fast bus mode" to "asynchronous bus mode" */
mrc p15, 0, r1, c1, c0, 0 /*read ctrl regester*/
orr r1, r1, #0xc0000000 /*asynchronous*/
mcr p15, 0, r1, c1, c0, 0 /*write ctrl register*/ #define S3C2440_MPLL_400MHZ (0x7f<<12 | 0x2<<4 | 0x1) /* refer to s3c2440.pdf page 255 */
#define S3C2440_UPLL_48MHZ (0x38<<12 | 0x2<<4 | 0x2)
#define MPLLCON 0x4c000004
#define UPLLCON 0x4c000008
ldr r0, =UPLLCON
ldr r1, =S3C2440_UPLL_48MHZ
str r1, [r0] ldr r0, =MPLLCON
ldr r1, =S3C2440_MPLL_400MHZ
str r1, [r0]
#else
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #
str r1, [r0]
#endif
如果没有定义CONFIG_SKIP_LOWLEVEL_INIT, 在执行完这部分代码后会跳转到start.S中的cpu_init_crit,
然后又跳转到board/friendlyarm/mini2440/lowlevel_init.S中的lowlevel_init函数,该函数中包含对sdram连接的BANK0-BANk7
以及SDRAM刷新频率进行配置(可以参考2440手册203-210页)。
但是我们当前代码中定义了CONFIG_SKIP_LOWLEVEL_INIT,所以cpu_init_crit不会执行,暂时也不需要考虑这部分代码。
接着调用_main,_main位于arch/arm/lib/crt0.S文件中,它会依次调用board_init_f和relocate_code.
在relocate_code中执行重定位代码,然后会根据其lr寄存器中的here地址跳转回arch/arm/lib/crt0.S,执行here标签下的内容(主要是board_init_r函数).
修改mini2440.c中的时钟频率,跟上面的汇编代码保持一致:
host@debian:~/soft/mini2440/u-boot-2014.04$ vim board/friendlyarm/mini2440/mini2440.c
host@debian:~/soft/mini2440/u-boot-2011.03$ vim board/friendlyarm/mini2440/mini2440.c
#define FCLK_SPEED #elif FCLK_SPEED==1 /* Fout = 202.8MHz */
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1
#elif FCLK_SPEED==2 /* Fout = 405MHz */
#define M_MDIV 0x7F
#define M_PDIV 0x2
#define M_SDIV 0x1
#endif
#define USB_CLOCK #elif USB_CLOCK==1
#define U_M_MDIV 0x48
#define U_M_PDIV 0x3
#define U_M_SDIV 0x2
#elif USB_CLOCK==2 /* Fout = 48MHz */
#define U_M_MDIV 0x38
#define U_M_PDIV 0x2
#define U_M_SDIV 0x2
#endif
int board_init (void)
{
......
gd->bd->bi_arch_number = MACH_TYPE_MINI2440;
......
}
此时,执行编译命令:
make CROSS_COMPILE=arm-linux-
会出来很多编译错误:
drivers/mtd/nand/s3c2410_nand.c: In function 's3c2410_hwcontrol':
drivers/mtd/nand/s3c2410_nand.c:: warning: implicit declaration of function 's3c2410_get_base_nand'
drivers/mtd/nand/s3c2410_nand.c:: warning: initialization makes pointer from integer without a cast
drivers/mtd/nand/s3c2410_nand.c:: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c:: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c:: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c:: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c: In function 's3c2410_dev_ready':
drivers/mtd/nand/s3c2410_nand.c:: warning: initialization makes pointer from integer without a cast
drivers/mtd/nand/s3c2410_nand.c:: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c: In function 'board_nand_init':
drivers/mtd/nand/s3c2410_nand.c:: warning: initialization makes pointer from integer without a cast
drivers/mtd/nand/s3c2410_nand.c:: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c:: error: dereferencing pointer to incomplete type
drivers/mtd/nand/s3c2410_nand.c:: error: dereferencing pointer to incomplete type
make[]: *** [drivers/mtd/nand/s3c2410_nand.o] 错误
查看代码可以知道是因为从board_init_r->nand_init经过一长串的调用后调用s3c2410_hwcontrol。
当前代码中在include/configs/mini2440.h中定义了CONFIG_NAND_S3C2410,所以使用了drivers/mtd/nand/s3c2410_nand.c中的代码。
上面的错误是因为未定义s3c2410_get_base_nand引起的,而该函数定义位于arch/arm/include/asm/arch-s3c24x0/s3c2410.h中,
在arch/arm/include/asm/arch-s3c24x0/s3c24x0_cpu.h中有下面内容:
#elif defined CONFIG_S3C2440
#include <asm/arch/s3c2440.h>
实际上当前代码中包含的文件是arch/arm/include/asm/s3c24x0/s3c2440.h,该头文件中没有 s3c2410_get_base_nand函数的定义,由于s3c2410.h和s3c2440.h中代码基本一致,直接包含将代码中 s3c2440.h修改成s3c2410.h即可。
另外几个错误是因为s3c2410_nand未定义引起的,可以在arch/arm/include/asm/arch-s3c24x0/s3c24x0.h中将s3c2440_nand修改成s3c2410_nand即可。
然后重新编译:
make CROSS_COMPILE=arm-linux-
参考《openocd+jlink为mini2440调试u-boot》配置好openocd,然后打开串口:
sudo minicom
在另一个控制台执行下面命令:
sudo openocd -f interface/jlink.cfg -f board/mini2440.cfg
telnet localhost
halt
init_2440
load_image /home/host/soft/mini2440/u-boot-2014.04/u-boot.bin 0x33f80000 bin
resume 0x33f80000
其中/home/host/soft/mini2440/u-boot-2014.04/u-boot.bin是我的uboot存放路径,根据自己的需要改成自己电脑上的路径即可。
得到下面的输出信息:
U-Boot 2014.04-gf5f2cb1-dirty (Jun - ::) CPUID:
FCLK: MHz
HCLK: 101.250 MHz
PCLK: 50.625 MHz
DRAM: MiB
之后没有进入uboot命令行就重启cpu了。
虽然这里能检测到DRAM,这也说明了DRAM的配置是基本上正确的。从s3c2440手册194页和mini2440原理图第5页可以看到DRAM连接nGCS6,
所以其对应基地址是0x30000000,与include/configs/mini2440.h中的PHYS_SDRAM_1的值一模一样。
(三)调试bug(未进入uboot重启cpu)
在include/configs/mini2440.h中添加一行:
#define DEBUG
然后按照上面的步骤将进行编译并将生成u-boot.bin加载到mini2440,从控制台可以得到输出:
U-Boot 2014.04-g0e7a234-dirty (Jun - ::) U-Boot code: 33F80000 -> 33FF9F84 BSS: -> 340489D0
CPUID:
FCLK: MHz
HCLK: 101.250 MHz
PCLK: 50.625 MHz
monitor len: 000C89D0
ramsize:
TLB table from 33ff0000 to 33ff4000
Top of RAM usable for U-Boot at: 33ff0000
Reserving 802k for U-Boot at: 33f27000
Reserving 4160k for malloc() at: 33b17000
Reserving Bytes for Board Info at: 33b16fe0
Reserving Bytes for Global Data at: 33b16f40
New Stack Pointer is: 33b16f30
RAM Configuration:
Bank #: MiB
relocation Offset is: fffa7000
然后就冻结在这个地方,不再有任何输出。
我在board_init_f函数中debug("relocation Offset is: %08lx\n", gd->reloc_off)之前添加了一行代码:
debug("addr=%08lx,_start=%08lx\n", addr,(ulong)&_start);
重新编译加载到mini2440后得到的输出信息如下:
U-Boot 2014.04-g0e7a234-dirty (Jun - ::) U-Boot code: 33F80000 -> 33FF9FB4 BSS: -> 340489D0
CPUID:
FCLK: MHz
HCLK: 101.250 MHz
PCLK: 50.625 MHz
monitor len: 000C89D0
ramsize:
TLB table from 33ff0000 to 33ff4000
Top of RAM usable for U-Boot at: 33ff0000
Reserving 802k for U-Boot at: 33f27000
Reserving 4160k for malloc() at: 33b17000
Reserving Bytes for Board Info at: 33b16fe0
Reserving Bytes for Global Data at: 33b16f40
New Stack Pointer is: 33b16f30
RAM Configuration:
Bank #: MiB
addr=33f27000,_start=33f80000
relocation Offset is: fffa7000
从调试信息可以看出addr < _start,但是gd_reloc_off=addr-(ulong)&_start,明显得到的结果溢出了。
这是因为我们配置的CONFIG_SYS_TEXT_BASE的问题,将其值修改成0x33F00000。
然后重新编译加载到mini2440(但命令中的0x33f80000都要替换成0x33f00000),得到下面的输出:
U-Boot 2014.04-g0e7a234-dirty (Jun - ::) U-Boot code: 33F00000 -> 33F79FB4 BSS: -> 33FC89D0
CPUID:
FCLK: MHz
HCLK: 101.250 MHz
PCLK: 50.625 MHz
monitor len: 000C89D0
ramsize:
TLB table from 33ff0000 to 33ff4000
Top of RAM usable for U-Boot at: 33ff0000
Reserving 802k for U-Boot at: 33f27000
Reserving 4160k for malloc() at: 33b17000
Reserving Bytes for Board Info at: 33b16fe0
Reserving Bytes for Global Data at: 33b16f40
New Stack Pointer is: 33b16f30
RAM Configuration:
Bank #: MiB
addr=33f27000,_start=33f00000
relocation Offset is:
虽然没有溢出,但是仍然是停留在这个位置不继续执行了。
我将CONFIG_SYS_TEXT_BASE改成了0x33e80000,然后重新编译并加载到mini2440内存中(命令中的地址也相应修改为0x33e80000),得到下面的输出:
U-Boot 2014.04-g0e7a234-dirty (Jun - ::) U-Boot code: 33E80000 -> 33EF9FA8 BSS: -> 33F489D0
CPUID:
FCLK: MHz
HCLK: 101.250 MHz
PCLK: 50.625 MHz
monitor len: 000C89D0
ramsize:
TLB table from 33ff0000 to 33ff4000
Top of RAM usable for U-Boot at: 33ff0000
Reserving 802k for U-Boot at: 33f27000
Reserving 4160k for malloc() at: 33b17000
Reserving Bytes for Board Info at: 33b16fe0
Reserving Bytes for Global Data at: 33b16f40
New Stack Pointer is: 33b16f30
RAM Configuration:
Bank #: MiB
addr=33f27000,_start=33e80000
relocation Offset is: 000a7000
WARNING: Caches not enabled
monitor flash len: 000847B0
Now running in RAM - U-Boot at: 33f27000
Flash: fwc addr cmd f0 00f0 16bit x bit
fwc addr 0000aaaa cmd aa 00aa 16bit x bit
fwc addr cmd 16bit x bit
fwc addr 0000aaaa cmd 16bit x bit
fwc addr cmd f0 00f0 16bit x bit
JEDEC PROBE: ID f0 ea00
fwc addr cmd ff 00ff 16bit x bit
fwc addr cmd 16bit x bit
fwc addr cmd ff 00ff 16bit x bit
JEDEC PROBE: ID ea00
*** failed ***
### ERROR ### Please RESET the board ###
从输出信息上看sdram已经通过了,但是flash中存在问题,接下来解决这个问题。
mini2440移植uboot 2014.04(一)的更多相关文章
- mini2440移植uboot 2014.04(七)
上一篇博文:<mini2440移植uboot 2014.04(六)> 代码已经上传到github上: https://github.com/qiaoyuguo/u-boot-2014.04 ...
- mini2440移植uboot 2014.04(六)
上一篇博文:<mini2440移植uboot 2014.04(五)> 代码已经上传到github上:https://github.com/qiaoyuguo/u-boot-2014.04- ...
- mini2440移植uboot 2014.04(五)
代码上传到github上:https://github.com/qiaoyuguo/u-boot-2014.04-mini2440 前几篇博文: <mini2440移植uboot 2014.04 ...
- mini2440移植uboot 2014.04(四)
我修改的代码已经上传到github上,地址:https://github.com/qiaoyuguo/u-boot-2014.04-mini2440.git 参考文章: <mini2440移植u ...
- mini2440移植uboot 2014.04(二)
我修改的代码已经上传到github上,地址:https://github.com/qiaoyuguo/u-boot-2014.04-mini2440.git 参考文章: <u-boot-2011 ...
- mini2440移植uboot 2014.04(三)
我修改的代码已经上传到github上,地址:https://github.com/qiaoyuguo/u-boot-2014.04-mini2440.git 参考文档: s3c2440手册(下载地址) ...
- mini2440移植uboot 2011.03(下)
参考博文: <u-boot-2011.03在mini2440/micro2440上的移植> 移植(五)添加nand支持: host@debian:~/soft/mini2440/u-boo ...
- 移植u-boot.2012.04.01
/*************************************************** *u-boot版本:u-boot2012.04.01 *gcc版本:arm-linux-gcc ...
- mini2440移植uboot 2011.03(上)
参考博文: <u-boot-2011.03在mini2440/micro2440上的移植> 本来我想移植最新版的uboot,但是移植却不太成功,所以先模仿他人的例子重新执行一遍,对uboo ...
随机推荐
- MQTT--入门 续
1.消息模型: MQTT是一种基于代理的发布/订阅的消息协议.提供一对多的消息分发,解除应用程序耦合.一个发布者可以对应多个订阅者,当发布者发生变化的时候,他可以将消息一一通知给所有的订阅者.这种模 ...
- Android 完整开源应用大全,完整开源项目
(Antox)聊天的 (new) (OpenKeychain)OpenPGP在android上的实现 (new) (Flock)提供同步服务 (OpenFlappyBird)以前火爆的坑爹鸟 (F ...
- Andrew Ng机器学习笔记+Weka相关算法实现(五)SVM最优间隔和核方法
这一章主要解说Ng的机器学习中SVM的兴许内容.主要包括最优间隔分类器求解.核方法. 最优间隔分类器的求解 利用以一篇讲过的的原始对偶问题求解的思路,我们能够将相似思路运用到SVM的求解上来. 详细的 ...
- C#中使用泛型对照使用通用基础类型效率减少近一倍
C#中使用泛型对照使用通用基础类型效率减少近一倍 以下是測试结果: CSharp class and generic TotalMilliseconds: 270772.9229CSharp g ...
- lua学习笔记(十一)
面向对象编程 对象的实现 在lua中table就是一种对象 1.有自己的状态 2.有自己的唯一标识self 3.有自己的生命周期 ...
- 篇三、开发前知识补充:Android的长度单位和屏幕分辨率,这个也是转载~~
这篇文章有点早,不过很实用.单位的实用看最后的红色标注的部分. 屏幕分辨率基础 1.术语和概念 术语 说明 备注 Screen size(屏幕尺寸) 指的是手机实际的物理尺寸,比如常用的2.8英寸,3 ...
- 开发app应用的开源项目推荐
app检测内存泄漏 请看这里:LeakCanary Android 和 Java 内存泄露检测 app应用想要控制状态栏 StatusBarUtil :https://github.com/laobi ...
- dynamic与var
dynamic与var示例 var是一种语法省略写法,编译器会根据上下文推断出正确的类型. , , , , , , , }; foreach (var item in scores) { Consol ...
- 修改Jmeter配置使能支持更大并发
Jmeter做并发测试时,报错 java.lang.OutOfMemoryError:gc overhead limit exceeded. 原因是jmeter默认分配内存的参数很小,256M吧.故而 ...
- H - Coins
H - Coins Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Descripti ...