嵌入式学习-uboot-lesson6-时钟初始化

Posted Stoneshen1211

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌入式学习-uboot-lesson6-时钟初始化相关的知识,希望对你有一定的参考价值。


1 6410时钟体系

这里写图片描述
从上图以及原理图可以知道下面的内容:
1.采用12M的晶振
2 有三个分频器 APLL MPLL EPLL
3.产生了四个时钟 ACLK HCLK PCLK SCLK
下面是几个时钟的应用范围:
这里写图片描述
其中ACLK为系统时钟,HCLK和PCLK为各种外设和内部的时钟,SCLK暂且不考虑


2时钟初始化过程

这里写图片描述

从上图可以看出,SYSCLK为系统时钟,起初频率为12MHZ,当设置频率之后,系统频率为有一段时间为0,这一时间为lock time ,如果要设置,可以对其进行操作,但是,一般情况下不需要,保持默认即可.

设置时钟,需要进行一下几个步骤:
1设置lock time
2.设置分频系数
3.设置CPU到异步工作模式
4.设置APLL.MPLL输出频率

  • 1设置lock time

默认为初始值,所以不需要做
这里写图片描述

如上图,6410共有三个locktime 分别为 APLL_LOCK MPLL_LOCK EPLL_LOCK,其寄存器的默认值都为0XFFFF,因此保持不变,不需要改变

  • 2.设置分频系数

主要是设置 ACLK HCLK PCLK SCLK之间的比例关系或者说设置他们之间的频率范围
这里写图片描述
从上图可以简化出频率的产生过程
这里写图片描述
其中红色部分为本课时钟需要的频率,是根据uboot中6410的频率得来的,因此需要根据设置好的频率来设置参数,
这里写图片描述
这里写图片描述

看上面两幅图,可以得知,要想设置ARMCLK HCLKX2 HCLK PCLK的频率,需要设置
DIVarm DIVhclkx2 DIVhclk DIVpclk的值,

根据上图的红色编号,可以确定四个数的值
1.ARMCLK=533/(RATIO+1)=533 因此ARM_RATIO=0
即DIVarm=0
2.HCLKX2=533/(HCLKX2_RATIO+1)=266 因HCLKX2_RATIO=1
即DIVhclkx2=1
3.HCLK=HCLKX2/(HCLK_RATIO+1)=133 因此HCLK_RATIO=1
即DIVhclk=1
4.PCLK=HCLKX2/(PCLK_RATIO+1)=66 因此PCLK_RATIO=3
即DIVpclk=3
即:

#define CLK_DIV0 0x7e00f020
#define DIV_VAL ((0X0<<0)|(0X1<<9)|(0X1<<8)|(0X3<<12))  @
        ldr r0,=CLK_DIV0 @设置分频系数
        ldr r1,=DIV_VAL  @将DIV_VAL的值写入寄存器
        str r1,[r0]
  • 3.设置CPU到异步工作模式

当CPU工作时钟和内存的时钟不一样的时候,需要把CPU 的时钟模式设为异步模式
这里写图片描述

根据上图,需要把第7位设置为0异步工作模式,同时也需要把第6位设置为0,主要原因是使HCLKx2获取到的时钟源来自MPLL而不是APLL,如下图所示。

这里写图片描述
这里写图片描述

        #define OTHERS 0x7e00f900
        ldr r0,=OTHERS @设置异步工作模式 第7位为06位为0(时钟选择器)
        ldr r1,[r0]
        bic r1,r1,#0xc0   @
        str r1,[r0]
  • 4.设置APLL.MPLL输出频率

这里写图片描述
要想设置APLL和MPLL的值为533Mhz,根据上图的计算公式和给出的表,可知需要设置 MDIV=266 PDIV=3 SDIV=1
根据下图,则配置相应的寄存器,同时 第31位 ENABLE位需要设置为1
这里写图片描述

#define MPLL_CON 0X7E00F010
#define APLL_CON 0X7E00F00c
#define PLL_VAL ((1<<31)|(266<<16)|(3<<8)|(1<<0))
        ldr r0,=APLL_CON @设置为533Mhz
        ldr r1,=PLL_VAL
        str r1,[r0]

        ldr r0,=MPLL_CON
        ldr r1,=PLL_VAL
        str r1,[r0]
  • 5选择时钟源

这里写图片描述
根据上图,需要选择使用是使用晶振频率或者MPLL作为后续时钟源,因此需要设置CLK_SRC[1]=1
这里写图片描述
这里写图片描述
根据上面两幅图,将其寄存器配置为1

#define CLK_SRC 0x7e00f01c
        ldr r0, =CLK_SRC @选择时钟源为APLL MPLL还是外部
        mov r1, #0x3      @APLL MPLL
        str r1, [r0]        
        mov pc,lr

总的代码:

@****************************
@name: start.S
@by  : stone
@time: 2016.6.26
@function: 
@     异常向量表
@         设置SVC模式
@         关闭看门狗
@         关闭中断
@         关闭MMU
@         外设基地址初始化
@         点亮LED
@         时钟初始化
@****************************

