HCS12X–数据定义(如何在CodeWarrior中将数据定义到分页区)
来源:互联网 发布:软件著作权独占许可 编辑:程序博客网 时间:2024/05/23 12:40
由于在暑假匆忙接收的嵌入式项目中需要使用特别大的数组,非分页RAM的内存不够用了,没办法,硬着头皮尝试使用分页RAM,但是完全没有单片机的基础,导致极其的困难。之前写程序都是按照纯软件的思维,主要考虑架构,不会考虑到每个变量具体存在哪个物理地址这么底层的问题,结果被飞思卡尔这分页地址、prm文件什么的搞得一头雾水,而网上的资料又少,讲的又大同小异的笼统,最后写出来的程序因为这分页地址的原因存在各种问题(还以为把变量放到分页RAM了,结果现在稍微懂了点回去看,发现其实很多根本还是分配在非分页区。晕倒~。但是居然还能相对正常运行也是很神奇)。这些天各种找相关的资料,结果发现在CodeWarrior的官方文档资料里其实把我想知道的都讲的很清楚了(还是官方文档给力,以后学什么东西直接找官方文档,不去到处找网上一堆零零散散的资源来学了)。本着学习的态度,将逐步把官方文档翻译一遍,供大家一起交流学习进步。
翻译的资料是公开的,我想应该不会有什么版权问题,如涉及版权问题,请联系我删除文章,原文档在这里(https://www.nxp.com/pages/codewarrior-development-studio-for-hcs12x-microcontrollers-classic-ide-v5.2:CW-HCS12X?&tab=Documentation_Tab&linkline=Users-Guides),另感谢NXP提供的学习资料。
另外,本人有另一篇详解怎么定义及访问直接寻址区的博文
http://blog.csdn.net/lin_strong/article/details/78535785
HCS12X – 数据定义
译者注:译者博客(http://blog.csdn.net/lin_strong),转载请保留这条。此为官方文档TN238,仅供学习交流使用,请勿用于商业用途。
这个文档描述了程序员要怎么样帮助HCS12X编译器来产生在数据访问上更加优化的代码。我们将讨论以下主题:
- 分配在直接寻址区的变量
- 分配在扩展寻址区的变量
- 分配在banked寻址区的变量 — 使用逻辑寻址
- 分配在banked寻址区的变量 — 使用全局寻址
- Banked常量分配
- 逻辑地址 vs. 全局地址
对于以上举例的每个变量类型,我们都会描述:
- 怎么定义一个变量
- 怎么声明一个变量
- 生成来分为这变量的代码
- 怎么定义一个指向这样一个变量的指针
- 生成来访问指针和其指向的变量的代码
- PRM文件中的位置
- 注意1:
- 这篇技术文档中描述的信息适用于SMALL(-Ms)以及BANKED(-Mb)地址模型。而不适用于LARGE(-Ml)地址模型。
- 注意2 :
- 对于少于32Kb代码的应用,我们通常推荐使用SMALL地址模型,或者使用BANKED地址模型。我们不推荐使用LARGE地址模型。
分配在直接寻址区的变量
为了使编译器将某个变量分配到直接寻址页,你必须定义(以及声明)它到个特别的segment中,这segment带有属性__SHORT_SEG。
- 定义&访问直接寻址区的数据
1 像这样进行变量定义:
- 1
- 2
- 3
2 像这样进行变量声明:
- 1
- 2
- 3
3 对这变量的访问会生成如下代码:
- 1
- 2
- 3
4 没有用于访问直接寻址页变量的特殊指针类型。一个指向这样一个变量的指针将像这样定义:
- 1
5 初始化和访问被指向的对象会产生如下代码:
- 1
- 2
- 3
- 4
6 对于定义在__SHORT_SEG section的变量,PRM文件中的SEGMENT和PLACEMENT是这样子的:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 注意:
- 包含通过直接寻址模式访问的变量的section,应该被分配在用逻辑地址定义的segment中
配置直接寻址区
在HCS12X上,直接寻址页可以移动,并且不是硬编码到0x00..0xFF(HCS12上是硬编码到这的)。编译器需要进行特别的设置来支持这一特性。
- 如果DIRECT寄存器包含任何东西但是默认值是0(译者注:意思是存在DIRECT寄存器?),编译器和汇编器就要启用-CpDirect选项,其后跟着可直接访问区的起始地址。比如:如果DIRECT初始化为0x20,那么直接访问窗口就是从0x2000到0x20FF,编译器和汇编器选项就是-CpDirect0x2000。编译器和汇编器都要加上这个选项。
- DIRECT寄存器必须由用户代码来初始化。默认的启动代码不初始化DIRECT。
- 在prm文件中,section MyShortData要被分配到这个区域(在上例中是从0x2000到0x20FF)。
- 小心,不正确地分配直接访问section(也就是说MyShortData没有被正确地分配)不会产生链接器诊断消息。
对于HCS12,链接器会报告一个fixup溢出。但是对于HCS12X却无法做到这一点,因为直接访问页可以被映射。
分配在扩展寻址区的变量
为了使编译器将某个变量分配到扩展地址空间,你只需要用普通的方式定义(并声明)它。
1 像这样进行变量定义:
- 1
2 像这样进行变量声明:
- 1
3 对这变量的访问会生成如下代码:
- 1
- 2
- 3
4 指向这个变量的指针可以像这样定义:
- 1
5 初始化和访问被指向的对象会产生如下代码:
- 1
- 2
- 3
- 4
6 这种方式定义的变量被分配在预定义section DEFAULT_RAM中。在PRM文件中,这个section的SEGMENT和PLACEMENT定义是这样子的:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 注意:
- 包含使用扩展寻址模式定义的变量的Section应该被分配在使用逻辑地址定义的segment中。
分配在Banked寻址区的变量
分配在banked RAM中的变量可以使用以下来访问:
- 逻辑地址(使用RPAGE) 或
- 全局地址
使用逻辑地址
为了告诉编译器你想要使用一个变量的逻辑地址来访问它,你得使用如下语法:
1 像这样进行变量定义:
- 1
- 2
- 3
2 像这样进行变量声明:
- 1
- 2
- 3
3 对这变量的访问会生成如下代码:
- 1
- 2
- 3
- 4
- 5
4 指向这个变量的指针可以像这样定义:
- 1
5 初始化和访问被指向的对象会产生如下代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
6 对于定义在RPAGE section中的变量,对应PRM文件中的SEGMENT和PLACEMENT是这样子的:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 注意:
- 包含通过逻辑寻址模式访问的变量的section,应该被分配在用逻辑地址定义的segment中
- 注意:
- 分配在RPAGE segment中的变量也可以通过使用far指针来访问,
- unsigned char * __far ptr_on_far_var;
- 在这种情况下,将会使用全局寻址模式来访问指向的对象
使用全局地址
使用全局地址的主要原因是因为一个对象可能没法装进单页的逻辑地址中去。通过使用全局地址访问对象,就绕开了这个制约,对象就可以大到所有可用的内存大小或可访问的64KB。
全局地址指针可以用于任何对象,对象不受到任何特殊限制。
为了告诉编译器你想要访问一个使用全局地址的变量,你要使用以下语法:
1 像这样进行变量定义:
- 1
- 2
- 3
2 像这样进行变量声明:
- 1
- 2
- 3
3 对这变量的访问会生成如下代码:
- 1
- 2
- 3
- 4
- 5
4 指向这个变量的指针可以像这样定义:
- 1
5 初始化和访问被指向的对象会产生如下代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
6 对于定义在 GPAGE section中的变量,对应PRM文件中的SEGMENT和PLACEMENT是这样子的:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 注意:
- 包含通过全局寻址模式访问的变量的section可以被分配在使用逻辑或全局地址定义的segment中。所以PRM文件也可以看起来像这样:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
分页常量分配
常量可以被分配在banked EEPROM或者在banked FLASH中,并且可以通过以下来访问:
- EEPROM(使用EPAGE)中的逻辑地址 或
- FLASH(使用PPAGE)中的逻辑地址 或
- 全局地址
在EEPROM中使用逻辑地址
为了告知编译器你想要使用一个常量在EEPROM中的逻辑地址访问它,你得使用如下语法:
1 像这样进行常量定义:
- 1
- 2
- 3
2 像这样进行常量声明:
- 1
- 2
- 3
3 指向这个变量的指针可以像这样定义:
- 1
- 注意:
- 分配在一个EPAGE segment的常量还可以使用far指针来访问。
- const unsigned char *__far ptr_on_far_const;
- 这种情况下,会使用全局寻址模式来访问指向的对象
在FLASH中使用逻辑地址
编译器只支持那些分配在非分页区的代码在FLASH中使用逻辑地址来寻址。因为通常不会这样做,我们推荐为所有在FLASH中的数据对象使用全局地址。
为了实现使用逻辑地址,要使用segment qualifier __PPAGE_SEG 和pointer
qualifier __pptr。
使用全局地址
1 像这样进行常量定义:
- 1
- 2
- 3
2 像这样进行常量声明:
- 1
- 2
- 3
3 指向这个变量的指针可以像这样定义:
- 1
逻辑地址 vs 全局地址
- 对于那些大小不大于4K(Banked RAM窗口的大小)的变量,使用逻辑地址比使用全局地址更有效率。
- 如果一个变量的大小大于4K,连接器将不得不把它分配地横跨bank的边界。这种情况下,我们推荐使用全局寻址来访问这个变量
- 我们推荐使用全局寻址模式来访问分配在FLASH中的常量或字符串常量
- 我们推荐为所有那些在运行时使用逻辑地址的对象使用逻辑寻址。包括:栈,代码,直接寻址的变量,扩展寻址区的变量,I/O寄存器。
- 为了定义个分页的变量,一定要使用DATA_SEG pragma。不要试图使用 __far关键字来干这件事。far关键字指定了编译器应该怎么访问一个变量,但它不会影响变量被分配的方式。
- HCS12X–数据定义(如何在CodeWarrior中将数据定义到分页区)
- HCS12X–数据定义(如何在CodeWarrior中将数据定义到分页区)
- HCS12X–数据访问(如何在CodeWarrior中转换逻辑地址与全局地址)
- 数据定义
- 如何在头文件中定义静态数据成员(消除重复定义)
- 如何在DELPHI中将EXCEL中的数据导入到SQL数据库
- 如何在 Azure 门户中将托管数据磁盘附加到 Windows VM
- static 数据成员必须在类定义的外部定义
- js中如何定义json数据
- WebService推送数据,数据结构应该如何定义?
- 怎样在不同平台间定义数据
- 如何提高C#中将数据导入到Excel的性能
- 如何利用python从mysql中将数据导出到excel
- mysql学习笔记六(数据定义表约束,分页)
- 所处理的数据在什么地方 有多长 如何定义 如何寻找
- 在VBA中将不规则数据导出到Excel
- 在linux系统中将自己程序的日志输出到自己定义的文件
- 数据字典之定义
- Universal 2nd Factor (U2F) 概述(7)-FIDO协议支持廉价的U2F设备
- java之动态代理初探
- 栈和队列
- Apache-伪静态配置
- js使用animation
- HCS12X–数据定义(如何在CodeWarrior中将数据定义到分页区)
- tcp之backlog参数
- hadoop面试题整理
- mongodb创建数据库和配置用户
- MariaDB中文乱码字符集处理
- forward(转发)和redirect(重定向)的区别?
- 函数简单程序设计
- 双列集合(Map)
- C++中的static静态类 与::代表什么意思