引言

在嵌入式系统开发中,微处理器的时钟配置是确保系统性能和稳定性的关键步骤之一。本文将详细介绍如何为I.MX6U处理器配置PLL(Phase-Locked Loop)及时钟频率分配器(PFD),并设置AHB、IPG和PERCLK根时钟,以确保所有外设能够正常工作。

系统概述

I.MX6U是一款基于ARM Cortex-A7架构的多核处理器,其内部集成了多个PLL用于生成不同频率的时钟信号。每个PLL都有若干个PFD来进一步细分这些时钟信号,以满足不同外设的需求。正确配置这些时钟源对于系统的正常运行至关重要。

目标设定

  • PLL2:固定为528MHz。
  • PLL3:固定为480MHz。
  • PLL7:固定为480MHz。
  • PLL4~PLL6:针对特殊外设使用,按需设置。
  • PFD:根据NXP推荐值进行配置。
  • AHB_CLK_ROOT:设置为132MHz。
  • IPG_CLK_ROOTPERCLK_CLK_ROOT:均设置为66MHz。

PLL 和 PFD 设置

PLL2 和 PLL3 的 PFD 配置

我们将首先配置PLL2和PLL3及其各自的4路PFD。具体的频率设置如下表所示:

PFDNXP 推荐频率 (MHz)计算公式FRAC 值
PLL2_PFD0352528 * 18 / PFD0_FRAC27
PLL2_PFD1594528 * 18 / PFD1_FRAC16
PLL2_PFD2400 (实际396)528 * 18 / PFD2_FRAC24
PLL2_PFD3297528 * 18 / PFD3_FRAC32
PLL3_PFD0720480 * 18 / PFD0_FRAC12
PLL3_PFD1540480 * 18 / PFD1_FRAC16
PLL3_PFD2508.2480 * 18 / PFD2_FRAC17
PLL3_PFD3454.7480 * 18 / PFD3_FRAC19
寄存器操作细节
  • 使用寄存器CCM_ANALOG_PFD_528n设置PLL2的PFD:
    • PFDx_FRAC位用于设定分频数。
    • PFDx_STABLE只读位表示是否稳定。
    • PFDx_CLKGATE使能位控制输出(0=使能, 1=关闭)。
  • 使用寄存器CCM_ANALOG_PFD_480n设置PLL3的PFD:
    • 结构与CCM_ANALOG_PFD_528n相同,只是频率计算公式不同。
    • 对应的FRAC值通过PLL3的基础频率480MHz计算得出。

AHB、IPG 和 PERCLK 根时钟设置

寄存器说明
  • CCM_CBCDR:用于设置AHB、IPG等总线时钟分频。
  • CCM_CBCMR:用于选择pre_periph_clk和其他时钟源。
  • CCM_CSCMR1:主要用于外设时钟源的选择。
配置过程
  1. 选择PrePeriph时钟源

    • 设置CCM_CBCMR中的PRE_PERIPH_CLK_SEL位选择PLL2_PFD2作为pre_periph_clk的时钟源。
  2. 选择Periph时钟源

    • 设置CCM_CBCDR中的PERIPH_CLK_SEL位为0,即选择PLL2作为Periph时钟源。
  3. 设置AHB_CLK_ROOT

    • 设置CCM_CBCDR中的AHB_PODF位为3(3分频),得到132MHz(396/3=132MHz)。
    • 注意:修改此位会引起一次与MMDC的握手,所以修改完成后要等待握手完成。
  4. 设置IPG_CLK_ROOT

    • 设置CCM_CBCDR中的IPG_PODF位为2(2分频),得到66MHz(132/2=66MHz)。
    • 同样地,需要等待与MMDC的握手完成。
  5. 设置PERCLK_CLK_ROOT

    • 设置CCM_CSCMR1中的PERCLK_CLK_SEL位为0,选择IPG_CLK_ROOT作为PERCLK_CLK_ROOT的源。
    • 设置PERCLK_PODF位为1(1分频),保持66MHz不变。
关键寄存器字段解释
  • CCM_CBCDR:

    • PERIPH_CLK2_PODF: Peripheral2时钟分频,范围07对应18分频。
    • PERIPH2_CLK_SEL: Peripheral2主时钟选择,0选PLL2,1选periph2_clk2_clk。
    • AHB_PODF: AHB时钟分频,范围07对应18分频。
    • IPG_PODF: IPG时钟分频,范围03对应14分频。
  • CCM_CBCMR:

    • PRE_PERIPH_CLK_SEL: PrePeriph时钟源选择,范围00~11对应不同的PLL或PFD选项。
    • PERIPH_CLK2_SEL: Peripheral_clk2时钟源选择,范围00~10对应不同的PLL或振荡器选项。
  • CCM_CSCMR1:

    • PERCLK_CLK_SEL: Perclk时钟源选择,0选IPG clk,1选OSC clk。
    • PERCLK_PODF: Perclk时钟分频,范围07对应18分频。

注意事项

  • 修改某些分频器或时钟选择器时会触发与MMDC(Memory Management Data Controller)之间的握手协议,必须等待握手完成才能继续操作。
  • 在修改arm_podfahb_podf时需要先关闭相关时钟输出,完成后重新开启,避免出现无时钟输出的问题。
  • 某些配置可能会影响内存控制器的操作,因此在进行任何更改之前,请确保了解潜在的影响,并采取适当的预防措施。

实际应用中的代码片段示例

下面是一段伪代码示例,展示了如何编程实现上述配置:

// 定义PLL和PFD配置函数
void configure_pll_pfd(void) {
    // 设置PLL2和PLL3的PFD
    CCM_ANALOG_PFD_528n = (0 << 31) | // PFD0_CLKGATE
                          (27 << 0);   // PFD0_FRAC for 352MHz
    
    CCM_ANALOG_PFD_480n = (0 << 31) | // PFD0_CLKGATE
                          (12 << 0);  // PFD0_FRAC for 720MHz
    
    // ...其他PFD配置...
}

// 定义AHB、IPG和PERCLK配置函数
void configure_bus_clocks(void) {
    // 设置PrePeriph时钟源为PLL2_PFD2
    CCM_CBCMR |= (1 << PRE_PERIPH_CLK_SEL);
    
    // 设置Periph时钟源为PLL2
    CCM_CBCDR &= ~(1 << PERIPH_CLK_SEL);
    
    // 设置AHB_PODF为3分频
    CCM_CBCDR |= (3 << AHB_PODF);
    
    // 设置IPG_PODF为2分频
    CCM_CBCDR |= (2 << IPG_PODF);
    
    // 等待与MMDC握手完成
    while (CCM_CDHIPR & (1 << AHB_PODF)) {}
    
    // 设置PERCLK_CLK_ROOT为IPG_CLK_ROOT且不分频
    CCM_CSCMR1 &= ~(1 << PERCLK_CLK_SEL);
    CCM_CSCMR1 |= (1 << PERCLK_PODF);
}

结论

通过上述详细的步骤,我们可以成功地将I.MX6U的主频及其他重要时钟源配置到位,确保了系统的稳定性和性能。这一过程涉及到多个关键寄存器的操作,包括但不限于CCM_CBCDRCCM_CBCMRCCM_CSCMR1。理解并掌握这些寄存器的功能对于高效配置I.MX6U至关重要。

参考资料

希望这篇博客能帮助你更好地理解和应用I.MX6U的时钟配置。如果有任何疑问或需要进一步的帮助,请随时联系我。