本文介绍如何用KEAZ128评估版(FRDM-KEAZ128Q80)配置为40MHz core freqency/20MHz bus frequency。
1.了解器件时钟特性
参见NXP KEA128 DS(S9KEA128P80M48SF0.pdf ),可以知道这个MCU最高支持48MHz core frequency.
从KEA128 RM(KEA128RM (中文).pdf),可以知道KEA128各个时钟名称及频率等特性。这里需要注意,设置的配置内核时钟频率(40MHz)不能超过最高频率(48MHz)。由于外部时钟较内部时钟稳定、可靠,所以选择外部晶振作为总线时钟源。
不过,为何内核频率最高频率是48MHz?使用外部晶振8MHz最高支持多少频率呢?接着往下看。
3.观察时钟框图,选择一条配置时钟的路线
可以从RM时钟示意图,看到KEA各种类型时钟及连接关系,
假如以IRC=37.5KHZ作为FLL基准时钟,FLL倍频=1280,那么内核时钟=37.5KHZ * 1280 = 48000KHZ = 48MHZ。这解释了48MHZ最大频率是怎么计算得来的。
但是,想要的,不是使用内部时钟IRC,而是外部晶振(8MHz)作为时钟源,这样应该选择下面这条路线配置。
4.计算时钟及所需配置的参数
从上面的路线图,知道要用8M生成40MHz,必须经过FLL倍频(*1280),而8M*1280 = 10240M >> 48M,明显不合理,所以8M不会是直接送到FLL输入,必须先经过系统振荡器模块(OSC)进行分频处理后,才能经过FLL倍频。
设OSC分频系数=n,那么内核时钟 = 8M / n * 1280 / bdiv / div1 , 其中n属于OSC模块,bdiv属于ICS模块,div1属于SIM模块。
不过,OSC是个什么模块?跟ICS是什么关系?
5. 分析内部时钟源模块(ICS)
查看RM ICS章节,发现可以选择如下线路配置ICSOUT(ICSOUTCLK),进而配置内核时钟。这里外部基准时钟输入后,会有一个RDIV决定的分频,再由FLL倍频,再由BDIV分频,得到ICSOUT。
1)先看看RDIV,是如何分频的。
看寄存器描述,可以得知,RDIV的分频,与OSC_CR[RANGE](频率范围)相关。而8M外部晶振作为OSC模块时钟时(8M > 4M),必然选择OSC_CR[RANGE] = 1,也就是说,RDIV所代表的分频系数只能是32,64,...1024.
不妨试试RDIV=0b000,也就是rdiv=32,那么内核时钟 = 8M / 32 * 1280 / bdiv / div1 = 320M/bdiv / div1 ,理论上,可以设置bdiv * div1 = 8,让内核时钟最终为40MHz,但是过程中,会导致传输的时钟为8M/32*1280=320M,这可能会导致器件无法正常各种。
配置时钟的时候,不仅要最终的结果满足小于最大时钟,而且过程中的时钟,也必须符合手册规范。这里,选择RDIV=0b011 => rdiv = 256, 内核时钟= 8M/256 *1280 / bdiv / div1 = 31.25kHz *1280 / bidv / div1 = 40M / bdiv / div1, 这里40M作为FLL输出,是符合40M~50M要求的。
FLL输出,要求<50M
2)FLL倍频
固定为*1280,也就是FLL输出ICSFLLCLK = 1280*FLL输入 ,FLL输入只能是OSCCLK(外部晶振或OSC),或者37.5 kHz IRC (内部IRC)
3)再看看BDIV是怎么分频的
直接通过设置BDIV的值,范围0~0b111来决定分频系数。
4)系统时钟(core clock/system clock)与总线时钟(bus clock/flash clock),FTM/PWT关系
由RM时钟分布章节可知,core clock = ICSOUTCLK / div1, bus clock = core clock / div2, FTM/PWT时钟 = core clock / div3
一般地建议是,div2 = 2, div3 = 2,也就是说,如果core clock = 40M, 那么其他的需要配置为bus clock = 20M, FTM/PWT时钟 = 20M
=> 建议值DIV1 = 0, DIV2 = 1, DIV3 = 1
6. 其他注意事项
1)配置时钟前,建议关闭看门狗和中断,MCU必要外设初始化完成后再开启;
2)非屏蔽中断NMI功能(NMI_b引脚)不用时,建议关闭(默认是开启的,见SIM_SOPT0[NMIE]描述);
7. 代码实现
简便起见,本文基于S32DS for ARM 2018.R1提供的KEAZ128 SDK V1.0.0实现。
1 #define ICS_Trim_VALUE 54u 2 3 void ClockManager_Init(void) 4 { 5 ICS_Trim(ICS_Trim_VALUE); 6 7 ClockManager_Init_Bus_20M(); 8 }
1 /** 2 * void ClockManager_Init_Bus_20M(void) 3 * @param void 4 * @note configure bus clock work at 20MHz, core clock 40MHz, disable NMI pin as default 5 * bus clock = core clock / 2 , see function ICS_Init() 6 */ 7 void ClockManager_Init_Bus_20M(void) 8 { 9 ICS_ConfigType sConfig = {0}; 10 11 SIM->CLKDIV |= SIM_CLKDIV_OUTDIV2_MASK; //OUTDIV2 = 1, bus clock = core clock / 2 12 13 sConfig.bdiv = 0; 14 sConfig.bLPEnable = 0; 15 sConfig.u8ClkMode = ICS_CLK_MODE_FEE; 16 17 #if EXT_CLK_FREQ > 4000 18 sConfig.oscConfig.bRange =1; 19 #endif 20 21 sConfig.oscConfig.bGain = 1; 22 sConfig.oscConfig.bIsCryst = 1; // use OSC 23 sConfig.oscConfig.bEnable = 1; 24 sConfig.oscConfig.bWaitInit = 1; 25 sConfig.oscConfig.u32OscFreq = EXT_CLK_FREQ; 26 27 ICS_Init(&sConfig); 28 }
8. 验证配置
通过配置PTH2为BUSOUT功能(ALT2),然后用示波器测量PTH2 pin输出波形,查看是否为20M bus clock 。