目录
问题描述
CC8编译报错:error #10099-D: program will not fit into available memory. placement with alignment/blocking fails for section"
错误的原因大概就是说内存不够了,猜测是RAMLS5内存太小的原因。
解决办法
双击错误信息定位到cmd文件,我这里的是28004x_generic_ram_Ink.cmd文件。
想当然得把RAMLS5后面的length改大,我这里改成了0x002000。编译仍然报错
现在的错误信息就是说后面的几篇RAM会overlaps重叠RAMLS5的内存。
猜测origin的意思是RAM空间的起始位置地址,RAMLS5后面的几片RAM的origin都得一起修改。
RAMLS5起始为0x00A800, 长度0x002000,那么下一片RAMLS6的其实地址应该是0x00C800, 修改RAMLS6的长度为0x002000,下一篇的RAMLS7的起始地址就应该是0x00E800...如此计算然后修改。
最后编译成功
最后仔细想想这RAM的origin和length的知识好像在微机这门课上学到过
2023-01-08 21-22-54更新
Memory Allocation简介
本人比较喜欢事物,新功能,把C2000器件的IDE也CCS也更新到了最新的版本12.1。在新版本的编译界面,默认展现了Memory Allocation这一个功能视图。该功能视图能直观反映cmd文件所置顶的内存分区的使用情况。以及某内存分区下所包含的内容。
这玩意在在低一点的版本不会默认打开,打开方式如下。如果没有如图的选项可能就是版本过低了。
应用说明
我使用TI的SysConfig软件,快速配置了8个PWM外设和16个ADCA的SOC。这外设用的够多了吧。
编译一下,果不其然内存爆掉了。
切换到Memory Allocation视图。
这样子就能轻松且快速看出究竟是哪些section的内存不够用了。以我这里为例,显然是text这个分区的内存爆满了。
打开ram_cmd文件(因为我这里使用ram文件进行链接,如果是采用flash或cla等文件同理),定位到文件末尾处对text这一section的内存划分。
很明显可以看到这一行的左边有一个error的标识符,表明这一次的error出现在这一行。而这一行代码的作用是指明.text这一个section的内存划分,到RAMLS0、RAMLS1、RAMLS2、RAMLS3、RAMLS4里面去的。这些RAMLSx的地址空间也在cmd文件中可以找到。
但是从MemoryAllocation视图中又可以看出.text所划分的5个内存区并没有完全使用完,但仍然报错了,这究竟是为什么呢?根据TI的文档[1],.text分区中的内容是所有可执行代码和常量,并且均是以文件为单位写入的,比如说对于我在main.c文件中的写的代码以及定义的常量,都可以在某一个RAMLS下找到。以我这里为例,main.c文件中定义的代码和常量就在RAMLS1下,占用的内存也比较少。
所以我这里报错的是因为使用SysConfig自动生成代码的文件board.c的代码及常量过于庞大,足足有2126个单位,而.text分区所划分到的内存RAMLSx的最大内存也只有2048个单位,不爆才怪了呢。
解决办法
显然,只需要给.text所划分的内存改大即可。比如把RAMLS0的内存长度改为0x001000。
可以看出原来庞大的board.c文件成功的存放到了修改过后的RAMLS0里面去了,但是现在也面临着新的问题,内存重叠memory overlaps。也就是说RAMLS0起始于0x008000,长度0x001000,那么RAMLS1就应该从0x009000开始,而不是原来的0x008800。这也就是本博客一开始所记录的解决方法。
毕竟是更新,当然就是发现了个比原来更行之有效的解决办法才回来更新博客。
目光还是注意到ram_cmd文件16行的注释。
/* Flash sectors: you can use FLASH for program memory when the RAM is filled up*/
/* BANK 0 */
也就是说TI在编写默认的cmd文件的时候就为用户考虑到了内存写满的情况了,实现给我们定义了很多长度为0x001000的内存区。
所以我们可以使用这些预留的内存区,指定.text分区也存放到这一片内存中去。
修改指定.text段所在内存的代码为
.text : >> RAMLS0 | RAMLS1 | RAMLS2 | RAMLS3 | RAMLS4 | FLASH_BANK0_SEC0, PAGE = 0
再次编译,观察Memory Allocation视图。
可以看到board.c定义的代码和常量都放在FLASH_BAND0_SEC0里面去了。不像原来那样修改内存长度一个一个改,可算方便可多了。
注意事项
可以注意到cmd文件中对不同的分段如.text、.cinit、.switch等的内存划分的同时,也规定了他们所在的PAGE。比如说.cinit在PAGE0下的RAMM0。使用TI预留的FLASH_BANK_SEC那些内存区,必须与这些内存区位于同一个PAGE0才可以。
参考文献
[1] TMS320C28x Optimizing C/C++ Compiler v22.6.0.LTS