跟着视频学习了ARM芯片时钟体系,信息量有点大,做个笔记梳理梳理。
有很多外设,一些工作在AHB总线,一些工作在APB总线
CPU工作在FCLK,AHB总线工作在HCLK,APB总线工作在PCLK
根据数据手册,我们可以知道FCLK、HCLK、PCLK的时钟频率,时钟源由12MHz的晶振经过锁相环PLL得到这些时钟频率
OM[3:2]是选择器,选择时钟源,根据数据手册,若为00,则两个时钟源(CPU用、USB用)都选择为晶振
MPLL(main PLL):给CPU时钟用的PLL,使用MPLLCON寄存器控制输出频率(见4)
UPLL(USB PLL):给USB时钟用的PLL,使用UPLLCON控制输出频率(见4)
由图可知,经过MPLL得到一个时钟,作为FCLK提供给CPU,FCLK经过HDIVN得到HCLK,经过PDIVN得到PCLK
HCLK提供给AHB总线,并由AHB总线提供给挂载在AHB总线上的其他各种高速设备作为时钟
PCLK提供给APB总线,并由APB总线提供给挂载在APB总线上的其他各种低速设备作为时钟
先来看下上电之后时钟的设置过程:
1.上电之后等待电源稳定,复位芯片输出高电平给S3C2440的复位引脚(对应nRESET那里的一小段低电平时间)
2.根据OM[3:2]的值(默认为00),FCLK = 晶振(12MHz),一上电FCLK就开始起振,但此时CPU还没开始运行(对应The logic ...)
3.PLL锁存OM[3:2]的值,此时CPU才开始运行(对应PLL can operate ...)
4.设置PLL(对应Lock Time),此时FCLK不起振,CPU停止工作
5.在Lock Time时,PLL工作
6.等待Lock Time结束,PLL输出稳定,FCLK = PLL输出的新时钟频率,CPU开始工作
计算公式以及参数表格
如果HDIV不为0,则必须设置CPU工作位异步模式,否则CPU会选择HCLK为时钟
.text
.global _start
_start:
/* 关闭看门狗 */
ldr r0, =0x53000000
ldr r1, =0;
str r1, [r0]
/* 设置LOCALTIME */
ldr r0, =0x4c000000
ldr r1, =0xFFFFFFFF
str r1, [r0]
/* 设置分频系数HDIVN、PDIVN,使得FCLK:HCLK:PCLK = 400M:100M:50M */
ldr r0, =0x4c000014
ldr r1, =0x5
str r1, [r0]
/* 设置CPU工作于异步模式 */
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000
mcr p15,0,r0,c1,c0,0
/* 设置MPLLCON,使得FCLK=400MHz */
ldr r0, =0x4c000004
ldr r1, =( (92<<12)|(1<<4)|(1) ) // 根据公式得到以下数值
str r1, [r0]
/* 一旦设置PLL,就会锁定localtime,直到PLL输出稳定,CPU才会开始工作 */
/* 设置内存: sp 栈 */
/* 分辨是nor/nand启动
* 方法:写0至0地址,再读出
* 如果为0,则为nand启动(nand0地址对应片内RAM,可随意更改)
* 否则为nor启动(nor相当于硬盘,要更改需要先发数据格式)
*/
mov r1, #0
ldr r0, [r1] /* 读出原来的值备份 */
str r1, [r1] /* 将0写入0地址 */
ldr r2, [r1]
cmp r0, r2 /* r1==r2? 相等表示从NAND启动 */
ldr sp, =0x40000000+4096 /* 先假设nor启动 */
moveq sp,#4096 /* 若r1==r2,执行该语句,即从nand启动 */
streq r0, [r1]
/* 调用main */
bl main
halt:
b halt