GNU ARM汇编--(六)s3c2440的时钟控制

前面几篇利用GNU ARM汇编控制LED以及ARM的中断处理的设计,对ARM汇编以及体系结构有了一定的认识.后面的汇编学习会结合具体的芯片进行,一个为了更灵活熟练的使用汇编,二也是为了通过学习一款具体芯片来提炼出一些有价值的经验.此次选择的芯片是三星的s3c2440,arm920t的核,整个板子是TQ2440的板子,这个板子放了两年多了,零散的玩过一些,但是为了建立更有体系的知识结构,还是值得把它玩过个遍.可能这个芯片很过时了,应该很多人在玩6410,在工作中接触的也是arm11\Cortex-A9或者ppc,但是很多东西并不会过时的.虽然工作中接触的东西比较新,但是作为做应用的公司,很多底层的东西IC设计厂商都帮你做好了,你只需按照它给的东西去做就行.个人是对底层很感兴趣的,而工作中很少有人对底层有完整的认识,所以只能自己利用点个人时间慢慢玩咯.

        不再发感慨了,下面就对s3c2440的时钟做一个说明,然后给出汇编对时钟的控制代码,最后比较一下有时钟控制和没时钟控制下的流水灯的区别.

        s3c2440的时钟控制逻辑可以产生3个时钟信号:用于CPU核(ARM920T)的FCLK,用于AHB总线外设(存储控制器\中断控制器\LCD控制器\DMA\USB的主机端)的HCLK和用于APB总线外设(比如WDT IIS I2C PWM timer MMC ADC UART GPIO RTC SPI)的PCLK.s3c2440有两个锁相环,一个是用于FCLK HCLK PCLK的MPLL,一个专用与USB的UPLL.

        首先看一下下面的表格:

GNU ARM汇编--(六)s3c2440的时钟控制_第1张图片

        时钟源可以来自于外部晶振(XTlpll)或者外部时钟(EXTCLK).datasheet中的图7-1显示了时钟的体系框图,这里就不给出了,截出一小部分与上图做个呼应:

GNU ARM汇编--(六)s3c2440的时钟控制_第2张图片        

这个图就反映了OM[3:2]在XTlpll和EXTCLK之间的选择.

        接下来看看TQ2440的原理图是如何处理的:



GNU ARM汇编--(六)s3c2440的时钟控制_第3张图片

从原理图可以看出:OM[3:2]为00b,意味着使用晶振来产生MPLL CLK和UPLL CLK.我们的XTIpll接的就是12M的晶振,这时候EXTCLK按照规定是要接高的,对应图如下:

GNU ARM汇编--(六)s3c2440的时钟控制_第4张图片

值得注意的是:尽管MPLL在reset后就开始工作了,但是MPLL output只有在软件写有效的设置值到MPLLCON寄存器后才作为系统时钟的.在有效设置之前,外部晶振或者EXTCLK直接用于系统时钟.哪怕是你不想改动MPLLCON寄存器的初始值,你也得将该值写入MPLLCON.

上面的话意味着:如果不进行时钟的设置,那么我的板子就运行在晶振为12M的系统时钟下,这个和s3c2440的400M相去甚远,做流水灯的延时肯定也差数量级的,这个等会就可以看到.

Mpll = (2*m * Fin) / (p * 2^s)
m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2

s3c2440支持FCLK HCLK和PCLK之间的分频比的选择.比例由CLKDIVN寄存器的HDIVN和PDIVN决定.可参见下表:

GNU ARM汇编--(六)s3c2440的时钟控制_第5张图片

注意:CLKDIVN要小心设置,不要超出了HCLK和PCLK的限制.如果HDIVN不为0,要用下面的指令,CPU总线模式从Fast Bus Mode变为异步总线模式:

MMU_SetAsyncBusMode
mrc p15,0,r0,c1,c0,0
orr r0,r0,#R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0


下面开始看看寄存器的设置:

LOCK TIME COUNT REGISTER (LOCKTIME)

GNU ARM汇编--(六)s3c2440的时钟控制_第6张图片

这个时间是要保证PLL输出频率稳定的,时序图如下:

GNU ARM汇编--(六)s3c2440的时钟控制_第7张图片

这个计数器的设置就是时序图中的lock time,而在寄存器说明中规定要大于300us,那么这个时候根据12M的晶振频率,计算如下:

(1/12M)*N>300us  所以N>3600  所以可以用寄存器的默认值0xffff.

PLL CONTROL REGISTER (MPLLCON & UPLLCON)

GNU ARM汇编--(六)s3c2440的时钟控制_第8张图片

MPLL Control Register
Mpll = (2 * m * Fin) / (p * 2S)
m = (MDIV + 8), p = (PDIV + 2), s = SDIV


UPLL Control Register
Upll = (m * Fin) / (p * 2S)
m = (MDIV + 8), p = (PDIV + 2), s = SDIV


PLL Value Selection Guide (MPLLCON)
1. FOUT = 2 * m * Fin / (p*2^S), FVCO = 2 * m * Fin / p where: m=MDIV+8, p=PDIV+2, s=SDIV
2. 600MHz <= FVCO <= 1.2GHz
3. 200MHz <= FCLKOUT <= 600MHz
4. Don't set the P or M value as zero, that is, setting the P=000000, M=00000000 can cause malfunction of
the PLL.
5. The proper range of P and M: 1 <= P <= 62, 1 <= M <= 248

