CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

problem with WDT in 16LF1825
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
starfire151



Joined: 01 Apr 2007
Posts: 195

View user's profile Send private message

problem with WDT in 16LF1825
PostPosted: Mon May 10, 2021 10:47 am     Reply with quote

First, the basics:
Windows 10 x64
PCWHD 5.071

I'm trying to get a PIC16LF1825 to run in a low power mode by using the WDT and an external interrupt. As a test case, I have the WDT set for 2 seconds (I plan to use 128 seconds in the final version). I loop a total of 10 times, restarting the WDT for the full 2 second count and then going to to sleep. When the final loop is done, I'm trying to turn off the WDT so I can do some activity, which will take longer than the watchdog time. In this test case, I'm using a couple of pins to monitor status.

I see the background timeouts work correctly. I see the peripheral output pin get turned on after the loops. ...but... I see the peripheral get turned off after one watchdog period (2 seconds) instead of waiting for the 10 second peripheral period. It's as if the setup_wdt(WDT_OFF) command is not being recognized.

I put the PIN_C2 on a scope and I see the voltage go from low to high and stay high for 2 seconds and then start to decay off. It decays from +3.3VDC to about 0.5VDC in about 40ms then shoots up to +3.3VDC again briefly (around 10us) before decaying off to 0VDC again.

I'm including the test code below:
Code:

#include <16LF1825.h>

#device adc=10       // 10-bit ADC => 1024 steps
#device *=16

#FUSES NODEBUG       // No Debug mode for ICD
#FUSES WDT           // Watch Dog Timer
#FUSES HS            // High speed osc
#FUSES NOPROTECT     // Code not protected from reading
#FUSES IESO          // Internal External Switch Over mode enabled
#FUSES NOBROWNOUT    // No brownout reset
#FUSES STVREN        // Stack full/underflow will cause reset
#FUSES NOLVP         // No low volt prgm, B3(PIC16) or B5(PIC18) used for I/O
#FUSES MCLR          // Master Clear pin enabled

#define clk_freq 16000000
#use delay(internal=clk_freq)

#define PA_TRIS 0b11001111
#define PA_DEF 0b11011111
#define PC_TRIS 0b11100000
#define PC_DEF 0b11100000

typedef unsigned int8 uint8;
typedef unsigned int16 uint16;
typedef unsigned int32 uint32;

int1 extIntFlag;     // TRUE=external int seen
int1 wdFlag;         // TRUE=doing WDT loops

uint16 loopCntr;     // current WDT loop count
uint16 bgLoopCntr;   // background loop count for peripheral acitvity


// ---- external interrupt service ----
//  if ext int seen from light sensor, set flag for background
#int_EXT
void ExtISR(void)
{
   extIntFlag = TRUE;
}


// ---- main background routine ----
#zero_ram
void main(void)
{
   set_tris_a(PA_TRIS);
   set_tris_c(PC_TRIS);

   set_rtcc(0);
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED, 0, 1);

   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   output_a(PA_DEF);
   output_c(PC_DEF);
   extIntFlag = FALSE;
   wdFlag = TRUE;
   bgLoopCntr = 0;   // reset background loop counter

   delay_ms(100);                // system stability time
   
   ext_int_edge(L_TO_H);   // external int from light sensor through 74AHC14
   clear_interrupt(INT_EXT);        // clear any pending interrupt
   enable_interrupts(INT_EXT);      // enalbe external interrupts
   enable_interrupts(GLOBAL);       // global activation of enabled ints

   setup_wdt(WDT_ON | WDT_2S);   // enable WDT and set for 2 second timeout

   while(TRUE) // background
   {
      if(wdFlag)
      {
         loopCntr = 0;  // reset loop counter
         while((loopCntr < 10) && (extIntFlag == FALSE))
         {
            restart_wdt(); // restart WDT to get full 2 second delay time
         
            sleep();       // go to sleep now

            output_high(PIN_A5);  // flash test pin to show awake now
            delay_ms(100);
            output_low(PIN_A5);
           
            loopCntr++;    // if no ext int, just increment loop counter
         }
         
         // enable an output pin to show active now
         output_high(PIN_C2); // turn peripheral power on

         setup_wdt(WDT_OFF);  // turn off WDT
         wdFlag = FALSE;      // don't do WDT loops until done with activity
         
         output_high(PIN_A5); // flash test pin to show it got to here
         delay_ms(50);
         output_low(PIN_A5);
         delay_ms(50);
         output_high(PIN_A5);
         delay_ms(50);
         output_low(PIN_A5);

         extIntFlag = FALSE;  // verify ext int flag reset, if it was set
      }
     
      delay_ms(1);
     
      if(++bgLoopCntr == 10000)   // delay to allow background activity
      {
         bgLoopCntr = 0;      // reset for next time
         
         // disable 3V and 6V supplies and turn off LEDs now
         output_low(PIN_C2);       // turn peripheral power off

         setup_wdt(WDT_ON | WDT_2S);
         restart_wdt();
         
         wdFlag = TRUE;    // tell the WDT to loop again
      }
   }
}


