天天看点

linux点亮led程序,嵌入式linux------编写C语言程序点亮led灯

使用c语言替代汇编的原理也是往寄存器地址写数值,访问寄存器地址和访问内存是一样的。给出C语言程序:

int main()

{

unsigned int *pGPFDAT = (unsigned int*)0x56000050;

unsigned int *pGPFCON = (unsigned int*)0x56000054;

*pGPFDAT = 0x400;

*pGPFCON = 0;

return 0;

}

对于main函数的调用:

.text

.global _start

_start:

ldr sp,=4096

//ldr sp,=0x40000000+4096

bl main

halt:

b halt

其中bl表示在栈中调用main函数,返回值给到halt中。ldr是两种启动的程序复制到的最开始的地址。

烧写oflash  xxx.bin

0  1  0  0  0

测试。

原理分析:

start.S 可以用来设置栈,因为c函数要使用,保存局部变量和lr等寄存器。同时调用者还可以向被调用者传参数和接受返回值。

为了使C语言和汇编程序之间能够互相调用,必须为子程序间的调用指定规则,在ARM处理器中这个规则被称为ATPCS:ARM程序和Thumb程序中子程序调用规则。基本的ATPCS规则包括寄存器使用规则、数据栈使用规则、参数传递规则。ARM处理器中有r0-15共16个寄存器,r0到r3用来参数传递,r4到r11可能在函数中被使用,所以在函数入口保存,在函数的出口恢复。

对Nand启动来说,硬件上会把nand flash前4k的内容完全拷贝的片内的4k内存,如何区分是哪种启动?

// 设置内存:sp栈

ldr sp,=4096  

ldr sp,=0x40000000+4096

所以分辨的方方法就是写0到0地址再读出来,如果得到0表示nand flash启动:

mov r1,#0 //给r1赋值为0

ldr r0,[r1] //把原来0地址的值取出来备份给r0

str r1,[r1] //给0地址写入0

ldr r2,[r1] //把0地址再读出来

cmp r1,r2 //比较读出来的数值r2是不是0

ldr sp,=0x40000000+4096 //默认当成nor启动调到sp

moveq sp,#4096 //如果r1等于r2的话,说明是nand flash启动

streq r0,[r1] //再把备份的r0数值放回到0地址中