历史上的今天
返回首页

历史上的今天

今天是:2024年10月28日(星期一)

正在发生

2021年10月28日 | C51和MDK的ROM大小及变量绝对地址初始化

2021-10-28 来源:eefocus

#1. C51的ROM大小

Keil编译完之后,显示的Program Size: data=9.0 xdata=8 const=15 code=180,则

The Total ROM(const + code + code-gap + const-gap) is 199BYTE

实际生成的bin文件大小:

这里写图片描述

在.MAP中的C O D E M E M O R Y 中

这里写图片描述

code-gap为0,cosnt-gap为4,则const + code + const-gap=15 + 180 + 4 = 199,刚好和实际生成的bin文件大小一致。

#2. C51的ROM大小优化

如果实际编译显示的const + code远小于实际的Bin文件,表明有非常大的空隙,需要优化。

优化空间,有几个查找方向:


.A51文件中的代码段起始地址CSEG AT 0xXX是否与Off-chip Code Memory设置的起始位置一致,如果不一致可能导致GAP。

函数及变量指定的绝对地址超出Off-chip Code Memory设置的范围。

interrupt vectors at adress: 0xXX设置的中断向量地址是否超出Off-chip Code Memory设置的范围。interrupt vectors at adress必须设置,因为Keil C51默认的是0x03,可能不在Off-chip Code Memory设置的范围内,导致GAP。

打开.MAP文件,搜索GAP,如果存在一些GAP,则可能是多个指定的绝对地址之间有GAP导致的,可以将绝对地址调整对齐。

因为xdata + const + code将占用整个Off-chip(1581为58KB),所以可以将一些const,code类型的变量转换成xdata。总之,根据这三者根据实际情况进行一个调整,总大小不超过58KB即可。有时ROM存放在EEPROM上,所以适当减少const+code的大小,一些变量转换成Xdata是一种方法。

#3. C51变量绝对地址定位及初始化

##3.1. 关键字_at_

int xdata nValA _at_ 0x1114;

int xdata nValA = 0x2222; // nValA绝对地址定位于x:0x1114,初始化值为0x2222


char code nValD _at_ 0xD2;

char code nValD = 0x22; // 此句无效,nValD绝对地址定位于c:0xD2,初始值为0


##3.2. LX51 Locate

当勾选Use Extended liker(LX51) instead of BL51时,即使用LX51 Locate。


LX 51 Locate->User Segments->?CO?MAIN(C:0xD2), ?XD?MAIN(x:0x1114)

LX51 Misc->use linker control file->edit->SEGMENTS (?CO?MAIN(C:0xD2), ?XD?MAIN(x:0x1114))

以上两种设置均可,推荐用前面一种更方便,且还能够添加REMOVEUNUSED等编译关键字。

?CO?MAIN和?XD?MAIN作为segment name,是以变量类型缩写+文件名大写组合而成,对此不熟练,可以打开生成的.MAP文件,查看MEMORY MAP OF MODULE区域的描述也可以找到


当指定了当前文件Segment所在,那么当前文件所有的全局变量,均会在指定的绝对地址之后顺序排列,并且可以对变量进行初始化。


int xdata nValA = 0x2222; // nValA绝对地址定位于x:0x1114,初始化值为0x2222

int xdata nValB = 0x1111; // nValB绝对地址定位于x:0x1116,初始化值为0x1111

char code nValD = 0x22;   // nValD绝对地址定位于c:0xD2,初始值为x22

char code nValD = 0x11;   // nValD绝对地址定位于c:0xD2,初始值为x11


##3.3. BL51 Locate

当不勾选Use Extended liker(LX51) instead of BL51时,即使用BX51 Locate。


BL 51 Locate->code->?CO?MAIN(0xD2)

BL 51 Locate->Xdata->?XD?MAIN(0x1114)

BL1 Misc->use linker control file->edit->CODE( 0X0000-0X0FFF , ?CO?MAIN(0XD2) ) XDATA( 0X1000-0X2FFF , ?XD?MAIN(0x1002) )

以上两种设置均可,推荐使用LX51,这是新的链接器,性能更好。

#4. MDK的ROM大小

此处主要是针对M0而言。Keil编译之后,在.MAP文件结尾会显示:

Code (inc. data) RO Data RW Data ZI Data Debug

26864 2124 1284 2040 26632 118060 Grand Totals

26864 2124 1284 72 26632 118060 ELF Image Totals (compressed)

26864 2124 1284 72 0 0 ROM Totals

===================================================================

Total RO Size (Code + RO Data) 28148 ( 27.49kB)

Total RW Size (RW Data + ZI Data) 28672 ( 28.00kB)

Total ROM Size (Code + RO Data + RW Data) 28220 ( 27.56kB)


