本文基于国嵌的视频教程和TQ2440开发板,总结一下ARM如何实现C语言环境的搭建。
相信学过C语言的很多同学应该都了解,C语言之所以可以进行数据的运算处理,是因为系统会在内存空间开辟出一块堆栈空间。
那么什么是栈呢?栈是一种具有后进先出性质的数据结构,满栈是指堆栈指针SP总是指向最后压入堆栈的数据,空栈是指堆栈指针SP总是指向下一个将要放入数据的空地址。升栈是指入栈时,SP指针从低地址指向高地址,降栈是指入栈时,SP指针从高地址指向低地址。ARM采用的是满降栈的模式。
在这里,我们需要指出的是一个函数所使用的那一部分栈称为栈帧。一个栈帧的边界可分为上边界fp指针和下边界SP指针界定。栈的作用又可分为:1、保存局部变量。2、传递参数。3、保存寄存器的值。在ARM中,需要值得注意的是当用C语言传递参数时。如果参数个数≤4时,则用R0,R1,R2,R3来传递参数,否则使用栈来传递。
堆栈和bss段初始化:
init_stack:
ldr sp, =0x34000000
mov pc ,lr
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
cmp r0, r1
moveq pc, lr
在编写一些底层驱动以及Uboot时,我们常常采用混合编程的方式。汇编调用C函数,C调用汇编函数,C内嵌汇编。
汇编调用C函数:首先得有一个C文件和汇编文件。
在汇编文件中:
ldr pc, =gboot_main
在C语言文件中:
#define GPBCON (volatile unsigned long*)0x56000010
#define GPBDAT (volatile unsigned long*)0x56000014
int gboot_main()
{
*(GPBCON) = 0x15400;
*(GPBDAT) = 0x6BF;
return 0;
}
这样便轻松实现了汇编调用C函数,实现了也是点灯的功能。
C调用汇编函数:
如果用汇编语言编写的函数要在其他文件被引用的话,需将其汇编函数利用global定义为全局变量方可调用。
汇编文件中:
.global light_led
#define GPBCON 0x56000010
#define GPBDAT 0x56000014
light_led:
ldr r0, =GPBCON
ldr r1,=0x15400
str r1, [r0]
ldr r0, =GPBDAT
ldr r1,=0x6BF
str r1, [r0]
mov pc, lr
C文件中:
int gboot_main()
{
light_led();
return 0;
}
C内嵌汇编:
这种模式的编程可能就要稍微复杂一些,其编写格式如下:
__asm__(
"汇编语句部分\n"
:输出部分----对寄存器进行了写操作
:输入部分----对寄存器进行了读操作
:破坏描述部分----被修改了寄存器值得名字
);
例程如下:
#define GPBCON 0x56000010
#define GPBDAT 0x56000014
int gboot_main()
{
__asm__(
"ldr r1,=0x15400\n"
"str r1,[%0]\n"
"ldr r1,=0x6bf\n"
"str r1,[%1]\n"
:
:"r"(GPBCON),"r"(GPBDAT)
:"r1"
);
return 0;
}
具体可参考ARM相关技术手册以及国嵌培训视频。