嵌入式硬件——IMX6ULL时钟配置

一、时钟系统初始化准备

  • 关闭可能影响配置的模块(如Cache、MMU),避免时钟切换时内核不稳定;
  • 明确配置目标(如内核主频528MHz、AHB=132MHz、IPG=66MHz)。

读取并修改SCTLR寄存器(CP15协处理器):

  • 通过MRC指令读取CP15的SCTLR寄存器(系统控制寄存器);
  • 清零V位(bit13,允许异常向量表重定位)、I位(bit12,关闭I Cache)、C位(bit2,关闭D Cache)等,确保配置过程中无干扰。

确认外设时钟使能准备:

  • 后续需通过CCM_CCGR0~CCM_CCGR6寄存器启用外设时钟,初始可先全局使能(如enable_clocks函数,设置所有CCGR寄存器为0xFFFFFFFF)。

二、配置核心PLL(重点为ARM_PLL、PLL2、PLL3)

  • 配置ARM_PLL(PLL1)以设定内核主频;
  • 确认PLL2(528MHz)、PLL3(480MHz)的固定倍频(无需修改,仅需后续配置其PFD)。

操作步骤(以"内核主频528MHz"为例)

切换内核临时时钟源(避免PLL配置时内核停摆):

  • 配置CCM_CCSR寄存器(时钟控制状态寄存器):
    • CCM->CCSR &= ~(1 << 8):设置STEP_SEL位,使step_clk时钟源为24MHz晶振;
    • CCM->CCSR |= (1 << 2):设置PLL1_SW_CLK_SEL位,将内核时钟切换到step_clk(临时24MHz)。

配置ARM_PLL(PLL1)为1056MHz:

  • 操作CCM_ANALOG_PLL_ARM寄存器(PLL1配置寄存器):
    • 清零BYPASS位(bit16),禁用PLL旁路;
    • 设置DIV_SELECT位(bit12~bit0):根据公式Fout = Fin × (DIV_SELECT / 2.0),代入Fout=1056MHzFin=24MHz,计算得DIV_SELECT=88
    • 置位ENABLE位(bit13),使能PLL1输出。

设置内核分频(得到目标主频):

  • 配置CCM_CACRR寄存器(ARM时钟分频寄存器):
    • CCM->CACRR |= (1 << 0):设置ARM_PODF位为2分频(1056MHz / 2 = 528MHz)。

切换回PLL1主时钟:

  • CCM->CCSR &= ~(1 << 2):将PLL1_SW_CLK_SEL位清零,内核时钟切换回pll1_main_clk(528MHz)。

三、配置PLL2与PLL3的PFD(相位分数分频器)

  • 为外设提供多样化的根时钟源(如PLL2_PFD2供AHB根时钟),需按NXP推荐频率配置8路PFD(PLL2 4路+PLL3 4路)。

关键公式与配置步骤

PFD频率计算:

  • PLL2_PFDn:Fout = 528MHz × 18 / PFDn_FRACPFDn_FRAC范围12~35);
  • PLL3_PFDn:Fout = 480MHz × 18 / PFDn_FRACPFDn_FRAC范围12~35)。

按NXP推荐值配置PFD:

PFD模块 推荐频率 计算得PFDn_FRAC 操作寄存器
PLL2_PFD0 352MHz 27(528×18/27=352) CCM_ANALOG->PFD_528
PLL2_PFD1 594MHz 16(528×18/16=594) CCM_ANALOG->PFD_528
PLL2_PFD2 396MHz 24(528×18/24=396) CCM_ANALOG->PFD_528
PLL2_PFD3 297MHz 32(528×18/32=297) CCM_ANALOG->PFD_528
PLL3_PFD0 720MHz 12(480×18/12=720) CCM_ANALOG->PFD_480
PLL3_PFD1 540MHz 16(480×18/16=540) CCM_ANALOG->PFD_480
PLL3_PFD2 508.2MHz 17(480×18/17≈508) CCM_ANALOG->PFD_480
PLL3_PFD3 454.7MHz 19(480×18/19≈455) CCM_ANALOG->PFD_480

