zoukankan      html  css  js  c++  java
  • u-boot移植(五)---代码修改---时钟修改、SDRAM

      最开始已经建立了新单板以及配置文件,现在就需要做的是代码的修改,配置成适合目标板使用的u-boot。

    一、时钟修改

      在代码流程分析中,我们知道,系统的启动是:

    • 设置 CPU 为管理员模式
    • 关闭看门狗
    • 屏蔽中断
    • 设置启动参数:时钟 FCLK:HCLK:PCLK = 1:2:4     FCLK=120MHZ
    • flush v4 I/D caches
    • disable MMU stuff and caches
    • DRAM设置

      在DRAM设置中,有如下定义说明:

      

      在这段初始化步骤中,并没有看见系统时钟的设置。

      在S3C2440的datesheet中时钟那一章,我们可以看到如下定义:

      

      下面的英文的意思是:尽管 MPLL仅仅只是在一个 reset 后启动,但是直到软件对MPLLCON寄存器写一个有效的设置之后,MPLL才作为系统时钟的输出。在有效设置之前,从外部晶振源(XTlPll或EXTCLK)获得的时候将直接用于系统时钟。哪怕用户不想要改变MPLLCON寄存器的值,用户都应该写一个相同的值进MPLLCON寄存器。

      而我们外部时钟源的管脚定义说明如下:

      

      

      实际电路如下:

            

      黄色部分为我们外部时钟源(EXTCLK)的管脚,可以看到,外部时钟源被3.3V电压拉高。而管脚定义中已经说明,如果外部时钟源没有使用,则将此管脚拉高。

      OM[3:2]管脚都被拉低,则主时钟源和USB时钟源都选择的是外部晶振,外部晶振输入则为XTIpll管脚。晶振源为12MHz。

      再来看看CLK的定义:

    • FCLK: 为CPU核供给时钟信号,我们所说的cpu主频为200MHz,就是指的这个时钟信号,相应的,1/Fclk即为cpu时钟周期  
    • HCLK: 为AHB bus peripherals供给时钟信号,AHB为advanced high-performance bus
    • PCLK: 为APB bus peripherals供给时钟信号,APB为advanced peripherals bus

      分析一下时钟源码:

      

      CLKDIVN寄存器的定义如下:

      

        #3 = 0b0011   对应寄存器可知道

            DIVN_UPLL:UCLK = UPLL clock

            HDIVN:01  HCLK=FCLK/2

            PDIVN:0   PCLK = HCLK/2 = FCLK/4

      默认FCLK 为120MHz 则HDIVN和PDIVN都不为0,在datesheet的CLOCK CONTROL LOGIC 这一小节里面有这样的注意:

      

      意思就是说我们的S3C2440不支持同步总线模式,我们必须改为异步模式,那么我们必须在时钟设置上加上那段代母,修改CPU的总线模式,改后代码如下:

     1     /* FCLK:HCLK:PCLK = 1:2:4 */
     2     /* default FCLK is 120 MHz ! */
     3     /* 设置启动参数:时钟 */
     4     ldr    r0, =CLKDIVN            /* r0中存放时钟寄存器地址 */
     5     mov    r1, #3                    /* 将立即数0存放到r1中,r1 = 0x3 */
     6     str    r1, [r0]                /* 将r1中的值存放到以r0中的值为地址的存储单元中,即 CLKDIVN = 0 */
     7 
     8     /* MMU_SetAsyncBusMode */
     9     mrc p15,0,r0,c1,c0,0
    10     orr r0,r0,0xc0000000
    11     mcr p15,0,r0,c1,c0,0

      同样的,在The Clock Distribution Block Diagram (POWER MANAGEMENT )框图中,对FCLK有如下的定义:

       

      再来看看 normal mode和 slow mode是什么意思:

      

      

      我们CPU的启动是在normal mode中,同样所以此时,我们是在处于normal mode。

      MPLL为锁相环输出频率 ,用来给MCU提供频率,进而再给CPU的各个模块供应频率。具体可以看看datesheet中的Clock Generator Block Diagram 框图。而文档和前面已经说过:尽管 MPLL仅仅只是在一个 reset 后启动,但是直到软件对MPLLCON寄存器写一个有效的设置之后,MPLL才作为系统时钟的输出。在有效设置之前,从外部晶振源(XTlPll或EXTCLK)获得的时候将直接用于系统时钟。哪怕用户不想要改变MPLLCON寄存器的值,用户都应该写一个相同的值进MPLLCON寄存器。

      而我们的源码中,在时钟设置后,就直接跳到cpu_init_crit 去执行,在其中又跳进lowlevel_init中执行DRAM的初始化,并且注释中HCLK的默认频率为60MHZ,此时的HCLK是依赖于MPLL的,因此我们必须添加上MPLL的设置:

      

      注意下面的note:当我们设置MPLL & UPLL的值的时候,我们首先必须要设置UPLL的值,然后再设置MPLL的值。

      

      同样,在borad_f.c 中 board_early_init_f 函数里面,进行了时钟的初始化代码过程:

      

      我们可以将MPLL的设置放入我们的start.S中,并注释掉这里面的MPLL设置。

      修改如下:

      start.S 

     1     /* FCLK:HCLK:PCLK = 1:4:8 */
     2     /* default FCLK is 120 MHz ! */
     3     /* 设置启动参数:时钟 */
     4     ldr    r0, =CLKDIVN            /* r0中存放时钟寄存器地址 */
     5     mov    r1, #5                    /* 将立即数0存放到r1中,r1 = 0x3 */
     6     str    r1, [r0]                /* 将r1中的值存放到以r0中的值为地址的存储单元中,即 CLKDIVN = 0 */
     7 
     8     /* MMU_SetAsyncBusMode */
     9     mrc p15,0,r0,c1,c0,0
    10     orr r0,r0,0xc0000000
    11     mcr p15,0,r0,c1,c0,0
    12 
    13     /* MPLLCON = s3c2440_MPLL_400MHZ */
    14     ldr r0, =0x4c000004
    15     ldr r1, =s3c2440_MPLL_400MHZ
    16     str r1, [r0]
    17 
    18     /* 启动ICACHE */
    19     mrc p15, 0, r0, c1, c0, 0    /* read control reg */
    20     orr r0, r0, #(1<<12)
    21     mcr p15, 0, r0, c1, c0, 0    /* write it back */

      DRAM修改:lowlevel_init.S (boardsamsungjz2440) 

    /* 
     * 初始化存储控制器,经过此初始化之后,内存才可以使用
     */
     /* 地址为 0x00000eb0 */
    SMRDATA:
            .long 0x22011110     //BWSCON
            .long 0x00000700     //BANKCON0
            .long 0x00000700     //BANKCON1
            .long 0x00000700     //BANKCON2
            .long 0x00000700     //BANKCON3  
            .long 0x00000740     //BANKCON4
            .long 0x00000700     //BANKCON5
            .long 0x00018005     //BANKCON6
            .long 0x00018005     //BANKCON7
            .long 0x008C04F4     //REFRESH
            .long 0x000000B1     //BANKSIZE
            .long 0x00000030     //MRSRB6
            .long 0x00000030     //MRSRB7

      board_early_init_f(Jz2440.c (boardsamsungjz2440) ):

      

    二、调试

      完成修改后,进行编译调试:

    2.1 编译

      

      编译完成后,查看文件大小:

      

      编译出的文件大小公有500多KB。

    2.2 烧写进jz2440开发板

     2.2.1 烧写已经制作完成好的u-boot

      开发板拨码开关先拨至nand flash启动那端。

      用openjtag工具连接电脑和开发板,启动命令行,进入uboot-bin所在目录:

      

      启动oflash:

      

      输入数字0,启动openjtag:

      

      输入数字1,选择S3C2440:

      

      选择1 Nor Flash prog

      

      输入文件名:

      

      选择开始地址为0地址:

      

      开始烧写。

      烧写完成后,断开JTAG口。(JTAG 线上有复位引脚,使用 JTAG 工具烧好程序后,一定要把 JTAG 工具和开发板之间的 JTAG 排线断开, 并给开发板重新上电,开发板上的程序才能正常启动。

    2.2.2 烧写新的u-boot

      连接串口线,开发板设置为nor启动,启动开发板。启动过程中按空格键

       

      按q退出后,输入命令查看分区大小:

      

      bootloader分区不够,我们的新的u-boot.bin有500多K,无法用命令o来烧写。只能使用命令来烧写,接上USB线。

      打开dnw工具:

      

      输入如下命令:

      

      设置dnw工具:

      点击USB Port-》transmit->transmit,选择新编译的u-boot.bin。

      

      此时只是把文件发送到了内存当中。

      去掉nor flash的写保护:

      

      从0地址开始擦除:

      

      从30000000地址把程序拷贝到nor flash的0地址。

      

      重启开发板,查看烧写,串口上无任何反应。

    2.3 调试

      使用openjtag进行调试。连接openjtag  adapter。

      打开openOCD GUI工具 点击connect。

      

      打开telnet:

      

      执行命令,查看信息:

      

      查看nor flash的0地址:

        

      

       执行反汇编命令,生成u-boot.dis:

      

      结合代码查看,start.S中是执行玩了 cpu_init_crit后,跳转到 _main中去执行:

      

      _main在u-boot.dis中的地址如下:

      

      从0地址开始运行:

      

      在telnet中设置断点:

      

      继续运行:

      

      由于代码中那时候内存已经初始化,那么此时内存应该是可以访问的:

      读内存:

      

      写内存,并将内存读取出来:

      

      数据是正确的,证明我们的修改没有问题。SDRAM 的修改没有问题。

      此时还有一个问题是,我们的串口无任何打印。留待下一个再分析

      

      

      

     

  • 相关阅读:
    基于Hadoop的改进Apriori算法
    iOS 访问URL转码
    第一次进入应用图片轮播效果
    购物篮模型&Apriori算法
    Ionicons的使用
    如何在 Eclipse 中使用命令行
    Eclipse输入命令行参数
    CHAR,TCHAR,WCHAR 三者的区别与转换
    函数名、变量前后的_(一个下划线)、__(两个下划线)分别有什么用
    java爬虫简单实现
  • 原文地址:https://www.cnblogs.com/kele-dad/p/6952393.html
Copyright © 2011-2022 走看看