Code,不仅包括生成的代码,还包括inline data, literal pools, and short strings。

RO Data,Read Only data,用const修饰的变量,或是地址定位到RO Data的变量。

ZI Data,Zero Initialie data,编译器进行0初始化的数据。所有未显示初始化,或是显式初始化为0的变量均是ZI Data(包括栈变量和堆变量)。

RW Data,Read Write Data,显式初始化为非0的全局变量。

Total Rom Size即是生成的bin文件大小。ROM Size所包含的RW Data为28220-28148=72,而不是2040。

实际的代码:

int nArr[500] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};


nArr作为RW Data,实际大小有2000B,那么为什么通过ROM计算出的RW Data只有72B呢?

首先,RW Data为什么要记录在ROM中呢?这是因为RW Data的初始化值是编译期生成的,所以这些初始化值要记录在ROM中,这样一上电就能够初始化。正因为只记录初始化的值,所以上面的nArr只初始化了10个值,其他未初始化的其实都没有放进ROM中。所以这才导致了两者的不同。


Total RW Size即运行时存放变量的RAM的大小。

#5. MDK的ROM优化


打开.MAP文件,找到Memory Map of the image处,搜查看是否有PAD,如果存在一些PAD,则可能是多个指定的绝对地址之间有GAP导致的,可以将绝对地址调整对齐PAD的大小然后编译再查看.MAP文件的PAD。


因为Code + RO Data + RW Data + ZI Data将占用整个SRAM(5081为60KB),Code一般不易修改,所以可以动态调整RO Data、RW Data以及ZI Data的分布,只要总的大小不超过60KB即可,来优化ROM的大小。有时ROM存放在EEPROM上,所以适当减少ROM的大小,一些变量转换成ZI Data是一种方法。

#6. MDK的变量绝对地址定位及初始化

##3.1. 关键字__attribute__((at(address)))


const int MAX_LUN_CNT __at(0x2000E000) = 10;      // IROM1

const int MY_COLOR[4] __at(0x2000E004) = {1, 2, 3, 4}; // IROM1

int g_Val __at(0x2000E004); // 正确                 // IROM1

int g_Val1 __at(0x2000E200); // 正确 // IRAM1

// 错误.This is fixed with ARM Compiler V5.06u2, released in combination with MDK-ARM V5.20.

int g_Val __at(0x2000E200) = 10;  // Keil 4编译错误,Keil 5.20编译通过

推荐阅读

史海拾趣

方向电子公司的发展小趣事

机顶盒,全称为数字视频变换盒,是连接电视机与外部信号源的关键设备,具有高度的专业性和广泛的应用性。从广义上讲,凡是能与电视机连接并处理音视频信号的网络终端设备均可视为机顶盒。它不仅能够接收来自有线电缆、卫星天线、宽带网络及地面广播的数字电视信号,还能通过内置的解码器将这些信号转换为电视机可识别的格式,从而呈现出高清乃至4K的超高清画质,大大提升了观看体验。

机顶盒不仅限于基本的电视信号接收功能,还集成了多种增值服务。例如,它提供电子节目指南,让用户轻松查找和预约节目;支持因特网网页浏览,实现网络购物、在线视频观看、游戏娱乐等多元化互动体验。随着智能化技术的发展,现代机顶盒还融入了语音助手、智能推荐等功能,进一步提升了用户的操作便捷性和内容个性化程度。

在技术层面,机顶盒的发展日新月异,不断向高清化、智能化方向迈进。5G技术的应用更是为机顶盒带来了更快的传输速度和更低的延迟,为用户提供了更为流畅的观影体验。此外,虚拟现实和增强现实技术的融入,也为机顶盒的未来发展打开了新的想象空间,将为用户带来更为沉浸式和互动式的观影享受。

综上所述,机顶盒作为现代家庭娱乐的重要组成部分,不仅极大地丰富了人们的电视观看体验,还通过不断的技术创新和服务升级,满足着用户日益多样化的需求。

潮州三环(Three-circle)公司的发展小趣事

随着光通信技术的快速发展,三环集团敏锐地捕捉到了这一市场机遇。在2001年,公司开始研发生产光通讯用陶瓷部件,这些部件在光纤通信中发挥着重要作用。通过不断的技术创新和产品优化,三环集团成功地将光通讯用陶瓷部件推向市场,并获得了客户的广泛认可。这一举措不仅拓展了公司的业务领域,也为公司带来了新的增长点。

CNC Tech公司的发展小趣事

CNC Tech公司的创立源于几位电子工程领域的资深专家对于高精度数控加工技术的共同追求。他们发现,随着电子行业的快速发展,对高精度、高效率的数控加工技术的需求日益迫切。于是,他们决定集结力量,共同创立CNC Tech公司,专注于研发和生产先进的数控加工设备。凭借着对技术的执着和热情,CNC Tech在创立初期就成功开发出多款具有竞争力的产品,奠定了其在行业内的技术基石。

