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.

Compiler/TMS570LS3137: --entry_hook compiler option causes failure in sys_startup

Part Number: TMS570LS3137
Other Parts Discussed in Thread: HALCOGEN, LAUNCHXL2-RM46,

Tool/software: TI C/C++ Compiler

I'm attempting to use the --entry_hook compiler feature described in SPNU151 to monitor stack usage in my program. My program also uses the self-test code generated by HALCoGen. I've found that when I build  using the --entry_hook feature, my program reboots somewhere inside the call to memoryInit(0x1U). This occurs even if my entry hook function does absolutely nothing.

I suspect the compiler is dutifully inserting calls to my entry hook function in all of the HALCoGen-generated C functions, including memoryInit() and that calling this function is somehow causing the processor to reset. I don't really need to invoke the entry hook function inside the HALCoGen code and would be happy to just disable it, but the compiler doesn't seem to offer that degree of control. The --entry_hook feature is either on or off. Is there any other way to tell the compiler to not insert the entry hook calls into the HALCoGen functions?

HALCoGen 04.07.00

TI ARM C/C++ Compiler v18.1.3.LTS 

  • Hello Hugh,

    The compiler supports entry hook and exit hook functions, which can be handy during profiling. The entry hook is a routine that is called upon entry to each function in the program; and an exit hook is a routine that is called upon exit of each function.

    Applications for hooks include debugging, trace, profiling, and stack overflow checking.

    Is the --exit_hook enabled in your application?
  • QJ,

    Yes, I've tried enabling the --exit_hook option but as described in my original post this causes my program to fail.

    Hugh

  • With regard to ...

    Hugh Shane said:
    I don't really need to invoke the entry hook function inside the HALCoGen code and would be happy to just disable it

    If the HALCoGen created source files are part of a CCS project, then consider using the File Specific Options feature to remove the --entry_hook and --exit_hook options from those files.

    Thanks and regards,

    -George

  • Hello Hugh,

    You an not remove --entry_hook  from HALCoGen functions, but use --entry_hook in other functions. The default __entry_hook() function is a weak function, you can define your own to overwrite it, or you can define a hook function with a different name: --entry_hook[=name].

    I'd like to understand why it causes reboot in halCoGen C functions. Can you do a test with an empty hook function?

  • QJ Wang said:
    I'd like to understand why it causes reboot in halCoGen C functions. Can you do a test with an empty hook function?

    While I don't have a TMS570LS3137 to test which Hugh is using, the attached project is for a LAUNCHXL2-RM46 using HALCoGen 04.07.00 and TI ARM compiler v18.1.3.

    It contains an empty hook function named empty_entry_hook() in sys_main.c, where --entry_hook=empty_entry_hook is set in the compiler options. When stepping through the HALCoGen generated startup code a reset occurs when the calls to memoryInit(0x1U) called to initialise the CPU RAM attempts to return. The disassembly for memoryInit() is:

     185      {
              memoryInit():
    00000178:   E92D4008            push       {r3, lr}
    0000017c:   E58D0000            str        r0, [sp]
    00000180:   EB0019B4            bl         empty_entry_hook
     190          systemREG1->MINITGCR = 0xAU;
    00000184:   E3E000A3            mvn        r0, #0xa3
    00000188:   E3A0C00A            mov        r12, #0xa
    0000018c:   E580C000            str        r12, [r0]
     193          systemREG1->MSINENA  = ram;
    00000190:   E3E0009F            mvn        r0, #0x9f
    00000194:   E59DC000            ldr        r12, [sp]
    00000198:   E580C000            str        r12, [r0]
     197          while((systemREG1->MSTCGSTAT & 0x00000100U) != 0x00000100U)
              $C$L12:
    0000019c:   E3E0C097            mvn        r12, #0x97
    000001a0:   E59CC000            ldr        r12, [r12]
    000001a4:   E31C0C01            tst        r12, #0x100
    000001a8:   0AFFFFFB            beq        $C$L12
     202          systemREG1->MINITGCR = 0x5U;
    000001ac:   E3E000A3            mvn        r0, #0xa3
    000001b0:   E3A0C005            mov        r12, #5
    000001b4:   E580C000            str        r12, [r0]
     206      }
    000001b8:   E8BD8008            pop        {r3, pc}

    Where a reset occurs when attempt to step the final pop {r3, pc} instruction.

    What has happened is that the use of the entry hook has caused a call to empty_entry_hook() from the start of memoryInit, such that the generated assembly has to push the link register onto the stack at the start of the function, and then pop the link register from the stack to return to the caller. However, since memoryInit has zeroed all the CPU RAM when attempts to pop the return address from the stack the return address is zero which is the reset vector.

    RM46_light_sensor.zip

  • Chester Gillon said:
    What has happened is that the use of the entry hook has caused a call to empty_entry_hook() from the start of memoryInit, such that the generated assembly has to push the link register onto the stack at the start of the function, and then pop the link register from the stack to return to the caller. However, since memoryInit has zeroed all the CPU RAM when attempts to pop the return address from the stack the return address is zero which is the reset vector.

    When pbistRun() is called to run PBIST on CPU RAM a similar problem can occur, in that the RAM test can corrupt the link register which has been saved on the stack. In this case if you step over the call to pbistRun() the call to the function does return, whereas if you step though the pbistRun() the return generates a prefetch abort. It looks like a race condition about if PBIST test when sets the CPU RAM contents to the byte value 0xC3 completes before the program tries to pop the return address off the stack.

    The pbistIsTestCompleted() function which is called to check if a PBIST test has completed can also suffer from a prefetch abort in the same way as pbistRun().

    Since the TI compiler has a NO_HOOKS Pragma which allows the entry/exit hooks to be disabled on a per-function added the following to the USER CODE block at the start of the HALCoGen sys_selftest.c file:

    /* USER CODE BEGIN (0) */
    
    /* Disable the generation of hooks for the following functions, which must be leaf functions (i.e. call no other functions) to
     * avoid the link register being pushed on the stack and poped of the stack to obtain the return address.
     *
     * This is because these if these functions store the return address on the stack, the return address mat be overwritten
     * while the CPU RAM is being modified by the self tests.
     */
    #pragma NO_HOOKS (memoryInit)
    #pragma NO_HOOKS (pbistRun)
    #pragma NO_HOOKS (pbistIsTestCompleted)
    
    /* USER CODE END */
    
    #include "sys_selftest.h"

    With the above changes, the example with an empty hook function now successfully runs, either when debugging from CCS or from a hardware reset.

    The updated example is attached. 4744.RM46_light_sensor.zip

  • Chester,

    Thank you for your lucid and detailed explanation. I had a feeling the problem was something along these lines but didn't quite have the knowledge to get to the bottom of it. The #pragma NO_HOOKS solution did indeed fix things.

    Regards,

    Hugh