S32K1xx MCAL之Wdg模块配置——实现系统可靠复位
目录一、Wdg模块核心原理1.1 传统看门狗 vs MCAL Wdg1.2 Wdg模块的三种工作模式1.3 Wdg与GPT的协作机制二、EB tresos详细配置步骤2.1 时钟配置Mcu模块2.2 Gpt模块配置关键步骤2.3 Wdg模块核心配置2.4 与GPT的关联配置三、代码实现四、测试4.1 正常喂狗测试4.2 不进行喂狗在嵌入式系统中看门狗Watchdog是保障系统稳定运行的最后一道防线。当程序跑飞、死循环或关键任务被阻塞时看门狗能够及时复位系统将设备恢复到可控状态。对于S32K1xx系列芯片AUTOSAR架构下的Wdg模块与普通看门狗有一个关键区别它不直接在代码中喂狗而是通过GPT定时器中断自动完成喂狗操作。这种设计使得上层应用只需调用Wdg_SetTriggerCondition()更新超时时间即可实现任务监控大大简化了应用层的喂狗逻辑。本文将基于EB tresos Studio工具手把手完成S32K1xx MCAL Wdg模块的完整配置并解析其独特的“GPTWdg”协作机制教你如何实现系统可靠复位。一、Wdg模块核心原理1.1 传统看门狗 vs MCAL Wdg传统看门狗的使用方式非常简单在代码中周期性地调用喂狗函数。但如果程序跑飞后恰好执行到了喂狗函数看门狗就失去了防护作用。AUTOSAR MCAL的Wdg模块采用了一种更安全的设计Wdg模块与Gpt模块协作喂狗操作由GPT定时器中断自动完成。工作流程如下Wdg初始化时会启动一个GPT定时器通道GPT定时器周期产生中断在中断服务函数中执行喂狗操作上层应用需要周期调用Wdg_SetTriggerCondition()更新超时时间如果超时时间耗尽即上层长时间未调用该函数GPT将停止喂狗WDOG超时复位系统这种设计的核心优势喂狗操作不在主程序路径上即使主程序跑飞也无法“意外喂狗”。同时应用层只需关注“是否及时调用Wdg_SetTriggerCondition()”而不必关心底层喂狗时序。1.2 Wdg模块的三种工作模式Wdg模块支持三种工作模式通过Wdg_SetMode()切换1.3 Wdg与GPT的协作机制这是AUTOSAR Wdg模块的核心设计理解它才能正确配置和使用Wdg_au32GptPeriodGPT定时器的喂狗周期由EB配置自动计算Wdg_au32Timeout用户通过Wdg_SetTriggerCondition()设置的当前剩余超时时间逻辑流程每次GPT中断触发时检查Wdg_au32Timeout是否大于Wdg_au32GptPeriod如果是执行喂狗并将Wdg_au32Timeout减去Wdg_au32GptPeriod如果不是停止GPT定时器等待WDOG超时复位这意味着上层应用需要在Wdg_au32Timeout耗尽之前调用Wdg_SetTriggerCondition()给它“续命”。二、EB tresos详细配置步骤2.1 时钟配置Mcu模块Wdg模块需要选择合适的时钟源。S32K1xx的WDOG支持多种时钟源推荐使用LPO128kHz 作为看门狗时钟。进入Mcu模块设置FTM0外设时钟源为SIRC时钟频率为8MHzS32K118 SIRC时钟频率为8M。注意需要确保GPT模块的时钟正确——因为Wdg依赖GPT。这里使用FTM0作为GPT定时器喂狗通道。进入MCU时钟参考配置增加Wdg和FTM0模块时钟配置2.2 Gpt模块配置关键步骤Wdg需要依赖GPT来执行喂狗操作因此必须先配置GPT。使能FTM_0作为GPT喂狗硬件通道添加GPT时钟参考点添加一个GPT通道如GptChannelConfiguration_Wdg专门用于Wdg喂狗GptChannelMode配置为GPT_CH_MODE_CONTINUOUS连续模式GptChannelTickFrequency根据64分频计算得到125KhzGptChannelNotification填写Wdg_Cbk_GptNotification0——这是Wdg模块期望的回调函数名必须完全一致⚠️ 关键提醒在Gpt模块中配置的回调函数名必须是Wdg_Cbk_GptNotification0。如果名称不匹配Wdg模块将无法收到GPT中断通知喂狗不会执行。2.3 Wdg模块核心配置general配置主要配置初始化超时时间调用Wdg_Init()时设置的初始超时时间应大于WdgTimeoutPeriod因为这是给上层应用第一次调用Wdg_SetTriggerCondition()的缓冲时间。最大超时时间调用Wdg_SetTriggerCondition()时允许设置的最大超时值。在WdgSettingsConfig添加一个配置General中配置Wdg默认模式初始化后进入的模式选择Wdg喂狗触发源使能Wdg中断。Wdg模块支持配置SLOW和FAST两套独立的参数这里只使用到SLOW模式时钟源选择WdgClockSelection选择LPO_CLK约128kHz超时时间配置WdgTimeoutPeriod这是WDOG硬件的实际超时时间这里配置为0.1即100ms。不使用窗口模式。使能Debug Mode允许看门狗计数器在调试Debug模式下继续工作断点触发或单步执行时看门狗继续计时不会因CPU暂停而停止。方便验证看门狗功能模拟真实运行环境测试看门狗是否能按预期超时并触发复位。2.4 与GPT的关联配置Wdg模块会自动根据以下参数计算GPT的喂狗周期公式GPT喂狗周期 窗口周期 (超时时间 - 窗口周期) / 2或者更简单地说MCAL代码会计算出一个介于窗口起始点和超时点之间的时间作为喂狗周期。关键依赖Wdg的GptChannel引用必须指向第2.2节中配置的GPT通道。三、代码实现由于Wdg依赖GPT初始化顺序至关重要必须先初始化GPT再初始化Wdg主循环中的超时更新这是应用层最关键的接口周期调用Wdg_SetTriggerCondition()来延长超时时间。代码实现如下#includeS32K118.h#includes32_core_cm0.h#includeMcu.h#includePort.h#includeDio.h#includeGpt.h#includeMcal.h#includeCDD_Mcl.h#includeCan.h#includeWdg.h#includeS32K118_features.h#defineEnable_Wdg#ifdefined(__ghs__)#define__INTERRUPT_SVC__interrupt#define__NO_RETURN_Pragma(ghs nowarning 111)#elifdefined(__ICCARM__)#define__INTERRUPT_SVC__svc#define__NO_RETURN_Pragma(diag_suppressPe111)#elifdefined(__GNUC__)#define__INTERRUPT_SVC__attribute__((interrupt(SVC)))#define__NO_RETURN#else#define__INTERRUPT_SVC#define__NO_RETURN#endif#defineS32K11x_SERIES1/** S32_NVIC - Size of Registers Arrays */#defineS32_NVIC_ISER_COUNT1u#defineS32_NVIC_ICER_COUNT1u#defineS32_NVIC_ISPR_COUNT1u#defineS32_NVIC_ICPR_COUNT1u#defineS32_NVIC_IPR_COUNT8u/** S32_NVIC - Register Layout Typedef */typedefstruct{__IOuint32_tISER[S32_NVIC_ISER_COUNT];/** Interrupt Set Enable Register, array offset: 0x0, array step: 0x4 */uint8_tRESERVED_0[124];__IOuint32_tICER[S32_NVIC_ICER_COUNT];/** Interrupt Clear Enable Register, array offset: 0x80, array step: 0x4 */uint8_tRESERVED_1[124];__IOuint32_tISPR[S32_NVIC_ISPR_COUNT];/** Interrupt Set Pending Register, array offset: 0x100, array step: 0x4 */uint8_tRESERVED_2[124];__IOuint32_tICPR[S32_NVIC_ICPR_COUNT];/** Interrupt Clear Pending Register, array offset: 0x180, array step: 0x4 */uint8_tRESERVED_3[380];__IOuint32_tIPR[S32_NVIC_IPR_COUNT];/** Interrupt Priority Register n, array offset: 0x300, array step: 0x4 */}S32_NVIC_Type,*S32_NVIC_MemMapPtr;#defineS32_NVIC_BASE(0xE000E100u)/** Peripheral S32_NVIC base pointer */#defineS32_NVIC((S32_NVIC_Type*)S32_NVIC_BASE)/** Array initializer of S32_NVIC peripheral base addresses */#defineS32_NVIC_BASE_ADDRS{S32_NVIC_BASE}/** Array initializer of S32_NVIC peripheral base pointers */#defineS32_NVIC_BASE_PTRS{S32_NVIC}#defineFEATURE_NVIC_PRIO_BITS(2U)externuint32_t__VECTOR_RAM[((uint32_t)(LPUART0_RxTx_IRQn))16U1U];externuint32_t__VECTOR_TABLE[((uint32_t)(LPUART0_RxTx_IRQn))16U1U];externuint32_t__DATA_ROM[];externuint32_t__DATA_END[];typedefvoid(*isr_t)(void);voidINT_SYS_EnableIRQ(IRQn_Type irqNumber){S32_NVIC-ISER[(uint32_t)(irqNumber)5U](uint32_t)(1UL((uint32_t)(irqNumber)(uint32_t)0x1FU));}voidINT_SYS_InstallHandler(IRQn_Type irqNumber,constisr_tnewHandler,isr_t*constoldHandler){constuint32_t*aVectorRam(uint32_t*)__VECTOR_RAM;constuint32_t*aVectorTable(uint32_t*)__VECTOR_TABLE;constuint32_t*aDataRom(uint32_t*)__DATA_ROM;constuint32_t*aDataRam(uint32_t*)__DATA_END;if((aVectorRam!aVectorTable)||(aDataRomaDataRam)){uint32_t*pVectorRam(uint32_t*)__VECTOR_RAM;/* Save the former handler pointer */if(oldHandler!(isr_t*)0){*oldHandler(isr_t)pVectorRam[((int32_t)irqNumber)16];}pVectorRam[((int32_t)irqNumber)16](uint32_t)newHandler;}}voidINT_SYS_SetPriority(IRQn_Type irqNumber,uint8_tpriority){uint8_tshift(uint8_t)(8U-FEATURE_NVIC_PRIO_BITS);if((int32_t)irqNumber0){uint32_tintVectorId((uint32_t)(irqNumber)0xFU);uint32_tregIdintVectorId/4U;/* Compute pointer to SHPR register - avoid MISRA violation. */#ifdefined(S32K11x_SERIES)volatileuint32_t*shpr_reg_ptr((regId2U)?(volatileuint32_t*)S32_SCB-SHPR2:(volatileuint32_t*)S32_SCB-SHPR3);uint8_tpriByteShift(uint8_t)(((uint8_t)(intVectorId)0x3U)3U);/* Clear the old value from the register */*shpr_reg_ptr~(0xFFULpriByteShift);/* Set Priority for Cortex-M0P System Interrupts */*shpr_reg_ptr|((uint32_t)(((((uint32_t)priority)shift))0xFFUL))priByteShift;#elsevolatileuint8_t*shpr_reg_ptr((regId1U)?(volatileuint8_t*)S32_SCB-SHPR1:((regId2U)?(volatileuint8_t*)S32_SCB-SHPR2:(volatileuint8_t*)S32_SCB-SHPR3));/* Set Priority for Cortex-M4 System Interrupts */shpr_reg_ptr[intVectorId%4U](uint8_t)(((((uint32_t)priority)shift))0xffUL);#endif/* defined (S32K11x_SERIES) */}else{/* Set Priority for device specific Interrupts */#ifdefined(S32K11x_SERIES)uint32_tiprVectorId(uint32_t)(irqNumber)2U;uint8_tpriByteShift(uint8_t)((((uint8_t)irqNumber)0x3U)3U);/* Clear the old value from the register */S32_NVIC-IPR[iprVectorId]~(0xFFULpriByteShift);S32_NVIC-IPR[iprVectorId]|((uint32_t)(((((uint32_t)priority)shift))0xFFUL))priByteShift;#elseS32_NVIC-IP[(uint32_t)(irqNumber)](uint8_t)(((((uint32_t)priority)shift))0xFFUL);#endif/* defined (S32K11x_SERIES) */}}voidCan_TxMessage(void){Can_PduType TxPdu;uint8 TxMessage[8]{0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};TxPdu.id0x456;TxPdu.swPduHandle0;TxPdu.length8;TxPdu.sdu(uint8*)TxMessage[0];Can_Write((Can_HwHandleType)CanHardwareObject_TX,(Can_PduType*)TxPdu);}voidTask_10ms(void){Dio_FlipChannel(DioConf_DioChannel_PTC_6);#ifdefEnable_WdgWdg_SetTriggerCondition(100);#endif}voidWdg_IsrNotification0(void){Wdg_SetTriggerCondition(100);}uint8CAN_PdurReceiveCallout(void){returnTRUE;}voidCan_ErrorNotification(void){uint32 i0;i;}externISR(LPIT_0_ISR);externISR(FTM_0_ISR);externISR(Wdg_Wdog0_Isr);intmain(void){/* module init */Mcu_Init(Mcu_Config);Mcu_InitClock(0U);Port_Init(Port_Config);Mcl_Init(Mcl_Config);Gpt_Init(Gpt_Config);Can_Init(Can_Config);#ifdefEnable_WdgWdg_Init(Wdg_Config);Wdg_SetTriggerCondition(100);#endif/* Gpt Enable */Gpt_StartTimer(GptConf_GptChannelConfiguration_GptChannelConfiguration_10msTask,240000);Gpt_EnableNotification(GptConf_GptChannelConfiguration_GptChannelConfiguration_10msTask);Can_SetControllerMode(CanConf_CanController_CanController_0,CAN_CS_STARTED);#ifdefEnable_WdgWdg_SetMode(WDGIF_SLOW_MODE);#endifINT_SYS_SetPriority(LPIT_IRQn,3);#ifdefEnable_WdgINT_SYS_SetPriority(FTM0_Ch0_Ch7_IRQn,2);INT_SYS_SetPriority(WDOG_IRQn,1);#endif/* Interrupt Enable */INT_SYS_EnableIRQ(LPIT_IRQn);INT_SYS_InstallHandler(LPIT_IRQn,LPIT_0_ISR,NULL_PTR);#ifdefEnable_WdgINT_SYS_EnableIRQ(FTM0_Ch0_Ch7_IRQn);INT_SYS_InstallHandler(FTM0_Ch0_Ch7_IRQn,FTM_0_ISR,NULL_PTR);INT_SYS_EnableIRQ(WDOG_IRQn);INT_SYS_InstallHandler(WDOG_IRQn,Wdg_Wdog0_Isr,NULL_PTR);#endif/* CAN TX message */Can_TxMessage();while(1){Can_MainFunction_Mode();Can_MainFunction_Write();Can_MainFunction_Read();Can_MainFunction_BusOff();}}代码中main函数中主要完成模块初始化中断优先级设置非常重要否则可能会出现GPT中断触发失败使能相关中断。通过GPT中10ms任务周期喂狗防止系统超时复位。四、测试4.1 正常喂狗测试Task_10ms中周期翻转PTC6引脚电平并喂狗。黄色为MCU复位脚波形蓝色为PTC6脚波形可以看到没有复位PTC6脚10ms周期翻转。4.2 不进行喂狗Task_10ms中周期翻转PTC6引脚电平不进行喂狗。黄色为MCU复位脚波形蓝色为PTC6脚波形可以看到有复位信号在复位时PTC6脚翻转异常。voidTask_10ms(void){Dio_FlipChannel(DioConf_DioChannel_PTC_6);#ifdefEnable_Wdg//Wdg_SetTriggerCondition(100);#endif}如果觉得本文对你有帮助欢迎点赞、收藏、评论交流下一篇预告《S32K1xx MCAL之Pwm模块配置——实现精准占空比与频率控制》 版权声明本文为原创技术分享内容基于实际项目经验整理。如转载需注明出处。