zoukankan      html  css  js  c++  java
  • ARM芯片时钟体系

     目标:

      1、了解S3C2440的时钟体系结构

      2、掌握通过设置MPLL改变系统时钟的方法

      

    一、S3C2440的时钟体系结构

      什么是时钟体系?

        ARM的时钟系统包括4部分,分为晶体振荡器、唤醒定时器、锁相环(PLL)和VPB分频器,是一种电路。

      时钟系统有什么作用

        时钟是嵌入式系统的脉搏,处理器内核在时钟驱动下完成指令执行,状态变换等动作。

        外设部件在时钟的驱动下完成各种工作,比如串口数据的发送、A/D转换、定时器计数等等。

      时钟体系是怎么运作的? 

        当系统复位或者处理器从掉电模式唤醒时,“唤醒定时器”要对输入的时钟信号做计数延时,使芯片内部的部件有时间进行初始化。

        然后Fosc(时钟源)被PLL(锁相环/倍频器)提高到一个符合用户需要的频率Fcclk,Fcclk用于CPU内核。因为CPU内核通常比外设部件的工作速度要快,

        用户可以通过设置VPB分频器,把Fcclk信号降低到一个合适的值Fpclk,该信号用于外设部件。如下图:

                  

       

             再看看2440的结构图

       由上图,可知时钟控制逻辑给整个芯片提供了3种时钟:

      FCLK:帧时钟,用于CPU核;(如何选择CPU核的工作时钟是FCLK还是HCLK?)

      HCLK:总线时钟,用于AHB高速总线上的设备,比如CPU核,存储器控制器、中断控制器、LCD控制器等

      PCLK:外设时钟,用于APB总线上的设备,如看门狗,IIS,IIC,PWM,UART,GPIO,SPI,MMC等。

    对于2440 外接的晶振仅12MHz, 但CPU核的主频可以高达400MHz,总线时钟可以达136MHz, 而外设时钟可达68MHz,那如何设置才能使不同的时钟输出不同的时钟频率呢?

      通过一些硬件单元来处理,PLL--Phase Locked Loop -- 锁相环,

      2440有两个锁相环,MPLL -- Main PLL ,UPLL -- USB PLL,两者设置方法相同,以MPLL为例。

    从芯片手册上可以看到,时钟模块发生框图:

     在该图的左上角,晶振和一个外部时钟接在一个选择器上,这个选择器通过OM[3:2]的值来决定选择哪个时钟源。然后生成的MPLL(Main PLL)和UPLL(USB PLL),MPLL直接提供给FCLK,通过HDIVN分频给HCLK,通过PDIVN分频给PCLK,再传给下面的各个设备:

    那如何设置PLL?

    二、PLL的设置过程

       1)上电几毫秒后,晶振(SOC)输出稳定,FCLK 等于晶振频率,nRESET信号在电压稳定后恢复高电平,CPU开始执行指令。

      2)在nRESET信号的上升沿,引脚OM[2:3]的电平被内部电路捕获后,就可以操作PLL。在程序开头启动MPLL,设置MPLL相关寄存器后,需要等待一段时间(Lock Time),MPLL输出才稳定。在Lock Time内,FCLK停振,CPU停止工作。Lock Time由寄存器LOCKTIME设定。

      3)Lock Time之后,MPLL输出正常,CPU工作在新的FCLK下。

    三、设置寄存器,调整FCLK: HCLK : PCLK ,使CPU工作于400MHz的频率下

       调整FCLK: HCLK : PCLK = 400MHz : 100MHz : 50MHz

        —— MPLLCON --FCLK  = 400MHz

        ——    CLKDIVN  -- HCLK = FCLK / 4            PCLK = FCLK / 8

      (LOCKTIME寄存器使用默认值)

      1)时钟分频控制寄存器 --- CLKDIVN

      

       不涉及UCLK,[3]取默认值。HCLK 取FCLK/4,[2:1] = 10,且CAMDIVN[9]默认为0。

      PCLK = HCLK / 2 = FCLK / 8,故[0] =1

      故:CLKDIVN = 0x5;

      2)设置MPLLCON,主分频控制寄存器

      先设置MPLLCON,使FCLK=400MHz,

      直接查看芯片手册上的PLL值选择表

      

       12MHz的晶振,输出频率为400MHz时的参数:MDIV=92(0x5c),PDIV =1, SDIV=1

       

       验证一下:

      m = 92+8=100 , p = 1+2=3 , s = 1 

      MPLL = (2 * 100 * 12MHz) / (3 * 2^1) = 400MHz

      

       MPLLCON = (92 << 12) | (1 << 4) | (1<<0)

     

      3)设置CPU为异步总线模式

      基本设置已经完成,在芯片手册上还有一些注意事项:

      

       1-- CLKDIVN的值不应该超过HCLK和PCLK的最小值

       2-- 若HDIVN不为0,CPU总线模式应该使用以下指令使其从快速总线模式改为异步总线模式(S3C2440不支持同步总线模式)

        若HDIVN不为0,并且CPU总线模式为快速总线模式,CPU就会运行在HCLK,由此CPU主频会为FCLK下的一半或一半多。

      其中:#R1_nF:OR:R1_iA 为0xC000 0000

    实例:

    在实现LED循环点灯的程序上实验,观察CPU主频从12MHz改为400MHz前后的变化

    12MHz下:

     1 #define     __REG(x)                (*(volatile unsigned int *)(x))
     2 #define     GPFCON                   __REG(0x56000050)  //Port F control                                   
     3 #define     GPFDAT                   __REG(0x56000054)  //Port F data                     
     4 
     5 void delay(volatile int d)
     6 {
     7     while (d--);
     8 }
     9 
    10 int main(void)
    11 {
    12     int val = 0;  /* val: 0b000, 0b111 */
    13     int tmp;
    14 
    15     /* 设置GPFCON让GPF4/5/6配置为输出引脚 */
    16     GPFCON &= ~((3<<8) | (3<<10) | (3<<12));
    17     GPFCON |=  ((1<<8) | (1<<10) | (1<<12));
    18 
    19     /* 循环点亮 */
    20     while (1)
    21     {
    22         tmp = ~val;
    23         tmp &= 7;
    24         GPFDAT &= ~(7<<4);
    25         GPFDAT |= (tmp<<4);
    26         delay(100000);
    27         val++;
    28         if (val == 8)
    29             val =0;
    30         
    31     }
    32 
    33     return 0;
    34 }
    led.c
     1 .text
     2 .global _start
     3 
     4 _start:
     5 
     6     /* 关闭看门狗 */
     7     ldr r0, =0x53000000
     8     ldr r1, =0
     9     str r1, [r0]
    10 
    11     /* 设置内存: sp 栈 */
    12     /* 分辨是nor/nand启动
    13      * 写0到0地址, 再读出来
    14      * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
    15      * 否则就是nor启动
    16      */
    17     mov r1, #0
    18     ldr r0, [r1] /* 读出原来的值备份 */
    19     str r1, [r1] /* 0->[0] */ 
    20     ldr r2, [r1] /* r2=[0] */
    21     cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */
    22     ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
    23     moveq sp, #4096  /* nand启动 */
    24     streq r0, [r1]   /* 恢复原来的值 */
    25     
    26 
    27     bl main
    28 
    29 halt:
    30     b halt
    31     
    start.s
    1 all:
    2     arm-linux-gcc -c -o led.o led.c
    3     arm-linux-gcc -c -o start.o start.S
    4     arm-linux-ld -Ttext 0 start.o led.o -o led.elf
    5     arm-linux-objcopy -O binary -S led.elf led.bin
    6     arm-linux-objdump -D led.elf > led.dis
    7 clean:
    8     rm *.bin *.o *.elf *.dis
    9     
    Makefile

    400MHz下

    修改start.s

     1 .text
     2 .global _start
     3 
     4 _start:
     5 
     6     /* 关闭看门狗 */
     7     ldr r0, =0x53000000
     8     ldr r1, =0
     9     str r1, [r0]
    10 
    11     /* 设置MPLL, FCLK : HCLK : PCLK = 400MHz : 100MHz : 50MHz */
    12     /* LOCKTIME(0x4C000000) = 0xFFFFFFFF */
    13     ldr r0, =0x4C000000
    14     ldr r1, =0xFFFFFFFF
    15     str r1, [r0]
    16 
    17     /* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8  */
    18     ldr r0, =0x4C000014
    19     ldr r1, =0x5
    20     str r1, [r0]
    21 
    22     /* 设置CPU工作于异步模式 */
    23     mrc p15,0,r0,c1,c0,0
    24     orr r0,r0,#0xc0000000   //R1_nF:OR:R1_iA
    25     mcr p15,0,r0,c1,c0,0
    26 
    27     /* 设置MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0) 
    28      *  m = MDIV+8 = 92+8=100
    29      *  p = PDIV+2 = 1+2 = 3
    30      *  s = SDIV = 1
    31      *  FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M
    32      */
    33     ldr r0, =0x4C000004
    34     ldr r1, =(92<<12)|(1<<4)|(1<<0)
    35     str r1, [r0]
    36 
    37     /* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定
    38      * 然后CPU工作于新的频率FCLK
    39      */
    40     
    41     
    42 
    43     /* 设置内存: sp 栈 */
    44     /* 分辨是nor/nand启动
    45      * 写0到0地址, 再读出来
    46      * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
    47      * 否则就是nor启动
    48      */
    49     mov r1, #0
    50     ldr r0, [r1] /* 读出原来的值备份 */
    51     str r1, [r1] /* 0->[0] */ 
    52     ldr r2, [r1] /* r2=[0] */
    53     cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */
    54     ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
    55     moveq sp, #4096  /* nand启动 */
    56     streq r0, [r1]   /* 恢复原来的值 */
    57     
    58 
    59     bl main
    60 
    61 halt:
    62     b halt
    63     
    start.s

    可以观察到在提高CPU时钟频率后,LED闪烁的频率比之前快了很多。

     参考:

    什么是系统时钟?什么是时钟系统?时钟系统有什么作用?

  • 相关阅读:
    课程的正确步调——Leo鉴书74
    poj(1011)——Sticks(经典的dfs+剪枝)
    怎样去除JSP页面提示:Cannot return from outside a function or method.
    SharePoint 2013 中代码创建列表查阅项字段
    王立平--GUI与GUILayout的差别
    zoj How Many Shortest Path
    QVector的内存分配策略
    java中基于TaskEngine类封装实现定时任务
    超越竞争对手的秘密武器-技术重用
    redis-2.6.16源码分析之pub-sub系统
  • 原文地址:https://www.cnblogs.com/y4247464/p/12311229.html
Copyright © 2011-2022 走看看