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.

CCS/TM4C1294NCPDT: CCS V7 with GCC: Stack issues

Part Number: TM4C1294NCPDT

Tool/software: Code Composer Studio

Hi,

I had hard times finding out that the stack is by default 128 words only, is not 8 byte aligned and not located at RAMTOP at all. Is there any reason why you TI guys choose that strange layout?

From my understanding the stack:

- should be reasonable large (not 128 words). Maybe 1/4 of the total RAM would be a good start

- should be on a 8 byte boundary (it's written somewhere in the ARM ABI spec, if its not 8 byte aligned it breaks floating point stuff in the C library, found out the hard way)

- should not be inside the BSS in the middle of my variables but at RAMTOP (stack grows downwards from my understanding). It leads to the funny effect that depending on how many variables by chance end up in front of the stack, the alignment shifts, breaking the 8 byte alignment rule and floating point works or works not on a random base (also found out the hard way)

- should be initialized properly using the sections defined in the in the linker script (from what i see now the script is totally ignore and the stack pointer points into pui32Stack which is a variable in BSS

- I'm not sure if we actually create two stacks this way, not knowing where the libc actually expect the stack. I assume libc uses the references from the linker script but we setup the stack elsewhere

Can someone explain me why it is implemented in this way? I've never seen it on any other ARM platform (ST, NXP). And I still have mysterious crashes I blame on the weird stack management.

I changed the startup code to "static uint32_t __attribute__((aligned(0x8))) pui32Stack[32768];" to address the issues above but still crashes.

Markus

  • I am sorry that you are experiencing problems. Some of your concerns about the stack are handled "under the hood". Let me explain what is going on, and perhaps suggest some ways that we can customize the stack for more efficiency.

    For many of our example projects, the reserved stack space is quite small. The size of the stack can be changed by right clicking on the project name and  selecting "Show Build Settings...". Then  expand "CCSBuild" -> "ARM Linker" -> "Basic Options" and you can set the stack size.

    Your point about making sure the stack is aligned to an 8 byte boundary is well taken. That is actually forced in the initialization code in boot.asm:

    	;*-----------------------------------------------------
    	;* ALIGN THE STACK TO 64-BITS IF EABI.
    	;*-----------------------------------------------------
    	.if __TI_EABI_ASSEMBLER
    	MOV	r7, sp
    	MOVS	r0, #0x07
    	BICS    r7, r0         ; Clear upper 3 bits for 64-bit alignment.
    	MOV	sp, r7
    	.endif
    

    The link command file for most of our projects provides the linker no restrictions on placement of the stack other than if be in RAM. You prefer the stack to be at the top of RAM (highest address I assume), I prefer it to be at the lowest address in RAM. The reason for my preference is that since, as you correctly pointed out, the stack grows downward (toward lower addresses), if I get a stack overflow, instead of corrupting some variable in RAM I will get a precise data abort at the address 0x1FFFFFFx. That is easy for me to recognize as a need for more stack space. I can only do this if I don't have a bootloader that requires a vector table at the start of RAM. I can force the linker to put my stack at the bottom of RAM with this modification to the link command file:

    SECTIONS
    {
        .intvecs:   > APP_BASE
        .text   :   > FLASH
        .const  :   > FLASH
        .cinit  :   > FLASH
        .pinit  :   > FLASH
        .init_array : > FLASH
    
        .stack  :   > RAM_BASE
        .data   :   > SRAM
        .bss    :   > SRAM
        .sysmem :   > SRAM
    }
    
    __STACK_TOP = __stack + 256;
    

    The one thing I don't like, is the definition of "__STACK_TOP" at the end of the link command file. That definition is used to define the value to be placed at Flash location 0x0000000. That value is loaded into the SP on a device reset. Notice that they hardcoded the stack size, in my example at "256". I would much prefer that it be written as:

    __STACK_TOP = __STACK_END;
    

    This now forces the initial stack size to be the same as is defined in the projects options page shown above. However, the hardcoded initial size in the link command file is overwritten in "boot.asm" and the stack is set to the size specified in the project options. This allows the stack to be properly initialized if the code is restarted without a device reset.

    	;*------------------------------------------------------
            ;* INITIALIZE THE USER MODE STACK
            ;*------------------------------------------------------
    	.if __TI_AVOID_EMBEDDED_CONSTANTS
    	.thumb
    	MOVW	r0, __stack
    	MOVT	r0, __stack
    	MOV	sp, r0
    	MOVW	r0, __STACK_SIZE
    	MOVT	r0, __STACK_SIZE
    	.thumb
    	.else ; __TI_AVOID_EMBEDDED_CONSTANTS
    	LDR     r0, c_stack
    	MOV	sp, r0
            LDR     r0, c_STACK_SIZE
    	.endif ; __TI_AVOID_EMBEDDED_CONSTANTS
    	ADD	sp, r0
    
    

  • Bob Crosby said:
    The size of the stack can be changed by right clicking on the project name and  selecting "Show Build Settings...". Then  expand "CCSBuild" -> "ARM Linker" -> "Basic Options" and you can set the stack size.

    Bob, that setting for the stack size is for the TI ARM compiler. Whereas I think Markus was asking about the GCC ARM compiler which has different CCS project properties and different start-up code.

  • Markus Rudolf said:
    Can someone explain me why it is implemented in this way?

    In the past I found the CCS supplied linker scripts and *_startup_ccs_gcc.c start-up files didn't provide a full environment for the GCC run-time library.

    In CCS GNU C Compiler and Linker Setup I tried to explain some issues with the CCS 6.1.x supplied linker scripts and start-up files for the GCC ARM compiler, along with suggested fixes. I haven't checked to see if CCS 7 has fixed any of the previous reported issues, and so looks like I need to check again.

  • Chester,

    You are absolutely correct. Thank you for catching that for me.
  • Thanks for the link. Looks like you are one of the few people knowing what they are doing. I will have a look into that. From a first impression there was little to no improvement in CCS V7. I get the impression TI is not putting very much effort in the whole GCC support in CCS.
  • Thanks for looking into it anyways.
  • I think the issue with failing to align on an 8 byte boundary is that in the startup file for GCC we are missing a line that identifies the array pui32Stack[128] as belonging to the section “.stack”

    //*****************************************************************************
    //
    // Reserve space for the system stack.
    //
    //*****************************************************************************
    __attribute__ ((section(".stack")))
    static uint32_t pui32Stack[128];
    

    The line “__attribute__ ((section(".stack")))” is missing from the current “xxx_startup_ccs_gcc.c” files. I am looking into getting that corrected.