一、ARM内核启动代码
启动代码(start.S)是上电后最先执行的汇编代码,在引导内核进入C语言世界之前,需要完成以下7项工作:
| 序号 | 工作内容 | 说明 |
|---|---|---|
| 1 | 设置异常向量表 | 在向量表中填入各异常/中断的跳转入口 |
| 2 | 异常向量表地址重映射 | 通过cp15(SCTLR的V位 + VBAR寄存器)把向量表重映射到 0x87800000(DDR3中代码的位置) |
| 3 | 为不同工作模式开辟栈 | 至少为 IRQ模式 和 system模式 设置SP(各模式有独立栈) |
| 4 | 使能IRQ中断 | 修改CPSR的I位(如 cpsie i) |
| 5 | 清零bss段 | bss段(初始化为0/未初始化的全局变量)不占镜像空间,必须启动时手动清零 |
| 6 | 打开I-Cache | 提高取指效率(通过cp15的SCTLR bit12) |
| 7 | 引导内核跳转到C语言main函数执行 | b main(或 bl),从此进入C世界 |
补充:CPS指令(讲义新增指令)
cps :Change Processor State,直接切换工作模式/开关中断(armv6指令集后才支持):
cps #<mode> // 工作模式切换
cps #0x12 // 切到 irq 模式(10010)
cps #0x1F // 切到 system 模式(11111)
cps <effect> <iflags> // 使能/失能 irq 或 fiq 中断
cpsie i // 使能 IRQ(清除 I 位)
cpsid i // 失能 IRQ(置位 I 位)
之前切换模式要"mrs读CPSR → bic/orr修改 → msr写回"三步,
cps一条指令搞定,day06启动代码常用它来给各模式开栈。
补充:中断优先级(day06讲义回顾)
-
优先级规则:编号越小优先级越高
-
GIC V2 :1020个中断,256个优先级(0~255)
-
IMX6ULL :160个中断,32个优先级(0~31)
-
优先级分为:抢占优先级(组优先级) 和 子优先级------抢占优先级高的可以打断正在执行的低优先级中断;抢占优先级相同时,子优先级决定谁先响应,但不能互相抢占
补充:OCP开闭原则
讲义顺带提到软件设计原则:
开闭原则(OCP) :对于代码修改是关闭 的,对于代码扩展是开放的。 即写驱动/模块时不改旧代码,通过新增代码扩展功能------中断处理代码分层设计时遵循该原则。
二、PLL、Prescaler、PFD的作用
1. 先明确时钟从哪来
IMX6ULL外部接的晶振是低频的(讲义提到常见 12MHz 、11.0592MHz 等;开发板常用24MHz有源晶振,讲义标注了无源晶振/有源晶振的区别------无源晶振需芯片内部振荡电路配合,有源晶振自己起振直接输出时钟信号)。而CPU要跑到数百MHz,怎么升上去?靠下面三个器件:
2. 三大器件
| 器件 | 全称 | 作用 | 输入输出关系 |
|---|---|---|---|
| PLL | Phase Locked Loop,锁相环 | 倍频 | 24MHz × N → 高频时钟(如528MHz) |
| Prescaler | 预分频器 | 分频 | 24MHz ÷ M → 低频时钟 |
| PFD | Phase Fractional Divider,相位分数分频器 | 倍频/分频都可 | 24MHz × (N/M) |
-
锁相环(PLL) :输入24MHz,输出 24MHz × N(N为倍频系数)
-
预分频器(Prescaler) :输入24MHz,输出 24MHz ÷ M(M为分频系数)
-
PFD :输出 24MHz × (N/M)
-
N/M > 1 → 倍频(升频)
-
N/M < 1 → 降频(分频)
-
3. 预分频器的分频档位
-
2位预分频器:4档
编码 分频 00 1分频(不分) 01 2分频 10 3分频 11 4分频 -
3位预分频器 :8档,1分频 ~ 8分频
一句话:PLL只升不降,Prescaler只降不升,PFD可升可降(N/M灵活配比)------三者配合,把一个低频晶振"加工"出系统需要的各种频率。
三、IMX6ULL时钟配置
按讲义,IMX6ULL时钟配置三步:
-
配置ARM时钟为 528MHz
-
配置PLL2下的4个PFD 和 PLL3下的4个PFD
-
配置三个根时钟 :132MHz、66MHz、66MHz
具体对应关系:
| 配置项 | 频率 | 用途 |
|---|---|---|
| ARM内核时钟 | 528MHz | CPU主频 |
| AHB根时钟 | 132MHz | 高速总线(DDR、LCD等) |
| IPG根时钟 | 66MHz | 片内外设总线 |
| PERCLK根时钟 | 66MHz | 外设时钟(UART、GPT定时器等) |
四、ARM内核时钟频率
528MHz。
来源链路:24MHz晶振 → 经PLL(锁相环倍频)→ ARM_CLK = 528MHz。
五、AHB、PERCLK、IPG三个根时钟的频率
| 根时钟 | 频率 |
|---|---|
| AHB | 132MHz |
| PERCLK | 66MHz |
| IPG | 66MHz |
ARM 528 = AHB 132 × 4 = IPG 66 × 8;IPG = AHB ÷ 2,PERCLK默认与IPG同频66MHz。
六、IMX6ULL中有PLL、PFD
-
PLL:7个(PLL1~PLL7)
-
PFD:8个 (PLL2下4个 + PLL3下4个)
| PLL | 主要用途 |
|---|---|
| PLL1 | ARM内核时钟(528MHz) |
| PLL2(System PLL) | 系统总线时钟,带4个PFD(PFD0~PFD3,如352MHz、594MHz等) |
| PLL3(USB1 PLL) | USB/音频等,带4个PFD(如480MHz、200MHz、396MHz等) |
| PLL4 | 音频PLL |
| PLL5 | 视频PLL |
| PLL6 | ENET PLL |
| PLL7 | USB2 PLL |