打印
[Kinetis]

简单**飞思卡尔HCS12系列Flash空间限制

[复制链接]
2495|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
vigous1|  楼主 | 2015-3-20 22:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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


相关帖子

沙发
vigous1|  楼主 | 2015-3-20 22:49 | 只看该作者

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


使用特权

评论回复
板凳
vigous1|  楼主 | 2015-3-20 22:49 | 只看该作者

(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模式。


使用特权

评论回复
地板
vigous1|  楼主 | 2015-3-20 22:49 | 只看该作者

(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会溢出编译错误的问题。


使用特权

评论回复
5
vigous1|  楼主 | 2015-3-20 22:50 | 只看该作者

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

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

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

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

    到这里,简单**Flash空间限制就OK了,建议在网上找找讲解prm文件的**,毕竟我这里只是针对性的讲重点部分了。其实到最后只要按照第四步的方法简单改好了就行了


使用特权

评论回复
6
W_yk| | 2015-3-27 15:31 | 只看该作者
哈哈哈!以前也是参加飞思卡尔智能车的。。。

使用特权

评论回复
7
FSL_TICS_ZJJ| | 2015-4-10 14:44 | 只看该作者
非常感谢你关于Kinetis的经验分享 !

使用特权

评论回复
8
yuan58064313| | 2016-2-18 15:21 | 只看该作者
请问您上面所描述的:通过CALL来调用非固定页中的函数。如果的汇编上,直接使用SECTION是不是不行。我在PRM文件中定义了:
MYROM INTO PAGE_38

在汇编中:
MYROM: SECTION

func:
   

使用特权

评论回复
9
yuan58064313| | 2016-2-18 15:23 | 只看该作者

我指的是c中的#pragma CODE_SEG
在汇编中,call addr #0x38出现A12102错误。

使用特权

评论回复
10
谢谢谢林达| | 2017-9-18 21:06 | 只看该作者
楼主,我 想请教一下,比如我想把一段函数分配到PAGE_FC这个段里边,我应该怎么写呢?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

88

主题

427

帖子

15

粉丝