S3C2440与S3C2410的区别:
接口:S3C2440增加了摄像头接口,AC’97音频接口,NAND FLASH有较大的变化,主频更高(405M)S3C32410只有203M,芯片时钟芯片频率控制器有一定的变化,其它都是兼容的
时钟系统和电源管理模块由三个部分组成:时钟控制部分,usb控制部分和电源管理部分组成。
所用的S3C2440A有两个锁相环(PLL)一个提供给FCLK,HCLK,PCLK;另一个提供给USB模块(48MHZ)专用的。
首先是建立属于自己的板子 cd u-boot-2009.11/board/Samsung/
Mkdir mini2440 //这就是我们这次的开发板所在目录
选择和s3c2440最为相近的smdk2410作为参考板,将不同的地方修改为我们需要的。
Cp -rf smdk2410/* mini2440/
Cd mini2440
Mv smdk2410.c mini2440.c //改为自己的板子文件 比较有成就感
修改mini2440文件夹中的makefile COBJS :=mini2440.o flash.o
在/include/configs文件夹中以smdk2410.h作为模板 制作我们的开发板需要的头文件
Cp smdk2410.h mini2440.h
在
include/configs/mini2440.h
中,添加这类信息参照已有格式即可
#define CONFIG_S3C2440 1 //
很重要
修改u-boot-2009.11文件夹中的makefile文件 将交叉编译环境修改为 CROSS_COMPILE ?= arm-linux-gcc
在makefile文件中注册我们的板子芯片照着smdk2410_config的格式进行修改:
Mini2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t mini2440 samsung s3c24x0
在这里需要注意 最好是复制上面已有的格式然后修改 如果自己写的话要注意makefile书写格式第二行第一个@前面是Tab键 这个不能用4个空格代替 否则会编译出错。 Samsung表示的是所建立的mini2440目录在board/samsung文件夹中 如果你将mini2440直接建立在board文件夹中则直接写NULL,这个是告诉编译器mini2440在哪
Arm:cpu的架构
Arm920t:cpu的类型
Mini2440:对应在board目录下建立的开发板项目的目录
Samsung:新开发板目录的上级目录,如果直接在board下建立则为NULL
S3c2440: cpu型号
然后测试编译环境:make mini2440_config
Make
编译完成如果在u-boot-2009.11目录中出现u-boot.bin文件,就成功了一小小步。
接下来写段小程序验证一下我们制作的u-boot是否在板子上运行起来了(通过led显示)
通过cpu/arm920t/u-boot.lds文件可以知道程序的入口在start.S文件中的_start处,我们进入到start.S文件中看到
.
globl _start
_start
:
b start_code
//
将程序的执行跳转到
start_code
处
说明程序正在的入口在start_code处;
由于u-boot的移植都是采用这种打补丁的方式进行移植的,这个程序中存在了很多其他板子的程序段在,
bl coloured_LED_init
//
此处两行是对
AT91RM9200DK
开发板上的
LED
进行初始化的
bl red_LED_on
因为我们在
RAM
中调试程序
cpu
被
supervivi
初始化了故注释掉
u-boot
中的
cpu
初始化
/*#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif*/
不是我们需要的注释掉
我们自己写我们需要的
led
显示
(任何合适的地方)
#if defined(CONFIG_S3C2440)
//
区别与其他开发板,这个
CONFIG_S3C2440
要添加在
include/configs/mini2440.h
中,添加这类信息参照已有格式即可
#define CONFIG_S3C2440 1 //
很重要
//
根据
mini2440
原理图可知
LED
分别由
S3C2440
的
PB5
、
6
、
7
、
8
口来控制,以下是
PB
端口寄存器基地址
(
查
2440
的
DataSheet
得知
)
#define GPBCON 0x56000050
#define GPBDAT 0x56000054
#define GPBUP 0x56000058
//
以下对寄存器的操作参照
S3C2440
的
DataSheet
进行操作
ldr r0, =GPBUP
ldr r1, =0x7FF
//
即:二进制
11111111111
,
str r1, [r0]
ldr r0, =GPBCON
ldr r1, =0x15400
str r1, [r0]
ldr r0, =GPBDAT
ldr r1, =0x1C0
//
这里的等号别忘记了写,本人一时大意忘记了写结果就编译出错。
str r1, [r0]
#endif
//
此段代码使
u-boot
启动后,点亮开发板上的
LED1
,
LED2
、
LED3
、
LED4
不亮
如果编译成功的话将
u-boot.bin
文件下载到开发板中(通过友善之臂提供的
supervivi
下载到内存中)即可看到现象,又成功了一点点。
胜不骄败不馁继续。。。
在u-boot中添加中添加对s3c2440一些寄存器的支持、添加中断禁止部分和时钟设置部分。因为u-boot启动的stage1主要集中在start.S 中所以我们还是修改这个文件。由《u-boot官方移植教程》可以知道linux内核启动时除了内核映像必须在主存的适当位置,cpu还必须具备一定的条件:
第一步要做的事情就是关闭看门狗(现在的狗狗还认不到主人先关起来免得被咬)u-boot中已经做了关闭的工作我们只需要添加defined(CONFIG_S3C2440)
#
if
defined
(
CONFIG_S3C2400
)
||
defined
(
CONFIG_S3C2410
)
|| defined(CONFIG_S3C2440)
/
*
turn off the watchdog
*/
由于
s3c2410
中的很多寄存器和
s3c2440
中的一样节约了很多时间(知道要选择类似模板的原因了吧)如
# define pWTCON 0x53000000
# define INTMSK 0x4A000008 /
*
Interupt
-
Controller base addresses
*/
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014 /
*
clock divisor register
*/
禁止中断:
mov
r1
,
#0xffffffff
ldr r0
,
=
INTMSK
str
r1
,
[
r0
]
#
if
defined
(
CONFIG_S3C2410
)
ldr r1
,
=
0x3ff
ldr r0
,
=
INTSUBMSK
str
r1
,
[
r0
]
#
endif
# if defined(CONFIG_S3C2440)
//
添加
s3c2440
的中断禁止部分
ldr r1, =0x7fff
//0111 1111 1111
根据
2440
芯片手册,
INTSUBMSK
寄存器有
15
位可用
//INTSUBMSK
寄存器在数据手册中的定义
从这里可以知道
1
代表屏蔽其使能;
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
//
添加
s3c2440
的时钟部分
关于
s3c2440
的时钟和电源管理:微处理器主时钟可以由外部晶振或外部时钟提供,选择后可以生成
FCLK,HCLK,PCLK
时钟信号,其中
FCLK
信号提供给
IP
核使用,
HCLK
提供给
IP
核和
AHB
总线,
PCLK
提供给
APB
总线使用。
FCLK
时钟值可以根据
MPLLCON
寄存器的值来设置。如
FCLK
的时钟频率为
271.5MHZ,
通过数据手册上面的
PLL VALUE SELECTION TABLE
可以得到
MPLLCON=0Xad022
FCLK
经过
HDIV
分频和
PDIV
分频后得到
HCLK
和
PCLK,FCLK
、
HCLK
、
PCLK
之间的关系设置
CLKDIVN
寄存器得到,如
FCLK:HCLK:PCLK=8:4:1
,则
CLKDIVN = 0X5
# if defined(CONFIG_S3C2440)
#define MPLLCON 0x4C000004 //系统主频配置寄存器基地址
#define UPLLCON 0x4C000008 //USB时钟频率配置寄存器基地址
ldr r0,=CLKDIVN //设置分频系数FCLK:HCLK:PCLK = 8:4:1
mov r1,#5
str r1,[r0]
ldr r0, =MPLLCON //设置系统主频为405MHz
ldr r1, =0x7F021 //这个值参考芯片手册“PLL VALUE SELECTION TABLE”部分
str r1, [r0]
ldr r0, =UPLLCON //设置USB时钟频率为48MHz
ldr r1, =0x38022 //这个值参考芯片手册“PLL VALUE SELECTION TABLE”部分
str r1, [r0]
# else //其他开发板的时钟部分,这里就不用管了,我们现在是做2440的
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz !*/
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
# endif
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 || CONFIG_S3C2440 */
S3C2440的时钟部分除了在start.S中添加外,还要分别在board/samsung/mini2440/mini2440.c和cpu/arm920t/s3c24x0/speed.c中修改或添加部分代码,如下:
(时钟和电源管理块由三部分组成:时钟控制,USB控制和电源的控制)
board/samsung/mini2440/mini2440.c:
#
define FCLK_SPEED
2
//
设置默认等于
2
,即下面红色代码部分有效
#
if
FCLK_SPEED
==
0
/* Fout = 203MHz, Fin = 12MHz for Audio */
#
define M_MDIV 0xC3
#
define M_PDIV 0x4
#
define M_SDIV 0x1
#
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
//
这三个值根据
S3C2440
芯片手册“PLL VALUE SELECTION TABLE”部分进行设置
#define M_PDIV 0x2
#define M_SDIV 0x1
#
endif
#
define USB_CLOCK
2
//
最开始默认为
1
不是我们想要的,设置默认等于
2
,即下面红色代码部分有效
#
if
USB_CLOCK
==
0
#
define U_M_MDIV 0xA1
#
define U_M_PDIV 0x3
#
define U_M_SDIV 0x1
#
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
//
这三个值根据
S3C2440
芯片手册“PLL VALUE SELECTION TABLE”部分进行设置
#define U_M_PDIV 0x2
#define U_M_SDIV 0x2
#
endif
cpu/arm920t/s3c24x0/speed.c:
static
ulong get_PLLCLK
(
int
pllreg
)
{
S3C24X0_CLOCK_POWER
*
const
clk_power
=
S3C24X0_GetBase_CLOCK_POWER
();
ulong r
,
m
,
p
,
s
;
if
(
pllreg
==
MPLL
)
r
=
clk_power
->
MPLLCON
;
else
if
(
pllreg
==
UPLL
)
r
=
clk_power
->
UPLLCON
;
else
hang
();
m
=
((
r
&
0xFF000
)
>>
12
)
+
8
;
p
=
((
r
&
0x003F0
)
>>
4
)
+
2
;
s
=
r
&
0x3
;
#if defined(CONFIG_S3C2440)
if(pllreg == MPLL)
{
//
参考
S3C2440
芯片手册上的公式:PLL=(2 * m * Fin)/(p * 2s)
return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
}
#endif
return
((
CONFIG_SYS_CLK_FREQ
*
m
)
/
(
p
<<
s
));
}
/* return HCLK frequency */
ulong get_HCLK
(
void
)
{
S3C24X0_CLOCK_POWER
*
const
clk_power
=
S3C24X0_GetBase_CLOCK_POWER
();
#if defined(CONFIG_S3C2440)
return(get_FCLK()/4);
#endif
return
((
clk_power
->
CLKDIVN
&
0x2
)
?
get_FCLK
()/
2
:
get_FCLK
());
}
和刚才的比较可以看出时钟部分对u-boot的重要性,时钟频率正确才能保证系统的正常工作。从超级终端我们可以看出来显示信息和我们开发板不同 我们的flash是2M而显示的是512K,原因是我们还没有添加nor flash的支持。
(以上移植参考了千兵卫博士的博客http://www.cnblogs.com/doctorqbw/archive/2011/11/16/2251395.html)