寄存器操作细节:

  • 先清零PFDn_FRAC位(如CCM_ANALOG->PFD_528 &= ~(0x3F << 0)),避免残留值;
  • 清零PFDn_CLKGATE位(如CCM_ANALOG->PFD_528 &= ~(1 << 7)),使能PFD输出。

四、配置AHB/IPG/PERCLK根时钟

  • 为外设提供标准时钟(AHB=132MHz、IPG=66MHz、PERCLK=66MHz),需从PFD选择输入时钟并分频。

配置步骤(以"PLL2_PFD2=396MHz为输入"为例)

配置AHB_CLK_ROOT(132MHz):

  • 选择输入时钟:配置CCM_CBCMR寄存器的PRE_PERIPH_CLK_SEL位(bit19~18),选择PLL2_PFD2为输入;
  • 分频设置:配置CCM_CBCDR寄存器的AHB_PODF位(bit12~10),设置为3分频(396MHz / 3 = 132MHz)。

配置IPG_CLK_ROOT(66MHz):

  • 输入时钟为AHB_CLK_ROOT,配置CCM_CBCDRIPG_PODF位(bit9~8),设置为2分频(132MHz / 2 = 66MHz)。

配置PERCLK_CLK_ROOT(66MHz):

  • 输入时钟为IPG_CLK_ROOT,配置CCM_CSCMR1PERCLK_PODF位(bit6~0),设置为1分频(66MHz / 1 = 66MHz)。

五、使能外设时钟

  • 为具体外设(如GPIO、UART、PWM)启用时钟,避免未使用外设耗电。

操作方式

全局使能(调试阶段便捷使用):

  • 通过enable_clocks函数,设置CCM_CCGR0~CCM_CCGR60xFFFFFFFF,启用所有外设时钟。

按需使能(量产阶段节能):

  • 每个CCM_CCGRx寄存器的每2位控制一个外设时钟,例如:
    • CCM_CCGR0bit31~30控制GPIO2时钟,设置为11(除停止模式外均使能);
    • 公式:CCM->CCGRx |= (0x03 << n)n为外设对应的位偏移)。

六、时钟配置验证

  • 确认时钟配置是否生效(如内核主频、根时钟频率)。

验证方法

软件验证:

  • 读取CCM_CACRRARM_PODF位,确认分频是否正确;
  • 读取CCM_ANALOG_PLL_ARMDIV_SELECT位,确认PLL1倍频是否正确;
  • 通过延时函数间接验证。

硬件验证:

  • 若开发板有示波器接口,可测量外设时钟引脚(如UART的PCLK),确认频率是否匹配配置值。

