Mini2440裸机开发之系统时钟配置
首先,我们应该知道一点,Mini2440开发板在没有开启时钟前,整个开发板全靠一个12MHz的外部晶振提供频率来工作运行的,也就是说CPU、内存、UART、ADC等所有需要用到时钟频率的硬件都工作在12MHz下,而S3C2440A可以正常工作在400MHz下,可想而知两者速度相差会有多大了。
如果CPU工作在12MHz频率下,开发板的使用效率非常低,所有依赖系统时钟工作的硬件,其工作效率也很低,比如,我们电脑里面经常提到的超频,超频就是让CPU工作在更高的频率下,让电脑运算速度更快,虽然频率是越高越好,但是由于硬件特性决定了任何一个设备都不可能无止境的超频,电脑超频时要考虑到CPU或主板发热过大,烧坏的危险,同样开发板的主板上的外设和CPU也有一个频率限度。
ARM920T内核的S3C2440的最高正常工作频率如下:
- CPU FCLK:400MHz;
- AHB 总线外设的HCLK:100MHz ;
- APB 总线外设的PCLK:50MHz;
那这一节我们就来介绍如何将FCLK时钟的频率提高到400MHZ。S3C2440有关时钟控制的信息位于芯片手册第七章。
一、S3C2440上的工作时钟频率
1.1 时钟信息
S3C2440A 中的时钟控制逻辑可以产生时钟信号包括以下三种:
- CPU 的FCLK:提供给ARM920T的时钟;
- AHB 总线外设的HCLK :提供给用于ARM920T存储器控制器,中断控制器,LCD 控制器,DMA 和USB 主机模块的AHB总线的时钟;
- APB 总线外设的PCLK:提供给用于外设如WDT,IIS,I2C,PWM 定时器,MMC/SD 接口,ADC,UART,GPIO,RTC 和SPI 的APB 总线的时钟。
S3C2440A 包含两个锁相环(PLL):一个提供给FCLK、HCLK 和PCLK,另一个专用于 USB 模块(48MHz)。时钟控制逻辑可以不使用PLL 来减慢时钟,并且可以由软件连接或断开各外设模块的时钟, 以降低功耗。
为什么需要不同种类的时钟呢?
由于不同的硬件外设工作时需要的额定频率不同,所以需要产生不同种类的时钟频率。也就是说,对于一些需要时钟工作的硬件,如果切断其时钟源,就不会再工作了,从而达到低功耗的目的,这也是便携嵌入式设备的一个特点。
1.2 时钟结构
主时钟源来自一个外部晶振(XTIpll)或外部时钟(EXTCLK)。时钟发生包含了一个连接到外部晶振的振荡器(震荡放大器),还含有S3C2440A 所必须的两个用于产生高频率时钟的PLL(锁相环)。
锁相环是实现倍频功能的,说白了就是将12MHz成倍的增加,达到实际所需频率。虽然锁相环有很多指标,咱们完全可以将其理解为一个时钟变换电路,低频晶振输入即可得到处理器所使用的较高频率的时钟。
S3C2440里有两个PLL:
- MPLL:MPLL用来产生FCLK、HCLK、PCLK的高频工作时钟;
- UPLL:UPLL用来为USB提供工作频率;
1.3 时钟源选择
系统上电后,S3C2440处理器会自动锁存OM3和OM2引脚的电平值,这两个引脚用于选择外部时钟输入方式,如下表所示:
模式 OM[3:2] |
MPLL状态 |
UPLL状态 |
主时钟源 |
USB 时钟源 |
00 |
开启 |
开启 |
晶振 |
晶振 |
01 |
开启 |
开启 |
晶振 |
外部时钟 |
10 |
开启 |
开启 |
外部时钟 |
晶振 |
11 |
开启 |
开启 |
外部时钟 |
外部时钟 |
注意:虽然MPLL 在复位后就开始,MPLL输出并没有作为系统时钟,直到软件写入有效值来设置MPLLCON 寄存器。在设置此值之前,是将外部晶振或外部时钟源提供的时钟直接作为系统时钟。即使用户不想改变MPLLCON 寄存器的默认值,用户也应当写入与之相同的值到MPLLCON 寄存器寄存器中。
你可以从我们的mini2440开发板的电路图看到,开发板上的OM3和OM2均接地,即OM[3:2]=00。所以,时钟源为外部晶振。
开发板外部时钟频率太高容易受到外界环境的干扰,同时为了降低成本,通常开发板的外部晶振时钟频率都很低,Mini2440开发板就用用1个12MHz的晶振来提供时钟源。但是S3C2440处理器内部工作频率较高,这就需要用锁相环(PLL)来实现倍频功能。
1.4 锁相环(PLL)
时钟发生器之中作为一个电路的MPLL,参考输入信号的频率和相位同步出一个输出信号。在这种应用中,其包含了如下图所示的以下基本模块:
- 用于生成与输入直流电压成比例的输出频率的压控振荡器(VCO);
-
用于将 输入频率(Fin)按p分频的分频器P;
-
用于将VCO输出频率按m 分频并输入到相位频率检测器(PFD)中的分频器M;
-
用于将VCO输出频率按s 分频成为MPLL(输出频率来自MPLL 模块)的分频器S、鉴相器、电荷泵以及 环路滤波器。
输出时钟频率MPLL与输入时钟频率Fin 有如下等式:
$$MPLL=\frac{2\times m \times Fin}{p \times 2^s}$$
$$m=M+8,p=P+2$$
所以对于S3C2440、Fin与FCLK之间的关系为:
$$FCLK = MPLL = \frac{2 \times M \times Fin}{p \times 2^s} $$
1.5 时钟控制逻辑
时钟控制逻辑决定使用的时钟源,即使用PLL 时钟或直接使用外部时钟(XTIpll 或EXTCLK)。当配置了PLL为一个新频率值时,时钟控制逻辑先禁止FCLK,直至使用PLL 锁定时间使PLL 稳定输出。时钟控制逻 辑在上电复位时和从掉电模式中唤醒时同样是激活的。
分析上图,系统时钟初始化流程如下(FCLK即MPLL锁相环的输出):
- 系统刚上电几毫秒后,FCLK等于外部晶振(OSC)的时钟频率,即FCLK=Fin;
- 当复位信号nRESET恢复高电平后,锁相环按照寄存器MPLLCON和CLKDIVN设定的倍频比例开始生成所需要的时钟频率FCLK,HCLK,PCLK。从图可以看到,从锁相环开始工作到输出新的稳定的频率值需要一定的时间(Lock Time,也叫锁相环的捕获时间),经过这段时间后,锁相环输出新的频率值,这时FCLK等于锁相环MPLL的输出,而HCLK,PCLK通过CLKDIVN寄存器控制分频比。寄存器LOCKTIME中的值对应着图中的Lock Time,初始化时一般将其设为0xFFFFFFFF,这是S3C2440数据手册上给出的默认值,一般按照这个值初始化LOCKTIME寄存器即可满足要求。
1.6 FCLK、HCLK、PCLK关系
当HDIV=0时,HCLK=FCLK;当HDIV=1时,HCLK=FCLK/2;
当PDIV=0时,PCLK=HCLK;当PDIV=1时,PCLK=HCLK/2;
三者关系通过CLKDIVN寄存器进行设置,S3C2440时钟设置时,还要额外设置CAMDIVN(0X4C000018,照相机时钟分割寄存器),寄存器如下表,HCLK4_HALF,HCLK3_HALF分别与CAMDIVN[9:8]对应,下表列出了各种时钟比例:
注意:如果HDIVN设置为非0,CPU的总线模式要进行改变,默认情况下FCLK = HCLK,CPU工作在fast bus mode快速总线模式下,HDIVN设置为非0后, FCLK与HCLK不再相等,要将CPU改为asynchronous bus mod异步总线模式(S3C2440无同步总线模式),可以通过下面的嵌入汇编代码实现:
mrc p15, 0, r1, c1, c0, 0 /* 读取CP15 C1寄存器 */
orr r1, r1, #0xc0000000 /* 设置CPU总线模式 */
mcr p15, 0, r1, c1, c0, 0 /* 写回CP15 C1寄存器*/
1.7 总结
相信你看完上面的关于初始化的,应该大概懂了初始化流程,但可能还是不知道怎么产生对应的MCLK、PCLK和FCLK。
那么,如何控制锁相环PLL的输出频率呢?S3C2440处理器内部有两个寄存器:
- MPLLCON寄存器控制FCLK与Fin的比例关系;
- CLKDIVN寄存器控制FCLK和HCLK、PCLK的比例关系;
我们使用下图表示简要的表达这四者的关系:
二、 时钟相关寄存器
2.1 锁定时间计数寄存器(LOCKTIME)
寄存器信息:
寄存器 | 地址 | R/W | 描述 | 复位值 |
LOCKTIME | 0x4C000000 | R/W | PLL锁定时间计数寄存器 | 0xFFFFFFFF |
寄存器位信息:
BWSCON | 位 | 描述 | 初始状态 |
U_LYIME | [31:16] | UCLK 的UPLL 锁定时间计数值(U_LTIME 300μs) | 0xFFFF |
M_LTIME | [15:0] | FCLK,HCLK 和PCLK 的MPLL 锁定时间计数值(M_LTIME 300μs) | 0xFFFF |
2.2 PLL控制寄存器(MPLLCON和UPLLCON)
寄存器信息:
寄存器 | 地址 | R/W | 描述 | 复位值 |
MPLLCON | 0x4C000004 | R/W | MPLL配置寄存器 | 0x00096030 |
UPLLCON | 0x4C000008 | R/W | UPLL配置寄存器 | 0x0004D030 |
寄存器位信息:
PLLCON | 位 | 描述 | 初始状态 |
MDIV | [19:12] | 主分频控制 | 0x96/0x4D |
PDIV | [9:4] | 预分频控制 | 0x03/0x03 |
SDIV | [1:0] | 后分频控制 | 0x00/0x00 |
注意: 在系统初始化阶段,当你设置MPLL 和UPLL 的值时,你必须首先设置UPLL 值再设置MPLL 值。(大约需要7 个NOP的间隔).
MPLL控制寄存器:
$$MPLL=\frac{2 \times m \times Fin}{p \times 2^s}$$
$$m=MDIV+8,p= PDIV +2, s = SDIV$$
UPLL控制寄存器:
$$UPLL=\frac{ m \times Fin}{p \times 2^s}$$
$$m=MDIV+8,p= PDIV +2, s = SDIV$$
2.3 时钟控制寄存器
寄存器信息:
寄存器 | 地址 | R/W | 描述 | 复位值 |
CLKCON | 0x4C00000C | R/W | 时钟控制寄存器 | 0xFFFFF0 |
寄存器位信息:
CLKCON | 位 | 描述 | 初始状态 |
AC97 | [20] |
控制进入AC97模块的PCLK 0 :禁止 1:使能 |
1 |
Camera | [19] |
控制进入摄像头模块的HCLK 0 :禁止 1:使能 |
1 |
SPI | [8] |
控制进入SPI模块的PCLK 0 :禁止 1:使能 |
1 |
IIS | [17] |
控制进入IIS模块的PCLK 0 :禁止 1:使能 |
1 |
IIC | [16] |
控制进入IIC模块的PCLK 0 :禁止 1:使能 |
1 |
ADC | [15] |
控制进入ADC模块的PCLK 0 :禁止 1:使能 |
1 |
RTC | [14] |
控制进入RTC模块的PCLK 0 :禁止 1:使能 |
1 |
GPIO | [13] |
控制进入GPIO模块的PCLK 0 :禁止 1:使能 |
1 |
UART2 | [12] |
控制进入UART2模块的PCLK 0 :禁止 1:使能 |
1 |
UART1 | [11] |
控制进入UART1模块的PCLK 0 :禁止 1:使能 |
1 |
UART0 | [10] |
控制进入UART0模块的PCLK 0 :禁止 1:使能 |
1 |
SDI | [9] |
控制进入SDI模块的PCLK 0 :禁止 1:使能 |
1 |
PWMTIMER | [8] |
控制进入PWM模块的PCLK 0 :禁止 1:使能 |
1 |
USB device | [7] |
控制进入USB设备模块的PCLK 0 :禁止 1:使能 |
1 |
USB host | [6] |
控制进入USB主机模块模块的HCLK 0 :禁止 1:使能 |
1 |
LCDC | [5] |
控制进入LCDC模块的HCLK 0 :禁止 1:使能 |
1 |
NAND Flash Controller | [4] |
控制进入NAND FLash控制器模块的HCLK 0 :禁止 1:使能 |
1 |
SLEEP | [3] |
控制S3C2440的睡眠模式 0 :禁止 1:转换到空闲模式 |
0 |
IDLE BIT | [2] |
进入空闲模式,此位不会自动清理 0 :禁止 1:转换到睡眠模式 |
0 |
保留 | [1:0] | 保留 | 0 |
通过控制CLKCON寄存器对应的位就可以实现某个硬件模块时钟的开启和关闭,从而达到降低功耗的目的。
2.4 时钟分频控制寄存器(CLKDIVN)
寄存器信息:
寄存器 | 地址 | R/W | 描述 | 复位值 |
CLKDIVN | 0x4C000014 | R/W | 时钟分频控制寄存器 | 0x00000004 |
寄存器位信息:
CLKDIVN | 位 | 描述 | 初始状态 |
DIVN_UPLL | [3] |
UCLK 选择寄存器(UCLK 必须为48MHz 给USB) 0:UCLK = UPLL时钟 1:UCLK = UPLL 时钟 / 2 当UPLL 时钟被设置为48MHz 时,设置为0 当UPLL 时钟被设置为96MHz 时,设置为1 |
0 |
HDIVN | [2:1] |
00:HCLK = FCLK/1 01:HCLK = FCLK/2 10:HCLK = FCLK/4 当CAMDIVN[9] = 0时 HCLK = FCLK/8 当CAMDIVN[9] = 1时 11:HCLK = FCLK/3 当CAMDIVN[8] = 0 时 HCLK = FCLK/6 当CAMDIVN[8] = 1 时 |
00 |
PDIVN | [0] |
0:PCLK 是和HCLK/1 相同的时钟 1:PCLK 是和HCLK/2 相同的时钟 |
0 |
2.5 摄像头时钟分频控制寄存器(CAMDIVN)
寄存器信息:
寄存器名 |
地址 |
是否读写 |
描述 |
复位值 |
CAMDIVN |
0x4C000018 |
R/W |
摄像头时钟分频控制寄存器 |
0x00000000 |
寄存器位信息:
CAMDIVN | 位 | 描述 | 初始状态 |
DVS_EN | [12] |
0:关闭DVS 1:开启DVS |
0 |
保留 | [11] | 保留 | 0 |
保留 | [10] | 保留 | 0 |
HCLK4_HALF | [9] |
HDIVN分频因子选择位(当CLKIVN[2:1]位为10b时有效) 0: HCLK=FCLK/4 1: HCLK=FCLK/8 |
0 |
HCLK3_HALF | [8] |
HDIVN分频因子选择位(当CLKIVN[2:1]位为11b时有效) 0: HCLK=FCLK/3 1: HCLK=FCLK/6 |
0 |
CAMCLK_SEL | [4] |
0:使用UPLL 输出作为CAMCLK(CAMCLK=UPLL 输出) 1:CAMCLK_DIV 的值分频得到CAMCLK |
0 |
CAMCLK_DIV | [3:0] | CAMCLK 分频因子设置寄存器(0 至15)
摄像头时钟 = UPLL / [(CAMCLK_DIV +1)x2] |
0 |
2.6 FCLK值选择
现在咱们应该有个大概的意识了,设置MPLLCON中相应的位,就可以通过Fin获得FCLK了。但是这家伙还得一步步的算MDIV、PDIV、SDIV的值,太麻烦了,对于我这懒人,这样不好不好。那么怎么得到这三者的值呢?
虽然PLL给用户提供了灵活变换系统时钟的功能,但是,并不是任意的时钟下处理器都能正常工作,基于此种原因,为了照顾我等懒人,官方给出了系统时钟配置参考,如图所示:
下面以第5行为例讲解,假设外部晶振输入为$12MHz$,$MDIV=92$,$PDIV=1$,$SDIV=1$,则:
$$m=92+8=100,p=1+2=3,s=1$$
$$FCLK=\frac{2*100*12MHz}{3*2^1}=400MHz$$
小技巧:由上面的分析可以看到,MDIV、PDIV和SDIV都是占用了MPLLCON的连续某几位,如PDIV是MPLLCON寄存器的第4~9位。因此,初始化时可以使用移位指令来实现对MPLLCON的初始化。
亲爱的读者和支持者们,自动博客加入了打赏功能,陆陆续续收到了各位老铁的打赏。在此,我想由衷地感谢每一位对我们博客的支持和打赏。你们的慷慨与支持,是我们前行的动力与源泉。
日期 | 姓名 | 金额 |
---|---|---|
2023-09-06 | *源 | 19 |
2023-09-11 | *朝科 | 88 |
2023-09-21 | *号 | 5 |
2023-09-16 | *真 | 60 |
2023-10-26 | *通 | 9.9 |
2023-11-04 | *慎 | 0.66 |
2023-11-24 | *恩 | 0.01 |
2023-12-30 | I*B | 1 |
2024-01-28 | *兴 | 20 |
2024-02-01 | QYing | 20 |
2024-02-11 | *督 | 6 |
2024-02-18 | 一*x | 1 |
2024-02-20 | c*l | 18.88 |
2024-01-01 | *I | 5 |
2024-04-08 | *程 | 150 |
2024-04-18 | *超 | 20 |
2024-04-26 | .*V | 30 |
2024-05-08 | D*W | 5 |
2024-05-29 | *辉 | 20 |
2024-05-30 | *雄 | 10 |
2024-06-08 | *: | 10 |
2024-06-23 | 小狮子 | 666 |
2024-06-28 | *s | 6.66 |
2024-06-29 | *炼 | 1 |
2024-06-30 | *! | 1 |
2024-07-08 | *方 | 20 |
2024-07-18 | A*1 | 6.66 |
2024-07-31 | *北 | 12 |
2024-08-13 | *基 | 1 |
2024-08-23 | n*s | 2 |
2024-09-02 | *源 | 50 |
2024-09-04 | *J | 2 |
2024-09-06 | *强 | 8.8 |
2024-09-09 | *波 | 1 |
2024-09-10 | *口 | 1 |
2024-09-10 | *波 | 1 |
2024-09-12 | *波 | 10 |
2024-09-18 | *明 | 1.68 |
2024-09-26 | B*h | 10 |
2024-09-30 | 岁 | 10 |
2024-10-02 | M*i | 1 |
2024-10-14 | *朋 | 10 |
2024-10-22 | *海 | 10 |
2024-10-23 | *南 | 10 |
2024-10-26 | *节 | 6.66 |
2024-10-27 | *o | 5 |
2024-10-28 | W*F | 6.66 |
2024-10-29 | R*n | 6.66 |
2024-11-02 | *球 | 6 |
2024-11-021 | *鑫 | 6.66 |
2024-11-25 | *沙 | 5 |
2024-11-29 | C*n | 2.88 |

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了