View previous topic :: View next topic |
Author |
Message |
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
PIC24FJ64GA004 SLEEP |
Posted: Thu Feb 11, 2021 2:52 am |
|
|
Hello,
I am using a PIC24FJ64GA004 on a battery operated device which "wakes up" with the internal RTC interrupt, takes some ADC readings, stores to external flash and then sleeps again until the next alarm set to the RTC.
My Sleep function disables some peripherals and interrupts and puts the cpu to sleep. When the RTC interrupt is fired then the CPU resumes the execution and resets the cpu.
Code: |
setup_timer1(TMR_DISABLED);
setup_timer2(TMR_DISABLED);
disable_interrupts(INT_TIMER1);
disable_interrupts(INT_TIMER2);
disable_interrupts(INT_RDA);
disable_interrupts(INT_RDA2);
CLEAR_INTERRUPT(INT_RDA);
CLEAR_INTERRUPT(INT_RDA2);
CLEAR_INTERRUPT(INT_TIMER1);
CLEAR_INTERRUPT(INT_TIMER2);
CLEAR_INTERRUPT(INTR_CN_PIN);
CLEAR_INTERRUPT(INT_RTC);
enable_interrupts(INT_RTC); //enable RTC interrupt
Led1=0;
Led2=0;
delay_ms(50);
#asm
pwrsav #0
#endasm
delay_ms(50);
reset_cpu();
|
In the above, if I use:
instead of
Code: |
#asm
pwrsav #0
#endasm
|
then the cpu does not sleep. It just skips the SLEEP(SLEEP_FULL); and resets.
But even with the assembly code, sometimes (only a few) it also does not sleep.
Any ideas?
Of course somewhere in the code I have
Code: |
#INT_RTC
void RTCISR(){
}
|
_________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Thu Feb 11, 2021 4:18 am |
|
|
Er. Presumably you do have the WDT enabled?. Needs to be, or the RTC
clock will stop. You need to have the WDT setup for a timeout longer than
the longest sleep interval.
Why are you delaying before going to sleep?. Means there is lots of time
for something to trigger before the sleep starts. My big suspicion would
be that you are getting something like the CN_PIN interrupt triggered
in this time.
What compiler version?. They did make a mess of the 'sleep' instruction
at one point. However this would not explain your behaviour with the
PWRSAV assembler. However there is a 'behaviour' that could cause
this. The triggering of _any_ interrupt in the actual sleep instruction
will prevent it from sleeping. Not just 'enabled' ones. It'll actually sleep
for just one instruction and then wake straight up:
Quote: |
9.2.3 INTERRUPTS COINCIDENT WITH
POWER SAVE INSTRUCTIONS
Any interrupt that coincides with the execution of a
PWRSAV instruction will be held off until entry into Sleep
or Idle mode has completed. The device will then
wake-up from Sleep or Idle mode.
|
It's a behaviour that can be very annoying.... |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Thu Feb 11, 2021 4:41 am |
|
|
No, WDT is not enabled and the RTC does not stop.
It wakes the cpu correctly at the set alarm.
The sleep-wake interval could be 1 minute or 1 day. I can not set the WDT to be bigger than this.
I do not understand why the WDT must be enabled in order for the RTC to work.
Compiler 5.049.
Maybe disable global interrupts and just enable the RTC interrupt?
What do you think?
Thanks. _________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Thu Feb 11, 2021 5:28 am |
|
|
The LP clock is only enabled when the chip is fully asleep, if the WDT is
enabled. It is in the chip data sheet.... |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Thu Feb 11, 2021 5:33 am |
|
|
I do not get it.
Code: |
#FUSES NOWDT //Watch Dog Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES FRC_PLL //Internal osc + PLL
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOPR //Pimary oscillator disabled
#FUSES OSCIO //OSC2 is general purpose output
#FUSES NOCKSFSM //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#BUILD (stack=1024)
#use delay(int=32M)
|
I have NO WDT enabled.
The RTC operates normally. _________________ George. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Thu Feb 11, 2021 5:53 am |
|
|
Hmm...
you may not have enabled it BUT some software or firmaware between you and the PIC could have....
I use MPLAB to burn my PICs and there's an 'option' to have NOT use the actual PIC program FUSES, instead use the ones from the 'programmer' menu.
There might be yet another set of 'fuses' if you have used 'debug' or an ICD system....
I know in my case I had to specifically 'click' a 'use program fuses' option..
I also '#INCLUDE' a complete file of FUSES, one per line, so that I can SEE what the fuses ARE as someone else's defaults are never what my defaults should be !
Jay |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Thu Feb 11, 2021 6:05 am |
|
|
In Configure-> Configuration Bits, I always have the checkbox Configuration Bits set in code.
I modified as follows:
Code: |
setup_timer1(TMR_DISABLED);
setup_timer2(TMR_DISABLED);
CLEAR_INTERRUPT(INT_RDA);
CLEAR_INTERRUPT(INT_RDA2);
CLEAR_INTERRUPT(INT_TIMER1);
CLEAR_INTERRUPT(INT_TIMER2);
CLEAR_INTERRUPT(INTR_CN_PIN);
setup_wdt( WDT_OFF );
disable_interrupts(GLOBAL);
enable_interrupts(INT_RTC); //enable RTC interrupt
CLEAR_INTERRUPT(INT_RTC);
Led1=0;
Led2=0;
#asm
pwrsav #0
#endasm
delay_cycles(1);
reset_cpu();
|
Fingers crossed... _________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Thu Feb 11, 2021 7:46 am |
|
|
OK. So I'm guessing then that you have a 32768Hz crystal on the secondary
oscillator?. On some of the chips, you can run the RTC off the internal
oscillator, but on these this is only enabled, when the WDT is also enabled.
I'd stand by my comment that I suspect an interrupt is getting set in the
delay time. You should not have a delay after setting things up for the sleep,
before you actually sleep. The interrupt setups, should be the last thing done
before sleeping. |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Thu Feb 11, 2021 8:05 am |
|
|
No, I do not have external crystal.
Code: |
#include <24FJ64GA004.h>
#FUSES NOWDT //Watch Dog Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES FRC_PLL //Internal osc + PLL
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOPR //Pimary oscillator disabled
#FUSES OSCIO //OSC2 is general purpose output
#FUSES NOCKSFSM //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#BUILD (stack=1024)
#use delay(int=32M)
|
Code: |
void SetupRTC(){
setup_rtc(RTC_ENABLE , 0);
}
|
and my Sleep function:
Code: |
void Die(uint16_t Wk){
setup_rtc_alarm(RTC_ALARM_ENABLE | RTC_CHIME_DISABLE, RTC_ALARM_DAY, 0x00);
rtc_alarm_write(&write_clock);
WifiSW=1;
EpaperRST=0;
PerSW=1;
ADC_CS=1;
EEPROM_CS=1;
FLASH_CS=1;
THERM_CS=0;
EPAPER_CS=1;
SPIEN=0;
ADON=0;
UARTEN1=0;
UARTEN2=0;
setup_timer1(TMR_DISABLED);
setup_timer2(TMR_DISABLED);
CLEAR_INTERRUPT(INT_RDA);
CLEAR_INTERRUPT(INT_RDA2);
CLEAR_INTERRUPT(INT_TIMER1);
CLEAR_INTERRUPT(INT_TIMER2);
CLEAR_INTERRUPT(INTR_CN_PIN);
setup_wdt( WDT_OFF );
disable_interrupts(GLOBAL);
enable_interrupts(INT_RTC); //enable RTC interrupt
CLEAR_INTERRUPT(INT_RTC);
Led1=0;
Led2=0;
#asm
pwrsav #0
#endasm
delay_cycles(1);
reset_cpu();
}
|
RTC and ALARM is working properly.
The only problem is that sometimes the CPU does not Sleep.
Or I guess it sleeps and wakes at once. _________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Fri Feb 12, 2021 2:03 am |
|
|
What you are saying does not make sense.
This chip does not support running the RTC without an external oscillator.
If you look at the data sheet, the RTC module only receives it's clock
from the SOSC. Not from anywhere else (figure 18-1 in the sheet).
It's clock comes from SOSC. |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Fri Feb 12, 2021 2:28 am |
|
|
OMG!
Yes, of course I have an external 32768 crystal.
I am so frustrated with the problem that I even forgot my name.
Really sorry. I cannot understand how I insisted on such a stupid thing.
The problem remains. The device occasionally skips sleep or I guess sleeps and wakes at once.
My friend Ttelmah give me your wisdom
Maybe a compiler bug? _________________ George. |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Fri Feb 12, 2021 3:41 am |
|
|
I have the device wake up, do its task, set alarm to 10" after wake up and sleep. On wake I printf the current time and RCON value. Before Sleep, I printf the next alarm.
If you see the bold below, the device woke up after 1 second and not after 10.
Also the RCON value of 131 means that the device:
1)has not been in sleep(!)
2)reset has not been executed
3)MCLR reset has occurred.
Wake:11:32:27 RCON:131
Next:11:32:37
Wake:11:32:37 RCON:131
Next:11:32:47
Wake:11:32:47 RCON:131
Next:11:32:57
Wake:11:32:57 RCON:131
Next:11:33:07
Wake:11:33:07 RCON:131
Next:11:33:17
Wake:11:33:17 RCON:131
Next:11:33:27
Wake:11:33:18 RCON:131
Next:11:33:28
Wake:11:33:28 RCON:131
Next:11:33:38
Wake:11:33:38 RCON:131
Next:11:33:48
The code below does not fall to sleep.
Code: |
81: SLEEP(SLEEP_FULL);
34B2 AF001A btsc.b 0x001a,#0
34B4 811254 mov.w 0x224a,0x0008
34B6 AF2008 btsc.b 0x0008,#1
34B8 811264 mov.w 0x224c,0x0008
34BA AF4008 btsc.b 0x0008,#2
34BC FE4000 pwrsav #0
|
Probably bit 2 of address 0x0008 is clear and the next command pwrsav #0 is skipped.
But what is address 0x0008? IVT Address Error? _________________ George. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Fri Feb 12, 2021 5:57 am |
|
|
Compiler 5.049.
I really know how the alarm mask works.
I also disabled the RTC and alarm completely but still the PIC will not sleep with the SLEEP(SLEEP_FULL); command.
I will try a new empty project with just fuses and SLEEP(SLEEP_FULL); to see what will happen. _________________ George. |
|
|
georpo
Joined: 18 Nov 2008 Posts: 281 Location: Athens, Greece.
|
|
Posted: Fri Feb 12, 2021 7:05 am |
|
|
Houston, we have a problem!
I deleted everything but still the PIC will not SLEEP!
It loops flashing the LED <-> resetting.
What is the compiler testing before setting the device to sleep?
Code: |
47: SLEEP(SLEEP_FULL);
023A AF001A btsc.b 0x001a,#0
023C AF2802 btsc.b 0x0802,#1
023E AF4804 btsc.b 0x0804,#2
0240 FE4000 pwrsav #0
|
Code: |
#include <24FJ64GA004.h>
#FUSES NOWDT //Watch Dog Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES FRC_PLL //Internal osc + PLL
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOPR //Pimary oscillator disabled
#FUSES OSCIO //OSC2 is general purpose output
#FUSES NOCKSFSM //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#BUILD (stack=1024)
#use delay(int=32M)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#word LATA=getenv("SFR:LATA")
#word LATB=getenv("SFR:LATB")
#word LATC=getenv("SFR:LATC")
#word TRISA=getenv("SFR:TRISA")
#word TRISB=getenv("SFR:TRISB")
#word TRISC=getenv("SFR:TRISC")
#word PORTA=getenv("SFR:PORTA")
#word PORTB=getenv("SFR:PORTB")
#word PORTC=getenv("SFR:PORTC")
#bit Led1=LATA.8
#bit Led2=LATA.1
void Main(){
TRISA=0b0000000000000001;
TRISB=0b1010001110100000;
TRISC=0b0000000010000011;
Led1=1;
delay_ms(100);
Led1=0;
delay_ms(100);
SLEEP(SLEEP_FULL);
delay_cycles(1);
reset_cpu();
}
|
Code: |
--- E:\WORK\herado\mine\code\V13test\v1.c ------------------------------------------------------
1:
0000 040210 goto 0x000210
2: #include <24FJ64GA004.h>
3:
4: #FUSES NOWDT //Watch Dog Timer
5: #FUSES NOPROTECT //Code not protected from reading
6: #FUSES FRC_PLL //Internal osc + PLL
7: #FUSES NOIESO //Internal External Switch Over mode disabled
8: #FUSES NOPR //Pimary oscillator disabled
9: #FUSES OSCIO //OSC2 is general purpose output
10: #FUSES NOCKSFSM //Clock Switching is disabled, fail Safe clock monitor is disabled
11: #FUSES NOWRT //Program memory not write protected
12: #FUSES NODEBUG //No Debug mode for ICD
13: #BUILD (stack=1024)
14:
15: #use delay(int=32M)
0200 E00000 cp0.w 0x0000
0202 AF2042 btsc.b 0x0042,#1
0204 370004 bra 0x00020e
0206 093E7B repeat #15995
0208 000000 nop
020A E90000 dec.w 0x0000,0x0000
020C 3AFFFC bra nz, 0x000206
020E 060000 return
16:
17: #use fast_io(A)
18: #use fast_io(B)
19: #use fast_io(C)
20:
21: #word LATA=getenv("SFR:LATA")
22: #word LATB=getenv("SFR:LATB")
23: #word LATC=getenv("SFR:LATC")
24:
25: #word TRISA=getenv("SFR:TRISA")
26: #word TRISB=getenv("SFR:TRISB")
27: #word TRISC=getenv("SFR:TRISC")
28:
29: #word PORTA=getenv("SFR:PORTA")
30: #word PORTB=getenv("SFR:PORTB")
31: #word PORTC=getenv("SFR:PORTC")
32:
33: #bit Led1=LATA.8
34: #bit Led2=LATA.1
35:
36: void Main(){
0210 22400F mov.w #0x2400,0x001e
0212 227FF0 mov.w #0x27ff,0x0000
0214 B7A020 mov.w 0x0000,0x0020
0216 000000 nop
0218 A8E081 bset.b 0x0081,#7
021A EF2744 clr.w 0x0744
021C EFA32C setm.w 0x032c
37:
38: TRISA=0b0000000000000001;
021E 200014 mov.w #0x1,0x0008
0220 881604 mov.w 0x0008,0x02c0
39: TRISB=0b1010001110100000;
0222 2A3A04 mov.w #0xa3a0,0x0008
0224 881644 mov.w 0x0008,0x02c8
40: TRISC=0b0000000010000011;
0226 200834 mov.w #0x83,0x0008
0228 881684 mov.w 0x0008,0x02d0
41:
42: Led1=1;
022A A802C5 bset.b 0x02c5,#0
43: delay_ms(100);
022C 200640 mov.w #0x64,0x0000
022E 020200 call 0x000200
44: Led1=0;
0232 A902C5 bclr.b 0x02c5,#0
45: delay_ms(100);
0234 200640 mov.w #0x64,0x0000
0236 020200 call 0x000200
46:
47: SLEEP(SLEEP_FULL);
023A AF001A btsc.b 0x001a,#0
023C AF2802 btsc.b 0x0802,#1
023E AF4804 btsc.b 0x0804,#2
0240 FE4000 pwrsav #0
48:
49: delay_cycles(1);
0242 000000 nop
50: reset_cpu();
0244 FE0000 reset
51: }
52:
0246 FE4000 pwrsav #0
|
_________________ George. |
|
|
|