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.

Interrupt keyword does not save context of STF register when --float_support=fpu32 flag is used for compiling.

Other Parts Discussed in Thread: TMS320F28069

We are using a F28069.

The compiler version is cl2000 version 6.2.5.

We experienced unexpected behavior of our application when executing this bit of code:

whatTheUnholyHellIsGoingOnHere = (testValue >= testLimit);

if ( whatTheUnholyHellIsGoingOnHere) {

    /* some code that should never be executed because the condition is always false, yet it does occasionally. */

}

testValue and testLimit are float variables.

We have tracked the problem down to an interrupt service routine that apparently gets called between the assignment of the variable and the if statement check.  This interrupt service routine had used the interrupt keyword to perform the context save and restore.

In the ISR, there are no floating point C variables, but the code generated does use floating point registers.  In particular, it uses statements such as:

MOV32        R5H, *+XAR4[0], UNCF

Upon reading "TMS320C28x Floating Point Unit and Instruction Set Reference Guide", I have learned this instruction to affect the STF flag bits.

Looking at the context save/restore disassembly, there are no provisions to save the context of the STF register.

I have created my own context save and restore macros which do preserve this flag.  I put them in a 'normal' (not interrupt keyword prefixed function), which simply calls the real ISR function (which I removed the interrupt keyword from), and now the unexpected behavior does not occur.

  • I'm sure your analysis is correct.  However, to submit a bug report, I need an interrupt function which modifies bits in STF but does not preserve it.  I have been unable to create such a function.  I'd appreciate if you would submit the source file which contains the ISR you describe, preprocessed like this.  I also need to know all the compiler options used.

    Thanks and regards,

    -George

  • There is another problem.  This is the generated context save with the interrupt keyword.

    3e013c:   761B        ASP         
    3e013d:   FFF0        PUSH         RB
    3e013e:   0005        PUSH         AR1H:AR0H
    3e013f:   ABBD        MOVL         *SP++, XT
    3e0140:   A8BD        MOVL         *SP++, XAR4
    3e0141:   A0BD        MOVL         *SP++, XAR5
    3e0142:   C2BD        MOVL         *SP++, XAR6
    3e0143:   C3BD        MOVL         *SP++, XAR7
    3e0144:   E20000BD    MOV32        *SP++, STF
    3e0146:   E20300BD    MOV32        *SP++, R0H
    3e0148:   E20301BD    MOV32        *SP++, R1H
    3e014a:   E20302BD    MOV32        *SP++, R2H
    3e014c:   E20303BD    MOV32        *SP++, R3H
    3e014e:   E6300600    SETFLG       RNDF32=1,RNDF64=1
    3e0150:   FF69        SPM          #0
    3e0151:   2942        CLRC         OVM|PAGE0
    3e0152:   5616        CLRC         AMODE

    as you can see, R4H-R7H are not saved.  Although the individual registers that may be used in a function are pushed onto the stack at the beginning of functions and restored on exit, this is not enough.  If you want to use nested interrupts by clearing the global interrupt mask INTM, you now run into the situation when another higher priority interrupt occurs, you will lose the state of these registers.

    This is my command for compiling.  Do you see anything wrong with it?

    C:/ti/ccsv5/tools/compiler/c2000_6.2.5/bin/cl2000

    -eo.o28FP

    -ea.s28FP

    -DLARGE_MODEL=1

    -Dfar=

    -Dxdc_runtime_Assert_DISABLE_ALL

    -Dxdc_target_name__=C28_float

    -Dxdc_target_types__=trust/targets/SourceCode/C28_float/std.h

    -Dxdc_bld__profile_release

    -Dxdc_bld__vers_1_0_6_2_5

    -c

    -v28

    -ml

    -mt

    -k

    --float_support=fpu32

    --float_operations_allowed=all

    -me

    --gen_func_subsections=on

    -pdsw225

    --diag_suppress=23000

    -O3

    --symdebug:dwarf

    --optimizer_interlist

    --auto_inline=30

    --opt_for_speed=4

    --single_inline

    --embed_inline_assembly

    --inline_recursion_limit=20

    --symdebug:dwarf

    -I.

    -IC:/Projects/MotorWareConversion

    -IC:/Projects/TrustRepo

    -IC:/ti/xdctools_3_25_04_88

    -IC:/ti/xdctools_3_25_04_88/packages

    -I../../../..

    -IC:/ti/ccsv5/tools/compiler/c2000_6.2.5/include

    -fs=./package/lib/lib/release/trust.drivers.ti.tms320f28069/SourceCode/UartProvider

    -fr=./package/lib/lib/release/trust.drivers.ti.tms320f28069/SourceCode/UartProvider

    -fc SourceCode/UartProvider/UartProvider-DeviceSpecific.c

  • I just noticed that this time the STF flag was saved.  I don't know why this is now generated, so I am a little confused.  I will recompile and check to see if I still have problems and check back.

  • I stand corrected about the STF flag not being saved.  I had some other drivers using context save/restore macros that I wrote which enabled interrupt nesting, but did not store/restore the STF flag (as I didn't know that it would be affected since I didn't use any floating point math).

    However, I am still curious about why R4H-R7H are not saved, even though they are used in my ISR.  Interrupt nesting will require these to be saved, right?

  • James lOCKWOOD said:
    3e0140:   A8BD        MOVL         *SP++, XAR4
    3e0141:   A0BD        MOVL         *SP++, XAR5
    3e0142:   C2BD        MOVL         *SP++, XAR6
    3e0143:   C3BD        MOVL         *SP++, XAR7

    These instructions save all 32-bits of the XARn registers.  See page 6-210 of the C28x CPU manual (revision E).

    Thanks and regards,

    -George

  • I am asking about the FPU registers which are different from the XAR registers.  In the series,

    3e0146:   E20300BD    MOV32        *SP++, R0H
    3e0148:   E20301BD    MOV32        *SP++, R1H
    3e014a:   E20302BD    MOV32        *SP++, R2H
    3e014c:   E20303BD    MOV32        *SP++, R3H

    it seems odd to me that R4H through R7H are not saved, yet my routine uses RH5  Other documentation I find, "TMS320C28x FPU Primer", section 4.2 shows a routine that does save them all.  I understand that the default behavior of interrupts is to run them until completion (keeping INTM = 1 until context restore), in which case, letting the compiler save and restore the R4H-R7H registers as needed in each function that is called is just fine.  But we want nested interrupts, in which case it looks like I can not use the interrupt keyword to save the context properly.

    Is there a flag that I should be using to compile with so that the interrupt keyword saves the entire context, or should I just manually do it in the assembly code (which I have no problem with)?

  • James,

    The floating point registers (R0H - R7H, and STF) are shadowed in hardware for fast context saving.  See The FPU Guide, SPRUEO2A, p.14.  When you use the interrupt keyword, there is a "HPI" parameter option that tells the compiler to use the shadow register (ref. Compiler Guide SPRU514G, p.111).  Are you using the HPI parameter with the interrupt keyword to declare your ISR?

    Regards,

    David

  • I have to assume I must have been doing something wrong until I can reproduce the problem and be sure that I used the interrupt keyword in every driver that was used.

    I created my context save and restore macros based upon what I had disassembled, but it is now evident that the code that the compiler creates for the context save and restore varies based upon the compiler flags used and whatever optimizations the compiler implements.

    Thanks for your help.