嵌入式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  /*nand启动*/
//	ldr sp,=0x40000000+4096 /*nor启动*/

	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  /*nand启动时0地址对应的是片内内存*/  
ldr sp,=0x40000000+4096 /*nor启动0地址对应的是nor flash,nor flash类似于硬盘,它可以像内存一样读但是不能像内存一样写。对于nor flash 在写数据的时候需要先发出一定的格式的数据*/   

所以分辨的方方法就是写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地址中

 

你可能感兴趣的:(嵌入式linux)