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.

Declared variables are not created

Other Parts Discussed in Thread: TMS320F2812

Hello,

I am working with the digital signal controller TMS320F2812. Three of the variables that I declare are not created, or so it seems. For one, they do not appear in the variables list during the debug mode (please see the attached screenshot). Second, they do not appear in the disassembly window. Third, when one tries to write to them, the program execution stops and does not continue.

How does this come?

Update: The scalar ssLHC appears in the disassembly window and the variables list when a value is assigned to it later in the program. The problem persists with the two arrays: The program does not even run up to the point where an element of the array is accessed; it does not run at all.

Regards,

Adrian

 

Code Composer Studio Version: 5.3.0.00090

  • In some cases, the compiler removes arrays that are not used in the program.  I can't tell if that is the case here.  Does your program ever read or write these arrays?

    Thanks and regards,

    -George

  • When one tries to write to them, the program execution stops and does not continue. The program does not even run up to the point where an element of the array is accessed; it does not run at all.

  • Are you saying that when you add any access (read or write) of that variable and recompile, upon running the program doesn't even reach main?

  • It does reach main and halts there as usual. A few lines of main also work. Then (new discovery) the issue arises that I pointed out in
    http://e2e.ti.com/support/microcontrollers/tms320c2000_32-bit_real-time_mcus/f/171/t/235491.aspx
    There I described that the program execution stops at the line
      for (i=0;i<2500;i++) asm(" RPT #255 || NOP");.
    Now I found that the program stops working when the source code includes a writing to one of the mentioned arrays (e.g. v_oLHC[0]=_IQ(0.8);). The program sometimes stops at the mentioned for loop, but sometimes even earlier. The last few times I tried it only got to InitPll(0xA); and no further. Also, XCLKOUT, having the correct value of 37.5 MHz initially, changes to 3.75 MHz when the program execution stops. This occurs before the mentioned arrays are declared or accessed.

    If the source code that includes the writing to v_oLHC is debugged again, XCLKOUT remains at 3.75 MHz. If the line writing to v_oLHC is commented, XCLKOUT changes back to 37.5 MHz with the next debug after the the command InitPll(0xA);.

    In brief: If v_oLHC is never written to in the program, it works fine. If the line v_oLHC[0]=_IQ(0.8); is added after the array is declared, then, at a seemingly random point before the variable declaration, the program execution stops, and XCLKOUT changes to a tenth of its original frequency.

  • I presume the array v_oLHC is a global variable.  Please check the map file for where it is located.  The map file is in the Debug directory (or whatever the current configuration is named).  The file is named project_name.map.  Search the file for the name of the variable.  You'll eventually find its address.  Does this address make sense for such an array?  Or is it located in flash memory? 

    If v_oLHC is a function local variable ... Make sure you are not overflowing the stack.

    Thanks and regards,

    -George

  • Does that device have a watchdog timer?  Is it enabled?  If so, your loop may be exceeding the watchdog interval.

    The device probably has some sort of sleep timer, which you should probably use instead of NOP in a loop, which is CPU-intensive.

  • The watchdog is disabled right at the beginning of the main function.

    The variables in question are all declared within main.

    I tried setting the stack size as you suggested. So far it had always been set to 0x400 according to the warning that appeared. However, entering anything larger than "0x400" under Project | Properties | Build | C200 Linker | Basic Options | Set C System Stack Size resulted in

    error #10099-D: program will not fit into available memory

    Is that feasible? Is that the right place to specify the stack size?

  • 3446793 said:
    The variables in question are all declared within main.

    So all of these arrays and variables are local to the function main.  That's unusual.  Only code within main can read and write them.

    How do you know the stack has overflowed?  When main is executing, is the SP in the range of memory reserved for the stack, or beyond it?

    Thanks and regards,

    -George

  • As I understand the stack, it stores all local variables. When I wrote the original post, the variables declared in the main function required 25,008 bits = 1563 words. The standard stack size setting is 0x400 = 1024 words. Therefore the variables alone exceeded the stack size, as I know now.

    With some variable declarations commented that I do not need yet, they need 7632 bits = 477 words in total. The problem that the program stops when I try to access some variables does apparently not come up any more. The error message with insufficient available memory is however still there.

  • 3446793 said:
    The error message with insufficient available memory is however still there.

    Addressing this problem requires changes in the linker command file.  Please see this wiki article for more detail.

    Thanks and regards,

    -George

  • 477 words worth of local variables still seems like a lot for that device.  Can you make some of them const, static, or both?  This would reduce main's call frame size, which would allow you to decrease the size of .stack so that the linker could successfully allocate.

  • George Mock said:

    Addressing this problem requires changes in the linker command file.

    I understand that this might be the most appropriate solution. But given my understanding, things are likely to get worse when I start tampering there.

    Archaeologist said:

    Can you make some of them const, static, or both?  This would reduce main's call frame size, which would allow you to decrease the size of .stack so that the linker could successfully allocate.

    This sounds more like something I can do. Some of them can be constants. And the variables in question are all within main - so making them static should have no effect on the program behaviour, is that right?

    Where in the memory are constants and static variable stored? Is there enough space for 1563 words?

    Could they also be defined as global variables with the same effect?

    I am attaching below the two linker command files I use. They are what is provided for the device on the website:


    /*
    // TI File $Revision: /main/4 $
    // Checkin $Date: July 9, 2008   14:12:52 $
    //###########################################################################
    //
    // FILE:    F2812_IQmath_lnk.cmd
    //
    // TITLE:   Linker Command File For IQmath examples that run out of RAM
    //
    // NOTE; The example project uses memory protected by the
    //       Code Security Module (CSM).  Make sure the CSM is
    //       unlocked before you load the project.  One quick way
    //       to do this on an erased device is to open a memory
    //       window to the CSM password locations.  If these locations
    //       read back 0xFFFF (or non-zero), then the CSM is unlocked:
    //
    //      Device    Password locations
    //      2812:     0x3F7FF8 - 0x3F7FFF
    //
    //
    //###########################################################################
    // $TI Release: IQmath V1.5a $
    // $Release Date: June 2, 2009 $
    //###########################################################################
    */

    MEMORY
    {
    PAGE 0 :
       /* IQTABLES is part of the boot ROM.  The boot ROM
          is available in both program or data space so this
          can be defined on page 0 or page 1
       */
       IQTABLES   : origin = 0x3FF000, length = 0x000b50
       RAMM0      : origin = 0x000000, length = 0x000400
       BEGIN      : origin = 0x3F8000, length = 0x000002
       RAMH0      : origin = 0x3F8002, length = 0x001FFE
       RESET      : origin = 0x3FFFC0, length = 0x000002

    PAGE 1 :

       RAMM1    : origin = 0x000400, length = 0x000400
       RAML0L1  : origin = 0x008000, length = 0x002000
    }

    SECTIONS
    {
       /* IQmath includes the assembly routines in the IQmath library
          IQmathTables is used by division, IQsin, IQcos, IQatan, IQatan2
                       this is in boot ROM so we make it NOLOAD.  Using
                       the ROM version saves space at the cost of 1 cycle
                       per access (boot ROM is 1 wait).
          IQmathTablesRam is used by IQasin, IQacos, and IQexp
       */
       IQmath           : > RAMH0,       PAGE = 0
       IQmathTables     : > IQTABLES,    PAGE = 0, type = NOLOAD
       IQmathTablesRam  : > RAML0L1,     PAGE = 1

       codestart        : > BEGIN,       PAGE = 0
       ramfuncs         : > RAMH0        PAGE = 0
       .text            : > RAMH0,       PAGE = 0
       .cinit           : > RAMM0,       PAGE = 0
       .pinit           : > RAMH0,       PAGE = 0
       .switch          : > RAMM0,       PAGE = 0
       .reset           : > RESET,       PAGE = 0, TYPE = DSECT /* not used, */

       .stack           : > RAMM1,       PAGE = 1
       .cio             : > RAML0L1,     PAGE = 1
       .ebss            : > RAML0L1,     PAGE = 1
       .econst          : > RAML0L1,     PAGE = 1
       .esysmem         : > RAML0L1,     PAGE = 1
    }


    /*
    // TI File $Revision: /main/4 $
    // Checkin $Date: July 9, 2009   17:39:29 $
    //###########################################################################
    //
    // FILE:    DSP281x_Headers_nonBIOS.cmd
    //
    // TITLE:   DSP281x Peripheral registers linker command file
    //
    // DESCRIPTION:
    //
    //          This file is for use in Non-BIOS applications.
    //
    //          Linker command file to place the peripheral structures
    //          used within the DSP28 headerfiles into the correct memory
    //          mapped locations.
    //
    //          This version of the file includes the PieVectorTable structure.
    //          For BIOS applications, please use the DSP281x_Headers_BIOS.cmd file
    //          which does not include the PieVectorTable structure.
    //
    //###########################################################################
    // $TI Release: DSP281x C/C++ Header Files V1.20 $
    // $Release Date: July 27, 2009 $
    //###########################################################################
    */

    MEMORY
    {
     PAGE 0:    /* Program Memory */

     PAGE 1:    /* Data Memory */
     
       DEV_EMU     : origin = 0x000880, length = 0x000180     /* device emulation registers */
       PIE_VECT    : origin = 0x000D00, length = 0x000100     /* PIE Vector Table */
       FLASH_REGS  : origin = 0x000A80, length = 0x000060     /* FLASH registers */
       CSM         : origin = 0x000AE0, length = 0x000010     /* code security module registers */
       XINTF       : origin = 0x000B20, length = 0x000020     /* external interface registers */
       CPU_TIMER0  : origin = 0x000C00, length = 0x000008     /* CPU Timer0 registers */
       CPU_TIMER1  : origin = 0x000C08, length = 0x000008     /* CPU Timer1 registers */
       CPU_TIMER2  : origin = 0x000C10, length = 0x000008     /* CPU Timer2 registers */
       PIE_CTRL    : origin = 0x000CE0, length = 0x000020     /* PIE control registers */
       ECANA       : origin = 0x006000, length = 0x000040     /* eCAN control and status registers */
       ECANA_LAM   : origin = 0x006040, length = 0x000040     /* eCAN local acceptance masks */
       ECANA_MOTS  : origin = 0x006080, length = 0x000040     /* eCAN message object time stamps */
       ECANA_MOTO  : origin = 0x0060C0, length = 0x000040     /* eCAN object time-out registers */
       ECANA_MBOX  : origin = 0x006100, length = 0x000100     /* eCAN mailboxes */
       SYSTEM      : origin = 0x007010, length = 0x000020     /* System control registers */
       SPIA        : origin = 0x007040, length = 0x000010     /* SPI registers */
       SCIA        : origin = 0x007050, length = 0x000010     /* SCI-A registers */
       XINTRUPT    : origin = 0x007070, length = 0x000010     /* external interrupt registers */
       GPIOMUX     : origin = 0x0070C0, length = 0x000020     /* GPIO mux registers */
       GPIODAT     : origin = 0x0070E0, length = 0x000020     /* GPIO data registers */
       ADC         : origin = 0x007100, length = 0x000020     /* ADC registers */
       EVA         : origin = 0x007400, length = 0x000040     /* Event Manager A registers */
       EVB         : origin = 0x007500, length = 0x000040     /* Event Manager B registers */
       SCIB        : origin = 0x007750, length = 0x000010     /* SCI-B registers */
       MCBSPA      : origin = 0x007800, length = 0x000040     /* McBSP registers */
       CSM_PWL     : origin = 0x3F7FF8, length = 0x000008     /* Part of FLASHA.  CSM password locations. */
    }
     
    SECTIONS
    {
       PieVectTableFile : > PIE_VECT,   PAGE = 1

    /*** Peripheral Frame 0 Register Structures ***/
       DevEmuRegsFile    : > DEV_EMU,     PAGE = 1
       FlashRegsFile     : > FLASH_REGS,  PAGE = 1
       CsmRegsFile       : > CSM,         PAGE = 1
       XintfRegsFile     : > XINTF,       PAGE = 1
       CpuTimer0RegsFile : > CPU_TIMER0,  PAGE = 1
       CpuTimer1RegsFile : > CPU_TIMER1,  PAGE = 1
       CpuTimer2RegsFile : > CPU_TIMER2,  PAGE = 1  
       PieCtrlRegsFile   : > PIE_CTRL,    PAGE = 1      

    /*** Peripheral Frame 1 Register Structures ***/
       ECanaRegsFile     : > ECANA,       PAGE = 1
       ECanaLAMRegsFile  : > ECANA_LAM    PAGE = 1   
       ECanaMboxesFile   : > ECANA_MBOX   PAGE = 1
       ECanaMOTSRegsFile : > ECANA_MOTS   PAGE = 1
       ECanaMOTORegsFile : > ECANA_MOTO   PAGE = 1

    /*** Peripheral Frame 2 Register Structures ***/
       SysCtrlRegsFile   : > SYSTEM,      PAGE = 1
       SpiaRegsFile      : > SPIA,        PAGE = 1
       SciaRegsFile      : > SCIA,        PAGE = 1
       XIntruptRegsFile  : > XINTRUPT,    PAGE = 1
       GpioMuxRegsFile   : > GPIOMUX,     PAGE = 1
       GpioDataRegsFile  : > GPIODAT      PAGE = 1
       AdcRegsFile       : > ADC,         PAGE = 1
       EvaRegsFile       : > EVA,         PAGE = 1
       EvbRegsFile       : > EVB,         PAGE = 1
       ScibRegsFile      : > SCIB,        PAGE = 1
       McbspaRegsFile    : > MCBSPA,      PAGE = 1
       
    /*** Code Security Module Register Structures ***/
       CsmPwlFile        : > CSM_PWL,     PAGE = 1
    }
    /******************* end of file ************************/

  • For C2000, static-scope (global or static) const variables are placed in the .const or .econst section.  These sections are read-only sections, so they can go in ROM (or FLASH), freeing up space in RAM for other variables and the stack.

    Non-const static-scope variables are placed in .bss or .ebss.

    3446793 said:
    Is there enough space for 1563 words?

    Have a look at the linker map file (--map_file option).  It will tell you which memory areas still have room left.

    The first linker command file shows that .stack goes into RAMM1, which has a length of only 0x400, which is why you can't make the stack bigger.  If you can move your stack variables to .bss or .ebss, which goes into the larger RAML0L1, you will have more room for variables.

  • OK. Based on your tips I have tried the following: I changed the declaration of one local variable of type long (32 bit, 2 words) and looked at the effect on the memory usage as shown in the map file.

    • If the local variable is made a local constant, no changes are visible.
    • If the local variable is made a global constant, a local static constant or a global static constant, 5 more words are used in RAMM0 and 2 more words are used in RAML0L1.
    • If the local variable is made a global variable, a local static variable or a global static variable, 5 more words are used in RAMM0, 2 more words are used in RAML0L1 and 3 more words are used in RAMH0.

    The two words going into RAML0L1 are clear from the last posting. But how about the additional occupation in RAMM0 and RAMH0?

    Further, I have commented all local variable declarations except four. RAMM1, the section that holds the stack, is still filled up entirely in this case. This surprised me because

    • the local variables should only occupy 6 words,
    • the program is very simple and there are no functions that are called and to which arguments are passed, only an interrupt service routine that is frequently called,
    • only one computation is carried out that I expect to save temporary results,
    • no section other than the stack allocates in RAMM1 according to the previously posted linker command files.

    So how come the stack is taking up so much memory?

    Lastly, I noticed that constants defined through the #define statement do apparently not occupy memory at all. This is the case when used either locally or globally. Is there something that could prevent me from using this method of definition? How does one select the desired variable type in this case?

  • There is a difference between the total stack size and each function's call frame size.

    Total stack size is determined by the --stack_size option to the linker, not at all by your source code.

    Call frame size is determined by the local data (including compiler-generated space).  The stack must be large enough so that all of the currently-active frames (all the functions which have been called and have not yet returned) will fit.

  • Now I have defined the constants using #define and added static in front of all other declarations. It seems like all variables are created now.

    Unfortunately, they do not appear in the variable watch window in the order in which they are declared (as shown in the screenshot from the first post). Instead their order is seemingly random. How can you fix that?

    Further, there is a more serious problem: The variables do not assume the values to which they are initialized. See the following screenshots:

    These are just a few examples; there are more such cases. The program execution halted at a breakpoint after the variable declarations when I checked the values. The appearing warnings all say that the variables are never references/used.

  • Variables are not guaranteed to appear in memory in the order they were declared.  There is no compiler option to control this.  You can enforce the order by wrapping all of the variables inside a struct.

    If the variables are truly never used, the compiler might not be bothering to initialize them.

  • You are right. They behave differently now that they are declared as static regarding their order.

    It also looks like they are initialized properly if they are used in an expression later on, as far as I have tested it.

    This seems to resolve the issues associated with the variables. Thanks for bearing with me and providing all the information.

    Adrian