【裸机开发】指定外设根时钟配置实验(三)—— 寄存器分析篇(PERCLK_CLK_ROOT、IPG_CLK_ROOT)

前面已经完成了 PLL1 和 8 路 PFD 的初始化,至于其他 PLL 路,等实际需要的时候再初始化也不迟。接下来我们就挑选几个具体的外设时钟进行配置。

假设我们要初始化下面两个根时钟PERCLK_CLK_ROOTIPG_CLK_ROOT。(中途可能还涉及到根时钟 AHB_CLK_ROOT

【裸机开发】指定外设根时钟配置实验(三)—— 寄存器分析篇(PERCLK_CLK_ROOT、IPG_CLK_ROOT)_第1张图片

【裸机开发】指定外设根时钟配置实验(三)—— 寄存器分析篇(PERCLK_CLK_ROOT、IPG_CLK_ROOT)_第2张图片


目录

一、路线选择

1、PERCLK_CLK_ROOT 路线分析

2、IPG_CLK_ROOT 路线分析

3、AHB_CLK_ROOT 路线分析

二、寄存器分析

1、AHB_CLK_ROOT 路线寄存器分析

(1) CBCMR 寄存器的 PRE_PERIPH_CLK_SEL 位

(2) CBCDR 寄存器的 PERIPH_CLK_SEL 位

(3) 总结

2、IPG_CLK_ROOT 路线寄存器分析

3、PERCLK_CLK_ROOT 路线寄存器分析


一、路线选择

1、PERCLK_CLK_ROOT 路线分析

PERCLK_CLK_ROOT 的时钟来源有两个,一个是直接来自于晶振 OSC,一个是来自于 IPG_CLK_ROOT。选择哪一个由 CSCMR1 寄存器的 PERCLK_CLK_SEL 位决定,分频数由 PERCLK_PODF 位来决定。(我们实际进行的是“选择2”)

配置步骤如下:

  • 第一步,设置 CSCMR1 寄存器的 PERCLK_CLK_SEL 位,选择时钟源 IPG_CLK_ROOT
  • 第二步,设置 CSCMR1 寄存器的 PERCLK_PODF 位,设置成 1 分频

【裸机开发】指定外设根时钟配置实验(三)—— 寄存器分析篇(PERCLK_CLK_ROOT、IPG_CLK_ROOT)_第3张图片

2、IPG_CLK_ROOT 路线分析

IPG_CLK_ROOT 的时钟源只有一个,来自于上面的 AHB_CLK_ROOT,一环扣一环,所以接下来的关键就是分析 AHB_CLK_ROOT 的时钟来源。

配置步骤如下:

  • 只需要设置 CBCDR 寄存器的 IPG_PODF 位,设置成 2 分频

【裸机开发】指定外设根时钟配置实验(三)—— 寄存器分析篇(PERCLK_CLK_ROOT、IPG_CLK_ROOT)_第4张图片

3、AHB_CLK_ROOT 路线分析

按照箭头顺序,配置步骤如下:

  • 设置 CBCMR 寄存器的 PRE_PERIPH_CLK_SEL 位,选择 PLL2_PFD2 时钟源
  • 设置 CBCDR 寄存器的 PERIPH_CLK_SEL 位,选择下面那条路线

注意:原本要设置 CBCDR 的 AHB_PODF 位,虽然这里 CBCDR 写的是 4 分频,但是内部 boot rom已初始化成了 3 分频,所以这一步就无需做

【裸机开发】指定外设根时钟配置实验(三)—— 寄存器分析篇(PERCLK_CLK_ROOT、IPG_CLK_ROOT)_第5张图片

二、寄存器分析

1、AHB_CLK_ROOT 路线寄存器分析

这一步要做的是:

  • 设置 CBCMR 寄存器的 PRE_PERIPH_CLK_SEL 位,选择 PLL2_PFD2 时钟源
  • 设置 CBCDR 寄存器的 PERIPH_CLK_SEL 位,设为 0

(1) CBCMR 寄存器的 PRE_PERIPH_CLK_SEL 位

我们先找到 CBCMR 寄存器的 PRE_PERIPH_CLK_SEL 位,设为 01。

【裸机开发】指定外设根时钟配置实验(三)—— 寄存器分析篇(PERCLK_CLK_ROOT、IPG_CLK_ROOT)_第6张图片

(2) CBCDR 寄存器的 PERIPH_CLK_SEL 位

然后是 CBCDR 寄存器的 PERIPH_CLK_SEL 位,设为 0。这里需要搭配总线设计图来看(在第18章的functional description)

【裸机开发】指定外设根时钟配置实验(三)—— 寄存器分析篇(PERCLK_CLK_ROOT、IPG_CLK_ROOT)_第7张图片

【裸机开发】指定外设根时钟配置实验(三)—— 寄存器分析篇(PERCLK_CLK_ROOT、IPG_CLK_ROOT)_第8张图片

我们还需要注意到 PERIPH_CLK_SEL 位的第二个提示信息(NOTE),无论哪个选择都会涉及与MMDC的握手,这个需要参考 CCDR CDHIPR 寄存器的 handshake bypass 和 busy字段。

CCDR 的  MMDC_CH0_ MASK

凡是涉及 mmdc_ch0_axi_podf 字段或者 periph_clk_sel 字段的变化,都需要修改下面这个字段,是允许握手还是屏蔽握手。很显然选择允许,MMDC_CH0_ MASK 位 设为 0。

 CDHIPR 的 PERIPH_CLK_ SEL_BUSY

判断 PERIPH_CLK_SEL 是否在处理其他选择器的选择事件。

  • 0:如果处于空闲状态,便可以处理 CBCDR 寄存器的 PERIPH_CLK_SEL 位的选择
  • 1:如果处于忙线状态,说明需要先等待上一个选择器的占用结束

(3) 总结

寄存器: CCM_CBCMR
基地址: 0x20C4018
初始化操作:
    CCM_CBCMR &= ~(3 << 18);    // 19-18 位清零
    CCM_CBCMR |= (1 << 18);     // 19-18 设为01
   
/*
 * 在操作CCM_CBCDR之前需要做两步:
 *     1、允许和MMDC握手               —— CCDR 寄存器
 *     2、检查 PERIPH_CLK_SEL 是否忙线 —— CDHIPR 寄存器
 *
 * 做完上述两步以后才是操作 CCM_CBCDR 寄存器
 */
寄存器: CCM_CCDR
基地址: 0x20C4004
初始化操作:
    CCM_CCDR &= ~(1 << 17);    // 第 17 位置0

寄存器: CCM_CDHIPR
基地址: 0x20C4048
初始化操作:
    while((CCM_CDHIPR >> 5) & 0x01 != 0);    // 为 0 时表示空闲,跳出循环

寄存器: CCM_CBCDR
基地址: 0x20C4014
初始化操作:
    CCM_CBCDR &= ~(1 << 25);            // 第 25 位设为0

2、IPG_CLK_ROOT 路线寄存器分析

这一步比较简单,只需要找到 CBCDR 寄存器的 IPG_PODF 位,设置成 2 分频

【裸机开发】指定外设根时钟配置实验(三)—— 寄存器分析篇(PERCLK_CLK_ROOT、IPG_CLK_ROOT)_第9张图片

寄存器: CCM_CBCDR
基地址: 0x20C4014
初始化操作:
    CCM_CBCDR &= ~(3 << 8);    // 9-8 位清零
    CCM_CBCDR |= (1 << 8);     // 9-8 设为01

3、PERCLK_CLK_ROOT 路线寄存器分析

这一步要做的是:

  • 第一步,设置 CSCMR1 寄存器的 PERCLK_CLK_SEL 位,选择时钟源 IPG_CLK_ROOT
  • 第二步,设置 CSCMR1 寄存器的 PERCLK_PODF 位,设置成 1 分频

【裸机开发】指定外设根时钟配置实验(三)—— 寄存器分析篇(PERCLK_CLK_ROOT、IPG_CLK_ROOT)_第10张图片

寄存器: CCM_CSCMR1
基地址: 0x20C401C
初始化操作:
    CCM_CSCMR1 &= ~(0x7F);    // 6-0 位清零

你可能感兴趣的:(#,裸机开发,嵌入式硬件,驱动开发,linux)