1. 查看原理图
Tiny6410 中共有8 个用户按键,原理图如下:
相关的引脚信息如下图:
2. 代码编写
2.1 start.S
.global _start
_start:
//外设基地址及大小告诉CPU
ldr r0, =0x70000000 //ldr: load
orr r0, r0, #0x13 //0x13=b10011=256M, 参见arm1176jzfs内核参考手册Page3-130
mcr p15,0,r0,c15,c2,4 //把r0的值(包括了外设基地址+外设大小)告诉cpu
//关看门狗
ldr r0, =0x7E004000 //watch dog timer base address
mov r1, #0
str r1, [r0] //disable watch dog. str: Store
//设置栈
ldr sp, =0x0C002000 //S3C6410 的内部8K 的SRAM 被映射到0X0C000000,而ARM 默认的栈是递减的,所以可以让SP 指向0X0C002000
//调用C函数点灯
bl main
halt:
b halt
2.2 main.c
/*
* GPK4 --> LED1 | GPN0 --> KEY1
* GPK5 --> LED2 | GPN1 --> KEY2
* GPK6 --> LED4 | GPN2 --> KEY3
* GPK7 --> LED3 | GPN3 --> KEY4
*/
#define GPKCON0 (*(volatile unsigned long *)0x7F008800)
#define GPKDAT (*(volatile unsigned long *)0x7F008808)
#define GPNCON (*(volatile unsigned long *)0x7F008830)
#define GPNDAT (*(volatile unsigned long *)0x7F008834)
int main(void)
{
int key=0;
GPKCON0 = 0x11110000; //设置GPK 4、5、6、7为输出
GPNCON = 0x00; //设置GPN 0,1,2,3为输入
GPKDAT = 0x000000f0; //LED 熄灭
while(1)
{
key = GPNDAT; //读取按键状态
if(key & (1<<0)) //如果GPN0 ==1, KEY1没有按下
GPKDAT |= 1<<4; //LED1(GPK4)熄灭
else GPKDAT &= ~(1<<4); //LED1(GPK4)点亮
if(key & (1<<1)) //如果GPN1 ==1, KEY2没有按下
GPKDAT |= 1<<5; //LED2(GPK5)熄灭
else GPKDAT &= ~(1<<5); //LED2(GPK5)点亮
if(key & (1<<2)) //如果GPN2 ==1, KEY3没有按下
GPKDAT |= 1<<7; //LED4(GPK7)熄灭
else GPKDAT &= ~(1<<7); //LED4(GPK7)点亮
if(key & (1<<3)) //如果GPN3 ==1, KEY4没有按下
GPKDAT |= 1<<6; //LED3(GPK6)熄灭
else GPKDAT &= ~(1<<6); //LED3(GPK6)点亮
}
}
2.3 Makefile
led_key.bin: start.o main.o
arm-linux-ld -Ttext 0x50000000 -o led_key.elf $^
arm-linux-objcopy -O binary led_key.elf led_key.bin
arm-linux-objdump -D led_key.elf > led_key_elf.dis
%.o : %.S
arm-linux-gcc -o $@ $< -c
%.o : %.c
arm-linux-gcc -o $@ $< -c
clean:
rm *.o *.elf *.bin *.dis -rf