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.

Weak function definition in CCS - MSP430

Other Parts Discussed in Thread: MSP430F5528, TEST2

Hello,

I am trying to implement an application "hook" in a generic way in one of my custom libraries using a weak function definition but haven't been able to succeed. The overall functionality I am trying to get is similar to the one described in this Shared Example

Assuming that the library is mylib.c, mylib.h and the application in main.c, I have the following:

One of my library's functions calls ApplicationHook(), which is declared as extern in mylib.c.

If the application needs this hook then ApplicationHook() must be defined inside main.c.

However, If this hook is not needed and thus not defined in main.c, compilation will fail or even worse the program will jump to the null pointer (0), thus I want to use the weak symbol option to define a "weak" empty version of ApplicationHook() in mylib.c that will be used if and only if it is not defined anywhere else. I try to do that using in mylib.c:

void __attribute__((weak)) ApplicationHook( void );
void __attribute__((weak)) ApplicationHook( void ) { }

The compilation error goes away now when main.c does not define the hook, however when it does define it the final program still uses the empty version og mylib.c!
I am not 100% sure if I am using weak symbols correctly (I have enabled GCC extensions in CCS) or if CCS has a bug with weak symbols though.

Any help will be appreciated.

I am using CCS 5.5 with TI compiler 4.2.4.
My target is MSP430F5528 if its important.


