CMU僅適用于S32K11x系列。S32K1xx系列中的其他器件沒有CMU。S32K11x有兩個(gè)CMU單元:CMU0和CMU1。它監(jiān)控作為系統(tǒng)時(shí)鐘主要來源的FIRC。CMU需要通過軟件啟用,因?yàn)槟J(rèn)情況下未啟用。CMU0用于時(shí)鐘丟失檢測(cè)時(shí)產(chǎn)生復(fù)位,映射到RCM_SRS[4]。當(dāng)FIRC低于編程閾值時(shí),標(biāo)識(shí)時(shí)鐘丟失,將IER[FHAIE]和IER[FLLAIE]以及閾值編程設(shè)置為啟用復(fù)位功能。當(dāng)FIRC低于或高于編程閾值限制時(shí),CMU1用于中斷生成。在CMU1中設(shè)置IER[FHIE]和IER[FLLIE]以及閾值編程,以啟用中斷功能。下圖顯示了CMU與芯片的連接:
在禁用FIRC或SIRC之前,需要禁用CMU。如果FIRC從開始就不存在,則無法啟用CMU,因?yàn)閱⒂肅MU需要系統(tǒng)時(shí)鐘。
?對(duì)于安全應(yīng)用,CMU應(yīng)在與WDOG看門狗在不同的時(shí)鐘上運(yùn)行。
?CMU在最壞情況下將FIRC時(shí)鐘超出范圍事件標(biāo)記為+/-7.5%的準(zhǔn)確度,條件是FIRC和SIRC符合器件數(shù)據(jù)手冊(cè)規(guī)格范圍,即在最壞的情況下分別為+/-1.1%和+/-3.3%。如果FIRC和SIRC違反規(guī)范,CMU精度將進(jìn)一步下降到+/-7.5%以下。
?當(dāng)REF_CNT編程值為1000時(shí),CMU在標(biāo)記FIRC時(shí)鐘超出范圍事件時(shí)所用的硬件安全反應(yīng)時(shí)間為128 us,精確度為+/-7.5%。如果FIRC和SIRC違反規(guī)范,硬件安全反應(yīng)時(shí)長(zhǎng)將超過128 us。
?建議通過軟件將時(shí)鐘范圍超出事件,設(shè)置為復(fù)位系統(tǒng),而不是使用中斷。
在S32K116 系統(tǒng)添加時(shí)鐘監(jiān)控單元。初始化時(shí)鐘FIRC(48MHz),參考配置代碼如下。
CMU0只能在時(shí)鐘丟失時(shí)觸發(fā)復(fù)位,為此,配置參考計(jì)數(shù)、啟用CMU0中斷并啟用頻率檢查。CMU1只能在頻率高于或低于編程限制時(shí)觸發(fā)中斷。為此,配置參考計(jì)數(shù)、HTCR和LTCR、中斷和啟用頻率檢查。重新啟動(dòng)后,系統(tǒng)必須驗(yàn)證復(fù)位是否由時(shí)鐘丟失引起。功能Sanity_check執(zhí)行此操作,如果它是由FIRC丟失引起的,則系統(tǒng)進(jìn)入安全狀態(tài)。如果導(dǎo)致CMU1中斷,系統(tǒng)將驗(yàn)證中斷原因,然后進(jìn)入安全狀態(tài)。
#include "S32K116.h"
#include "clocks.h"
#define GREEN_LED 15 /* 定義綠色 LED */
#define RED_LED 16 /* 定義紅色LED */
/* Sanity_check函數(shù)可能返回狀態(tài)的枚舉*/
typedef enum
{
FIRC_NOT_OK = 0,
FIRC_OK= 1
}Sanity_check_status_t;
/*該功能表示如果時(shí)鐘監(jiān)視器檢測(cè)到FIRC有問題,系統(tǒng)應(yīng)跳至安全狀態(tài)。*/
void Safe_state(void)
{
for(;;)
{
/* 應(yīng)用程序特定安全狀態(tài)*/
}
}
// 通過讀取RCM_SRS寄存器,驗(yàn)證上次系統(tǒng)復(fù)位是否由時(shí)鐘丟失觸發(fā)。
SOSC_AND_SPLL_OK:系統(tǒng)復(fù)位不是由LOC或LOL觸發(fā)的
*SOSC_NOT_OK: LOC觸發(fā)了系統(tǒng)復(fù)位
*SPLL_NOT_OK: 系統(tǒng)復(fù)位由LOL觸發(fā)
Sanity_check_status_t Sanity_check(void)
{
///應(yīng)用軟件需要檢測(cè)RCM的錯(cuò)誤標(biāo)志狀態(tài)
/* 判斷RCM_SRS寄存器的CMU_LOC 位是否被置位*/
if(True == ((RCM->SRS & RCM_SRS_CMU_LOC_MASK) >> RCM_SRS_CMU_LOC_SHIFT))
{
/* 返回 SOSC_NOT_OK 狀態(tài)*/
return FIRC_NOT_OK;
}
/* 默認(rèn)返回SOSC_AND_SPLL_OK 狀態(tài)*/
return FIRC_OK;
}
/* SCG_CMU_LVD_LVWSCG_IRQHandler 表示 CMU中斷。當(dāng)頻率不在編程范圍內(nèi)時(shí),通過 CMU1觸發(fā),通過關(guān)閉綠色LED,點(diǎn)亮紅色 LED指示。*/
void SCG_CMU_LVD_LVWSCG_IRQHandler(void)
{
/* 關(guān)閉綠色的 LED */
PTD->PCOR |= 1 << GREEN_LED;
/* 開啟紅色的LED */
PTD->PSOR |= 1 << RED_LED;
///對(duì)于丟失的中斷請(qǐng)求,應(yīng)用程序可能需要在系統(tǒng)級(jí)別上包括檢測(cè)或保護(hù)措施
/* 中斷由CMU1引起,頻率高于閾值*/
if(True == (CMU_FC_1->IER & CMU_FC_SR_FHH_MASK) >> CMU_FC_SR_FHH_SHIFT)
{
/* 清除中斷的標(biāo)志*/
CMU_FC_1->SR |= CMU_FC_SR_FHH_MASK;
/* 進(jìn)入安裝狀態(tài) */
Safe_state();
}
/* 中斷由CMU1引起,頻率低于閾值*/
else if(True == (CMU_FC_1->IER & CMU_FC_SR_FLL_MASK) >> CMU_FC_SR_FLL_SHIFT)
{
/* 清除中斷的標(biāo)志*/
CMU_FC_1->SR |= CMU_FC_SR_FLL_MASK;
/* 進(jìn)入安裝狀態(tài) */
Safe_state();
}
}
int main(void)
{
/* 驗(yàn)證之前的復(fù)位是否是由時(shí)鐘丟失引起的*/
if(FIRC_NOT_OK == Sanity_check())
{
/* 進(jìn)入安全狀態(tài)*/
Safe_state();
}
/* 使能端口 D的時(shí)鐘,開啟綠色和紅色的LED 指示*/
PCC-> PCCn[PCC_PORTD_INDEX] = PCC_PCCn_CGC_MASK;
/* 選擇GPIO */
PORTD->PCR[GREEN_LED] = PORT_PCR_MUX(1);
/* 設(shè)置端口D 引腳 15 為輸出*/
PTD->PDDR |= 1 << GREEN_LED;
/* 選擇GPIO*/
PORTD->PCR[RED_LED] = PORT_PCR_MUX(1);
/* 設(shè)置端口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();
/* 設(shè)置SIRC 為系統(tǒng)時(shí)鐘*/
SCG->RCCR = SCG_RCCR_SCS(2);
///對(duì)于安全相關(guān)應(yīng)用,必須使用時(shí)鐘監(jiān)視器。如果應(yīng)用安全功能使用SCG監(jiān)視器的模塊,用戶應(yīng)驗(yàn)證時(shí)鐘監(jiān)視器未被禁用,且其故障由軟件管理。需要以下監(jiān)督功能:內(nèi)部快速參考時(shí)鐘丟失、系統(tǒng)FIRC頻率高于(可編程)上限頻率參考、系統(tǒng)FIRC頻率低于(可編程的)下限頻率參考、應(yīng)用軟件必須在激活安全相關(guān)功能之前驗(yàn)證S32K1xx的初始化是否正確。時(shí)鐘監(jiān)視器已啟用。
/* 配置CMU0 來檢測(cè)內(nèi)部的 FIRC是否丟失*/
CMU0_init();
/* 配置 CMU1來檢測(cè) FIRC的頻率是否變化*/
CMU1_init();
/* 關(guān)閉FIRC,因此CMU_FC_0 會(huì)觸發(fā)復(fù)位*/
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設(shè)置為除以1。啟用SIRC并等待SIRC有效。*/
void SIRC_init(void)
{
/* 驗(yàn)證是否可以寫入控制狀態(tài)寄存器 */
if(False == ((SCG->SIRCCSR & SCG_SIRCCSR_LK_MASK) >> SCG_SIRCCSR_LK_SHIFT))
{
/* 禁用SIRC,以便進(jìn)行更改 */
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)
{
/* 配置內(nèi)部的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 時(shí)鐘*/
PCC->PCCn[PCC_PORTB_INDEX] = PCC_PCCn_CGC_MASK;
/* 設(shè)置端口 B的引腳 5設(shè)為輸出*/
PTB->PDDR |= 1 << PTB5;
/* 選擇 CLKOUT */
PORTB->PCR[PTB5] = PORT_PCR_MUX(5);
}
/* CMU0_init:該函數(shù)配置 CMU0來檢測(cè)是否有 FIRC時(shí)鐘丟失。為此,需要對(duì)參考計(jì)數(shù)進(jìn)行編程,需要啟用中斷和頻率檢查。當(dāng)FIRC丟失時(shí),將觸發(fā)復(fù)位。*/
void CMU0_init(void)
{
/* 使能 CMU0時(shí)鐘門控*/
PCC->PCCn[PCC_CMU0_INDEX] = PCC_PCCn_CGC_MASK;
/*
總線頻率= 8 MHz
參考時(shí)鐘頻率= 8 MHz
監(jiān)控時(shí)鐘頻率 = 48 MHz
* 公式1:
F1 = 3 * 參考時(shí)鐘頻率 / 總線頻率
F1 = 3 * (8 MHz / 8MHz) = 3
* 公式 2:
F2 = 6 + 3 * (參考時(shí)鐘頻率 / 監(jiān)控時(shí)鐘頻率)
F2 = 6 + 3 * (8 MHz / 48 MHz) = 6.5
* F1和F2結(jié)果之間的最大值Max(F1, F2),Max(3, 6.5) = 6.5
* 最大結(jié)果的上限 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;
/* 使能頻率檢測(cè)*/
CMU_FC_0->GCR = CMU_FC_GCR_FCE_MASK;
/* 等待頻率檢查開始運(yùn)行 */
while(False == (CMU_FC_0->SR & CMU_FC_SR_RS_MASK) >> CMU_FC_SR_RS_SHIFT);
}
/*CMU1_init:其功能配置CMU1以檢測(cè)FIRC的頻率是否不在編程限制之間。為此,需要對(duì)參考計(jì)數(shù)、HTRC和LTRC進(jìn)行編程,需要啟用中斷和頻率檢查。如果頻率不在限值之間,將觸發(fā)SCG_CMU_LVD_LVWSCG_IRQ。*/
void CMU1_init(void)
{
/* 使能 CMU1時(shí)鐘門控 */
PCC->PCCn[PCC_CMU1_INDEX] = PCC_PCCn_CGC_MASK;
/*
總線頻率= 8 MHz
參考時(shí)鐘頻率= 8 MHz
監(jiān)控時(shí)鐘頻率 = 48 MHz
* 公式1:
F1 = 3 *參考時(shí)鐘頻率/ 總線頻率
F1 = 3 * (8 MHz / 8MHz) = 3
* 公式 2:
F2 = 6 + 3 * (參考時(shí)鐘頻率/ 監(jiān)控時(shí)鐘頻率)
F2 = 6 + 3 * (8 MHz / 48 MHz) = 6.5
*F1和F2結(jié)果之間的最大值Max(F1, F2),Max(3, 6.5) = 6.5
* 最大結(jié)果的上限 Ceiling(6.5) = 7
* RCCR[REF_CNT] = 7
*/
CMU_FC_1->RCCR = 7;
/*
* HTCR 和 LTCR 計(jì)算
* 參考時(shí)鐘頻率= 8 MHz
* 監(jiān)控時(shí)鐘頻率= 48 MHz
* RCCR[REF_CNT] = 7
* Ideal_monitored_clock_count = (監(jiān)控時(shí)鐘頻率 / 參考時(shí)鐘頻率) * REF_CNT
* Ideal_monitored_clock_count = (48 MHz / 8 MHz) * 7 = 42
*參考時(shí)鐘頻率和監(jiān)控時(shí)鐘頻率變化+/- 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;
/* 使能頻率檢測(cè)*/
CMU_FC_1->GCR = CMU_FC_GCR_FCE_MASK;
/* 等待頻率檢查開始運(yùn)行 */
while(False == (CMU_FC_1->SR & CMU_FC_SR_RS_MASK) >> CMU_FC_SR_RS_SHIFT);
}
-
芯片
+關(guān)注
關(guān)注
455文章
50714瀏覽量
423139 -
看門狗
+關(guān)注
關(guān)注
10文章
560瀏覽量
70789 -
時(shí)鐘
+關(guān)注
關(guān)注
10文章
1733瀏覽量
131446 -
CMU
+關(guān)注
關(guān)注
0文章
21瀏覽量
15249 -
時(shí)鐘模塊
+關(guān)注
關(guān)注
1文章
50瀏覽量
14374
原文標(biāo)題:配置 S32K116 CMU 檢測(cè)時(shí)鐘模塊
文章出處:【微信號(hào):嵌入式 MCU,微信公眾號(hào):嵌入式 MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論