最近因为要用到PIC18f24k20芯片,所以装了MCC18的编译器,配合MAPLAB一起使用,结果到最后编译的时候发现有错误,到网上Google了一下才知道原因。
编译时提示:
Error – section ‘.udata_main.o’ can not fit the section
原来是MCC18的编译器把这个芯片的RAM划分为n个256大小的区域,如果一次定于超过256个字节,譬如一次定义一个70个浮点数的数组(这个在AD转换应该也不难碰到),因为70×4=280大于256,所以超过了它一个区域的范围,导致报错。
后来在picpic.cn 上找到解决的办法,原帖如下:
MCC18 FAQ4 如何在数据存储器中创建一个大对象(> 256 字节)?
默认情况下, MPLAB C18 假设对象不超过存储区边界。要安全使用大于256 字节的
对象,需要执行下列步骤:
1. 必须使用#pragma idata 或#pragma udata 伪指令将对象分配到恰当的段
中:
#pragma udata buffer_scn
static char buffer[0x180];
#pragma udata
2. 必须通过指针访问对象:
char * buf_ptr = &buffer[0];
…
// examples of use
buf_ptr[5] = 10;
if (buf_ptr[275] > 127)
…
3. 必须在链接描述文件中创建一个跨越多个存储区的区域:
– 修改前的链接描述文件:
DATABANK NAME=gpr2 START=0x200 END=0x2FF
DATABANK NAME=gpr3 START=0x300 END=0x3FF
– 修改后的链接描述文件:
DATABANK NAME=big START=0x200 END=0x37F PROTECTED
DATABANK NAME=gpr3 START=0x380 END=0x3FF
4. 必须通过在链接描述文件中添加SECTION 伪指令,将对象所在的段(在第1 步
中创建)分配到新的区域(在第3 步中创建):
SECTION NAME=buffer_scn RAM=big
后面还有一个跟贴说明得很详细:
之所以强调用指针引用(包括显示引用和“隐式引用”–姑且这样称之,如上面“data”)是告诉编译器用间址寻址(indirect addressing,即用FSR0)引用大数据对象而不用考虑跨区(bank)引用时BSR 的值。
可能是目前版本的C18 不够聪明,有时跨区访问时不知道及时更新BSR。这样用直接寻址时就会访问了错误的地址单元。另外,有时如果编译时已知道大数据对象的地址,编译器会生成更为简洁的汇编代码,如直接用MOVFF等。
和同事讨论了一下,干脆一不做二不休,直接把整块RAM划到一块好了,但是后面仿真时发现需要用到gpr4,所以只把pgr1~gpr3放在一起,因为不知道PROTECTED是干嘛的,所以也没按照上面说的加上去,反正编译后烧录进了芯片,运行还是正常的。
后面有人提出了更好的修改方法:
不要修改MCC18 原来的.lkr文件。可拷贝一个.lkr到特定的项目文件夹里,修改拷贝的.lkr文件,然后将该修改的.lkr文件添加到项目中。
这样就更完美了,只修改特定的项目,其他项目还是和原来一样的。
参考文章地址: