View previous topic :: View next topic |
Author |
Message |
ronewart
Joined: 02 Aug 2008 Posts: 8
|
Problem putting PIC24 to sleep() |
Posted: Sun Oct 18, 2015 9:42 am |
|
|
Am trying to put PIC24FJ128GC006 to sleep. The test code below keeps running (i.e. through "test loop"). It seems like it is either not going to sleep, or it is waking up immediately from something. I was originally trying to wake up from RTC alarm, but have disabled all interrupts including INT_RTC at this point (just for test). Also tried sleep(SLEEP_FULL);, sleep(SLEEP_IDLE); without success.
Primary clock is 16mhz internal; RTC running from SOSC 32768 xtal
Any suggestions appreciated. Thanks.
Code: |
// Using PIC24FJ128GC006
// Main clock is 16 MHZ internal oscillator
// RTC is enabled using SOSC and external 32768 Xtal
// test code segment that tries to put system in sleep()
// ?? TEMPORARY SLEEP TEST AREA below ---------10/17/15-------------------------
fputc(RTCCChimeF,USBst); // output number of RTC Interrupts to USB port
while(TRUE) // test loop
{
LoggerLowPower(); // puts powers logger down; prepares to sleep
sleep(); // also tried sleep(SLEEP_FULL), sleep(SLEEP_IDLE) without success
LoggerFullPower(); // wakes up; powers up after sleep
fputc(RTCCChimeF,USBst); // output number of RTC Interrupts to USB port
fputc(test[2],USBst); // output number of RTC Interrupts to USB port
}
// ?? TEMPORARY SLEEP TEST AREA above ----------------------------------
void LoggerFullPower(void) // powers up logger
// Input: none
// Output: none
// Comment:
{
output_bit(EnExcitCh03_3,1); // turn Ch 0 +3.3 excitation OFF
output_bit(EnExcitCh13_3,1); // turn Ch 1 +3.3 excitation OFF
output_bit(EnExcitCh05_0,0); // turn Ch 0 +3.3 excitation OFF
output_bit(EnExcitCh15_0,0); // turn Ch 1 +3.3 excitation OFF
output_bit(En5sp,1); // turn signal processor OFF
delay_ms(1000); // allow time for regulators to stabilize
enable_interrupts(INT_TIMER1);
clear_interrupt(INT_TIMER1);
enable_interrupts(INT_RDA);
clear_interrupt(INT_RDA);
enable_interrupts(INT_RTC);
clear_interrupt(INT_RTC);
enable_interrupts(INT_EXT0);
clear_interrupt(INT_EXT0);
enable_interrupts(INTR_GLOBAL);
return;
}
void LoggerLowPower(void) // Put logger in low power state; then sleeps
// Input: none
// Output: none
// Comment:
{
output_bit(EnExcitCh03_3,0); // turn Ch 0 +3.3 excitation OFF
output_bit(EnExcitCh13_3,0); // turn Ch 1 +3.3 excitation OFF
output_bit(EnExcitCh05_0,0); // turn Ch 0 +5.0 excitation OFF
output_bit(EnExcitCh15_0,0); // turn Ch 1 +5.0 excitation OFF
output_bit(En5sp,0); // turn signal processor OFF
disable_interrupts(INT_TIMER2);
disable_interrupts(INT_EXT1);
disable_interrupts(INTR_GLOBAL);
disable_interrupts(INT_TIMER1);
clear_interrupt(INT_TIMER1);
disable_interrupts(INT_RDA);
clear_interrupt(INT_RDA);
clear_interrupt(INT_RTC);
disable_interrupts(INT_RTC);
clear_interrupt(INT_RTC);
clear_interrupt(INT_EXT0);
disable_interrupts(INT_EXT0);
disable_interrupts(INTR_GLOBAL);
test[2] = 9; // ?? for test only 10/18/15
return;
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 19, 2015 3:27 am |
|
|
I don't see your fuses or #device statements. Are you trying to run this
in Debug mode ? The MPLAB ICD3 help file says:
Quote: | dsPIC30F SMPS, dsPIC33F, PIC24F/H Limitations
The SLEEP instruction cannot be used when debugging unless the
device is set to “Break on SLEEP Instruction” (Debugger>Breakpoints,
Event Breakpoints).
|
|
|
|
ronewart
Joined: 02 Aug 2008 Posts: 8
|
|
Posted: Mon Oct 19, 2015 5:17 am |
|
|
Thanks for the reply PCM Programmer --
I don't have a debugger, but may have selected fuses improperly.
Fuses are shown below.
I did not know whether #FUSE DS_SW should or should not be used with the sleep() instruction. I tried it both ways without success.
Code: | #include <24FJ128GC006.h>
#device ADC=12
#FUSES NOWDT //No Watch Dog Timer
#FUSES LVR //Low Voltage Regulator Enabled, Controlled in Software
#FUSES NOWRT //Program memory not write protected
#FUSES NOPROTECT //Code not protected from reading
#FUSES JTAG //JTAG enabled
#FUSES NOOSCIO //OSC2 is clock output
#FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES VREFALT //VREF is on a alternate pins, VREF+ on RB0 and VREF- on RB1
#FUSES CVREFALT
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES WPFP //Write/Erase Protect Page Start/End Location, set to last page or use WPFP=x to set page
#FUSES SOSC_SEL //SOSC circuit selected
#FUSES BROWNOUT //Reset when brownout detected
#FUSES WPDIS //All Flash memory may be erased or written
#FUSES NOWPCFG //Configuration Words page is not erase/write-protected
#FUSES WPEND //Flash pages WPFP to Configuration Words page are write/erase protected
#FUSES NODSWDT //Deep Sleep Watchdog Timer disabled
// #FUSES DS_SW //Deep Sleep is controlled by the register bit DSEN
// tested with & without this fuse; does not enter sleep (or immediately exits)
#FUSES RTCBAT //RTC operation is continued through VBAT
#FUSES NOPLL
#FUSES NOALTI2C2 //I2C2 mapped to SDA2/SCL2 pins
#FUSES NOIOL1WAY //Allows multiple reconfigurations of peripheral pins
#device ICSP=1
#use delay(internal=16000000) |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19544
|
|
Posted: Mon Oct 19, 2015 8:23 am |
|
|
Old question.
Are you perhaps using MPLAB?.
If so, this _by default_ will program the chip for debug mode unless you override this setting.... |
|
|
ronewart
Joined: 02 Aug 2008 Posts: 8
|
|
Posted: Mon Oct 19, 2015 11:08 am |
|
|
Thanks Ttelmah & PCM Programmer!
Am using the CCS PCD compiler to generate .hex file. Am using MPLAB, to "Import Hex (Prebuilt) Project" which interfaces to PM3 programmer. I don't think that MPLAB does anything other than program the hex file, but could be wrong.
Under the "Debug" tab in the PCD compiler, most of the options are greyed out since I don't have ICD. When I click on the "enable button" it comes up with "Your code does not have ICD mode enabled" error message.
PCM Programmer -- am looking for the "Break on SLEEP Instruction" (Debugger>Breakpoints> Event Breakpoints) that you described. Should that be in the PCD compiler, or is that something that I might not have since I don't have ICD? Is there a specific #device . . . or preprocessor command that I could insert into my header file to ensure that the system does not get compiled in the debugger mode?
Thanks for your help. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 19, 2015 12:03 pm |
|
|
Look at the bottom of the .LST file created by the CCS compiler.
It will have a list of the fuses that the compiler set for the project.
The file will be in your CCS project directory. What does it show
for the debug fuse ?
Quote: | (Debugger>Breakpoints> Event Breakpoints) |
I don't have the CCS IDE so I can't answer questions on it. |
|
|
ronewart
Joined: 02 Aug 2008 Posts: 8
|
|
Posted: Mon Oct 19, 2015 12:25 pm |
|
|
"NODEBUG" fuse --> whole fuse .lst shown below.
Also found #fuses NODEBUG in CCS's FAQ section which I added to the header file. It did not make any difference in the .hex checksum, nor in the operation of the test program.
Thanks again PCM Programmer -- I appreciate your expertise.
Code: |
Configuration Fuses:
Word 1L: 7B3F WPOSTS16 WDT128 WINDIS NOWDT ICSP1 LVR NODEBUG NOWRT NOPROTECT JTAG
H: 0000
Word 2L: F93B NOPR WDTCLK_LPRC NOOSCIO CKSFSM FRC_PLL VREFALT CVREFALT WDTCMX IESO
H: 0000
Word 3L: FFFF WPFP SOSC_SEL WDTWIN_25% BROWNOUT WPDIS NOWPCFG WPEND
H: 0000
Word 4L: 477F DSWDT_25DAYS DSWDTCK_LPRC DSBOR NODSWDT DS_SW RTCBAT PLL2 NOALTI2C2 NOIOL1WAY
H: 0000 |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 19, 2015 4:50 pm |
|
|
So it's not the debug fuse. The first thing I would do is to greatly simplify
the test program, like this:
Code: |
void main()
{
output_low(LED2); // Ensure that LED2 is off
output_high(LED1); // Turn on LED1 to show that PIC is running
sleep(SLEEP_FULL);
output_high(LED2); // If PIC doesn't stay in sleep mode, turn on LED2
while(TRUE);
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19544
|
|
Posted: Tue Oct 20, 2015 1:25 am |
|
|
If I remember correctly, these chips have a more complex sleep than most of the older chips. Full 'deep sleep', loses everything, and can only be exited via a reset. Then there is deep sleep with the memory retained (configured by the RETEN' bit. Because deep sleep is so dangerous, the chips have this locked, so you have to unlock it before enabling the sleep instruction. CCS does not do this for you. So you need something like:
Code: |
//the low voltage regulator must be set to be available in the fuses
#bit DSEN=getenv("bit:DSEN")
#bit RETEN=getenv("bit:RETEN")
disable_interrupts(INTR_GLOBAL);
RETEN=TRUE; //enable the low power regulator
DSEN=TRUE;
DSEN=TRUE; //This must be set _twice_
sleep(SLEEP_FULL);
delay_cycles(1);
|
This enables the internal regulator to keep the RAM alive (so deep sleep
can wake), and then unlocks the deep sleep bit, and executes the sleep.
I played with this on an 'ancestor' chip, and found this was what was needed. On PIC 18's that need this sort of setup, CCS usually supply it via the setup_oscillator instruction, but I couldn't see any such option on the chip I was using.
Good luck... |
|
|
ronewart
Joined: 02 Aug 2008 Posts: 8
|
|
Posted: Tue Oct 20, 2015 6:13 am |
|
|
PCM_Programmer -- thanks for pointing the way. I read your post yesterday, but did not have time to try. I went to bed thinking about your KISS program, and woke up in the middle of the night thinking -- "maybe the SDADC is kicking out interrupts and waking it up".
It ended up that I had two offenders, that needed to be disabled before calling sleep(); see below.
Thanks Ttelmah -- although this was not my particular problem, it is a great reference that I'll archive for next time.
Thanks PCM-Programmer and Ttelmah -- your suggestions and expertise got me going in the right direction. I appreciate the time you took to consider my problem, and your help.
Code: |
// The solution was to DISABLE both the SDADC and the PWM Oscillator before calling sleep()
setup_SD_adc(SDADC_ENABLED | SDADC_NO_HALT | SDADC_GAIN_1 | SDADC_DITHER_LOW
| SDADC_SVDD_SVSS | SDADC_BW_NORMAL , SDADC_CHOPPING_ENABLED |
SDADC_INT_EVERY_5TH_SAMPLE | SDADC_RES_UPDATED_EVERY_INT_READY |
SDADC_ROUND_16_BITS , SDADC_CLOCK_DIV_4 | SDADC_OSR_256 | SDADC_CLK_SYSTEM );
// also disable
//#use pwm(OC2,OUTPUT=PIN_D2,TIMER=2,FREQUENCY=2000,DUTY=50)
|
|
|
|
|