clock switching

General discussion on mikroBasic PRO for dsPIC30/33 and PIC24.
Post Reply
Author
Message
peterverkaik
Posts: 174
Joined: 31 Aug 2009 22:44

clock switching

#1 Post by peterverkaik » 24 Aug 2010 21:18

I found the following assembly code for clock switching.
I use a dsPIC33FJ32GP304 with external resonator of 20MHz at pins OSC1 and OSC2.

Code: Select all

  'PLLPRE (=N1=4 -> setting 00010)
  PLLPRE_4_bit = 0
  PLLPRE_3_bit = 0
  PLLPRE_2_bit = 0
  PLLPRE_1_bit = 1
  PLLPRE_0_bit = 0
  'PLLPOST (=N2=2 -> setting 00)
  PLLPOST_1_bit = 0
  PLLPOST_0_bit = 0
  'PLLFBD (=M=32 -> setting 30)
  PLLFBD = 30
  'OSCTUN
  OSCTUN = 0
  'OSCCON
  'NewOsccon = OSCCON 'get current OSCCON value
  'NewOsccon = NewOsccon AND $F8FE 'clear NOSC bits and OSWEN bit
  'NewOsccon = NewOsccon OR $0300 'new oscillator setting = 3 -> Primary Oscillator with PLL
  asm
    'const OSCCONH as word = 0x0743 'volatile sfr
    ';Place the New Oscillator Selection (NOSC=0b011) in W0
    MOV #0x13, W0
    ';OSCCONH (high byte) Unlock Sequence
    MOV #0x0743, W1
    MOV #0x78, W2
    MOV #0x9A, W3
    MOV.B W2, [W1] '; Write 0x78
    MOV.B W3, [W1] '; Write 0x9A
    ';Set New Oscillator Selection
    MOV.B W0, 0x0743
    '; Place 0x01 in W0 for setting clock switch enabled bit
    MOV #0x01, W0
    ';OSCCONL (low byte) Unlock Sequence
    MOV #OSCCONL, W1
    MOV #0x46, W2
    MOV #0x57, W3
    MOV.B W2, [W1] '; Write 0x46
    MOV.B W3, [W1] '; Write 0x57
    '; Enable Clock Switch
    MOV.B W0, [W1]
    '; Request Clock Switching by Setting OSWEN bit
WaitForOswen:
    BTSC OSCCON, #0
    BRA WaitForOswen
  end asm
  while OSCCON.LOCK_bit = 0  'wait for PLL to lock
  wend
  
  AD1PCFGL = $FFFF  'In order to use PORTB pins for digital I/O, the corresponding bits in
                    'the AD1PCFGL register must be set to ‘1’, even if A/D module is turned off.



The compiler generates following errors:
142 313 Invalid ASM instruction: "MOV.B W0, 0x0743" SerialRGBW.mbas

The 0x0743 is the address of the highbyte of OSCCON register
OSCCONL is declared, but OSCCONH is not in the P33FJ32GP304 definition file
OSCCON as word absolute 0x0742 volatile sfr
OSCCONL as word absolute 0x0742 volatile sfr
I would add/change the following for OSCCONH and OSCCONL
OSCCONL as byte absolute 0x0742 volatile sfr
OSCCONH as byte absolute 0x0743 volatile sfr

What is wrong with my assembly code?

regards peter

User avatar
milan
mikroElektronika team
Posts: 1013
Joined: 04 May 2006 16:36
Contact:

Re: clock switching

#2 Post by milan » 22 Sep 2010 14:36

Hi,

I am sorry for the late reply.

Problem are asm lines

Code: Select all

MOV.B W0, 0x0743
MOV #OSCCONL, W1
MOV.B W0, 0x0743 is bad syntax, see http://ww1.microchip.com/downloads/en/D ... f#page=219
first, it looks like operands are swapped, W0 should be destination.
Second, .B means byte mode, 0x0743 is number that is outside the byte range.
Third, literals should start with #
If you want to move 0x0743 to W0, write this

Code: Select all

MOV #0x0743, W0
Another thing,

Code: Select all

OSCCONH as byte absolute 0x0743 volatile sfr
will generate "bad address alignment" error. (dsPIC specific)




Second line should be

Code: Select all

MOV OSCCONL, W1 ; if you want to move content of OSCCONL to W1
or

Code: Select all

MOV @OSCCONL, W1 ; if you want to move address of OSCCONL to W1
SmartADAPT2 rules !

