【说明】
前面我们说明了点亮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闪烁