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.

Can I dump the stack of F2812 under CCSv4?

I am developing apps for the F2812 using Code Composer V4
and every once in a while I wind up in the ILLEGAL_ISR(),
which I think is provided by the default PIE vector table,
which stops the processor.

I have in the past been able to trace these events
indirectly to some gross memory violation, but it takes a
lot of time. Other IDEs I have used allow the user to dump
the contents of the stack as well as the stack pointer to
the console (or a file) allowing me to track down the exact
point in my application where this jump took place. I can
find nothing in the CCS documentation to suggest it can do
this.

I know I can dump the .stack section in the 'Memory' window
and figure out what entries are addresses. Then I have to
pore over my .map file to figure out what sections those
addresses are inside of and calculate the offset. This is a
tedious, manual, and error-prone task that would be better
automated.  Has anybody done such a thing?

  • Gary,

    Here are some links and other references for debugging illegal isr and stack overflows which might be helpful. Some similar suggestions have been posted in the C2000 device forum as well.

    http://processors.wiki.ti.com/index.php/Interrupt_FAQ_for_C2000#The_ITRAP_Interrupt
    http://processors.wiki.ti.com/index.php/Checking_for_Stack_Overflow

  • AartiG, thanks for the ideas.

    I fear I am not phrasing my question accurately, so let me
    try again.

    In the last 48 hours I have solved my immediate problem
    using the "tedious, manual, and error-prone" methodology
    (which I have used on other processors and other IDEs) I
    described earlier. When something this bad goes wrong, I
    seek a way not to grope more intelligently in the dark, but
    to zero in on the root cause of the crash using evidence at
    hand at crash time. My approach goes like this.

      1.  When my program hit the ILLEGAL_ISR the stack pointer
          always pointed to 0x041C. I got this from the
          'Registers' window. I had initialized it at power
          up 0x0400.

      2.  From SPRU430E "TMS320C28x CPU Instruction Set
          Reference Guide", section 2.2.5, I learned that the
          the stack grows 'downward' from lower memory addresses
          to higher ones.  Section 3.4 told me that when a
          maskable interrupt occurs (and ILLEGAL_ISR is
          maskable) the hardware pushes 14 words onto the stack.
          The return address of the instruction following the
          one that caused the exception is the last two words
          pushed--low word first.

      3.  I then used the 'Memory' window in CCS to look at
          address 0x0400 in data memory. There is a 'Save'
          button there that allowed me to export a block of
          about 0x20 words (the entire content of the stack and
          then some) to a .dat file.

      4.  I then hand-edited that file to show the current
          location of the SP (which is always the next empty
          location that will receive the next push), and all the
          data items that got pushed right before entering the
          ILLEGAL_ISR, which I will embed here:
              0x0400 : 0x911B
              0x0401 : 0x0000
              0x0402 : 0x9AFA ??
              0x0403 : 0x003D ??
              0x0404 : 0x0800
              0x0405 : 0x0000
              0x0406 : 0x0400
              0x0407 : 0x0000
              0x0408 : 0x0800
              0x0409 : 0x0000
              0x040A : 0x9C5A ??
              0x040B : 0x003D ??
              0x040C : 0x00C5
              0x040D : 0x0FED
              0x040E : 0x0034 ST0
              0x040F : 0x0000 T
              0x0410 : 0xF1F9 AL
              0x0411 : 0x0069 AH
              0x0412 : 0x0001 PL
              0x0413 : 0xFFFF PH
              0x0414 : 0x8A08 AR0
              0x0415 : 0x0259 AR1
              0x0416 : 0x8006 ST1
              0x0417 : 0x001F DP
              0x0418 : 0x06A4 IER
              0x0419 : 0x0009 DBGSTAT
              0x041A : 0x8006 L(PC)
              0x041B : 0x001F H(PC)
        SP--> 0x041C : 0x8ED7
              0x041D : 0x003D
              0x041E : 0x0000
              0x041F : 0x0525

      5.  This tells me the instruction that caused my problem
          was the one right before memory location 0x1F 8006. 
          Consulting my linker command file, I find that this is
          not a valid address in either program nor data memory!
          Small wonder, then, that it held an invalid op-code.

      6.  So I proceed up the stack (this involved a little
          guesswork, which I dislike) and I see something else
          at 0x040A & 0x040B that looks like an address in the
          flash space. I go to a section in my .map file called
          "GLOBAL SYMBOLS: SORTED ALPHABETICALLY BY Name" and
          use the Windows findstr command to pull out all
          symbols whose address starts with "003d" and sort them
          in address order. The highest address that is less
          than 0x3D 9C5A looks like it could be my main().

      7.  If your eyes are glazed over by now, you have
          validated my assertion that this process is "tedious",
          but we are not done yet.

      8.  I subtract the address of main() from 0x3D 9C5A to
          obtain an offset into that section and generate a .lst
          file for the file that contains main().  I scroll down
          to the point indicated by my offset and find it points
          to:
            1245              ;------------------------------------------------------------
            1246              ; 495 | battStateTable[battState]();                                          
            1247              ;------------------------------------------------------------
            1248 000000ee 3B01          SETC      SXM                   ; [CPU_]
            1249 000000ef 8F00!         MOVL      XAR4,#_battStateTable ; [CPU_U] |495|
                 000000f0 0000
            1250 000000f1 5603!         MOV       ACC,@_battState << 1  ; [CPU_] |495|
                 000000f2 0100
            1251 000000f3 FF69          SPM       #0                    ; [CPU_]
            1252 000000f4 5601          ADDL      XAR4,ACC              ; [CPU_]
                 000000f5 00A4
            1253 000000f6 C5C4          MOVL      XAR7,*+XAR4[0]        ; [CPU_] |495|
            1254              $C$DW$137       .dwtag  DW_TAG_TI_branch
            1255                      .dwattr $C$DW$137, DW_AT_low_pc(0x00)
            1256                      .dwattr $C$DW$137, DW_AT_TI_call
            1257                      .dwattr $C$DW$137, DW_AT_TI_indirect
            1258 000000f7 3E67          LCR       *XAR7                 ; [CPU_] |495|
            1259                      ; call occurs [XAR7] ; [] |495|
            1260                      .dwpsn  file "../RectCtl.c",line 496,column 5,is_stmt

          This statement executes a finite state machine by
          calling a function out of a function pointer table,
          using battState as an index into the table. I had
          foolishly assumed that battState could not attain
          a value larger than I had provided for in the table
          because the only way its value changed was when I
          assigned a constant to it.  I put it inside an if
          statement to check this assumption:
            if(battState <= 7) {
              battStateTable[battState]();
            } else {
              battState = 0;
            }

          and set a breakpoint on the else-clause. Sure enough,
          someone had changed battState to 26 and this was the
          point where my app was crashing.

      9.  It took several more hours, working with my co-
          programmer to discover an out-of-bounds index into an
          array holding A/D data, upmemory from battState was
          trashing downmemory globals and we finally got it
          fixed.

    So, returning to my original question, the hardest part of
    this process was in step 4, which some IDEs call 'unwinding
    the stack.'  If there were just some way to automate that,
    it would have saved me a great deal of time.

    Most IDEs allow me to write script files to handle custom
    jobs like this, but the only thing I have been able to find
    in Code Composer is the GEL file. Every time I ask a
    programmer about GEL files he tells me "You have no use for
    GEL files in version 4." And all the resources I have found
    in the CCS web pages are associated with CCSv3, which I have
    never used and would hate to have to learn just to acqjuire
    this one resource.

    Any ideas?