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

Memory corruption when jumping into function

I am experiencing an high undesirable behavior on C8051F500DK kit. My scenario is:
Toolchain: PK51 Prof. Developers Kit for SiLabs Version: 9.52.0.0
Toolchain Path: C:\Keil\C51\BIN
C Compiler: C51.Exe V9.52.0.0
Assembler: A51.Exe V8.02b
Linker/Locator: BL51.Exe V6.22
Librarian: LIB51.Exe V4.29
Hex Converter: OH51.Exe V2.7.0.0
CPU DLL: S8051.DLL V3.91.0.0
Dialog DLL: DCYG.DLL V2.72.0.0
Target DLL: SiC8051F.dll V3.8.0.0
Dialog DLL: TCYG.DLL V2.70

I am using LARGE memory model, with variables in XDATA.
C51 optimization in level 3 (Peephole Optimizing) with emphasis on size.

I have this test case, ALWAYS reproducible:

typedef enum
{
   TPDU_MSG_COMPLETE,
   TPDU_NO_INIT,
   TPDU_MSG_NOT_READY,
   ....
}

static TpduRetCode_t MyFunc(void)
{
   TpduRetCode_t ret = TPDU_MSG_NOT_READY;                      // *A*
   if(...)
   {
        ...
        TPDU_FC_t fc;
        uint8_t txBuff[TPDU_PACKET_BYTELEN];
        ...
        if(TxHndlr != NULL)
        {
                if(TxHndlr(txBuff) == TRUE)                     // *B*
                {
                        ...
                }
        }
   }
}

At point *A* ret is equal to 2, but when executing function at point *B*, ret becomes equal to 0.
TxHndlr() is not affecting ret.
For example, ret is located in last run at X:0x06. When entering in TxHndlr() this location is overwritten by function and is NOT restored when exiting the function.

If I remove all optimization (level 0, constant Folding) the problem seems to disappear. Useless to say, if I do not optimize my code is too large for my memory mapping.

What is happening? How can I solve?

Thanks

  • The C51 compiler doesn't like function pointers too much.

    It converts auto variables into global variables and performs call tree analysis to see which code branches never overlaps, to allow it to reuse the same memory cells. This is obviously not going so well when you use function pointers.

    Preferably, you should do almost all you can to avoid function pointers together with C51.

    Anyway - is that function declared to be reentrant?

  • Ah, it could explain I had the same problem with an higher optimization level on the SAME function but called from another function.

    No function is declared as reentrant in my code.

    So the TxHndlr() is not reentrant...it should?

    Here is its body

    static bool_t TpduTxHandler(uint8_t* txData)
    {
            CanPacket_t outPacket;
    
            outPacket.Id = DIAGNOSE_ANSWER_CANID;
            memcpy(outPacket.Data.Data8,txData,TPDU_PACKET_BYTELEN);
            if(CanQueueWrPack(&outPacket,1,NULL,FALSE) != CAN_OK)
            {
                    return FALSE;
            }
    
            return TRUE;
    }
    

  • if you have chosen the '51 and want to use function pointers, reentrant code or malluc, you have chosen the wrong processor. BTW neither is required to make functional code.

    One man's opinion

    Erik