E-13 Invalid ASM instruction: ".REPT 31" Sleeptest

General discussion on mikroPascal for dsPIC30/33 and PIC24.
Post Reply
Author
Message
OT
Posts: 581
Joined: 19 May 2005 05:08
Location: Fairbanks, Alaska

E-13 Invalid ASM instruction: ".REPT 31" Sleeptest

#1 Post by OT » 16 Jan 2008 15:00

I am trying to implement Microchip's workaround for the sleep Errata issue, which is to place the PWRSAV #0 instruction in the last word of program memory and fill the rest of that row with NOP ( the ASM example shown at the end of this message).

The first problem is that the compiler does not accept ".REPT 31" as inline ASM (code for procedure towards the end). This can be worked around by repeating the NOP instruction 31 times (not very elegant!), however then I get the error:
"0:0 E-0 Linker error: Routine exceeds page boundaries 16320 Sleeptest.dpas"


If I remove two of the NOPS or shift the address of the routine accordingly, I can get it to compile. However then the that part of the ASM code end with:

Code: Select all

$3FF8	$000000			NOP
;Sleeptest.dpas,110 :: 		PWRSAV #0
$3FFA	$FE4000			PWRSAV	#0
;Sleeptest.dpas,111 :: 		end;
$3FFC	$	Sleeptest_L_6:
;Sleeptest.dpas,112 :: 		end;
$3FFC	$	L_end__gotosleep:
$3FFC	$060000			RETURN

So it is obvious that the two NOPs had to be deleted because, not surprising, there is an instruction to return from the procedure that take up space. This is not what the workaround asked for, the PWRSAV #0 has to be placed at the very end. I see no way of doing this without some modification of the compiler.

Out of curiosity, I checked the manual of the CCS compiler, and there it appears that a the PWRSAV instruction is by default inserted at the very end if this feature is not deactivated, the sleep errata could be the reason.

Could we get some help from ME on this?

My initial attempt (for dsPIC30F3013):

Code: Select all

Procedure GotoSleep; org $3FC0; 
// GotoSleep calls PwrSav #0
begin
  asm
   //; fill remainder of the last row of prog mem with NOP instructions
    .rept 31
     NOP
    .endr
    //;Place SLEEP instruction in the last word of program memory
    PWRSAV #0
  end;
end;
Workaround1 in Errata:
Ensure that the PWRSAV #0 instruction is located
at the end of the last row of Program Flash
Memory available on the target device and fill the
remainder of the row with NOP instructions.
This can be accomplished by replacing all
occurrences of the PWRSAV #0 instruction with a
function call to a suitably aligned subroutine. The
address( ) attribute provided by the MPLAB
ASM30 assembler can be utilized to correctly align
the instructions in the subroutine. For an
application written in C, the function call would be
GotoSleep( ), while for an assembly language
application, the function call would be
CALL _GotoSleep.
The Address Error Trap Service Routine software
can then replace the invalid return address saved
on the stack with the address of the instruction
immediately following the _GotoSleep or
GotoSleep( ) function call. This ensures that
the device continues executing the correct code
sequence after waking up from Sleep mode.
Example 8 demonstrates the work around
described above, as it would apply to a
dsPIC30F3012 device.
Microchip's ASM example:

Code: Select all

; ----------------------------------------------------------------------------------------------
.global __reset
.global _main
.global _GotoSleep
.global __AddressError
.global __INT1Interrupt
; ----------------------------------------------------------------------------------------------
.section *, code
_main:
BSET INTCON2, #INT1EP ; Set up INT pins to detect falling edge
BCLR IFS1, #INT1IF ; Clear interrupt pin interrupt flag bits
BSET IEC1, #INT1IE ; Enable ISR processing for INT pins
CALL _GotoSleep ; Call function to enter SLEEP mode
_continue:
BRA _continue
; ----------------------------------------------------------------------------------------------
; Address Error Trap
__AddressError:
BCLR INTCON1, #ADDRERR
; Set program memory return address to _continue
POP.D W0
MOV.B #tblpage (_continue), W1
MOV #tbloffset (_continue), W0
PUSH.D W0
RETFIE
; ----------------------------------------------------------------------------------------------
__INT1Interrupt:
BCLR IFS1, #INT1IF ; Ensure flag is reset
RETFIE ; Return from Interrupt Service Routine
; ----------------------------------------------------------------------------------------------
.section *, code, address (0x3FC0)
_GotoSleep:
; fill remainder of the last row with NOP instructions
.rept 31
NOP
.endr
; Place SLEEP instruction in the last word of program memory
PWRSAV #0

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

#2 Post by yo2lio » 16 Jan 2008 15:37

Hi

Code: Select all

asm
...
  REPEAT #31
  NOP
...
end;
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

OT
Posts: 581
Joined: 19 May 2005 05:08
Location: Fairbanks, Alaska

#3 Post by OT » 16 Jan 2008 16:53

Thanks,
Do you see any way to resolve the issue with the return statement at the end?

It seems that the address of the PWRSAV instruction does not change with the number of repeats. Are you sure this is the correct expression?
I am very far from knowing what I am doing here...

Here is the resulting ASM code:

Code: Select all

$3FC0	$	_gotosleep:
;Sleeptest.dpas,74 :: 		begin
;Sleeptest.dpas,77 :: 		REPEAT #31
$3FC0	$09001F			REPEAT	#31
;Sleeptest.dpas,79 :: 		//;Place SLEEP instruction in the last word of program memory
$3FC2	$000000			NOP
;Sleeptest.dpas,80 :: 		PWRSAV #0
$3FC4	$FE4000			PWRSAV	#0
;Sleeptest.dpas,81 :: 		end;
$3FC6	$	Sleeptest_L_6:
;Sleeptest.dpas,82 :: 		end;
$3FC6	$	L_end__gotosleep:
$3FC6	$060000			RETURN

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

#4 Post by yo2lio » 16 Jan 2008 17:25

OT wrote:It seems that the address of the PWRSAV instruction does not change with the number of repeats. Are you sure this is the correct expression?
REPEAT #n ASM instruction , repeat n + 1 times the next instruction.

I use this ASM instruction in my mem_cpy routine :

Code: Select all

procedure Mem_Cpy(p1, p2 : word; n : word);
begin
  W10 := n;
  W12 := p1;
  W11 := p2;
  asm
    CP0 W10
    BRA Z,la25
    DEC W10,W10
    REPEAT W10
    MOV.B [W11++],[W12++]
la25:
  end;
end; 
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

Post Reply

Return to “mikroPascal for dsPIC30/33 and PIC24 General”