内存溢出

原来一直不太明白单片机的地址映射,也没有仔细的研究过,我想这就是我不是牛人的原因吧。通常开始学单片机,都是写一些比较小的程序,如果不做项目开发之类的,以飞思卡尔16位单片机的资源配置来说也足够了。但是前一阵子遇到了一个问题,需要在RAM中存一个比较大的常数数组,但是单单存在RAM中的话,肯定是存不下,考虑到数组是常数,所以只能存在ROM里,但是当时时间较短,没有研究明白,还得到了非常惨痛的教训,觉得不甘心,打算再花时间研究了一下。在以后的文章中我会把我的研究心得记录下来,希望大家提出意见。

飞思卡尔16位单片机的资源配置 以MC9S12XS128MAL为例,其实DG128之类的类似。如图一,128代表的是单片机中的FLASH大小为128K Byte,同理64代表的是单片机中的FLASH大小为64 K Byte,256代表的是单片机中的FLASH大小为256 K Byte。但是S12(X)所使用的内核CPU12(X)的地址总线为16位,寻址范围最大为2^16 =64K Byte,而这64K Byte的寻址空间还包括寄存器、EEPROM(利用Data Flash模拟)、RAM等,因此不是所有的64K Byte都是用来寻址FLASH。所以在S12(X)系列单片机中,很多资源是以分页的形式出现的,其中包括EEPROM、RAM、FLASH。EEPROM的每页大小为1K Byte,RAM的每页大小为4K Byte,FLASH的每页大小为16K Byte。因此XS128中EEPROM的页数为8K/1K = 8页,RAM的页数为8K/4K = 2页,Flash的页数为128K/16K = 8页。 图一

图二

在单片普通模式中,复位后,所有内存资源的映射如图二所示,其中从0x0000-0x07FF的2K范围内映射为寄存器区,如I/O端口寄存器等,当然寄存器没有那么多,后面的一部分其实没有使用;

从0x0800-0x0BFF,共1K的空间,映射为EEPROM区,由上面的分析,XS128中共有8页的共8K的EEPROM,所以这8页的EEPROM都是以分页的形式出现的,可以通过设置寄存器EPAGE选择不同的页并进行访问;

从0x0C00到0x0FFF的1K空间为保留区(其实这里面也有学问,以后探讨);

从0x1000到0x3FFF的12K空间为RAM区,分为三页,但是和前面所说的EEPROM不同,这三页中有2页(对于XS128和XS256)或一页(对于XS64)为固定页,位于12K空间的后一部分,以XS128为例,其内部的RAM资源为8K,所以其三页中的最后两页(0x2000-0x3FFF)为固定页,第一页(0x1000-0x1FFF)为窗口区,通过设置寄存器RPAGE来映射其他分页的RAM,当然在单片普通模式下,XS128内部已经没有其他的RAM了,所以这一页其实也没有用。但是对于XS256,这一页是有用的,因为它总共有12K的RAM。但是,在单片普通模式下,即没有外扩RAM的情况下,用户是不用刻意的去配置RPAGE的,因为复位的时候,已经默认指向那一页的RAM。

从0x4000-0xFFFF的总共48K的空间为Flash区,分为三页。其中第一页和第三页为固定的Flash页,中间的一页(0x8000-0xBFFF)为窗口区,通过设置PPAGE寄存器,可以映射到其他的分页Flash。

在最后的一页固定的Flash区域中的最后256字节中,保存的是中断向量。

对于RAM和Flash来说,其实固定页和其他的分页资源是统一编址的,不同的是固定页不可以通过寄存器(RPAGE、PPAGE)改变映射,而其他的页必须通过寄存器的设置来选择映射不同的页。

codewarrior中的prm文件

网上广泛流传的一篇文章讲述的是8位飞思卡尔单片机的内存映射,这几天,研究了一下Codewarrior 5.0 prm文件,基于16位单片机MC9S12XS128,一点心得,和大家分享。有什么错误请指正。 正文:

关于Codewarrior中的 .prm文件

要讨论单片机的地址映射,就必须要接触.prm文件,本篇的讨论基于Codewarrior 5.0 编译器,单片机采用MC9S12XS128。

通过项目模板建立的新项目中都有一个名字为“project.prm”的文件,位于Project Settings->Linker Files文件夹下。一个标准的基于XS128的.prm文件起始内容如下:

.prm文件范例:

NAMES END

SEGMENTS

RAM = READ_WRITE DATA_NEAR 0x2000 TO 0x3FFF;

ROM_4000 = READ_ONLY DATA_NEAR IBCC_NEAR 0x4000 TO 0x7FFF; ROM_C000 = READ_ONLY DATA_NEAR IBCC_NEAR 0xC000 TO 0xFEFF;

//OSVECTORS = READ_ONLY 0xFF10 TO 0xFFFF;

EEPROM_00 = READ_ONLY DATA_FAR IBCC_FAR 0x000800 TO 0x000BFF; EEPROM_01 = READ_ONLY DATA_FAR IBCC_FAR 0x010800 TO 0x010BFF; EEPROM_02 = READ_ONLY DATA_FAR IBCC_FAR 0x020800 TO 0x020BFF; EEPROM_03 = READ_ONLY DATA_FAR IBCC_FAR 0x030800 TO 0x030BFF; EEPROM_04 = READ_ONLY DATA_FAR IBCC_FAR 0x040800 TO 0x040BFF; EEPROM_05 = READ_ONLY DATA_FAR IBCC_FAR 0x050800 TO 0x050BFF; EEPROM_06 = READ_ONLY DATA_FAR IBCC_FAR 0x060800 TO 0x060BFF; EEPROM_07 = READ_ONLY DATA_FAR IBCC_FAR 0x070800 TO 0x070BFF;

PAGE_F8 = READ_ONLY DATA_FAR IBCC_FAR 0xF88000 TO 0xF8BFFF; PAGE_F9 = READ_ONLY DATA_FAR IBCC_FAR 0xF98000 TO 0xF9BFFF; PAGE_FA = READ_ONLY DATA_FAR IBCC_FAR 0xFA8000 TO 0xFABFFF; PAGE_FB = READ_ONLY DATA_FAR IBCC_FAR 0xFB8000 TO 0xFBBFFF; PAGE_FC = READ_ONLY DATA_FAR IBCC_FAR 0xFC8000 TO 0xFCBFFF;

PAGE_FE = READ_ONLY DATA_FAR IBCC_FAR 0xFE8000 TO 0xFEBFFF; END

PLACEMENT

_PRESTART, STARTUP, ROM_VAR, STRINGS,

VIRTUAL_TABLE_SEGMENT, //.ostext,

DEFAULT_ROM, NON_BANKED, COPY

INTO ROM_C000 ;

OTHER_ROM INTO PAGE_FE, PAGE_FC, PAGE_FB, PAGE_FA, PAGE_F9, PAGE_F8;

//.stackstart, SSTACK, //.stackend, PAGED_RAM,

DEFAULT_RAM INTO RAM;

DISTRIBUTE DISTRIBUTE_INTO

ROM_4000, PAGE_FE, PAGE_FC, PAGE_FB, PAGE_FA, PAGE_F9, PAGE_F8; CONST_DISTRIBUTE DISTRIBUTE_INTO

ROM_4000, PAGE_FE, PAGE_FC, PAGE_FB, PAGE_FA, PAGE_F9, PAGE_F8; DATA_DISTRIBUTE DISTRIBUTE_INTO RAM;

//.vectors INTO OSVECTORS;

联系客服:779662525#qq.com(#替换为@) 苏ICP备20003344号-4