peterverkaik
Posts: 174
Joined: 31 Aug 2009 22:44

Re: clock switching

#3 Post by peterverkaik » 22 Sep 2010 16:20

Hi,

I managed to get things compiled without error.

Code: Select all

dim B_OSCCONH as byte absolute 0x0743 volatile sfr
dim B_OSCCONL as byte absolute 0x0742 volatile sfr

sub procedure ClockSwitch()
  'FOSC = ((FIN / N1) * M) / N2 = ((20 MHz / 4) * 32) / 2 = 80 MHz
  'PLLPRE (=N1=4 -> setting 00010)
  PLLPRE_4_bit = 0
  PLLPRE_3_bit = 0
  PLLPRE_2_bit = 0
  PLLPRE_1_bit = 1
  PLLPRE_0_bit = 0
  'PLLPOST (=N2=2 -> setting 00)
  PLLPOST_1_bit = 0
  PLLPOST_0_bit = 0
  'PLLFBD (=M=32 -> setting 30)
  PLLFBD = 30
  'OSCTUN
  OSCTUN = 0
  'OSCCON
  asm
    ;Place the New Oscillator Selection (NOSC=0b011) in W0
    MOV #0x03, W0
    ;OSCCONH (high byte) Unlock Sequence
    MOV #B_OSCCONH, W1
    MOV #0x78, W2
    MOV #0x9A, W3
    MOV.B W2, [W1] ; Write 0x78
    MOV.B W3, [W1] ; Write 0x9A
    ;Set New Oscillator Selection
    MOV.B W0, [W1]
    ; Place 0x01 in W0 for setting clock switch enabled bit
    MOV #0x01, W0
    ;OSCCONL (low byte) Unlock Sequence
    MOV #B_OSCCONL, W1
    MOV #0x46, W2
    MOV #0x57, W3
    MOV.B W2, [W1] ; Write 0x46
    MOV.B W3, [W1] ; Write 0x57
    ; Request Clock Switching by Setting OSWEN bit
    MOV.B W0, [W1]
  end asm
  while OSCCON.OSWEN_bit = 1
  wend
  while OSCCON.LOCK_bit = 0  'wait for PLL to lock
  wend
end sub

At the main I start with

Code: Select all

'********************************************************
'* Program body:
'********************************************************
main:
  AD1PCFGL = $FFFF  'In order to use PORTB pins for digital I/O, the corresponding bits in
                    'the AD1PCFGL register must be set to ‘1’, even if A/D module is turned off.


  ClockSwitch()
  
but the program is not running. I have a flashing led that only flashes when I
use the internal FRC oscillator.
So either the external resonator is not working or the code is incorrect.
I copied this code from the datasheet.

I disagree that an odd address definition is improper.
The unlock sequences require a byte write to the high byte of a 16bits sfr register.

regards peter

User avatar
milan
mikroElektronika team
Posts: 1013
Joined: 04 May 2006 16:36
Contact:

Re: clock switching

#4 Post by milan » 23 Sep 2010 08:51

Hi,
peterverkaik wrote:I disagree that an odd address definition is improper.
You are right, I accidentally typed word instead of byte and I got an error. Sorry for making confusion :oops:
peterverkaik wrote:I copied this code from the datasheet.
It will help if you give us a link to the original code.
Then mikroElektronika team and forum members can help you to port the code.
SmartADAPT2 rules !

peterverkaik
Posts: 174
Joined: 31 Aug 2009 22:44

Re: clock switching

#5 Post by peterverkaik » 23 Sep 2010 09:33

Here is the link
http://ww1.microchip.com/downloads/en/D ... 70216C.pdf

I took the code from chapter 39.12 (clockswitching) example 39-3

Code: Select all

;Place the New Oscillator Selection (NOSC=0b101) in W0
MOV #0x15, WREG
;OSCCONH (high byte) Unlock Sequence
MOV#OSCCONH, w1
MOV#0x78, w2
MOV#0x9A, w3
MOV.B w2, [w1] ; Write 0x78
MOV.B w3, [w1] ; Write 0x9A
;Set New Oscillator Selection
MOV.B WREG, OSCCONH
; Place 0x01 in W0 for setting clock switch enabled bit
MOV #0x01, w0
;OSCCONL (low byte) Unlock Sequence
MOV #OSCCONL, w1
MOV #0x46, w2
MOV #0x57, w3
MOV.B w2, [w1]; Write 0x46
MOV.B w3, [w1]; Write 0x57
; Enable Clock Switch
MOV.B w0, [w1]
; Request Clock Switching by Setting OSWEN bit
wait:
btsc OSCCONL, #OSWEN
bra wait
regards peter

