6.ARM编程实战
环境:
- FS4412 ARM-A9开发板
- Ubuntu-14.0.4虚拟机
- vim编辑器
GPIO
目标: 实现LED2小灯闪烁
1.确定使用的管脚
在原理图中找到LED2和它连接的管脚
2.确定要配置的寄存器
3.编程实现功能
汇编代码
.text
_start:
MAIN:
BL LED_CONFIG
LOOP:
BL LED_ON
BL DELAY
BL LED_OFF
BL DELAY
B LOOP
LED_CONFIG:
LDR R2, =0x11000C40 @GPX2CON
LDR R1, =0x10000000
STR R1,[R2]
MOV PC, LR @返回
LED_OFF:
LDR R2, =0x11000c44 @GPX2DAT
LDR R1, =0x00000000 @低电平灭灯
STR R1,[R2]
MOV PC, LR @返回
LED_ON:
LDR R2, =0x11000c44 @GPX2DAT
LDR R1, =0x00000080 @点亮第七位
STR R1,[R2]
MOV PC, LR @返回
DELAY:
LDR R1, =1000000000
L:
SUB R1, R1, #1
CMP R1, #0
BNE L
MOV PC, LR @返回
@死循环,防止程序跑飞
STOP:
B STOP
.end
Makefile编写
简便写法
TARGET = arm_led
CROSS_COMPILE = arm-none-linux-gnueabi-
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
all:
$(CC) -c $(TARGET).s -o $(TARGET).o
$(LD) $(TARGET).o -Ttext 0x40008000 -o $(TARGET).elf
$(OBJCOPY) -O binary -S $(TARGET).elf $(TARGET).bin
clean:
rm $(TARGET).o $(TARGET).elf $(TARGET).bin
目标+依赖写法
TARGET = arm_led
CROSS_COMPILE = arm-none-linux-gnueabi-
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
# 编译生成目标文件的规则
# $(TARGET).o 依赖于 $(TARGET).s
$(TARGET).o: $(TARGET).s
$(CC) -c $(TARGET).s -o $(TARGET).o
# -c 选项是编译但不链接,生成目标文件
# 链接生成 elf 可执行文件的规则
# $(TARGET).elf 依赖于 $(TARGET).o
$(TARGET).elf: $(TARGET).o
$(LD) $(TARGET).o -Ttext 0x40008000 -o $(TARGET).elf
# -Ttext 选项指定程序的入口地址为 0x40008000
# 生成二进制文件的规则
# $(TARGET).bin 依赖于 $(TARGET).elf
$(TARGET).bin: $(TARGET).elf
$(OBJCOPY) -O binary -S $(TARGET).elf $(TARGET).bin
# -O binary 选项指定输出为二进制格式,-S 选项表示丢弃调试信息
# all 目标依赖于最终生成的三个关键文件
all: $(TARGET).o $(TARGET).elf $(TARGET).bin
# clean 目标用于清理生成的文件
clean:
rm $(TARGET).o $(TARGET).elf $(TARGET).bin
C工程与寄存器封装
引用封装好的寄存器库:exynos_4412.h
流水灯实验
#include "exynos_4412.h"
void Delay(unsigned int Time)
{
while(Time --);
}
int main()
{
GPX2.CON = GPX2.CON & (~(0xF << (4*7))) | (0x1 << (4*7));
GPX1.CON = GPX1.CON & (~(0xF << (4*0))) | (0x1 << (4*0));
GPF3.CON = GPF3.CON & (~(0xF << (4*4))) | (0x1 << (4*4));
GPF3.CON = GPF3.CON & (~(0xF << (4*5))) | (0x1 << (4*5));
while(1)
{
// 点亮
GPX2.DAT = GPX2.DAT | (1 << 7);
Delay(1000000);
GPX1.DAT = GPX1.DAT | (1 << 0);
Delay(1000000);
GPF3.DAT = GPF3.DAT | (1 << 4);
Delay(1000000);
GPF3.DAT = GPF3.DAT | (1 << 5);
Delay(1000000);
// 熄灭
GPX2.DAT = GPX2.DAT & (~(1 << 7));
Delay(1000000);
GPX1.DAT = GPX1.DAT & (~(1 << 0));
Delay(1000000);
GPF3.DAT = GPF3.DAT & (~(1 << 4));
Delay(1000000);
GPF3.DAT = GPF3.DAT & (~(1 << 5));
Delay(1000000);
}
return 0;
}