外设需要工作也需要时钟驱动,通过多路选择器以及对应的寄存器配置初始化最适合的外设频率可以让外设更高频的工作。
从上面截图以及红框中可以看到,外设时钟根PERCLK_CLK_ROOT
与IPG_CLK_ROOT
为大多数常用的外设提供时钟,初始化这两个时钟根需要先对AHB_CLK_ROOT
进行初始化
AHB_CLK_ROOT
的时钟来源在CBCDR[PERIPH_CLK_SEL]
处有一个多路选择器
从上面这个图可以看出AHB_CLK_ROOT
最大支持的频率是132MHz,如果在CBCDR[PERIPH_CLK_SEL]
这个多路选择器这里选择了上路,那它的时钟来源最大的频率是PLL3_480
,通过CBCDR[PERIPH_CLK2_RODF]
分频后最大只能到120(此时分频器的值是4,如果是3的话160则超过了最大值),因为AHB_CLK_ROOT
限制最大是132。因此CBCDR[PERIPH_CLK_SEL]
这个多路选择器,选择下路, 同时在CBCMR[PRE_PERIPH_CLK_SEL]
时选择PLL2
的PFD2
时钟源,它的时钟频率是396MHz,最终达到AHB_CLK_ROOT
时经过CBCDR[AHB_PODF]
分频器处理刚好得到132MHz的频率。
/// 配置外接设备的时钟频率
/// CBCMR[PRE_PERIPH_CLK_SEL]选择PLL2->PFD2
/// 先将19-18两个bit位清0
/// 再将19-18两个bit位的数据写成1,选择PFD2
CCM->CBCMR &= ~(3 << 18);
CCM->CBCMR |= (1 << 18);
/// CBCDR[PERIPH_CLK_SEL]多路选择器选择下路
CCM->CBCDR &= ~(1 << 25);
/// 读取第5个bit位(PERIPH_CLK_ SEL_BUSY),如果是1指示正忙于握手,如果是0表示握手完成
while ((CCM->CDHIPR >> 5) & 0x1);
/* 修改 AHB_PODF 位的时候需要先禁止 AHB_CLK_ROOT 的输出,但是
* 我没有找到关闭 AHB_CLK_ROOT 输出的的寄存器,所以就没法设置。
* 下面设置 AHB_PODF 的代码仅供学习参考不能直接拿来使用!!
* 内部 boot rom 将 AHB_PODF 设置为了 3 分频,即使我们不设置 AHB_PODF, * AHB_ROOT_CLK 也依旧等于 396/3=132Mhz。
*/
#if 0
/// 将CBCDR[AHB_PODF]的12-10三个bit位清0
CCM->CBCDR &= ~(7 << 10);
/// 将CBCDR[AHB_PODF]的值设置成3,即3分频
CCM->CBCDR | (2 << 10);
/// 等待忙位检测通过
while ((CCM->CDHIPR >> 1) & 0x1);
#endif
IPG_CLK_ROOT
的频率最大值是66MHz,从AHB_CLK_ROOT
过来的频率是132MHz,所以这里只需要将CBCDR[IPG_PODF]
分频器的值设置成除2即可。
/// 将9-8两个bit位的数据清0
CCM->CBCDR &= ~(3 << 8);
/// 设置成2分频
CCM->CBCDR |= (1 << 8);
PERCLK_CLK_ROOT
的频率最大值是66MHz,在CBCDR[IPG_PODF]
分频器的作用下它的频率已经是66MHz了,所以此时只需要将CSCMR1[PERCLK_CLK_SEL]
多路选择器选择到IPG_CLK_ROOT
,将PERCLK_PODF
分频器的值设置成1分频即可。
/// CSCMR1[PERCLK_CLK_SEL]选择ipg clk root
CCM->CSCMR1 &= ~(1 << 6);
/// 将5-0 6个bit位清0,设置成1分频,此时已经是1分频了
CCM->CSCMR1 &= ~(0x3F << 0);
以上都初始化完成后IPG_CLK_ROOT
与PERCLK_CLK_ROOT
两个时钟根的频率就工作在子66MHz,最大的发挥了SOC的性能,这两个时钟根也是大部分外设的时钟源。
修改 AHB_PODF 位的时候需要先禁止 AHB_CLK_ROOT 的输出,但是
全部0条评论
快来发表一下你的评论吧 !