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.

CCS/TM4C129XNCZAD: Debugging an asm bootloader

Part Number: TM4C129XNCZAD

Tool/software: Code Composer Studio

I am having problems debugging the TivaWare project boot_emac_flash. The project should download a new firmware image via Ethernet.

Breakpoints don't work initially and I can't step through the assembly code. These two issue combined make it impossible for me to see any initial setup code. The code doesn't run properly with optimizations off. I think the issues are caused by the chip running code from SRAM.

Breakpoints for C files can not be set when the code is first loaded. Disabling and enabling a breakpoint will cause it to take effect after the code is allowed to run. I also see the breakpoint take efect if the chip is suspended and resumed, but thos results are intermittent. I know the processor will hit a while(1) loop on line 1776 of bl_emac.c. I set a break point in this loop. Pausing the chip shows it is within this loop. I can single step over the breakpoint. After I resume running, the chip might start hitting the breakpoint . If I pause, disabled and re-enabled the breakpoint, it will break. I do this by unchecking and checking the box in the Breakpoints window. Note to re-create this issue, the dev kit needs to be plugged into a switch. A previous wait looks for network connectivity. before hitting line 1776 of bl_emac.c

Line 257 of bl_startup_ccs.s does not work with the step over or step into commands. Either of those commands seem to act like the command resume running. ProcessorInit is on line 190 of bl_startup_ccs.s. I can set a break point after the label "ProcessorInit " and it will stop, but the process will behave as if "resume running" was clicked if the breakpoint is not set.

