0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

配置S32K116 CMU检测时钟模块

li1756686189 来源:嵌入式 MCU 2023-01-30 16:24 次阅读

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与芯片的连接:

08ba4104-a077-11ed-bfe3-dac502259ad0.png

在禁用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);

}

08c8299a-a077-11ed-bfe3-dac502259ad0.png

08d3115c-a077-11ed-bfe3-dac502259ad0.png

08df5d5e-a077-11ed-bfe3-dac502259ad0.png

0910f760-a077-11ed-bfe3-dac502259ad0.png

091fb49e-a077-11ed-bfe3-dac502259ad0.png

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 芯片
    +关注

    关注

    447

    文章

    47821

    浏览量

    409198
  • 看门狗
    +关注

    关注

    10

    文章

    541

    浏览量

    70257
  • 时钟
    +关注

    关注

    10

    文章

    1480

    浏览量

    130306
  • CMU
    CMU
    +关注

    关注

    0

    文章

    19

    浏览量

    15129
  • 时钟模块
    +关注

    关注

    1

    文章

    45

    浏览量

    14244

原文标题:配置 S32K116 CMU 检测时钟模块

文章出处:【微信号:嵌入式 MCU,微信公众号:嵌入式 MCU】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何使用S32K116主机MCU与ST25R3920通信?

    大家好,我正在尝试使用 S32K116 主机 MCU 与 ST25R3920 通信。我设法读取了一些数据,但根据数据表,它们似乎毫无意义。例如:我试图读取 IC 身份寄存器 (3Fh) 以测试我
    发表于 12-06 07:00

    请问S32K116可以改变I/O驱动电流吗?

    S32K116可以改变I/O驱动电流吗?
    发表于 02-28 06:57

    S32K116 FlexCan TxFrame MB在从PN唤醒后损坏怎么解决?

    我正在使用 S32DS3.4.1 和 RTM.4.0.2 开发 S32K116我正在尝试使用 500kbps CAN 网络实现一些低功耗模式。FlexCan 配置为使用 MessageBuffer
    发表于 03-15 06:49

    求分享开发S32K116引导加载程序应用程序

    我正在尝试为在 S32K116 上运行的应用程序开发引导加载程序。我设法找到了一个 S32K148 引导加载程序的示例项目,我读到可以修改它以在 S32K116 上使用。但问题是我不知道如何修改
    发表于 03-21 07:12

    如何在S32K116上使用Touch Slider功能?

    我在 mcu s32k116 上使用了触摸滑块功能,我们有 6 个电极垫,其中两个用作滑块功能。能否提供一下文档号:AN_CSSWUG中提到的Slider Application Quick Start Guide文档,网上找不到。
    发表于 03-22 06:31

    S32K上编程时如何观察POT值的变化?

    我正在使用#S32K116 评估板 - S32K116EVB2Q048。 板上有一个ADC_POT,但看起来没有连接。如果我正在看正确的原理图,你能帮我吗?如果是这样,在 S32K 上编程时如何观察 POT 值的变化。
    发表于 03-29 08:59

    S32K116如何通过连续DMA使用flexI2S发送数据?

    中没有任何触发。我查看了 S32DS 上的“edma_transfer_s32k146”项目。该项目未配置为从 flex 模块发送数据。我无法通过将 scatterGatherEnab
    发表于 03-31 08:58

    使用S32DS通过J-Link连接到S32K116板报告错误怎么处理?

    处理所有,为了使用 S32DS 通过 J-Link 连接到 S32K116 板,它失败并报告错误:“发送后无法确定 GDB 版本:C:NXPS32DS_ARM_v2.2eclipse../S
    发表于 04-10 07:31

    如何更改S32K116 Vref?

    我试图在我的项目中实施 ADC 转换。我已经知道了,但是这个值有问题,所以我决定检查一些例子,比如“adc_hwtrigger_s32k116”、“adc_pal_s32k116”……问题一直出现在
    发表于 04-20 07:17

    如何将多个.elf文件刷入S32K116

    我正在尝试使用 pegdb 控制台、bootloader.elf 和 app.elf 将 2 个 .elf 文件闪存到 S32K116。 以下是我正在执行的步骤:使用命
    发表于 05-04 08:17

    S32K116缺少.elf文件是怎么回事?

    我最近购买了 S32K116 开发套件,想开始使用电机控制软件提供的代码示例。但是,在设置所有内容时,我注意到我的安装文件中缺少调试器的 .elf 文件。 我的问题是,是否有一个数据库可以直接从
    发表于 05-06 06:39

    Freemaster工具入门,S32k116连接不上怎么处理?

    我已经安装了 Freemaster 2.0 并将我的 S32k116 评估板连接到我的 USB 端口,我已经按照指南使用以下设置调整了项目的通信端口 :打开 SDA 速度:115200 当我尝试开始通信时下面附加的日志窗口发生错误。 “
    发表于 05-24 08:25

    S32K116实施基于LIN的引导加载程序,NxpOpenBus SW仅支持.bin文件格式怎么解决?

    需要为 S32K116 实施基于 LIN 的引导加载程序,统一的引导加载程序框架... 这个链接。 对于我们的项目,我们使用 IAR 编译器,它在编译 IAR 后生成 .out 文件,但我观察到
    发表于 05-29 06:42

    求分享s32k116的示例链接描述文件和启动代码

    s32k118,s32k144,s32k144W等都有一个文件夹。,问题是为什么没有 s32k116 的示例,这个包应该支持 s32k1xx
    发表于 06-05 13:09

    S32K116调试启动晶振正常,上电启动晶振不振是什么原因?

    S32K116调试启动晶振正常,且能进行单步调试,但引脚不输入信号,重新上电启动,晶振不正常,没有人知道哪孩子出问题了
    发表于 06-08 07:53