友善micro2440(s3c2440) U-boot移植过程
收藏
到u-boot官网
上
下载了最新版u-boot-2009.06。移植到过程主要是参照了韦东山的《嵌入式linux应用开发完全手册》一书。首先阅读了一下readme,全
E文,有点晕(又开始后悔英文学的不好了)。大体知道了编译u-boot官方推荐的开发环境ELDK,以及一些串口调试工具的设置
(minicom,ckermit..)。由于原来机器上本来就装了比较新的交叉编译工具(arm-linux-gcc4.3.2),就没有装eldk。
但后来在编译过程中发现很多东西的不兼容,没办法,还是把eldk给装上了(又得浪费了1G的空间了)。
环境搭建好后就开始了移植过程。简单看了一下书上讲的bootloader的原理,它的主要功能是初始化硬件,引导操作系统。当然,对于开发人员来说,它
还有一个功能是下载操作系统和文件系统到开发板的存储设备上去。下面是移植到具体过程:
(1)
首先选定开发板型号,若u-boot中没有提供,则选择一款最相近的,在其基础上修改。我的这款开发板(友善micro2440)是友善根据三星的公板自
己做的,u-boot中与其最相近的就是smdk2410了。
(2)
在顶层的makefile中添加开发板的选项。找到顶层makefile的smdk2410选项:
smdk2410_config : unconfig
(TAB键)@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
仿照其格式,在下面添加我自己的开发板选项(取名为micro2440)。
micro2440_config : unconfig
(TAB键) @$(MKCONFIG) $(@:_config=) arm arm920t micro2440 NULL s3c24x0
(3)
在board/samsung目录下添加micro2440文件夹(与makefile添加的项对应)。并复制该目录下smdk2410文件夹中的文件到
新建立的文件夹下。
(4)
在inclue/config目录下添加micro2440.h文件,内容就复制smdk2410.h的。这个文件是u-boot的配置文件,后面对u-
boot进行配置时基本上就是通过在这个文件中增加或减少宏定义实现的。
至此,第一阶段工作完成。在u-boot下执行make distclean ;make micro2440_congfig ;make
all验证一下编译是否能通过。没出错的话会编译生成u-boot.bin文件。我download到开发板下试了一下,如我所料,一点反应也没有。因为
代码还没有做任何修改,实际上这个u-boot是基于2410的,而2440和2410在时钟频率设置上有很大差别,所以cpu初始化时不能通过的。
下面进行代码修改:
u-boot属于两阶段的bootloader,第一阶段文件为cpu/arm920t/start.s和board/smdk2410
/lowlevel_init.s。前者是平台相关,后者是开发板相关。移植到新的平台时,一般这两个文件都要根据具体情况修改。
(1)修改sdram设置
sdram的初始化是在u-
boot引导的第一阶段的lowlevel_init.s中完成的。检查bank6设置:
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
- #define B1_BWSCON (DW32)
- #define B2_BWSCON (DW16)
- #define B3_BWSCON (DW16 + WAIT + UBLB)
- #define B4_BWSCON (DW16)
- #define B5_BWSCON (DW16)
- #define B6_BWSCON (DW32)
- #define B7_BWSCON (D
B6_BWSCON (DW32) 位宽为32,无需修改。
然后是根据hclk设置sdram刷新参数,主要是对REFCNT寄存器进行设置。我的开发板的hclk是100MHz,sdram芯片为
HY57V561620,查阅其datasheet,刷新周期为7.8125us。所以将
#define REFCNT 1113 /* period=15.6us, HCLK=60Mhz,
(2048+1-15.6*60) */
修改为
#define REFCNT 0x4f4 /* period=7.8125us, HCLK=100Mhz,
(2048+1-7.8125*100) */
(2)修改与时钟相关的部分。
首先是board/samsung/micro2440/micro2440.c中的board_init函数。将2410的时钟设置改成2440
的。代码如下:
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
-
-
-
- #define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
- #define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
- #define S3C2440_MPLL_100MHZ ((0x5c<<12)|(0x01<<4)|(0x03))
- #define S3C2440_UPLL_96MHZ ((0x38<<12)|(0x02<<4)|(0x01))
- #define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02))
- #define S3C2440_CLKDIV (0x05) // | (1<<3)) /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL/2 */
- #define S3C2440_CLKDIV188 0x04 /* FCLK:HCLK:PCLK = 1:8:8 */
- #define S3C2440_CAMDIVN188 ((0<<8)|(1<<9)) /* FCLK:HCLK:PCLK = 1:8:8 */
- int board_init (void)
- {
- S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
- S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
-
- gpio->GPACON = 0x007FFFFF;
- gpio->GPBCON = 0x00044555;
- gpio->GPBUP = 0x000007FF;
- gpio->GPCCON = 0xAAAAAAAA;
- gpio->GPCUP = 0x0000FFFF;
- gpio->GPDCON = 0xAAAAAAAA;
- gpio->GPDUP = 0x0000FFFF;
- gpio->GPECON = 0xAAAAAAAA;
- gpio->GPEUP = 0x0000FFFF;
- gpio->GPFCON = 0x000055AA;
- gpio->GPFUP = 0x000000FF;
- gpio->GPGCON = 0xFF95FFBA;
- gpio->GPGUP = 0x0000FFFF;
- gpio->GPHCON = 0x002AFAAA;
- gpio->GPHUP = 0x000007FF;
-
- gd->bd->bi_arch_number = MACH_TYPE_S3C2440;
-
- clk_power->CLKDIVN = S3C2440_CLKDIV;
-
- __asm__( "mrc p15, 0, r1, c1, c0, 0\n"
- "orr r1, r1, #0xc0000000\n"
- "mcr p15, 0, r1, c1, c0, 0\n"
- :::"r1"
- );
-
- clk_power->LOCKTIME = 0xFFFFFFFF;
-
- clk_power->UPLLCON = S3C2440_UPLL_48MHZ;
-
- delay (4000);
-
- clk_power->MPLLCON = S3C2440_MPLL_400MHZ;
-
- delay (8000);
-
- gd->bd->bi_boot_params = 0x30000100;
- icache_enable();
- #if 0
- dcache_enable();
- #endif
- return 0;
- }
然后修改cpu/arm920t/s3c24x0/speed.c中的get_HCLK,get_PLLCLK,get_PCLK函数。
get_PLLCLK函数中,将 return((CONFIG_SYS_CLK_FREQ * m) / (p
<< s));
改为 return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s)); /*
S3C2440 */。
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
-
- #define S3C2440_CLKDIVN_PDIVN (1<<0)
- #define S3C2440_CLKDIVN_HDIVN_MASK (3<<1)
- #define S3C2440_CLKDIVN_HDIVN_1 (0<<1)
- #define S3C2440_CLKDIVN_HDIVN_2 (1<<1)
- #define S3C2440_CLKDIVN_HDIVN_4_8 (2<<1)
- #define S3C2440_CLKDIVN_HDIVN_3_6 (3<<1)
- #define S3C2440_CLKDIVN_UCLK (1<<3)
- #define S3C2440_CAMDIVN_CAMCLK_MASK (0xf<<0)
- #define S3C2440_CAMDIVN_CAMCLK_SEL (1<<4)
- #define S3C2440_CAMDIVN_HCLK3_HALF (1<<8)
- #define S3C2440_CAMDIVN_HCLK4_HALF (1<<9)
- #define S3C2440_CAMDIVN_DVSEN (1<<12)
-
- ulong get_HCLK(void)
- {
- S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
- unsigned long clkdiv;
- unsigned long camdiv;
- int hdiv = 1;
- clkdiv = clk_power->CLKDIVN;
- camdiv = clk_power->CAMDIVN;
-
- switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
- case S3C2440_CLKDIVN_HDIVN_1:
- hdiv = 1;
- break;
- case S3C2440_CLKDIVN_HDIVN_2:
- hdiv = 2;
- break;
- case S3C2440_CLKDIVN_HDIVN_4_8:
- hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
- break;
- case S3C2440_CLKDIVN_HDIVN_3_6:
- hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
- break;
- return get_FCLK() / hdiv;
- }
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
- get_PCLK函数:
-
-
- ulong get_PCLK(void)
- {
- S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
- unsigned long clkdiv;
- unsigned long camdiv;
- int hdiv = 1;
- clkdiv = clk_power->CLKDIVN;
- camdiv = clk_power->CAMDIVN;
-
- switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
- case S3C2440_CLKDIVN_HDIVN_1:
- hdiv = 1;
- break;
- case S3C2440_CLKDIVN_HDIVN_2:
- hdiv = 2;
- break;
- case S3C2440_CLKDIVN_HDIVN_4_8:
- hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
- break;
- case S3C2440_CLKDIVN_HDIVN_3_6:
- hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
- break;
- return get_FCLK() / hdiv / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
- }
至此,第二阶段工作完成。重新执行 make micro2440_config 和 make all
后生成u-boot.bin。下载到开发板上,串口有输出了。
阅读(1063) | 评论(0) | 转发(1) |