problem using FF 16 bit counter as watchdog

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
PeSi_1583586
Level 3
Level 3
10 replies posted 10 questions asked 5 replies posted

I have a project using a PSoC5LP device compiled using PSoCCreater 4.2.

I am trying to use a fixed function Counter component as a watchdog timer. The counter generates an interrupt when the counter reaches its terminal count which generates a software reset.

I have named the counter 'Fido'. I call Fido_Start() at the start of my program, and periodically call Fido_WriteCounter(1200) to reset the counter to 1200 thus preventing it from reaching the terminal count and generating a reset unless the program crashes, in which case the counter will not be set to 1200, but will continue to count down to zero and generate an interrupt.

When I run the program, the first time Fido_WriteCounter(1200) is called, the program hangs.

Analysing the compiler-generated source file Fido.c

Fido_Start() calls Fido_Enable() which sets the enable flag by executing the statement

Fido_GLOBAL_ENABLE |= Fido_BLOCK_EN_MASK;

in Fido_WriteCounter(uint16 counter)         it executes the statement

CYASSERT (0u == (Fido_GLOBAL_ENABLE & Fido_BLOCK_EN_MASK));

       

As the enable flag in Fido_GLOBAL_ENABLE was set in Fido_Start() the if statement equates to zero, passing zero to  CYASSERT  which causes the cpu to be halted!

Should I disable the counter before calling Fido_WriteCounter() ?

The only high level API function which clears the enable bit in Fido_GLOBAL_ENABLE  is Fido_Stop()

Should I be calling Fido_Stop()?

Assuming the enable flag in Fido_GLOBAL_ENABLE  is clear when I called Fido_WriteCounter(),it would get past the statement

CYASSERT (0u == (Fido_GLOBAL_ENABLE & Fido_BLOCK_EN_MASK));

and immediately set the enable flag by executing  the statement

        Fido_GLOBAL_ENABLE |= Fido_BLOCK_EN_MASK;

Then writing data to the counter register before immediately clearing the enable flag by executing the statement

Fido_GLOBAL_ENABLE &= ((uint8)(~Fido_BLOCK_EN_MASK));

The counter would remain disabled until the next time I called Fido_WriteCounter();

This seems all wrong to me!

Am I misinterpreting the program?

Am I missing something?

or is there a bug in the compiler-generated Fido.c?

I have the following configuration settings in PSoC Creator

16bit Fixed Function

Period 1500

Run Mode: Continuous

Interrupt on TC

The version number for the Counter component is 3.0

The version number for PSoC Creator is 4.2

A copy of Fido.c is attached.

I originally tried using the built-in watchdog timer defined in CyLib.c

I started the Watchdog by calling

CyWdtStart(CYWDT_1024_TICKS  , CYWDT_LPMODE_NOCHANGE );

then periodically calling CyWdtClear();

When the program starts, I test the value of CyResetStatus, and if the CY_RESET_WD    bit is set, I take action to recover the error.

I modified my program so that it would deliberately get stuck in an infinite loop.

The Watchdog timer generated a reset 

but on testing the value returned by CyResetStatus,  the only bits that are set are

CY_RESET_SW                  and CY_RESET_GPIO1             

There is no sign of the supply voltage dipping during reset which could be interpreted as a normal power-on reset.

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.

Peter,

It is solved!

Attached is a Bootloader/Bootloadable example project that proves the proof of concept.

It is VERY simple.

The Bootloader adds ONE line of code immediately entering main().

/* Save 'true' CyResetStatus to DMA config TD chan 22. Pass to Bootloadable code */

*(reg32 *)(CYREG_PHUB_CFGMEM22_CFG1) = CyResetStatus;

The Bootloadable adds ONE line of code immediately entering main().

/* Recover 'true' CyResetStatus from DMA config TD chan 22. Passed from Bootloader code */

CyResetStatus = *(reg32 *)(CYREG_PHUB_CFGMEM22_CFG1);

Now CyResetStatus contains the 'real' reason for the reset that survives a Bootloader intervention.

Note:  In the example project.  The Bootloader will only wait 5 seconds with the LED on to allow Bootloader Host to load in a new Bootloadable app. (If there is no app it will wait forever).  Once the 5 seconds expires (with the LED ON), you will get either 8 to 10 long blinks (due to a Reset event) or 3 quick blinks (due to a watchdog event).

To cause the watchdog, make sure the WDT_dtct_reset app is loaded.  Wait for the RESET blinking to complete.  The LED should be off.  Press the SW1 (P2.2) for about 4 seconds.  Once the LED turns back ON release SW1.   The Bootloader will keep the LED for 5 seconds then blink 3 times quickly to indicate a watchdog event.

This method uses a currently unused PSoC register that preserves the installed value through a reset.  No EEPROM resource needed.

Len

Len
"Engineering is an Art. The Art of Compromise."

View solution in original post

0 Likes
12 Replies