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.

MSP-EXP432P401R: Creation of large array

Part Number: MSP-EXP432P401R

Hi to all!

I have a problem on creating a large arrays object. I'm using the gcc compiler (4.9.3) on ccsv6 (6.2.0.00050) and I write the program in c++.

I have done some test to discover the problem, but I'm unable to find a solution because when I arrive to the line of code that create the array (using the new) the debug run for a long time, and when i pause it, the debug pointer goes to the default_handler routine. But before the debug execute this line of code, i obtain some message like this "memory map prevent reading ...", this message disappear if I do a debug step.

I have read some post about this error, but I did not understand how to fix it.

In my program, I need to use 4 arrays of 2000/3000 uint16_t elements. The msp432 have a 64Kb of ram, so i not fill all the memory of the microcontroller.

Someone can help me to solve this problem?

  • While there may be enough RAM, there might not be enough available to the new operator. While this advice is getting a bit long in the tooth, in general it is not a good idea to dynamically allocate a lot of memory on an embedded processor. I suggest you allocate it statically.
  • Hi Keith, thank you for the reply.

    You are right on the fact that is not a good idea to dynamically allocate the memory on an embedded processor, but in my case, i allocate this memory in the init phase of my program and not in the "runtime".

    For better explain, i have this situation:

    int main(){
    
    Scheduler s;
    Object one;
    Object two;
    
    enable_interrupt();
    s.run(); }

    I allocate dinamically the memory only in the objects creation, the "program" is in the run method, and in this method i doesn't allocate memory dinamically. The new fails in the creation of the object two.

    I know how to resolve this problem using static allocation, but i have done a framework so i prefer to use the dynamic allocation if possible, otherwise I have to change my framework and I would like to avoid doing it.

    A note on the my framework, it work well with the atmega2560, in this case the problem is that the atmega2560 has 8Kb of ram, and using 4 large arrays, i fill all the memory so i can't use this microcontroller.

  • I also believe that the size of the heap is the problem, because if i use small arrays (like 300 elements per array), the program run normally. My heap setting use the default setting, so I think that i need to be increase it. Tomorrow I try to understand how to change it.

    Thank so much! ;)
  • Hi Keith,

    I have tryed to change the heap size but i'm unable to change it. In the link that you have posted, there is a way to set the heap, but i thing that is useful if one use the ti compiler.

    The procedure doesn't work with gnu compiler, I have tryed to add this flag "-heap=<heap size in byte>" to the gnu linker, but it doesn't work.

    Also i have changed the SRAM_CODE and SRAM_DATA length defined in the lds file, but in this case the debugger run continuosly between reset and restart.

    At the moment i haven't any idea on how to change the heap size using gnu compiler, please can you tell me some good document so i find some info on how to change the heap size?

  • Nope, I only use TI.
  • Ok, thanks anyway. I cannot use the Ti compiler because it doesn't support the c++11.
  • There should be something in your linker control file that defines where the heap and stack are. Is that file short enough to post?
  • Hi Bruce!

    This is the content of lds file that are in my project folder:

    MEMORY
    {
        MAIN_FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x00040000
        INFO_FLASH (RX) : ORIGIN = 0x00200000, LENGTH = 0x00004000
        SRAM_CODE  (RWX): ORIGIN = 0x01000000, LENGTH = 0x00010000
        SRAM_DATA  (RW) : ORIGIN = 0x20000000, LENGTH = 0x00010000
    }
    
    REGION_ALIAS("REGION_TEXT", MAIN_FLASH);
    REGION_ALIAS("REGION_INFO", INFO_FLASH);
    REGION_ALIAS("REGION_BSS", SRAM_DATA);
    REGION_ALIAS("REGION_DATA", SRAM_DATA);
    REGION_ALIAS("REGION_STACK", SRAM_DATA);
    REGION_ALIAS("REGION_HEAP", SRAM_DATA);
    REGION_ALIAS("REGION_ARM_EXIDX", MAIN_FLASH);
    REGION_ALIAS("REGION_ARM_EXTAB", MAIN_FLASH);
    
    SECTIONS {
    
        /* section for the interrupt vector area                                 */
        PROVIDE (_intvecs_base_address =
            DEFINED(_intvecs_base_address) ? _intvecs_base_address : 0x0);
    
        .intvecs (_intvecs_base_address) : AT (_intvecs_base_address) {
            KEEP (*(.intvecs))
        } > REGION_TEXT
    
        /* The following three sections show the usage of the INFO flash memory  */
        /* INFO flash memory is intended to be used for the following            */
        /* device specific purposes:                                             */
        /* Flash mailbox for device security operations                          */
        PROVIDE (_mailbox_base_address = 0x200000);
    
        .flashMailbox (_mailbox_base_address) : AT (_mailbox_base_address) {
            KEEP (*(.flashMailbox))
        } > REGION_INFO
    
        /* TLV table for device identification and characterization              */
        PROVIDE (_tlv_base_address = 0x00201000);
    
        .tlvTable (_tlv_base_address) (NOLOAD) : AT (_tlv_base_address) {
            KEEP (*(.tlvTable))
        } > REGION_INFO
    
        /* BSL area for device bootstrap loader                                  */
        PROVIDE (_bsl_base_address = 0x00202000);
    
        .bslArea (_bsl_base_address) : AT (_bsl_base_address) {
            KEEP (*(.bslArea))
        } > REGION_INFO
    
        PROVIDE (_vtable_base_address =
            DEFINED(_vtable_base_address) ? _vtable_base_address : 0x20000000);
    
        .vtable (_vtable_base_address) : AT (_vtable_base_address) {
            KEEP (*(.vtable))
        } > REGION_DATA
    
        .text : {
            CREATE_OBJECT_SYMBOLS
            KEEP (*(.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
    
        .rodata : {
            *(.rodata)
            *(.rodata.*)
        } > REGION_TEXT 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
    
        __etext = .;
    
        .data : {
            __data_load__ = LOADADDR (.data);
            __data_start__ = .;
            KEEP (*(.data))
            KEEP (*(.data*))
            . = ALIGN (4);
            __data_end__ = .;
        } > REGION_DATA AT> REGION_TEXT
    
        .bss : {
            __bss_start__ = .;
            *(.shbss)
            KEEP (*(.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
    
        .stack (NOLOAD) : ALIGN(0x8) {
            _stack = .;
            __stack = .;
            KEEP(*(.stack))
        } > REGION_STACK AT> REGION_STACK
    	
    	__StackTop = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK);
    }
    

    I have tryed to modify this file whitout success. In particular i have modified the length of SRAM_CODE and SRAM_DATA.

    However, this file is a bit hard to read for me, now I'm looking for some document to learn how to read and modify it.

  • You probably shouldn't mess with those SRAM_* variables, since they describe your actual device.

    > KEEP (*(.heap))
    This isn't what I'm used to -- it appears to expect an actual section of type ".heap", and I'm not sure where that should come from.

    However, here's a quick hack. I compute 3000*4*sizeof(uint16_t) as 24000 and round it to 32K. Insert this line after the KEEP:

    > . = . + 32768; /* Heap Size 32K */

    You should be able to see this in the .map file as __heap_start__ and __heap_end__
    ---------------
    Your code schema above doesn't disable the watchdog. Does your actual code do this? I've seen cases reported where initialization of large arrays takes so long that it triggers the watchdog.
  • Hi Bruce!

    Your hack solve the problem! Thank you so much!! ;)

    I have found this, maybe can help you to solve your doubts on ".heap" section.

    Yes, my code disable the watchdog, I do this in the "system_msp432p401r.c" file that is generated from the ccs project. In this file i also set the timers that i use in my program.

  • The GCC (ld) linker files I'm used to do the heap/stack pretty much as I suggested, except that the "magic number" 32768 is replaced by a "magic name" that is passed in from the build environment; that name seems to vary from one IDE to the next, and I don't know what it is here.
  • I'm not an expert, so maybe i'm not able to solve your doubts. However i have also a ccsv7 installed on another windows os, and using this ide,
    if i create a gcc tirtos project, like "hello world", the lds file generated in this project is this:

    /*
     * Copyright (c) 2015-2017, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*
     *  ======== MSP_EXP432P401R_TIRTOS.lds ========
     *  Define the memory block start/length for the MSP_EXP432P401R M4
     */
    
    STACKSIZE = 1024;
    HEAPSIZE = 0x8000;   /* Size of heap buffer used by HeapMem */
    
    MEMORY
    {
        MAIN_FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x00040000
        INFO_FLASH (RX) : ORIGIN = 0x00200000, LENGTH = 0x00004000
        SRAM_DATA  (RW) : ORIGIN = 0x20000000, LENGTH = 0x00010000
    }
    
    REGION_ALIAS("REGION_TEXT", MAIN_FLASH);
    REGION_ALIAS("REGION_BSS", SRAM_DATA);
    REGION_ALIAS("REGION_DATA", SRAM_DATA);
    REGION_ALIAS("REGION_STACK", SRAM_DATA);
    REGION_ALIAS("REGION_HEAP", SRAM_DATA);
    REGION_ALIAS("REGION_ARM_EXIDX", MAIN_FLASH);
    REGION_ALIAS("REGION_ARM_EXTAB", MAIN_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
    
        .text : {
            CREATE_OBJECT_SYMBOLS
            KEEP (*(.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
    
        .rodata : {
            *(.rodata)
            *(.rodata.*)
        } > REGION_TEXT 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
    
        __etext = .;
    
        .data : {
            __data_load__ = LOADADDR (.data);
            __data_start__ = .;
            KEEP (*(.data))
            KEEP (*(.data*))
            . = ALIGN (4);
            __data_end__ = .;
        } > REGION_DATA AT> REGION_TEXT
    
        .nvs (NOLOAD) : ALIGN(0x1000) {
            *(.nvs)
        } > REGION_TEXT
    
        .bss : {
            __bss_start__ = .;
            *(.shbss)
            KEEP (*(.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
    }

    As you can see, in this file are defined the two "magic name"...

    Your hack that you suggest me, look like this:

        .stack (NOLOAD) : ALIGN(0x8) {
            _stack = .;
            __stack = .;
            KEEP (*(.stack))
            . += STACKSIZE;
        } > REGION_STACK AT> REGION_STACK

    I had guessed what this piece of code does, but I've been confused by these other pieces of code:

        .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

    The last snippet of code, use the HeapMem object that is part of the tirtos enviroment, and this confused me a lot because the first piece of code refers to the "heap" section, where I expected the change in the length of the heap, but the change in the length of the heap is not done in this section, so my doubts.

    In the non-tirtos project, however, this "magic names" are not defined in the lds file located in the gcc project folder. However, these are defined in the Ti compiler project but for using those, one need to uncomment then.

**Attention** This is a public forum