CMU僅適用于S32K11x系列。S32K1xx系列中的其他器件沒有CMU。S32K11x有兩個CMU單元:CMU0和CMU1。它監控作為系統時鐘主要來源的FIRC。CMU需要通過軟件啟用,因為默認情況下未啟用。CMU0用于時鐘丟失檢測時產生復位,映射到RCM_SRS[4]。當FIRC低于編程閾值時,標識時鐘丟失,將IER[FHAIE]和IER[FLLAIE]以及閾值編程設置為啟用復位功能。當FIRC低于或高于編程閾值限制時,CMU1用于中斷生成。在CMU1中設置IER[FHIE]和IER[FLLIE]以及閾值編程,以啟用中斷功能。下圖顯示了CMU與芯片的連接:
在禁用FIRC或SIRC之前,需要禁用CMU。如果FIRC從開始就不存在,則無法啟用CMU,因為啟用CMU需要系統時鐘。
?對于安全應用,CMU應在與WDOG看門狗在不同的時鐘上運行。
?CMU在最壞情況下將FIRC時鐘超出范圍事件標記為+/-7.5%的準確度,條件是FIRC和SIRC符合器件數據手冊規格范圍,即在最壞的情況下分別為+/-1.1%和+/-3.3%。如果FIRC和SIRC違反規范,CMU精度將進一步下降到+/-7.5%以下。
?當REF_CNT編程值為1000時,CMU在標記FIRC時鐘超出范圍事件時所用的硬件安全反應時間為128 us,精確度為+/-7.5%。如果FIRC和SIRC違反規范,硬件安全反應時長將超過128 us。
?建議通過軟件將時鐘范圍超出事件,設置為復位系統,而不是使用中斷。
在S32K116 系統添加時鐘監控單元。初始化時鐘FIRC(48MHz),參考配置代碼如下。
CMU0只能在時鐘丟失時觸發復位,為此,配置參考計數、啟用CMU0中斷并啟用頻率檢查。CMU1只能在頻率高于或低于編程限制時觸發中斷。為此,配置參考計數、HTCR和LTCR、中斷和啟用頻率檢查。重新啟動后,系統必須驗證復位是否由時鐘丟失引起。功能Sanity_check執行此操作,如果它是由FIRC丟失引起的,則系統進入安全狀態。如果導致CMU1中斷,系統將驗證中斷原因,然后進入安全狀態。
#include "S32K116.h"
#include "clocks.h"
#define GREEN_LED 15 /* 定義綠色 LED */
#define RED_LED 16 /* 定義紅色LED */
/* Sanity_check函數可能返回狀態的枚舉*/
typedef enum
{
FIRC_NOT_OK = 0,
FIRC_OK= 1
}Sanity_check_status_t;
/*該功能表示如果時鐘監視器檢測到FIRC有問題,系統應跳至安全狀態。*/
void Safe_state(void)
{
for(;;)
{
/* 應用程序特定安全狀態*/
}
}
// 通過讀取RCM_SRS寄存器,驗證上次系統復位是否由時鐘丟失觸發。
SOSC_AND_SPLL_OK:系統復位不是由LOC或LOL觸發的
*SOSC_NOT_OK: LOC觸發了系統復位
*SPLL_NOT_OK: 系統復位由LOL觸發
Sanity_check_status_t Sanity_check(void)
{
///應用軟件需要檢測RCM的錯誤標志狀態
/* 判斷RCM_SRS寄存器的CMU_LOC 位是否被置位*/
if(True == ((RCM->SRS & RCM_SRS_CMU_LOC_MASK) >> RCM_SRS_CMU_LOC_SHIFT))
{
/* 返回 SOSC_NOT_OK 狀態*/
return FIRC_NOT_OK;
}
/* 默認返回SOSC_AND_SPLL_OK 狀態*/
return FIRC_OK;
}
/* SCG_CMU_LVD_LVWSCG_IRQHandler 表示 CMU中斷。當頻率不在編程范圍內時,通過 CMU1觸發,通過關閉綠色LED,點亮紅色 LED指示。*/
void SCG_CMU_LVD_LVWSCG_IRQHandler(void)
{
/* 關閉綠色的 LED */
PTD->PCOR |= 1 << GREEN_LED;
/* 開啟紅色的LED */
PTD->PSOR |= 1 << RED_LED;
///對于丟失的中斷請求,應用程序可能需要在系統級別上包括檢測或保護措施
/* 中斷由CMU1引起,頻率高于閾值*/
if(True == (CMU_FC_1->IER & CMU_FC_SR_FHH_MASK) >> CMU_FC_SR_FHH_SHIFT)
{
/* 清除中斷的標志*/
CMU_FC_1->SR |= CMU_FC_SR_FHH_MASK;
/* 進入安裝狀態 */
Safe_state();
}
/* 中斷由CMU1引起,頻率低于閾值*/
else if(True == (CMU_FC_1->IER & CMU_FC_SR_FLL_MASK) >> CMU_FC_SR_FLL_SHIFT)
{
/* 清除中斷的標志*/
CMU_FC_1->SR |= CMU_FC_SR_FLL_MASK;
/* 進入安裝狀態 */
Safe_state();
}
}
int main(void)
{
/* 驗證之前的復位是否是由時鐘丟失引起的*/
if(FIRC_NOT_OK == Sanity_check())
{
/* 進入安全狀態*/
Safe_state();
}
/* 使能端口 D的時鐘,開啟綠色和紅色的LED 指示*/
PCC-> PCCn[PCC_PORTD_INDEX] = PCC_PCCn_CGC_MASK;
/* 選擇GPIO */
PORTD->PCR[GREEN_LED] = PORT_PCR_MUX(1);
/* 設置端口D 引腳 15 為輸出*/
PTD->PDDR |= 1 << GREEN_LED;
/* 選擇GPIO*/
PORTD->PCR[RED_LED] = PORT_PCR_MUX(1);
/* 設置端口D引腳16 為輸出*/
PTD->PDDR |= 1 << RED_LED;
/* 開啟綠色 LED輸出*/
PTD->PSOR |= 1 << GREEN_LED;
/* 配置寄存器將FIRC映射到引腳*/
FIRC_init();
/*啟用NVIC模塊中的CMC_FC_0和CMC_FC_1中斷*/
NVIC_enable_CMU_interrupt();
/* 配置SIRC */
SIRC_init();
/* 設置SIRC 為系統時鐘*/
SCG->RCCR = SCG_RCCR_SCS(2);
///對于安全相關應用,必須使用時鐘監視器。如果應用安全功能使用SCG監視器的模塊,用戶應驗證時鐘監視器未被禁用,且其故障由軟件管理。需要以下監督功能:內部快速參考時鐘丟失、系統FIRC頻率高于(可編程)上限頻率參考、系統FIRC頻率低于(可編程的)下限頻率參考、應用軟件必須在激活安全相關功能之前驗證S32K1xx的初始化是否正確。時鐘監視器已啟用。
/* 配置CMU0 來檢測內部的 FIRC是否丟失*/
CMU0_init();
/* 配置 CMU1來檢測 FIRC的頻率是否變化*/
CMU1_init();
/* 關閉FIRC,因此CMU_FC_0 會觸發復位*/
SCG->FIRCCSR &= ~SCG_FIRCCSR_FIRCEN_MASK;
for(;;){}
return 0;
}
#include "clocks.h"
/*NVIC_enable_CMU_interrupt 在NVIC中使能CMU模塊的中斷*/
void NVIC_enable_CMU_interrupt(void)
{
/* 清除 IRQs, SCG NVIC 中斷 ID = 21 */
S32_NVIC->ICPR[0] = 1 << (SCG_CMU_LVD_LVWSCG_IRQn % 32);
/* 使能 IRQ */
S32_NVIC->ISER[0] = 1 << (SCG_CMU_LVD_LVWSCG_IRQn % 32);
}
/*SIRC_init 如果可以寫入SIRCCSR,則禁用SIRC,以便可以選擇8MHz頻率,然后將DIV 1和2設置為除以1。啟用SIRC并等待SIRC有效。*/
void SIRC_init(void)
{
/* 驗證是否可以寫入控制狀態寄存器 */
if(False == ((SCG->SIRCCSR & SCG_SIRCCSR_LK_MASK) >> SCG_SIRCCSR_LK_SHIFT))
{
/* 禁用SIRC,以便進行更改 */
SCG->SIRCCSR &= ~(SCG_SIRCCSR_SIRCLPEN_MASK |SCG_SIRCCSR_SIRCEN_MASK);
SCG->SIRCDIV |= SCG_SIRCDIV_SIRCDIV1(1) | SCG_SIRCDIV_SIRCDIV2(1);
/*選擇高頻范圍 (8MHz) */
SCG->SIRCCFG |= SCG_SIRCCFG_RANGE_MASK;
/* 使能 SIRC */
SCG->SIRCCSR |= SCG_SIRCCSR_SIRCLPEN_MASK |SCG_SIRCCSR_SIRCEN_MASK;
/* 等待直到 SIRC 是有效的*/
while(False == ((SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK) >> SCG_SIRCCSR_SIRCVLD_SHIFT));
}
}
/*FIRC_init 配置寄存器需要將FIRC輸出到引腳上*/
void FIRC_init(void)
{
/* 配置內部的FIRC到端口 B的第5腳*/
/* 在SCG_CLKOUTCNFG寄存器的CLKOUTSEL 中選擇 FIRC*/
SCG->CLKOUTCNFG |= SCG_CLKOUTCNFG_CLKOUTSEL(3);
/* 在SIM_CHIPCTL,CLKOUTSEL中 選擇 FIRC*/
SIM->CHIPCTL |= SIM_CHIPCTL_CLKOUTSEL(0);
/* 配置 CLKOUT 分頻*/
SIM->CHIPCTL |= SIM_CHIPCTL_CLKOUTDIV(0);
/* 使能CLKOUT */
SIM->CHIPCTL |= SIM_CHIPCTL_CLKOUTEN_MASK;
/* 將 CLKOUT 配置到引腳 PTB5 */
/* 使能端口 B 時鐘*/
PCC->PCCn[PCC_PORTB_INDEX] = PCC_PCCn_CGC_MASK;
/* 設置端口 B的引腳 5設為輸出*/
PTB->PDDR |= 1 << PTB5;
/* 選擇 CLKOUT */
PORTB->PCR[PTB5] = PORT_PCR_MUX(5);
}
/* CMU0_init:該函數配置 CMU0來檢測是否有 FIRC時鐘丟失。為此,需要對參考計數進行編程,需要啟用中斷和頻率檢查。當FIRC丟失時,將觸發復位。*/
void CMU0_init(void)
{
/* 使能 CMU0時鐘門控*/
PCC->PCCn[PCC_CMU0_INDEX] = PCC_PCCn_CGC_MASK;
/*
總線頻率= 8 MHz
參考時鐘頻率= 8 MHz
監控時鐘頻率 = 48 MHz
* 公式1:
F1 = 3 * 參考時鐘頻率 / 總線頻率
F1 = 3 * (8 MHz / 8MHz) = 3
* 公式 2:
F2 = 6 + 3 * (參考時鐘頻率 / 監控時鐘頻率)
F2 = 6 + 3 * (8 MHz / 48 MHz) = 6.5
* F1和F2結果之間的最大值Max(F1, F2),Max(3, 6.5) = 6.5
* 最大結果的上限 Ceiling(6.5) = 7
* RCCR[REF_CNT] = 7
*/
CMU_FC_0->RCCR = 7;
/* 使能CMU0 中斷*/
CMU_FC_0->IER |= CMU_FC_IER_FHHAEE_MASK | CMU_FC_IER_FLLAEE_MASK;
/* 使能頻率檢測*/
CMU_FC_0->GCR = CMU_FC_GCR_FCE_MASK;
/* 等待頻率檢查開始運行 */
while(False == (CMU_FC_0->SR & CMU_FC_SR_RS_MASK) >> CMU_FC_SR_RS_SHIFT);
}
/*CMU1_init:其功能配置CMU1以檢測FIRC的頻率是否不在編程限制之間。為此,需要對參考計數、HTRC和LTRC進行編程,需要啟用中斷和頻率檢查。如果頻率不在限值之間,將觸發SCG_CMU_LVD_LVWSCG_IRQ。*/
void CMU1_init(void)
{
/* 使能 CMU1時鐘門控 */
PCC->PCCn[PCC_CMU1_INDEX] = PCC_PCCn_CGC_MASK;
/*
總線頻率= 8 MHz
參考時鐘頻率= 8 MHz
監控時鐘頻率 = 48 MHz
* 公式1:
F1 = 3 *參考時鐘頻率/ 總線頻率
F1 = 3 * (8 MHz / 8MHz) = 3
* 公式 2:
F2 = 6 + 3 * (參考時鐘頻率/ 監控時鐘頻率)
F2 = 6 + 3 * (8 MHz / 48 MHz) = 6.5
*F1和F2結果之間的最大值Max(F1, F2),Max(3, 6.5) = 6.5
* 最大結果的上限 Ceiling(6.5) = 7
* RCCR[REF_CNT] = 7
*/
CMU_FC_1->RCCR = 7;
/*
* HTCR 和 LTCR 計算
* 參考時鐘頻率= 8 MHz
* 監控時鐘頻率= 48 MHz
* RCCR[REF_CNT] = 7
* Ideal_monitored_clock_count = (監控時鐘頻率 / 參考時鐘頻率) * REF_CNT
* Ideal_monitored_clock_count = (48 MHz / 8 MHz) * 7 = 42
*參考時鐘頻率和監控時鐘頻率變化+/- 5%
* CMU_FC_inaccuracy = 3
* HTCR[HFREF] = (Ideal_monitored_clock_count * (100% + 5%)) + CMU_FC_inaccuracy
* HTCR[HFREF] = (42 * (105%)) + 3 = 47.1 --> 47
* LTCR[LFREF] = (Ideal_monitored_clock_count * (100% - 5%)) - CMU_FC_inaccuracy
* LTCR[LFREF] = ( 42 * (95%)) - 3 = 36.9 --> 37
*/
CMU_FC_1->HTCR = 47;
CMU_FC_1->LTCR = 37;
/* 使能 CMU1 中斷 */
CMU_FC_1->IER = CMU_FC_IER_FHHIE_MASK | CMU_FC_IER_FLLIE_MASK;
/* 使能頻率檢測*/
CMU_FC_1->GCR = CMU_FC_GCR_FCE_MASK;
/* 等待頻率檢查開始運行 */
while(False == (CMU_FC_1->SR & CMU_FC_SR_RS_MASK) >> CMU_FC_SR_RS_SHIFT);
}
-
芯片
+關注
關注
459文章
52125瀏覽量
435663 -
看門狗
+關注
關注
10文章
579瀏覽量
71542 -
時鐘
+關注
關注
11文章
1878瀏覽量
132808 -
CMU
+關注
關注
0文章
21瀏覽量
15398 -
時鐘模塊
+關注
關注
1文章
58瀏覽量
14545
原文標題:配置 S32K116 CMU 檢測時鐘模塊
文章出處:【微信號:嵌入式 MCU,微信公眾號:嵌入式 MCU】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
S32K116 FlexCan TxFrame MB在從PN喚醒后損壞怎么解決?
求分享開發S32K116引導加載程序應用程序
如何在S32K116上使用Touch Slider功能?
S32K116如何通過連續DMA使用flexI2S發送數據?
使用S32DS通過J-Link連接到S32K116板報告錯誤怎么處理?
如何更改S32K116 Vref?
如何將多個.elf文件刷入S32K116?
S32K116缺少.elf文件是怎么回事?
Freemaster工具入門,S32k116連接不上怎么處理?
為S32K116實施基于LIN的引導加載程序,NxpOpenBus SW僅支持.bin文件格式怎么解決?
求分享s32k116的示例鏈接描述文件和啟動代碼
S32K116調試啟動晶振正常,上電啟動晶振不振是什么原因?
基于 NXP S32K116 &amp; PJF7992 的 PEPS 評估板方案

評論