Does anyone have any idea what's happening?

Thanks for any help.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

Re: problem with WDT in 16LF1825
PostPosted: Mon May 10, 2021 2:22 pm     Reply with quote

starfire151 wrote:
It's as if the setup_wdt(WDT_OFF) command is not being recognized.


#FUSES NODEBUG // No Debug mode for ICD
#FUSES WDT // Watch Dog Timer
#FUSES HS // High speed osc
#FUSES NOPROTECT // Code not protected from reading
#FUSES IESO // Internal External Switch Over mode enabled
#FUSES NOBROWNOUT // No brownout reset
#FUSES STVREN // Stack full/underflow will cause reset
#FUSES NOLVP // No low volt prgm, B3(PIC16) or B5(PIC18) used for I/O
#FUSES MCLR // Master Clear pin enabled

On page 569 of the CCS manual, in the section on setup_wdt(), it says:
Quote:

Note: For PCH parts and PCM parts with software controlled WDT, setup_wdt( ) would enable/disable watchdog timer only if NOWDT fuse is set. If WDT fuse is set, watchdog timer is always enabled.

You need to change your fuse to NOWDT.
starfire151



Joined: 01 Apr 2007
Posts: 195

View user's profile Send private message

PostPosted: Mon May 10, 2021 2:44 pm     Reply with quote

Hi PCM programmer. Thanks for responding so quickly.

I changed the #FUSES WDT to #FUSES NOWDT and tried it again. I don't even see the loops counting now on the PIN_A5 output.

When I activate the external interrupt, though, it turns on the peripheral pin on PIN_C2 and it stays active for 10 seconds, like its supposed to. It appears the setup_wdt(WDT_OFF) is working now ...progress...

Why wouldn't the PIN_A5 output work in the loop now, though? Shouldn't program execution continue after the sleep() command when the WDT times out?

Thanks for your help.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 11, 2021 12:47 am     Reply with quote

Did you put the IDE into Debug mode ? That would disable the WDT.
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Tue May 11, 2021 2:18 am     Reply with quote

One little change that may affect things:

Code:

            sleep();       // go to sleep now
            delay_cycles(1);
            output_high(PIN_A5);  // flash test pin to show awake now

The instruction _after_ the sleep, is 'prefetched' when you go to sleep.
As a result, it may not actually execute correctly when you wake.
Hence this instruction should always be a NOP. delay_cycles(1) codes
as a NOP.
It may affect how the code behaves when it wakes.

You don't actually need the restart_wdt when entering sleep. The act of
entering the sleep mode always restarts the WDT.
starfire151



Joined: 01 Apr 2007
Posts: 195

View user's profile Send private message

PostPosted: Tue May 11, 2021 8:33 am     Reply with quote

Hi PCM programmer -

I included the #FUSES NODEBUG so I think the WDT should be enabled?

Hi Ttelmah -

I included the delay_cycles(1); after the sleep() command. This didn't appear to make any difference. It's as if it's not being awakened by the WDT timeout. I removed the restart_wdt() before going to sleep(), also. Thanks for that info.

