This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

accesses to a structure in code space causes error

I have a large structure I wish to locate in code space. The problem appears to be the linker intreprets the accesses to this structure as a subroutine call. I get the error "Too many recursive calls to segment...".
The structure works fine in XDATA. It also worked fine in code space until there were enough routines accessing the structure.

Anyone have a clue?

Parents
  • This is one area where the compiler is not as smart as I might wish it to be. Everything in a single .c file goes into the same segment, and that segment name is the unit of granularity for tracking references.

    I run into the problem a lot with code that has the structure:

    // Cmd.c
    const code Strings[];
    
    void Cmd1 () { printf (Strings[0]); }
    void Cmd2 () { printf (Strings[1]); }
    
    const code CmdTbl[] =
        {
        Cmd1,
        Cmd2
        }
    

    As far as the compiler can tell, the Cmd functions reference the data segment of Cmd.c, and the data segment references the Cmds. So, the compiler can't be sure there's not a recursive loop waiting to happen. It doesn't actually happen (CmdTbl -> Cmd1 -> Strings, but Strings -X CmdTbl), but the linker can't tell because all it sees is ?PR?CMD -> ?CO?CMD -> ?PR?CMD.

    Unfortunately, Keil lacks controls like #pragmas to set segment names for individual objects. The only way to get a new segment name is to create a new .c file.

    The brute force answer is to disable the recursive reference warning, which of course runs the risk of missing real errors of that type. Otherwise, you have to restructure your code and break up your file into multiple files so that the pieces get different segment names and avoid the circular reference.

    You'll probably want to read the manual sections and app notes about function pointers and overlay processing to gain more understanding about what the compiler is doing in these situations.

Reply
  • This is one area where the compiler is not as smart as I might wish it to be. Everything in a single .c file goes into the same segment, and that segment name is the unit of granularity for tracking references.

    I run into the problem a lot with code that has the structure:

    // Cmd.c
    const code Strings[];
    
    void Cmd1 () { printf (Strings[0]); }
    void Cmd2 () { printf (Strings[1]); }
    
    const code CmdTbl[] =
        {
        Cmd1,
        Cmd2
        }
    

    As far as the compiler can tell, the Cmd functions reference the data segment of Cmd.c, and the data segment references the Cmds. So, the compiler can't be sure there's not a recursive loop waiting to happen. It doesn't actually happen (CmdTbl -> Cmd1 -> Strings, but Strings -X CmdTbl), but the linker can't tell because all it sees is ?PR?CMD -> ?CO?CMD -> ?PR?CMD.

    Unfortunately, Keil lacks controls like #pragmas to set segment names for individual objects. The only way to get a new segment name is to create a new .c file.

    The brute force answer is to disable the recursive reference warning, which of course runs the risk of missing real errors of that type. Otherwise, you have to restructure your code and break up your file into multiple files so that the pieces get different segment names and avoid the circular reference.

    You'll probably want to read the manual sections and app notes about function pointers and overlay processing to gain more understanding about what the compiler is doing in these situations.

Children
  • Thanks for the tip(s). I really want this structure in code space. It is the heart of a complex menuing system and I don't want take any chances that it may get corrupted.

    Again thank you for taking the time to answer.

  • "I really want this structure in code space ... I don't want take any chances that it may get corrupted."

    So the true requirement here is to have it read-only, yes?
    Placing it in code space is merely a means to that end?

    Is your memory architecture such that you can map (some of) a ROM into XDATA space?
    If so, you could look at XCONST as an alternative solution to your requirement.

  • You are correct. Read only is the goal.
    Can't do any re-mapping. I am using a Cygnal 8051 type processor. The flash and RAM are internal and fixed.

    By the way, I have looked high and low for a way to turn off the recursion errors. I have not found it yet.

    Thanks again.