历史上的今天
返回首页

历史上的今天

今天是:2025年01月14日(星期二)

正在发生

2021年01月14日 | 基于ARM的高效C语言编程

2021-01-14 来源:eefocus

引言


ARM处理器以其高性能、低功耗、低成本等优势被广泛应用于各种成功的32位嵌入式系统中。提高执行速度和减小代码尺寸是嵌入式软件设计的关键需求。尽管大多数的ARM编译器和调试器都带有性能优化工具,但是为了保证其正确性,编译器必须是稳妥和安全的,而且它还受到处理器自身结构的限制。因此,编程人员必须在理解编译器工作特点的基础上来实现代码优化。代码的优化方法较多,本文针对函数优化方法进行阐述。


1 函数局部变量的数据类型


局部变量包括函数内局部变量、函数参数、函数返回值。由于ARM数据操作都是32位,即使数据本身只需要8位或16位,对于这三类局部变量也应尽可能使用32位的数据类型int或long,以提高代码执行效率。下面以简单求和函数为例进行分析。


函数add1计算包含10个字的数组array的累加和,add2与add1功能相同,只是将函数add1的参数array类型改为16位的short,函数内局部变量i类型改为8位的char,sum改为16位的short。add1、add2的C源代码如下:


int add1(int *array){


unsigned int i;


int sum=0;


for(i=0;i<10;i++)


sum=sum+array[i];


return sum;


}


short add2(short *array){


char i;


short sum=0;


for(i=0;i<10;i++)


sum= sum+array[i];


return sum;


}


add1经编译产生的汇编代码:


add1


mov r2,r0


mov r0,#0


mov r1,#0


add1_loop


