使用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地址中