Changing initial execution point in codewarrior (for HC12)

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Changing initial execution point in codewarrior (for HC12)

5,770 Views
pgo
Senior Contributor V
I'm considering using codewarrior for undergraduate teaching but one thing that puts me off is the rather complicated C startup code. This is very offputting to a newbie and in this case I would have a class of about 170 of them! This is different to several other products I've used e.g. IAR embedded workbench usually 'resets' to the start of main().

This seems to have been acknowledged somewhat by the fact that when initially starting the debugger it displays main() rather than startup(). Of course when you start single-stepping it then immediately drops into the startup code. This also occurs if you reset the program.

So (finally) my question:
Is is possible to arrange things so that the C startup code is not so 'visible'. My attempts so far haven't been successful. I've tried a few approaches involving modifying the cmd files.

My attempts so far (and why they don't work):

Change Postload.cmd so it sets a temporary breakpoint at main() and then runs the code. This actually works leaving the program at the start of main after succesfully running the startup code BUT it only has this effect at loading not when reset.

Change Reset.cmd in the above manner. This has the major problem that you often don't have a breakpoint register available i.e. you are already using two breakpoints, so it fails.

Any ideas would be appreciated.

What I would really like would be an option in the tools to do the above properly - it wouldn't be very difficult. Dear Metrowerks developers - any chance of this?
Labels (1)
Tags (1)
0 Kudos
8 Replies

565 Views
Lundin
Senior Contributor IV
In postload.cmd you could write:

FindProc main
reset


My advice would however be to skip the start12.c entirely and do all initialization of static/global variables in "runtime". This is how my own reset isr looks:

#pragma TRAP_PROC
void interrupt_reset(void)
{
#pragma MESSAGE DISABLE C12053
asm LDS #$2500;

INITRM = 0x21;
INITEE = 0x09;

asm CALL main /* jump to main, not to startup */
}

Note that this will eat a couple of bytes from the stack. If that is a problem, then you can set up the stack pointer on more time in the start of main().

But I find it odd that you haven't got an option upon creating a project: "compact startup or ANSI C". There is such an option for CW HC08 projects.
0 Kudos

565 Views
pgo
Senior Contributor V
Dear Lundin,

Thanks for your reply.

The sequence:
FindProc main
reset

does result in the source code of main() being displayed but it does not actually change the execution point. As soon as you try single-stepping you are dropped back into startup(). This is what I want to avoid since I want the students to be able to (reasonably painlessly!) step through the 'important' code that they are examining or coding rather than the startup code which is confusing for novices. In any case, this can be improved by using a temporary breakpoint. (Also see the posting above for more on the 'rational' for my request.)

The real problem is that a similar sequence can't be applied to reset (reset.cmd) without tying up a breakpoint - of which there are only two. This is a bit too expensive to my mind.

Your second suggestion is more appealing but I don't like having to materially change the startup just to make it pretty.

I really think the best solution would be an option in the debugger as described in the original posting.

Thanks
0 Kudos

565 Views
Lundin
Senior Contributor IV
"Your second suggestion is more appealing but I don't like having to materially change the startup just to make it pretty."


My point is, start12.c doesn't do anything good. You can keep it in your project to make the linker happy, but you don't need to run the code inside it. _Startup is an evil thing they had to add to conform to ANSI C's initialization of static variables. It does 3 things:

- Clear the RAM (to zero). This is totally pointless imo, unless for debugging purposes - to check if the program is writing in places where it shouldn't write. But in that case, you can use the debugger to set RAM to zero - problem solved.

- Set the stack pointer. Wow, it saves one line of inline asm... totally pointless to have in a separate file as well, it is just there so that the MW support doesn't have to answer questions from dummies that have forgotten to set the SP. Some would say that it is there because it retrieves the stack address from the .prm file, but that doesn't make sense either since one should keep the stack in a separate, fixed memory segment and not at some random location.

- Initializes static/global variables. Ie the magic behind

static int something = 0;

But you can live without this and set the variables in runtime:

static int something;
something = 0;

And you probably don't want static initialization at all. Lets say that you have a system with years of years without powerloss. If it takes years of uptime before it runs the code using the static variable, then you can't trust the RAM value anymore. Therefore it is good programming practice to init the variables just before using them.
0 Kudos

565 Views
CrasyCat
Specialist III

Hello

Not sure I understand the issue here.

Are you looking for a way to make sure that the PC points directly in main function after you started the debugger?

Then add following command to your postload.cmd file:

bs main T
go

This way after loading code the startup code will be automatically executed (initializing stack pointer, variables, ...) and the application will stop at main.

I hope that helps.

CrasyCat

0 Kudos

565 Views
pgo
Senior Contributor V
Dear CrasyCat,

Not quite!

I would like the debugger to run the startup code and then stop at main whenever it is reset - not just on the initial load. This would effectivly hide the startup code.

I have considered the method you suggested (see the end of original post) but it only works on startup - not reset.

Trying it on reset as well is quite hard to get correct (there are some timing issues - the debugger resets the uC several times and even does it when starting before loading the code so setting the breakpoint fails!) These can be programmed around but reset.cmd ends up a bit messy. However, the real problem is that there are only two hardware breakpoints available so setting a temporary breakpoint often fails. I cannot find a work around for this as there appears to be no facility to save the existing breakpoints. If this existed I could do the following (in reset.cmd):

  1. save breakpoints (using magical command that doesn't exist)
  2. set temporary breakpoint at main() (as you suggest)
  3. run which wil execute to main() and remove the breakpoint
  4. restore saved breakpoints (using magical command that doesn't exist)

I hope this clarifies my request.

thanks
0 Kudos

565 Views
CrasyCat
Specialist III
Hello

The commands specified can be used in the reset.cmd as well.

When you are doing a reset on the hardware you may have a timing issue.

You ma want to add a small delay at the beginning of the reset.cmd file.
Command for that is wait.

Adding
wait 10
will add a 1 second delay

The main issue you are facing here is the limitation of 2 hardware breakpoints in a HCS12 CPU.

There is no easy way out of that.

You may want to submit a feature request through our web interface for the missing save breakpoints command.

In fact today we are saving breakpoints when you close the debugger (as soon as "Save and Restore on load" is checked in the Breakpoint configuration dialog).
The breakpoint are saved in a command file, which can be called after ward.
What is missing here is a way to deliberately save the breakpoints set at a specific moment.

CrasyCat
0 Kudos

565 Views
Alban
Senior Contributor II

Dear Pgo,

Good you fancy teaching some Codewarrior :smileywink:

If you want, you can remove the Start file from the project, remove its inclusions and also change the reset vector to point to main() instead of startup.

However, this file does the initialisation of variables and other things of the MCU (Stack initialization...).

Therefore it means that if you don't use the startup sequence you have to do everything manually in the main()...

In a course, you could still include the start file and not go into details about it explaining it initializes the variable to zéro for ANSI compatibility and also stack pointer. Which level you want to explain ? (debugging, C coding, linking, compiling.. ?)

Alban.

0 Kudos

565 Views
pgo
Senior Contributor V
Dear Alban,

Thanks for the suggestions. I have been considering doing a simplified startup() that limits itself to the initialisation that is actually necessary. This would be along the lines of your suggestion.

However I don't think I've made myself very clear.

I don't object to the startup code as such. I agree it's pretty necessary and I do (usually) want the global initialization etc. (I even consider doing C++ occasionally which needs it even more). However, there is no reason for the startup code to be so 'visible'. Its quite possible for the debugger to quietly run startup and then halt execution at main() rather than at the start of startup(). It is relatively rare that you spend much time debugging this part of the code and certainly not at an introductory level.

The rational for the request is that I'm more interested (at least initially) in introducing the students to 'bit-banging' rather than getting bogged down in the details of the C environment. Having the students dropped into startup() is a bit daunting - it's 440 lines of code which includes conditional compilation macros, inline assembler etc. This results in a fair bit of pain for the students :smileyhappy: even if I explain that they should just step through it until they arrive at main().

In any case, even for the non-novice, I would think it more convenient to start the debugger at main(). This would only be an option so that, when necessary, you could delve into startup().

Thanks for the input Alban.

bye
0 Kudos