1 原理图
从原理图看到,3个LED分别由GPF4、GPF5和GPF6控制。
2 寄存器描述
GPF4、GPF5和GPF6可用作输入输出,或中断功能。要点亮LED,需要将IO设置为输出模式,并输出低电平。怎么做?
关于GPIO的寄存器描述如下(主要关注配置CON和数据DCT寄存器):
3个LED对应的CON与DAT寄存器功能,以及寄存器地址描述:
3 2440启动过程
大多数ARM芯片,CPU从0地址启动。
NorFlash启动时,基地址为0,片内内存地址为0x4000 0000。CPU读出Nor上第1个指令(4字节)执行,CPU继续读出其他指令执行。
NAND启动时,片内4K RAM基地址为0,NorFlash不可访问。2440硬件把NAND前4K内容复制到片内RAM,然后CPU从0地址取出指令开始执行。
CPU内部有两类寄存器:R0、R1~R15,这类寄存器可以直接访问;GPFCON、GPFDAT,这类寄存器,以地址访问。
4 ARM常用汇编
ldr指令:ldr r0, [r1] 假设r1的值为x,则读取地址x上的4字节到r0
str指令:str r0, [r1] 假设r1的值为x,则把r0的值写入到地址x
b指令:跳转
mov指令:mov r0, r1 把r1的值赋值给r0
mov r0, #0x100 把立即数0x100赋值给r0
ldr指令: ldr r0,=0x12345678 伪指令,最终会被拆分成几条真正的ARM指令
以下是部分ARM指令介绍:
5 点亮LED灯的汇编代码
/*
* 点亮LED1: GPF4
*/
.text
.global _start
_start:
/* 配置GPF4为输出引脚
* 把0x100写到地址0x56000050(GPFCON)上
*/
ldr r1, =0x56000050
ldr r0, =0x100
str r0, [r1] /* 把r0的值写到r1的地址 */
/* 设置GPF4输出高电平
* 把0x00写到0x56000054(GPFDAT)上
*/
ldr r1, =0x56000054
ldr r0, =0x0
str r0, [r1] /* 把r0的值写到r1的地址 */
/*
* 死循环
*/
halt:
b halt
使用arm-linux-gcc进行编译,Makefile如下:
all:
arm-linux-gcc -c -o led_on.o led_on.S
arm-linux-ld -Ttext 0 led_on.o -o led_on.elf
arm-linux-objcopy -O binary -S led_on.elf led_on.bin
clean:
rm *.bin *.o *.elf
上传到ubuntu进行编译,使用oflash烧录bin文件,可以看到点亮led。
5 ARM寄存器和汇编分析
1 修改Makefile,查看反汇编代码
all:
arm-linux-gcc -c -o led_on.o led_on.S
arm-linux-ld -Ttext 0 led_on.o -o led_on.elf
arm-linux-objcopy -O binary -S led_on.elf led_on.bin
arm-linux-objdump -D led_on.elf > led_on.dis
clean:
rm *.bin *.o *.elf
上述代码反汇编文件:
led_on.elf: file format elf32-littlearm
Disassembly of section .text:
00000000 <_start>:
0: e59f1014 ldr r1, [pc, #20] ; 1c <.text+0x1c>
4: e3a00c01 mov r0, #256 ; 0x100
8: e5810000 str r0, [r1]
c: e59f100c ldr r1, [pc, #12] ; 20 <.text+0x20>
10: e3a00000 mov r0, #0 ; 0x0
14: e5810000 str r0, [r1]
00000018 <halt>:
18: eafffffe b 18 <halt>
1c: 56000050 undefined
20: 56000054 undefined
下面是ARM寄存器描述:
几个重要的寄存器:
sp:stack pointer 栈指针
lr:link register 返回地址
pc:program counter 程序计数器 = 当前指令地址 + 8 (流水线架构),当前执行地址A的指令时,已经在对地址A+4的指令进行译码,已经在读取地址A+8的指令。
反汇编分析:
可以看到,这里的GPFCON、GPFDAT,在CPU看来就是内存。只不过,这些内存你写入或读出,能控制管脚。
字节序:低位保存在低地址。