One question on how to start the WDT. I've tried setup_wdt(WDT_ON | WDT_2S), setup_wdt(WDT_2S), and both setup_wdt(WDT_2S) then setup_wdt(WDT_ON). All three conditions give the same result. What is the correct method. The documentation is kind of vague about this.

In all three cases, though, when I trigger the external interrupt, the code after the sleep() statement all works correctly. I see the flashes to the PIN_A5, the PIN_C2 turns on and stays on for the expected 10 seconds before turning off the PIN_C2 and returning to the loop.

Thanks for your continued help in resolving this issue.
temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue May 11, 2021 9:47 am     Reply with quote

re: I included the #FUSES NODEBUG so I think the WDT should be enabled?

NOT necessarily if you're using an IDE. IDEs can overwrite the pgm code setups....

Also, if you're using MPLAB, you must compiler in 'release' mode not 'debug' mode......
so... is the hardware totally 'standalone'? IE burn the PIC then test in the 'real World' ??
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 11, 2021 10:06 am     Reply with quote

starfire151 wrote:
Hi PCM programmer -

I included the #FUSES NODEBUG so I think the WDT should be enabled?

Temtronics answered the question, but here is some more:

Using MPLAB vs. 8.92, I set the Release/Debug drop-down box
to DEBUG, and compiled your program. I then looked at the bottom
of the .LST file to see the fuses set by the compiler:
Quote:
Configuration Fuses:
Word 1: 19E4 INTRC_IO NOWDT NOPUT MCLR NOPROTECT NOCPD NOBROWNOUT NOCLKOUT IESO NOFCMEN
Word 2: 0EFF NOWRT PLL_SW STVREN BORV19 DEBUG NOLVP

Some fuses have been forced to be compatible with the ICD debugger.

Note that the drop-down box setting has over-ridden the NODEBUG
in your program.

That's why I mentioned it. What IDE are you using and is it
accidentally set for DEBUG mode ?
starfire151



Joined: 01 Apr 2007
Posts: 195

View user's profile Send private message

PostPosted: Tue May 11, 2021 5:20 pm     Reply with quote

Hi PCM programmer and temtronic

I checked the bottom of the .lst file and get this:

Configuration Fuses:
Word 1: 39C4 INTRC_IO NOWDT PUT MCLR NOPROTECT NOCPD NOBROWNOUT NOCLKOUT IESO FCMEN
Word 2: 1EFF NOWRT PLL_SW STVREN BORV19 NODEBUG NOLVP

It appears I am not in debug mode.

I'm using V5.071 of the compiler. I'm using the ICD-USB module to program the PIC. I use the "Build and Run" option from the menu. It compiles and downloads the program to the PIC and then starts operation. Since this test case isn't using the PClk or PDat lines, the program runs OK. I have also disconnected the ICD-USB module from the PIC and done a reset to the system but it still responds the same way.

As an aside, I also just compiled the program and loaded it to the PIC with the ccsload program but that also showed the same results. The WDT appears to not be working but the EXT interrupt still works.
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Tue May 11, 2021 6:06 pm     Reply with quote

Have you read the errata for that processor?

Item 1.1: LFINTOSC, Item summary: Wake from sleep. Revision A0 affected.

Item 1.2: Clock switching, Item summary: clock switching can cause a single corrupted instruction. Revision A0 affected.

Item 1.3: Oscillator start-up timer, Item summary: OSTS bit remains set. Revisions A0 and A2 affected.

These are, to my mind, 3 possibilities in terms of your troubles.

Use CCSLoad to read the HW rev of your processor.
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Tue May 11, 2021 6:15 pm     Reply with quote

starfire151 wrote:
Hi PCM programmer and temtronic

I checked the bottom of the .lst file and get this:

Configuration Fuses:
Word 1: 39C4 INTRC_IO NOWDT PUT MCLR NOPROTECT NOCPD NOBROWNOUT NOCLKOUT IESO FCMEN
Word 2: 1EFF NOWRT PLL_SW STVREN BORV19 NODEBUG NOLVP

It appears I am not in debug mode.


Your WDT is completely disabled. It cannot function in SW controlled mode because it's off. From the data sheet, chapter 4, page 48:

WDTE bits (4:3): 00 = watchdog disabled.

