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.

How to set breakpoints in bootloaders

Breakpoints  within TI's flash based bootloader are initially overwritten. This makes debugging bootloader initialization code difficult.

The issue is caused by the function ProcessorInit in bl_startup_css.s. ProcessorInit has a copy loop that puts bootloader code from flash into SRAM. This allows the bootloader to erase and write to flash at will. The hardware FPB unit only places breakpoints in code memory. Breakpoints in SRAM code are implemented by modifying the the opcodes. The copy loop overwrites the SRAM breakpoint. You may notice the debugging session starts the PC at an SRAM address. This does not solve the problem as the copy loop itself is copied and runs. Everything in SRAM is written twice.

As a workaround, you can set a hardware watch point at the address shortly after the copy loop.  The disassembly window shows where the assembly code is placed in memory. In this example, the copy loop is followed by a movs at address 0x2000032C.


Setting a hardware watchpoint at 0x2000032E will break after this particular movs is copied into SRAM for a second time. After this second copy, you may place an SRAM breakpoint at  0x2000032C. Hitting this breakpoint indicates the copy loop is over, and you are free to place SRAM breakpoints elsewhere in the bootloader.

  • Hi Peter,

    Great stuff!

    Some of this may be now out of date with new CCS versions out, but a few years back this detailed post covered a lot of the gotcha's as well, might be a good read for you (if you hadn't already stumbled upon it): https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/295119/1033395#1033395

  • This was interesting. The copy loop doesn't actually need to happen twice at runtime, but the debugger complicates things by wanting to start at _c_init00. I see this happen; the debugger starts the PC at 0x200003A2. However running successfully should not be possible because the copy loop hasn't happened yet and the SRAM should not be initialized. My workaround shouldn't work.

    Mr Miles acknowledges this "So single-stepping from _c_int00() is not going to work". However, I can single step past _c_int00(). I do not understand why this works, and I don't expect it to. I assume CCS lets the chip run for a fraction of a second and the code that does the coping gets to run before the debugger starts the chip back at _c_int00().

    Is Stellaris named after him?
  • Hi Peter,

    Interesting that the _c_int00() issue doesn't happen for you now... I wonder if CCS had some change to prevent it from impacting boot loader operations. Honestly I haven't needed to debug a boot loader at that level yet, so I have no experience to go from on my end. To figure that out it probably would need to be asked to the CCS folks, they might be able to shed light on what is going on with the debugger that now allows the issue to be circumvented without extra user steps. May have been a QOL improvement.

    RE: Miles, Never met him but highly doubt it :). There were a few "Stellaris" names on the forums from years past (I think Paul was another). Maybe back then there wasn't a dedicated forum and they used that to stick out as support for the devices?