#1997 printf_small + cc2530.h cause 'Multiple definition of _TR0'

Maarten Brock
George Oikonomou

To reproduce, use the attached foo.c:
sdcc foo.c
Multiple definition of _TR0

Observed with rev #7519 but this must have been the case for a while (at least since the introduction of cc2530.h).

This is a problem caused by the inclusion of 8051.h in printfl.c

#ifndef __SDCC_ds390
/* just for the SP */
#include <8051.h>

Including the entire 8051.h just for SP is a bit overkill, in my humble opinion. Furthermore, the only place where SP is used is in function pval, which is excluded by default.

What brings the problem to the surface in this particular case is that cc2530.h does this:
SFRX(TR0, 0x624B); // Test register 0

This is a) correct and b) totally different than TCON.TR0. I suspect different platform header files may cause similar namespace conflicts.

Perhaps only declare SP and wrap it inside the same #if guard as pval? Like so:

svn diff device/lib/printfl.c

Index: device/lib/printfl.c

--- device/lib/printfl.c (revision 7519)
+++ device/lib/printfl.c (working copy)
@@ -46,9 +46,11 @@
#include <stdio.h>
#include <stdlib.h>
#ifndef __SDCC_ds390
-/* just for the SP */
-#include <8051.h>
+#include <compiler.h>
+SFR(SP, 0x81); /* Stack pointer */

static __data char radix ;
static __bit long_flag = 0;


  • To reproduce

  • Maarten Brock
    Maarten Brock

    Fixed in SDCC 3.1.5 #7870 by moving the include inside the guard.

    But what a mess. How can they reuse a special function register name of the original 8051, just because they happen to not implement that part.

    There are more library modules that include <8051.h> and when linked they will recreate this problem. The real solution would be that TI renames the TR0 and the cc2530.h is modified accordingly.

  • Maarten Brock
    Maarten Brock

    • milestone: --> fixed
    • assigned_to: nobody --> maartenbrock
    • status: open --> closed-fixed
  • Maarten Brock
    Maarten Brock

    I've contacted TI and got the following response:

    > Hi,
    > In the CC2530 User Guide there is a register defined as TR0 (Test Register 0).
    > However this register name is already defined in the intel 8051 as the
    > bit-addressable TCON.TR0 and as such almost every compiler will have it defined as
    > TR0. As the libraries that come with a compiler are not recompiled for every 8051
    > derivative, but use a default 8051.h, this register name is in the global namespace
    > when a module is linked in that uses this 8051.h include file. When the user
    > subsequently includes cc2530.h TR0 is redefined because you reused the name and the
    > user gets a redefinition error. I suggest you rename TR0 in the user guide to a more
    > unique name that is not present in the original 8051 or 8052. Something like
    > TESTREG0 would do, I think. After that we can update our cc2530.h to reflect your
    > choice.
    > Kind regards,
    > Maarten Brock
    > SDCC Developer

    > Dear Maarten Brock,
    > I got the reply from the LPRF team managing the CC2530 device as follows:
    > I agree that it is a good idea. We will have to look into the consequences of such a
    > change (what documents, code examples, software etc. that are affected).
    > The easiest and quickest solution is maybe that SDCC renames the CC2530 "TR0"
    > register to "TESTREG0", with a comment in their cc2530.h that the register is called
    > "TR0" in the CC2530 user's guide
    > Would this then be good for you if you just rename the register name and put some
    > comment in the header file?
    > Best regards,
    > Leo Hendrawan
    > Texas Instruments

    I have therefor renamed TR0 to TESTREG0 in our cc2530.h