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 support@ccsinfo.com

clock switching at PIC24 does not work
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
andresteff



Joined: 21 Mar 2020
Posts: 44

View user's profile Send private message

clock switching at PIC24 does not work
PostPosted: Mon May 03, 2021 2:47 am     Reply with quote

Hi,
I have a big problem with clock switching.
In standby the clock should have 31kHz with LPRC.
Outside the standby the clock should have 500kHz with LPFRC.

Here little test program. It does not work correctly.
The last switching to the 31kHz LPRC does not work!
The PIC works with 125kHz!

Where is the problem?


CCS Version: 5.080 with IDE
PIC: PIC24F16KA301
ICD3
Code:

#include <24F16KA301.h>

#device ADC=8       
#device ICSP=1
#use delay(RC=31000)


#fuses LPRC                      //Internal low power RC Oscillator
#fuses NOCKSFSM                  //Clock Switching is disabled, fail Safe clock monitor is disabled

#FUSES NOBROWNOUT                //No brownout reset
#fuses MCLR                      //Master Clear pin enabled
#fuses PUT                       //Power Up Timer
#fuses SOSC_DIGITAL              //SOSC pins set for Digital mode for use with external clock or Digital I/O
#fuses NOWDT                     //No Watch Dog Timer
#fuses WDT_SW                    //No Watch Dog Timer, enabled in Software

// LPRC=31kHz           
            setup_oscillator(OSC_RC, 0);     
            #use delay(RC=31000)
            delay_ms(100);
         
            output_high(LED_RT); 
            delay_ms(1000);
            output_low(LED_RT);
            delay_ms(2000);
             
             
             
// LPFRC=500kHz             
            setup_oscillator( OSC_LPFRC, 500000);       
            #use delay(clock=500000)
            delay_ms(100);
           
            output_high(LED_RT); 
            delay_ms(1000);
            output_low(LED_RT);
            delay_ms(2000);
           
           
// LPFRC=125kHz
            setup_oscillator( OSC_LPFRC, 125000);       
            #use delay(clock=125000)
            delay_ms(100);
           
            output_high(LED_RT); 
            delay_ms(1000);
            output_low(LED_RT);
            delay_ms(2000);
           
           
 // LPRC=31kHz           
            setup_oscillator(OSC_RC, 0);     
            #use delay(RC=31000)
            delay_ms(100);
         
            output_high(LED_RT); 
            delay_ms(1000);
            output_low(LED_RT);
            delay_ms(2000);
             
             
             while(1){}
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Mon May 03, 2021 3:10 am     Reply with quote

I don't know if this is what is causing your problem, but change your
fail safe fuse to:

#fuses CKSNOFSM //Clock Switching is enabled, fail Safe clock monitor is disabled

This changes the bit pattern put into the two bits controlling clock switching.
With this, you get 0x7B, which is the correct setting to allow clock switching,
but disable FSCM. I think this stands for Clock Switching, No FSM. Your
current setting gives No Clock Switching or FSM. This obviously causes
problems when you try to do clock switching!....

There are also problems with your settings. The LPRC, only support 31000Hz,
not 125000. The RC supports 125000 Hz. You are also saying to set the
clock to 0. Both wrong.
andresteff



Joined: 21 Mar 2020
Posts: 44

View user's profile Send private message

PostPosted: Mon May 03, 2021 9:01 am     Reply with quote

I changed the Fuse to:
Code:
#fuses CKSNOFSM //Clock Switching is enabled, fail Safe clock monitor is disabled

The same wrong behavior!

The last switch to 31kHz LPRC does not work.
The led pulse is not 1s, but 0,25s. This shows, that the PIC runs with 125kHz, like the last setting.

The LPRC runs only with 31kHz. I can't write any value, except zero in the function:
Code:
           
// LPRC=31kHz           
setup_oscillator(OSC_RC,0);     
#use delay(RC=31000)
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Tue May 04, 2021 12:18 am     Reply with quote

