crt0.S
@******************************************************************************
@ File:crt0.S
@ 功能:通过它转入C程序
@******************************************************************************
.text
.global _start
_start:
LDR r0,=0x53000000 @ WATCHDOG寄存器地址
MOV r1,#0x00000000
STR r1,[r0] @ 写入0,禁止WATCHDOG,否则CPU会不断重启
LDR sp,=1024*4 @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
@ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
bl main @ 调用C程序中的main函数
halt_loop:
b halt_loop
key_led.c
#define GPBCON *((volatile unsigned long *)0x56000010)
#define GPBDAT *((volatile unsigned long *)0x56000014)
#define GPGCON *((volatile unsigned long *)0x56000060)
#define GPGDAT *((volatile unsigned long *)0x56000064)
/*
* LED1,LED2,LED3对应GPB5、GPB6、GPB7
*/
#define GPB5_out (1<<(2*5))
#define GPB6_out (1<<(2*6))
#define GPB7_out (1<<(2*7))
#define GPB5_msk (3<<(2*5))
#define GPB6_msk (3<<(2*6))
#define GPB7_msk (3<<(2*7))
/*
* k1,k2,k3对应GPG0、GPG3、GPG5
*/
#define GPG0_in (0<<(2*0))
#define GPG3_in (0<<(2*3))
#define GPG5_in (0<<(2*5))
#define GPG0_msk (3<<(2*0))
#define GPG3_msk (3<<(2*3))
#define GPG5_msk (3<<(2*5))
int main()
{
unsigned long dwDat;
// LED1,LED2,LED3对应的3根引脚设为输出
GPBCON &=~(GPB5_msk|GPB6_msk|GPB7_msk);
GPBCON |= GPB5_out|GPB6_out|GPB7_out;
// k1,k2,k3对应的2根引脚设为输入
GPGCON &=~(GPG0_msk|GPG3_msk|GPG5_msk);
GPGCON |= GPG0_in|GPG3_in|GPG5_in;
//LEDn为1,not bright
GPBDAT |=(1<<5)|(1<<6)|(1<<7);
while(1)
{
dwDat= GPGDAT;// 读取GPG管脚电平状态
if(dwDat & (1<<0))// k1没有按下
{
GPBDAT |=(1<<5);// LED1熄灭
}
else
{
GPBDAT &=~(1<<5);// LED1点亮
}
if(dwDat & (1<<3))
{
GPBDAT |=(1<<6);
}
else
{
GPBDAT &=~(1<<6);
}
if(dwDat & (1<<5))
{
GPBDAT |=(1<<7);
}
else
{
GPBDAT &=~(1<<7);
}
}
return 0;
}
Makefile
CFLAGS := -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -ffreestanding
ledon.bin:crt0.S key_led.c
arm-linux-gcc -g -c crt0.S -o crt0.o
arm-linux-gcc -g -c key_led.c -o key_led.o
arm-linux-ld -Ttext 0x00000000 crt0.o key_led.o -o ledon_elf
arm-linux-objcopy -O binary -S ledon_elf ledon.bin
arm-linux-objdump -D -m arm ledon_elf > ledon.dis
clean:
rm -rf *.bin *elf *.o *.dis