You want 01 = WDT controlled by the SWDTEN bit in the WDTCON register.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 11, 2021 7:35 pm     Reply with quote

On page 569 of the CCS manual, in the section on setup_wdt(), it says:
Quote:

Note: For PCH parts and PCM parts with software controlled WDT, setup_wdt( ) would enable/disable watchdog timer only if NOWDT fuse is set. If WDT fuse is set, watchdog timer is always enabled.
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Tue May 11, 2021 8:32 pm     Reply with quote

Manual appears to be wrong.

Test program:
Code:
#include <16LF1825.h>
#device ADC=10

#FUSES PUT                      //Power Up Timer
#FUSES NOBROWNOUT               //No brownout reset
#fuses WDT_SW         //No Watch Dog Timer, enabled in Software
#fuses INTRC_IO       //Internal RC Osc, no CLKOUT

#use delay(internal=4000000)

void main(void) {
   setup_wdt(WDT_ON | WDT_512MS);
   
   while(TRUE) {
     
   }
}


List file:
Code:
CCS PCM C Compiler, Version 5.093, 46949               11-May-21 20:21

               Filename:   C:\temp\main.lst

               ROM used:   19 words (0%)
                           Largest free fragment is 2048
               RAM used:   5 (0%) at main() level
                           16 (2%) worst case
               Stack used: 0 locations
               Stack size: 16

0000:  MOVLP  00
0001:  GOTO   main
0002:  NOP
.................... #include <16LF1825.h>
.................... //////////// Standard Header file for the PIC16LF1825 device ////////////////
.................... ///////////////////////////////////////////////////////////////////////////
.................... ////        (C) Copyright 1996, 2014 Custom Computer Services          ////
.................... //// This source code may only be used by licensed users of the CCS C  ////
.................... //// compiler.  This source code may only be distributed to other      ////
.................... //// licensed users of the CCS C compiler.  No other use, reproduction ////
.................... //// or distribution is permitted without written permission.          ////
.................... //// Derivative programs created using this software in object code    ////
.................... //// form are not restricted in any way.                               ////
.................... ///////////////////////////////////////////////////////////////////////////
.................... #device PIC16LF1825
....................
.................... #list
....................
.................... #device ADC=10
....................
.................... #FUSES PUT                      //Power Up Timer
.................... #FUSES NOBROWNOUT               //No brownout reset
.................... #fuses WDT_SW         //No Watch Dog Timer, enabled in Software
.................... #fuses INTRC_IO       //Internal RC Osc, no CLKOUT
....................
.................... #use delay(internal=4000000)
....................
.................... void main(void) {
0003:  MOVLW  6A
0004:  MOVLB  01
0005:  MOVWF  OSCCON
0006:  MOVLB  03
0007:  CLRF   ANSELA
0008:  CLRF   ANSELC
0009:  MOVLB  02
000A:  CLRF   CM1CON1
000B:  CLRF   CM1CON0
000C:  CLRF   CM2CON1
000D:  CLRF   CM2CON0
....................    setup_wdt(WDT_ON | WDT_512MS);
000E:  MOVLW  13
000F:  MOVLB  01
0010:  MOVWF  WDTCON // this is correct
....................   
....................    while(TRUE) {
0011:  GOTO   011
....................       
....................    }
.................... }
0012:  SLEEP

Configuration Fuses:
   Word  1: 39CC   INTRC_IO WDT_SW PUT MCLR NOPROTECT NOCPD NOBROWNOUT NOCLKOUT IESO FCMEN // correct
   Word  2: 1EFF   NOWRT PLL_SW STVREN BORV19 NODEBUG NOLVP


If the WDT fuse is changed to disable it:
Code:
CCS PCM C Compiler, Version 5.093, 46949               11-May-21 20:26

               Filename:   C:\temp\main.lst

               ROM used:   19 words (0%)
                           Largest free fragment is 2048
               RAM used:   5 (0%) at main() level
                           16 (2%) worst case
               Stack used: 0 locations
               Stack size: 16

