时钟配置¶
1、简介¶
本文围绕芯片的主频配置、内部晶振和外部晶振的选择,每个外围设备接口的分频如何修改,IIS时钟配置展开说明。
CI14LP系列芯片的时钟管理由SCU(System Control Unit)模块负责,相关接口位于 driver\ci14lp_chip_driver\inc\ci14lp_scu.h,系统时钟全局变量接口位于 system\ci_system.h。
2、主频配置¶
- CI14LP系列芯片的主频通过PLL配置,正常模式(全速)主频为73.728M,降频模式主频为12.288M,低功耗模式主频为12.288M,相关宏定义位于
driver\ci14lp_chip_driver\inc\ci14lp_scu.h:
#define NORMAL_MAIN_FREQUENCY (PLL_73728000) //(不可更改)正常模式(全速)的主频
#define NORMAL_MAIN_FREQUENCY_DOWN (PLL_12288000) //(不可更改)正常模式(降频)的主频
#define LOWPOWER_MAIN_FREQUENCY (PLL_12288000) //(不可更改)低功耗模式的主频
- 或者直接调用接口配置主频
#include "ci_scu.h"
#include "ci_system.h"
/* 设置PLL0频率为73.728M */
scu_pll_set_freq(SCU_PLL_INDEX_PLL0, PLL_73728000);
scu_pll_init(SCU_PLL_INDEX_PLL0, PLL_73728000);
/* 获取PLL频率并更新系统时钟全局变量 */
uint32_t main_freq = scu_get_pll_frequency(SCU_PLL_INDEX_PLL0);
set_ipcore_clk(main_freq);
set_ahb_clk(main_freq);
set_apb_clk(main_freq / 2);
注意
- PLL频率选择枚举
pll_freq_t支持 12.288M、24.576M、49.152M、73.728M。 - 正常模式(全速)主频不可更改,为73.728M。
3、晶振选择¶
-
如果模组外挂了晶振,可以配置选择外部晶振,否则选择内部RC,作为系统工作频率时钟源。CI14LP支持内部RC4M、内部RC32K、外部OSC4M/OSC26M、外部OSC32K等时钟源。
-
通过SCU接口配置SRC时钟源(内部RC或外部OSC):
#include "ci_scu.h"
scu_src_clk_select(SCU_SRC_CLK_OUTSIDE_OSC); //使用外部OSC作为SRC时钟源
scu_src_clk_select(SCU_SRC_CLK_INNER_RC); //使用内部RC作为SRC时钟源
scu_src_clk_select(SCU_SRC_CLK_BY_EFUSE); //系统默认,efuse选择(未烧录efuse选外部osc,烧录了efuse选内部rc)
- 外部晶振时钟来源选择(OSC4M/OSC26M 或 OSC32K):
scu_ext_osc_clk_select(SCU_EXT_OSC4M_OR_OSC26M); //系统外部晶振来源于OSC4M或OSC26M
scu_ext_osc_clk_select(SCU_EXT_OSC32K); //系统外部晶振来源于OSC32K
- 系统工作时钟选择(SRC或PLL):
scu_sys_clk_select(SCU_SYS_CLK_SRC); //系统的工作时钟为SRC频率
scu_sys_clk_select(SCU_SYS_CLK_PLL); //系统的工作时钟为PLL频率
4、外设系统时钟频率配置¶
- 先明确几个概念:
- AHB:Advanced High performance Bus,高级高性能总线,这是一种系统总线。主要用于高性能模块如CPU、DMA、UART等之间的连接
- APB:是Advanced Peripheral Bus的缩写,这是一种外围总线。主要用于低频率的周围外设之间的连接,例如IIC、GPIO、PWM等
-
IPCORE_CLK:系统主频
-
时钟分频关系说明:
- 晶振时钟通常为4.096MHz(PLL_SRC_CLK)
- 晶振时钟经过倍频后得到PLL时钟
- PLL时钟经过一级分频可得到IPCORE_CLK主频
-
PLL时钟经过两级分频可得到PCLK
-
可调用接口得到IPCORE_CLK等时钟的值,再根据分频值去推算每个外围设备接口的默认时钟
#include "ci_system.h"
void device_clk_test()
{
//获取IPCORE_CLK主频
uint32_t ipcore_clk = get_ipcore_clk(); //从接口读取IPCORE_CLK主频
//获取PCLK时钟
uint32_t pclk = get_apb_clk(); //从接口读取PCLK时钟
//获取UART时钟
uint32_t uart_clk = get_ahb_clk() / 2; //AHB时钟和IPCORE_CLK时钟相同
//获取PWM或TIMER时钟
uint32_t pwm_timer_clk = get_src_clk() / 16; //选择时钟源为晶振时,默认分频为16
//获取IWDG的时钟
uint32_t iwdg_clk = get_src_clk() / 16; //默认分频为16,计算得到IWDG的系统时钟
//获取iic、gpio的时钟
uint32_t iic_clk = pclk;
uint32_t gpio_clk = pclk;
}
- 如需修改各外设的分频值,可参考下列方式调用接口(注意:更改分频系数时需按顺序操作):
#include "ci_scu.h"
#include "ci_system.h"
void device_div_test()
{
/* 更改分频系数的详细步骤:
* (1)、关闭外设时钟:scu_set_device_clock_en
* (2)、复位外设Reset:scu_set_device_reset
* (3)、设置外设时钟分频参数div:scu_set_div_parameter
* (4)、复位释放外设ResetRelease:scu_set_device_reset_release
* (5)、打开外设时钟:scu_set_device_clock_en
*/
scu_set_device_clock_en(HAL_UART0_BASE, DISABLE); //关闭UART0时钟
scu_set_device_reset(HAL_UART0_BASE); //复位UART0
scu_set_div_parameter(HAL_UART0_BASE, 2); //设置UART0为2分频
scu_set_device_reset_release(HAL_UART0_BASE); //复位释放UART0
scu_set_device_clock_en(HAL_UART0_BASE, ENABLE); //打开UART0时钟
}
5、IIS时钟配置¶
5.1、IIS时钟分频关系介绍¶
- 先了解几个IIS的专有名词,以下会用此类名词来说明IIS时钟配置。
- IIS具有独立的时钟和数据信号,IIS接口由MCLK、SCK、LRCK、SDI、SDO这些信号线组成。
- MCLK:主时钟,通常为音频采样率(LRCK的频率)的64/128/256/384/768倍。
- SCK:位时钟,一个时钟周期传输一个bit数据,通常为音频采样率(LRCK时钟)的32、64倍。
-
LRCK:帧时钟,用于切换左右声道的数据,IIS格式下LRCK为0表示当前数据帧是左声道数据,为1表示当前数据帧是右声道数据。
-
IIS的时钟分频配置,有单独的一套配置接口,支持多组IIS使用独立的时钟通路。
-
第1级时钟来源选择有4个(
iis_clock_source_t):PLL0、PAD B组MCLK输入、PLL1、PAD A组MCLK输入。 -
第2级IIS时钟分频器选择有3个(
iis_divder_t):SRC0、SRC1、SRC2,3个独立的分频器,可分出不一样的MCLK时钟。 -
第3级MCLK配置器选择有4个(
iis_mclk_t):MCLK0~MCLK3,可独立配置不同的过采样率(iis_mclk_over_sample_t:64/128/256/384/768)和SCK/LRCK比值(iis_sck_lrck_wid_t:32/64)。 -
第4级每个IIS的SCK和LRCK来源选择(
iis0_scklrck_src_t、iis1tx_scklrck_src_t、iis1rx_scklrck_src_t),也能作为PAD输出SCK和LRCK的来源(iis_pad_scklrck_src_t)。
5.2、IIS时钟示例代码¶
- 一步配置接口定义:
//位于#include "ci_scu.h"中
void iis_clk_config(iis_clk_config_t* config);
- 调用一步配置接口,配置IIS0为master模式的时钟通路示例:
#include "ci_scu.h"
#include "ci_system.h"
void init_iis_clk_sample()
{
uint32_t sample_rate = 16000; //音频采样率
uint32_t ipcore_clk = get_ipcore_clk(); //时钟源频率
uint32_t fs = 256;
float div = ((float)ipcore_clk / (float)sample_rate / (float)fs); //根据时钟源频率、音频采样率和过采样率,计算分频值
iis_clk_config_t config = {0};
config.device_select = IISNum0_TX; //配置IIS0的时钟通路
config.model_sel = IIS_MASTER; //配置为master模式
config.div_config.source = IIS_CLOCK_SOURCE_PLL0; //选择时钟源为PLL0
config.div_config.divder = IIS_DIV_REGISTER_SRC0; //选择SRC0分频器
config.div_config.div = (uint16_t)div; //配置分频参数
config.mclk_config.mclk = IIS_MCLK_MCLK0; //选择MCLK0配置器
config.mclk_config.src = IIS_DIV_REGISTER_SRC0; //MCLK0来源于SRC0分频器
config.mclk_config.over_sample.mclk0_oversample = IIS_MCLK_OVER_SAMPLE_256; //配置过采样率为256
config.mclk_config.sck_lrck_ratio = IIS_SCK_LRCK_WID_64; //配置SCK/LRCK比值为64
config.iis_scklrck_src.iis0tx_scklrck_src = IIS0_SCKLRCK_FROM_MCLK0; //选择MCLK0产生的SCK和LRCK
iis_clk_config(&config);
uint32_t lrck = sample_rate; //LRCK的频率
uint32_t sck = sample_rate * 64; //计算得到SCK的频率
uint32_t mclk = sample_rate * fs; //计算得到MCLK的频率
}
- 分多步配置的接口定义:
//位于#include "ci_scu.h"中
void scu_iis_src_config(iis_clock_div_config_t *config); //设置IIS时钟源和分频值
void scu_iis_mclk_config(iis_mclk_config_t *config); //设置IIS MCLK(0、1、2、3)时钟参数
void scu_iis_clk_config(iisnumx_t device, uint8_t clk_source); //设置IIS(0、1)时钟参数
void scu_iis_pad_mclk_output(iis_pad_group_t type, iis_divder_t src); //设置IIS PAD输出MCLK
void scu_iis_pad_mclk_input(iis_pad_group_t type); //设置IIS PAD输入MCLK
void scu_iis_pad_clk_output(iis_pad_group_t type, iis_pad_scklrck_src_t src); //设置IIS PAD输出SCK、LRCK
void scu_iis_pad_clk_input(iis_pad_group_t type); //设置IIS PAD输入SCK、LRCK
- 其实一步配置接口内,也是调用的分步接口。
6、注意事项¶
-
通常配置晶振选项是在配置PLL时钟之前
-
修改外设分频时,需关闭外设时钟,再修改分频值,再打开时钟。
-
修改SCU配置寄存器前,需先调用
scu_unlock_topcrg_cfg()/scu_unlock_subcrg_cfg()解锁,配置完成后调用scu_lock_topcrg_cfg()/scu_lock_subcrg_cfg()锁定。