<RT1176系列15>clock_config代码分析
一、核心功能概览
- 基础时钟初始化:使能并配置外部晶振(OSC_24M)、内部 RC 振荡器(OSC_RC_16M/400M/48M 等),等待时钟稳定
- PLL/PFD 配置:初始化 ARM_PLL、SYS_PLL2、SYS_PLL3、VIDEO_PLL 等锁相环,及对应的 PFD(相位频率检测器),生成多档高频时钟
- 外设时钟分配:通过时钟根(Clock Root)为各外设(UART、I2C、SPI、定时器等)配置时钟源和分频系数
- 特殊模块配置:包括 SEMC(存储器控制器)、GC355(图形加速器)等特殊外设的时钟切换与适配
二、核心配置接口解析
1. 基础时钟初始化接口
基础时钟源是整个时钟系统的起点,代码中通过以下接口初始化:
// 初始化内部48MHz RC振荡器及其2分频(24MHz)
CLOCK_OSC_EnableOsc48M(true);
CLOCK_OSC_EnableOsc48MDiv2(true);// 配置外部24MHz晶振
ANADIG_OSC->OSC_24M_CTRL |= ANADIG_OSC_OSC_24M_CTRL_OSC_EN(1) | ...;
// 等待晶振稳定
while (ANADIG_OSC_OSC_24M_CTRL_OSC_24M_STABLE_MASK !=(ANADIG_OSC->OSC_24M_CTRL & ANADIG_OSC_OSC_24M_CTRL_OSC_24M_STABLE_MASK))
原理:外部晶振(OSC_24M)提供稳定的低频时钟,内部 RC 振荡器(如 OSC_RC_48M)则提供快速启动的时钟源。初始化后需等待稳定信号,避免使用不稳定的时钟。
2. PLL 配置接口
PLL(锁相环)用于将低频时钟倍频为高频时钟,代码中通过结构体定义配置参数,再调用初始化函数:
// ARM_PLL配置参数
const clock_arm_pll_config_t armPllConfig_BOARD_BootClockRUN = {.postDivider = kCLOCK_PllPostDiv2, // 后分频系数(2分频).loopDivider = 132, // 环路分频系数
};
// 初始化ARM_PLL
CLOCK_InitArmPll(&armPllConfig_BOARD_BootClockRUN);
频率计算:PLL输出频率 = 输入频率 × (loopDivider / (2 × postDivider))以 ARM_PLL 为例,输入为 24MHz,计算得:24 × (132 / (2×2)) = 792MHz,与代码注释中的ARM_PLL_CLK.outFreq = 792 MHz一致。
3. PFD 配置接口
PFD(相位频率检测器)是 PLL 的扩展,可生成多个不同频率的时钟,通过CLOCK_InitPfd接口配置:
// 初始化SYS_PLL2的PFD0,分频系数27
CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd0, 27);
频率计算:PFD输出频率 = PLL输出频率 × 18 / 分频系数例如 SYS_PLL2 输出 528MHz,PFD0 分频系数 27 时:528 × 18 / 27 = 352MHz,与代码中SYS_PLL2_PFD0_CLK.outFreq = 352 MHz一致。
4. 外设时钟根配置接口
每个外设通过时钟根(Clock Root) 配置时钟源和分频,核心接口是CLOCK_SetRootClock,其参数为时钟根 ID 和配置结构体:
clock_root_config_t rootCfg = {0};
rootCfg.mux = kCLOCK_UART_ClockRoot_MuxOscRc48MDiv2; // 选择24MHz时钟源
rootCfg.div = 1; // 不分频
CLOCK_SetRootClock(kCLOCK_Root_Uart, &rootCfg); // 应用到UART外设
配置要素:
mux:选择时钟源(如 PLL 输出、PFD 输出、外部晶振等)div:分频系数(1 表示不分频,n 表示 n 分频)
三、典型外设配置
1. 内核时钟配置
MIMXRT1176 包含 M7 和 M4 两个内核,时钟配置如下:
// M7内核:使用ARM_PLL输出(792MHz),不分频
rootCfg.mux = kCLOCK_M7_ClockRoot_MuxArmPllOut;
rootCfg.div = 1;
CLOCK_SetRootClock(kCLOCK_Root_M7, &rootCfg);// M4内核:使用SYS_PLL3_PFD3输出,不分频
rootCfg.mux = kCLOCK_M4_ClockRoot_MuxSysPll3Pfd3;
rootCfg.div = 1;
CLOCK_SetRootClock(kCLOCK_Root_M4, &rootCfg);
2. 通用外设(UART/I2C/SPI)配置
多数低速外设使用 24MHz 时钟(OSC_RC_48M_DIV2),例如:
// UART时钟配置(以LPUART1为例)
rootCfg.mux = kCLOCK_LPUART1_ClockRoot_MuxOscRc48MDiv2; // 24MHz源
rootCfg.div = 1;
CLOCK_SetRootClock(kCLOCK_Root_Lpuart1, &rootCfg);// I2C时钟配置(以LPI2C1为例)
rootCfg.mux = kCLOCK_LPI2C1_ClockRoot_MuxOscRc48MDiv2;
rootCfg.div = 1;
CLOCK_SetRootClock(kCLOCK_Root_Lpi2c1, &rootCfg);
3. 高速外设(SEMC/GC355)配置
部分高速外设需要更高频率的时钟,例如:
// SEMC(存储器控制器):使用SYS_PLL2_PFD1(594MHz),3分频后为198MHz
rootCfg.mux = kCLOCK_SEMC_ClockRoot_MuxSysPll2Pfd1;
rootCfg.div = 3;
CLOCK_SetRootClock(kCLOCK_Root_Semc, &rootCfg);// GC355(图形加速器):使用VIDEO_PLL(984MHz),2分频后为492MHz
rootCfg.mux = kCLOCK_GC355_ClockRoot_MuxVideoPllOut;
rootCfg.div = 2;
CLOCK_SetRootClock(kCLOCK_Root_Gc355, &rootCfg);
四、配置流程
1. 配置流程总结
- 初始化基础时钟:使能外部晶振和内部 RC 振荡器,等待稳定
- 配置 PLL:初始化 ARM_PLL、SYS_PLL2 等,生成高频基准
- 配置 PFD:为 PLL 扩展更多频率选项
- 配置外设时钟根:为每个外设分配时钟源和分频系数
