assembly syntax

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

assembly syntax

#1 Post by peterverkaik » 17 Dec 2009 16:09

I have some procedures written as assembly.
These asm instructions are converted from Microchip C30
and were also tested in MikroE C PRO for dsPIC.

One of the routines is

Code: Select all

'//state 0: wait for data in transmit buffer, check if transmission may begin
'//Cycles is 23
sub procedure dvpSTX_S0
'/*
'  register vpBank *slot asm("w5");
'  register unsigned int portSelect asm("w4");
'  register unsigned int portInput asm("w3");
'  register unsigned int pinMask asm("w2");
'  if (slot->vpUart.nmUartFlag) { //data to transmit?
'    portSelect = slot->vpUart.nmUartHSPort;
'    pinMask = slot->vpUart.nmUartHSPin;
'    if (pinMask) { //hardware handshake (CTS input) used
'      portInput = PORTB;
'      if (portSelect & 0x02) portInput = PORTC;
'      if (slot->vpUart.nmUartHSInvert) portInput = ~portInput;
'      if (portSelect & 0x01) pinMask <<= 8;
'      if (portInput & pinMask) //CTS asserted, transmission may begin
'        slot->statePtr = &dvpSTX_S4; //next state
'    }
'    else { //no hardware handshake, transmission may begin
'      slot->statePtr = &dvpSTX_S4; //next state
'    }
'  }
'  else { //wait for data in transmit buffer
'    if (slot->vpUart.nmUartHead != slot->vpUart.nmUartTail) { //buffer not empty
'      slot->vpUart.nmUartFlag = 1; //mark transmitter busy
'      slot->statePtr = &dvpSTX_S1; //next state
'      slot->vpUart.nmUartDataH &= 0x7F; //setup startbit (true mode)
'    }
'  }
'*/
  '//manually optimized assembly of above C code
  asm
    ;UARTCOUNT = 0x00
    ;UARTDIVIDE = 0x01
    ;UARTDATAH = 0x02
    ;UARTDATAL = 0x03
    ;UARTDATAS = 0x04
    ;UARTFORMAT = 0x05
    ;UARTINVERT = 0x00
    ;UARTHSINVERT = 0x01
    ;UARTFLAG = 0x02
    ;UARTBITS11 = 0x03
    ;UARTDATA7 = 0x04
    ;UARTUNUSED = 0x05
    ;UARTEVEN = 0x06
    ;UARTODD = 0x07
    ;UARTBAUD = 0x06
    ;UARTSTOPBITS = 0x07
    ;UARTHEAD = 0x08
    ;UARTTAIL = 0x09
    ;UARTBUFFERH = 0x0A
    ;UARTBUFFERL = 0x0B
    ;UARTPORT = 0x0C
    ;UARTPIN = 0x0D
    ;UARTHSPORT = 0x0E
    ;UARTHSPIN = 0x0F
    ;STATEPTR = 0x10
    ;NEXTVP = 0x12
    ;INPORT = 0x14
    ;INPIN = 0x16
    ;OUTPORT = 0x18
    ;OUTPIN = 0x1A
    mov.b [w5+UARTFORMAT],w2;     //if (slot->vpUart.nmUartFlag) { //data to transmit?
    btss w2,#UARTFLAG;
    bra _dvpSTX_S0b;
    mov.w [w5+UARTHSPORT],w4;     //  portSelect = slot->vpUart.nmUartHSPort;
    lsr w4,#8,w3;                 //  pinMask = slot->vpUart.nmUartHSPin;
    cp0.b w3;                     //  if (pinMask) { //hardware handshake (CTS input) used
    bra z,_dvpSTX_S0a;
    mov.w PORTB,w1;               //    portInput = PORTB;
    btsc w4,#1;                   //    if (portSelect & 0x02)
    mov.w PORTC,w1;               //      portInput = PORTC;
    btsc w2,#UARTHSINVERT;        //    if (slot->vpUart.nmUartHSInvert)
    com.w w1,w1;                  //      portInput = ~portInput;
    btsc w4,#0;                   //    if (portSelect & 0x01)
    sl w3,#8,w3;                  //      pinMask <<= 8;
    and.w w1,w3,w0;               //    if (portInput & pinMask) //CTS asserted, transmission may begin
    bra z,_dvpSTX_S0c;            //      slot->statePtr = &dvpSTX_S4; //next state
                                 ;//  }
    _dvpSTX_S0a:;                 //  else { //no hardware handshake, transmission may begin
    mov.w #handle(_dvpSTX_S4),w0; //    slot->statePtr = &dvpSTX_S4; //next state
    mov.w w0,[w5+STATEPTR];       //  }
    bra _dvpSTX_S0c;              //}
    _dvpSTX_S0b:;                 //else { //wait for data in transmit buffer
    mov.b [w5+UARTHEAD],w0;       //  if (slot->vpUart.nmUartHead != slot->vpUart.nmUartTail) { //buffer not empty
    mov.b [w5+UARTTAIL],w1;
    sub.b w0,w1,w0;
    bra z,_dvpSTX_S0c;
    bset w2,#UARTFLAG;            //    slot->vpUart.nmUartFlag = 1; //mark transmitter busy
    mov.b w2,[w5+UARTFORMAT];
    mov.w #handle(_dvpSTX_S1),w0; //    slot->statePtr = &dvpSTX_S1; //next state
    mov.w w0,[w5+STATEPTR];
    mov.b [w5+UARTDATAH],w0;      //    slot->vpUart.nmUartDataH &= 0x7F; //setup startbit (true mode)
    bclr w0,#7;                   //  }
    mov.b w0,[w5+UARTDATAH];      //}
    _dvpSTX_S0c:;
  end asm
end sub
Building succeeds and the generated assembly code is

Code: Select all

_dvpSTX_S0:
;RGBWSv0_01p.mbas,183 :: 		sub procedure dvpSTX_S0
;RGBWSv0_01p.mbas,244 :: 		mov.b [w5+UARTFORMAT],w2;     //if (slot->vpUart.nmUartFlag) { //data to transmit?
0x02C6	0x97F975  	MOV.B	[W5+-1], W2
;RGBWSv0_01p.mbas,264 :: 		bra _dvpSTX_S0c;              //}
0x02C8	0x370001  	BRA	_dvpSTX_S0c
;RGBWSv0_01p.mbas,276 :: 		mov.b w0,[w5+UARTDATAH];      //}
0x02CA	0x9FFAF0  	MOV.B	W0, [W5+-1]
;RGBWSv0_01p.mbas,277 :: 		_dvpSTX_S0c:;
_dvpSTX_S0c:
;RGBWSv0_01p.mbas,278 :: 		end asm
L_end_dvpSTX_S0:
0x02CC	0x060000  	RETURN
; end of _dvpSTX_S0
There are a lot of asm instructions missing !!

I also like to know why I can't declare asm constants like
UARTCOUNT = 0x00
I had to comment these out as they give Invalid asm instruction error.

regards peter

User avatar
anikolic
mikroElektronika team
Posts: 1775
Joined: 17 Aug 2009 16:51
Location: Belgrade
Contact:

#2 Post by anikolic » 18 Dec 2009 09:00

Hi peterverkaik,
Thank you very much for reporting this! Your support in this beta testing is very valuable to us! I have generated the bug report to our developers, and as soon as we pinpoint the source of error we will inform you on this topic and possibly provide you with a workaround.

Best regards,
Aleksandar
Web Department Manager

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

#3 Post by milan » 18 Dec 2009 11:56

Hi,

you found 3 problems with one code, it is probably a record :)

1) Basic highlighter
2) Basic parser
3) Help explanation missing

----------------------------------------------------------------

1) Basic highlighter isn't coloring variables as it should.

2) Basic parser looks at {} block as a comment
Workaround : remove "{" and "}" characters from your comments

3) Explanation for variables and constants names is missing in help

All of this should be solved for the release version.
----------------------------------------------------------------
peterverkaik wrote:I also like to know why I can't declare asm constants like
UARTCOUNT = 0x00
If you want this syntax, write this outside the asm block








After removing "{" and "}" characters and declaring constants outside the asm block - you will get CODE1

Code: Select all

program asm_test
'//state 0: wait for data in transmit buffer, check if transmission may begin
'//Cycles is 23
sub procedure dvpSTX_S0

const
    UARTCOUNT = 0x00
    UARTDIVIDE = 0x01
    UARTDATAH = 0x02
    UARTDATAL = 0x03
    UARTDATAS = 0x04
    UARTFORMAT = 0x05
    UARTINVERT = 0x00
    UARTHSINVERT = 0x01
    UARTFLAG = 0x02
    UARTBITS11 = 0x03
    UARTDATA7 = 0x04
    UARTUNUSED = 0x05
    UARTEVEN = 0x06
    UARTODD = 0x07
    UARTBAUD = 0x06
    UARTSTOPBITS = 0x07
    UARTHEAD = 0x08
    UARTTAIL = 0x09
    UARTBUFFERH = 0x0A
    UARTBUFFERL = 0x0B
    UARTPORT = 0x0C
    UARTPIN = 0x0D
    UARTHSPORT = 0x0E
    UARTHSPIN = 0x0F
    STATEPTR = 0x10
    NEXTVP = 0x12
    INPORT = 0x14
    INPIN = 0x16
    OUTPORT = 0x18
    OUTPIN = 0x1A
  asm
    mov.b [w5+UARTFORMAT],w2;     //if (slot->vpUart.nmUartFlag)  //data to transmit?
    btss w2,#UARTFLAG;
    bra _dvpSTX_S0b;
    mov.w [w5+UARTHSPORT],w4;     //  portSelect = slot->vpUart.nmUartHSPort;
    lsr w4,#8,w3;                 //  pinMask = slot->vpUart.nmUartHSPin;
    cp0.b w3;                     //  if (pinMask)  //hardware handshake (CTS input) used
    bra z,_dvpSTX_S0a;
    mov.w PORTB,w1;               //    portInput = PORTB;
    btsc w4,#1;                   //    if (portSelect & 0x02)
    mov.w PORTC,w1;               //      portInput = PORTC;
    btsc w2,#UARTHSINVERT;        //    if (slot->vpUart.nmUartHSInvert)
    com.w w1,w1;                  //      portInput = ~portInput;
    btsc w4,#0;                   //    if (portSelect & 0x01)
    sl w3,#8,w3;                  //      pinMask <<= 8;
    and.w w1,w3,w0;               //    if (portInput & pinMask) //CTS asserted, transmission may begin
    bra z,_dvpSTX_S0c;            //      slot->statePtr = &dvpSTX_S4; //next state
                                 ;//
    _dvpSTX_S0a:;                 //  else  //no hardware handshake, transmission may begin
    mov.w #handle(_dvpSTX_S4),w0; //    slot->statePtr = &dvpSTX_S4; //next state
    mov.w w0,[w5+STATEPTR];       //
    bra _dvpSTX_S0c;              //
    _dvpSTX_S0b:;                 //else  //wait for data in transmit buffer
    mov.b [w5+UARTHEAD],w0;       //  if (slot->vpUart.nmUartHead != slot->vpUart.nmUartTail)  //buffer not empty
    mov.b [w5+UARTTAIL],w1;
    sub.b w0,w1,w0;
    bra z,_dvpSTX_S0c;
    bset w2,#UARTFLAG;            //    slot->vpUart.nmUartFlag = 1; //mark transmitter busy
    mov.b w2,[w5+UARTFORMAT];
    mov.w #handle(_dvpSTX_S1),w0; //    slot->statePtr = &dvpSTX_S1; //next state
    mov.w w0,[w5+STATEPTR];
    mov.b [w5+UARTDATAH],w0;      //    slot->vpUart.nmUartDataH &= 0x7F; //setup startbit (true mode)
    bclr w0,#7;                   //
    mov.b w0,[w5+UARTDATAH];      //
    _dvpSTX_S0c:;
  end asm
end sub

main:
  dvpSTX_S0()
end.

----------------------------------------------------------------
CODE1 couldn't be compiled because constants are not named properly.

Missing help explanation about asm names:

Code: Select all

_myVar, if it is global variable or constant.
<routine_name>_myVar, if it is local variable or constant.
so in your case (local constants)
you should replace
mov.b [w5+UARTFORMAT],w2 with
mov.b [w5+dvpSTX_S0_UARTFORMAT],w2

btss w2,#UARTFLAG with
btss w2,#dvpSTX_S0_UARTFLAG

etc.


- Another way that may be easier is to move your constants from
procedure to global section:

Code: Select all

program asm_test
// here
sub procedure dvpSTX_S0
than you will be adding only "_", like this

mov.b [w5+_UARTFORMAT],w2
----------------------------------------------------------------


Now, you must change all lines of this type:
mov.w PORTB,w1 to
mov PORTB,w1

we talked about that before:
http://www.mikroe.com/forum/viewtopic.p ... 009#115009 - part 1)


The only thing that left is this syntax
mov.w #handle(_dvpSTX_S1),w0
it is probably some C30 macro, we do not support that, can you explain what should it do?

PS: please post code that could be pasted and compiled immediately,
in this case, I had to add main function.
Also try to remove irrelevant code to make post smaller (see my code).
SmartADAPT2 rules !

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

#4 Post by peterverkaik » 18 Dec 2009 13:13

Hi Milan,

Thanks for the extensive explanation.

I declared the constants as global constants, as suggested.
I replaced the {} in comments by [] to keep brackets

After that only instructions like
mov.w #handle(_dvpSTX_S4,w0; //slot->statePtr = &dvpSTX_S4;
generate Invalid asm instruction error.

#handle is a C30 (ASM30) command to retrieve a 16bits address
of a subroutine. C30 places a GOTO at a low address (below $FFFF)
for subroutines that are actually located beyond $FFFF
This must be replaced by the Basic equivalent.
I noticed that
;RGBWSv0_02p.mbas,636 :: vpMem[0].statePtr = @dvpNOP_S0
0x0296 0x203460 MOV lo_addr(_dvpNOP_S0), W0
0x0298 0x884080 MOV W0, _vpMem+16
uses lo_addr(_subname) to get the sub address.
Replacing #handle by lo_addr however still produces
Invalid asm instruction error.

The routine

Code: Select all

