【说明】
前面我们说明了点亮LED灯的原理以及用汇编代码如何实现,其实我们可以用C来写,正如前面介绍C和汇编混合编程的时候讲的那样,从汇编调用C函数和从C调用汇编函数都是很容易的,这一节,我们就把主要的代码放在C语言中,硬件相关原理和前一节一样,就不再复述。直接看代码。
【代码】
//C 中的代码是这样的
// 延时
void delay()
{
volatile int i = 0x10000;
while (i--);
}
int main()
{
int i = 0x10;
// 配置引脚
volatile unsigned long *gpkcon0 = (volatile unsigned long *)0x7F008800;
volatile unsigned long *gpkdat = (volatile unsigned long *)0x7F008808;
*gpkcon0 = 0x11110000;
// 跑马灯
while (1)
{
*gpkdat = i;
i++;
if (i == 0x100 )
i = 0x10;
delay();
}
return 0;
}
上面的main 没什么特殊意义,只是个函数名而已,不像平时我们做系统编程的时候,main是程序入口(实际上即使是系统编程,在运行main之前,在main之后,操作系统都加了点代码上去)
//汇编语言应该这样
// 启动代码
.global _start
_start:
// 把外设的基地址告诉CPU
ldr r0, =0x70000000 //对于6410来说,内存(0x00000000~0x60000000),外设(0x70000000-0x7fffffff)
orr r0, r0, #0x13 //外设大小:256M
mcr p15,0,r0,c15,c2,4 //把r0的值(包括了外设基地址+外设大小)写给cpu
// 关看门狗
ldr r0, =0x7E004000
mov r1, #0
str r1, [r0]
// 设置栈
ldr sp, =0x0c002000
// 调用C函数点灯
bl main
halt:
b halt
我想原因在前面小节中已经说得十分清楚,这个例子就是为了说明在实际中,如何在汇编中调用C
【makefile】
//makefile
led.bin: start.o main.o
arm-linux-ld -Ttext 0x50000000 -o led.elf $^
arm-linux-objcopy -O binary led.elf led.bin
arm-linux-objdump -D led.elf > led_elf.dis
%.o : %.S
arm-linux-gcc -o $@ $< -c
%.o : %.c
arm-linux-gcc -o $@ $< -c
clean:
rm *.o *.elf *.bin *.dis -rf
【实验现象】
LED闪烁