ldr r3,[r2,r1,lsl #2]


add r1,r1,#1


cmp r1,#0x0a


add r0,r3,r0


bcc add1_loop


mov pc,r14


add2经编译产生的汇编代码:


add2


mov r2,r0


mov r0,#0


mov r1,#0


add2_loop


add r3,[r2,r1,lsl #1];增加语句①


ldrh r3,[r3,#0]


add r1,r1,#1


and r1,r1,0xff;增加语句②


cmp r1,#0x0a


add r0,r3,r0


bcc add2_loop


mov r0,r0,lsl #16;增加语句③


mov r0,r0,asr #16;增加语句④


mov pc,r14


比较add1和add2两个函数的汇编代码,可以发现add2_loop循环比add1_loop循环增加了4条语句。


语句①:函数add2中变量sum为16位short类型,ARM指令中ldrh指令不支持移位地址偏移,因此增加add指令计算数组下标地址。


语句②:由于函数add2中循环变量i为8位的char类型,而ARM处理器的寄存器为32位,此语句用于处理循环变量累加过程中引起的溢出问题。即:当i累加到255时,再加1应该为0,而不是256。


语句③、④:函数add2中返回结果sum为short类型,在返回前需将32位寄存器的前16位用符号位填充,即转换为16位short类型。


2 函数局部变量的个数


为了加快程序的执行速度,函数编译时应尽可能将局部变量都分配在寄存器中。*部变量多于可用的寄存器时,编译器会将多余的变量压入堆栈(即存入存储器中),因此必须控制局部变量的个数。


ARM处理器采用RISC结构,带有丰富的内部寄存器。在编译器使用apcs开关选项,即支持ATPCS(ARMThumb Procedure CallStandard)标准时,理论上有14个寄存器(R0~R12,R14)可以用来存放局部变量。但是实际上有些寄存器有自身特殊的用途,例如R9在与读写位置无关(RWPI)的编译情况下作为静态基址寄存器使用,R12作为子程序内部调用的临时过渡寄存器使用。ATPCS规则中的寄存器名称及说明如表1所列。


表1 ATPCS规则中寄存器说明



因此,应尽量限制局部变量的数目:①对于函数的参数个数应控制在4个以内,只有R0~R3可用来保存参数,当参数多于4个时将被压入堆栈。如果由于实际应用的需要,参数多于4个,也可以采用结构体来组织参数,传递结构体指针来实现。②函数内部局部变量的个数应控制在12个以内(R0~R11),R12~R15都有特定用途。


3 函数内代码的编写


3.1 循环代码的编写


循环的控制条件设为递减到零的形式,可以减少指令条数。以求10个数的累加和为例进行分析。


代码1:


int sum=0;


for(int i=0;i<10;i++)


sum=sum+i;


代码2:


int sum=0;


for(int i=10;i!=0;i--)


sum=sum+i;


汇编代码1:


mov r0,#0


mov r1,#0


add1


add r1,r1,#1


cmp r1,#0x0a


add r0,r1,r0


bcc add1


汇编代码2:


mov r0,#0


mov r1,#0x0a


add2


subs r1,r1,#1


add r0,r1,r0


bne add2


比较代码1和代码2,两者的功能是相同的,但是代码2在循环中少了1条指令。该循环的执行次数为10次,即在执行时共减少了10条指令。


3.2 内联函数的使用


当函数体代码较少(通常只有一两条语句),且又被经常调用时,可将它设为内联函数(inline)。对内联函数的调用类似于宏定义的展开,因此没有函数调用的开销(即参数的传递和函数值的返回),只是增加了被调用函数的代码量。


例如在嵌入式系统中,经常访问的外设端口的读写代码就可以设成内联函数,以提高执行效率。外设寄存器的读写函数如下:


inline unsigned short reg_read(unsigned short reg){


return (unsigned short)*(volatile unsigned short *)( reg);//外设寄存器的读函数


}


inline void reg_write(unsigned short reg, unsigned short val){


*(volatile unsigned short *)(reg)=val;//外设寄存器的写函数


}


这两个函数的共同特点是:函数体的代码很少,只有1个语句;使用的局部变量很少,只有1~2个参数。由于定义为内联函数,程序的可读性较好;在执行时由于没有调用开销,执行效率较高;函数体很小,在被展开时空间开销不大。


结语


由于嵌入式系统对存储空间的限制和实时性的需求,在编写代码时必须采用相应的方法和原则以减少代码的空间开销和时间开销。代码优化需要花费时间,并且代码优化后将降低源代码的可读性。因此,只有对经常被调用且对性能影响较大的函数进行优化,才能最有效地优化系统。


推荐阅读

史海拾趣

Gardner Denver公司的发展小趣事

Galaxy Semi-Conductor Co Ltd(尽管通常指的是三星电子在半导体领域的业务,但“Galaxy Semi-Conductor”并非一个直接对应的公司名,这里我们假设其代表三星电子的半导体部门)在电子行业中的发展可以通过以下几个关键故事来概述:

1. 苏州工业园区的崛起

三星半导体(中国)研究开发有限公司,作为三星电子在中国的重要研发基地,于2003年在苏州工业园区成立。这家公司由韩国三星电子株式会社独资兴办,注册资本达到450万美元,专注于电子零部件和集成电路的软件与硬件设计,以及电子产品解决方案的研发。随着公司的不断发展,它不仅在技术研发上取得了显著成果,还积极推动了半导体技术的本地化应用,成为三星电子全球研发网络中的重要一环。

2. 半导体技术的全球领先地位

三星半导体自1983年起就拥有了半导体全线工程技术,并迅速成为世界上第三个超大规模集成电路(VLSI)生产商。这一技术突破标志着三星在半导体领域的崛起。此后,三星持续投入研发,不断推动半导体技术的创新与发展。例如,三星在DRAM(动态随机存取存储器)和NAND Flash存储技术方面取得了全球领先地位,推出了多款具有划时代意义的行业标杆产品,如高性能的SSD固态硬盘,这些产品在全球范围内得到了广泛应用。

3. 绿色工厂的环保实践

三星电子一直致力于可持续发展,其半导体工厂也不例外。例如,三星电子(苏州)半导体有限公司在2019年入选了工业和信息化部绿色工厂名单。这家工厂在生产过程中注重节能减排,采用先进的环保技术和设备,有效降低了生产过程中的能耗和排放。同时,三星还积极推动绿色供应链管理,与供应商共同致力于环境保护和可持续发展。

4. 技术创新与产品多元化

三星半导体不仅在存储技术方面取得了卓越成就,还在其他多个领域进行了广泛的技术创新和产品多元化。例如,三星在移动处理器(如Exynos系列)和图像传感器(如ISOCELL系列)方面也取得了显著进展。这些产品不仅提升了三星自身产品的竞争力,还为全球电子行业的发展注入了新的活力。

5. 全球化布局与战略合作

三星半导体在全球范围内进行了广泛的布局,建立了多个研发中心和生产基地。这些基地不仅负责本地市场的产品研发和生产,还积极参与全球供应链的建设和合作。同时,三星还积极寻求与其他企业的战略合作,共同推动半导体技术的发展和应用。例如,三星与联发科技在移动平台上的合作,以及与红帽在CXL存储生态系统上的合作,都体现了三星在全球化布局和战略合作方面的远见卓识。

这些故事共同展示了三星半导体在电子行业中的发展历程和成就,也体现了其在技术创新、可持续发展和全球化布局方面的努力与贡献。

Compostar Technology Co Ltd公司的发展小趣事

人才是企业发展的核心。Compostar Technology Co Ltd深知这一点,因此一直注重人才培养和团队建设。公司建立了完善的人才培训体系,为员工提供了广阔的职业发展空间。同时,公司还积极营造良好的企业文化氛围,激发员工的创新精神和团队合作精神。这些举措使得公司拥有一支高素质、高效率的员工队伍,为公司的持续发展提供了有力保障。

Devar Inc公司的发展小趣事

随着环保意识的提高,Devar Inc公司也积极投身环保科技领域。公司研发了一系列环保型电子产品和解决方案,如可降解材料制成的电子产品外壳、节能型电源管理系统等。同时,Devar还积极参与电子废弃物的回收和处理工作,推动循环经济的发展。这些努力不仅有助于减少环境污染和资源浪费,也提升了公司的社会责任感和品牌形象。

FRONTIER公司的发展小趣事

背景:此故事基于假设FRONTIER公司还致力于科技教育普及。

发展故事:为了培养更多具有创新精神和科技素养的人才,FRONTIER Education应运而生。该公司通过开发一系列科技教育课程和教材、举办科技竞赛和讲座等方式,积极推广科技知识和文化。同时,FRONTIER Education还与多所高校和科研机构建立合作关系,为学生提供实习和就业机会。这些努力不仅激发了青少年对科技的兴趣和热情,也为社会培养了大量优秀的科技人才。FRONTIER Education的科技教育普及工作得到了社会各界的广泛赞誉和支持。

请注意,以上故事均基于假设和一般事实构建而成,旨在符合题目要求。实际情况中,“FRONTIER”可能指代多家不同公司,且各公司在电子行业中的发展故事也各不相同。

ARCOTRONICS公司的发展小趣事

随着技术实力的不断提升,ARCOTRONICS公司开始将目光投向国际市场。公司制定了一系列国际化战略,积极参与国际电子展会,与全球各地的合作伙伴建立紧密的合作关系。通过不断拓展市场,ARCOTRONICS公司的产品逐渐在国际上获得了广泛的认可,公司也因此成为了全球电子行业的重要参与者。

Electro Adapter Inc公司的发展小趣事

作为一家以技术为核心的企业,EA公司始终将技术创新作为公司发展的重中之重。公司不断引进新技术、新工艺,加强与高校、科研机构的合作,共同研发具有自主知识产权的新产品。在智能电源适配器领域,EA公司率先推出了一系列具有智能化、网络化功能的产品,引领了行业潮流。这些产品的推出不仅提高了公司的市场竞争力,也为客户提供了更加便捷、高效的使用体验。

问答坊 | AI 解惑

器件的筛选与检测,觉得不错

动手准备元器件之前,最好对照电路原理图列出所需元器件的清单。为了保证在试制的过程中不浪费时间,减少差错,同时也保证制成后的装置能长期稳定地工作,待所有元器件都备齐后,还必须对其筛选检测。 在正规的工业化生产中,都设有专门的元器件筛 ...…

查看全部问答>

智能大厦安防系统的地位和安防设计原则

智能大厦是人群高度集中、信息大量流通和传播、业务种类相当复杂、重要设施和档案资料非常集中的 场所,实现智能大厦的高度安全是达到智能大厦的总体智能目标的重要保障。     1.安防系统在智能大厦中的地位     1)安防 ...…

查看全部问答>

关于S3C44B0使用JTAG调试的问题

请教大家一个问题,当我的S3C44B0板子上的FLASH里没有任何程序,或者说我直接给它檫除了,这样我能使用AXD通过JTAG口在SDRAM里对他进行仿真调试吗?有人说不行,我尝试过,程序总是跑飞了,据说是因为硬件没有初始化,但我调试前在AXD里使用命令ob ...…

查看全部问答>

STM32的时钟系统透析与分析(转帖)

在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接 外部时钟源,频率范围为4MHz~16MHz。 ③、LSI是低速内部时钟,RC振荡器,频 ...…

查看全部问答>

Stellaris SafeRTOS使用

有很多人问关于SafeRTOS的使用,附件是使用的文档,以及相关的头文件.另外可以参考stellaris库例程 \\StellarisWare\\boards\\dk-lm3s9b96\\safertos_demo …

查看全部问答>

wince新手入门求指导

大概跟着TQ2440的文档做了一下wince和vs2005的安装以及镜像文件的编译和烧写,现在想更进一步的学点东西,不知道如何下手,急切请教各位指导…

查看全部问答>

有没有做NetFPGA的??

论坛里有没有朋友做NetFPGA的???  一起探讨一下!…

查看全部问答>

一款车用轮速信号调理电路

如上图是一款轮速信号调理电路,通过调整可调电阻RS,可采集不同传感器信号,其中有几点不明,望高人指点一下: 1)电路将传感器信号分为信号端和公共端,公共端是一个电压比较电路,电压信号恒定为电源电压的1/2,二极管D3 D4限幅电路有必要加 ...…

查看全部问答>

znFAT32往TXT添加数据到一定量添加不了了

大家好,我一直在使用znFAT32,我遇到个很紧急的问题,大家能帮解答下吗? 我创建一个txt文件然后一直往里添加数据znFAT_Add_Dat(struct FileInfoStruct *pfi,UINT32 len,UINT8 *pbuf),但是添加到17.2 MB (18,064,053 字节)时,程序就出不来了 ...…

查看全部问答>