• Not Answered

How does interrupt affect the AMR register

Hi, I am developing a fir filter in linear asm and used AMR to setup the circular buffer. The AMR is set during the filter start and returned to previous setting when exiting the filter. But I would like to know what will happen to the ISR, when being interrupted when running the filter. Does the AMR setting still effective when executing ISR. And how to prevent the ISR from being interfere by AMR setting in the filter? Thanks.

9 Replies

  • Kind of freaky timing, because I'm too "wrestling" with it. I have some subroutines that use circular addressing and they sporadically fail to produce correct result when interrupts are enabled. Admittedly it's not properly documented. Originally I thought that I ought to preserve ARM in ISR:

    cregister int AMR;
    interrupt void Isr()
    { int saved_AMR=AMR;
      AMR=0;
      /* process */
      AMR=saved_AMR;
    }
    

    but my subroutines still fail sporadically... Is it possible that AMR is cleared upon interrupt delivery? In such case one would have to arrange that no interrupts are delivered between write to AMR and circular addressing instruction. This would mean frequent writes to AMR and a lot of DINT/RINT (or tracing when interrupts are disabled implicitly like in SPLOOP).

  • In reply to Andy Polyakov:

    Another freaky thing is that neither of you said which DSP you are using. It may also be helpful to know if you are using BIOS, which version of CCS, and which version of the compiler tools you are using.

    AMR will be preserved across an interrupt and can cause problems for an ISR if the same registers are used. The C Compiler User's Guide will tell you which registers are expected to be at their default states for the C environment to operate correctly.

    Put a test into your FIR code that checks the value of AMR prior to clearing it at the end of that function. Set a breakpoint to catch if that value is ever different or set a global flag that you can test when you have noticed that the FIR has functioned incorrectly.

    Try one of our FIR routines from the DSPLIB and see if they ever have this problem. I do not know if they use AMR, but probably not.

    Try DINT/RINT across the whole FIR function to see if that fixes the problem. Then move the DINT later in the code and/or the RINT earlier until you find a smaller region in which the interrupt is causing the problem.

    The C6000 architecture uses an unprotected pipeline that can have problems with interrupts. The compiler knows this and will keep its software-pipelined loops safe, but the linear assembler might not add that overhead to its output.

    Regards,
    RandyP

  • In reply to RandyP:

    RandyP
    Another freaky thing is that neither of you said which DSP you are using. It may also be helpful to know if you are using BIOS, which version of CCS, and which version of the compiler tools you are using.

    I use C6455 DSP. One can argue that my comment is misplaced, as it appears in C67x forum, but I assume that it doesn't matter much in the context. CCS and compiler versions are of no relevance in my case, because I write raw assembler, i.e. non-linear. I'm not using DSP/BIOS and can only disclose that my AMR code fails when interrupts are enabled, but works correctly otherwise. I'm saving/restoring AMR in one ISR and verified with disassembler that remaining can't be affected by non-zero AMR.

    RandyP
    The C6000 architecture uses an unprotected pipeline that can have problems with interrupts. The compiler knows this and will keep its software-pipelined loops safe, but the linear assembler might not add that overhead to its output.

    Compiler never uses AMR. But why doesn't it preserve it the way it does [R]ILC? I mean in prologue/epilogue in functions declared as 'interrupt'? And by extension all control registers available to non-privileged code?

  • In reply to Andy Polyakov:

    Kee Yong Ting,

    Which device are you using? The C6701, for example, is going to behave differently in many cases than any C64x+ device. That device information can be helpful when you do not already know the answer. We have tried to keep upward compatibility in most family paths in the C6000 family, but there is some divergence between the original C62x and the original C67x; there has been a merging of those in the C674x and later.

    Andy Polyakov
    Compiler never uses AMR. But why doesn't it preserve it the way it does [R]ILC?

    The compiler version may be of some relevance if you are using it in your application. Please refer to the User's Guide for the version of compiler you are using to see what restrictions exist on the use of the AMR or other registers. You can use the pdf reader's search on AMR to find what restrictions there may be.

    Regards,
    RandyP

  • In reply to Andy Polyakov:

    As it turns out I have to withdraw my question about preserving and zeroing AMR in interrupt service routine being insufficient. Above mentioned Isr() snippet is sufficient [for AMR and modulo that AMR has to be declared unsigned int(*)]. I apparently had two problems with my code, only one attributed to AMR. I mean I did have problem with AMR, which I was able to fix by preserving and zeroing AMR, and there was another unrelated problem that caused sporadic failures [on another kind]. For completeness second problem was following. I arrange circular buffer on stack. As you surely know it has to be aligned at the buffer size. So I aligned stack pointer but failed to reserve two additional words above it, as one on top is overwritten by interrupt service routine.

    (*) As Randy implied, you can as well include c6x.h and be excused from declaring it yourself.

  • In reply to RandyP:

    RandyP
    Andy Polyakov
    Compiler never uses AMR. But why doesn't it preserve it the way it does [R]ILC?

    The compiler version may be of some relevance if you are using it in your application.

    6.0.13 and 7.2.2. I've even had quick look with disassembler at code generated by 6.1.x and 7.3.x and can't see any significant difference in the context.

    RandyP
    Please refer to the User's Guide for the version of compiler you are using to see what restrictions exist on the use of the AMR or other registers.

    This is not my question. Let me rephrase. I could observe that above mentioned compilers do preserve [R]ILC in functions declared as 'interrupt' in C. This means that apparently [at some point] TI decided to make life easier for developers by arranging this. Question is why did TI stop at [R]ILC? Why not all computationally significant control registers, specifically AMR, SSR, GFPGFR, GPLY[AB], ...?

    Well, this is getting out of topic, because C67x doesn't have most of the mentioned registers, but I'd argue that point in general still stands. I.e. that it would be more than appropriate if compiler would preserve all computationally significant control registers. Just that in C67x case it would be AMR and floating-point specific control registers.

    RandyP
    You can use the pdf reader's search on AMR to find what restrictions there may be.

    This is cold, man, so cold...

  • In reply to Andy Polyakov:

    Andy,

    Impressive use of the Quote button. And your questions and thought process are impressive, too.

    We document what our tools do, not the reasons why they do not do everything else. The C environment is intended for a valid implementation of C code, with a documented interface to allow integration with assembly code; but that assembly code must meet the interface requirements that we establish. You seem to want it to be the other way around where the C environment is tolerant of anything the assembly programmer could throw at it; but that is impossible and difficult to even aim for. Maybe you only want it to be the other way around for specific cases that apply to you.

    I think you can figure out a good reason why [R]ILC are preserved, and it is not for the benefit of assembly programmers. I prefer to get you to think of the reason, so please stop reading this paragraph until you have an answer. The compiler uses SPLOOP, and therefore [R]ILC, for optimizing loops. So it knows it has to preserve those registers to maintain the C environment.

    The compiler does not use the other registers you listed, so it does not preserve them. It would have to be done at the expense of extra MIPS required for every ISR for everyone, just to appease the rare assembly programmer who wants to have interrupts enabled while doing things that the compiler does not like.

    Andy Polyakov

    RandyP
    You can use the pdf reader's search on AMR to find what restrictions there may be.

    This is cold, man, so cold...

    No offense intended. It is impossible to tell from this side of your browser window how adept you are with searches and how interested you are in finding the answers yourself. In my case, I wrote that after doing that very search. The "cold" part is that I wanted you to go find those restrictions so you would learn your way around the Compiler User's Guide, and since I did not know how old or new the version of your compiler is (at that time, I did not know). What I found from the v7.3 User's Guide were only 30 instances of AMR (case-sensitive), and many of them were multiple instances in a single paragraph:

    • The AMR must be set to 0 when interrupts are enabled, or the SAVE_AMR and STORE_AMR macros should be used in all interrupts (see Section 7.6.3).
    • By default, the compiler does not do anything extra to save/restore the AMR and the SAT bit.
      Macros for handling the SAT bit and the AMR register are included in the c6x.h header file.
    • The C code interrupt service routine assumes that the AMR is set to 0.

    It was not obvious from our discussion that you saw these already, but from your reaction I was mistaken. Again, I apologize for any offense and for any wrong assumptions.

    Regards,
    RandyP

     

    If you need more help, please reply back. If this answers the question, please click  Verify Answer  , below.

  • In reply to RandyP:

    RandyP
    I think you can figure out a good reason why [R]ILC are preserved, and it is not for the benefit of assembly programmers. I prefer to get you to think of the reason, so please stop reading this paragraph until you have an answer. The compiler uses SPLOOP, and therefore [R]ILC, for optimizing loops. So it knows it has to preserve those registers to maintain the C environment.

    The compiler does not use the other registers you listed, so it does not preserve them.

    This is not entirely true. While compiler indeed doesn't use AMR, rest of registers is accessible from C. To keep it in C67x context let's consider say FMCR. Imagine C code that sets up specific rounding mode and monitors status to detect some specific condition [for whatever reasons]. If interrupt occurs between instructions that write and read FMCR and interrupt handler performs multiplication that affects the register, the user code will be led to wrong conclusions. Even from the other size, what if interrupt service works correctly only with default power-up values in FMCR and ISR programmer was not experienced enough to realize that? Yes, I imply that in this case it might be appropriate to let compiler not only preserve FMCR, but even reset it to default value upon entry to interrupt service routine.

    RandyP
    It would have to be done at the expense of extra MIPS required for every ISR for everyone,

    1 cycle per control register in addition to 64+ cycles for full-blown 'interrupt' prologue+epilogue is a problem? If it's so important why not optimize prologue+epilogue to run in 32+ cycles instead of 64+? And use those freed cycles for preserving control registers? I mean MIPS is not viable argument...

    RandyP
    just to appease the rare assembly programmer who wants to have interrupts enabled while doing things that the compiler does not like.

    This works under assumption that one person [or tight team] programs everything. But there is whole world beyond that and by keeping compiler to itself shuts this world for that person [or tight team]. It's not a good strategy...

  • Kee Yong Ting,

    From all of this discussion, do you have your answer?

    Regards,
    RandyP