今天是我申请此博客的第一天,从现在开始养成每次学完新东西,都要写博客进行总结的习惯!!!Come on!
首先就从这两天学的uboot开始吧,这两天学这个东西郁闷死了,不知道该怎么去学,尤其是到nand那部分,根据mini2440之uboot移植详细手册进行改写uboot,越到后面越头疼,怎么办??今天下载了aiku的驱动视频感觉不错,等这两天把之前学的uboot总结一下,还是回归学习驱动吧。总之学这个东西,我现在觉得就是颠来倒去一点点深入地学习。不说废话了,开始吧:
一、简介
根据国嵌实验手册4.2.4,基于uboot-2008.10,移植出可以在mini2440 norflash上运行的uboot
二、uboot启动简述
uboot与其他bootloader类似,有两个阶段
stage1:
1、初始化硬件
2、为stage2运行代码准备RAM空间
3、将stage2代码复制到RAM空间
4、设置堆栈
5、跳转到stage2的C入口点
stage2:
1、初始化本阶段要使用的硬件
2、检测系统内存映射
3、将内核映像和根文件系统,从Flash读到RAM空间
4、为内核设置启动参数
5、调用内核
1、系统上电 2、_start标号(cpu/arm920t/start.s)3、reset标号(start.s)4、cpu_init_crit标号(start.s)5、low_level_init.s(board/smdk2410/low_level_init.s)5、relocate标号(start.s)6、_start_arm_boot标号(start.s)7、start_armboot()函数(lib_arm/board.c)8、main_loop()函数(common/main.c)9、进入uboot命令行
三、开始移植
1、修改顶层Makefile
根据
smdk2410_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
添加
mini2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t mini2440 NULL s3c24x0
2、修改cpu/arm920t/start.S (加黑的为添加部分)
2.1、添加对S3C2440的支持 代码136行
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
2.2、添加寄存器的定义与修改时钟频率的参数
# define CLK_CTL_BASE 0x4c000000
# define MDIV_405 0x7f<<12
# define PSDIV_405 0x21
# define UPLL_MDIV_48 0x38<<12
# define UPLL_PSDIV_48 0x22
# define MDIV_200 0xa1<<12
# define PS_DIV_200 0x31
2.3、修改中断禁止部分,添加s3口440中断禁止代码 代码164行 后面添加
# if defined(CONFIG_S3C2440)
ldr r1, =0x7fff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
2.4、修改时钟设置(将s3c2440主频设置为405MHz)
/*FCLK:HCLK:PCLK=1:2:4*/ 166行左右
/*defauk FCLK is 120Mhz!*/
ldr r0,=CLKDlVN
mov r1,#3
str r1,[r0]
改为
179 # if defined(CONFIG_S3C2440)
180 /* FCLK:HCLK:PCLK = 1:4:8 */
181 ldr r0, =CLKDIVN
182 mov r1, #5
183 str r1, [r0]
184
185 mrc p15, 0, r1, c1, c0, 0
186 orr r1, r1, #0xc0000000
187 mcr p15, 0, r1, c1, c0, 0
188
189 mov r1, #CLK_CTL_BASE
190
191 mov r2, #UPLL_MDIV_48
192 add r2, r2, #UPLL_PSDIV_48
193 str r2, [r1, #0x08]
194
195 mov r2, #MDIV_405
196 add r2, r2, #PSDIV_405
197 str r2, [r1, #0x04]
199 # else
200 /* FCLK:HCLK:PCLK = 1:2:4 */
201 ldr r0, =CLKDIVN
202 mov r1, #3
203 str r1, [r0]
204
205 mrc p15, 0, r1, c1, c0, 0
206 orr r1, r1, #0xc0000000
207 mcr p15, 0, r1, c1, c0, 0
208
209 mov r1, #CLK_CTL_BASE
210 mov r2, #MDIV_200
211 add r2, r2, #PSDIV_200
212 str r2, [r1, #0x04]
213
214 # endif
3、修改cpu/arm920t/s3c24x0/interrupt.c
3.1、 修改宏定义,增加对S3C2440的支持 (加黑的为添加部分)
32 #include <common.h>
33 #if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined(CONFIG_S3C2440) || defined (CONFIG_TRAB)
34
35 #include <arm920t.h>
36 #if defined(CONFIG_S3C2400)
37 #include <s3c2400.h>
38 #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
39 #include <s3c2410.h>
40 #endif
3.2、 在函数get_tbclk()中添加对mini2440的支持 (加黑的为添加部分)
173 ulong get_tbclk (void)
174 {
175 ulong tbclk;
176
177 #if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB)
178 tbclk = timer_load_val * 100;
179 #elif defined(CONFIG_SBC2410X) || \
180 defined(CONFIG_SMDK2410) || \
181 defined(CONFIG_MINI2440) || \
182 defined(CONFIG_VCMA9)
183 tbclk = CFG_HZ;
184 #else
185 # error "tbclk not configured"
186 #endif
187
188 return tbclk;
189 }
4、修改cpu/arm920t/s3c24x0/speed.c
4.1、 修改宏定义,增加对S3C2440的支持 (加黑的为添加部分)
32 #include <common.h>
33 #if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined(CONFIG_S3C2440) || defined (CONFIG_TRAB)
34
35 #if defined(CONFIG_S3C2400)
36 #include <s3c2400.h>
37 #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
38 #include <s3c2410.h>
39 #endif
4.2、修改函数get_PLLCLK() (加黑的为添加部分)
由于S3C2440的MPLL计算公式与S3C2410不一样,而UPLL的计算公式一样,所以修改如下
54 static ulong get_PLLCLK(int pllreg)
55 {
56 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
57 ulong r, m, p, s;
58
59 if (pllreg == MPLL)
60 r = clk_power->MPLLCON;
61 else if (pllreg == UPLL)
62 r = clk_power->UPLLCON;
63 else
64 hang();
65
66 m = ((r & 0xFF000) >> 12) + 8;
67 p = ((r & 0x003F0) >> 4) + 2;
68 s = r & 0x3;
69
70 #if defined(CONFIG_S3C2440)
71 if (pllreg == MPLL)
72 return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
73 #endif
74
75 return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
76 }
4.3、修改函数get_HCLK() (加黑的为添加部分)
具体修改参考S3C2440数据手册
85 ulong get_HCLK(void)
86 {
87 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
88
89 #if defined(CONFIG_S3C2440)
90 if(clk_power->CLKDIVN & 0x6)
91 {
92 if (2 == (clk_power->CLKDIVN & 0x6))
93 return (get_FCLK()/2);
94 if (6 == (clk_power->CLKDIVN & 0x6))
95 return((clk_power->CAMDIVN & 0x100) ? get_FCLK()/6 : get_FCLK()/3) ;
96 if (4 == (clk_power->CLKDIVN & 0x6))
97 return((clk_power->CAMDIVN & 0x200) ? get_FCLK()/8 : get_FCLK()/4) ;
98 else
99 return (get_FCLK());
100 }
101 else
102 return (get_FCLK());
103
104 #else
105 return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
106 #endif
107 }
5、修改cpu/arm920t/s3c24x0/serial.c (加黑的为添加部分)
21 #include <common.h>
22 #if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined(CONFIG_S3C2440) || defined (CONFIG_TRAB)
23
24 #if defined(CONFIG_S3C2400) || defined(CONFIG_TRAB)
25 #include <s3c2400.h>
26 #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
27 #include <s3c2410.h>
28 #endif
6、修改drivers/rtc/s3c24x0_rtc.c (加黑的为添加部分)
28 #include <common.h>
29 #include <command.h>
30
31 #if (defined(CONFIG_CMD_DATE))
32
33 #if defined(CONFIG_S3C2400)
34 #include <s3c2400.h>
35 #elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
36 #include <s3c2410.h>
37 #endif
7、修改include/asm-arm/mach-type.h
第1859行左右添加
#define MACH_TYPE_MINI2440 1999
8、修改include/s3c24x0.h(加黑的为添加部分)
添加寄存器定义
77 /* INTERRUPT (see manual chapter 14) */
78 typedef struct {
………………
83 S3C24X0_REG32 INTPND;
84 S3C24X0_REG32 INTOFFSET;
85 #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
86 S3C24X0_REG32 SUBSRCPND;
87 S3C24X0_REG32 INTSUBMSK;
88 #endif
89 } /*__attribute__((__packed__))*/ S3C24X0_INTERRUPT;
92 /* DMAS (see manual chapter 8) */
93 typedef struct {
94 S3C24X0_REG32 DISRC;
95 #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
96 S3C24X0_REG32 DISRCC;
97 #endif
98 S3C24X0_REG32 DIDST;
99 #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
100 S3C24X0_REG32 DIDSTC;
101 #endif
…………
110 #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
111 S3C24X0_REG32 res[7];
112 #endif
113 } /*__attribute__((__packed__))*/ S3C24X0_DMA;
120 /* CLOCK & POWER MANAGEMENT (see S3C2400 manual chapter 6) */
121 /* (see S3C2410 manual chapter 7) */
122 typedef struct {
………
128 S3C24X0_REG32 CLKDIVN;
129 #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
130 S3C24X0_REG32 CAMDIVN;
131 #endif
132 } /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER;
135 /* LCD CONTROLLER (see manual chapter 15) */
136 typedef struct {
……
149 S3C24X0_REG32 DITHMODE;
150 S3C24X0_REG32 TPAL;
151 #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
152 S3C24X0_REG32 LCDINTPND;
153 S3C24X0_REG32 LCDSRCPND;
154 S3C24X0_REG32 LCDINTMSK;
155 S3C24X0_REG32 LPCSEL;
156 #endif
157 } /*__attribute__((__packed__))*/ S3C24X0_LCD;
372 /* I/O PORT (see manual chapter 9) */
373 typedef struct {
374 #ifdef CONFIG_S3C2400
………
407 #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
408 S3C24X0_REG32 GPACON;
409 S3C24X0_REG32 GPADAT;
……………
457 } /*__attribute__((__packed__))*/ S3C24X0_GPIO;
9、在board目录中添加属于新开发板的目录
(1)在board目录下创建mini2440文件夹,将board/smdk2410下的所有文件拷贝到mini2440文件夹下
(2)将mini2440文件夹下的smdk2410.c改为mini2440.c
(3)修改mini2440文件夹下的Makefile, COBJS := mini2440.o flash.o
10、修改board/mini2440/mini2440.c (修改如下)
39 #elif FCLK_SPEED==1 /* Fout = 202.8MHz */
40
41 #if defined(CONFIG_S3C2440)
42 #define M_MDIV 0x7f
43 #define M_PDIV 0x2
44 #define M_SDIV 0x1
45 #endif
46
47 #if defined(CONFIG_S3C2410)
48 #define M_MDIV 0xA1
49 #define M_PDIV 0x3
50 #define M_SDIV 0x1
51 #endif
52
53 #endif
61 #elif USB_CLOCK==1
62
63 #if defined(CONFIG_S3C2440)
64 #define U_M_MDIV 0x38
65 #define U_M_PDIV 0x2
66 #define U_M_SDIV 0x2
67 #endif
68
69 #if defined(CONFIG_S3C2410)
70 #define U_M_MDIV 0x48
71 #define U_M_PDIV 0x3
72 #define U_M_SDIV 0x2
73 #endif
74
75 #endif
88 int board_init (void)
89 {
…………
125 /* arch number of SMDK2410-Board */
126 gd->bd->bi_arch_number = MACH_TYPE_MINI2440;
128 /* adress of boot parameters */
129 gd->bd->bi_boot_params = 0x30000100;
130
131 icache_enable();
132 dcache_enable();
133
134 return 0;
135 }
11、修改board/mini2440/lowlevel_init.S (修改如下)
#define REFCNT 1012 改为 #define REFCNT 0x4f4
原因:根据SDRAM芯片手册上说的 8192(8K) refresh cycles / 64ms 得到 SDRAM刷新周期 period=64ms/8192 =7.8125us
REFCNT 是刷新控制寄存器REFRESH的Refresh Counter([10:0])
SDRAM时钟频率就是HCLK的频率
REFCNT = 2^11 + 1 - SDRAM时钟频率(MHz) * SDRAM刷新周期(us) = 2^11 + 1 – 100 * 7.8125 = 1267.75 = 0x4F4
12、修改配置文件 include/configs/mini2440.h
将include/configs下的smdk2410.h 拷贝一份到mini2440.h
36 #define CONFIG_ARM920T 1 /* This is an ARM920T Core */
37 #define CONFIG_S3C2410 1 /* in a SAMSUNG S3C2410 SoC */
38 #define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */
改为
36 #define CONFIG_ARM920T 1 /* This is an ARM920T Core */
37 #define CONFIG_S3C2440 1 /* in a SAMSUNG S3C2440 SoC */
38 #define CONFIG_MINI2440 1 /* on a SAMSUNG Mini440 Board */
13、编译
#make clean
#make mini2440_config
#make CROSS_COMPILE=arm-linux-