关键代码参考(基于clock.c

c 复制代码
// 1. 全局使能外设时钟
void enable_clocks(void) {
    CCM->CCGR0 = 0xFFFFFFFF;
    CCM->CCGR1 = 0xFFFFFFFF;
    CCM->CCGR2 = 0xFFFFFFFF;
    CCM->CCGR3 = 0xFFFFFFFF;
    CCM->CCGR4 = 0xFFFFFFFF;
    CCM->CCGR5 = 0xFFFFFFFF;
    CCM->CCGR6 = 0xFFFFFFFF;
}

// 2. 核心时钟配置(内核528MHz、AHB=132MHz、IPG=66MHz)
void init_clock(void) {
    unsigned int t;
    // 阶段2:切换内核临时时钟源(24MHz)
    CCM->CCSR &= ~(1 << 8);   // STEP_SEL=0,step_clk=24MHz
    CCM->CCSR |= (1 << 2);    // PLL1_SW_CLK_SEL=1,内核时钟=step_clk

    // 阶段2:配置ARM_PLL(PLL1=1056MHz)
    t = CCM_ANALOG->PLL_ARM;
    t &= ~(3 << 14);          // 清除BYPASS_CLK_SRC
    t |= (1 << 13);           // 使能PLL1
    t &= ~(0x7F << 0);        // 清除DIV_SELECT
    t |= (88 << 0);           // DIV_SELECT=88(1056MHz=24×88/2)
    CCM_ANALOG->PLL_ARM = t;
    CCM->CACRR |= (1 << 0);   // ARM_PODF=2分频(528MHz)

    // 阶段2:切换回PLL1主时钟
    CCM->CCSR &= ~(1 << 2);   // PLL1_SW_CLK_SEL=0,内核时钟=pll1_main_clk

    // 阶段3:配置PLL2_PFD(528MHz衍生)
    t = CCM_ANALOG->PFD_528;
    t &= ~((0x3F << 0) | (0x3F << 8) | (0x3F << 16) | (0x3F << 24));
    t &= ~((1 << 7) | (1 << 15) | (1 << 23) | (1 << 31));  // 使能PFD输出
    t |= (27 << 0) | (16 << 8) | (24 << 16) | (32 << 24);  // PFD0~PFD3配置
    CCM_ANALOG->PFD_528 = t;

    // 阶段3:配置PLL3_PFD(480MHz衍生)
    t = CCM_ANALOG->PFD_480;
    t &= ~((0x3F << 0) | (0x3F << 8) | (0x3F << 16) | (0x3F << 24));
    t &= ~((1 << 7) | (1 << 15) | (1 << 23) | (1 << 31));  // 使能PFD输出
    t |= (12 << 0) | (16 << 8) | (17 << 16) | (19 << 24);  // PFD0~PFD3配置
    CCM_ANALOG->PFD_480 = t;

    // 阶段4:配置AHB/IPG/PERCLK根时钟
    t = CCM->CBCMR;
    t &= ~(3 << 18);
    t |= (1 << 18);           // PRE_PERIPH_CLK_SEL=PLL2_PFD2
    CCM->CBCMR = t;

    t = CCM->CBCDR;
    t &= ~((7 << 10) | (3 << 8));
    t |= (2 << 10) | (1 << 8);  // AHB_PODF=3分频(132MHz)、IPG_PODF=2分频(66MHz)
    CCM->CBCDR = t;

    CCM->CSCMR1 &= ~(0X3F << 0);  // PERCLK_PODF=1分频(66MHz)

    // 阶段5:全局使能外设时钟
    enable_clocks();
}
相关推荐
朱嘉鼎7 小时前
状态机的介绍
c语言·单片机
清风6666668 小时前
基于单片机的噪声波形检测与分贝测量仪设计
单片机·嵌入式硬件·毕业设计·课程设计
易享电子8 小时前
基于单片机车窗环境监测控制系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
三佛科技-134163842129 小时前
LED氛围灯方案开发MCU控制芯片
单片机·嵌入式硬件·智能家居·pcb工艺
小莞尔9 小时前
【51单片机】【protues仿真】基于51单片机主从串行通信系统
c语言·单片机·嵌入式硬件·物联网·51单片机
Hello_Embed10 小时前
STM32 环境监测项目笔记(一):DHT11 温湿度传感器原理与驱动实现
c语言·笔记·stm32·单片机·嵌入式软件
三佛科技-1341638421211 小时前
便携式榨汁机方案开发,榨汁机果汁机MCU控制方案设计
单片机·嵌入式硬件·智能家居·pcb工艺
yongui4783412 小时前
基于TMS320F28027实现光伏MPPT控制
单片机·嵌入式硬件
炸膛坦客14 小时前
Cortex-M3 内核 MCU-STM32F1 开发之路:(一)单片机 MCU 的构成,包括 FLASH 和 SRAM 的区别,以及引脚类型
stm32·单片机·嵌入式硬件
A9better14 小时前
嵌入式开发学习日志39——stm32之I2C总线物理层与常用术语
stm32·单片机·嵌入式硬件·学习