公告

大中华汽车电子生态圈社区并入开发者社区- 更多资讯点击此

Tip / 登入 to post questions, reply, level up, and achieve exciting badges. Know more

cross mob

TC275调试日志——最小系统搭建:时钟参数配置

TC275调试日志——最小系统搭建:时钟参数配置

凌风2018_版主_
Level 4

大家好,这是这周的时钟系统说明的补充。主要说明时钟初始化的代码,希望这周能结束时钟部分,下周开始启动配置。(其实不准备现在写,隔壁姑娘打电话把我吵醒了。。。很尴尬。)

在配置之前,我们首先要选择晶振频率,并且设定时钟倍频的目标时钟。这些都被事先定义为宏:

1.png

很明显是一簇条件编译的指令,所以我们需要准备一个头文件,定义好晶振时钟和时钟倍频的目标。如下定义是在if_cfg.h头文件里定义的:20MHz-200MHz。

2.png

正如我们上一个帖子所描述的,时钟配置可以在启动阶段的SSW里面配置,也可以在启动后立即进行配置。ILLD当中,时钟是在启动文件的后半段进行配置的,调用了时钟初始化函数:        

IfxScuCcu_init(&IfxScuCcu_defaultClockConfig);

函数的定义为:boolean IfxScuCcu_init(const IfxScuCcu_Config *cfg);

该函数的工作就是配置时钟源、PLL配置、时钟分频三个部分。在进行函数分析之前,我们先讲讲该函数调用的参数:结构体指针类型:cfg。ILLD给出的IfxScuCcu_defaultClockConfig是 该函数的实参,是事先定义好的宏,该数据里面包括所有时钟配置需要的参数。以下是该数据结构体的定义:

3.PNG

(找不到插入代码的选项,只能这么看了。。。)我们看到该结构体定义了5个成员。如果我们以20MHz的晶振为例,目标是倍频到200MHz。因为如上一贴所说,时钟频率不能瞬间变化。我们的想法是先给定一个时钟基准,假如是100MHz,然后一步一步倍频到目标时钟。第一个参数就是指达到目标时钟倍频的次数,illd推荐的从100MHz到200MHz倍频三次,从120MHz、150 MHz到200MHz,当然也可以进行个性化设置。而以下代码就是时钟倍频设置的宏,总共有三次倍频,也就是第一个参数等于3。

4.png

而第二个成员,是指向每次时钟倍频的配置数组的首地址,该数组就是通过上述宏定义的。数组的三个元素就是三次时钟倍频的配置结构体,而对应的配置值为K2,分别是5、4、3。

然后我们看第三个成员:初始化时钟分频因子,其实就是我们刚刚所说的配置一个基准时钟100MHz,当然这个值也可以因人而异。以下就是20MHz倍频到200MHz的基准时钟100MHz宏定义:

5.png

我们得到了P=2;N=60;K2=6;而f_OSC=20MHz,带入正常模式PLL时钟计算公式:

f_PLL=N/(P*K2) f_OSC=100MHz;

第四个成员,终于到了为每个模块分频的配置。我们知道时钟分频是CCU单元负责的,它共有八个CCU控制寄存器。这里就是对着八个寄存器进行配置。

6.png

寄存器的定义有个小窍门(我也是刚学会)。

7.png

通过这个结构体,先定义寄存器相应位域的值value;然后定义寄存器相应位域的位数mask。最后将两个值相与,结果就很严格了,不会相互干扰。以下就是寄存器的宏定义:

8.png

当然这种方法适用于你懒得严格定义每一位的情况,尤其是像我现在的初始化配置,参数给定如果定义的太复杂,那么我们的数据结构就更庞大了。而严格的寄存器定义是采用联合结构体,如下:

9.png

10.png

如上所示,每一个位域的定义都很严格了。这种定义很实用,既可以实现寄存器的整体读写,也可以实现位域和位的操作。(老司机必会)

表一:寄存器CCUCON0宏定义

3130[29:28][27:26][25:24][23:22][21:20]
[19:16[15:12][11:8][7:4]
[3:0]
LCKUPCLKSELADCCLKSELFSIDIV0FSI2DIVSPBDIV
LPDIV
SRIDIVBAUD2DIVBAUD1DIV




2
120112




100MHz
200MHz100MHz
200MHz200MHz100MHz

表二:寄存器CCUCON1配置

3130[29:28][27:24][23:20]
[19:16[15:12][11:8][7:4]
[3:0]
LCKUPINSELASCLINSDIVASCLINFDIVETHDIV
GTMIV
STMIVERAYDIVCANDIV



2142232



100MHz200MHz5MHz
100MHz
100MHz
80/3MHz100MHz

接下来我们以CCUCON0为例来讲解,该寄存器定义了12个参数。以下是宏定义里面给出的值:

BAUD1DIV  = 1*2;

BAUD1DIV  = 1;

SRIDIV    = 1;

SPBDIV    = 1*2;

FSI2DIV   = 1;

FSIDIV    = 1*2;

大家可以翻看上几贴的时钟树,查看每一个分频因子的含义。

f_BAUD1   = f_source/2  =f_pll/2 =100MHz;//I2C总线基础时钟

f_BAUD2   = f_source=200 MHz;// QSPI总线和PSI5的基础时钟

f_SRI     = f_source=200 MHz;// SRI总线的基础时钟

f_SPB     = f_source/2  =f_pll/2 =100MHz;//SPB总线基础时钟

f_FSI2    = f_SRI  =200 MHz;//flash接口2时钟

f_FSI    =  f_SRI/2=100 MHz;//flash接口时钟

最后一个参数是指,在时钟改变的过程中,FLASH要保持等待,是对该状态的配置。主要通过配置FCON寄存器实现,具体的配置等到我们进行到FLASH的时候再分析(不知将会是何年月。。。)

到这里我们就将时钟初始化输入参数分析完了。总结一下,这个输入参数作为一个比较复杂的数组,它包含时钟倍频的参数和时钟分频的参数(而且这些参数随晶振时钟和目标时钟的定义而改变)。

本以为这帖子可以把时钟初始化讲完,但是估计有点困难了,没想到光是输入参数就这么多内容。不过不着急,我们下次帖子在再见吧。

大家可以根据本帖子的内容分析,以得到各个子系统的时钟,在这里我直接给出,ILLD的默认时钟配置表:

PLLERAY_PLLSPBADCCANFSI2FSICPU2CPU1CPU0SRIGTM
200MHz80MHz100MHz关闭100MHz200MHz100MHz200MHz200MHz200MHz200MHz100MHz
STMOSC0BAUD1BAUD2ERAYASCLINFASCLINSBBBREFCLK1/2
100MHz20MHz100MHz200MHz80/3MHz200MHz100MHz100MHz25/3MHz


0 点赞
4726 次查看
12 评论