- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Solved! Go to Solution.
- Labels:
-
PSoC Creator Software
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
"Engineering is an Art. The Art of Compromise."