.text
.global _start  @将_start声明为全局变量
_start:
        b   reset                       
        ldr pc, _undefined_instruction  
        ldr pc, _software_interrupt     
        ldr pc, _prefetch_abort         
        ldr pc, _data_abort             
        ldr pc, _not_used               
        ldr pc, _irq                    
        ldr pc, _fiq

_undefined_instruction: .word undefined_instruction
_software_interrupt:    .word software_interrupt
_prefetch_abort:    .word prefetch_abort
_data_abort:        .word data_abort
_not_used:      .word not_used
_irq:           .word irq
_fiq:           .word fiq                   

undefined_instruction:  @处理未定义指令异常
        nop

software_interrupt:     @软中断
        nop

prefetch_abort:         @预取指令异常
        nop

data_abort:             @数据访问异常
        nop

not_used:               @空位
        nop

irq:                    @中断
        nop

fiq:                    @快速中断
        nop

reset:                          @reset
    bl set_svc              @设置为SVC模式
    bl set_peri_port        @外设基地址初始化
    bl disable_watchdog     @关闭看门狗
    bl disable_interrupt    @关闭中断
    bl disable_mmu          @关闭mmu
    bl init_clock           @时钟初始化
    bl light_led            @点亮LED

set_svc:        
    mrs r0, cpsr        @将值取出cpsr寄存器
    bic r0, r0, #0x1f   @将后5位 即M[4:0]清零 
    orr r0, r0, #0xd3   @0b10011 转化为16进制为0x13 同时为了屏蔽irq和fiq,可以将其设置为0b11010011即0xd3  
    msr cpsr, r0        @将值送回cpsr寄存器
    mov pc, lr              @返回

set_peri_port:
    ldr r0, =0x70000000     @基地址
    orr r0, r0, #0x13       @256MB
    mcr p15,0,r0,c15,c2,4   @写入cp15
    mov pc, lr

#define pwTCON 0x7E004000       @WTCON寄存器
disable_watchdog: 
        ldr r0, =pwTCON         @把地址装载到R0
        mov r1, #0x0            @置0,关闭看门狗
        str r1,[r0]     
        mov pc,lr

disable_interrupt:
        mvn r1,#0x0             @0x0 取反,给r1
        ldr r0,=0x71200014      @VIC0
        str r1,[r0]
        ldr r0,=0x71300014      @VIC1
        str r1,[r0]
        mov pc,lr

disable_mmu:
        mcr p15,0,r0,c7,c7,0    @使ICACHE 和DCACHE 无效
    mrc p15,0,r0,c1,c0,0    @read control register
    bic r0,r0,#0x00000007   @mmu 和 dcache置零
    mcr p15,0,r0,c1,c0,0    @write control register
    mov pc,lr

#define CLK_DIV0 0x7e00f020
#define CLK_SRC  0x7e00f01c
#define OTHERS   0x7e00f900
#define MPLL_CON 0X7E00F010
#define APLL_CON 0X7E00F00c
#define PLL_VAL ((1<<31)|(266<<16)|(3<<8)|(1<<0))
#define DIV_VAL ((0X0<<0)|(0X1<<9)|(0X1<<8)|(0X3<<12))
init_clock:
        ldr r0,=CLK_DIV0 @设置分频系数
        ldr r1,=DIV_VAL
        str r1,[r0]

        ldr r0,=OTHERS   @设置异步工作模式 第7位为06位为0(时钟选择器)
        ldr r1,[r0]
        bic r1,r1,#0xc0
        str r1,[r0]

        ldr r0,=APLL_CON @APLL设置为533Mhz
        ldr r1,=PLL_VAL
        str r1,[r0]

        ldr r0,=MPLL_CON @MPLL设置为533Mhz
        ldr r1,=PLL_VAL
        str r1,[r0]

        ldr r0, =CLK_SRC @选择时钟源为APLL MPLL还是外部
        mov r1, #0x3     @APLL MPLL
        str r1, [r0]        
        mov pc,lr

#define GPMCON 0x7F008820       @控制寄存器
#define GPMDAT 0x7F008824   @数据寄存器  
light_led:
        ldr r0,=GPMCON
        ldr r1,=0x1111  @输出模式
        str r1,[r0]

        ldr r0,=GPMDAT
        ldr r1,=0x00    @低电平点亮
        str r1,[r0] 
        mov pc,lr

菜鸟一枚,如有错误,多多指教。。。

以上是关于嵌入式学习-uboot-lesson6-时钟初始化的主要内容,如果未能解决你的问题,请参考以下文章

嵌入式自己做的考研计时小时钟

嵌入式STM32程序编写基本流程(LED流水灯)

STM32学习之路-SysTick的应用(时间延迟)

ds1302时钟芯片。。。谁给我看下这个程序?液晶可以显示,但是时钟不会走显示的也不是我初始化的时间。

X-002 Exyson4412芯片启动过程分析

嵌入式系统低功耗性能调试注意要点