Chinaunix首页 | 论坛 | 博客
  • 博客访问: 32354
  • 博文数量: 12
  • 博客积分: 445
  • 博客等级: 下士
  • 技术积分: 150
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-06 16:49
文章分类

全部博文(12)

文章存档

2012年(12)

我的朋友

分类: 嵌入式

2012-10-06 21:36:13

3、根据u-boot启动流程图的步骤来分析及修改u-boot源码,使其适合smdk2440开发板
     
      注:修改或添加的地方用红色表示


(1) u-boot的stage1入口点分析

    一般在嵌入式系统软件开发中,在所有源码文件编译完成之后,链接器要读取一个链接分配文件,在该文件中定义了程序的入口点,代码段、数据段等分配情况等。那么我们的smdk2440开发板u-boot的这个链接文件就是cpu/arm920t/u-boot.lds,打开该文件部分代码如下:

  1. OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
  2. OUTPUT_ARCH(arm)    //定义生成文件的目标平台是arm
  3. ENTRY(_start)       //定义程序的入口点是_start
  4. SECTIONS
  5. {
  6.     //其他一些代码段、数据段等分配
  7.     . = 0x00000000;
  8.     . = ALIGN(4);

  9.     .text :
  10.     {
  11.         cpu/arm920t/start.o (.text)
  12.         *(.text)
  13.     }
  14.     ..................
  15.     ..................
  16. }
    知道了程序的入口点是_start,那么我们就打开smdk2440开发板u-boot第一个要运行的程序cpu/arm920t/start.S,查找到_start的位置如下:

  1. .globl _start
  2. _start: b start_code     //将程序的执行跳转到start_code处
     从这个汇编代码可以看到程序又跳转到start_code处开始执行,那么再查找到start_code处的代码如下:

  1. /*
  2. * the actual start code
  3. */
  4. start_code:
  5. /*
  6. * set the cpu to SVC32 mode
  7. */
  8. mrs r0,cpsr
  9. bic r0,r0,#0x1f
  10. orr r0,r0,#0xd3
  11. msr cpsr,r0
  12. bl coloured_LED_init //此处两行是对AT91RM9200DK开发板上的LED进行初始                       //化
  13. 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运行的状态,给调试带来方便,可将该段代码放到任何你想调试的地方),代码如下:

  1. #if 0       //这两行是AT91RM9200DK开发板的LED初始化,注释掉
  2.   bl coloured_LED_init
  3.   bl red_LED_on
  4. #endif

  5. #if defined (CONFIG_S3C2440)
  6.        /*根据XC2440原理图可知LED分别由S3C2440的PF0、1、2、3口来控制,以下是PB端口寄          存器基地址(查2440的DataSheet得知)*/
  7.   #define GPFCON 0x56000050
  8.   #define GPFDAT 0x56000054
  9.   #define GPFUP 0x56000058
  10.   ldr r0, =GPFUP
  11.   ldr r1, =0x0f
  12.   str r1, [r0]
  13.   ldr r0, =GPFCON
  14.   ldr r1, =0x55
  15.   str r1, [r0]
  16.   ldr r0, =GPFDAT
  17.   ldr r1, =0x0c   
  18.   str r1, [r0]
  19. #endif
  20. //此段代码使u-boot启动后,点亮开发板上的LED1和LED2
    include/configs/smdk2440.h头文件中添加CONFIG_S3C2440宏 

  1. #define CONFIG_ARM920T    1    /* This is an ARM920T Core    */
  2. #define CONFIG_S3C24X0    1    /* in a SAMSUNG S3C24x0-type SoC    */
  3. #define CONFIG_S3C2410    1  /*specifically a SAMSUNG S3C2410 SoC */
  4. #define CONFIG_SMDK2410    1    /* on a SAMSUNG SMDK2410 Board */
  5. #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的支持即可,代码如下:
   
  1. #ifdef CONFIG_S3C24X0
  2. /* turn off the watchdog */
  3. # if defined(CONFIG_S3C2400)
  4. # define pWTCON 0x15300000
  5. # define INTMSK 0x14400008 /* Interupt-Controller base addresses */
  6. # define CLKDIVN 0x14800014 /* clock divisor register */
  7. #else
  8. # define pWTCON 0x53000000
  9. # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
  10. # define INTSUBMSK 0x4A00001C
  11. # define CLKDIVN 0x4C000014 /* clock divisor register */
  12. # endif
  13. ldr r0, =pWTCON
  14. mov r1, #0x0
  15. str r1, [r0]
  16. /*
  17. * mask all IRQs by setting all bits in the INTMR - default
  18. */
  19. mov r1, #0xffffffff
  20. ldr r0, =INTMSK
  21. str r1, [r0]

  22. # if defined(CONFIG_S3C2410)
  23. ldr r1, =0x3ff
  24. ldr r0, =INTSUBMSK
  25. str r1, [r0]
  26. # endif

  27. #if defined(CONFIG_S3C2440)
  28. ldr r1, =0x7fff          //根据2440芯片手册,INTSUBMSK寄存器有15位可用
  29. ldr r0, =INTSUBMSK
  30. str r1, [r0]
  31. #endif
  32. #if defined(CONFIG_S3C2440)      //添加s3c2440的时钟部分
  33. #define MPLLCON 0x4C000004
  34. #define UPLLCON 0x4C000008
  35. ldr r0, =CLKDIVN
  36. mov r1, #5              //设置分频系数FCLK:HCLK:PCLK = 1:4:8
  37. str r1, [r0]
  38. ldr r0, =MPLLCON
  39. ldr r1, =0x7F021       //设置系统主频为405MHz 
  40. str r1, [r0]
  41. ldr r0, =UPLLCON
  42. ldr r1, =0x38022        //设置USB时钟频率为48MHz 
  43. str r1, [r0]
  44. #else
  45. /* FCLK:HCLK:PCLK = 1:2:4 */
  46. /* default FCLK is 120 MHz ! */
  47. ldr r0, =CLKDIVN
  48. mov r1, #3
  49. str r1, [r0]
  50. #endif 
  51. #endif /* CONFIG_S3C24X0 */

     S3C2440的时钟部分除了在start.S中添加外,还要分别在board/samsung/smdk2440/smdk2440.c和cpu/arm920t/s3c24x0/speed.c中修改或添加部分代码:

smdk2440.c中的修改如下:

  1.         //设置主频和USB时钟频率参数与start.S中的一致
  2. #define FCLK_SPEED 2     //设置默认等于2,即下面红色代码部分有效

  3. #if FCLK_SPEED==0        /* Fout = 203MHz, Fin = 12MHz for Audio */
  4. #define M_MDIV    0xC3
  5. #define M_PDIV    0x4
  6. #define M_SDIV    0x1
  7. #elif FCLK_SPEED==1        /* Fout = 202.8MHz */
  8. #define M_MDIV    0xA1
  9. #define M_PDIV    0x3
  10. #define M_SDIV    0x1

  11. #elif FCLK_SPEED==2      
  12. #define M_MDIV    0x7f
  13. #define M_PDIV    0x2
  14. #define M_SDIV    0x1
  15. #endif

  16. #define USB_CLOCK 2

  17. #if USB_CLOCK==0
  18. #define U_M_MDIV    0xA1
  19. #define U_M_PDIV    0x3
  20. #define U_M_SDIV    0x1
  21. #elif USB_CLOCK==1
  22. #define U_M_MDIV    0x48
  23. #define U_M_PDIV    0x3
  24. #define U_M_SDIV    0x2

  25. #elif USB_CLOCK==2
  26. #define U_M_MDIV    0x38
  27. #define U_M_PDIV    0x2
  28. #define U_M_SDIV    0x2

  29. #endif

speed.c中的修改如下:

  1. static ulong get_PLLCLK(int pllreg)
  2. {
  3.     struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
  4.     ulong r, m, p, s;

  5.     if (pllreg == MPLL)
  6.         r = readl(&clk_power->MPLLCON);
  7.     else if (pllreg == UPLL)
  8.         r = readl(&clk_power->UPLLCON);
  9.     else
  10.         hang();

  11.     m = ((r & 0xFF000) >> 12) + 8;
  12.     p = ((r & 0x003F0) >> 4) + 2;
  13.     s = r & 0x3;

  14. #if defined(CONFIG_S3C2440)
  15.     if (pllreg == MPLL)
  16.     {
  17.         //参考S3C2440 芯片手册上的公式:PLL=(2 * m * Fin)/(p * 2s)
  18. return (CONFIG_SYS_CLK_FREQ * m * 2) / (p << s);    
  19.     }
  20. #endif

  21.     return (CONFIG_SYS_CLK_FREQ * m) / (p << s);
  22. }

  23. /* return FCLK frequency */
  24. ulong get_FCLK(void)
  25. {
  26.     return get_PLLCLK(MPLL);
  27. }

  28. /* return HCLK frequency */
  29. ulong get_HCLK(void)
  30. {
  31.     struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();

  32. #if defined(CONFIG_S3C2440)
  33.     return(get_FCLK()/4);
  34. #endif

  35.     return (readl(&clk_power->CLKDIVN) & 2) ? get_FCLK() / 2 : get_FCLK();
  36. }

    修改完毕后我们再重新编译u-boot,然后再下载到Norflash中运行测试。结果终端有输出信息并且出现类似Shell的命令行,这说明这一部分移植完成。示意图如下
阅读(1036) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~