User avatar
milan
mikroElektronika team
Posts: 1013
Joined: 04 May 2006 16:36
Contact:

Re: clock switching

#6 Post by milan » 24 Sep 2010 09:45

Hi,

this code should be equivalent

Code: Select all

program test
main:
 asm
    ;Place the New Oscillator Selection (NOSC=0b101) in W0
    MOV #0x15, WREG
    ;OSCCONH (high byte) Unlock Sequence
    MOV #Lo_Addr(OSCCONH), w1
    MOV #0x78, w2
    MOV #0x9A, w3
    MOV.B w2, [w1] ; Write 0x78
    MOV.B w3, [w1] ; Write 0x9A
    ;Set New Oscillator Selection
    MOV.B WREG, OSCCONH
    ; Place 0x01 in W0 for setting clock switch enabled bit
    MOV #0x01, w0
    ;OSCCONL (low byte) Unlock Sequence
    MOV #Lo_Addr(OSCCONL), w1
    MOV #0x46, w2
    MOV #0x57, w3
    MOV.B w2, [w1]; Write 0x46
    MOV.B w3, [w1]; Write 0x57
    ; Enable Clock Switch
    MOV.B w0, [w1]
    ; Request Clock Switching by Setting OSWEN bit
wait:
    btsc OSCCONL, #0 ;#OSWEN
    bra wait
  end asm

end.
#OSWEN should not generate an error, I will report this to asm parser coders.
Thank you for helping us, I hope the code will work.
SmartADAPT2 rules !

gbtjom
Posts: 58
Joined: 13 Jan 2012 23:48

Re: clock switching

#7 Post by gbtjom » 18 Nov 2012 03:23

I found this thread because this relates to something I'm working on. I tried using this:

Code: Select all

 
dim OSCCONH as byte absolute 0x0743 volatile sfr
.....

sub procedure ASMChangeOsc(dim SetOsc as byte)

    asm
      ;Place the New Oscillator Selection in W0
      MOV #SetOsc, WREG
      ;OSCCONH (high byte) Unlock Sequence
      MOV #OSCCONH, w1
      MOV #0x78, w2
      MOV #0x9A, w3
      MOV.B w2, [w1] ; Write 0x78
      MOV.B w3, [w1] ; Write 0x9A
      ;Set New Oscillator Selection
      MOV.B WREG, OSCCONH
      ; Place 0x01 in W0 for setting clock switch enabled bit
      MOV #0x01, w0
      ;OSCCONL (low byte) Unlock Sequence
      MOV #Lo_Addr(OSCCONL), w1
      MOV #0x46, w2
      MOV #0x57, w3
      MOV.B w2, [w1]; Write 0x46
      MOV.B w3, [w1]; Write 0x57
      ; Enable Clock Switch
      MOV.B w0, [w1]
      ; Request Clock Switching by Setting OSWEN bit
    wait:
      btsc OSCCONL, #0 ;#OSWEN
      bra wait
    end asm
      
  end sub
However, I get several errors:

1) MOV #SetOsc, WREG

Identifier "SetOsc" was not declared.

I'm trying to make the number moved into WREG on that line a variable which gets brought into the procedure. I guess I wanted it to be more flexible than just the constant (0X15) used above. It will be one of the oscillator settings from NOSC in the OSCCON register. Whatever the case why is this an error?

2) This line:

btsc OSCCONL, #0

gives an error if you replace #0 with #OSWEN. That shouldn't be an error should it?

3) I can't find any reference to the command "Lo_Addr()". I have no idea what it is suppose to do. If I take out the "Lo_Addr" and just use:

MOV #OSCCONL, w1

I get an Invalid ASM instruction error. Why? This line above it:

MOV #OSCCONH, w1

doesn't give an error.

I'm completely confused here....

jom

User avatar
janko.kaljevic
Posts: 3565
Joined: 16 Jun 2011 13:48

Re: clock switching

#8 Post by janko.kaljevic » 19 Nov 2012 18:15

Hello,

The main problem is in naming of variables in asm.
For example variable which is a parameter of the function has it's unique name in asm.
In your case try with:

Code: Select all

MOV FARG_ASMChangeOsc_SetOsc, WREG
You can not use register definitions with literals.
Lo_addr() function will store lower two bytes of the address of desired register into desired destination.
And you should use it in your code.

