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:创建大型阵列

Guru**** 2609555 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/657507/msp-exp432p401r-creation-of-large-array

部件号:MSP-EXP432P401R

大家好!

我在创建大型数组对象时遇到问题。 我在ccsv6 (6.2 .0.0.005万)上使用gcc编译器(4.9 .3),并在c++中编写程序。

我已经进行了一些测试来发现问题,但我无法找到解决方案,因为当我到达创建阵列的代码行(使用新的)时,调试会运行很长时间, 当我暂停它时,调试指针转到default_handler例程。 但在调试执行这一行代码之前,我得到了类似“memory map prevent reading...”这样的消息,如果我执行调试步骤,此消息就会消失。

我已经阅读了一些有关此错误的帖子, 但我不知道如何修复。

在我的程序中,我需要使用4个2000/3000 uint16_t3000 uint16_t元素的数组。 msp432有64KB的RAM,所以我没有填满微控制器的所有内存。

有人能帮我解决这个问题吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    虽然可能有足够的RAM,但新操作员可能没有足够的可用RAM。 虽然此建议越来越长,但通常在嵌入式处理器上动态分配大量内存并不是一个好主意。 我建议您静态分配它。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Keith,您好,感谢您的回复。

    您认为,在嵌入式处理器上动态分配内存不是一个好主意,但在我的情况下,我在程序的初始化阶段而不是在“运行时”中分配内存。

    为了更好地解释,我有以下情况:

    int main(){
    
    调度程序;
    对象一;
    对象二;
    
    enable_interrupt ();
    s.run(); }

    我只在对象创建中以二次方式分配内存,“程序”在运行方法中,而在这种方法中,我不以二次方式分配内存。 新的在创建对象2时失败。

    我知道如何使用静态分配来解决这个问题,但是我已经建立了一个框架,所以如果可能的话,我更喜欢使用动态分配,否则 我必须改变我的框架,我想避免这样做。

    关于我的框架的一个注释,它很适合atmega2560,在这种情况下,问题是atmega2560有8KB的RAM,使用4个大阵列,我填满了所有的内存,所以我不能使用这个微控制器。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    堆设置也是什么?
    processors.wiki.ti.com/.../Stack_and_Heap_size_requirements
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我还认为堆的大小是个问题,因为如果我使用小数组(如每个数组300个元素),程序将正常运行。 我的堆设置使用默认设置,因此我认为我需要增加它。 明天,我会试着了解如何改变它。

    非常感谢! ;)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 ,Keith:

    我尝试更改堆大小,但无法更改。 在您发布的链接中,有一种设置堆的方法,但我认为如果使用ti编译器,这是有用的。

    此过程不适用于GNU编译器,我尝试将此标志"-heap=<heap size in byte>"添加到GNU链接器,但它不起作用。

    我还更改  了lds文件中定义的SRAM_CODE和SRAM_DATA长度,但在这种情况下,调试程序在重置和重新启动之间持续运行。

    目前我还不知道如何使用GNU编译器更改堆大小,请告诉我一些好的文档,以便我找到一些有关如何更改堆大小的信息?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    不,我只使用TI。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    好的,谢谢。 我无法使用TI编译器,因为它不支持c++11。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    链接程序控制文件中应该有一些内容定义堆和堆栈的位置。 该文件是否足够短,足以发布?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,布鲁斯!

    这是我的项目文件夹中的lds文件的内容:

    内存
    {
    main_flash (RX):起源= 0x0万,长度= 0x4万
    INFO_FLASH (RX):原点= 0x20万,长度= 0x0.4万
    SRAM_CODE (rwx):原始= 0x100万,长度= 0x1万
    SRAM_DATA (RW):Origin = 0x2000万,length = 0x1万
    }
    
    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);
    
    部分{
    
    中断矢量区域的/*部分 */
    提供(_intvecs_base_address =)
    已定义(_intvecs_base_address)? _intvecs_base_address:0x0);
    
    intvecs (_intvecs_base_address): at (_intvecs_base_address){
    保留(*(.intvecs))}
    > region_text
    
    /*以下三个部分显示信息闪存的使用情况*/
    /* INFO闪存用于以下用途 */
    /*设备特定用途: */
    /*用于设备安全操作的闪存邮箱 */
    提供(_mailbox_base_address = 0x20万);
    
    .flashMailbox (_mailbox_base_address): at (_mailbox_base_address){
    保留(*(.flashMailbox))}
    > region_info
    
    /*用于设备识别和表征的TLV表 */
    提供(_tlv_base_address = 0x20.1万);
    
    .tlvTable (_tlv_base_address)(NoLoad): at (_tlv_base_address){
    保留(*(.tlvTable))}
    > region_info
    
    设备引导加载程序的/* BSL区域 */
    提供(_BSL_base_address = 0x20.2万);
    
    .bslArea (_BSL_base_address):位于(_BSL_base_address){
    保留(*(.bslArea))
    } > region_info
    
    提供(_vtable_base_address =
    已定义(_vtable_base_address)? _vtable_base_address:0x2000万);
    
    .vtable (_vtable_base_address):位于(_vtable_base_address){
    保留(*(.vtable))
    } > region_data
    
    文本:{
    创建对象符号
    保留(*(.text))
    *(.text.*)
    。 =对齐(0x4);
    保留(*(.ctors))
    。 =对齐(0x4);
    保留(*(.ditors))
    。 =对齐(0x4);
    __init_array_start =.;
    保留(*(.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*.gu.linkonce.armexidx.*)
    __exidx_end =.;
    } > region_arm_EXIDX AT> region_arm_EXIDX
    
    arm.extab:{
    *(.arm.extab*.gu.linkonce.armextab.*)
    } > region_arm_extAB at > region_arm_extAB
    
    图文=.;
    
    数据:{
    __data_load__= LOADADADADDDR (.data);
    __data_start__=.;
    保留(*(.data))
    保留(*(.data*)
    。 =对齐(4);
    __data_end__=.;
    } > region_data at > region_text
    
    bss:{
    __bss_start__=.;
    *(.shbss)
    保留(*(.BSS))
    *(.bss.*)
    *(普通)
    。 =对齐(4);
    __bss_end__=.;
    } > region_BSS AT> region_BSS
    
    堆:{
    __heap_start__=.;
    end =__heap_start_;
    _end =结束;
    __end = end;
    保留(*(.heap))
    __heap_end__=.;
    __HeapLimit =__heap_end_;
    } > region_heap at > region_heap
    
    堆栈(NoLoad):对齐(0x8){
    _stack =.;
    __stack =.;
    Keep (*(.stack)
    )} > region_stack at > region_stack
    	
    	__StackTop = origin(region_stack)+ length (region_stack);
    }
    

    我已尝试修改此文件,但没有成功。 我特别修改了SRAM_CODE和SRAM_DATA的长度。

    但是,这个文件对我来说有点难阅读,现在我正在寻找一些文档来学习如何阅读和修改它。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您可能不应该把这些SRAM_*变量弄乱,因为它们描述了您的实际设备。

    > 保留(*(.heap))
    这不是我习惯的--它似乎期望一个类型为".heap"的实际部分,我不确定它应该来自哪里。

    但是,这是一个快速黑客攻击。 我将3000*4*sizeof(uint16_t)计算为2.4万并将其舍入到32K。 在Keep:

    > 。 =。 + 3.2768万;/*堆大小32K */

    您应该能够在.map文件中以__heap_start__和__heap_end__的格式看到这一点
    --------
    上述代码纲要不会禁用监视程序。 您的实际代码是否会执行此操作? 我看到报告的案例表明,大数组的初始化需要很长时间,因此会触发看门狗。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,布鲁斯!

    您的黑客解决了问题! 非常感谢!! ;)

    我发现 了这一点,也许可以帮助您解决".heap"部分的疑问。

    是的,我的代码禁用了看门狗,我在CCS项目生成的“system_msp432p401r.c”文件中执行此操作。 在此文件中,我还设置了程序中使用的计时器。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    GCC (ld)链接器文件,我习惯了执行堆栈/堆栈,正如我建议的那样,除了“magic number”3.2768万被从构建环境传入的“magic name”替换; 该名称似乎因IDE而异,我不知道它在这里是什么。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我不是专家,所以可能我无法解决您的疑问。 但是,我在另一个Windows操作系统上也安装了一个ccsv7,并且使用此IDE,
    如果我创建一个gcc tirtos项目(如"Hello world"),则在该项目中生成的lds文件如下所示:

    /*
    版权所有(c) 2015-2017,2017,Texas Instruments Incorporated
    *保留所有权利。
    *
    **
    允许以源代码和二进制格式重新发布和使用,无论是否进行*修改,只要
    满足以下条件*:
    *
    ****重新发布源代码必须保留上述版权
    *声明,此条件列表和以下免责声明。
    *
    ***以二进制格式重新分发时,必须在
    
    随分发提供的*文档和/或其他材料中复制上述版权*声明,此条件列表和以下免责声明。
    *
    ***
    
    未经事先书面许可,不得使用德州仪器(TI)公司的名称或*其贡献者的名称来支持或促销由本软件衍生的产品*。
    *
    *本软件由版权所有者和贡献者"按原样"提供
    *,
    
    不提供任何明示或暗示的担保,包括但不限于*对适销性和特定*用途适用性的暗示担保。 在任何情况下,版权所有者或
    *贡献者均不对任何直接,间接,附带,特殊,
    *示范, 或后果性损害(包括但不限于
    *购买替代商品或服务;使用,数据或利润损失;
    (*或业务中断),但根据任何责任理论
    ,*无论是合同,严格责任还是侵权行为(包括疏忽或
    *其他),均因使用本软件而导致*
    ,即使已被告知此类损害的可能性。
    */
    
    /*
    === MSP_EXP432P401R_TIRTOS.lds =========
    *定义MSP_EXP432P401R M4
    */
    
    STACKSIZE = 1024;
    HEAPSIZE = 0x8000;/* HeapMem *使用的堆缓冲区大小*/
    
    memory
    {
    main_flash (RX):起源= 0x0万,长度= 0x4万
    INFO_FLASH (RX):原点= 0x20万,长度= 0x0.4万
    SRAM_DATA (RW):Origin = 0x2000万,length = 0x1万
    }
    
    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);
    
    部分{
    
    提供(_intvecs_base_address =)
    已定义(_intvecs_base_address)? _intvecs_base_address:0x0);
    
    intvecs (_intvecs_base_address): at (_intvecs_base_address){
    保留(*(.intvecs))}
    > region_text
    
    提供(_vtable_base_address =
    已定义(_vtable_base_address)? _vtable_base_address:0x2000万);
    
    .vtable (_vtable_base_address)(NoLoad):{
    保留(*(.vtable))
    } > region_data
    
    文本:{
    创建对象符号
    保留(*(.text))
    *(.text.*)
    。 =对齐(0x4);
    保留(*(.ctors))
    。 =对齐(0x4);
    保留(*(.ditors))
    。 =对齐(0x4);
    __init_array_start =.;
    保留(*(.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*.gu.linkonce.armexidx.*)
    __exidx_end =.;
    } > region_arm_EXIDX AT> region_arm_EXIDX
    
    arm.extab:{
    *(.arm.extab*.gu.linkonce.armextab.*)
    } > region_arm_extAB at > region_arm_extAB
    
    图文=.;
    
    数据:{
    __data_load__= LOADADADADDDR (.data);
    __data_start__=.;
    保留(*(.data))
    保留(*(.data*)
    。 =对齐(4);
    __data_end__=.;
    } > region_data at > region_text
    
    NVS (NoLoad):对齐(0x1000){
    *(.NVS)
    } > region_text
    
    bss:{
    __bss_start__=.;
    *(.shbss)
    保留(*(.BSS))
    *(.bss.*)
    *(普通)
    。 =对齐(4);
    __bss_end__=.;
    } > region_BSS AT> region_BSS
    
    堆:{
    __heap_start__=.;
    end =__heap_start_;
    _end =结束;
    __end = end;
    保留(*(.heap))
    __heap_end__=.;
    __HeapLimit =__heap_end_;
    } > region_heap at > region_heap
    
    /* HeapMem */使用的堆缓冲区
    .priheap:{
    。 =对齐(8);
    __primary_heap_start__=.;
    。 += HEAPSIZE;
    __primary_heap_end__=.;
    } > region_heap at > region_heap
    
    堆栈(NoLoad):对齐(0x8){
    _stack =.;
    __stack =.;
    保留(*(.stack))
    。 += STACKSIZE;
    } > region_stack at > region_stack
    } 

    如您所见,在此文件中定义了两个"魔法名称"...

    您建议我的攻击,如下所示:

    堆栈(NoLoad):对齐(0x8){
    _stack =.;
    __stack =.;
    保留(*(.stack))
    。 += STACKSIZE;
    } > region_stack at > region_stack 

    我猜到了这段代码的作用,但我被其他代码的内容迷惑了:

    堆:{
    __heap_start__=.;
    end =__heap_start_;
    _end =结束;
    __end = end;
    保留(*(.heap))
    __heap_end__=.;
    __HeapLimit =__heap_end_;
    } > region_heap at > region_heap
    
    /* HeapMem */使用的堆缓冲区
    .priheap:{
    。 =对齐(8);
    __primary_heap_start__=.;
    。 += HEAPSIZE;
    __primary_heap_end__=.;
    } > region_heap at > region_heap 

    代码的最后一个片段,使用属于tirtos环境一部分的HeapMem对象,这使我很困惑,因为第一段代码引用了“堆”部分,我在该部分中预期堆长度会发生变化, 但是,堆长度的改变不是在这一节中完成的,所以我对此表示怀疑。

    但是,在非tirtos项目中,gcc项目文件夹中的lds文件中没有定义此“魔法名称”。 但是,这些是在TI编译器项目中定义的,但要使用这些,则需要取消注释。