本文介紹如何用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 。