×
嵌入式 > 技术百科 > 详情

MSP430FR5969内存分配的问题

发布时间:2020-06-20 发布时间:
|

cmd文件里的具体内容我就不贴了,大家自己可以看一下。cmd文件主要由两部分构成,一个是MEMORY{};另一个是SECTIONS{}

其中MEMORY{}是定义内部所有寄存器及存储器的地址,在这里大部分内容都是厂家定义好的,一般不能修改。但是咱们今天要改的就是他,当然只能改其中允许该的地方,那就是FRAM的分配问题。根据数据手册里提供的内存分配情况(如下图)我们可以得知,59x9的内存从0x0000开始,一直到0x13FFF。对应着这个图和Cmd文件,我们可以了解内部的地址分配问题,如果做过总线扩展之类的同学肯定对这个不会陌生了,如果没有见过就需要理解一下。其实也很简单,就是对应的地址要对应上就可以了。有一些是固定好的不能变,比如各个中断向量的地址,各个寄存器的地址等。一般能变的就是程序存储空间和数据空间了,对应到59x9里面就是cmd文件里的三个部分,即
RAM                      :origin = 0x1C00, length = 0x0800
FRAM                     : origin = 0x4400, length = 0xBB80
FRAM2                   : origin = 0x10000,length = 0x4000
其中origin 表示起始地址,length 表示长度

这几个关键的起始地址和长度可以在上表以及msp430FR59xx69xx数据手册.pdf的21页22页找到,这两页是中断向量地址,也就是cmd文件下面的部分了。上面说到地址的和21页和22页上的地址是内部规定好的,用户不能自行改变。看到这里,我想大家应该明白了,其实这个芯片留给用户的地址有3部分。分别是0x1C00开始的2K空间,0x4400开始的46K空间以及0x100000开始的16K空间。那么这些空间都是放什么内容的呢?这就要说到CMD文件中的另一部分SECTIONS{}了。
顾名思义,SECTIONS就是选择的意思,当然就是选择程序编译过程中的每一部分数据的位置了。这一部分每一行的具体意义我也说不太明白。只是略知一二,与此帖有关的的有这样几句
  1. .cinit            : {}  > FRAM          /* INITIALIZATION TABLES             */
  2.     .pinit            : {}  > FRAM          /* C++ CONSTRUCTOR TABLES            */
  3.     .init_array       : {}  > FRAM          /* C++ CONSTRUCTOR TABLES            */
  4.     .mspabi.exidx     : {}  > FRAM          /* C++ CONSTRUCTOR TABLES            */
  5.     .mspabi.extab     : {}  > FRAM          /* C++ CONSTRUCTOR TABLES            */
  6.     .const            : {} >> FRAM | FRAM2  /* CONSTANT DATA                     */
  7.  
  8.     .text:_isr        : {}  > FRAM          /* CODE ISRs                         */
  9.     .text             : {} >> FRAM2 | FRAM  /* CODE   
复制代码
还有
  1.  
  2.     .bss        : {} > RAM                  /* GLOBAL & STATIC VARS              */
  3.     .data       : {} > RAM                  /* GLOBAL & STATIC VARS              */
  4.     .TI.noinit  : {} > RAM                  /* For #pragma NOINIT                */
  5.     .stack      : {} > RAM (HIGH)           /* SOFTWARE SYSTEM STACK             */
  6.  
复制代码
     相信大家已经看出来了,这一部分就是与我们实用的代码和数据相关的部分。比如.text:_isr : {} > FRAM /* CODE ISRs */这一句是中断代码的位置,在FRAM区域,也就是0x4400开始的46K空间内,具体分配到什么位置就看编译器了,反正不会出这个范围。.text : {} >> FRAM2 | FRAM /* CODE这一个是其他代码的位置,FRAM|FRAM2,即这两块FRAM区域均可。下面的.bbs、.stack、.data等均在RAM区,也就是0x1C00开始的2K空间内。    在实际的使用中,最常见的可能就是数据超出范围,一般都是定义的变量较多或者缓冲区较大,比如在串口通讯的应用中,2K不够用,那么我们就可以把.data : {} > RAM修改为.data : {} > RAM|FRAM2,在以前数据和程序分开定义的芯片中,这个时候在上面.text和.const中就不能再出现FRAM2了。至于这个片子应该是可以的,我还没有试,留个疑问吧。大家可以自己试一下。

    除了上面那样利用官方分好的区块重新定义之外,我们还可以自己重新划分地址。比如把46K的区块划分成两个或者多个区块,当然一般为了实用方便区块还是少一些比较好,把同一类型数据中的子类数据的地址分配权利给编译器会更简单一些,如果对数据的存放比较关心,比如我想单独拿出一块放参数,那么我们就可以单独定义一块地址作为参数,方便数据的管理。

 

 

   

 

从上图中,我们可以看到,字符串常量存储的位置上FLASH1区或者FLASH2区,可执行代码也是存储在FLASH1去或者FLASH2区。这里出现这个问题的原因可能是可执行代码存储在FLASH区,但是需要的字符串常量存在是FLASH2区,所以重定向时,由于存储的位置较远,导致无法定向到。
        因此,我们考虑修改cmd文件,使得字符串常量全部存储在FLASH区。在经过了这样的修改之后,再编译时,不再报错,程序正常运行。
        通过工程目录下的.map文件,我们也可以获取内存分配的信息,可以借此来验证我们修改的正确性。
注:这样做可能还存在一个问题,因为FLASH1区的大小非常小,只有31K,按照目前这种做法,中断函数代码、变量初始化的值以及字符串常量都被存储在FLASH1区,部分执行代码也存在这个区域。如果前面三者的大小超过了FLASH1区的大小,这种情况不知道编译器是否会有提示。如果没有提示,但是溢出的话,可能是会出问题的。但是从目前调试的情况来看,一切正常。如果后续出现奇怪的现象,需要考虑是否是这里的问题。


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
单片机与PC机的通讯介绍02