一、 ARM内核启动代码与cps指令
在ARMv6及以上的指令集中,引入了cps指令,用于更灵活地切换处理器工作模式和中断使能。
1. cps指令基础
-
切换模式 :
CPS #<mode>-
irq模式:10010-> 对应指令cps #0x12 -
system模式:11111-> 对应指令cps #0x1F
-
-
使能/禁用中断 :
CPS <effect> <iflags>- 使能IRQ中断:
cpsie i(清除CPSR中的I位)
- 使能IRQ中断:
2. ARM内核启动代码主要做了哪些工作?
ARM内核上电后的启动代码(通常为汇编文件,如start.S)是系统运行的第一步。结合图示,它主要完成了以下7项工作:
-
设置异常向量表:定义复位、未定义指令、软中断、IRQ等异常的处理入口。
-
异常向量表地址重映射 :将向量表重映射到
0x87800000(IMX6ULL的DDR3链接地址)。 -
为不同工作模式开辟栈:特别是为IRQ模式和System模式分配栈空间(结合之前学的满减栈知识)。
-
使能IRQ中断:允许CPU响应中断。
-
清零BSS段:将未初始化的全局变量区域清零,保证C语言环境干净。
-
打开I-cache:开启指令缓存,提高指令读取速度。
-
引导内核跳转到C语言
main函数执行:完成汇编阶段的初始化,正式进入C语言世界。
二、 时钟系统核心模块(PLL/Prescaler/PFD)
时钟是SoC的脉搏。在理解IMX6ULL的时钟配置前,需要先搞清几个核心概念。
1. 晶振(时钟源)
-
无源晶振:需要外部电路驱动,成本低,常见的频率有12MHz、11.0592MHz。
-
有源晶振:内部自带振荡电路,需要供电,输出更稳定,成本高。
2. PLL、Prescaler、PFD作用?
-
PLL (Phase Locked Loop,锁相环) :倍频 。将低频晶振(如24MHz)倍频到CPU所需的高频(如528MHz、1.2GHz)。公式:
24MHz * N。 -
Prescaler (预分频器) :分频 。将高频时钟降频,供低速外设使用。公式:
24MHz / M。 -
PFD (Phase Fractional Divider,相位分数分频器) :倍频/分频 。可以通过配置N/M的值,实现非整数倍的频率调整。公式:
24MHz * (N/M)。当N/M > 1时为倍频,N/M < 1时为降频。
预分频器细节:
2位预分频器:00 (1分频)、01 (2分频)、10 (3分频)、11 (4分频)。
3位预分频器:支持1分频到8分频。
三、 IMX6ULL时钟配置实战
1. IMX6ULL时钟主要做了哪些配置?
根据图示,IMX6ULL的时钟配置主要分为三步:
-
配置ARM内核时钟:设置PLL1,将ARM内核时钟配置为528MHz。
-
配置PLL2和PLL3的PFD:配置PLL2下的4个PFD和PLL3下的4个PFD,为各个外设提供基础的时钟源。
-
配置三个根时钟:配置AHB、PERCLK、IPG三个根时钟,分配到具体的外设总线。
2. 配置的ARM内核时钟频率是多少?
528MHz。这是Cortex-A7内核的工作频率。
3. 配置的AHB、PERCLK、IPG三个根时钟的频率分别是多少?
-
AHB:132MHz
-
PERCLK:66MHz
-
IPG:66MHz
4. IMX6ULL中有几个PLL、几个PFD?
-
PLL :IMX6ULL共有 7个PLL(包括ARM_PLL、PLL2、PLL3、USB1_PLL、USB2_PLL、ENET_PLL、AUDIO_PLL、VIDEO_PLL)。
-
PFD :PLL2下有4个PFD,PLL3下有4个PFD,共8个PFD。这些PFD为不同外设提供了丰富的时钟频率组合。
四、 中断优先级与OCP原则
1. 中断优先级
-
规则:编号越小,优先级越高。
-
GIC V2:支持1020个中断,256个优先级(0 - 255)。
-
IMX6ULL:支持160个中断,32个优先级(0 - 31)。
-
抢占优先级(组优先级)与子优先级:图示展示了优先级的位分配,通过设置抢占优先级和子优先级,可以决定高优先级中断是否能打断正在执行的低优先级中断。
2. OCP原则(开闭原则)
-
对于代码修改是关闭的:已经写好并测试稳定的底层驱动/核心代码,尽量避免直接修改其内部逻辑。
-
对于代码扩展是开放的:应该通过提供接口、回调函数、或添加新模块的方式来扩展功能,而不是修改原有的代码。这在嵌入式框架设计中尤为重要。
今日总结与反思
今天的内容跨度很大,既有底层的汇编启动代码,又有宏观的时钟树架构。
-
启动代码 是裸机开发的"地基",理清那7个步骤后,再看
start.S就不再觉得像天书了。 -
时钟配置是后续所有外设(UART、GPIO、定时器)能正常工作的前提。IMX6ULL的时钟树非常复杂,借助PLL、PFD、Prescaler的公式,能更清晰地计算出每个外设最终的时钟频率。
-
OCP原则提醒我们,在写驱动代码时要考虑可扩展性,不要轻易破坏已有的稳定代码。