'//state 0: wait for data in transmit buffer, check if transmission may begin
'//Cycles is 23
sub procedure dvpSTX_S0
'/*
'  register vpBank *slot asm("w5");
'  register unsigned int portSelect asm("w4");
'  register unsigned int portInput asm("w3");
'  register unsigned int pinMask asm("w2");
'  if (slot->vpUart.nmUartFlag) { //data to transmit?
'    portSelect = slot->vpUart.nmUartHSPort;
'    pinMask = slot->vpUart.nmUartHSPin;
'    if (pinMask) { //hardware handshake (CTS input) used
'      portInput = PORTB;
'      if (portSelect & 0x02) portInput = PORTC;
'      if (slot->vpUart.nmUartHSInvert) portInput = ~portInput;
'      if (portSelect & 0x01) pinMask <<= 8;
'      if (portInput & pinMask) //CTS asserted, transmission may begin
'        slot->statePtr = &dvpSTX_S4; //next state
'    }
'    else { //no hardware handshake, transmission may begin
'      slot->statePtr = &dvpSTX_S4; //next state
'    }
'  }
'  else { //wait for data in transmit buffer
'    if (slot->vpUart.nmUartHead != slot->vpUart.nmUartTail) { //buffer not empty
'      slot->vpUart.nmUartFlag = 1; //mark transmitter busy
'      slot->statePtr = &dvpSTX_S1; //next state
'      slot->vpUart.nmUartDataH &= 0x7F; //setup startbit (true mode)
'    }
'  }
'*/
  '//manually optimized assembly of above C code
  asm
    mov.b [w5+_UARTFORMAT],w2;    //if (slot->vpUart.nmUartFlag) [ //data to transmit?
    btss w2,#_UARTFLAG;
    bra _dvpSTX_S0b;
    mov.w [w5+_UARTHSPORT],w4;    //  portSelect = slot->vpUart.nmUartHSPort;
    lsr w4,#8,w3;                 //  pinMask = slot->vpUart.nmUartHSPin;
    cp0.b w3;                     //  if (pinMask) [ //hardware handshake (CTS input) used
    bra z,_dvpSTX_S0a;
    mov PORTB,w1;                 //    portInput = PORTB;
    btsc w4,#1;                   //    if (portSelect & 0x02)
    mov PORTC,w1;                 //      portInput = PORTC;
    btsc w2,#_UARTHSINVERT;       //    if (slot->vpUart.nmUartHSInvert)
    com.w w1,w1;                  //      portInput = ~portInput;
    btsc w4,#0;                   //    if (portSelect & 0x01)
    sl w3,#8,w3;                  //      pinMask <<= 8;
    and.w w1,w3,w0;               //    if (portInput & pinMask) //CTS asserted, transmission may begin
    bra z,_dvpSTX_S0c;            //      slot->statePtr = &dvpSTX_S4; //next state
                                 ;//  ]
    _dvpSTX_S0a:;                 //  else [ //no hardware handshake, transmission may begin
;    mov.w #handle(_dvpSTX_S4),w0; //    slot->statePtr = &dvpSTX_S4; //next state
    mov.w w0,[w5+_STATEPTR];      //  ]
    bra _dvpSTX_S0c;              //]
    _dvpSTX_S0b:;                 //else [ //wait for data in transmit buffer
    mov.b [w5+_UARTHEAD],w0;      //  if (slot->vpUart.nmUartHead != slot->vpUart.nmUartTail) [ //buffer not empty
    mov.b [w5+_UARTTAIL],w1;
    sub.b w0,w1,w0;
    bra z,_dvpSTX_S0c;
    bset w2,#_UARTFLAG;           //    slot->vpUart.nmUartFlag = 1; //mark transmitter busy
    mov.b w2,[w5+_UARTFORMAT];
;    mov.w #handle(_dvpSTX_S1),w0; //    slot->statePtr = &dvpSTX_S1; //next state
    mov.w w0,[w5+_STATEPTR];
    mov.b [w5+_UARTDATAH],w0;     //    slot->vpUart.nmUartDataH &= 0x7F; //setup startbit (true mode)
    bclr w0,#7;                   //  ]
    mov.b w0,[w5+_UARTDATAH];     //]
    _dvpSTX_S0c:;
  end asm
end sub
now compiles into

Code: Select all

