|
|
View previous topic :: View next topic |
Author |
Message |
andresteff
Joined: 21 Mar 2020 Posts: 44
|
clock switching at PIC24 does not work |
Posted: Mon May 03, 2021 2:47 am |
|
|
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: 19504
|
|
Posted: Mon May 03, 2021 3:10 am |
|
|
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
|
|
Posted: Mon May 03, 2021 9:01 am |
|
|
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: 19504
|
|
Posted: Tue May 04, 2021 12:18 am |
|
|
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
|
|
Posted: Tue May 04, 2021 8:56 am |
|
|
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: 19504
|
|
Posted: Tue May 04, 2021 9:55 am |
|
|
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: 19504
|
|
Posted: Wed May 05, 2021 1:10 am |
|
|
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
|
|
Posted: Wed May 05, 2021 1:20 pm |
|
|
Does this mean the chip is buggy?
I can't change from any clock to the 31kHz LPRC? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Thu May 06, 2021 12:38 am |
|
|
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
|
|
Posted: Thu May 06, 2021 10:54 am |
|
|
-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: 19504
|
|
Posted: Fri May 07, 2021 12:02 am |
|
|
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
|
|
Posted: Fri May 07, 2021 9:03 am |
|
|
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: 19504
|
|
Posted: Fri May 07, 2021 11:09 am |
|
|
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
|
|
Posted: Sat May 08, 2021 6:32 am |
|
|
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: 19504
|
|
Posted: Sun May 09, 2021 11:43 pm |
|
|
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. |
|
|
|
|
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
|