微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 嵌入式软件开发之: 基于ARM处理器的嵌入式系统设计

嵌入式软件开发之: 基于ARM处理器的嵌入式系统设计

时间:10-18 来源:互联网 点击:

)和-Otime(执行非对齐存取内联)选项来控制。

例如:

创建一个名为foo.c源文件。

__packed struct mystruct {

int aligned_i;

short aligned_s;

int unaligned_i;

};

struct mystruct S1;

int foo (int a, short b)

{

S1.aligned_i=a;

S1.aligned_s=b;

return S1.unaligned_i;

}

使用armcc -c -Otime foo.c编译。所生成的代码为:

MOV r2,r0

LDR r0,|L1.84|

MOV r12,r2,LSR #8

STRB r2,[r0,#0]

STRB r12,[r0,#1]

MOV r12,r2,LSR #16

STRB r12,[r0,#2]

MOV r12,r2,LSR #24

STRB r12,[r0,#3]

MOV r12,r1,LSR #8

STRB r1,[r0,#4]

STRB r12,[r0,#5]

ADD r0,r0,#6

BIC r3,r0,#3

AND r0,r0,#3

LDMIA r3,{r3,r12}

MOV r0,r0,LSL #3

MOV r3,r3,LSR r0

RSB r0,r0,#0x20

ORR r0,r3,r12,LSL r0

BX lr

其中,“|L1.84|”为结构体mystruct在内存中的地址。

从上例可以看出,所有对结构体域成员的访问都是通过字节访问实现的,所以这种不对齐内存访问无论从代码占用的存储器空间,还是代码的执行时间上都要付出一定的代价。

然而,开发者可以给编译器提供更多的信息,使其知道结构体内哪个字段是对齐的,哪个字段不是。为此,必须将未对齐字段声明为__packed,并从struct本身除去__packed属性。通过这种方法可以保证对struct中自然对齐成员的快速访问。而且,哪个字段是未对齐的也更清楚,但这样就增加了访问struct结构的难度,当用户从结构中增加或删除字段时需要特别小心。

修改上例中结构体的定义,来减少访问结构体的开销。具体代码如下所示。

struct mystruct {

int aligned_i;

short aligned_s;

__packed int unaligned_i;

};

struct mystruct S1;

对修改后的程序进行编译,产生的汇编代码如下所示。

MOV r2,r0

LDR r0,|L1.32|

STR r2,[r0,#0]

STRH r1,[r0,#4]

LDMIB r0,{r3,r12}

MOV r0,r3,LSR #16

ORR r0,r0,r12,LSL #16

BX lr

从编译后的汇编代码不难看出,对结构体内符号自然边界对齐的域,编译器直接使用相应的Load/Store指令进行访问,而只有那些非自然边界对齐的域,编译器才进行附加处理。这样,从时间和空间两方面减小了程序的开销。

同一原理也适应于联合体结构(unions)。使用在存储器中未对齐的联合组件的__packed属性。

13.1.3 用于半字存取的非对齐 LDR指令

一些特殊情况下,ARM编译程序可以生成非对齐LDR指令。特别是编译程序从存储器中载入半字时将使用该方法。这是因为,通过使用相应地址,所需的半字可以载入到寄存器的高半段(bits[31:16]),然后通过移位,将有效数据移到寄存器的低半段(bits[15:0])。这样做的目的是通过减少内存访问次数来减少程序的执行时间。通过上面的方法,程序只需要一次存储器的访问,而使用LDRB指令做同样的操作需要两次存储器的存取,而且还要为将这两个字节合并在一起添加特殊的代码。在ARM体系结构v3和其早期版本中,通常使用该方法进行所有的半字载入。但在ARMv4及其以后版本中,出现了专门的半字载入指令,这种方法逐渐被取代。但是,非对齐LDR指令仍可能会出现,比如在一个充填结构中存取一个非对齐short域类型。

注意在RVCT中已经不再支持ARMv3架构。

13.1.4 移植代码并检测非对齐内存访问

在非RISC体系结构的处理器上执行的代码中,可能会存在使用指针访问非自然边界对齐的数据类型。这种操作,在ARM体系结构中是不允许的。这就给代码的移植带来很大困难。用户必须识别并更改此类内存访问代码才能使其在RISC体系结构的处理器上正确执行。

识别非对齐存取可能会很困难,因为使用非对齐地址进行的载入或存储操作会产生不正确的动作。追踪到底是哪部分的C源程序造成了这个问题是很困难的。

具有完整存储器管理单元(MMUs)的ARM处理器,例如ARM920TTM,支持内存对齐检测功能,用户可以通过设置MMU使处理器检测每一次的内存访问以确保其被正确地对齐。如果出现非对齐内存访问,MMU将产生数据中断。这样就给追踪出错代码带来了很大的方便。

对于一些简单的没有MMU的内核,如ARM7TDMI,最好的方法是在ASIC(Application Specific Integrated Circuit)/ASSP(Application Specific Standard Product)内部实现对齐检测。可以增加专门的ARM内核扩展硬件,由其监控每次数据的访问的内存大小和存取地址总线的最低有效位。在非对齐存取的情况下,可以通过配置ASIC/ASSP产生中断信号(ABORT)。ARM公司建议在需要运行移植代码设备中包含这样的ASIC/ASSP逻辑。

如果在设计系统时,将系统设计成为当出现非对齐的内存访问时产生异常,则必须

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top