jicheng0622

【原创】写在圣诞节之简单破解飞思卡尔HCS12系列Flash空间限制

0
阅读(34409)

    这么好的天气,好好的圣诞节没有人陪只能宅在实验室了,所以也就有了本篇的故事(汗,孤独的人啊,呵呵)。。。

    说是破解Flash空间限制,其实更准确的说应该是深度挖掘才对,因为这个不是CW对我们的限制,只不过是我们平时没有关注罢了(限于初手),所以这里我就用“简单”两字来形容了,哈哈~其实遇到这个问题也是我在今年指导小弟们的智能车比赛时遇到的,提起这个我不得不汗颜一下,毕竟我当年做智能车的时候也没把代码写超了啊,嘿嘿,没想到这帮“孩子们”还真写了这么多(16kCode,一万行的代码啊,虽然是我们一代代的积累,不过还颇有长江后浪推前浪的赶脚了),所以俺们今年的这个特等奖也不是白给的是吧,哈哈。

    Code超过了16k也就遇到了本篇的主题了,这个时候就会遇到编译器的错误提示了,提示代码空间不够用。可能第一直觉会想到,128k啊会不够用吗(用的xs128,做过智能车的都懂的),随即我就想到了问题的所在,那就是出在系统默认的内存映射上了,当年为了尽可能快的提高程序执行效率和速率,我建工程的时候选择了Small模式,在这个模式下,系统是默认只提供不足16k的代码空间的,这一点可能没遇到这个问题的人很少去关注它。下面我就以HCS12系列的MC9S12DG128为例(跟XS128内存分配是一样的)开始破解这个问题:

(1)建立工程,前几步默认就行,然后选择Small模式,其实如果选择Banked(即分页模式)就不会出现问题了,不过当时为了代码的执行效率我毅然决然的选择了Small模式,结果还真给了我机会去解决接下来的问题了,哎,自己找事么这不是。至于为什么Small模式下代码执行效率高,下面随着分析的深入会揭晓的。

(2)分析下HCS12这三种内存配置模式,即Small,Banked,Large。

Small模式:默认的完整的16位地址寻址空间,即64k,注意这64k不单单是Flash,因为HCS12是数据存储器和程序存储器统一编址的;

Banked模式:默认代码为分页地址的,即代码是存到分页Flash区的;

Large模式:默认数据和代码都是分页寻址的;

    那么上面提到为什么在Small模式下代码执行效率最快呢,那就是因为在Small模式下所有函数调用都是Near;在Banked模式下函数为Far,数据可以为Near或者Far;large模式下,都为Far。而Near函数是通过JSR或者BSR调用的,Far是通过Call调用的,这样他们的执行效率自然是前者高了,这也是我为什么当初建立工程是选择了Small模式的原因。另外还有一个原因,那就是部分中断服务函数是不能放到分页区的,所以在Banked模式下,就需要预编译指令#pragma CODE_SEG重新分配其中断服务函数到非分页区了,怪麻烦的,懒惯了,所以选择了Small模式。

(3)这步就是关键所在了,分析代码不是本篇的重点,本篇的重点是深度挖掘其内存分配,所以就需要查看CW工程的.prm文件了,该文件可以在左侧工程窗口的Project Settings->Linker Files->“工程名”.prm,下面还是上图了,呵呵:

    上图就是prm文件的内容了,这里就捡重点的来了,其中ROM_C000、ROM_4000和DEFAULT_ROM这三个关键词是要说的重点。ROM_C000(该区不满16k,抽出0xFF00~0xFFFF这一段为中断向量区)和ROM_4000这两个为HCS12的64K寻址空间的固定Flash区,在这两个区的函数是Near寻址的,也是Small模式的使用区;而在主程序里,如果不加#pragmatic CODE_SEG声明,主程序的代码是默认放到DEFAULT_ROM这个段里的。而从上面的文件里可以看到DEFAULT_ROM这个段是被系统默认分配到ROM_C000这个地址空间里的(ROM_4000默认被注释掉了),所以就看出问题所在了吧,也就是默认的DEFAULT_ROM大小最大也不会超过ROM_C000的空间16k大小,更何况ROM_C000空间里还不单独只有DEFAULT_ROM这一个段来,所以也就会出现代码超过16k会溢出编译错误的问题。

(4)上面已经找到问题所在了,那么接下来就要给出其解决办法,这里我总结了三种办法:

    第一种,也是最简单的一种,也是我推荐的一种,那就是把ROM_4000左右的"*/"和"*/"这两个注释符去掉,让那几个段包括DEFAULT_ROM平均分配到这两个空间里,也就是地址空间增大到了32K左右,这样就基本满足要求了;

    第二种,就是通过#pragma CODE_SEG可以把部分函数放到OTHER_ROM段里以分担一部分代码空间的需求,从上面文件可以看到这个段是属于分页Flash区的,可以考虑把一些执行效率要求不高的函数放到该段里。

    第三种,那就是我最最上面提到的选择内存模式时直接选到Banked模式下就没这个问题了,不过我不爱用罢了,呵呵,但也是一种好的方式,下面是Banked模式下prm文件内容,它默认吧DEFAULT_ROM段放到分页Flash区了,所以就不会出现代码限制了。

    到这里,简单破解Flash空间限制就OK了,建议在网上找找讲解prm文件的文章,毕竟我这里只是针对性的讲重点部分了。其实到最后只要按照第四步的方法简单改好了就行了,至于为什么还要啰嗦了上面一堆东西,那就是我一直坚持授之以“渔”的原则,还有就是上面毕竟是我一家之言啊,难免有不妥之处,还是希望能仔细看完这篇的广大网友不吝赐教和改正(群众的眼光是雪亮的啊),多交流很重要,感激不已啊,呵呵~

    天还没黑,趁这会儿功夫还是出去逛逛吧,圣诞节不能白过了不是,哈哈,未完待续~