This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Call IQ24div() from asm

Hi,

I'm writing a new asm macro for use with the DPLib DPL_ISR one part of this performs some division with Q24 numbers, so instead of rolling my own division I though why not use the IQ lib _IQ24div() function.

Great, except when I try to call it from asm it causes an illegal ISR :(

If I run the same code without the LCR, there's no issue. I have IQmath.lib and the boot ROM symbols linked in the project and the IQmathLib.h file include path added to the compiler include search path.

The code I currently have is:

	    .cdecls   C, LIST
	    %{
	    	#include <IQmathLib.h>
	    %}
	    .ref __IQ24div
;...

		ADDB	SP, #2			; Add frame space on stack
		MOVL	ACC, *XAR2		; Copy denominator value to stack frame
		MOVL	*-SP[2], ACC
		MOVL	ACC, *XAR1		; Copy numerator value to ACC
		LCR	    __IQ24div		; Call IQ 24 division function ; THIS LINE CAUSES THE ILLEGAL ISR
		MOVL	*XAR3, ACC		; Copy result to quotient
		SUBB	SP, #2			; Remove frame space from stack

Have I done something incorrectly here??

Thanks

  • Toby,

    What happens when you single-step into the function call?  Does it go into the IQ24div implementation, or does it go off to la-la land?

    You aren't running this in a simulator, are you?

    Regards,

    Bill

  • Hi Bill,

    Left the office there now, but IIRC single stepping it at least enters the divide function. I don't have any interrupts other than the PWM that drives the DPL_ISR enabled at this time however... and the DPL ISR contains only this macro ATM, as I've commented every other macro out.

    Ta

  • Hi Toby,

    It looks like wherever its branching to (LCR), its fetching an opcode it doesnt understand and then going to the illegal ISR. What does the disassembly for this statement look like? It will tell you where the code is trying to branch to. I would then check that address against the address of IQ24div in the .map file to see if they match- if they do match i would check to see that the code is actually at that location. 

  • I've observed this issue further and noted that it is not quite as I first described.

    The issue occurs with the LCR instruction present and not when it is removed.

    The issue itself is actually slightly different, the illegal_isr does not *seem* to occur when the LCR instruction is run, as control never seems to reach the DPL_ISR, if, I put a break-point immediately inside the DPL_ISR, when the LCR instruction is present within the ISR, operation never gets to the DPL_ISR, instead the illegal_ISR occurs...

    This seems to indicate that an instruction that is never actually reached is affecting the operation of the PWM interrupt that drives the DPL_ISR.??

    Continuing to single step after the occurance of the illegal_ISR shows that it returns to reserved memory between 0x2000 & 0x6000 usually around the 0x2500 - 0x3500 mark.

    The PIECTRL.PIEVECT bits are 0x0D26 which is the illegal operation interrupt... again though this seems to indicate to me that possibly an instruction that is never actually reached (the LCR) is somehow affecting the program?? Or that the LCR is causing the DPL_ISR not to be built correctly and so the vector is incorrect??

    My next step to trace this will be to try to trace back through the frames on the stack and see where the illegal_ISR interrupt is originally occurring :(

  • Toby,

    You should definitely test the operation of your macro outside of any interrupt environment.  That will make the debugging much easier.

    Be aware that the function you are calling may modify CPU registers.  Make sure that you are completely preserving *every* register in your ISR, otherwise your code will malfunction once you return to the main loop.

    Are you sure you really need a division?  Fixed point multiplication is much simpler and doesn't require a function call...

    Bill

  • Just to be sure that you do the full context save. The DPL-ISR.asm template does not save RPC. If you use a LCR you must save RPC. So if your ISR looks like this:

    _DPL_ISR:
            ; full context save - push any unprotected registers onto stack
            PUSH      AR1H:AR0H
            PUSH      XAR2
            PUSH      XAR3
            PUSH      XAR4
            PUSH      XAR5
            PUSH      XAR6
            PUSH      XAR7
            PUSH      XT
            SPM       0               ; set C28 mode
            CLRC      AMODE       
            CLRC      PAGE0,OVM
    ;        CLRC    INTM             ; clear 

    then add a

    PUSH RPC ; e.g. after PUSH XT

    and

    POP RPC ; e.g. before POP XT

    at the end

    Best Regards,

    Roger

  • D'oh! Was only yesterday morning I was trying to remember why I had cryptically written:

        "M-Inv. asm G"

    On the corner of a page. Gah. Of course changed to multiplication now.

    Thanks guys!