With optimizations off, the chip does not go to the function specified by the reset vector. I can see the reset vector is set to 0x16D5 in the memory browser and the disassembly shows ResetISR() at 0x2000016D4, but this point is not hit by the first step over. I think the PC arrives at the wrong function by error (

With optimizations on, ResetISR() is hit by the first step over with optimizations on when the reset vector is 0x0DC9 and ResetISR() at 0x20000DC8

The disassembly window always shows the processor at some 0x2000XXXX address which is why I believe the setup code makes the chip operate from SRAM.

I import the project from TivaWare_C_Series 2.1.4.178. I follow CCS warning to change the compiler from TI v5.2.6 to TI v18.1.1.LTS. CCS is at version  8.0.0.00016. The target hardware is the EK-TM1294XL. The connection is ICDI.

  • Hi Peter,

    Peter Borenstein said:
    I import the project from TivaWare_C_Series 2.1.4.178. I follow CCS warning to change the compiler from TI v5.2.6 to TI v18.1.1.LTS. CCS is at version  8.0.0.00016. The target hardware is the EK-TM1294XL. The connection is ICDI.

    I've got the exact same setup here.

    However,

    Peter Borenstein said:
    Breakpoints don't work initially and I can't step through the assembly code.

    I can't reproduce these issues. I imported the project and built it with the default options (-o2)

    I have no issues setting breakpoints in C files when the code is first loaded. I was able to set one on line 1783 of bl_emac.c (I double clicked on the editor marge at 1776 but the debugger moved it to 1783 where relevant code was). I have no issues setting breakpoints in bl_startup_ccs.s and I can step through that asm file just fine. I can set a breakpoint at line 257, run to the breakpoint and then asm step into ProcessorInit.

    Peter Borenstein said:
    The code doesn't run properly with optimizations off. I think the issues are caused by the chip running code from SRAM.

    I can't comment on the above two issues as I lack the expertise of the device and the example code. I will forward this thread to the device experts who can provide more insight.

    Thanks

    ki

  • Hi Peter,

    I seem to be able to see the same problem. I'm using CCS7.3. I can single step fine but if I place a breakpt then it does not halt. I think I agree with you that it may have something with the reset vector mapped to SRAM area. Once you load the bootloader the debugger will first halt at the reset vector. If you look at the PC address. It is at 0x2000xxxx address which is the "run" address not the "load" address. When you place a breakpt I wonder if the breakpt is placed in the flash which will be at 0x0000xxxx and hence the debugger does not hit the breakpt. I have to say I'm not sure if the theory holds.

    Did you have the boot_emac_flash working in run mode that let you update the firmware image via Ethernet?
  • ki,

    I put a fresh install of tivaware v2.1.4.178 on another PC. The issue occurse. I have to do some odd combination of suspending and disabling/re-enabling to get the breakpoint to break.

    I see the same breakpoint movement to line 1783 in my setups. The pbreakpoint is at an SRAM address 0x20000B3C. but it breaks at address 0x20000B44 (after the hack steps)

  • Here is a screenshot of the breakpoint's properties at the start. The properties don't change between this point and when CCS is coerced into to respecting the breakpoint.

  • Charles,

    I had the same theory about the breakpoint initially being set to the flash location, but my screenshots of the breakpoint properties prove this is not so.

    The project does work. I can get the LM Flash programmer to upgrade my devices with some .bin file.

    I hope to edit this bootloader to save a new image to some memory region, verify the CRC, then copy the new verified image over the current image. A botched update should resume running the current image. You replied to my other post on the topic.

    The goal is made difficult by this debugging issue. Stepping through the code helps me understand what is happening

    Do you know of any documentation for this project? I see "Doxygen" in the comments.
  • Hi Peter,
    There is no separate documentation for the boot_emac_flash project. There is the TivaWare Boot Loader user's guide that you may have already looked at. It is the SW-TM4C-BOOTLDR-UG-2.1.4.178.pdf in the TivaWare library under the docs folder.
  • This issue occurs in the project boot_serial which is available in the resource explorer. boot_emac_flash must be imported from the TivaWare install directory. Perhaps using this project could eliminate some variables?

  • Peter Borenstein said:
    but it is comical that the TI employee responsible for CCS doesn't see the the debugging error and the TI employee responsible for devices does.

    This happens sometimes. The common reason for that is the tools person (in this case - me) lacks fundamental expertise of the device (and example/SDK) to properly understand the issue to reproduce it - knowledge that both the device expert and the experienced customer would find trivial. I will work with Charles so he can help me reproduce the issue.

    Thanks

    ki

  • The breakpoints will be "ignored" again after a core reset or restart command is given.

    Breakpoints placed in the flash address are always respected including after core resets. I have to give a core reset to get back into flash. The restart button puts you where CCS starts (_c_int00 at an SRAM address).

    Breakpoints placed in the flash have a label "H/W BP". Does this label mean hardware breakpoint? The The ignored breakpoints are labeled "S/W BP". Is there a way to set a H/W BP in SRAM code instead of a S/W BP?

    After a core reset is given, I can see assembly code that matches the source in bl_startup_ccs.s. I have to see this in the dissasembly window. CCS doesn't display the source and says "Break at address "0xdc8" with no debug information available, or outside of program code." Because of this, I set the breakpoint by clicking the margin in the disassembly window.

  • I tried to set a hardware breakpoint in SRAM but CCS says "Error enabling this function. Address exceeds the allowed range".

    Testing if software breakpoints are ignored in a non-bootloader project would be interesting. I do not know how to explicitly set software breakpoints in flash memory. Right clicking the disassembly margin on allows me to specify a hardware breakpoint.
  • Hi Peter,

    You cannot set s/w breakpt on the flash memory. S/w breakpt requires the debugger to modify the instruction (when stored in the SRAM) to make the instruction breakable. You can only do hardware breakpt on the flash memory.
  • I believe the initial assembly code of this project copies memory into SRAM. Could this be overwriting the s/w breakpoints?

    This would not explain why Ki successfully hit them...
  • May I rise to the defense of Ki-Soo-Lee?     It has long been noted that he has effectively serviced,  "THOUSANDS of client-users" - and his knowledge is unusually broad, deep & caring.

    That said - Vendor Agents - even outsiders here who have Co-founded - taken past Tech Firm PUBLIC - cannot be expected to know "everything" - especially when "cold" - and when otherwise, "Scrambling to Assist!"

    I thus find Peter's choice of the word "comical" highly IMPROPER - even regretful.     A word-choice such as, "unfortunate" (yet understandable - as Mr. Lee well detailed) - would have proved far more appropriate & markedly superior...      To "attack" one striving to assist - never proves,  "well-thought, kind or wise!"

  • Hi Peter,
    I think that is a decent theory. After l first loaded the program the CPU is first halted at the reset vector. It hasn't copied the code to the SRAM yet. I don't know how the debugger places the s/w breakpt at this time. Eventually when the run code is copied to the SRAM whatever was previously in the SRAM will be overwritten.

    Now I tried to let the code run first. It will stay in the while(1) loop of the UpdateBOOTP function as it is waiting for the magic packet. If I place s/w breakpts on some of the lines inside the while(1) loop then it will break.
  • Hello Peter,

    I have been having a private discussion with Charles, but let me share what I have found.

    I have been able to reproduce some of the issues. Specifically:

    Peter Borenstein said:
    Breakpoints for C files can not be set when the code is first loaded. Disabling and enabling a breakpoint will cause it to take effect after the code is allowed to run. I also see the breakpoint take efect if the chip is suspended and resumed, but thos results are intermittent. I know the processor will hit a while(1) loop on line 1776 of bl_emac.c. I set a break point in this loop. Pausing the chip shows it is within this loop. I can single step over the breakpoint. After I resume running, the chip might start hitting the breakpoint . If I pause, disabled and re-enabled the breakpoint, it will break. I do this by unchecking and checking the box in the Breakpoints window. Note to re-create this issue, the dev kit needs to be plugged into a switch. A previous wait looks for network connectivity. before hitting line 1776 of bl_emac.c

    I can definitely reproduce this consistently now. Basically once the debugger halts or steps over the address where the breakpoint is, it now seems to "recognize" that breakpoint. I set a few breakpoints in the C code, on lines 1783, 1865, 1909. I manually halted and it was on line 1783. When I ran again, it would only halt on 1783. After it halted on 1783, I source stepped to 1865. The I ran. It would halt on 1783. When I ran again, now I'd halt on 1865. Eventually I got the breakpoint on 1909 recognized when I went through a similar step.

    Peter Borenstein said:
    Line 257 of bl_startup_ccs.s does not work with the step over or step into commands. Either of those commands seem to act like the command resume running. ProcessorInit is on line 190 of bl_startup_ccs.s. I can set a break point after the label "ProcessorInit " and it will stop, but the process will behave as if "resume running" was clicked if the breakpoint is not set.

    Now this part I didn't consistently reproduce. After an explicit program load, I can always halt on breakpoints I set in the asm file. I can also step in/over line 257. However, if I restart the program, I get the issue where the breakpoints in the asm file are ignored.

    this is still under investigation...

  • Charles Tsai said:
    After l first loaded the program the CPU is first halted at the reset vector. It hasn't copied the code to the SRAM yet. I don't know how the debugger places the s/w breakpt at this time. Eventually when the run code is copied to the SRAM whatever was previously in the SRAM will be overwritten.

    the debugger will be aware of the run address and will try to set a breakpoint at the run address, even before the code got copied to it

    It could be that then the breakpoint op codes set in SRAM gets overwritten when the code is copied to it. But the question is why does it eventually "work" once that address is reached? Maybe the debugger recognizes that there is no breakpoint opcode there and reapplies it. 

  • Ki-Soo Lee said:
    It could be that then the breakpoint op codes set in SRAM gets overwritten when the code is copied to it.

    This seems to be the case. If you load the program and run it so that the code has been copied to SRAM, and then halt the program and set breakpoints in the C file, everything works. 

  • Charles Tsai said:
    Now I tried to let the code run first. It will stay in the while(1) loop of the UpdateBOOTP function as it is waiting for the magic packet. If I place s/w breakpts on some of the lines inside the while(1) loop then it will break.

    I see you already confirmed what I wrote just before. I missed that originally. Sorry!

  • After discussing with our debugger expert, I got some clarification on the breakpoint behavior

    -the debugger will set any breakpoints on the run address. For SW breakpoints, the debugger will save the original instruction elsewhere and write a breakpoint opcode at that target address. If you set the SW breakpoints before the code is copied to RAM, the breakpoint opcodes will be overwritten during the copy process. This is why the debugger was not halting at those addresses in question (breakpoint opcodes overwritten).

    -the reason why the breakpoints were suddenly "enabled" when you stepped over the address with the breakpoint is because of the way breakpoints are handled by the debugger. The debugger still thinks a breakpoint opcode is at that address and will copy back that original instruction it stored elsewhere to execute it. After the instruction is executed, it places the breakpoint opcode at that location again. Hence the breakpoint opcode is now really there and the next time you run, it will hit the opcode and halt.

    In cases such as this example, if you wish to set a breakpoint in the C file after program load, the option would be to either use HW breakpoints (which does not do any opcode replacement) or set the breakpoints after the code has been copied. However, there seems to be some HW limitation on your device (I think all Cortex M devices), where addresses outside the Flash memory range is not supported. Hence the latter option of setting the breakpoints after the code is copied into RAM seems to be the best bet.

    Thanks
    ki
  • Ki,

    Ki-Soo Lee said:
    Hence the latter option of setting the breakpoints after the code is copied into RAM seems to be the best bet.

    This seems very difficult to do because the code that does the copying itself is executed in SRAM. When CCS starts, the processor (PC) is already at SRAM address 0x20000E1A. The breakpoints are overwritten from SRAM.

    The 6th op code branches to the function that does the copying and therefore overwrites all of our breakpoints.

    The code after this copy loop is at address 0x20000DA2. The loop copies 4 bytes at a time. So I would need to step through this loop 873 times, then set a post-loop-breakpoint after this loop, then resume running, and finally, when the post-loop-breakpoint breaks, I can set other breakpoints.

  • Ki-Soo Lee said:

    Now this part I didn't consistently reproduce. After an explicit program load, I can always halt on breakpoints I set in the asm file. I can also step in/over line 257. However, if I restart the program, I get the issue where the breakpoints in the asm file are ignored.

    this is still under investigation...



    It is still a mystery why you can set into line 257, but I would not expect you to be able to break on line 208. Line 208 is right after the copy loop. I expect this loop is overwriting the breakpoints.

    This does not seem like a large problem because I can set a break point on line 195, but it may be a clue...

  • Ki-Soo Lee said:
    Hence the latter option of setting the breakpoints after the code is copied into RAM seems to be the best bet.



    This works. I stepped through the copy_loop 874+ times, broke after the loop, and after that, all breakpoints worked.