_dvpSTX_S0:
;RGBWSv0_02p.mbas,207 :: 		sub procedure dvpSTX_S0
;RGBWSv0_02p.mbas,238 :: 		mov.b [w5+_UARTFORMAT],w2;    //if (slot->vpUart.nmUartFlag) [ //data to transmit?
0x030C	0x97F975  	MOV.B	[W5+-1], W2
;RGBWSv0_02p.mbas,239 :: 		btss w2,#_UARTFLAG;
0x030E	0xA62002  	BTSS	W2, #2
;RGBWSv0_02p.mbas,240 :: 		bra _dvpSTX_S0b;
0x0310	0x37000F  	BRA	_dvpSTX_S0b
;RGBWSv0_02p.mbas,241 :: 		mov.w [w5+_UARTHSPORT],w4;    //  portSelect = slot->vpUart.nmUartHSPort;
0x0312	0x7B8265  	MOV	[W5+W7], W4
;RGBWSv0_02p.mbas,242 :: 		lsr w4,#8,w3;                 //  pinMask = slot->vpUart.nmUartHSPin;
0x0314	0xDE21C8  	LSR	W4, #8, W3
;RGBWSv0_02p.mbas,243 :: 		cp0.b w3;                     //  if (pinMask) [ //hardware handshake (CTS input) used
0x0316	0xE24006  	CP0.B	W3
;RGBWSv0_02p.mbas,244 :: 		bra z,_dvpSTX_S0a;
0x0318	0x320009  	BRA.Z	_dvpSTX_S0a
;RGBWSv0_02p.mbas,245 :: 		mov PORTB,w1;                 //    portInput = PORTB;
0x031A	0x801651  	MOV	PORTB, W1
;RGBWSv0_02p.mbas,246 :: 		btsc w4,#1;                   //    if (portSelect & 0x02)
0x031C	0xA71004  	BTSC	W4, #1
;RGBWSv0_02p.mbas,247 :: 		mov PORTC,w1;                 //      portInput = PORTC;
0x031E	0x801691  	MOV	PORTC, W1
;RGBWSv0_02p.mbas,248 :: 		btsc w2,#_UARTHSINVERT;       //    if (slot->vpUart.nmUartHSInvert)
0x0320	0xA71002  	BTSC	W2, #1
;RGBWSv0_02p.mbas,249 :: 		com.w w1,w1;                  //      portInput = ~portInput;
0x0322	0xEA8081  	COM	W1, W1
;RGBWSv0_02p.mbas,250 :: 		btsc w4,#0;                   //    if (portSelect & 0x01)
0x0324	0xA70004  	BTSC	W4, #0
;RGBWSv0_02p.mbas,251 :: 		sl w3,#8,w3;                  //      pinMask <<= 8;
0x0326	0xDD19C8  	SL	W3, #8, W3
;RGBWSv0_02p.mbas,252 :: 		and.w w1,w3,w0;               //    if (portInput & pinMask) //CTS asserted, transmission may begin
0x0328	0x608003  	AND	W1, W3, W0
;RGBWSv0_02p.mbas,253 :: 		bra z,_dvpSTX_S0c;            //      slot->statePtr = &dvpSTX_S4; //next state
0x032A	0x32000C  	BRA.Z	_dvpSTX_S0c
;RGBWSv0_02p.mbas,255 :: 		_dvpSTX_S0a:;                 //  else [ //no hardware handshake, transmission may begin
_dvpSTX_S0a:
;RGBWSv0_02p.mbas,257 :: 		mov.w w0,[w5+_STATEPTR];      //  ]
0x032C	0x7C3280  	MOV	W0, [W5+, W8]
;RGBWSv0_02p.mbas,258 :: 		bra _dvpSTX_S0c;              //]
0x032E	0x37000A  	BRA	_dvpSTX_S0c
;RGBWSv0_02p.mbas,259 :: 		_dvpSTX_S0b:;                 //else [ //wait for data in transmit buffer
_dvpSTX_S0b:
;RGBWSv0_02p.mbas,260 :: 		mov.b [w5+_UARTHEAD],w0;      //  if (slot->vpUart.nmUartHead != slot->vpUart.nmUartTail) [ //buffer not empty
0x0330	0x97F875  	MOV.B	[W5+-1], W0
;RGBWSv0_02p.mbas,261 :: 		mov.b [w5+_UARTTAIL],w1;
0x0332	0x97F8F5  	MOV.B	[W5+-1], W1
;RGBWSv0_02p.mbas,262 :: 		sub.b w0,w1,w0;
0x0334	0x504001  	SUB.B	W0, W1, W0
;RGBWSv0_02p.mbas,263 :: 		bra z,_dvpSTX_S0c;
0x0336	0x320006  	BRA.Z	_dvpSTX_S0c
;RGBWSv0_02p.mbas,264 :: 		bset w2,#_UARTFLAG;           //    slot->vpUart.nmUartFlag = 1; //mark transmitter busy
0x0338	0xA84004  	BSET	W2, #2
;RGBWSv0_02p.mbas,265 :: 		mov.b w2,[w5+_UARTFORMAT];
0x033A	0x9FFAF2  	MOV.B	W2, [W5+-1]
;RGBWSv0_02p.mbas,267 :: 		mov.w w0,[w5+_STATEPTR];
0x033C	0x7C3280  	MOV	W0, [W5+, W8]
;RGBWSv0_02p.mbas,268 :: 		mov.b [w5+_UARTDATAH],w0;     //    slot->vpUart.nmUartDataH &= 0x7F; //setup startbit (true mode)
0x033E	0x97F875  	MOV.B	[W5+-1], W0
;RGBWSv0_02p.mbas,269 :: 		bclr w0,#7;                   //  ]
0x0340	0xA17000  	BCLR	W0, #7
;RGBWSv0_02p.mbas,270 :: 		mov.b w0,[w5+_UARTDATAH];     //]
0x0342	0x9FFAF0  	MOV.B	W0, [W5+-1]
;RGBWSv0_02p.mbas,271 :: 		_dvpSTX_S0c:;
_dvpSTX_S0c:
;RGBWSv0_02p.mbas,272 :: 		end asm
L_end_dvpSTX_S0:
0x0344	0x060000  	RETURN
; end of _dvpSTX_S0
There are still a few problems with the generated code,
like [w5+-1],[w5+,w8],[w5+w7] but those are related to ++
I assume.

regards peter

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

#5 Post by milan » 18 Dec 2009 13:30

Hi,
peterverkaik wrote: Replacing #handle by lo_addr however still produces
Invalid asm instruction error.
your code is too big, can you remove everything irrelevant and make the small code.
I would like to investigate this, but it is much easier with small code.
peterverkaik wrote: There are still a few problems with the generated code,
like [w5+-1],[w5+,w8],[w5+w7] but those are related to ++
I assume.
You should also make a small example to help us to solve this.
SmartADAPT2 rules !

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

#6 Post by peterverkaik » 18 Dec 2009 13:58

Here is the complete file

Code: Select all

