• TI Thinks Resolved

Compiler/MSP430FR5969: GDB launch causing program counter error

Intellectual 720 points

Replies: 17

Views: 390

Part Number: MSP430FR5969

Tool/software: TI C/C++ Compiler

I've spent the past day investigating a very strange error occurring in GDB.

Behavior
- program fails to reach main (usually, not always)
- occurs only on first run after launching gdb, all successive loads are error free

To investigate this issue, I examined the assembly step by step. Immediately after load we seem to be where we should be:

0xe0e8 <__crt0_start>                   mova   #81920, r1      ;0x14000                                                                                 
0xe0ec <__crt0_init_bss>                mova   #7982,  r12     ;0x01f2e                                                                                 
0xe0f0 <__crt0_init_bss+4>              clr    r13             ;                                                                                        
0xe0f2 <__crt0_init_bss+6>              mova   #132,   r14     ;0x00084                                                                                 
0xe0f6 <__crt0_init_bss+10>             clr    r15             ;                                                                                        
0xe0f8 <__crt0_init_bss+12>             calla  #53686          ;0x0d1b6                                                                                 
0xe0fc <__crt0_init_highbss>            mova   #65538, r12     ;0x10002                                                                                 
0xe100 <__crt0_init_highbss+4>          clr    r13             ;                                                                                        
0xe102 <__crt0_init_highbss+6>          mova   #844,   r14     ;0x0034c                                                                                 
0xe106 <__crt0_init_highbss+10>         cmp    #0,     r14     ;r3 As==00                                                                               
0xe108 <__crt0_init_highbss+12>         jz     $+6             ;abs 0xe10e                  