So in this case your function should look as follows:

Code: Select all

sub procedure ASMChangeOsc(dim SetOsc as byte)

    asm   
    ;Place the New Oscillator Selection (NOSC=0b101) in W0
    MOV FARG_ASMChangeOsc_SetOsc, WREG
    ;OSCCONH (high byte) Unlock Sequence
    MOV #Lo_Addr(OSCCONH), w1
    MOV #0x78, w2
    MOV #0x9A, w3
    MOV.B w2, [w1] ; Write 0x78
    MOV.B w3, [w1] ; Write 0x9A
    ;Set New Oscillator Selection
    MOV.B WREG, OSCCONH
    ; Place 0x01 in W0 for setting clock switch enabled bit
    MOV #0x01, w0
    ;OSCCONL (low byte) Unlock Sequence
    MOV #Lo_Addr(OSCCONL), w1
    MOV #0x46, w2
    MOV #0x57, w3
    MOV.B w2, [w1]; Write 0x46
    MOV.B w3, [w1]; Write 0x57
    ; Enable Clock Switch
    MOV.B w0, [w1]
    ; Request Clock Switching by Setting OSWEN bit
wait:
    btsc OSCCONL, #0
    bra wait
    end asm
     
  end sub
And do not forget to allow Clock switching in Config words.
To do this go to Project->Edit Project and under Clock Switching and Monitor set:
Clock switching is enabled.

Best regards.

gbtjom
Posts: 58
Joined: 13 Jan 2012 23:48

Re: clock switching

#9 Post by gbtjom » 19 Nov 2012 20:19

Thanks for that Janko. A couple of things:

1) Where can I find info on this use of "FARG_ASMChangeOsc_SetOsc"? I'm going to guess and say that if the Procedure name was XXX and the dim was YYY I'd use:

FARG_XXX_YYY

Is this correct? Whatever the case, where can I find documentation on this?

2) This statement:

MOV #Lo_Addr(OSCCONH), w1

This actually compiled when I did this instead:

MOV #OSCCONH, w1

Yet this did NOT compile

MOV #OSCCONL, w1

Why? They seem the same to me.

Using Lo_Addr() is odd since both OSCCONH and L are bytes so how can Lo_Addr() take take "lower two bytes" from a byte size variable? I' still confused. :D Also, where is the documentation on this?

3) Why didn't OSWEN work?

Thanks for the help!

jom

User avatar
janko.kaljevic
Posts: 3565
Joined: 16 Jun 2011 13:48

Re: clock switching

#10 Post by janko.kaljevic » 20 Nov 2012 10:32

Hello,

This explanation is currently listed in dsPIC compiler, and t will be propagated to all other.
Accessing variables
Depending on the place of declaration, accessing a variable can be done in several ways :

Accessing global variable :
1. If declared as static (visible only in the file where it was declared) : <source_file_name>_<variable_name>.
2. If declared as a non-static global (visible throughout the whole project) : _<variable_name>.
3. If accessing registers (declared through register, rx or sfr specifiers, visible throughout the whole project) : <variable_name>.
Accessing local variable : <routine_name>_<variable_name>.
Accessing routine parameter : FARG_<routine_name>_<variable_name>.
Yes it will give the same generated code, but as I said you should not use registers (sfrs) as literal value.
And this is the reason why it was not compiled in other case. OSCCONL was declared in other source file.

And Lo_addr() will take 16 bit address of desired register/sfr.

The same as before. OSWEN is constant declared in another source file.
In order to use it as literal declare it in the same source file.

I assume that you confirmed that the code is working.

Best regards.

gbtjom
Posts: 58
Joined: 13 Jan 2012 23:48

Re: clock switching

#11 Post by gbtjom » 20 Nov 2012 21:29

Yes, the code is working! Thanks!

The concept of the "address" itself vs. the actual value has always been a bit of a mental block for me so I apologize for the questions.

The quoted text you gave above about Accessing Variables comes from the MB Pro for dsPIC compiler manual, true? If so, is there an available latest version of this somewhere in .pdf format? If not, it is online somewhere?

Thanks for the help.

jom

User avatar
janko.kaljevic
Posts: 3565
Joined: 16 Jun 2011 13:48

Re: clock switching

#12 Post by janko.kaljevic » 21 Nov 2012 09:41

Hello,

quoted text is from the help file for dsPIC compiler under asm Declaration description.

Best regards.

Post Reply

Return to “mikroBasic PRO for dsPIC30/33 and PIC24 General”