我们利用的MCU是普冉的PY32F030,这颗芯片在低功耗运用处景下,利用看门狗会有很多的问题和毛病,须要非常把稳,稍有不慎,就会出问题。
关于看门狗在低功耗场景下的运用,几个问题点可以提前思考一下:

看门狗的分类,根据实现办法的不同,可以分为软件看门狗和硬件看门狗:
软件看门狗:通过软件实现的一种机制,常日由系统中的软件来设置和管理硬件看门狗: 嵌入在处理器或芯片中的专用硬件模块根据利用办法的不同,又可以区分为独立看门狗和窗口看门狗
独立看门狗: 独立看门狗常日用于监控全体系统的运行状态,而不特定于某个任务或进程,当系统故障,去世锁,无相应的时候,运用程序无法进行正常喂狗,看门狗超时从而产生复位。窗口看门狗: 窗口看门狗更专注于监控特界说务或进程的运行状态,并在特定的韶光窗口内完成。比如在某个任务中,它的实行韶光哀求非常高,可以利用窗口看门狗,它有一个韶光窗口,如果太早喂狗和太晚喂狗,都会产生非常,正由于它喂狗韶光有个韶光窗口,以是才叫窗口看门狗。我利用的普冉PY32F030系列MCU,它是32位Cortex-M0+的内核,里面带有一个独立看门狗IWDG和一个窗口看门狗WWDG。
个中,独立看门狗和窗口看门狗,还有软件和硬件的差异,紧张差异是在看门狗的启动办法上不同。下面我们的先容,紧张针对独立看门狗。
(二)启动看门狗
看门狗的启动有多种办法:
通过接口设置启动直接设置寄存器启动设置选项字节启动(1)通过接口设置这里可以直接参考官方sample进行初始化:
IWDG_HandleTypeDef IwdgHandle; HAL_Init(); /##-3- Configure & Start the IWDG peripheral #########################################/ IwdgHandle.Instance = IWDG; IwdgHandle.Init.Prescaler = IWDG_PRESCALER_32;//T=1MS IwdgHandle.Init.Reload = (1000); //1ms1000=1s IwdgHandle.Init.Window = IWDG_WINDOW_DISABLE; if(HAL_IWDG_Init(&IwdgHandle) != HAL_OK) { / Initialization Error / Error_Handler(); }
这里须要特殊把稳,由于IWDG是依赖于LSI时钟的,也便是在HAL_IWDG_Init 函数调用之前,必须先打开LSI时钟。
官方给的sample中,是在HAL_Init()中把LSI时钟打开了。当你把上面这段代码移植到你自己工程上,如果你LSI没有开启,或者是在HAL_IWDG_Init后面才开LSI时钟,你调用HAL_IWDG_Init就会一贯失落败,系统一贯ERROR,全体MCU会启动不了。
(2)通过寄存器直接设置直接往 IWDG_SR,IWDG_RLR,IWDG_KR三个寄存器地址写入对应的参数,使能IWDG
void init_wtd(void){volatileu int32_t IWDG_KR_ADDR = (volatileuint32_t )0x40003000UL;volatileu int32_t IWDG_PR_ADDR = (volatileuint32_t )0x40003004UL;volatileu int32_t IWDG_RLR_ADDR = (volatileuint32_t )0x40003008UL;IWDG_KR_ADDR = 0x5555;IWDG_PR_ADDR = 0x03;IWDG_RLR_ADDR = 0xF40;}
实际IWDG是有四个寄存器,还有一个IWDG_PR,它与前面一样,如果不初始化时钟,看门狗会启动不了,就算是设置了,看门狗也是不会启动。
如果要使能时钟,可以添加时钟设置语句:
SET_BIT(RCC->CSR, RCC_CSR_LSION);
直接设置寄存器有一个好处,便是在boot中, 由于对代码量哀求比较高,可以比较精简的实现功能
(3)通过选项字节配置MCU上内部有一个小的flash,里面有个FLASH user option,在这里面可以设置MCU的一些配置参数
这个参数是可以通过烧录器在烧录的时候就把参数配置进去,对付已经烧录的设备,可以通过写选项字节的办法把IWDG_SW置位或是清零。
void Option_config_NRST_to_gpio_hwwdg(void){FLASH_OBProgramInitTypeDef OBInitCfg;/ Reset of all peripherals, Initializes the Flash interface and the Systick. // 初始化flash擦写韶光参数 /HAL_FLASH_Init(FLASH_PROGRAM_ERASE_CLOCK_8MHZ);/ 获取option bytes数据 /HAL_FLASHEx_OBGetConfig(&OBInitCfg);//配置Nreset为GPIOif(((OBInitCfg.USERConfig & OB_RESET_MODE_GPIO) != OB_RESET_MODE_GPIO)||((OBInitCfg.USERConfig & OB_IWDG_SW) == OB_IWDG_SW)){/ 修正 USER(RESET , WWDG, IWDG) 配置值 , 把稳一定要3个一起配置/OBInitCfg.OptionType = OPTIONBYTE_USER;MODIFY_REG(OBInitCfg.USERConfig, (OB_RESET_MODE_GPIO|OB_WWDG_SW|OB_IWDG_SW), (OB_RESET_MODE_GPIO | OB_WWDG_SW | OB_IWDG_HW));/ 启动option byte编程 /HAL_FLASHEx_OBProgram(&OBInitCfg);/ 产生一个复位,option byte装载 /HAL_FLASH_OB_Launch(); }}
通过选项字节配置了硬件看门狗之后,芯片会自动开启LSI时钟,这个时候,软件要关闭LSI时钟是关闭不了的。
软件独立看门狗与硬件独立看门狗的差异:
软件独立看门狗通过软件初始化,可以通过关闭时钟的办法把它关闭了如果在设备上电到看门狗初始化之前系统非常了,看门狗是不生效的,这种情形比较多的涌如今软件初始化的时候非常卡去世。硬件独立看门狗通过烧录器烧录的时候配置,或者是通过软件程序,修正选项字节里面参数进行修正硬件独立看门狗一但配置上,它从上电的时候就会开始生效,停滞不了,除非重新修正配置项参数。硬件独立看门狗开启之后,LSI时钟会自动开启,并且关闭不了。(三)休眠唤醒喂狗在低功耗设备中,MCU更加多的时候是在深度就寝的模式,以达到省功耗的目的。在深度休眠模式下,看门狗还是在正常运行的。
也便是说,在深度休眠模式下,还是须要定时唤醒设备进行喂狗,喂完狗之后,设备再重新进入休眠。
(1)常规办法官方补充文档上有先容,在PY32F030、PY32F003、PY32F002A系列上,在休眠前,须要进行下面几个操作:
关闭非唤醒源中断关闭系统滴答 HAL_SuspendTick();担保RTC稳定 while(RTC->DIVL<2);实际在利用的时候,我们比较常用的办法是,利用RTC的秒中断,在休眠的时候,每秒唤醒一下设备,然后进行喂狗操作,末了再休眠下去。
(2)非常情形实际测试的时候创造,在普冉030利用RTC唤醒喂狗的办法,随着韶光的推移,设备会涌现非常导致看门狗复位。
我们升级五百台设备,24小时内,会有几台设备偶尔涌现该问题,36小时后,大部分的设备基本上都会涌现这个非常。
普冉官方的阐明是,它们RTC作为唤醒源确实是会存在这个问题,没有好的办理方案,只能是改用LPTIM来做唤醒源。涌现这类问题的根本缘故原由是如果休眠的stop指令与唤醒源中断同一韶光触发,那么他们芯片就会挂去世。
实际利用的时候,利用LPTIM的办法,还是会存在上面的内容,只是涌现的概率会比较低而已。
(3)补救方案上面的非常情形,是设备在产线上才创造的,那要怎么解?客户肯定也是接管不了这种频繁重启的情形,特殊是在低功耗设备上。
末了的办法是将RAM进行分区,分出一个IRAM2区,将一些状态位保存在IRAM2区,该区启动的时候不进行初始化,看门狗复位的时候,该区的数据也不会被打消掉。
如果是检测到看门狗非常导致的复位,可以通过保存在状态位信息规复到复位前的状态。
利用IRAM2区不初始化的办法须要把稳一点:如果程序分为boot和app两个部分,须要在boot和app上同时设置该区域,否则可能在boot运行阶段,IRAM2区的数据就被打消掉了。
结尾针对普冉PY32F030 MCU,如果要利用独立看门狗,须要把稳几点:
最好是在烧录的时候就直接配置启动硬件看门狗不要利用RTC作为休眠唤醒源进行喂狗最好预留一个IRAM分区,以备时时之需有些坑,没踩之前并不知道这是一个坑,对付做嵌入式运用软件的工程师而言,他并不知道芯片设计上会存在什么样的毛病。
如果一颗芯片,价格比别人便宜很多倍,那么在利用的时候就须要特殊把稳了,为啥它可以做到这么便宜?是不是哪里有坑我们不清楚?就算韶光再紧急,最好也要小批量试产之后才能批量利用。
---------------------------End---------------------------
如需获取更多内容
请关注liwen01"大众年夜众号