The registers also appear to be correct (though I suspect these don't get updated before running) :

(gdb) info registers
pc             0xe0e8	0xe0e8 <__crt0_start>
sp             0x14000	81920
sr             0x0	0
cg             0x0	0
r4             0xffff	65535
r5             0xffff	65535
r6             0xffff	65535
r7             0xa55a	42330
r8             0xffff	65535
r9             0x112	274
r10            0x1af8	6904
r11            0xffff	65535
r12            0x4	4
r13            0x1113	4371
r14            0x1a1a	6682
r15            0x4400	17408

Then after entering a single "stepi" instruction, the $pc is suddenly pointing at the beginning of HIFRAM:

(gdb) stepi
0x00010004 in cosmosStrP.2845 ()

Instructions at this address:
0x10004 <cosmosStrP.2845+2>     and.b  @r15+,  -1(r15) ; 0xffff
0x10008 <cosmosStrP.2845+6>     and.b  @r15+,  -1(r15) ; 0xffff                                                                                         
0x1000c <cosmosStrP.2845+10>    and.b  @r15+,  -1(r15) ; 0xffff                                                                                         
0x10010 <cosmosStrP.2845+14>    and.b  @r15+,  -1(r15) ; 0xffff                                                                                         
0x10014 <cosmosStrP.2845+18>    and.b  @r15+,  -1(r15) ; 0xffff                                                                                         
.
.
.

As you can see, the program counter is in the weeds:

(gdb) info registers 
pc             0x10004	0x10004 <cosmosStrP.2845+2>
sp             0x14000	81920
sr             0x101	257
cg             0x0	0
r4             0xffff	65535
r5             0xffff	65535
r6             0xffff	65535
r7             0xa55a	42330
r8             0xffff	65535
r9             0x112	274
r10            0x1af8	6904
r11            0xffff	65535
r12            0x4	4
r13            0x1113	4371
r14            0x1a1a	6682
r15            0x4400	17408

According to the map file, this is the location of upper.data:

.upper.data     0x0000000000010000        0x2 load address 0x00000000000058de
                0x00000000000058de                __upper_data_init = LOADADDR (.upper.data)
                0x0000000000010000        0x2 SHORT 0x1
                0x0000000000010002                __high_datastart = .
*(.upper.data.* .upper.data)                  
                0x0000000000010002                __high_dataend = .
                0x0000000000000000                __rom_highdatacopysize = (SIZEOF (.upper.data) - 0x2)
                0x00000000000058e0                __rom_highdatastart = (LOADADDR (.upper.data) + 0x2)

So that's very strange and I don't see how $pc can be set to 0x10000 on the initial load. I was unable to find clear information on how the CPU registers are set. Now if we do a "load" the registers appear to be back to normal:

(gdb) info registers 
pc             0xe0e8	0xe0e8 <__crt0_start>
sp             0x14000	81920
sr             0x101	257
cg             0x0	0
r4             0xffff	65535
r5             0xffff	65535
r6             0xffff	65535
r7             0xa55a	42330
r8             0xffff	65535
r9             0x112	274
r10            0x1af8	6904
r11            0xffff	65535
r12            0x4	4
r13            0x1113	4371
r14            0x1a1a	6682
r15            0x4400	17408

And indeed, we can run with no issues:

(gdb) stepi
0x0000e0ec in __crt0_init_bss ()
0x0000e0f0 in __crt0_init_bss ()
0x0000e0f2 in __crt0_init_bss ()
0x0000e0f6 in __crt0_init_bss ()
(gdb) b	main
Breakpoint 1 at 0x5a32: file src/main.c, line 13.
(gdb) c
Continuing.

Breakpoint 1, main (argc=0, argv=0x0) at src/main.c:13

Debugging

  • This behavior is repeatable
  • I've been using the same debug stack for the past two weeks and the problem only started yesterday, so I assumed this was a code problem
  • The most likely cause seemed to be the linker file. I pointed the stack at the top of HIFRAM and changed the length of HIFRAM to be 0x4000 instead of 0x3FFF to align $sp. Even though this is technically 1 address past the end of the allowable address range, my understanding is that $sp is always decremented (into an allowable address) before being used. This has been working for days but just to be safe I tried restoring the linker to its original configuration
  • I used old code that never encountered this problem and is also ~12kB smaller
  • When I power cycle the board without gdb running, the board restarts and the code executes normally
  • I tried disconnecting my analog ADC signals
  • I tried using another MSP device
  • I restarted the lab machine it's running on

Without knowing more about how the core CPU registers are set and how to probe them before executing, I'm out of debugging ideas

  • Hey Mike,

    Thanks for the detailed post, lots of info to dig through.  I'm not very familiar with the GBD tool, so let me dig in and I might have to loop someone else in.

    I'll try and get back to you later today. 

    Thank,

    JD    

    _____________________________________________________________________________


  • In reply to JD Crutchfield:

    Hi JD,

    Is there any update on this? I know there's a lot to work through here but I'm curious to know what's going on.

    Cheers,
    EM

  • The MSP430 will load the program counter from the reset vector at 0xFFFE on reset. What gdb will do is another question. It could look at the .elf file for the starting point (after a load command) or do something else.

  • In reply to David Schultz36:

    Hello Mike,

    Very sorry, I got pulled away and haven't been able to look into this.  I wanted to check in.  Are you still having this issue with GBD somehow corrupting the PC? 

    Was this is only after the very initial flashing of the device and after either a software or hardware reset it worked as expected?  

    Thanks,

    JD

    _____________________________________________________________________________


  • In reply to JD Crutchfield:

    Thanks for checking in. Somehow, the issue seems to have disappeared.

    The problem was occurring only after the initial flash when launching gdb. After gdb was running, I could reload the code (without killing gdb) consistently with no issue.

  • In reply to EmbeddedMike:

    Of course after I made this comment the problem is back. Pretty strange because it had been working without issue for the past week or so.

  • In reply to EmbeddedMike:

    I discovered that the problem seems at least partially dependent on the image being flashed for some reason. While I was debugging a watchdog problem, I commented out a single line of code, rebuilt, launched gdb, and noticed that the first launch problem did not occur. I tried this several more times to confirm.

    I then uncommented that line of code and the problem returned, but this time the $pc problem occurs on every other launch. I tried this several more times to confirm as well. Note that this behavior has been observed before as well.

    The line of code in question: while(REFCTL0 & REFGENBUSY);

    I do not believe that this line of code is causing the problem. This line has been included in my application for some time and was present both when the problem was occurring and when it was not. If anything, this seems like a problem with the way the image is flashed in certain cases. 

  • In reply to EmbeddedMike:

    Hey Mike,

    This does seem like a very strange issue.  I've never heard of anything like it before.  

    What does you full setup look like?  What compiler and tools are you using? Can you provide version numbers for compiler and gdb?  

    We're getting beyond my scope of knowledge here, so I might send this info over to the compiler team and see if they have any ideas.  

    Thanks,

    JD


      

    _____________________________________________________________________________


  • In reply to JD Crutchfield:

    I've tried everything I can think of to debug this issue. On launches where the $pc is wild, the very first "stepi" is off in the weeds so the code never has a chance. My best guess is that the $pc is never properly initialized but I couldn't find any info on how or why that might be the case.

    As for my setup, I'm using the MSP430-GCC Standalone Debug Stack. Version info:

    Component versions

    • GCC 7.3.2.154
    • GDB 8.1
    • binutils 2.26.0
    • Newlib 2.4.0
    • MSPDebugStack 3.14.0.000
    • MSP430 header and support files 1.207
    • MSP430 GDB Agent 8.0.809.0

     

    Link to download page: http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/6_1_1_0/index_FDS.html

  • In reply to EmbeddedMike:

    I wonder if this is a manifestation of an issue we've seen where GDB fails to flash large executables properly: http://e2e.ti.com/support/tools/ccs/f/81/p/801858/2971415#2971415

    Is executing the "load" command again the only thing that fixes it when you experience the bad execution?

    The default timeout in GDB for communication with the gdb_agent_console is only 2s in 7.3.2.154. You can increase the timeout using "set remotetimeout 10".

    There is now an installer available for the latest MSP430-GCC release 8.3.0.16, so if you want to try that release, this higher timeout is set by default.

    P.S.

    Make sure to use the tag "MSP430-GCC-OPENSOURCE" when posting about the MSP430-GCC toolchain, I'll see the post a lot quicker.

    Regards,


    Jozef Lawrynowicz
    MSP430-GCC Developer
    www.mittosystems.com