0000:  MOVLP  00
0001:  GOTO   main
0002:  NOP
.................... #include <16LF1825.h>
.................... //////////// Standard Header file for the PIC16LF1825 device ////////////////
.................... ///////////////////////////////////////////////////////////////////////////
.................... ////        (C) Copyright 1996, 2014 Custom Computer Services          ////
.................... //// This source code may only be used by licensed users of the CCS C  ////
.................... //// compiler.  This source code may only be distributed to other      ////
.................... //// licensed users of the CCS C compiler.  No other use, reproduction ////
.................... //// or distribution is permitted without written permission.          ////
.................... //// Derivative programs created using this software in object code    ////
.................... //// form are not restricted in any way.                               ////
.................... ///////////////////////////////////////////////////////////////////////////
.................... #device PIC16LF1825
....................
.................... #list
....................
.................... #device ADC=10
....................
.................... #FUSES PUT                      //Power Up Timer
.................... #FUSES NOBROWNOUT               //No brownout reset
.................... #fuses NOWDT          //No Watch Dog Timer
.................... #fuses INTRC_IO       //Internal RC Osc, no CLKOUT
....................
.................... #use delay(internal=4000000)
....................
.................... void main(void) {
0003:  MOVLW  6A
0004:  MOVLB  01
0005:  MOVWF  OSCCON
0006:  MOVLB  03
0007:  CLRF   ANSELA
0008:  CLRF   ANSELC
0009:  MOVLB  02
000A:  CLRF   CM1CON1
000B:  CLRF   CM1CON0
000C:  CLRF   CM2CON1
000D:  CLRF   CM2CON0
....................    setup_wdt(WDT_ON | WDT_512MS);
000E:  MOVLW  13
000F:  MOVLB  01
0010:  MOVWF  WDTCON // same as before
....................   
....................    while(TRUE) {
0011:  GOTO   011
....................       
....................    }
.................... }
0012:  SLEEP

Configuration Fuses:
   Word  1: 39C4   INTRC_IO NOWDT PUT MCLR NOPROTECT NOCPD NOBROWNOUT NOCLKOUT IESO FCMEN // setup_wdt() doesn't change the fuse - the WDT is killed
   Word  2: 1EFF   NOWRT PLL_SW STVREN BORV19 NODEBUG NOLVP
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Tue May 11, 2021 11:40 pm     Reply with quote

No, the manual is right, except it dates from older chips that only had
WDT and NOWDT fuses. This chip has WDT, NOWDT, WDT_NOSL, and
WDT_SW options.

You have to look at and understand what the fuses actually 'do' (data sheet).

For this chip it says:
Quote:

bit 4-3 WDTE<1:0>: Watchdog Timer Enable bit
11 = WDT enabled
10 = WDT enabled while running and disabled in Sleep
01 = WDT controlled by the SWDTEN bit in the WDTCON register
00 = WDT disabled


Note that only the third (which is WDT_SW), allows the SWDTEN bit to
control the watchdog.

On the earlier chips, you had:
Quote:

bit 3 WDTE: Watchdog Timer Enable bit
1 = WDT enabled
0 = WDT disabled and can be enabled by SWDTEN bit (WDTCON<0>)


So to use the SWDTEN, you simply had to disable the WDT in the fuses.
The manual has not been updated for these later chips.

The key thing always is to look at the data sheet.
starfire151



Joined: 01 Apr 2007
Posts: 195

View user's profile Send private message

PostPosted: Wed May 12, 2021 8:32 am     Reply with quote

Hi Ttelmah, newguy, and PCM programmer -

GREAT HELP EVERYBODY! I changed the #FUSES NOWDT line to #FUSES WDT_SW, recompiled, and loaded it. It worked right off the bat completely correctly!

I'm seeing the 100ms pulse every 2 seconds on PIN_A5 during the WDT counting loop, I see the PIN_C2 get enabled after the end of the counting loop, I see the background operation run correctly for 10 seconds with no WDT timeout, I see the PIN_C2 get disabled at the end of the 10 second background operation, and I see the PIN_A5 100ms pulse every 2 seconds from the WDT for another 10 loops, etc.

I didn't see WDT_SW as a fuse option in the device file. It worked great!


Thanks, again, everyone!

I'm off to the races... Very Happy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group