LPC2114是基于ARM7TDMI核的可加密的单片机,具有零等待128 KB的片内Flash,16 KB的SRAM,时钟频率可达60 MHz。外部晶振的频率为11.059 2 MHz,时钟频率设置为11.059 2×4 =44.236 8 MHz,片内外设频率为时钟频率的1/4,即晶振的频率。ARM7TDMI核通过使用三级流水线和大量使用内部寄存器来提高指令流的执行速度,能提供0.9 MIPS/MHz的指令执行速度,即指令周期为1/(0.9×44.236 8)=0.025 12 μs,约为25 ns。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
为了观察指令周期,将LPC2114中GPIO的P0.25脚设置为输出口,并对其进行循环的置位操作和清除操作。C源程序如下:
#include "config.h"
#define LED4 (1<<25)
int main(void)
{
PINSEL0=0x00000000;
PINSEL1=0x00000000;
IO0DIR=LED4;
while(1)
{
IO0SET=LED4;
IO0CLR=LED4;
}
return 0;
}
采用ADS1.2进行编译、链接,生成可执行文件。当调用AXD Debugger时,可以得到上述源程序的反汇编代码:
Main [0xe<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />59f1020] * ldr r1,0x40000284 ;
40000260 [0xe3a00000] mov r0,#0
40000264 [0xe5810000] str r0,[r1,#0]
40000268 [0xe5810004] str r0,[r1,#4]
4000026c [0xe3a00780] mov r0,#0x2000000
40000270 [0xe1c115c0] bic r1,r1,r0,asr #11
40000274 [0xe5810008] str r0,[r1,#8]
40000278 [0xe5810004] str r0,[r1,#4]
4000027c [0xe581000c] str r0,[r1,#0xc]
40000280 [0xeafffffc] b 0x40000278 ;
40000284 [0xe002c000] dcd 0xe002c000 ....
每行汇编代码的第1列为该代码在存储器中的位置,第2列为机器码,后面是编译、链接后的汇编语言代码。循环部分的语句最关键的就是下面3句:
40000278 [0xe5810004] str r0,[r1,#4]
4000027c [0xe581000c] str r0,[r1,#0xc]
40000280 [0xeafffffc] b 0x40000278 ;
在AXD Debugger中,将其调用到RAM中运行程序得到循环部分GPIO的P0.25的输出波形,如图1所示。 从图中可以看出,循环周期中保持为高电平的时间为1350 ns左右,低电平的时间为450 ns左右,即指令“str r0,[r1,#4]”和指令“str r0,[r1,#0xc]”均需350 ns左右,而跳转指令则需100 ns左右。这主要是由于以下原因造成的:
① ARM的大部分指令是单周期的,但是也有一些指令(如乘法指令)是多周期的;
② 基于ARM核的微控制器只有加载、存储和交换指令可以对存储器的数据进行访问,这样从存储器读数据或向存储器写数据要增加1个时钟周期;
③ 访问片内外设要增加一个外设时钟周期。当然,每个指令还要有1个时钟周期,跳转时要清空流水线还要另加一定的时钟周期。
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
图1 GPIO的P0.25脚输出波形
为了观察乘法指令,特地采用下述汇编语言进行了实验。首先是没有乘法指令的汇编源程序:
INCLUDE LPC2294.INC ; 引入头文件
LEDCON EQU 0x02000000 ; P0.25引脚控制LED4,低电平点亮
EXPORT MAIN
AREA LEDCONC,CODE,READONLY ; 声明程序代码块
MAIN LDR R0,=PINSEL0 ; 装载寄存器地址,PINSEL0
MOV R1,#0x00000000 ; 设置数据,即设置管脚连接GPIO
STR R1,[R0] ; [R0] <= R1
LDR R0,=PINSEL1
STR R1,[R0]
LDR R0,=IO0DIR
LDR R1,=LEDCON
STR R1,[R0] ; 设置LED控制口为输出
LOOP LDR R1,=LEDCON ; 设置GPIO控制参数
LEDSET LDR R0,=IO0SET
STR R1,[R0] ; LED控制I/O置位,即LED4熄灭
LEDCLR LDR R0,=IO0CLR
STR R1,[R0] ; LED控制I/O复位,即LED4点亮
B LOOP ; 无条件跳转到LOOP
采用ADS1.2进行编译、链接后的汇编代码为:
LOOP [0xe3a01780] mov r1,#0x2000000原文位置
LEDSET [0xe59f0028] ldr r0, 0x40000128
400000fc [0xe5801000] str r1,[r0,#0]
LEDCLR [0xe59f0024] ldr r0,0x4000012c
40000104 [0xe5801000] str r1,[r0,#0]原文位置
40000108 [0xeafffff9] b LOOP
在AXD Debugger中,将其调用到RAM中运行程序得到循环部分的GPIO的P0.25脚输出波形,如图2所示。 从图中可以看出,循环周期中保持为高电平的时间为450 ns左右,低电平的时间为550 ns左右。
图2 GPIO的P0.25脚输出波形2
在上例的LOOP循环部分中加入乘法指令,即将循环部分改为:
LOOP LDR R1,=LEDCON
LEDSET LDR R0,=IO0SET
STR R1,[R0]
MOV R2,#0x0234
MUL R2,R1,R2
LEDCLR LDR R0,=IO0CLR
STR R1,[R0]
B LOOP
采用ADS1.2进行编译、链接后的汇编代码为:
LOOP [0xe3a01780] mov r1,#0x2000000
LEDSET [0xe59f0030] ldr r0,0x40000130
400000fc [0xe5801000] str r1,[r0,#0]
40000100 [0xe3a02f8d] mov r2,#0x234
40000104 [0xe0020291] mul r2,r1,r2
LEDCLR [0xe59f0024] ldr r0,0x40000134
4000010c [0xe5801000] str r1,[r0,#0]
40000110 [0xeafffff7] b LOOP
在AXD Debugger中,将其调用到RAM中运行程序得到循环部分的GPIO的P0.25脚输出波形,如图3所示。 从图中可以看出,循环周期中保持为高电平的时间为550 ns左右,低电平的时间为550 ns左右。与上例比较可知,多出的MUL乘法指令和MOV传送指令共占用100 ns。
图3 GPIO的P0.25脚输出波形3
综上所述,得出如下结论:
当ARM指令放在RAM中运行时,指令“str r0,[r1,#4]”和指令“str r0,[r1,#0xc]”均需350 ns左右,相当于14个指令周期;指令“ldr r0,0x4000012c”的执行时间为100 ns,相当于4个指令周期;MUL乘法指令和MOV传送指令共占用100ns,相当于4个指令周期;跳转指令共占用100 ns,相当于4个指令周期。
(转帖:单片机与嵌入式系统应用)
文章评论(0条评论)
登录后参与讨论