You are still using 0 for the frequency.
This says 'use the last frequency specified'. Since your last frequency was
125000, the clock setting again sets 125000....

The first time you do this, it works, since the last frequency selected was
31KHz in the boot. The second time, it won't since there is effectively
a conflict between the clock source you are asking for, and the frequency
you specify.
andresteff



Joined: 21 Mar 2020
Posts: 44

View user's profile Send private message

PostPosted: Tue May 04, 2021 8:56 am     Reply with quote

I can't write any other value in this function, except 0: setup_oscillator(OSC_RC,0);

For example: setup_oscillator(OSC_RC, 31000);
The compiler reports:
*** Error 99 "main-GX3.c" Line 408(37,42): Option invalid :: No PLL option

"0" is the only value with which the compiler compiles!

Which value should be write in the function for 31k LPRC?
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Tue May 04, 2021 9:55 am     Reply with quote

OK. That implies the compiler is not switching to the 31K oscillator.
Instead it is trying to switch using the LPRC oscillator with it's division and
PLL options. I remember this coming up in a thread ages ago. Will have to
do some experiments and see what your compiler version actually does.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Wed May 05, 2021 1:10 am     Reply with quote

Why do you want to do this?.
Simplify.
Just use the single oscillator, and switch divisions. The power difference
is tiny.
The problem seems to be that the compiler does not correctly identify the
LPRC option. It doesn't then like switching to this. The value in the
setup_oscillator does not give the correct values for this clock setting.

So:
Code:

#use delay(INTERNAL=31250)
#FUSES WDT_SW                    //No Watch Dog Timer
#FUSES MCLR
#FUSES CKSNOFSM                   //Clock Switching is enabled, fail Safe clock monitor is disabled
#FUSES SOSC_LOW        //these seem to slightly reduce power
#FUSES POSCFREQ_L
#fuses SOSC_DIGITAL
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BORV_LOW                 //Brown-out Reset set to lowest voltage

// LPFRC=31250kHz           
            setup_oscillator(OSC_LPFRC, 31250);     
            #use delay(clock=31250)
            delay_ms(100);
         
            output_high(LED_RT);
            delay_ms(1000);
            output_low(LED_RT);
            delay_ms(2000);
             
             
             
// LPFRC=500kHz             
            setup_oscillator( OSC_LPFRC, 500000);       
            #use delay(clock=500000)
            delay_ms(100);
           
            output_high(LED_RT);
            delay_ms(1000);
            output_low(LED_RT);
            delay_ms(2000);
           
           
// LPFRC=125kHz
            setup_oscillator( OSC_LPFRC, 125000);       
            #use delay(clock=125000)
            delay_ms(100);
           
            output_high(LED_RT);
            delay_ms(1000);
            output_low(LED_RT);
            delay_ms(2000);
           
           
 // LPFRC=31250kHz           
            setup_oscillator(OSC_LPFRC, 31250);     
            #use delay(clock=31250)
            delay_ms(100);
         
            output_high(LED_RT);
            delay_ms(1000);
            output_low(LED_RT);
            delay_ms(2000);


These are all merrily accepted and do correctly switch.

What is happening is the LPRC actually stops when you switch away from
it. It only stays working if the WDT is enabled or FSCM is enabled. It then
doesn't like trying to switch back to it....
andresteff



Joined: 21 Mar 2020
Posts: 44

View user's profile Send private message

PostPosted: Wed May 05, 2021 1:20 pm     Reply with quote

Does this mean the chip is buggy?
I can't change from any clock to the 31kHz LPRC?
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Thu May 06, 2021 12:38 am     Reply with quote

No, you'd have to keep the LPRC running. Enable the WDT, and it'll keep
running whatever oscillator you have selected. Or enable FSCM in the fuses
(no disadvantage to having this enabled), and again the LPRC will then
keep running. However there is a problem in this case, since FSCM will fail
with an oscillator under 100KHz....
andresteff