'/**********************************************************************
'* FileName:        main.c
'* Dependencies:    none
'* Processor:       dsPIC33FJ128GP804
'* Compiler:        MikroE Basic for dsPIC PRO beta (code migrated from MPLAB C30 v3.21)
'* Tested On:       not yet
'*
'* REVISION HISTORY:
'*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'* Author            Date           Comments on this revision
'*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'* Peter Verkaik     17/02/2009     Original Release
'*
'*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'* ADDITIONAL NOTES:
'* The Processor starts with the internal oscillator without PLL enabled
'* and then the clock is switched to PLL Mode.
'*
'**********************************************************************/
'//#include <p33FJ128GP804.h>

'//_FOSCSEL(FNOSC_FRC);                        // Internal FRC oscillator
'//_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF  & POSCMD_NONE);
'                                                                // Clock Switching is enabled and Fail Safe Clock Monitor is disabled
'                                                                // OSC2 Pin Function: OSC2 is Clock Output
'                                                                // Primary Oscillator Mode: XT Crystal

'//-----------------------------  vp registers  ------------------------------

program RGBWS

typedef TvoidSub as procedure()

structure vpBank
  'registers for generic use
  dim reg as byte[16] '// vp register array
  'common to all vp structures
  dim statePtr as ^TvoidSub '//state function
  dim nextVP as word        '^vpBank
  dim inPort as word        '//for fast access to PORTx
  dim inPin as word
  dim outPort as word       '//for fast access to LATx (or TRISx)
  dim outPin as word
  dim spare1 as word
  dim spare2 as word
end structure

const
  UARTCOUNT = 0x00
  UARTDIVIDE = 0x01
  UARTDATAH = 0x02
  UARTDATAL = 0x03
  UARTDATAS = 0x04
  UARTFORMAT = 0x05
    UARTINVERT = 0x00
    UARTHSINVERT = 0x01
    UARTFLAG = 0x02
    UARTBITS11 = 0x03
    UARTDATA7 = 0x04
    UARTUNUSED = 0x05
    UARTEVEN = 0x06
    UARTODD = 0x07
  UARTBAUD = 0x06
  UARTSTOPBITS = 0x07
  UARTHEAD = 0x08
  UARTTAIL = 0x09
  UARTBUFFERH = 0x0A
  UARTBUFFERL = 0x0B
  UARTPORT = 0x0C
  UARTPIN = 0x0D
  UARTHSPORT = 0x0E
  UARTHSPIN = 0x0F
  STATEPTR = 0x10
  NEXTVP = 0x12
  INPORT = 0x14
  INPIN = 0x16
  OUTPORT = 0x18
  OUTPIN = 0x1A
  SPARE1 = 0x1C
  SPARE2 = 0x1E

structure nmUart
  'registers for uart vp
  dim nmUartCount as byte    '// 0x00 number of bits to transmit or receive
  dim nmUartDivide as byte   '// 0x01 timing counter
  dim nmUartDataH as byte    '// 0x02 transmit register highbyte, receive byte save
  dim nmUartDataL as byte    '// 0x03 transmit register lowbyte, receive shiftin
  dim nmUartDataS as byte    '// 0x04 stopbits, transmission ends at first '0' bit
  dim nmUartFormat as byte   '// 0x05 b0=invert,b1=hsinvert,b2=flag,b3=bits11,b4=data7,b5=unused,b6=even,b7=odd
  dim nmUartBaud as byte     '// 0x06 baudrate divider
  dim nmUartStopBits as byte '// 0x07 Tx only: 00000001 for 1 stop bit, 00000011 for 2 etc
  dim nmUartHead as byte     '// 0x08 Index of the next free byte in the buffer.
  dim nmUartTail as byte     '// 0x09 Index of the oldest byte in the buffer.
                             '//      If tailPointer == headPointer the buffer is empty.
  dim nmUartBufferH as byte  '// 0x0A address of 256 byte buffer
  dim nmUartBufferL as byte  '// 0x0B
  dim nmUartPort as byte     '// 0x0C 0=PortB 0-7, 1=PortB 8-15, 2=PortC 0-7, 3=PortC 8-9
  dim nmUartPin as byte      '// 0x0D bit mask (1 of 8 set)
  dim nmUartHSPort as byte   '// 0x0E 0=PortB 0-7, 1=PortB 8-15, 2=PortC 0-7, 3=PortC 8-9
  dim nmUartHSPin as byte    '// 0x0F bitmask (1 of 8 set)
  'common to all vp structures
  dim statePtr as ^TvoidSub  '//state function
  dim nextVP as word         '^vpBank
  dim inPort as word         '//for fast access to PORTx
  dim inPin as word
  dim outPort as word        '//for fast access to LATx (or TRISx)
  dim outPin as word
  dim spare1 as word
  dim spare2 as word
end structure

dim vpMem as vpBank[7]
dim vpPtr as ^vpBank
dim vp0buf as byte[256]

'//-----------------------------------------------------------------------------
'// Virtual Peripheral Scheduler
'//-----------------------------------------------------------------------------

