View previous topic :: View next topic |
Author |
Message |
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
Wake result from Deep Sleep on PIC24FJ128GA204 |
Posted: Mon Sep 17, 2018 5:37 am |
|
|
Hi Folks,
I am trying to get a PIC24FJ128GA204 to go into deep sleep, and then wake up and give me an accurate reason as to whether it was a conventional wake up, or whether it has woken from Deep sleep.
I can put it to sleep perfectly well, however determining the reason for wake isn't quite so simple. The restart_cause() routine from CCS doesn't seem to return anything of value/use so I've tried to do it using registers and reading it directly.
I'm putting it to sleep with both INT_EXT enabled and the RTCC alarm clock running on internal crystal, set to wake once a minute.
The code goes to deep sleep (at the moment the processor current is 78uA)
When I press the int_ext button I wake up and it tells me it's woken from deep sleep - but the contents of the DSWAKE register are zero
Any Ideas?
Code: |
/* DEEP SLEEP REGISTERS */
#word DSCON_REG = getenv("SFR:DSCON")
#word RCON_REG = getenv("SFR:RCON")
#word DEEP_SLEEP_WAKE_REG = getenv("SFR:DSWAKE")
#bit DEEP_SLEEP_WAKE_BIT=getenv("BIT:DPSLP")
#bit DEEP_SLEEP_INT0_BIT=getenv("BIT:DSINT0")
#bit DEEP_SLEEP_RTCC_BIT=getenv("BIT:DSRTCC")
#bit DEEP_SLEEP_RELEASE_BIT=getenv("BIT:RELEASE")
/* ------------------------------------------------------------------------- */
/* MAIN CODE */
void main()
{
/* STAGE 1 - READ THE DEEP SLEEP BIT */
if (DEEP_SLEEP_WAKE_BIT == TRUE)
{
/* CLEAR THIS BIT */
DEEP_SLEEP_WAKE_BIT = 0;
UI_16 DSWakeReg = DEEP_SLEEP_WAKE_REG;
UI_16 RConRegister = RCON_REG;
DEEP_SLEEP_RELEASE_BIT = 0;
delay_ms(100); /* DELAY TO ALLOW THE UART TO WAKE */
fprintf(DEBUG_PORT,"\r\nDEEP SLEEP DSWAKE:%04X RCON:%04X INT0:%u RTCC:%u",DSWakeReg, RConRegister, DEEP_SLEEP_INT0_BIT, DEEP_SLEEP_RTCC_BIT);
|
My RS232 debug output looks like this
SLEEPING·¿
DEEP SLEEP DSWAKE:0000 RCON:0003 INT0:0 RTCC:0
UNKNOWN WAKE FROM DEEP SLEEP:0000
DSCON:0000 DSWAKE:0000
AWAKE NOW
Thanks in advance
James |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Sep 17, 2018 7:03 am |
|
|
How is the interrupt setup before you go to sleep?. Show this.
Check the assembler being generated, and that the compiler is actually selecting the right registers/bits.
Have you got the three NOP's between setting DSEN and the sleep instruction?.
Have you got a handler for INT0?. If not, and you are happy to only poll the detection, disable and clear this interrupt before triggering the sleep. |
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Mon Sep 17, 2018 7:15 am |
|
|
My state machine that handles the sleep setup of the system is shown below
There is quite a lot commented out at the moment, as I've been experimenting with what I physically have to disable, and what is turned off automatically when entering sleep.
I'm using the CCS sleep command - which hopefully does the job its supposed to! I stuck a delay_cycles(10) after calling it just to be safe (although never entirely sure that this is in the right place!)
Code: |
void Manage_Sleep_System()
{
switch (System.SleepManagerState)
{
/* UNIT IS RUNNING NORMALLY - SLEEP NOT REQUIRED */
case NORMAL_MODE:
{
break;
}
/* WE WANT TO START THE SHUTDOWN PROCESS */
/* TELL ALL OPEN TASKS TO SHUTDOWN */
case START_SHUTDOWN:
{
fprintf(DEBUG_PORT,"\r\n STARTING SLEEP");
delay_ms(500);
/* IF THE LCD DISPLAY IS RUNNING - INSTRUCT SHUTDOWN */
if (GraphicsDisplay.CurrentState != LCD_OFF)
{
DRV_SSD1327_Power(0);
}
/* SWITCH AND WAIT FOR SHUTDOWN TO COMPLETE */
System.SleepManagerState = WAIT_SHUTDOWN_PROCESSES;
break;
}
/* WAIT FOR ALL TASKS TO SHUT DOWN */
case WAIT_SHUTDOWN_PROCESSES:
{
/* HAS THE LCD SHUTDOWN */
if (GraphicsDisplay.CurrentState == LCD_OFF)
{
System.SleepManagerState = START_SLEEPING;
}
break;
}
case START_SLEEPING:
{
/* TURN OFF THE SERIAL PORTS */
// Uart_Disable();
//! /* TURN OFF THE ADC */
//! setup_adc(ADC_OFF);
//!
//! /* TURN OFF THE I2C */
//! i2c_init(I2C_PORT1, FALSE);
//!
//! /* MAKE SURE THE PINS ARE LOW */
//! output_drive(PIN_B2);
//! output_high(PIN_B2);
//! output_drive(PIN_B3);
//! output_high(PIN_B3);
setup_wdt(WDT_OFF);
//! spi_init(LCD_DISPLAY,FALSE);
//!
//! setup_timer2(TMR_DISABLED);
//! setup_timer4(TMR_DISABLED);
//! setup_timer5(TMR_DISABLED);
//!
//! SPI1_EN = FALSE;
//! SPI2_EN = FALSE;
//! SPI3_EN = FALSE;
//! UART3_EN = FALSE;
//! UART4_EN = FALSE;
//!
//! PMD1_REG = 0xFFFF;
//! PMD2_REG = 0xFFFF;
//! PMD3_REG = 0xFFFF;
//! PMD4_REG = 0xFFFF;
//! PMD5_REG = 0xFFFF;
//! PMD6_REG = 0xFFFF;
//! PMD7_REG = 0xFFFF;
//! PMD8_REG = 0xFFFF;
/* TURN OFF DMA CONTROLLER */
// DMA_ENABLE_BIT = FALSE;
Disable_And_Clear_All_Interrupts();
/* TURN OFF LED'S */
output_low(PANEL_LED);
output_low(BOARD_LED);
System.SleepManagerState = SLEEPING;
break;
}
case SLEEPING:
{
fprintf(DEBUG_PORT,"\r\nSLEEPING");
delay_ms(100);
/* ALLOW US TO WAKE UP ON A PUSHBUTTON */
ext_int_edge(0, H_TO_L);
clear_interrupt(INT_EXT0);
enable_interrupts(INT_EXT0);
/* TURN ON THE MINUTE ALARM */
RTC_Enable_Minute_Alarm();
clear_interrupt(INT_RTC);
enable_interrupts(INT_RTC);
/* SWITCH STATE TO THE STATE WE WILL BE IN ON WAKE UP */
System.SleepManagerState = WAKING;
sleep(DEEP_SLEEP);
delay_cycles(10);
break;
}
case WAKING:
{
fprintf(DEBUG_PORT,"\r\n AWAKE NOW");
System.SleepManagerState = NORMAL_MODE;
break;
}
default:
{
break;
}
}
}
|
Just to be sure - I am disabling/clearing every Interrupt individually
Code: |
void Disable_And_Clear_All_Interrupts()
{
disable_interrupts(INTR_GLOBAL);
disable_interrupts(INT_ADC1);
clear_interrupt(INT_ADC1);
//disable_interrupts(INT_ADDRERR);
clear_interrupt(INT_ADDRERR);
disable_interrupts(INT_BUSCOL);
clear_interrupt(INT_BUSCOL);
disable_interrupts(INT_CNI);
clear_interrupt(INT_CNI);
disable_interrupts(INT_COMP);
clear_interrupt(INT_COMP);
disable_interrupts(INT_CRC);
clear_interrupt(INT_CRC);
disable_interrupts(INT_CTMU);
clear_interrupt(INT_CTMU);
disable_interrupts(INT_DMA0);
clear_interrupt(INT_DMA0);
disable_interrupts(INT_DMA1);
clear_interrupt(INT_DMA1);
disable_interrupts(INT_DMA2);
clear_interrupt(INT_DMA2);
disable_interrupts(INT_DMA3);
clear_interrupt(INT_DMA3);
disable_interrupts(INT_DMA4);
clear_interrupt(INT_DMA4);
disable_interrupts(INT_DMA5);
clear_interrupt(INT_DMA5);
disable_interrupts(INT_EXT0);
clear_interrupt(INT_EXT0);
disable_interrupts(INT_EXT1);
clear_interrupt(INT_EXT1);
disable_interrupts(INT_EXT2);
clear_interrupt(INT_EXT2);
disable_interrupts(INT_EXT3);
clear_interrupt(INT_EXT3);
disable_interrupts(INT_EXT4);
clear_interrupt(INT_EXT4);
disable_interrupts(INT_FRC);
clear_interrupt(INT_FRC);
disable_interrupts(INT_IC1);
clear_interrupt(INT_IC1);
disable_interrupts(INT_IC2);
clear_interrupt(INT_IC2);
disable_interrupts(INT_IC3);
clear_interrupt(INT_IC3);
disable_interrupts(INT_IC4);
clear_interrupt(INT_IC4);
disable_interrupts(INT_IC5);
clear_interrupt(INT_IC5);
disable_interrupts(INT_IC6);
clear_interrupt(INT_IC6);
disable_interrupts(INT_LVD);
clear_interrupt(INT_LVD);
//disable_interrupts(INT_MATHERR);
clear_interrupt(INT_MATHERR);
disable_interrupts(INT_MI2C);
clear_interrupt(INT_MI2C);
disable_interrupts(INT_MI2C2);
clear_interrupt(INT_MI2C2);
disable_interrupts(INT_OC1);
clear_interrupt(INT_OC1);
disable_interrupts(INT_OC2);
clear_interrupt(INT_OC2);
disable_interrupts(INT_OC3);
clear_interrupt(INT_OC3);
disable_interrupts(INT_OC4);
clear_interrupt(INT_OC4);
disable_interrupts(INT_OC5);
clear_interrupt(INT_OC5);
disable_interrupts(INT_OC6);
clear_interrupt(INT_OC6);
//disable_interrupts(INT_OSCFAIL);
clear_interrupt(INT_OSCFAIL);
disable_interrupts(INT_PMP);
clear_interrupt(INT_PMP);
disable_interrupts(INT_RDA);
clear_interrupt(INT_RDA);
disable_interrupts(INT_RDA2);
clear_interrupt(INT_RDA2);
disable_interrupts(INT_RDA3);
clear_interrupt(INT_RDA3);
disable_interrupts(INT_RDA4);
clear_interrupt(INT_RDA4);
disable_interrupts(INT_RTC);
clear_interrupt(INT_RTC);
disable_interrupts(INT_SI2C);
clear_interrupt(INT_SI2C);
disable_interrupts(INT_SI2C2);
clear_interrupt(INT_SI2C2);
disable_interrupts(INT_SPI1E);
clear_interrupt(INT_SPI1E);
disable_interrupts(INT_SPI1RX);
clear_interrupt(INT_SPI1RX);
disable_interrupts(INT_SPI1TX);
clear_interrupt(INT_SPI1TX);
disable_interrupts(INT_SPI2E);
clear_interrupt(INT_SPI2E);
disable_interrupts(INT_SPI2RX);
clear_interrupt(INT_SPI2RX);
disable_interrupts(INT_SPI2TX);
clear_interrupt(INT_SPI2TX);
disable_interrupts(INT_SPI3E);
clear_interrupt(INT_SPI3E);
disable_interrupts(INT_SPI3RX);
clear_interrupt(INT_SPI3RX);
disable_interrupts(INT_SPI3TX);
clear_interrupt(INT_SPI3TX);
//disable_interrupts(INT_STACKERR);
clear_interrupt(INT_STACKERR);
disable_interrupts(INT_TBE);
clear_interrupt(INT_TBE);
disable_interrupts(INT_TBE2);
clear_interrupt(INT_TBE2);
disable_interrupts(INT_TBE3);
clear_interrupt(INT_TBE3);
disable_interrupts(INT_TBE4);
clear_interrupt(INT_TBE4);
disable_interrupts(INT_TIMER1);
clear_interrupt(INT_TIMER1);
disable_interrupts(INT_TIMER2);
clear_interrupt(INT_TIMER2);
disable_interrupts(INT_TIMER3);
clear_interrupt(INT_TIMER3);
disable_interrupts(INT_TIMER4);
clear_interrupt(INT_TIMER4);
disable_interrupts(INT_TIMER5);
clear_interrupt(INT_TIMER5);
disable_interrupts(INT_UART1E);
clear_interrupt(INT_UART1E);
disable_interrupts(INT_UART2E);
clear_interrupt(INT_UART2E);
disable_interrupts(INT_UART3E);
clear_interrupt(INT_UART3E);
disable_interrupts(INT_UART4E);
clear_interrupt(INT_UART4E);
}
|
I've got handlers for the two Interrupts as well
Code: |
#INT_EXT0
void HandlePushbutton()
{
}
#INT_RTC
void HandleRTCIRQ()
{
}
|
As to what the compiler has done with the sleep I am not sure
Code: |
010A8: MOV.B #5,W0L
010AA: MOV.B W0L,826
....................
.................... sleep(DEEP_SLEEP);
010AC: DISI #3
010AE: BSET.B 10F.7
010B0: BSET.B 10F.7
010B2: PWRSAV #0
.................... delay_cycles(10);
010B4: REPEAT #8
010B6: NOP
....................
....................
.................... break;
010B8: GOTO 10DE
.................... }
|
|
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Mon Sep 17, 2018 7:23 am |
|
|
Looking at the assembler - it doesn't look too far off the example in the datasheet, albeit the datasheet doesnt mention the PWRSAV #0 line
Quote: |
EXAMPLE 10-2: THE REPEAT SEQUENCE
Note: To re-enter Deep Sleep after a Deep Sleep
wake-up, allow a delay of at least 3 TCY
after clearing the RELEASE bit.
Note: A repeat sequence is required to set the
DSEN bit. The repeat sequence (repeating
the instruction twice) is required to write
into any of the Deep Sleep registers
(DSCON, DSWAKE, DSGPR0, DSGPR1).
This is required to prevent the user from
entering Deep Sleep by mistake. Any
write to these registers has to be done
twice to actually complete the write (see
Example 10-2).
Example 1:
mov #8000, w2 ; enable DS
mov w2, DSCON
mov w2, DSCON ; second write required to
actually write to DSCON
Example 2:
bset DSCON, #15
nop
nop
nop
bset DSCON, #15 ; enable DS (two writes required)
|
Last edited by JamesW on Mon Sep 17, 2018 7:37 am; edited 1 time in total |
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Mon Sep 17, 2018 7:37 am |
|
|
Out of curiosity I've had a go at doing it in assembler as well - but it doesn't seem to make any difference - in fact on about half the wakes the deep sleep flag itself isn't set, so it boots thinking it's a normal boot
Code: |
case SLEEPING:
{
fprintf(DEBUG_PORT,"\r\nSLEEPING");
delay_ms(100);
/* ALLOW US TO WAKE UP ON A PUSHBUTTON */
ext_int_edge(0, H_TO_L);
clear_interrupt(INT_EXT0);
enable_interrupts(INT_EXT0);
/* TURN ON THE MINUTE ALARM */
RTC_Enable_Minute_Alarm();
clear_interrupt(INT_RTC);
enable_interrupts(INT_RTC);
/* SWITCH STATE TO THE STATE WE WILL BE IN ON WAKE UP */
System.SleepManagerState = WAKING;
/* TRY USING HARD REGISTER ACCESS */
DEEP_SLEEP_ENABLE_BIT = 1;
DEEP_SLEEP_ENABLE_BIT = 1;
#asm
NOP
NOP
NOP
PWRSAV #0
#endasm
//! sleep(DEEP_SLEEP);
//! delay_cycles(3);
//!
break;
}
|
|
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Mon Sep 17, 2018 7:52 am |
|
|
Also - to add further to the confusion - the unit looks like it's attempting to boot up after the minute expires on the RTCC. The power increases, I get a little garbage out of the RS232 port - and then the power decreases to 42uA but it doesn't wake.
When I then press the ext int button, it tells me it's not woken from deep sleep. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Sep 17, 2018 8:29 am |
|
|
OK. Good start.
The instruction after the sleep shouldn't matter here (since deep_sleep resets). However if it did, you need delay_cycles(1), not 15. It has to be a NOP, which the longer delay does not guarantee to give...
The data sheet differs slightly from 39727b. Probably worth having a look at this!...
In the data sheet it says you have to set the enable bit twice (as the CCS driver is doing), but in the more detailed power saving note, it says that you have to enter sleep within one to three cycles of setting the DSEN bit, and that in the specific case of wanting to use the external interrupt, this must be three cycles. It also warns that if using a bit set to access the DSEN bit there must be a delay between the bit set operations.
The delay after setting the bit allows the interrupt hardware to get into the state required. So I'd use assembler:
Code: |
DEEP_SLEEP_ENABLE_BIT = 1;
delay_cycles(1);
delay_cycles(1);
delay_cycles(1);
DEEP_SLEEP_ENABLE_BIT = 1;
#asm
nop //This is meant to be needed to let the hardware get ready
nop
nop
pwrsav #0
#endasm
|
This gives the delays specified in the more detailed section. Will be interesting to see if it has any effect!...
The stupid thing is that the data sheet gives the first half of this, while the power save note gives the second. Stupidity!... |
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Mon Sep 17, 2018 8:47 am |
|
|
OK - I've now coded this in . . .
Code: |
case SLEEPING:
{
fprintf(DEBUG_PORT,"\r\nSLEEPING");
delay_ms(100);
/* ALLOW US TO WAKE UP ON A PUSHBUTTON */
ext_int_edge(0, H_TO_L);
clear_interrupt(INT_EXT0);
enable_interrupts(INT_EXT0);
/* TURN ON THE MINUTE ALARM */
RTC_Enable_Minute_Alarm();
clear_interrupt(INT_RTC);
enable_interrupts(INT_RTC);
delay_cycles(4);
/* SWITCH STATE TO THE STATE WE WILL BE IN ON WAKE UP */
System.SleepManagerState = WAKING;
//! /* TRY USING HARD REGISTER ACCESS */
//! DEEP_SLEEP_ENABLE_BIT = 1;
//! DEEP_SLEEP_ENABLE_BIT = 1;
//!
//! #asm
//! NOP
//! NOP
//! NOP
//! PWRSAV #0
//! #endasm
//! sleep(DEEP_SLEEP);
//! delay_cycles(10);
DEEP_SLEEP_ENABLE_BIT = 1;
delay_cycles(1);
delay_cycles(1);
delay_cycles(1);
DEEP_SLEEP_ENABLE_BIT = 1;
#asm
nop //This is meant to be needed to let the hardware get ready
nop
nop
pwrsav #0
#endasm
break;
}
|
Which has given me this output
Code: |
.................... //! /* TRY USING HARD REGISTER ACCESS */
.................... //! DEEP_SLEEP_ENABLE_BIT = 1;
.................... //! DEEP_SLEEP_ENABLE_BIT = 1;
.................... //!
.................... //! #asm
.................... //! NOP
.................... //! NOP
.................... //! NOP
.................... //! PWRSAV #0
.................... //! #endasm
.................... //! sleep(DEEP_SLEEP);
.................... //! delay_cycles(10);
....................
.................... DEEP_SLEEP_ENABLE_BIT = 1;
010B0: BSET.B 10F.7
.................... delay_cycles(1);
010B2: NOP
.................... delay_cycles(1);
010B4: NOP
.................... delay_cycles(1);
010B6: NOP
.................... DEEP_SLEEP_ENABLE_BIT = 1;
010B8: BSET.B 10F.7
....................
.................... #asm
.................... nop //This is meant to be needed to let the hardware get ready
010BA: NOP
.................... nop
010BC: NOP
.................... nop
010BE: NOP
.................... pwrsav #0
010C0: PWRSAV #0
.................... #endasm
|
I have also altered the start of main - as the act of reading the RCON register seems to clear it, so for clarity I read the register and bit test it.
Code: |
/* ------------------------------------------------------------------------- */
/* MAIN CODE */
void main()
{
UI_16 RConRegister = RCON_REG;
/* STAGE 1 - READ THE DEEP SLEEP BIT */
//if (DEEP_SLEEP_WAKE_BIT == TRUE)
if (bit_test( RConRegister,10) == TRUE)
{
/* CLEAR THIS BIT */
DEEP_SLEEP_WAKE_BIT = 0;
UI_16 DSWakeReg = DEEP_SLEEP_WAKE_REG;
//UI_16 RConRegister = RCON_REG;
DEEP_SLEEP_RELEASE_BIT = 0;
delay_ms(100); /* DELAY TO ALLOW THE UART TO WAKE */
fprintf(DEBUG_PORT,"\r\nDEEP SLEEP DSWAKE:%04X RCON:%04X INT0:%u RTCC:%u",DSWakeReg, RConRegister, DEEP_SLEEP_INT0_BIT, DEEP_SLEEP_RTCC_BIT);
|
When I wake on pushing the button I get this over RS232
Quote: |
STARTING SLEEP
SLEEPING
DEEP SLEEP DSWAKE:0000 RCON:0403 INT0:0 RTCC:0
UNKNOWN WAKE FROM DEEP SLEEP:0000
|
If I stay asleep for over a minute, the current starts off at 78uA, after a minute drops to 43uA (after rising for a second or so and outputting a couple of garbage characters to the screen - turned to red below)
If I then press the wake button - I get the message informing me that it hasn't woken from sleep as below
Quote: |
SLEEPING÷·¿¿ 766 NOT WOKEN FROM DEEP SLEEP:0000
DSCON:0000 DSWAKE:0000
|
|
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Mon Sep 17, 2018 8:52 am |
|
|
OK - for completeness I've looked at the start of the code.
Where I declare the variable for the RCON register, it doesn't appear to be reading the register contents into the variable - am I reading this right?
Code: |
.................... {
....................
....................
....................
.................... UI_16 RConRegister = RCON_REG;
....................
.................... /* STAGE 1 - READ THE DEEP SLEEP BIT */
.................... //if (DEEP_SLEEP_WAKE_BIT == TRUE)
.................... if (bit_test( RConRegister,10) == TRUE)
011A6: BTSS.B 1181.2
011A8: BRA 1340
.................... {
.................... /* CLEAR THIS BIT */
.................... DEEP_SLEEP_WAKE_BIT = 0;
011AA: BCLR.B 109.2
....................
.................... UI_16 DSWakeReg = DEEP_SLEEP_WAKE_REG;
011AC: PUSH 110
011AE: POP 1182
.................... //UI_16 RConRegister = RCON_REG;
....................
.................... DEEP_SLEEP_RELEASE_BIT = 0;
011B0: BCLR.B 10E.0
....................
.................... delay_ms(100); /* DELAY TO ALLOW THE UART TO WAKE */
011B2: MOV #64,W0
011B4: CALL 59C
.................... fprintf(DEBUG_PORT,"\r\nDEEP SLEEP DSWAKE:%04X RCON:%04X INT0:%u RTCC:%u",DSWakeReg, RConRegister, DEEP_SLEEP_INT0_BIT, DEEP_SLEEP_RTCC_BIT);
|
|
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Mon Sep 17, 2018 8:55 am |
|
|
However if I declare the start of main like this instead. . . .
Code: |
/* MAIN CODE */
void main()
{
UI_16 RConRegister;
RConRegister = RCON_REG;
/* STAGE 1 - READ THE DEEP SLEEP BIT */
//if (DEEP_SLEEP_WAKE_BIT == TRUE)
if (bit_test( RConRegister,10) == TRUE)
{
|
I get this
Code: |
.................... {
.................... UI_16 RConRegister;
....................
.................... RConRegister = RCON_REG;
0116E: PUSH 108
01170: POP 1180
....................
.................... /* STAGE 1 - READ THE DEEP SLEEP BIT */
.................... //if (DEEP_SLEEP_WAKE_BIT == TRUE)
.................... if (bit_test( RConRegister,10) == TRUE)
01172: BTSS.B 1181.2
01174: BRA 130C
.................... {
.................... /* CLEAR THIS BIT */
.................... DEEP_SLEEP_WAKE_BIT = 0;
01176: BCLR.B 109.2
|
I am assuming that there is some weird byte addressing thing going on here and bit 10 of 1180 is the same as 1181.2???? |
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Mon Sep 17, 2018 8:57 am |
|
|
However I can report that neither of those has made any difference to how it works - and it still half wakes up when the RTC interrupts the system and then the power drops - and then says it wasn't woken from deep sleep. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Sep 17, 2018 8:59 am |
|
|
It should be in the initialisation code for the block.
This is one reason why I hate declaring registers and initialising them in one line (except to fixed values). The actual initialisation does not occur where the code line appears.
Declare the variable and initialise it separately. You should then see the value being loaded. |
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Mon Sep 17, 2018 9:31 am |
|
|
This gets even stranger, I have now amended my main code to look like this (declaring both registers and then reading them, then forcing a clear of the release bit.
Code: |
/* MAIN CODE */
void main()
{
UI_16 RConRegister = 0, DSWakeReg = 0;
RConRegister = RCON_REG;
DSWakeReg = DEEP_SLEEP_WAKE_REG;
DEEP_SLEEP_RELEASE_BIT = 0;
/* STAGE 1 - READ THE DEEP SLEEP BIT */
//if (DEEP_SLEEP_WAKE_BIT == TRUE)
if (bit_test( RConRegister,10) == TRUE)
{
/* CLEAR THIS BIT */
DEEP_SLEEP_WAKE_BIT = 0;
|
My output of the code FROM A POWER UP looks like this.
In each case I am waiting approximately 2 seconds after the processor goes to sleep before triggering the INT0 pushbutton.
Quote: |
NOT WOKEN FROM DEEP SLEEP:0000
DSCON:0000 DSWAKE:0000
TICK:1 POWER BUT:1
TICK:2 POWER BUT:1
TICK:3 POWER BUT:1
TICK:4 POWER BUT:1
TICK:5 POWER BUT:1
TICK:6 POWER BUT:1
TICK:7 POWER BUT:1
TICK:8 POWER BUT:1
TICK:9 POWER BUT:1
TICK:10 POWER BUT:1
STARTING SLEEP
SLEEPING
DEEP SLEEP DSWAKE:0100 RCON:0403 INT0:1 RTCC:0
WAKE BUTTON FROM DEEP SLEEP:0100
DSCON:0000 DSWAKE:0100
AWAKE NOW
TICK:1 POWER BUT:1
TICK:2 POWER BUT:1
TICK:3 POWER BUT:1
TICK:4 POWER BUT:1
TICK:5 POWER BUT:1
TICK:6 POWER BUT:1
TICK:7 POWER BUT:1
TICK:8 POWER BUT:1
TICK:9 POWER BUT:1
TICK:10 POWER BUT:1
STARTING SLEEP
SLEEPING
DEEP SLEEP DSWAKE:0100 RCON:0403 INT0:1 RTCC:0
WAKE BUTTON FROM DEEP SLEEP:0100
DSCON:0000 DSWAKE:0100
AWAKE NOW
TICK:1 POWER BUT:1
TICK:2 POWER BUT:1
TICK:3 POWER BUT:1
TICK:4 POWER BUT:1
TICK:5 POWER BUT:1
TICK:6 POWER BUT:1
TICK:7 POWER BUT:1
TICK:8 POWER BUT:1
TICK:9 POWER BUT:1
TICK:10 POWER BUT:1
STARTING SLEEP
SLEEPING
DEEP SLEEP DSWAKE:0000 RCON:0403 INT0:0 RTCC:0
UNKNOWN WAKE FROM DEEP SLEEP:0000
DSCON:0000 DSWAKE:0000
AWAKE NOW
TICK:1 POWER BUT:1
TICK:2 POWER BUT:1
TICK:3 POWER BUT:1
TICK:4 POWER BUT:1
|
The first couple of times it woke - it tells me that the INT0 has triggered the wake, however then it reverts to telling me it has no idea what woke it |
|
|
JamesW
Joined: 23 Apr 2007 Posts: 91 Location: Rochester, England
|
|
Posted: Mon Sep 17, 2018 9:32 am |
|
|
RTCC still has no real effect |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Sep 17, 2018 11:23 am |
|
|
OK. You've moved forwards. Doesn't look like something odd like a watchdog triggering.
The one thing that will wake from deep sleep without setting a bit in the DSWAKE register, is DSBOR. Worth checking this.
As a comment, the deep sleep enable bit is cleared by the hardware on wake. You don't have to clear this. |
|
|
|