赞
踩
配置工具:EB Tresos Studio
芯片类型:S32K146
MCU模块提供了访问内核
相关功能的API,例如配置时钟、初始化RAM、设置低功耗模式、提供复位接口等。
从上图可以看到最左边为输入时钟源,右边为输出时钟
,为了让系统运行在合适的时钟频率环境下,我们需要选择合适的时钟源并通过倍频、分频
来得到我们想要的时钟频率。
S32K14x时钟源:
输入时钟源 | 描述 | 频率 |
---|---|---|
FIRC | 内部高速时钟源 | 48MHz |
SIRC | 内部低速时钟源 | 8MHz |
SOSC | 外部晶振 | 8MHz~40MHz |
LPO | 内部低功耗时钟源 | 128KHz |
SOSC可以通过PLL倍频成SPLL_CLK
S32K14x系统时钟信号:
输出时钟源 | 描述 |
---|---|
CORE_CLK | 内核时钟 |
SYS_CLK | 系统时钟 |
BUS_CLK | 总线时钟 |
FLASH_CLK | FLASH时钟 |
运行模式 | 描述 |
---|---|
HSRUN | 高速运行模式 |
RUN | 普通运行模式 |
VLPR | 低速运行模式 |
S32K146在每个工作模式下的最高运行时钟频率如下表所示:
各个模式下允许使用的时钟源以及切换如下图所示:
通过一个例子来说明:
配置项 | 目标 |
---|---|
CORE_CLK | 80MHz |
SYS_CLK | 80MHz |
BUS_CLK | 40MHz |
FLASH_CLK | 20MHz |
为了达到上述的配置目标,可以看到我这里选择CORE_CLK
和SYS_CLK
为80MHZ,可以发现通过内部时钟源根本无法达到该频率,因此使用外部晶振(SOSC)8MHz,通过PLL倍频得高速频率,再通过分频达到我们想要的80MHz。
计算方式:
SPLL_CLK = SOSC(8MHz)* 40(PLL倍频)/ 2(PLL分频)= 160MHz.
CORE_CLK \ SYS_BUS = SPLL_CLK / 2(DIVCORE分频)= 80MHz.
BUS_CLK = SPLL_CLK / 2(DIVCORE分频)/ 2 (DIVBUS分频)= 40MHz.
FLASH_CLK = SPLL_CLK / 2(DIVCORE分频)/ 4(DIVFLASH分频)= 20MHz.
通过上面的公式可以看到我们通过PLL倍频后,时钟频率达到了160MHz。后续再通过分频达到我们想要的频率。从上面公式可以得到配置参数
:
配置相 | 参数 |
---|---|
PLL 倍频 | 40 |
DIVCORE | 2 |
DIVBUS | 2 |
DIVFLASH | 4 |
在S32K-RM
里面可以看到复位信息是存放在SSRS
寄存器中,软件读取该寄存器值来获取复位源。
通过设置M4内核的系统控制寄存器AIRCR
的SYSRESETREQ
来对MCU进行复位:
FUNC(void, MCU_CODE) Mcu_CM4_SystemReset(void)
{
ASM_KEYWORD(" dsb"); /* All memory accesses have to be completed before reset */
/** @violates @ref Mcu_CortexM4_c_REF_4 Required Rule 11.1, Conversion from integer to pointer */
/** @violates @ref Mcu_CortexM4_c_REF_5 The cast is used to access memory mapped registers.*/
REG_WRITE32( CM4_AIRCR_BASEADDR, (uint32)(CM4_AIRCR_VECTKEY(0x5FAU) | (REG_READ32(CM4_AIRCR_BASEADDR) & CM4_AIRCR_PRIGROUP_MASK) | CM4_AIRCR_SYSRESETREQ_MASK ));
ASM_KEYWORD(" dsb"); /* All memory accesses have to be completed */
}
函数 | 功能 |
---|---|
Mcu_Init | MCU初始化 |
Mcu_InitRamSection | RAM初始化 |
Mcu_InitClock | 时钟初始化 |
Mcu_DistributePllClock | 使能PLL |
Mcu_GetPllStatus | 获取PLL状态 |
Mcu_GetResetReason | 获取复位源(SSRS寄存器原始值处理过后得到的复位信息) |
Mcu_GetResetRawValue | 获取复位源(SSRS寄存器原始值) |
Mcu_SetMode | 运行模式设置 |
Mcu_GetVersionInfo | 获取版本信息 |
Mcu_GetRamState | 获取RAM状态 |
Mcu Init Clock API:
MCU初始化API
Mcu No PLL:
禁用PLL,从下面代码看出MCU配置PLL需要关闭Mcu No PLL
并且勾选SPLL UNDER MCU CONTROL
#if (MCU_NO_PLL == STD_OFF)
/* Configure SPLL */
if (MCU_IPW_SPLL_UNDER_MCU_CONTROL == (Mcu_pClockConfig->u8ClockSourcesControl & MCU_IPW_SPLL_UNDER_MCU_CONTROL))
{
/** @violates @ref Mcu_IPW_c_REF_5 The comma operator shall not be used. */
/** @violates @ref Mcu_IPW_c_REF_7 MISRA 2004 Rule 16.9, function identifier */
/** @violates @ref Mcu_IPW_c_REF_9 MISRA 2004 Rule 8.3, For each function parameter */
Call_Mcu_SCG_SpllInit(Mcu_pClockConfig->SCG_pClockConfig);
}
#endif /* MCU_NO_PLL */
Mcu Enter Low-Power Mode:
允许MCU进入低功耗模式
System clock under MCU control:
是能了以后MCU模块才能配置SCG
/* Configure SIRC and then select it as system clock by default. This is needed to apply new configuration for Pll
in case of the Pll selected as system clock previously. This is possible only when sys clock is under Mcu control.
*/
if(SCG_SYS_CLK_NOT_UNDER_MCU_CONTROL != Mcu_pClockConfigPtr->SCG_pClockConfig->u32RunClockControlConfiguration)
{
/** @violates @ref Mcu_IPW_c_REF_5 The comma operator shall not be used. */
/** @violates @ref Mcu_IPW_c_REF_7 MISRA 2004 Rule 16.9, function identifier */
/** @violates @ref Mcu_IPW_c_REF_8 MISRA 2004 Rule 8.1, Functions shall have prototype */
Call_Mcu_SCG_DropSystemClockToTrustedClock();
}
SCG ClkOut Select:
系统时钟选择
各模式下的时钟配置
Run System Clock Select:
系统运行时钟源选择
Run Core Clock Divider:
DIVCORE分频
Run Bus Clock Divider:
DIVBUS分频
Run Slow Clock Divider:
DIVSLOW分频
其他配置项使用自动计算按钮计算即可。
时钟源配置
SOSC under MCU Control:
勾选了之后MCU模块才能够配置SOSC,如下代码所示
/* Configure SOSC */
if (MCU_IPW_SOSC_UNDER_MCU_CONTROL == (Mcu_pClockConfig->u8ClockSourcesControl & MCU_IPW_SOSC_UNDER_MCU_CONTROL))
{
/** @violates @ref Mcu_IPW_c_REF_5 The comma operator shall not be used. */
/** @violates @ref Mcu_IPW_c_REF_7 MISRA 2004 Rule 16.9, function identifier */
/** @violates @ref Mcu_IPW_c_REF_9 MISRA 2004 Rule 8.3, For each function parameter */
Call_Mcu_SCG_SoscInit(Mcu_pClockConfig->SCG_pClockConfig);
}
SOSC Frequency:
SOSC外部晶振频率
SOSC Enable:
使能SOSC时钟源
SOSC Divider2:
DIV2分频系数
SOSC Divider1:
DIV1分频系数
SOSC Clock Monitor Enable:
使能SOSC时钟监控
SOSC Clock Monitor Reset Enable:
时钟异常复位
SOSC Range Select:
MEDIUM_FREQ_RANGE(4MHz - 8MHz)/ HIGH_FREQ_RANGE(8MHz - 40MHz)
其他配置项自动计算即可。
PLL配置
System PLL under MCU control:
勾选了之后MCU才能配置PLL
System PLL Enable:
使能PLL
System PLL Divider2:
DIV2分频系数
System PLL Divider1:
DIV1分频系数
System PLL Multiplier:
PLL倍频系数
Mcu SPLL source clock :
PLL的输入时钟源(是能选择SOSC)
外设时钟配置,所有的外设时钟都在此处配置,除了WDG。
时钟参考点,其他模块引用时钟参考点进行时钟频率值的计算。
复位源
通过查看Mcu_Cfg.h
可以看到定义的枚举
/**
* @brief The type Mcu_ResetType, represents the different reset that a specified MCU can have.
* @details The MCU module shall provide at least the values MCU_POWER_ON_RESET and MCU_RESET_UNDEFINED for the enumeration Mcu_ResetType.
*
* @implements Mcu_ResetType_enumeration
*/
typedef enum
{
MCU_STOP_ACKNOWLEDGE_ERROR_RESET = McuConf_McuResetReasonConf_MCU_STOP_ACKNOWLEDGE_ERROR_RESET, /**< @brief Stop Acknowledge Error reset . RCM_SRS[SACKERR]. */
MCU_MDM_AP_SYSTEM_RESET = McuConf_McuResetReasonConf_MCU_MDM_AP_SYSTEM_RESET, /**< @brief MDM-AP System Reset Request . RCM_SRS[MDM_AP]. */
MCU_SW_RESET = McuConf_McuResetReasonConf_MCU_SW_RESET, /**< @brief Software reset . RCM_SRS[SW]. */
MCU_CORE_LOCKUP_RESET = McuConf_McuResetReasonConf_MCU_CORE_LOCKUP_RESET, /**< @brief Core Lockup reset . RCM_SRS[LOCKUP]. */
MCU_JTAG_RESET = McuConf_McuResetReasonConf_MCU_JTAG_RESET, /**< @brief JTAG generated reset . RCM_SRS[JTAG]. */
MCU_POWER_ON_RESET = McuConf_McuResetReasonConf_MCU_POWER_ON_RESET, /**< @brief Power-on reset. RCM_SRS[POR]. */
MCU_EXTERNAL_PIN_RESET = McuConf_McuResetReasonConf_MCU_EXTERNAL_PIN_RESET, /**< @brief External Reset Pin. RCM_SRS[PIN]. */
MCU_WATCHDOG_RESET = McuConf_McuResetReasonConf_MCU_WATCHDOG_RESET, /**< @brief Watchdog reset. RCM_SRS[Watchdog]. */
MCU_CMU_LOSS_OF_CLOCK_RESET = McuConf_McuResetReasonConf_MCU_CMU_LOSS_OF_CLOCK_RESET, /**< @brief CMU Loss-of-Clock Reset. RCM_SRS[CMU_LOC]. */
MCU_LOSS_OF_LOCK_RESET = McuConf_McuResetReasonConf_MCU_LOSS_OF_LOCK_RESET, /**< @brief Loss-of-Lock Reset. RCM_SRS[LOL]. */
MCU_LOSS_OF_CLOCK_RESET = McuConf_McuResetReasonConf_MCU_LOSS_OF_CLOCK_RESET, /**< @brief Loss-of-Clock Reset. RCM_SRS[LOC]. */
MCU_LOW_OR_HIGH_VOLTAGE_DETECT_RESET = McuConf_McuResetReasonConf_MCU_LOW_OR_HIGH_VOLTAGE_DETECT_RESET, /**< @brief Low-Voltage Detect Reset or High-Voltage Detect Reset. RCM_SRS[LVD]. */
MCU_NO_RESET_REASON = McuConf_McuResetReasonConf_MCU_NO_RESET_REASON, /**< @brief No reset reason found */
MCU_MULTIPLE_RESET_REASON = McuConf_McuResetReasonConf_MCU_MULTIPLE_RESET_REASON, /**< @brief More than one reset events are logged except "Power on event" */
MCU_RESET_UNDEFINED = McuConf_McuResetReasonConf_MCU_RESET_UNDEFINED /**< @brief Undefined reset source. */
} Mcu_ResetType;
通过查看Reg_eSys_RCM.h
能够看到复位状态的掩码,在下面的计算器截图中我们可以看到,总的复位状态掩码0x00002FFEU的二进制位与上面手册中一一对应。
/****************************************************/
/*** RCM_SSRS ***/
/****************************************************/
#define RCM_SSRS_RWBITS_MASK32 ((uint32)0x00002FFEU)
因此我们这边在配置的时候,应该根据芯片支持的复位源,并且设置对应的编号
,MCU模块在对复位源做初始化的时候才使能对应的复位源。序号是根据寄存器中的有效位,按照从高位到低位的顺序来设置的(例如SSACKERR
在最高位,那序号为0,可以从后续的查询代码介绍部分,看出这么排序的原因)。芯片复位源一般由芯片厂商规定好了,不需要用户修改,例如下面的复位源都是不可更改不可删除的
。
在McuModeSettingConf
界面中可以增加模式,注意Mode ID
,在程序中切换模式调用的Mcu_SetMode
函数需要传入此参数切换到对应的模式上。
低功耗模式使能配置,Mcu Enter Low-Power Mode:✔
才可以切换到低功耗模式。
在Mcu_SMC_ModeConfig
函数中可以看到,MCU_ENTER_LOW_POWER_MODE
控制低功耗模式的切换。
参考资料:
S32K-RM.pdf - NXP
AUTOSAR_MCAL_MCU_UM[1].pdf - NXP
Cortex M3/M4 权威指南.pdf
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。