历史上的今天
返回首页

历史上的今天

今天是:2025年08月12日(星期二)

正在发生

2021年08月12日 | HC9S12X 定义及访问直接寻址区

2021-08-12 来源:eefocus

从官方文档TN238中,我们知道了HC9S12X微控制器有直接寻址区这个概念,并且由它的示例得知访问直接寻址区的变量只需要一个字节的地址;嗯,比常用的扩展寻址区省了一个字节,很不错的特性,但是它并没有说清楚定义并访问直接寻址区的整个步骤。


后来,发现自带的代码示例里有DirectData这个示例工程,哇,赶快开始学习。使用示例工程的时候十分成功,但是当想在自己的代码上使用直接寻址区的变量时就出问题了,只要uCOS-II一切换任务,程序就直接跑飞。搞了我好久。好在终于明白怎么回事了。来给大家分享下学习成果。


定义变量到直接寻址区


基础知识

我们知道S12X单片机是16位单片机,正常访问内存地址的时候需要使用16位地址。但是访问直接寻址区(或说,使用直接寻址模式)时却只需要8位地址,那另外8位哪去了呢?其实另外(高)8位是由DIRECT寄存器控制的,比如现在DIRECT寄存器中的值是0x30,然后你访问0x34处的变量其实就是在访问0x3034。


修改prm文件

从另一个角度来看,因为直接寻址只用到了8位地址,所以必须得把所有要直接寻址的变量都定义在某个0xXX00-0xXXFF地址内,只可以少不可以多。为了实现这一步,需要修改prm文件。


下面假设我要把直接寻址区定在0x2000-0x20FF。


打开prm文件,把原来的:


SEGMENTS

...

      RAM           = READ_WRITE  DATA_NEAR            0x2000 TO   0x3FFF;

...

END

PLACEMENT

...

END


修改为:


SEGMENTS

...

      RAM_DIRECT    = READ_WRITE  DATA_NEAR            0x2000 TO   0x20FF;

      RAM           = READ_WRITE  DATA_NEAR            0x2100 TO   0x3FFF;

...

END

PLACEMENT

...

      DIRECT_DATA       INTO  RAM_DIRECT;

...

END


数据定义和声明

对所有要定义在直接寻址区的变量:

像这样进行定义:


#pragma DATA_SEG __SHORT_SEG DIRECT_DATA

int oftenUsed1, oftenUsed2, oftenUsed3; /* these variables are accessed with 8-bit addresses */


int oftenUsed[10] = {

  0,1,2,3,4,5,6,7,8,9

};

#pragma DATA_SEG DEFAULT


像这样进行声明:


#pragma DATA_SEG __SHORT_SEG DIRECT_DATA

extern int oftenUsed1, oftenUsed2, oftenUsed3; 

extern int oftenUsed[];

#pragma DATA_SEG DEFAULT


这样链接器就知道要把这些变量放到DIRECT_DATA这个segment中。编译器就会考虑用直接寻址的方式访问它们。


注意:

