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/LAUNCHXL-CC1352R1: Usage of STACKSIZE defined in lds file.

Part Number: LAUNCHXL-CC1352R1

Tool/software: Code Composer Studio

Hi!

Environment:

CC1352R1 HW Rev. B.
CCS 10
SDK 4.20.00.35

Problem:

I'm trying to figure out what is STACKSIZE (in .lds file) for.

In my project I use lots of global variables and temporary variables on Task stack. When I display size with arm-none-eabi-size.exe console show me sum of all these variables: global + tasks + STACKSIZE, but I don't understand when STACKSIZE memory is used.

Strange thing is that to make my project work I have to set STACKSIZE to value minimum 30k bytes (!), project will fail on GPIO_init() otherwise (beginning of my project, before is just Board_init()). My global variables use something like ~30kb + 4kb for all tasks stacks, so I'm almost out of memory on my board. 

Probably in ROV is some way to check memory usage that I'm missing, or maybe is other way to see what is using this memory? Also if you have any advice what can I do to decrease required STACKSIZE it will be really helpful.

Robert.

  • Hi Robert,

    Can you please provide more context regarding your project settings?  The default GNU command linker file reserves 1024 bytes for the stack, as compared to a CCS program stack configuration of 1376.  This is further verified by investigating __STACK_SIZE of the generated map file.  This SRAM is reserved for system use including general and idle tasks.  Other stack sizes used reserve SRAM for application & MAC tasks, but these are still typically 2k or less.  The heap is another major factor towards SRAM which is typically set for auto-size allocation to use the remaining memory not designated for other functions.

    Regards,
    Ryan

  • Can you please provide more context regarding your project settings?

    My project is made from CC1352R1_Hello_GCC example project.

    Drivers I'm using:

    • RTOS
    • AESCCM
    • DMA
    • GPO
    • NVS
    • TRNG
    • UART
    • RF (with custom IEEE Stack)

    I have:

    • 4 Tasks with 1KB char array stack for each
    • 4 Events one for every task
    • 3 Queues
    • custom power policy
    • few registered interrupts
    • one struct of every driver

    and of course my library which uses multi dimensional std::tuple (tuple of tuples of tuples with multiple variables etc.).


    I can provide more info, but please can you precise what exactly?

    Here is my .lds config file:

    STACKSIZE = 1024*32;
    HEAPSIZE = 0x0400;
    
    MEMORY
    {
        FLASH (RX)      : ORIGIN = 0x00000000, LENGTH = 0x00057fa8
        FLASH_CCFG (RX) : ORIGIN = 0x00057fa8, LENGTH = 0x00000058
        SRAM (RWX)      : ORIGIN = 0x20000000, LENGTH = 0x00014000
        GPRAM (RWX)     : ORIGIN = 0x11000000, LENGTH = 0x00002000
    }
    
    REGION_ALIAS("REGION_TEXT", FLASH);
    REGION_ALIAS("REGION_BSS", SRAM);
    REGION_ALIAS("REGION_DATA", SRAM);
    REGION_ALIAS("REGION_STACK", SRAM);
    REGION_ALIAS("REGION_HEAP", SRAM);
    REGION_ALIAS("REGION_ARM_EXIDX", FLASH);
    REGION_ALIAS("REGION_ARM_EXTAB", FLASH);
    
    SECTIONS {
    
        PROVIDE (_intvecs_base_address =
            DEFINED(_intvecs_base_address) ? _intvecs_base_address : 0x0);
    
        .intvecs (_intvecs_base_address) : AT (_intvecs_base_address) {
            KEEP (*(.intvecs))
        } > REGION_TEXT
    
        PROVIDE (_vtable_base_address =
            DEFINED(_vtable_base_address) ? _vtable_base_address : 0x20000000);
    
        .vtable (_vtable_base_address) (NOLOAD) : {
            KEEP (*(.vtable))
        } > REGION_DATA
    
        _rom_data_start = 0x20000100;
        _rom_data_size = DEFINED(ROM_DATA_SIZE) ? 12 : DEFINED(ROM_DATA_SIZE_NO_OAD) ? 0x108 : 0;
    
        .rom_data_reserve (_rom_data_start): {
            . += _rom_data_size;
        } > REGION_DATA
    
        UDMACC26XX_CONFIG_BASE = 0x20001800;
    
        DMA_UART0_RX_CONTROL_TABLE_ENTRY_ADDRESS  = (UDMACC26XX_CONFIG_BASE + 0x10);
        DMA_UART0_TX_CONTROL_TABLE_ENTRY_ADDRESS  = (UDMACC26XX_CONFIG_BASE + 0x20);
        DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS   = (UDMACC26XX_CONFIG_BASE + 0x30);
        DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS   = (UDMACC26XX_CONFIG_BASE + 0x40);
        DMA_UART1_RX_CONTROL_TABLE_ENTRY_ADDRESS  = (UDMACC26XX_CONFIG_BASE + 0x50);
        DMA_UART1_TX_CONTROL_TABLE_ENTRY_ADDRESS  = (UDMACC26XX_CONFIG_BASE + 0x60);
        DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS   = (UDMACC26XX_CONFIG_BASE + 0x70);
        DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x90);
        DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS   = (UDMACC26XX_CONFIG_BASE + 0x100);
        DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS   = (UDMACC26XX_CONFIG_BASE + 0x110);
    
        DMA_UART0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x210);
        DMA_UART0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x220);
        DMA_SPI0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x230);
        DMA_SPI0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x240);
        DMA_UART1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x250);
        DMA_UART1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x260);
        DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS     = (UDMACC26XX_CONFIG_BASE + 0x270);
        DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS   = (UDMACC26XX_CONFIG_BASE + 0x290);
        DMA_SPI1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x300);
        DMA_SPI1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS = (UDMACC26XX_CONFIG_BASE + 0x310);
    
        UDMACC26XX_uart0RxControlTableEntry_is_placed = 0;
        .dmaUart0RxControlTableEntry DMA_UART0_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0RxControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_uart0TxControlTableEntry_is_placed = 0;
        .dmaUart0TxControlTableEntry DMA_UART0_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0TxControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_dmaSpi0RxControlTableEntry_is_placed = 0;
        .dmaSpi0RxControlTableEntry DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0RxControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_dmaSpi0TxControlTableEntry_is_placed = 0;
        .dmaSpi0TxControlTableEntry DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0TxControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_uart1RxControlTableEntry_is_placed = 0;
        .dmaUart1RxControlTableEntry DMA_UART1_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1RxControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_uart1TxControlTableEntry_is_placed = 0;
        .dmaUart1TxControlTableEntry DMA_UART1_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1TxControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_dmaADCPriControlTableEntry_is_placed = 0;
        .dmaADCPriControlTableEntry DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_ADC_PRI_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaADCPriControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_dmaGPT0APriControlTableEntry_is_placed = 0;
        .dmaGPT0APriControlTableEntry DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_GPT0A_PRI_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaGPT0APriControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_dmaSpi1RxControlTableEntry_is_placed = 0;
        .dmaSpi1RxControlTableEntry DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_RX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1RxControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_dmaSpi1TxControlTableEntry_is_placed = 0;
        .dmaSpi1TxControlTableEntry DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_TX_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1TxControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_uart0RxAltControlTableEntry_is_placed = 0;
        .dmaUart0RxAltControlTableEntry DMA_UART0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0RxAltControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_uart0TxAltControlTableEntry_is_placed = 0;
        .dmaUart0TxAltControlTableEntry DMA_UART0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart0TxAltControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_dmaSpi0RxAltControlTableEntry_is_placed = 0;
        .dmaSpi0RxAltControlTableEntry DMA_SPI0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0RxAltControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_dmaSpi0TxAltControlTableEntry_is_placed = 0;
        .dmaSpi0TxAltControlTableEntry DMA_SPI0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI0_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi0TxAltControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_uart1RxAltControlTableEntry_is_placed = 0;
        .dmaUart1RxAltControlTableEntry DMA_UART1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1RxAltControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_uart1TxAltControlTableEntry_is_placed = 0;
        .dmaUart1TxAltControlTableEntry DMA_UART1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_UART1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaUart1TxAltControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_dmaADCAltControlTableEntry_is_placed = 0;
        .dmaADCAltControlTableEntry DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_ADC_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaADCAltControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_dmaGPT0AAltControlTableEntry_is_placed = 0;
        .dmaGPT0AAltControlTableEntry DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_GPT0A_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaGPT0AAltControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_dmaSpi1RxAltControlTableEntry_is_placed = 0;
        .dmaSpi1RxAltControlTableEntry DMA_SPI1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_RX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1RxAltControlTableEntry)} > REGION_DATA
    
        UDMACC26XX_dmaSpi1TxAltControlTableEntry_is_placed = 0;
        .dmaSpi1TxAltControlTableEntry DMA_SPI1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS (NOLOAD) : AT (DMA_SPI1_TX_ALT_CONTROL_TABLE_ENTRY_ADDRESS) {*(.dmaSpi1TxAltControlTableEntry)} > REGION_DATA
    
        _rom_rodata_start = 0x2000;
        _rom_rodata_size = DEFINED(ROM_RODATA_SIZE) ? 0 : DEFINED(ROM_RODATA_SIZE_NO_OAD) ? 0x330 : 0;
    
        .rom_rodata_reserve (_rom_rodata_start): {
            . += _rom_rodata_size;
        } > REGION_TEXT AT> REGION_TEXT
    
        .text : {
            CREATE_OBJECT_SYMBOLS
            *(.text)
            *(.text.*)
            . = ALIGN(0x4);
            KEEP (*(.ctors))
            . = ALIGN(0x4);
            KEEP (*(.dtors))
            . = ALIGN(0x4);
            __init_array_start = .;
            KEEP (*(.init_array*))
            __init_array_end = .;
            *(.init)
            *(.fini*)
        } > REGION_TEXT AT> REGION_TEXT
    
        PROVIDE (__etext = .);
        PROVIDE (_etext = .);
        PROVIDE (etext = .);
    
        .rodata : {
            *(.rodata)
            *(.rodata.*)
            *(.rodata_*)
        } > REGION_TEXT AT> REGION_TEXT
    
        .data : ALIGN(4) {
            __data_load__ = LOADADDR (.data);
            __data_start__ = .;
            *(.data)
            *(.data.*)
            . = ALIGN (4);
            __data_end__ = .;
        } > REGION_DATA AT> REGION_TEXT
    
        .ARM.exidx : {
            __exidx_start = .;
            *(.ARM.exidx* .gnu.linkonce.armexidx.*)
            __exidx_end = .;
        } > REGION_ARM_EXIDX AT> REGION_ARM_EXIDX
    
        .ARM.extab : {
            *(.ARM.extab* .gnu.linkonce.armextab.*)
        } > REGION_ARM_EXTAB AT> REGION_ARM_EXTAB
    
        .nvs (NOLOAD) : ALIGN(0x2000) {
            *(.nvs)
        } > REGION_TEXT
    
        .ccfg : {
            KEEP (*(.ccfg))
        } > FLASH_CCFG AT> FLASH_CCFG
    
        .bss : {
            __bss_start__ = .;
            *(.shbss)
            *(.bss)
            *(.bss.*)
            *(COMMON)
            . = ALIGN (4);
            __bss_end__ = .;
        } > REGION_BSS AT> REGION_BSS
    
        .heap : {
            __heap_start__ = .;
            end = __heap_start__;
            _end = end;
            __end = end;
            KEEP(*(.heap))
            __heap_end__ = .;
            __HeapLimit = __heap_end__;
        } > REGION_HEAP AT> REGION_HEAP
    
        /* Heap buffer used by HeapMem */
        .priheap : {
            . = ALIGN (8);
            __primary_heap_start__ = .;
            . += HEAPSIZE;
            __primary_heap_end__ = .;
        } > REGION_HEAP AT> REGION_HEAP
    
        .stack (NOLOAD) : ALIGN(0x8) {
            _stack = .;
            __stack = .;
            KEEP(*(.stack))
            . += STACKSIZE;
        } > REGION_STACK AT> REGION_STACK
    }
    

  • How did you determine the STACKSIZE and HEAPSIZE since the values listed in your .lds file are not the defaults (1024 and 0x1000, respectively)?  If you parse the generated map file then you will be able to further understand the memory allocations.  If you haven't already found them, here are some further ROV resources:

    https://dev.ti.com/tirex/explore/node?node=AAvd2v6HXXe-QpjluM.XgA__pTTHBmu__LATEST 
    https://dev.ti.com/tirex/content/simplelink_cc13x2_26x2_sdk_4_20_00_35/docs/proprietary-rf/proprietary-rf-users-guide/proprietary-rf-guide/debugging-index.html 
    https://processors.wiki.ti.com/index.php/Runtime_Object_View_(ROV) 
    https://training.ti.com/debugging-common-application-issues-ti-rtos 

    Regards,
    Ryan

  • Ryan Brown1 said:

    How did you determine the STACKSIZE and HEAPSIZE since the values listed in your .lds file are not the defaults (1024 and 0x1000, respectively)? 

    That's what I mean. I had to increase dramatically STACKSIZE to make my program works. 

    After more research I found a solution, problem was with way that I initialized my objects.

    I wanted to create all of my objects compile time, but inside objects were lots of cross pointers which I tried to set inside constructor initialization list, something like this (pseudocode):

    struct Attribute;
    struct Object;
    struct Owner;
    
    struct Attribute {
     constexpr Object(Object* _obj) : obj(_obj) {}
    
     Object* obj;
    }
    struct Object {
     constexpr Object(Owner* _owner) : owner(_owner), attr(createAttrs()) {}
     constexpr  std::tuple<Attribute...> createAttrs() {
      return { Attribute(this) etc... }; 
     }
    
     Owner* owner;
     std::tuple<Attribute...> attr;
    }
    struct Owner {
     constexpr Owner() : objs(createObjects()) {}
     constexpr std::tuple<Object...> createObjects() {
      return { Object(this) etc... }; 
     }
    
      std::tuple<Object...> objs;
    }

    and I figure out that when I created my objects this way program consumed giant amount of ISR memory on createObjects() etc method. Probably it created temporary objects which aggregate another ones, then copy constructor on std::tuple with lots of types. This way I created awful situation with huge memory usage and non compile time objects creation (do I understand this right?).  

    Solution was to default set all pointers to nullptr, not using references and for every class/struct create method like init() when I pass and set all pointers (in short, fun with addresses is made runtime).