Thanks,
Giannis





  • I have looked more into the problem and found something really strange.

    At first I verified that my approach is correct by creating a simple test case in Linux which worked as expected.

    Then I tried a simple CCS project with the following files:

    main.c:

    #include <msp430.h> 
    #include <stdio.h>
    #include "mylib.h"
    
    void user_func ( void );
    
    int main(void) {
        WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
        puts("Calling lib function");
    
    	return 0;
    }
    
    void user_hook(void)
    {
       puts("Main Hook");
       user_func();
    }
    
    void user_func ( void )
    {
    	puts("User FUnction");
    }

    mylib.c:

    #include <stdio.h>
    #include "mylib.h"
    #include "msp430.h"
    
    void __attribute__((weak)) user_hook(void);
    
    #pragma vector=TIMER1_A0_VECTOR
     __interrupt void Timer_ISR(void) {
     	mylibfunc(1);
     }
    
    void user_hook(void)
    {
      puts("Empty Library Hook");
      libfunc2();
    }
    
    int mylibfunc(int x)
    {
    	user_hook();
    	return 1;
    }
    
    void libfunc2 ( void )
    {
    	puts("LibFunc2");
    }
    

    mylib.h:

    #ifndef MYLIB_H_
    #define MYLIB_H_
    
    
    int   mylibfunc(int x);
    void libfunc2 ( void );
    
    #endif /* MYLIB_H_ */

    All this example does is call mylibfunc() from an interrupt handled (also tried calling it from main with the same results) which in turn calls UserHook, which is declared in mylib.c as weak and a default implementation is also provided there. UserHook is also defined in main.c and overrides the definition in mylib.c.

    Now I try the same thing in my application with the "UserHook" function changed to TimerTick. I have set the compiler to keep the ASM files for examination and in the main ASM TimerTick is defined as global:

    	.sect	".text:TimerTick"
    	.align	2
    	.clink
    	.global	TimerTick

    while in the library ASM TimerTick is correctly definmed as weak:

    	.sect	".text:TimerTick"
    	.align	2
    	.clink
    	.weak	TimerTick

    However in the final executable the weak version of the library is linked instead of the one defined in main.c

    Is it possible that some strange linker settings could cause this?

  • OK, I think I found the cause of the problem: Optimisation settings 3 and 4 cause the weak implementation to get linked in although another strong implementation exists. With optimisation level set to 2 everything works as expected.

    So it seems that there is a bug in the TI Compiler or is it normal for the high optimisation levels to mix up things like that?

    UPDATE: Tried newer compiler v4.2.6 and the problem remains. On the other hand gcc in Linux works correctly regardless of the optimisation level.

  • Giannis,

    thanks for the feedback, I am moving this to the compiler forum to get in touch with the compiler team.

  • Thank you Leo.

    Though I am thinking about declaring the userhook extern after all so that I can also make it inline.

    Weak linking results to linking, i.e. the function can not be inlined, which is bad for some critical functions.

  • Yes, this is a compiler bug.  I've submitted SDSCM00050713 to track it.  The workaround is as you have noted - use optimization level 2 or lower.

  • Hi,

    so this is a known bug? Is there a fix scheduled?

    Also, on this matter, when using a weak symbol can it be inlined?

  • It's known now, only because of this thread.  It is in the queue to be fixed, but there is no schedule for it.  The function should not be inlined, but apparently it is in this case.  As to whether it is legal to have a function definition that is marked both weak and inline, I don't have the answer.

  • Hi,

    I see at the bug tracking database that bug SDSCM00050713 is planned to be fixed in V4.2.7, however in the notes it is mentioned that it is still present in MSP430 Compiler 4.3.0B1 - 4.3.4.

    Can you please clarify if this bug is fixed in the latest MSP430 Compiler version (4.3.4 in CCS V6.0.1) and if not whether there is a plan for it.

    Giannis

  • I think you misunderstand how our compiler releases work.  The MSP430 compiler has two release streams currently available: 4.2.x and 4.3.x.  This bug is present on both streams, in this range of releases: 4.2.0B1 - 4.2.6 and 4.3.0B1 - 4.3.4.  The next release planned for each stream will fix the bug.

    For more general background on TI compiler release numbering, please see this wiki article.

    Thanks and regards,

    -George

  • Is this bug related to the behaviour like this: The ISR routines in libraries are always linked, even main code does not call, use anything from that module?

  • No.  The error is that a call to a weak function may be inlined.  This prevents the linker from later overriding this call to a weak function definition with a call to a normal (or strong) function.  

    Thanks and regards,

    -George

  • Hi Deniz,

    if its still relevant, I don't think that what you describe is a problem, it is normal behavior. The interrupt functions are always linked in, since even when they are used they are not called by the code itself. The compiler cannot know if the interrupt will ever be active so it always links ISRs. If you dont want this to happen you have to either exclude the library .c file from build or comment out the ISR definition.


    On the other hand, while the bug discussed here seemed to go away in V4.35, I am now experiencing it again, using V4.35 and V4.4.2.

    Can you please confirm that this issue is resolved and provide a working example?

  • I have been testing compiler V4.4.4 and the bug remains.
    i managed to overcome it by placing the weak function definitions in a separate .c file. Before they were defined in the .c file where they were called from, and they were not linked externally as they should.
  • I rewrote the ISR routins in assembly.. They are not included unless something in that module is referred.. I added dummy function to be called from C++ routine. Now, only if the call hierarchy includes that dummy routine, the ISR routine is included..
  • Just writing to report that in compiler version V4.4.5 the bug remains!
    If the weak version of the function is defined in the same file where it is called, then it is inlined internally and not emitted as an external symbol so that it can be overridden later by the linker.
    This also happens if the function is defined as weak and extern, though weak implies extern anyway.
    To avoid having the function inlined I have to completely disable optimisations.

    The workaround I am using for now is to define the weak version in a separate .c file, though the bug remains dangerous because in many cases I compile code written previously and the strong version of a function is silently ignored.

    Is there any update on this from TI? Is it being addressed?

    I dont have compiler V4.3.5 available now to check, but this seems like a regression, since in V4.3.5 the bug occurred only at optimisation levels 3 and 4, now it seems that only completely disabling optimisations avoids the problem.

  • We think you are experiencing a different bug.  The bug is already known, and has the ID SDSCM00050834 .  This bug is not fixed, but is in the process of being fixed.  You can look it up with the SDOWP link below in my signature.

    To be sure you are not experiencing a new and unknown bug, we would appreciate if you would send in a test case.  Since this test case has to link, this is a bit more difficult than most test cases.  It would be ideal if your code were organized as a CCS project you could share with us.

    Thanks and regards,

    -George

  • Hi George,

    the description of the bug you mentioned seems relative to my problems, however the target product is the TMS470 compiler. Does it also apply to MSP430?

    I have already created a minimal CCS project to test the behaviour, I will send it to you later today.

  • Yes, SDSCM00050834 affects all EABI targets, including MSP430 EABI.
  • Is there a planned resolution of this bug?
  • SDSCM00050834 will be fixed.  We think that is the bug affecting you.  Of course, we cannot be certain.  That is why we would appreciate getting a test case from you.

    Thanks and regards,

    -George

  • Hi all,

    I am attaching a simple sample project to show the bug I am facing. With optimisations off, the callback() definition in main.c is used and test2 variable is modified. With optimisations enabled the weak callback() definition is lib.c is used and test2 is never modified

    2045.testProject.zip

  • Hi Giannis,

    Can I confirm a detail with you from your example: are you only seeing the failure with -o4? I tried the test here, and the behavior I observed is that the test ran correctly for -o0, -o1, -o2, and -o3. If that is the case, you are seeing SDSCM00052238: using the weak symbol due to link time optimization. (That will soon be fixed along with SDSCM00050834.)