我正在寻找一些在Bootloader中处理死人定时器和看门狗定时器的技巧和建议。我的情况如下:我使用PIC32 MZ2048 EFM144@ 200 MZZySyl CLKYFRQ。我的应用程序基于和声2.03B。它由一个主循环组成,它为异步外围设备提供服务。以阻塞的方式。这包括文件处理和MICROSD、TCPIP栈与Web服务器、通过SPI的EEPROM、通过QSPI的闪存。但是应用程序的主要组件是一个时间关键中断,它被称为每20ms,并完成主要功能。当访问主循环和中断之间共享的资源时,主循环禁用一些指令的中断。CONFIG(用MHC设置)是这样的:到目前为止,我使用Windows模式下的死人定时器监视中断。它被设置为具有打开窗口的16的除数的DMT22。这给出了大约19661毫秒关闭窗口,然后1311毫秒打开窗口,导致2097 2ms超时。这就足够了中断来完成它的工作了。我在中断开始时调用CurnStest1,在中断结束时调用CeleS
tist2。它被设置为PS1684和窗口时间为50%。这给出了8192MS的闭合窗口和8192MS的打开窗口,从而导致超时16164MS。在主回路中的一个点上,我读取100MHz核心定时器,并且在上次重置后超过1228个毫秒时,我清除了看门狗。第一次重置将在1228800000个核心定时器周期之后完成(参见下面的代码)。这就使得主循环完成大约4秒。我已经看到SD卡有时需要大约2秒。这就是为什么我有这么大。这个设置已经很好地为应用程序,我想保持它。但是,现在,一个引导加载程序被创建。不幸的是,它被创建了许多阻塞循环,等待一些东西。为了发展,Deadman Timer和看门狗定时器都关闭了。到目前为止,引导加载程序运行并能够进行固件更新。现在我想再次启用死人定时器和看门狗定时器。现在我的主要问题是,如何处理这个问题。当然,一种方法是将这两个残疾人放在引导加载程序中,并在主应用程序启动时用软件启用它们。但实际上我更喜欢在设备配置中使用它。这里有几个问题:-引导加载程序有很多阻塞循环。完全改变它将是很好的,但它目前不是我的选择。-当引导装载器移交应用程序时,时间必须适合,所以应用程序将击中监视器和死人定时器窗口的第一个明确的命令正确。目前,我的想法是创建20MS INTE。用于引导加载程序的RURBT。幸运的是,我能做到这一点,因为中断在Bootloader中总是启用的,除了很短的时间(只有几个指令)。在这20毫秒的中断中,我将以与应用程序类似的方式清除死人和看门狗定时器(例如,每12300毫秒)。当移交给应用程序时,BooDoad主代码将等待最后一次20MS中断发生。然后,它将操纵核心定时器,并将其设置为经过的时间,因为最后一个看门狗清除。然后交给应用程序。在移交给应用程序之前的点将是Bootloader和应用程序中唯一可以处理核心定时器的地方。20MS中断的最后调用将允许应用程序正确地继续20MS间隔。而核心定时器的操作将允许应用程序在正确的时间点完成看门狗定时器的第一次清除。这对你有意义吗?或者你将如何处理这个问题?
以上来自于百度翻译
以下为原文
I'm looking for some tips and recommendations for handling a deadman timer and a watchdog timer in a bootloader.
My situations is a following:
I'm using a PIC32MZ2048EFM144 @ 200MHz SYS_CLK_FREQ. My application is based on H
ARMony 2.03b.
It consists of a main loop, which serves asynchronous peripherals in a blocking way. This includes file handling and microSD, TCPIP stack with web server, an EEPROM via SPI, an Flash via QSPI. But the main component of the application is a time critical interrupt, which is called every 20ms and doing the main functionality. When accessing resources which are shared between main loop and interrupt, then the main loop disables the interrupt for a few instructions.
Config (set with MHC) is like this:
/*** DEVCFG1 ***/
#pragma config FNOSC = SPLL
#pragma config DMTINTV = WIN_15_16
#pragma config FSOSCEN = OFF
#pragma config IESO = OFF
#pragma config POSCMOD = EC
#pragma config OSCIOFNC = OFF
#pragma config FCKSM = CSECME
#pragma config WDTPS = PS16384
#pragma config WDTSPGM = STOP
#pragma config FWDTEN = ON
#pragma config WINDIS = WINDOW
#pragma config FWDTWINSZ = WINSZ_50
#pragma config DMTCNT = DMT22
#pragma config FDMTEN = ON
So far I'm using a Deadman Timer in window mode for monitoring the interrupt. It is set to DMT22 with an divisor of 16 for the open window. This gives about 19,661 ms closed window, then 1,311 ms open window, resulting in 20,972ms for the timeout. This is enough for the interrupt to do its job. I'm calling ClearStep1 at the beginning of the interrupt and ClearStep2 at the end of the interrupt.
Also I'm using a watchdog timer with window mode for the main loop. It is set to PS16384 and a window time of 50%. This gives a closed window of 8192ms and an open window of 8192ms, resulting in 16384ms for the timeout. At one point in the main loop I read the 100MHz core timer, and I clear the watchdog when more than 12288ms have been passed since the last reset. The first reset will be done after 1228800000 core timer cycles (see code below). So this leaves about 4 seconds for a main loop to do its stuff. I have already seen that the SD card sometimes might take about 2 seconds. That's why I have it so huge.
// watch dog time out: 16384 ms
// watch dog window size: 50%
// watch dog open/closed window: 8192 ms
// targeted reset time for watch dog: 3/4 * 16384 ms = 12288 ms
// number of clock cycles till reset:
// 16384ms / 1000ms/s * 3/4 * 100000000 cyc/s
// overflow of core timer: 2^32 = 4294967296 = ~ 42,9 s
#define TS_WTD_TILL_NEXT_RESET 1228800000
uint32_t const TS_now = ReadCoreTimer();
if ((int32_t)(TS_now - TS_wtd_next_reset) > 0) {
SYS_WDT_TimerClear();
TS_wtd_next_reset = TS_now + TS_WTD_TILL_NEXT_RESET;
}
This setup has worked very well for the application and I would like to keep it.
However, now a bootloader was created. Unfortunately it was created with many blocking loops, which wait for something. For the development both Deadman Timer and Watchdog Timer were turned off. So far the bootloader works and is able to do firmware updates. Now I would like to enable Deadman Timer and Watchdog Timer again. And the main question for me is now, how to handle this.
One way of course would be to leave these two disabled for the bootloader, and enable them by software, when the main application starts. But actually I would prefer to have it in the device config.
There are several problems with this:
- The bootloader has a lot of blocking loops. Changing it completely would be nice, but it is currently no option for me.
- When the bootloader hands over the application, the timing must fit, so the application will hit the windows of watchdog and deadman timer with its first clear commands correctly.
Currently, my idea is to create a 20ms interrupt for the bootloader. Fortunately I can do this, because interrupts are always enabled in the bootloader, except for very short amounts of time (just a few instructions). In this 20ms interrupt I would clear both deadman and watchdog timer (e.g. every 12300ms) in a similar way as in the application.
When handing over to the application, the boodloader main code would wait for a last 20ms interrupt to happen. Then it would manipulate the core timer and set it to the passed time, since the last watchdog clear. And then hand over to the application. The point just before handing over to the application would be the only place in both bootloader and application where I would manipulate the core timer. The last call of the 20ms interrupt would allow the application to continue with the 20ms intervals correctly. And the manipulation of the core timer would allow the application to do the first clear of the watchdog timer at the correct point in time.
Does this make any sense to you?
Or how would you handle this issue?
0