1
votes

I am using IAR embedded workbench for MSP430 v5.60.7, which is IAR embedded workbench version 6.6. I am using C99.

I am trying to override __program_start() with my own symbol, a function called __unit_test_main(). I have gone to the linker config tab and checked the box "override default program entry", selected the "entry symbol" option and typed in __unit_test_main. This compiles and links however it does not run in the simulator. I get the message "User error: Illegal opcode found on address 0x0". When I try to run this on the target it just doesn't work - the controller goes into low power mode.

The PC and SP are both initialized to 0x00 at startup.

So what else do I need to do/define to get the PC and SP initialized properly?

My unit test main function is trivial right now, here's the whole file its in:

    #include <cstdio>
    void __unit_test_main(void);
    void __unit_test_main(void)
    {
        printf("Hello World");
        for(;;)
        {
        }
    }
1
I am not sure if you can call library functions in that function. If I have understood correctly, you are taking over the program when initialization work is not yet done; .bss section is not zeroed and .data section is not initialized. This likely means that any global variables required by library funcions (I imagine printf has some) have garbage values. Note: This is just a guess, I haven't worked with MSP, or entry overriding. - user694733
I can't even run to __unit_test_main though - not sure why that would have anything to do with the CLIB. - Nick

1 Answers

0
votes

__program_start: is defined in cstartup.s43. This file can be copied into your project directory and included in your project which overrides the library version.

Immediately after __program_start: label the stack pointer is initialized, __low_level_init() is called, and then ?cstart_call_main is called.

Around the ?cstart_call_main: label (line 339) is the following:

    XRSEGCSTART
    PUBLIC  ?cstart_call_main

    EXTERN  main
    EXTERN  exit

?cstart_call_main:
    XXCALL  main
    XXCALL  exit

There you can add the symbol of the function you want to replace main with.

You can do it conditionally with some #ifdef preprocessor logic.

So I have

    XRSEGCSTART
    PUBLIC  ?cstart_call_main
#ifdef UNIT_TEST
    EXTERN  test_runner_main
#else
    EXTERN  main
#endif
    EXTERN  exit

?cstart_call_main:
#ifdef  UNIT_TEST
    XXCALL  test_runner_main
#else
    XXCALL  main
#endif
    XXCALL  exit

    PUBLIC  ?cstart_end

I had to define my UNIT_TEST symbol in the assembler and the compiler options.

Another option would have been implementing the function __low_level_init() somewhere in my project and conditionally making a call to test_runner instead of calling main()