'//This routine is called every 1.24 usec (49 cycles @79MHz). It provides 7 timeslots.
'//These run at priority 7 to ensure deterministic behaviour for all states.
'//Cycles is 16 + statefunction cycles
'//Only registers w0-w5 must be used by vp driver code because other w registers are not saved.
'//The interrupt frequency for each timeslot equals 1/(7*1.24) MHz = 115.2 kHz
sub procedure T4Interrupt org 0x003E '//On C30 this autogenerates push.s and pop.s statements)
  'dim slot as ^vpBank rx '// asm("w5");
  w5 = vpPtr                      '//this value is used in all statefunctions
  vpPtr^.statePtr^                '//call statefunction for slot
  vpPtr = vpPtr^.nextVP           '//next vp
  IFS1.T4IF = 0                   '//clear T4 interruptflag
  asm
    push.s;             //save w0-w3,status
    mov.d w4,[w15++];   //save w4,w5
    mov _vpPtr,w5;      //slot = vpPtr; //this value is used in all statefunctions
    mov.w [w5+16],w0;   //(slot->statePtr)(); //call statefunction for slot
    ;call w0;
    mov.w [w5+18],w0;   //vpPtr = (vpBank *)slot->nextVP; //next vp
    mov w0,_vpPtr;
    bclr IFS1,#11;      //IFS1bits.T4IF = 0; //clear T4 interruptflag
    mov.d [--w15],w4;   //restore w4,w5
    pop.s;              //restore w0-w3,status
  end asm
end sub

sub procedure T5Interrupt org 0x0040
  IFS1.T5IF = 0                   '//clear T5 interruptflag
end sub

'//-----------------------------------------------------------------------------
'// Virtual Peripheral Uninstalled
'//-----------------------------------------------------------------------------

'// State 0: do nothing
sub procedure dvpNOP_S0
  '//This function does nothing
end sub

'//-----------------------------------------------------------------------------
'// Virtual Peripheral Serial Transmit
'//-----------------------------------------------------------------------------

sub procedure dvpSTX_S0 forward
sub procedure dvpSTX_S4 forward

'//-----------------------------------------------------------------------------

'//state 0: wait for data in transmit buffer, check if transmission may begin
'//Cycles is 23
sub procedure dvpSTX_S0
  asm
    mov.b [w5+_UARTFORMAT],w2;    //if (slot->vpUart.nmUartFlag) [ //data to transmit?
    btss w2,#_UARTFLAG;
    bra _dvpSTX_S0b;
    mov.w [w5+_UARTHSPORT],w4;    //  portSelect = slot->vpUart.nmUartHSPort;
    lsr w4,#8,w3;                 //  pinMask = slot->vpUart.nmUartHSPin;
    cp0.b w3;                     //  if (pinMask) [ //hardware handshake (CTS input) used
    bra z,_dvpSTX_S0a;
    mov PORTB,w1;                 //    portInput = PORTB;
    btsc w4,#1;                   //    if (portSelect & 0x02)
    mov PORTC,w1;                 //      portInput = PORTC;
    btsc w2,#_UARTHSINVERT;       //    if (slot->vpUart.nmUartHSInvert)
    com.w w1,w1;                  //      portInput = ~portInput;
    btsc w4,#0;                   //    if (portSelect & 0x01)
    sl w3,#8,w3;                  //      pinMask <<= 8;
    and.w w1,w3,w0;               //    if (portInput & pinMask) //CTS asserted, transmission may begin
    bra z,_dvpSTX_S0b;            //      slot->statePtr = &dvpSTX_S4; //next state
                                 ;//  ]
    _dvpSTX_S0a:;                 //  else [ //no hardware handshake, transmission may begin
;    mov.w #handle(_dvpSTX_S4),w0; //    slot->statePtr = &dvpSTX_S4; //next state
    mov.w w0,[w5+_STATEPTR];      //  ]
                                 ;//]
    _dvpSTX_S0b:;
  end asm
end sub

'//state 4: wait for time to send
'//Cycles is 23
sub procedure dvpSTX_S4
  asm
    mov.b [w5+_UARTDIVIDE],w0;    //if (! --slot->vpUart.nmUartDivide) [ //time to send?
    dec.b w0,w0;
    mov.b w0,[w5+_UARTDIVIDE];
    bra nz,_dvpSTX_S4a;
    mov.b [w5+_UARTBAUD],w0;      //  slot->vpUart.nmUartDivide = slot->vpUart.nmUartBaud - 1;
    dec.b w0,w0;
    mov.b w0,[w5+_UARTDIVIDE];
    mov.w [w5+_UARTDATAH],w0;     //  slot->vpUart.nmUartDataH >>= 1;
    mov.b [w5+_UARTDATAS],w1;     //  slot->vpUart.nmUartDataH |= (slot->vpUart.nmUartDataL<<7);
    lsr.w w1,w1;                  //  slot->vpUart.nmUartDataL >>= 1;
    rrc.w w0,w0;                  //  slot->vpUart.nmUartDataL |= (slot->vpUart.nmUartDataS<<7);
    mov.b w1,[w5+_UARTDATAS];     //  slot->vpUart.nmUartDataS >>= 1;
    mov.w w0,[w5+_UARTDATAH];
    mov.b [w5+_UARTFORMAT],w2;    //  if (slot->vpUart.nmUartInvert) slot->vpUart.nmUartDataH ^= 0x20; //b5 is output bit
    btsc w2,#_UARTINVERT;
    btg.b w0,#5;
                                 ;//]
    _dvpSTX_S4a:;
  end asm
