Occasionally I run into this kind of problem: I have downloaded my application, and it immediately crashes or looses the connection:
What is the problem? It is helpful to understand what happens if I press ‘debug’ in CodeWarrior or any other debugger:
What happens on debug
- It flashes my application to the target. For this either the debugger or the target probe (e.g. P&E Multilink) downloads a small applet to the target RAM and performs flash programming. While doing this, the debugger is constantly feeding data to the flash programming applet.
- The debugger initialize the PC (Program Counter) and SP (Stack Pointer).
- If configured, the debugger will set a temporary breakpoint. More on this below.
- The debugger performs a ‘run’.
What exactly happens in step 2 (setting the initial program counter) depends a bit on the microcontroller architecture. And it seems every debugger is a bit different here too. But usually this will set the PC (Program Counter) and the SP (stack pointer). These values are usually stored in the vector table (e.g. S08 and ColdFire). These values are fetched by the CPU at reset time as well. So it is very possible that the debugger is asserting reset to load these values too.
Temporary Breakpoint
The interesting part is step 3: The debugger sets a temporary breakpoint. Usually this breakpoint is set at main(): that way you download your application, and your target will stop at main(): Usually what I want as I do not need to step through the startup code.
That works fine, unless something goes wrong on the way from reset to main(). Typical things which could go wrong are:
- The startup code takes too long, and a watchpoint resets my target before I have a chance to ‘kick the dog’ in main().
- My application entry point or initial stack pointer is out in the weeds, causing a bus access error.
- My run control/debug connection gets lost because of a crashing target.
- Any other weird problem I could imagine :-).
Stop on Startup
So to solve the problem I need to have the debugger to stop earlier than in main(). There is a setting for this in the debug/run/launch configuration of CodeWarrior:
- Stop on startup at: if this is set, the debugger will set a temporary breakpoint. Otherwise the target will be running.
- Program entry point: if selected, then the debugger will at the application entry point.
- User specified: here I can specify a name of a function.
Program Entry Point
One question remains: where is the program entry point?
The HCS08 linker reports it in the linker map file:
********************************************************************************************* STARTUP SECTION --------------------------------------------------------------------------------------------- Entry point: 0xC004 (_EntryPoint) _startupData is allocated at 0xC09C and uses 6 Bytes
The S08 linker has the ENTRY command which is used to assign a specific application entry point. That entry point encoded in the application ELF file format and is shown with an ELF/Dwarf reader such as readelf (or run <MCU10.2>\Cross_Tools\CodeSourcery_Linux\bin\m68k-linux-gnu-readelf.exe):
readelf -l hello.abs Elf file is EXEC (Executable file) Entry point 0xc004 ....
Summary
If something goes weird right after download, or if my application does not reach main(), then it is a good idea to stop on the application entry point instead run to main() with the debugger.
Happy Stopping 🙂