dbuezas / lgt8fx

Board Package for Logic Green LGT8F328P LGT8F328D and LGT8F88D
359 stars 90 forks source link

The WDT issue. #263

Closed LaZsolt closed 1 year ago

LaZsolt commented 1 year ago

As @wollewald mentioned in his article most of the LGT8F328P have Watchdog error. This error causes that the watchdog interrupt not working and jumping to the reset vector instead. So with this error the watchdog timer is mainly useful only for watchdog reset.

It is possible to create a code snippet in the init procedure which detecting the WDT error. If the error exist it is detectable trough WDIF bit. If no WDT interrupt error in the chip the WDIF bit will be cleared by WDT interrupt and no jump to reset vector. At the end a flag can be set for a user can see if the chip is faulty.

dbuezas commented 1 year ago

That's clever! We can fix it in the core.

wollewald commented 1 year ago

Sounds good! Thank you for following up on this topic.

LaZsolt commented 1 year ago

a flag can be set for a user can see if the chip is faulty.

I changed my mind. It is not necessary to set a signal, but restore WDT interrupt capability by software.

If this function below inserted into main.cpp the WDT interrupt capability will be restored. The only difference is the WDT interrupt + reset function will be longer about 64 ms. This process not tested on 328D yet. I will test it on 328D today.

#if defined(__LGT8FX8P__)
void softRepairedWdtIsr(void) __attribute__ ((naked)) __attribute__ ((used)) __attribute__ ((section (".init0")));
void softRepairedWdtIsr(void)
{
    uint8_t tmpwsr = WDTCSR;
    if (tmpwsr & ( (1 << WDIF))) {
        if (tmpwsr & ( (1 << WDIE))) {
            tmpwsr &= ~(1 << WDIE);
            WDTCSR = tmpwsr;
            WDTCSR = tmpwsr | (1 << WDIF);
            // WDT interrupt
            __asm__ __volatile__ ("jmp __vector_6 \n");
        }
        // WDT interrupt then system reset.
        __asm__ __volatile__ ("call __vector_6 \n");
        WDTCSR = (1 << WDE) | (1 << WDCE);
        WDTCSR = (1 << WDE);
        while(1);
    }
}
#endif
LaZsolt commented 1 year ago

If this function below inserted into main.cpp the WDT interrupt capability will be restored.

It is better to include it in WDT.h because there will be no wasted FLASH space when the Watchdog timer not in use.

LaZsolt commented 1 year ago

Ohhh. Must save and restore SREG before jumping to WDT ISR ( __vector_6 ).

LaZsolt commented 1 year ago

And some registers. But because I don't know which registers the compiler put there, all of the above must be written in assembler language.

LaZsolt commented 1 year ago

Done. I finished the better watchdog timer library. Pls try it: https://github.com/dbuezas/lgt8fx/tree/Better_wdt_lib/lgt8f/libraries/WDT

wollewald commented 1 year ago

@LaZsolt, you are a hero! I tried the wdt_interrupt sketch and it's working perfect.

In particular, I was missing the ISR to be able to perform actions before the reset. For example, that could be saving data to the EEPROM which can help to find the reason for the WDT reset. wdt_ienable() does not trigger a reset, but if wdt_ienable(WTO_4S) in line 34 is changed to wdt_enable(WTO_4S); I get exactly what I wanted (ISR + reset).

Screenshot 2023-04-15 120103

Great thanks - I will modify this section my blog post.

dbuezas commented 1 year ago

That's great! @LaZsolt would you open a PR so it gets auto deployed after we merge?

LaZsolt commented 1 year ago

Okay, but a bit later. I would like to finish the LowPower library and after that I will open PR.

LaZsolt commented 1 year ago

This issue is solved with is PR: https://github.com/dbuezas/lgt8fx/pull/274