end sub

'//-----------------------------------------------------------------------------
'// Initialisation
'//-----------------------------------------------------------------------------

'//external resonator 20MHz
'//Fosc = (20MHz/10)*(79)/2 = 79MHz
'//           PLLPRE^    ^PLLPOST
'//           2MHz        158MHz
sub procedure PLL_Init
  PLLFBD = 77                      '// M = 79
  CLKDIV = (CLKDIV AND $FFE0) OR 8 'PLLPRE = 8            '// N1 = 10
  CLKDIV = (CLKDIV AND $FF3F) OR 0 'PLLPOST = 0           '// N2 = 2
  OSCTUN = 0
  RCON.SWDTEN = 0
  '// Clock switch to incorporate PLL
  OSCCONH = 0x01    '// Initiate Clock Switch to FRC with PLL (NOSC=0b001)
  OSCCONL = 0x01    '// Start clock switching
  while ((OSCCON AND $7000) <> $4000) '// Wait for Clock switch to occur
  wend
  while (OSCCON.LOCK_ <> 1)
  wend
end sub

sub procedure T4_Init
  T4CON = 0           '//T4 off
  TMR4 = 0            '//T4 clear
  IFS1.T4IF = 0   '//reset T4 interrupt flag
  'IPC6bits.T4IP = 7   '//set T4 interrupt priority level to 7 for deterministic behaviour
  PR4 = 48            '//set T4 period register to 48, T4period = (48+1)*2/79MHz = 1.24usec
  IEC1.T4IE = 1    '//enable T4 interrupt
  'T4CONbits.TCS = 0   '//select internal timer clock
  'T4CONbits.TCKPS = 0 '//prescale 1:1
  'T4CONbits.TON = 1   '//T4 start
end sub

sub procedure vpMem_Init
  vpMem[0].statePtr = @dvpNOP_S0
  vpMem[0].nextVP = @vpMem[1]
  vpMem[1].statePtr = @dvpNOP_S0
  vpMem[1].nextVP = @vpMem[2]
  vpMem[2].statePtr = @dvpNOP_S0
  vpMem[2].nextVP = @vpMem[3]
  vpMem[3].statePtr = @dvpNOP_S0
  vpMem[3].nextVP = @vpMem[4]
  vpMem[4].statePtr = @dvpNOP_S0
  vpMem[4].nextVP = @vpMem[5]
  vpMem[5].statePtr = @dvpNOP_S0
  vpMem[5].nextVP = @vpMem[6]
  vpMem[6].statePtr = @dvpNOP_S0
  vpMem[6].nextVP = @vpMem[0]
  vpPtr = @vpMem[0]
end sub

'//-----------------------------------------------------------------------------
'// Main code
'//-----------------------------------------------------------------------------

main:
  PLL_Init  '//start the clock (this must be revisited for MikroE dsPIC PRO C)
  ADPCFG = 0xFFFF  '//all AD pins set to digital I/O
  DisableContextSaving()
  SetFuncCall(dvpNOP_S0)
  SetFuncCall(dvpSTX_S0,dvpSTX_S4)

  vpMem_Init '//setup vpMem table (all banks idle)
  T4_Init    '//start vp scheduler

  while (1)
  wend
end.
regards peter

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

#7 Post by milan » 18 Dec 2009 15:33

Hi,

all 3 problems should be solved now.

Send me the original project (with "{" and "}" characters in your comments so I could test that.

Zip the project folder and send it to milan ( att ) mikroe . com
so I could know on which MCU you are working.
(Right now, PLLFBD register gives me a trouble, I am trying on P30F4013)
SmartADAPT2 rules !

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

#8 Post by peterverkaik » 18 Dec 2009 16:11

I use dsPIC33FJ128GP804
also specified at top of file (last listing)

I will zip the original and mail it to you.

regards peter

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

#9 Post by milan » 21 Dec 2009 10:52

Hi,

lo_addr works, I sent you an email back


For other users, here this demo for
lo_addr and procedure

Code: Select all

program test


sub procedure p1()
  PORTB = 6
end sub

main:
  p1()
  
  asm
    mov #lo_addr(_p1), W0
  end asm
  
end.
SmartADAPT2 rules !

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

#10 Post by peterverkaik » 21 Dec 2009 11:14

Hi Milan,

It does not work for my code, where I use _dvpSTX_S4 from
sub dvpSTX_S0 (forward reference). For that reason I declared
all statefunctions forward.
In the full test code I have 7 states and state S0
may be called from those states, so rearranging the order of the
subs will not work, hence the forward declarations.

regards peter

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

#11 Post by peterverkaik » 21 Dec 2009 11:41

It wouldn't work for v1.95 would it?
So I assume I must await the next release
before I can continue this interruptcode.

Any idea when this next release will be?

regards peter

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

#12 Post by milan » 21 Dec 2009 15:08

Hi Peter,

we made some changes and now your original project
from an email attachment compiles.

Unfortunately it's impossible to provide you a fix right now, you should wait for the official release (we hope this will be 2-3 days from now, if we don't have unexpected delays).

Thank you for your reports and patience, you are helping us very much.
SmartADAPT2 rules !

Post Reply

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