Joined: 21 Mar 2020
Posts: 44

View user's profile Send private message

PostPosted: Thu May 06, 2021 10:54 am     Reply with quote

-WDT=on
-FSCM=on
the µc switch NOT to the LPRC! The wdt is on and runs!

The asm code show, that switch to 500kHz LPFRC! (switch to 31kHz)
at line: 02AC: MOV #102,W0 => NOSC-Bits=110=500kHz LPFRC

Code:

.................... // LPRC=31kHz           
....................             setup_oscillator(OSC_RC, 0);     
02A8:  CLR     744
02AA:  DISI    #E
02AC:  MOV     #102,W0
02AE:  MOV     #743,W1
02B0:  MOV     #78,W2
02B2:  MOV     #9A,W3
02B4:  MOV.B   W2L,[W1]
02B6:  MOV.B   W3L,[W1]
02B8:  MOV.B   W0L,743
02BA:  LSR     W0,#8,W0
02BC:  MOV     #742,W1
02BE:  MOV     #46,W2
02C0:  MOV     #57,W3
02C2:  MOV.B   W2L,[W1]
02C4:  MOV.B   W3L,[W1]
02C6:  MOV.B   W0L,[W1]
....................             #use delay(clock=31000)
....................             delay_ms(100);
02C8:  REPEAT  #5DA
02CA:  NOP     





Complete code example :

Code:

#include <24F16KA301.h>
#device ADC=8       
#device ICSP=3

#use delay(internal=500000)

#fuses LPFRC_DIV              //Low-Power FRC oscillator with divide-by-N
#fuses LPRCLOW                //Low-Power FRC Low Power and Low Accuracy
#fuses CKSFSM                 //Clock Switching is enabled, fail Safe clock monitor is enabled

#fuses WDT_SW                    //No Watch Dog Timer, enabled in Software



#FUSES NOBROWNOUT                //No brownout reset
#fuses MCLR                      //Master Clear pin enabled
#fuses PUT                       //Power Up Timer
#fuses SOSC_DIGITAL              //SOSC pins set for Digital mode for use with external clock or Digital I/O

 
//#fuses LPRC                      //Internal low power RC Oscillator
//#fuses CKSNOFSM                  //Clock Switching is enabled, fail Safe clock monitor is disabled
//#fuses WPOSTS16          //Watch Dog Timer PostScalar 1:32768


#define LED_RT  PIN_B7