注意:在设置MPLL和UPLL值的时候,要先设置UPLL,再设置MPLL.大约需要内部的7个NOP的延时操作.

在datasheet中给出了一个PLL设置的参考表格.

设置MPLL的MDIV = 92 PDIV = 1 SDIV = 1

Fout = 2*(92 + 8)*12M/(1+2)/2^1 = 400M

设置UPLL的MDIV = 56 PDIV = 2 SDIV = 2

Fout = (56+8)*12M/(2+2)/2^2 = 48M

CLOCK CONTROL REGISTER (CLKCON)

这个寄存器控制各个外设的时钟时能,是与电源管理相关的.


CLOCK SLOW CONTROL (CLKSLOW) REGISTER

这个寄存器也是与电源管理相关的,可以使用默认的初始值.


CLOCK DIVIDER CONTROL (CLKDIVN) REGISTER

GNU ARM汇编--(六)s3c2440的时钟控制_第9张图片

这个寄存器设置的是FCLK HCLK PCLK之间的比例:

DIVN_UPLL = 0

UPLL是48M

HDIVN = 01

PDIVN = 1

FCLK : HCLK : PCLK = 1:2:4


datasheet读懂了,写出汇编就很容易了,添加了时钟设置的流水灯如下:

[cpp] view plain copy print ?
  1. .equ    GPBCON, 0x56000010    
  2. .equ    GPBDAT,  0x56000014    
  3.   
  4. .equ GPB5_out,  (1<<(5*2))    
  5. .equ GPB6_out,  (1<<(6*2))    
  6. .equ GPB7_out,  (1<<(7*2))    
  7. .equ GPB8_out,  (1<<(8*2))    
  8.         
  9. .equ GPBVALUE,    (GPB5_out | GPB6_out | GPB7_out | GPB8_out)    
  10.   
  11. .equ    LOCKTIME, 0x4c000000  
  12. .equ    MPLLCON, 0x4c000004  
  13. .equ    UPLLCON, 0x4c000008  
  14. .equ    M_MDIV, 92  
  15. .equ   M_PDIV, 1  
  16. .equ    M_SDIV, 1  
  17. .equ    U_MDIV, 56  
  18. .equ   U_PDIV, 2  
  19. .equ    U_SDIV, 2  
  20.   
  21. .equ    CLKDIVN, 0x4c000014  
  22. .equ    DIVN_UPLL, 0  
  23. .equ    HDIVN,  1  
  24. .equ    PDIVN,  1    @FCLK : HCLK : PCLK = 1:2:4  
  25.   
  26.   
  27. .global _main    
  28. _main:   
  29.   
  30.     ldr r0,=GPBCON  
  31.   
  32.     ldr r1,=0x15400  
  33.     str r1, [r0]  
  34.   
  35.     @bl clock_setup  
  36.   
  37.     ldr r2,=GPBDAT  
  38.   
  39.     ldr r1,=0x1c0  
  40.     str r1,[r2]  
  41.     bl delay  
  42. ledloop:  
  43.   
  44.     ldr r1,=0x1c0  
  45.     str r1,[r2]  
  46.     bl delay  
  47.   
  48.     ldr r1,=0x1a0  
  49.     str r1,[r2]  
  50.     bl delay  
  51.   
  52.     ldr r1,=0x160  
  53.     str r1,[r2]  
  54.     bl delay  
  55.   
  56.     ldr r1,=0x0e0  
  57.     str r1,[r2]  
  58.     bl delay  
  59.   
  60.   
  61.     b ledloop  
  62.   
  63. clock_setup:  
  64.   
  65.     ldr r0,=LOCKTIME  
  66.     ldr r1,=0xffffffff  
  67.     str r1, [r0]  
  68.   
  69.     ldr r0,=CLKDIVN  
  70.     ldr r1,=(DIVN_UPLL<<3) | (HDIVN<<1) | (PDIVN<<0)  
  71.     str r1, [r0]  
  72.   
  73.     ldr r0,=UPLLCON  
  74.     ldr r1,=(U_MDIV<<12) | (U_PDIV<<4) | (U_SDIV<<0)   @Fin=12M  UPLL=48M  
  75.     str r1, [r0]  
  76.     nop  
  77.     nop  
  78.     nop  
  79.     nop  
  80.     nop  
  81.     nop  
  82.     nop  
  83.     ldr r0,=MPLLCON  
  84.     ldr r1,=(M_MDIV<<12) | (M_PDIV<<4) | (M_SDIV<<0)    @Fin=12M  FCLK=400M  
  85.     str r1, [r0]  
  86.   
  87.   
  88.   
  89.     mov pc,lr  
  90.   
  91. delay:  
  92.     @ldr r3,=0xffffffff  
  93.     ldr r3,=0xfffff  
  94.   
  95. delay1:  
  96.     sub r3,r3,#1  
  97.   
  98.     cmp r3,#0x0  
  99.   
  100.     bne delay1  
  101.   
  102.     mov pc,lr  

[cpp] view plain copy print ?
  1. 在注释掉bl clock_setup与不注释的条件对比,流水灯跑的速度明显不一样了.在正确设置时钟后,后面的各个设备模块才可以正确运作.  

就写到这里了~~~

你可能感兴趣的:(GNU ARM汇编--(六)s3c2440的时钟控制)