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.

VFP Interrupt Handling

I am running into a problem when I am trying to turn on an interrupt to capture floating point exceptions.  I have some initial thoughts on some work-arounds for the issue, but wanted to get some suggestions as I don't like the work-arounds I am coming up with.  Here is the scenario:

I have turned on the VIM reporting of the Divide By Zero floating point exception via the appropriate bit in the ARM Secondary Auxiliary Control Register.  I have also enabled the VIM interrupt and provided my interrupt function (currently written in C code).  I then force a floating point divide by zero, and I am entering my ISR as expected.  My understanding is that I need to manually write a "0" back to the DZC bit (Division by Zero cumulative flag) in the FPSCR register in order to clear this bit and subsequently clear the VIM interrupt request flag.  The problem is that the FPSCR register is saved and restored by the compiler when I enter/leave this ISR (which I think makes sense given that the FPSCR also holds the N,Z,C,V flags).  This is basically making it impossible to leave the ISR without restoring the DZC bit to 1 (as this being 1 was what got me into the ISR to begin with) and subsequently triggering another VFP VIM interrupt.

Any thoughts on if my understanding is incorrect on any of this?  Any workarounds that can be suggested?  I didn't necessarily want to have to write the ISR completely in assembly language to put custom code on the restoration of the FPSCR register.

Thanks, 

Luke

  • Hello Lucas,

    I have forwarded your post to our VIM expert.  They will respond back soon.

  • Lucas,

    Thanks for using our forum.

    Your analysis is perfectly correct. Because the compiler knows that the VFP is used, the following VFP registers are save in the IRQ or FIQ stack each time an ISR is serviced:

    FPEXC
    FPSCR
    D0-D7

    This set of registers are restored when you exit your ISR.

    Right now, the only method I can think of is to write your VFP ISR in assembly code.

    I've also contacted our Code Generator Team to see if there is a way to avoid saving the VFP context in the case you are sure that this ISR will not execute any VFP code.

    I will be back to you as soon as I have an answer.

  • Luke,

    Can you give me more detail on the way your ISR is written?

    I assume that the ISR is a C routine. For the access to the VFP registers, are you using Inline assembly or call to a subroutine is asm?

    Can you share this code?

  • Jean-Marc,

    Yes, the ISR is written in C.  To be honest, I haven't yet written the code to clear the FPSCR register, I was just manually clearing the bit in the register through the debugger.  I presume had I done so though, I would have written it as a subroutine call, not inline assembly.  I think I am starting to follow where your questions are heading though.  I did a little more testing here, and noticed that if my ISR is empty, it doesn't save the floating point registers during it's context save/restore.  I assume this is because the compiler is smart enough to see that the ISR is not using any floating point operations.  If I add any function/subroutine calls though, it appears to always save/restore the FPU registers (regardless of if the subroutine uses any floating point operations).  

    If this is indeed the case, were you going to suggest I use inline assembly to modify the FPSCR register (vs a subroutine), so that the compiler wouldn't restore the register on exit that I am trying to modify?  This may or may not be a feasible solution to my issue (I may not be able to change the ISR enough to remove ALL function/subroutine calls).

    Please correct me if I'm way off base on any of this.  I can't readily provide you the exact ISR code, but can see what I can do if you still would like to look at my exact use-case.

    Thanks,

    Luke

  • Hello,

    I am also facing this same problem. My FPU interrupt routine is checking what flags are set in register FPSCR to know which one of the six FPU exceptions happened. It is also clearing all exception flags. But compiler is adding code to save and restore register FPSCR so as soon as register is restored interrupt is raised again.

    Only solution I can think of is to write the interrupt service routine in assembler so I do not save/restore FPSCR register but I would prefer not to do that as I am working in a library and it would my the library user who would need to write this assembler function.

    Please help to solve this issue. I just need to instruct the compiler not to save/restore register FPSCR.

    Thanks,

  • Hi Lucas, Francisco,

    We just want you to know that we have been having some internal discussion with our compiler team and made some progress and will send you an update soon as far as workaround proposal in assembly (for now) and possible future steps taken from compiler team...

    The rational on why FPSCR is stored to stack (provided from compiler team) was that some customers were complaining that VCMP like instructions in the ISR can modify the floating point status bit in the FPSCR.  But saving it on the stack also creating problem for you like in the case of clearing the exception flags.  

  • I apologize for the long delay. We wanted to make sure we completely understood the issue before responding. We have determined that this is a compiler bug and have filed SDSCM00048834 to track the issue. The compiler should provide a mechanism that allows the user to clear the exception bits of the FPSCR before restoring it. This is not currently supported. 

    To workaround the problem you will need to write the interrupt handler in assembly. The best way to accomplish this is to place most of the interrupt handling code in a separate function and call it from the interrupt handler. You can then use the compiler to generate the assembly code for the handler and then modify that assembly code to clear the appropriate bits before restoring the FPSCR. Once you have done this you can just use the assembly file in your project.