3、根据u-boot启动流程图的步骤来分析及修改u-boot源码,使其适合smdk2440开发板
注:修改或添加的地方用红色表示
(1) u-boot的stage1入口点分析
一般在嵌入式系统软件开发中,在所有源码文件编译完成之后,链接器要读取一个链接分配文件,在该文件中定义了程序的入口点,代码段、数据段等分配情况等。那么我们的smdk2440开发板u-boot的这个链接文件就是cpu/arm920t/u-boot.lds,打开该文件部分代码如下:
- OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
- OUTPUT_ARCH(arm) //定义生成文件的目标平台是arm
- ENTRY(_start) //定义程序的入口点是_start
- SECTIONS
- {
- //其他一些代码段、数据段等分配
- . = 0x00000000;
- . = ALIGN(4);
- .text :
- {
- cpu/arm920t/start.o (.text)
- *(.text)
- }
- ..................
- ..................
- }
知道了程序的入口点是_start,那么我们就打开smdk2440开发板u-boot第一个要运行的程序cpu/arm920t/start.S,查找到_start的位置如下:
- .globl _start
- _start: b start_code //将程序的执行跳转到start_code处
从这个汇编代码可以看到程序又跳转到start_code处开始执行,那么再查找到start_code处的代码如下:- /*
- * the actual start code
- */
- start_code:
- /*
- * set the cpu to SVC32 mode
- */
- mrs r0,cpsr
- bic r0,r0,#0x1f
- orr r0,r0,#0xd3
- msr cpsr,r0
- bl coloured_LED_init //此处两行是对AT91RM9200DK开发板上的LED进行初始 //化的
- bl red_LED_on
由此可以看到,start_code处才是u-boot启动代码的真正开始处。以上就是u-boot的stage1入口的过程。
(2) u-boot的stage1阶段的硬件设备初始化
由于在u-boot启动代码处有两行是AT91RM9200DK的LED初始代码,但我们smdk2440上的LED资源与该开发板的不一致,所以我们要删除或屏蔽该处代码,再加上smdk2440的LED驱动代码(注:添加smdk2440 LED功能只是用于表示u-boot运行的状态,给调试带来方便,可将该段代码放到任何你想调试的地方),代码如下:
- #if 0
//这两行是AT91RM9200DK开发板的LED初始化,注释掉
- bl coloured_LED_init
- bl red_LED_on
- #endif
- #if defined (CONFIG_S3C2440)
- /*根据XC2440原理图可知LED分别由S3C2440的PF0、1、2、3口来控制,以下是PB端口寄 存器基地址(查2440的DataSheet得知)*/
- #define GPFCON 0x56000050
- #define GPFDAT 0x56000054
- #define GPFUP 0x56000058
- ldr r0, =GPFUP
- ldr r1, =0x0f
- str r1, [r0]
- ldr r0, =GPFCON
- ldr r1, =0x55
- str r1, [r0]
- ldr r0, =GPFDAT
- ldr r1, =0x0c
- str r1, [r0]
- #endif
- //此段代码使u-boot启动后,点亮开发板上的LED1和LED2
在include/configs/smdk2440.h头文件中添加CONFIG_S3C2440宏 - #define CONFIG_ARM920T 1 /* This is an ARM920T Core */
- #define CONFIG_S3C24X0 1 /* in a SAMSUNG S3C24x0-type SoC */
- #define CONFIG_S3C2410 1 /*specifically a SAMSUNG S3C2410 SoC */
- #define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */
- #define CONFIG_S3C2440 1
/* on a SAMSUNG SMDK2440 Board */
编译u-boot,在根目录下会生成一个u-boot.bin文件,然后利用Jlink把u-boot.bin下载到Norflash中运行测试。 下载运行后可以看到开发板上的LED灯第一个和第二个亮了,其他两个熄灭,测试结果符合上面的要求。
(3)在u-boot中添加对S3C2440一些寄存器的支持,添加中断禁止部分和时钟设置部分
由于2410和2440的寄存器及地址大部分是一致的,所以这里就直接在2410的基础上再加上对2440的支持即可,代码如下:
- #ifdef CONFIG_S3C24X0
- /* turn off the watchdog */
- # if defined(CONFIG_S3C2400)
- # define pWTCON 0x15300000
- # define INTMSK 0x14400008 /* Interupt-Controller base addresses */
- # define CLKDIVN 0x14800014 /* clock divisor register */
- #else
- # define pWTCON 0x53000000
- # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
- # define INTSUBMSK 0x4A00001C
- # define CLKDIVN 0x4C000014 /* clock divisor register */
- # endif
- ldr r0, =pWTCON
- mov r1, #0x0
- str r1, [r0]
- /*
- * mask all IRQs by setting all bits in the INTMR - default
- */
- 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)
- ldr r1, =0x7fff
//根据2440芯片手册,INTSUBMSK寄存器有15位可用
- ldr r0, =INTSUBMSK
- str r1, [r0]
- #endif
- #if defined(CONFIG_S3C2440)
//添加s3c2440的时钟部分
- #define MPLLCON 0x4C000004
- #define UPLLCON 0x4C000008
-
- ldr r0, =CLKDIVN
- mov r1, #5
//设置分频系数FCLK:HCLK:PCLK = 1:4:8
- str r1, [r0]
-
- ldr r0, =MPLLCON
- ldr r1, =0x7F021
//设置系统主频为405MHz
- str r1, [r0]
-
- ldr r0, =UPLLCON
- ldr r1, =0x38022
//设置USB时钟频率为48MHz
- str r1, [r0]
- #else
- /* FCLK:HCLK:PCLK = 1:2:4 */
- /* default FCLK is 120 MHz ! */
- ldr r0, =CLKDIVN
- mov r1, #3
- str r1, [r0]
- #endif
- #endif /* CONFIG_S3C24X0 */
S3C2440的时钟部分除了在start.S中添加外,还要分别在board/samsung/smdk2440/smdk2440.c和cpu/arm920t/s3c24x0/speed.c中修改或添加部分代码:
smdk2440.c中的修改如下:
- //设置主频和USB时钟频率参数与start.S中的一致
- #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
- #define M_MDIV 0x7f
- #define M_PDIV 0x2
- #define M_SDIV 0x1
- #endif
- #define USB_CLOCK 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
- #define U_M_MDIV 0x38
- #define U_M_PDIV 0x2
- #define U_M_SDIV 0x2
- #endif
speed.c中的修改如下:
- static ulong get_PLLCLK(int pllreg)
- {
- struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
- ulong r, m, p, s;
- if (pllreg == MPLL)
- r = readl(&clk_power->MPLLCON);
- else if (pllreg == UPLL)
- r = readl(&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 FCLK frequency */
- ulong get_FCLK(void)
- {
- return get_PLLCLK(MPLL);
- }
- /* return HCLK frequency */
- ulong get_HCLK(void)
- {
- struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
- #if defined(CONFIG_S3C2440)
- return(get_FCLK()/4);
- #endif
- return (readl(&clk_power->CLKDIVN) & 2) ? get_FCLK() / 2 : get_FCLK();
- }
修改完毕后我们再重新编译u-boot,然后再下载到Norflash中运行测试。结果终端有输出信息并且出现类似Shell的命令行,这说明这一部分移植完成。示意图如下:
阅读(1033) | 评论(0) | 转发(0) |