裸机程序二:GPIO点亮led灯 汇编

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/heyuqian_csdn/article/details/52988948

开发板:  JZ2440 V3 + EasyOpenJTAG

参考资料:《CPU三星S3C2440A芯片手册.pdf

        JZ2440_V3电路图.pdf

        ARM寄存器介绍


使用汇编代码点亮led灯,主要是设置gpio GPCONGPDAT寄存器,使用开发版资料中的源码:

@******************************************************************************
@ File:led_on.S
@ 功能:LED点灯程序,点亮LED1
@******************************************************************************       
            
.text
.global _start
_start:     
            LDR     R0,=0x56000050      @ R0设为GPFCON寄存器。此寄存器
                                        @ 用于选择端口B各引脚的功能:
                                        @ 是输出、是输入、还是其他
            MOV     R1,#0x00000100        
            STR     R1,[R0]             @ 设置GPF4为输出口, 位[8:7]
            
            LDR     R0,=0x56000054      @ R0设为GPBDAT寄存器。此寄存器
                                        @ 用于读/写端口B各引脚的数据
            MOV     R1,#0x00000000      @ 此值改为0x00000010,
                                        @ 可让LED1熄灭
            STR     R1,[R0]             @ GPF4输出0,LED1点亮
MAIN_LOOP:
            B       MAIN_LOOP


然后是Makefile:

led_on.bin : led_on.S
        #编译但不链接
        arm-linux-gcc -g -c -o led_on.o led_on.S
        #链接并指定入口地址
        arm-linux-ld -Ttext 0x0000000 -g led_on.o -o led_on_elf
        arm-linux-objcopy -O binary -S led_on_elf led_on.bin
clean:
        rm -f   led_on.bin led_on_elf *.o

最后启动openocd,并在另一个命令行中通过telnet登陆openocd,如下:

$ telnet localhost 4444
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt //中断设备运行
> load_image ./led_on.bin //下载bin文件
72 bytes written at address 0x00000000
downloaded 72 bytes in 0.005064s (13.885 KiB/s)
> resume 0x0 //从地址0x0恢复设备运行
> halt
s3c2440.cpu: target state: halted
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0xf00000d3 pc: 0x00000014
MMU: disabled, D-Cache: disabled, I-Cache: disabled
> 

板子默认led1是亮的,修改上诉代码,关闭led1,重新烧写运行,发现led1熄灭一会儿又会被点亮,这是由于我们没有关闭看门狗,导致系统复位了

1、汇编语言是否区分大小写


汇编语言的语句是不区分大小写的,编译软件会自动识别这些语句,但是汇编程序中用户定义的变量、标号等,将区分其大小写,编程时要注意这些区别


2、指令ldrmov的区别


ARMRISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令。

比如想把数据从内存中某处读取到寄存器中,只能使用ldr

ldr r0, 0x12345678

就是把0x12345678这个地址中的值存放到r0中。

mov不能干这个活,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中,这个和x86这种CISC架构的芯片区别最大的地方。

x86中没有ldr这种指令,因为x86mov指令可以将数据从内存中移动到寄存器中。


另外还有一个就是ldr伪指令,虽然ldr伪指令和ARMldr指令很像,但是作用不太一样。ldr伪指令可以在立即数前加上=,以表示把一个地址写到某寄存器中,比如:

ldr r0, =0x12345678

这样,就把0x12345678这个地址写到r0中了。所以,ldr伪指令和mov是比较相似的。只不过mov指令限制了立即数的长度为8位,也就是不能超过512。而ldr伪指令没有这个限制。如果使用ldr伪指令时,后面跟的立即数没有超过8位,那么在实际汇编的时候该ldr伪指令是被转换为mov指令的。


ldr伪指令和ldr指令不是一个同东西。


所以上述代码可以用str代替mov,如下:

LDR     R0,=0x56000050      @ R0设为GPFCON寄存器。此寄存器
                            @ 用于选择端口B各引脚的功能:
                            @ 是输出、是输入、还是其他
@MOV    R1,#0x00000100</span>        
STR     R1,=0x00000100</span>
STR     R1,[R0]             @ 设置GPF4为输出口, 位[8:7]
            
LDR     R0,=0x56000054      @ R0设为GPBDAT寄存器。此寄存器
                            @ 用于读/写端口B各引脚的数据
@MOV    R1,#0x00000000</span>      @ 此值改为0x00000010,
STR     R1,=0x00000000</span>      @ 此值改为0x00000010,



3ARM寄存器


ARM共有3732位寄存器,其中31个为通用寄存器,6个为状态寄存器.这些寄存器不能被同时访问,但在任何时候,通用寄存器R0~R14,程序计数器PC,一个或两个状态寄存器都是可访问的.

通用寄存器

通用寄存器包括R0~R15,可以分为3:

(1)未分组寄存器R0~R7

(2)分组寄存器R8~R14

(3)程序计数器PC(R15)



寄存器R13ARM指令中常用作堆栈指针,   用户也可使用其他的寄存器作为堆栈指针,而在Thumb指令集中,某些指令强制性的要求使用R13作为堆栈指针.

寄存器R13ARM指令中常用作堆栈指针,但这只是一种习惯用法,用户也可使用其他的寄存器作为堆栈指针。而在Thumb指令集中,某些指令强制性的要求使用R13作为堆栈指针。

由于处理器的每种运行模式均有自己独立的物理寄存器R13,在用户应用程序的初始化部分,一般都要初始化每种模式下的R13,使其指向该运行模式的栈空间。这

样,当程序的运行进入异常模式时,可以将需要保护的寄存器放入R13所指向的堆栈,而当程序从异常模式返回时,则从对应的堆栈中恢复,采用这种方式可以保证异常发生后程序的正常执行。

R14称为链接寄存器(Link Register),当执行子程序调用指令(BL),R14可得到R15(程序计数器PC)的备份.

在每一种运行模式下,都可用R14保存子程序的返回地址,当用BLBLX指令调用子程序时,将PC的当前值复制给R14,执行完子程序后,又将R14的值复制回PC,即可完成子程序的调用返回。以上的描述可用指令完成。


寄存器R16

寄存器R16用作CPSR(Current

Program Status Register,当前程序状态寄存器)CPSR可在任何运行模式下被访问,它包括条件标志位、中断禁止位、当前处理器模式标志位,以及其他一些相关的控制和状态位。

每一种运行模式下又都有一个专用的物理状态寄存器,称为SPSR(Saved Program Status Register,备份的程序状态寄存器),当异常发生时,SPSR用于保存CPSR的当前值,从异常退出时则可由SPSR来恢复CPSR

由于用户模式和系统模式不属于异常模式,它们没有SPSR,当在这两种模式下访问SPSR,结果是未知的




猜你喜欢

转载自blog.csdn.net/heyuqian_csdn/article/details/52988948