Changing the Startup: Custom initial PC and SP Register Setting with the Debugger

By default, the debugger cares about the initial register settings after connecting to the target. But for special cases like using a bootloader combined with a loaded application, this requires a bit more than the usually ‘standard procedure’. For example I need to set both a custom program counter (PC) and stack pointer (SP).

How to set custom PC and SP for startup of the application

The principle is pretty much the same for every IDE or debug probe used. But the exact details (as always) can be different for the debug probe used. I’ll show it here with using the NXP MCUXpresso IDE 11.7.x and using the P&E (PEMICRO) debug probe.

P&E Multilink Universal FX with NXP FRDM-K22F Board

Standard Procedure

Here is what usually happens if you press ‘debug’ in your IDE (simplified):

  1. Debugger process gets started, with the ELF/Dwarf binary as input to be programmed to the device
  2. The debugger programs the memory of the device, based on the information in the binary, which usually includes the vector table
  3. Debugger sets a breakpoint on the ‘main’ symbol
  4. Debugger performs a reset of the target to run it
  5. The target starts executing according to the hardware reset sequence, e.g. fetching initial PC and SP from the vector table
  6. Target runs until it hits the breakpoint on main from step 3 from above

Now in the context of a bootloader, you might want to start execution not from the original vector table, but from a different location. This requires to set a custom program counter (PC) and stack pointer (SP) with the debugger in step 5 from above.

đź’ˇ Note that setting this custom SP and PC is done with the debugger. So running the target without the debugger will show a different flow of execution.

Setting Program Counter

Setting a custom PC is simple in Eclipse: there is a setting for this in the launch configuration Startup tab:

set custom PC

I have disabled the ‘run on reset’ part (see step 4 from above) so I can verify it is indeed doing what I want. The debugger shows me this:

Starting from PL_Init()

As you can see, the PC value is correctly set and code execution starts from the desired function.

You might notice that the debugger tries to show the source for the address 0x190. As seen from the gdb traces, this is because the debugger tries to list the initial thread list. So what happened is that the debugger first fetched the values from the vector table, and then changed the PC. This can be verified with looking at the vector table which contains 0x190 (plus the thumb bit) as initial PC:

Initial PC from Vector Table

Setting Stack Pointer

Now what about the initial stack pointer. As you might have noticed in above picture: the SP is still set from the value in the vector table:

To have custom SP, some trickery is needed: we need to set the SP (Register 13) using a small script file. So create a text file (e.g. init.mac) with following content:

R13 $20000000

This sets the register 13 (MSP, SP) with the value 0x2000’0000.

Then use that script file in the launch configuration. There is a setting under ‘Advanced Options’ in the PEMICRO debugger settings where I can specify a script:

calling initialization script

With this, I have both my custom PC and SP configured through the debugger:

Setting both PC and SP with the Debugger

Summary

Sometimes it is necessary to have a custom download or startup sequence executed by the debugger. In this example I showed how the initial PC and SP register content can be configured by the debugger, for example to execute a custom starting point with a custom stack location. The approach shown here is very useful in the process of bootloader development, or in the context of reverse engineering ;-).

Happy debugging 🙂

Links

Advertisement

2 thoughts on “Changing the Startup: Custom initial PC and SP Register Setting with the Debugger

  1. Don’t you need to change the vector table address at startup? It is usually something that is done by the bootloader, but if you want to skip the bootloader at all, I think you should change the vector table in your custom startup process.

    Like

    • It depends. The vector table only really gets used once you enable interrupts. And you certainly can relocate the vector table in the code with the relocated PC/SP location.

      Like

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.