最近做项目使用到Cypress 的芯片CY8C4147AZI-S475,使用 PSoC Creator进行项目开发,在调试看门狗时遇到一些问题,在此分享并记录;
CY8C4147AZI-S475的看门狗与一般MCU在使用上有些不同,他可以在自己的中断函数中进行喂狗操作,若不进行相应的操作,则在第三次看门狗计数溢出时,才会产生系统中断;
在使用 PSoC Creator进行开发时,有两种方式进行看门狗的配置。
-
一.在低速时钟设置选项中打开看门狗
周期的选择对看门狗复位时间的影响: -
选择周期1.6,实测2.95S会产生一次复位
-
选择周期819.2ms,实测1.521S会产生一次复位
-
选择周期409.6ms,实测805.629ms会产生一次复位
实测下来,复位时间并不是准确意义上的三倍周期,不知道是不是使用内部时钟的关系;
若不想它进行复位,则在调用**CySysWdtClearInterrupt()**函数进行喂狗:
/*******************************************************************************
* Function Name: CySysWdtClearInterrupt
****************************************************************************//**
*
* \brief
* Feeds the watchdog.
* Cleans the WDT match flag which is set every time the WDT counter reaches a
* WDT match value. Two unserviced interrupts lead to a system reset
* (i.e. at the third match).
*
*******************************************************************************/
void CySysWdtClearInterrupt(void)
{
CY_SYS_SRSS_INTR_REG |= CY_SYS_WDT_LOWER_BIT_MASK;
}
[ ] 二 .图形库+库函数配置
- 添加一个WDT中断全局模块
-
编译会自动生成相对应的库函数
-
编写int函数
/*******************************************************************************
* Function Name : wdtInit
* Description : wdt init
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void WDT_init(void)
{
/*configure WDT ISR*/
wdt_isr_StartEx(isr_wdt);
/*set match vaule*/
CySysWdtWriteMatch(WDT_MATCH_VALUE);
/*set ignore*/
CySysWdtWriteIgnoreBits(0);
/*start WDT*/
CySysWdtEnable();
/*enable wdt interrupt*/
CySysWdtUnmaskInterrupt();
}
其中isr_wdt为看门狗中断入口函数,通过 CY_ISR_PROTO(isr_wdt);
指定;ISO为40k,WDT_MATCH_VALUE
的值为 0x9C40 ,1S溢出一次。
- 编写中断处理函数
/*******************************************************************************
* Function Name : isr_wdt
* Description : wdt interrupt callback
* Input : None
* Output : None
* Return : None
*******************************************************************************/
CY_ISR(isr_wdt)
{
//if( user_resetflag==RTSET_FLAG_ACTIVE)
{
/*Clear watch dog interrupt feed watchdog*/
CySysWdtClearInterrupt();
/*Clear interrupt status in an interrupt controller*/
wdt_isr_ClearPending();
/*reload count num*/
CySysWdtWriteMatch(CySysWdtGetMatch()+WDT_MATCH_VALUE);
}
}
理论上为1s进入一次中断,2次进入中断不处理,第三次就会触发系统中断。把中断里的函数屏蔽掉(即不喂狗),实测下来,3.73S才会进行一次系统复位;
看门狗时间的问题不知道为什么会这样,希望有懂的朋友留言指点。
完整的代码如下:
第一次触发看门狗复位后,后面看门狗中断进行喂狗,不会在触发复位;正常使用中,直接在看门狗中断回调函数里直接喂狗操作即可;
#define bool unsigned char
#define WDT_MATCH_VALUE 0x9C40
#define RTSET_FLAG_ACTIVE 0x0001
enum
{
false,
true
};
/*******************************************************************************
* Function Name : wdtInit
* Description : wdt init
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void WDT_init(void)
{
/*configure WDT ISR*/
wdt_isr_StartEx(isr_wdt);
/*set match vaule*/
CySysWdtWriteMatch(WDT_MATCH_VALUE);
/*set ignore*/
CySysWdtWriteIgnoreBits(0);
/*start WDT*/
CySysWdtEnable();
/*enable wdt interrupt*/
CySysWdtUnmaskInterrupt();
}
/*******************************************************************************
* Function Name : isr_wdt
* Description : wdt interrupt callback
* Input : None
* Output : None
* Return : None
*******************************************************************************/
CY_ISR(isr_wdt)
{
if( user_resetflag==RTSET_FLAG_ACTIVE)
{
/*Clear watch dog interrupt feed watchdog*/
CySysWdtClearInterrupt();
/*Clear interrupt status in an interrupt controller*/
wdt_isr_ClearPending();
/*reload count num*/
CySysWdtWriteMatch(CySysWdtGetMatch()+WDT_MATCH_VALUE);
}
}
/*******************************************************************************
* Function Name : user_test_reset
* Description : test reset of wdt
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void User_test_reset(void)
{
if(CY_SYS_RESET_WDT==CySysGetResetReason(CY_SYS_RESET_WDT))
{
user_resetflag=RTSET_FLAG_ACTIVE;
Application_LED_Control(true);
CyDelay(2000);
Application_LED_Control(false);
}
else
{
Application_LED_Control(true);
}
}
int main(void)
{
CyGlobalIntEnable; /* Enable global interrupts. */
/* Place your initialization/startup code here (e.g. MyInst_Start()) */
User_test_reset();
WDT_init();
for(;;)
{
/* Place your application code here. */
Application_LED_Control(false);
}
}