void main()
{
            setup_wdt(WDT_8S);
            restart_wdt();
         
         
// LPFRC=31250kHz           
            setup_oscillator(OSC_LPFRC, 31250);     
            #use delay(clock=31250)
            delay_ms(100);
         
            output_high(LED_RT);
            delay_ms(1000);
            output_low(LED_RT);
            delay_ms(2000);
            restart_wdt();
                   
// LPFRC=125kHz
            setup_oscillator( OSC_LPFRC, 125000);       
            #use delay(clock=125000)
            delay_ms(100);
           
            output_high(LED_RT); 
            delay_ms(1000);
            output_low(LED_RT);
            delay_ms(2000);
            restart_wdt();
           
// LPRC=31kHz           
            setup_oscillator(OSC_RC, 0);     
            #use delay(clock=31000)
            delay_ms(100);
         
            output_high(LED_RT); 
            delay_ms(1000);
            output_low(LED_RT);
            delay_ms(2000);
            restart_wdt();
             
            while(1){ } // "wdt-loop", after 8s wdt time out
 
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Fri May 07, 2021 12:02 am     Reply with quote

As I said earlier:

Quote:

OK. That implies the compiler is not switching to the 31K oscillator.
Instead it is trying to switch using the LPRC oscillator with it's division and
PLL options. I remember this coming up in a thread ages ago. Will have to
do some experiments and see what your compiler version actually does.


The setup oscillator on your compiler version at least does not know how
to actually switch to the RC oscillator. Instead it uses the LPRC.

This is why it won't accept the 31000, since it 'knows' this is not an
available PLL/DIV option.

This should allow the switch to 31K. Call this instead of the
setup_oscillator(OSC_RC, 0); line:

Code:

#WORD OSCCON=getenv("SFR:OSCCON")
#WORD CLKDIV=getenv("SFR:CLKDIV")
#DEFINE NOSC 0b0101
#bit OSWEN=OSCCON.0

void change_toRC31K(void)
{
   //routine to switch oscillator to the RC at 31000Hz, on compiler not suporting this
#ASM
   MOV.b NOSC, W0 //new value to load
   MOV #0x743,W1 //address to write to
   MOV #0x78, W2
   MOV #0x9A, W3 //preload unlock sequence
   DISI #5
   //write unlock
   MOV.b W2, [W1]
   mov.b W3, [W1]
   mov.b W0, [W1]
   
   MOV.b #1, W0 //new value to load OSWEN
   MOV #0x742,W1 //address to write to
   DISI #5
   MOV #0x46, W2
   MOV #0x57, W3 //preload unlock sequence
   //write unlock
   MOV.b W2, [W1]
   mov.b W3, [W1]   
   //Trigger switch
   mov.b W0, [W1]
#ENDASM   
   //Now need to wait for the RC oscillator to start
   delay_us(70); //wait for LPRC to start. Needs 70uSec. Time will be variable since
   //clock may switch at some point
   while (OSWEN!=0)
      ; //wait for switch to be successful
}

Use like:
Code:

// LPRC=31kHz           
change_toRC31K();   
#use delay(clock=31000)
andresteff



Joined: 21 Mar 2020
Posts: 44

View user's profile Send private message

PostPosted: Fri May 07, 2021 9:03 am     Reply with quote

I test the code, but the PIC runs with 8MHz!? (PIC Current ca. 4mA)

I found this asm code example in "Section 38. Oscillator with 500 kHz Low-Power FRC", on page 22.

They write explicit "OSCCONH" and "OSCCONL" ?????

Code:

;Place the new oscillator selection in W0
;OSCCONH (high byte) Unlock Sequence
MOV #OSCCONH,w1
MOV #0x78, w2
MOV #0x9A, w3
MOV.b w2, [w1]
MOV.b w3, [w1]
;Set new oscillator selection
MOV.b WREG, OSCCONH
;OSCCONL (low byte) unlock sequence
MOV #OSCCONL,w1
MOV.b #0x01, w0
MOV #0x46, w2
MOV #0x57, w3
MOV.b w2, [w1]
MOV.b w3, [w1]
;Start oscillator switch operation
MOV.b w0, [w1]
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Fri May 07, 2021 11:09 am     Reply with quote

This line is what is wrong:

MOV.b NOSC, W0 //new value to load

Needs to be

MOV.b #5 W0 //new value to load

As I posted it is treating the NOSC define as a pointer, not a constant.
andresteff



Joined: 21 Mar 2020
Posts: 44

View user's profile Send private message

PostPosted: Sat May 08, 2021 6:32 am     Reply with quote

Very fine it works!

For comparison:
Current consumption:
31000Hz LPRC = ca.15µA
31250Hz LPFRC = ca. 150µA

(Ok, the tolerance of the frequency by the 31000Hz is significantly worse +-15%).
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Sun May 09, 2021 11:43 pm     Reply with quote

Fair enough.
It does seem rather silly to be trying to keep such a powerful chip 'awake'
at such slow speeds. Thing is you can do so much more by just going
up to a proper operating speed for a tiny burst of time. If you really want
to actually be operating at such slow speeds, consider a much less
power hungry chip. A PIC18 will draw a tiny fraction of the power. You only
show your top speed at 125KHz, and if you are working at such a slow top
speed a less powerful chip really would be the better choice.
That the designers really don't expect low power operation from this chip
family is reflected in the KV version where the voltage regulator wastes about
250uA all the time. Sad
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