对于所有要使用这变量的代码,一定要让它见到(比如include包含这个声明的头文件)以上形式(主要是#pragma语句)的定义或者声明,否则它不会知道这个变量在直接寻址区,也不会进行对应优化。


访问直接寻址区的变量

配置编译器

首先要配置编译器,让编译器知道你使用了DIRECT寄存器,以及知道DIRECT寄存器的值,这样编译器才知道怎么优化及产生正确的代码。


菜单栏 Edit->XXXX Settings… 或 Alt + F7 打开配置窗体。

选择Target->Compiler for HC12。添加命令行选项-CpDirect8192或者-CpDirect0x2000。

这句是让编译器知道直接寻址区定义在了0x2000上,同时也定义了宏。

注意:

如果用到了汇编代码,在Target->Assembler for HC12里最好也添加命令行选项-CpDirect8192或-CpDirect0x2000。


修改DIRECT寄存器的值

尽可能早地,起码在用到直接寻址区之前(比如main函数的一开始),修改DIRECT寄存器的值为你配置的地方对应的值,这个只能手动改,编译器不会帮忙添加这段代码。


  DIRECT = __DIRECT_ADR__ >> 8;   /* initialize the DIRECT register. This value matches 

                                     the value specified on the command line of the Compiler 

                                     (e.g. 0x20 for -CpDIRECT0x2000) */


这样产生的代码才能正确的访问直接寻址区。


生成的访问代码

访问直接寻址区的代码没什么特别的,就和访问扩展寻址区的一样;区别是生成的代码。


  ...

   52:      oftenUsed1 = oftenUsed1 + 2*oftenUsed2 +3*oftenUsed3;

  0003 dc00         [3]     LDD   oftenUsed2

  0005 59           [1]     LSLD  

  0006 d300         [3]     ADDD  oftenUsed1

  0008 b745         [1]     TFR   D,X

  000a dc00         [3]     LDD   oftenUsed3

  000c cd0003       [2]     LDY   #3

  000f 13           [1]     EMUL  

  0010 1ae6         [2]     LEAX  D,X

  0012 5e00         [2]     STX   oftenUsed1

  ...

   64:      normalUsed1 = normalUsed1 + 2*normalUsed2 +3*normalUsed3;

  002f fc0000       [3]     LDD   normalUsed2

  0032 59           [1]     LSLD  

  0033 f30000       [3]     ADDD  normalUsed1

  0036 b745         [1]     TFR   D,X

  0038 fc0000       [3]     LDD   normalUsed3

  003b cd0003       [2]     LDY   #3

  003e 13           [1]     EMUL  

  003f 1ae6         [2]     LEAX  D,X

  0041 7e0000       [3]     STX   normalUsed1

  ...


可以看出,每次访问直接寻址区都比访问扩展寻址区的变量少产生1字节代码。


另外,直接寻址区的数组如果使用变量系数,则没有任何优化。


   ...

   31:    oftenUsed1 = oftenUsed[i];     /* -> thereis no gain to access arrays in the direct page range with variable index     */

  0009 ee80         [3]     LDX   0,SP

  000b 1848         [2]     LSLX  

  000d ece20000     [4]     LDD   oftenUsed,X

  0011 5c00         [2]     STD   oftenUsed1

  ...

   39:    nornalUsed1 = nornalUsed[i];  /* above                                           */

  000d ee80         [3]     LDX   0,SP

  000f 1848         [2]     LSLX  

  0011 ece20000     [4]     LDD   nornalUsed,X

  0015 7c0000       [3]     STD   nornalUsed1

  ...


但是如果是使用常量系数的话,就能得到优化


  ...

   56:    oftenUsed[3] = 10;     /* howerver, with a constant index, arrays accesses can be optimized too   */

  0024 c60a         [1]     LDAB  #10

  0026 87           [1]     CLRA  

  0027 5c00         [2]     STD   oftenUsed:6

  ...

   68:    nornalUsed[3] = 10;   

  0054 c60a         [1]     LDAB  #10

  0056 87           [1]     CLRA  

  0057 7c0000       [3]     STD   nornalUsed:6

  ...


注意事项

① 可能有聪明的小朋友想到,可以使用DIRECT寄存器和直接访问模式配合的方式来寻址,这样如果需要成片成片访问地址时就可以增加效率了!但是这有个问题,芯片手册中(198页)提到,DIRECT寄存器在特殊模式下可以任意写,但是在其他模式下只能写一次。所以可能你在BDM调试时没有问题,但是正常运行时却出问题。当然,这条我没有进行验证,感兴趣的朋友可以试试。


② DIRECT寄存器必须由用户代码来初始化。自动生成的代码不初始化DIRECT寄存器。


③ 虽然这里是以 RAM存储器变量 作为例子,但实际上直接寻址区可以定义在整个逻辑地址的任意地方,如寄存器区、EEPROM、RAM、D-flash、P-flash。


④ 前面说到我在uCOS-II中使用直接寻址区时程序会跑飞。

最后发现原因就是因为没有给汇编器添加命令行选项-CpDirect8192。


而uCOS-II有一个汇编文件 os_cpu_a.s,其中有很多负责出栈入栈PPAGE、RPAGE、EPAGE和GPAGE的代码。如:


    pula                               ; Get value of PPAGE register

    staa   PPAGE                       ; Store into CPU's PPAGE register                                


    pula                               ; Get value of RPAGE register

    staa   RPAGE                       ; Store into CPU's RPAGE register                                


    pula                               ; Get value of EPAGE register

    staa   EPAGE                       ; Store into CPU's EPAGE register                                


    pula                               ; Get value of GPAGE register

    staa   GPAGE                       ; Store into CPU's GPAGE register   


在默认情况下,汇编器会将其优化,生成的代码是(以PPAGE为例,其他类似):


  122  122   000016 32              pula                               ; Get value of PPAGE register

  123  123   000017 5A15            staa   PPAGE                       ; Store into CPU's PPAGE register   


这是使用了直接寻址的方式来进行访问,因为汇编器认为我们没用到DIRECT寄存器,所以认为其值为默认的0,所以就优化为了使用直接寻址的方式访问PPAGE寄存器(地址为0x0015)。但是由于我已经把DIRECT寄存器设置为了0x20,这样就变成实际访问的是0x2015,结果就出问题跑飞了。


为了生成正确的程序,一种方式是按如上所述添加命令行选项,让汇编器意识到现在DIRECT寄存器的值是0x20,这样就不会进行这种优化。另外一种是把所有XPAGE寄存器前面都加个 ‘>’ ,这样就可以强制使用扩展寻址了:


    pula                               ; Get value of PPAGE register

    staa   >PPAGE                      ; Store into CPU's PPAGE register     


用任一方法后,生成的代码就变成了:


  122  122   000016 32              pula                               ; Get value of PPAGE register

推荐阅读

史海拾趣

Hong Kong X'Tals Ltd公司的发展小趣事
在必要时,可以加入保护电路(如过流保护、过压保护等),以提高电路的可靠性和安全性。
Clever Little Box公司的发展小趣事

Clever Little Box深知,优质的客户服务是企业长期发展的关键。因此,公司始终注重提升服务质量,为客户提供专业的技术支持和售后服务。同时,公司还注重与客户建立良好的关系,通过定期沟通、反馈收集等方式,了解客户的需求和意见,以便更好地满足客户的期望。

Anritsu公司的发展小趣事

Clever Little Box深知,优质的客户服务是企业长期发展的关键。因此,公司始终注重提升服务质量,为客户提供专业的技术支持和售后服务。同时,公司还注重与客户建立良好的关系,通过定期沟通、反馈收集等方式,了解客户的需求和意见,以便更好地满足客户的期望。

Bce Sud公司的发展小趣事

随着公司规模的扩大和市场份额的提升,Bce Sud开始实施国际化战略。公司先后在多个国家和地区设立了研发中心和销售网络,进一步扩大了市场份额。通过与国际知名企业的合作与交流,Bce Sud不断提升自身的技术水平和国际竞争力。

思博科技(Cybermax)公司的发展小趣事

随着市场竞争的加剧,思博科技意识到只有不断创新才能在市场中立足。于是,公司加大了研发投入,不断推出具有创新性的产品。其中,一款名为“MaxPower”的高效能电源芯片在市场上引起了广泛关注。这款芯片不仅性能卓越,而且具有极高的能效比,为客户节省了大量能源成本。这一创新产品的成功推出,使思博科技在行业中树立了良好的口碑。

Global Communications公司的发展小趣事
温度传感器的输出与温度之间的线性关系也很重要,因为这直接影响到补偿电路的准确性和稳定性。

问答坊 | AI 解惑

北京青云创新公司招聘研发工程师

岗位职责: 1、承担FPGA液晶驱动板及图形卡的设计及技术更改任务,负责所设计产品技术文件资料的整理归档工作; 2、负责对所设计产品的材料加工、采购技术资料的确认,协助解决产品在生产过程中出现的问题; 任职要求: 1、熟练掌握FPGA/CP ...…

查看全部问答>

汽车电子范围太大,我来发个好玩的。

如果有一辆车:前面看象奔驰,后面看象宝马;这一定是吉利。           如果有一辆车:样子一直没变,但名称一直在改;这一定是桑塔那。           如果有一辆车:三厢和二厢卖一 ...…

查看全部问答>

s3c2440_NorFlash启动 代码

哪位同仁能提供一份s3c2440从Norflash启动的Bootload代码啊,网上的Bootload代码铺天盖地啊,不够都是Nandflash启动滴!最好是Ads编译环境下的啊,给个下载的链结地址就行了!…

查看全部问答>

RS485通讯

要和电机通讯,电机有几个,连在一起和电脑有一个接口,接口是RS485,那边人告诉我格式是这样, (1位起始+8位数据+1位数据/地址标识符+1位结束) 我原来做的东西,都是设置下MSCOMM控件的属性,比如9600,n,8,1,然后发送8位的数据就可以。 那个 ...…

查看全部问答>

恳求WinCE.Net下ASP调用文本文件方法

求WinCE.Net下ASP页面调用文本文件方法。 小弟已试过在WinCE.Net ASP页面中不能创建Scripting.FileSystemObject对象和ADODB.Stream对象,请问各位大侠还有没有别的方法在ASP中调用文本文件?先谢过了…

查看全部问答>

请教一个时序约束?

这个时序一直不好约束,上升和下降沿都约束了,但还是有问题?请问大家这个在DC里怎么约束比较好?这个是8051里面的一个输出信号,不是自己设计的…

查看全部问答>

VCA810 没有输出波形,求助求助。

大家好: 我在做上面这个电路,我是用面包板接的,Vin 输入一个 500 mVp-p,Vc 用一个 VR 调整电压,可是输出电压都是 0V,试了 3 颗样片结果都一样,不知道问题到底在哪里? 请问有人用过 VCA810 吗?能否给我一些指导,谢谢。 上面那个图 ...…

查看全部问答>

zigbee好学吗?

zigbee好学吗?协议栈之类的复杂吗?…

查看全部问答>

IIC接口技术与24C02在瑞萨RL78/G13中的开发笔记整理

本帖最后由 ohy3686 于 2016-4-9 14:50 编辑 IIC接口技术与24C02在瑞萨RL78/G13中的开发笔记整理 广东职业技术学院  欧浩源1.IIC总线概述     IIC总线全称:Inter-Integrated Circuit,是由飞利浦公司开发出来的一种串行总 ...…

查看全部问答>