Reference:http://e2e.ti.com/support/low_power_rf/f/538/t/95098.aspx
http://blog.sina.com.cn/s/blog_4c8287230100d5hx.html
http://e2e.ti.com/support/low_power_rf/f/538/t/163680.aspx
http://www.deyisupport.com/question_answer/analog/wireless_connectivity/f/45/t/16467.aspx
http://blog.csdn.net/bailyzheng/article/details/7541422
今天运行IAR程序时,连接阶段报错:
Error[e104]: Failed to fit all segments into specified ranges. Problem discovered in segment XDATA_N. Unable to place 2 block(s) (0xbba byte(s) total) in 0x925 byte(s) of memory. The problem occurred while processing the segment placement command
"-P(XDATA)XDATA_N=_XDATA_START-_XDATA_END", where at the moment of placement the available memory ranges were "XDATA:15db-1eff"
Error while running Linker
首先,告诉大家一些解决办法,然后分析一下:
1、 减少冗余数组,优化程序
2、 换用更大内存的片子
一般而言,我们板子都是买好的,要想换掉不太容易,所以我们选择优化程序。
解决办法:
在预编译里面有一个INT_HEAP_LEN属性,默认的值为3027,将他改小到1000或者更小,这个问题就可以解决。
###############################################################################
为什么会这样子呢?我们可以来分析一下。
首先,我们得了解CC2540的存储器的情况。
CC2540里的四种存储空间(结构上划分的存储空间,并不是实际的存储器,是一种理论上的概念)
1. CODE 程序存储器 用处存放程序代码和一些常量
有16根地址总线,所以CODE的寻址范围是 0000H~FFFFH共64KB
2. DATA 数据存储器 用于存放程序运行过程中的数据
有8根地址总线,所以DATA的寻址空间为 00H~FFH共256 byte.低128位可以直接寻址,高128位只能间接寻址。
3. XDATA 外部数据存储器(只能间接寻址,访问速度比较慢) DMA是在XDATA上寻址的,这一点很重要
有16根地址总线,所以 XDATA的寻址空间为 0000H ~ FFFFH共64K
4. SFR 特殊功能寄存器 就是那些T1CTL, EA, P0等配置寄存器存储的地方共128K。因为CC2530的配置寄存器比较多,所以一些多余的寄存器就放到了XREG 里面。XREG的大小为1K XREG的访问速度比 SFR慢。
从图中可以看出,XDATA中包含了所有存储器的映射,包括256kb的FLASH存储器,8K的SRAM存储器,还有 SFR , XREG, INFORMATION FAGE。这里看出来,其实CC2530的DATA,和 XDATA,都是用SRAM作为物理存储媒介的,但是它们的寻址方式不一样,所以访问DATA,比访问XDATA要快。至于SFR,XREG,INFORMATION PAGE,我不知道它们用了什么物理存储媒介,但是它们都被映射到XDATA上,可以被DMA访问。
这里要搞清楚一个概念,映射到XDATA上,不代表就只能用XDATA的寻址方式访问。比如SFR,它虽然被映射到了XDATA上,只能说明,DMA可以通过访问XDATA来操作SFR,但是CPU还是可以通过单周期访问SRF.打个比方,我们平时坐的公交车上都有一把逃生应急锤,在紧急情况下可以敲破窗子逃生。我们平时不会使用锤子敲碎窗子进出车厢,我们平时有车门可以走。但是在特殊情况下(比如DMA要操作某个存储器中的数据时),我们可以用特殊的方法(从XDATA上的映射来得到我们想要的数据)。
*************************************************************************
虽然上面说了这么多,其实我们只需要了解到:DATA和XDATA存在SRAM上,而CODE存在Flash上就可以了。哪一段的代码溢出我们就处理哪一段。CC2540是256KB的Flash和8KB的SRAM。
我们在Output文件夹的.map文件中的最后可以看到
166 159 bytes of CODE memory
26 bytes of DATA memory (+ 81 absolute )
6 396 bytes of XDATA memory
192 bytes of IDATA memory
8 bits of BIT memory
4 478 bytes of CONST memory
也就是我们比较关心的DATA+XDATA所占的内存不能SRAM的8KB,这就是我们处理问题的关键。那么,我们知道DATA是用于存放程序运行过程中的数据。XDATA中包括堆的定义,也就是堆数组包括在XDATA。
**********************************************************************
那么我们把INT_HEAP_LEN的值改小以后,程序有什么影响呢?
正如前面所说的INT_HEAP_LEN位于XDATA,它是一个堆,是为了动态内存分配的,BLE协议栈使用动态分配了几个功能,主要用于执行加密和存储安全密钥。如果你减少INT_HEAP_LEN的值太多,加密就会失败。现在设想一个主机可以可以用加密的方式同时连接到三个从机。这里的堆大小就需要特别大,如果没有充足的空间,程序将无法执行。但是如果INT_HEAP_LEN值改的太大,又影响了运行中的数据处理。所以一个合适的INT_HEAP_LEN值,是比较难找的。
Heap size is reserved for dynamic memory allocation in the stack. Reduced
heap size may reduce the performance and may reject packets in the heavily
loaded system especially for Coordinator. 1K heap would be enough for some
small demo i.e. LIGHT – SWITCH demo, it depends on the application and how
much data to send.
*************************************************************************
那么为什么我们把INT_HEAP_LEN的值改小以后,程序就能正常执行了呢?
在OSAL_Memory.c中我们找到了
{
static __no_init osalMemHdr_t theHeap[MAXMEMHEAP / OSALMEM_HDRSZ];
}
其中MAXMEMHEAP的定义,我们在Onboard.h中可以找到
{
// Memory Allocation Heap
#if defined( EXTERNAL_RAM )
#define MAXMEMHEAP EXT_RAM_LEN // Typically, 32K
#else
#define MAXMEMHEAP INT_HEAP_LEN // Typically, 0.70-1.50K
#endif
}
上面的代码就是定义了一个堆,大小为(MAXMEMHEAP / OSALMEM_HDRSZ)
所以,INT_HEAP_LEN的大小就决定了整个堆的大小,我们可以适当的减小INT_HEAP_LEN的值来达到减少程序大小的目的。
如需转载请标明出处:http://blog.csdn.net/itas109