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.

TMS320F28335: SYSBIOS-1052 C28 Dispatcher alignment issue

Part Number: TMS320F28335

Hello,

According to the release notes for SYS/BIOS 6.76.01.12, one of the defects fixed since SYS/BIOS 6.76.00.08 is a "C28 Dispatcher alignment issue" with JIRA ID SYSBIOS-1052:

https://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/bios/sysbios/6_76_01_12/exports/bios_6_76_01_12/release_notes_bios_6_76_01_12.html

Can anyone provide me with more details about this issue?

Thank you,

Robert Stroud

  • The issue is located in /family/c28/Hwi_disp_asm.s28. There's some code like this:

     movz    ar0,@sp
    
        .if (.TMS320C2800_FPU32 == 1)
           subb    xar0, #13       ; point to IER on stack
        .else
            subb    xar0, #11       ; point to IER on stack
        .endif
                                    ; Note: if we change order of items
                                    ;       pushed on stack, double check
                                    ;       the value here.
    
            mov     *xar0, ier      ; IER value may have changed by
                                    ; the user till this time
                                    ; this need to be corrected in
                                    ; the stack where value of IER
                                    ; have been saved as hardware
                                    ; context and will be restored
                                    ; as a part of iret instruction

    Here's the description of the bug:

    It is writing current IER register value (possibly modified within HWI) to the location relative to the current stack pointer, where IER is restored from by the HW as part of the IRET sequence. Therefore, the intent is to preserve the current IER value at the end of an interrupt.

    Here is the problem. 32-bit register pairs written to the stack are aligned at even addresses, while alignment of the stack pointer itself is unchanged (SP is unconditionally incremented first to avoid overwrite). The exact sequence is documented in “3.4 Standard Operation for Maskable Interrupts” section of the “TMS320C28x CPU and Instruction Set” manual. The way it works, depending on the initial (odd or even) value of the SP register when an interrupt is triggered, the offset between the final SP value and IER restore location may be either 10 or 11 words (12 or 13 with FPU) at the moment the code above executes. The code assumes a fixed value of 11 (13 with FPU), which is wrong when an interrupt is triggered with initially odd-aligned SP. As a result, a data page (DP) register is getting overwritten with IER value. This causes a code running after the interrupt to read from or write to a wrong memory location.

    Whitney

  • Hello Whitney,

    Thank you for your quick response, which is very helpful. 

    Confusingly, the comment at the start of dispatchMain that describes the content of the stack after the interrupt context switch is wrong:

    ; At this point, the following registers have already been saved:
    ; ** Automatic interrupt context save (see SPRU513C) **
    ; ST0, T, AL, AH, PL, PH, AR0, AR1, DP, ST1, DBGSTAT, PC, and IER.

    The order is actually

    ; ST0, T, AL, AH, PL, PH, AR0, AR1, ST1, DP, IER, DBGSTAT, PC

    which makes more sense of the bug description because DP is adjacent to IER.

    Thanks again.

    Robert

  • Hello again,

    As a follow-up to my original question, this seems like quite a nasty bug, but how much of a problem was it in practice?

    If there is some reason why the stack pointer is almost always aligned to an even address (for example, because the code was written in C), it might be quite unusual for a hardware interrupt to occur when the stack is aligned to an odd address.

    I believe the C compiler requires the stack to be aligned on an even address boundary before calling a function - the Hwi_Dispatch logic ensures this - but is that sufficient to ensure that the stack is always on an even boundary whilst executing C code, or can the stack be on an odd address boundary?

    Thanks,

    Robert

  • Yes, that's my understanding of why this wasn't discovered sooner. The bug record had this additional info:

    The reason we don’t see this all the time is likely related to the way how compiler is using and aligning stack frames within functions, so the stack is even-aligned most of the time. Within __disable_interrupts() intrinsic a 16-bit value of ST1 is put on stack making SP odd, if preempted by an interrupt right after (before they are actually disabled), DP is now wrong.

    For reference __disable_interrupts is equivalent to the following assembly:

    PUSH ST1
    SETC INTM, DBGM
    POP reg16

    Whitney