上海晶丰明源(BPS)公司的发展小趣事

上海晶丰明源半导体股份有限公司的创立,标志着中国在半导体领域的又一重要布局。公司自成立之初,就专注于电源管理芯片的研发与销售,凭借对技术的深入理解和市场需求的敏锐洞察,迅速在行业中崭露头角。初步发展阶段,晶丰明源通过不断优化产品设计、提升生产工艺,逐步赢得了客户的信任,并在市场上占据了一席之地。

动运科技(DONGWOON)公司的发展小趣事

在电子行业中,技术创新是企业持续发展的关键。动运科技始终将技术创新作为公司的核心竞争力,不断投入研发资源,推动产品升级和技术创新。近年来,公司在自动对焦和光学防抖技术方面取得了重大突破,成功应用于音圈马达驱动芯片中,为智能手机等设备的摄像头模组提供了更加稳定、清晰的成像效果。这一技术的成功应用,不仅提升了动运科技在业界的地位,也为公司带来了广阔的市场前景。

EVERLIGHT公司的发展小趣事

EVERLIGHT公司的故事始于1983年,当时台湾的电子产业正迎来蓬勃发展的时期。创始人凭借对LED(发光二极管)技术的深刻洞察,决定创立EVERLIGHT,专注于LED的研发和生产。公司从一开始就注重技术创新,投入大量资源研发新型LED产品,不断提高产品的亮度和稳定性。随着技术的不断突破,EVERLIGHT逐渐在LED市场上崭露头角。

问答坊 | AI 解惑

常见的谬误(1)——我们担心什么?

1.概述 也许您曾经想过无线网络的应用,但是您听到的说法让您犹豫再三。您的同事告诉您,无线应用不但复杂而且昂贵。您的老板提到可靠性和升级的问题。或者,在您最后一次参加的技术会议上,与会者提到了太多太多的安全风险问题。 虽然各种形 ...…

查看全部问答>

FPGA如何防盗?

FPGA加密有那些高招?请教高人!…

查看全部问答>

如何精确处理模拟信号

大家好,现在实验中要对模拟信号精确处理,模拟信号Vo为电流传感器输出,经过隔离芯片后为Vin,然后送到跟随器,由于隔离芯片有误差,导致Vin高于Vo,差值为0.02v,为固定值,请问如何才能才能使用模拟电路抵消0.02v的差值?(见附件) [ 本帖最后 ...…

查看全部问答>

关于wince 在读写flash时候突然掉电的问题

昨天,一应用程序员反问了这个问题 在写向flash写数据的时候,突然断电,下次再启动的时候。这个文件变成不可读写了,说是写保护了。 请问大家是否遇到这种情况了? 我看了两个类似的帖子。 http://topic.eeworld.net/u/20080616/11/C34E5388-9 ...…

查看全部问答>

请问BootSector的最后两个字节到底是什么

我最近在看《自己动手写操作系统》那本书,已经看到了保护模式,但尚有一问,第一章时,BootSector的代码的最后两个字节是0x55aa 但是我后来改成了0xaa55 也可以正常引导,请问这到底是怎么回事呢?…

查看全部问答>

用制作LED16*16单行点阵屏通过RS232串口接收数据问题

本人用89C51做了一个LED16*16点阵单行显示屏,带RS232串行口,现在本人写的程序可显示4个中文汉字左或右、上或下循环显示,我懂用计时器0、方式1 设置9600波特率通过串口助手发十六进制01 、02控制带串口的LED单灯左循环的启停,现在有几点请教大家 ...…

查看全部问答>

atmel程序

各位大虾,写atmega的C程序需要注意一些什么问题呀。。…

查看全部问答>

S3C2416开发板ARM9EJ内核 完美替代S3C2440

一、S3C2416简介     S3C2416是低功耗、高性能、低成本的SAMSUNG ARM9(ARM926EJ)处理器,最具性价比优势的芯片,S3C2440最完美的替代者。    UT-S3C2416开发板是一款以S3C2416处理器为核心的高 ...…

查看全部问答>

转让一款omap3530开发板devkit8000

本人现在有一款omap3530嵌入式开发板devkit8000,当初心血来潮买的,因为种种原因买了之后就没用过了,算是全新的。关于该开发板的信息可以看这里http://www.timll.com/products/Devkit8000.asp这里http://elinux.org/DevKit8000和这里http://item. ...…

查看全部问答>

比例鉴频器的制作

我把相位鉴频器直接改为比例鉴频器,参数都没变,怎么输出的不是调制信号,而是载波信号呢?谢谢…

查看全部问答>