1)系统的启动
PC-->BIOS-->引导操作系统--->识别分区 (c盘、d盘等)--->启动应用程序。
嵌入式Linux--->bootloader--->引导linux操作系统--->挂载根文件系统----->启动应用。
2)怎么生成一个可执行程序?
得到一个可执行程序的步骤无非是这么几步:
1> 编辑文件2> 编译/链接
3> 烧写测试
在Windows下有很多的集成开发环境,如ADS.TAR.KEIL等,点点鼠标就帮我们生成了。
在Linux下也有一些GNU工具链,如gcc之类的,要我们用命令行来运行生成。最后的效果都是一样的。
3)应用程序与裸板程序的差别
以前一直没关心这个main()是怎么执行起来的,只知道一执行就从main()开始执行。然而,这个main函数也只是一个普通的函数而以,main它又被谁调用的呢?
它是被启动代码调用,裸板没有操作系统,如果我们要在裸板上跑程序的话,这个启动代码也要由我们自己来写。
启动代码要完成什么功能呢?
1>硬件相关的初始化。2>调用C函数。
4)裸板点LED
一、写启动代码
1)硬件初始化
a、设置CPU
把外设的地址告诉处理器。
b、关看门狗
一般是3秒倒数,3秒一到就重启了(是为了防止死机)。
看一下,以下这是个完全汇编的代码例子:
.globl _start
_start:
/* 硬件相关的设置 */
/* Peri port setup */
ldr r0, =0x70000000
orr r0, r0, #0x13
mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff)
/* 关看门狗 */
/* 往WTCON(0x7E004000)写0 */
ldr r0, =0x7E004000
mov r1, #0
str r1, [r0]
/* 设置GPMCON让GPM3作为输出引脚 */
ldr r1, =0x7F008820
mov r0, #0x1000
str r0, [r1]
/* 设置GPMDAT让GPM3输出0 */
ldr r1, =0x7F008824
mov r0, #0
str r0, [r1]
halt:
b halt
硬件代码实现点灯,汇编实现,_start开始,硬件相关设置---关看门狗---设置GPM3为输出,让它输出0。还要设置cpu,设定外设起始地址,(所谓外设地址就是gpio,uart等寄存器地址,从0x70000000~0x7fffffff)。
进行linux环境,执行#arm-linux-gcc -o start.o start.S -c -c是只编译不链接,把start.S 编译成 start.o。
#arm-linux-ld -Ttext 0 -o led.elf start.o -ld是链接,-Ttext 0 是代码段从0开始
#arm-linux-objcopy -O binary led.elf led.bin 再把.elf 格式的转换成.bin文件
ELF:可执行链接格式。其实就是Unix下的执行文件和动态库(*.so)和目标文件(*.o)文件格式。
不光是可执行文件(Windows的.exe和Linux下的ELF可执行文件)按照可执行文件格式存储。动态链接库(DLL,Dynamic Linking Library)(Windows的.dll和Linux的.so)及静态链接库(Static Linking Library)(Windows的.lib和Linux的.a)文件都按照可执行文件格式存储。
上拉电阻:接到VCC。
下拉电阻:接到地。
2)调用C函数
上面一个程序是全汇编的,没有用到C的程序,汇编比较麻烦,下面我们来看看用C怎么写。
.globl _start
_start:
/*设置CPU,把外设地址告诉CPU*/
/* Peri port setup */
ldr r0, =0x70000000
orr r0, r0, #0x13
mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff)
/*关看门狗*/
ldr r0, =0x7E004000
mov r1, #0
str r1, [r0]
/*设置栈*/
ldr sp, =8*1024
bl ledBright
halt:
b halt
我们还要了解一个6410的内部结构,我们现在都是设置的从Nand flash启动。这样一上电,Nand flash前8k的内容就会原原本本的拷贝到内存中。我们的程序很小,暂时就把sp指向8k之上。
启动后就会调用C函数,一般是名为main,但是这个叫什么是没关系的,程序中我们就命名为ledBright.
bl长跳转,后把下条指令的地址存到lr寄存器中。恢复是用ldr pc,lr就可跳回来。
二、写c函数
1)ledBright中实现点灯:
void delay()
{
volatile int i = 0x10000;
while (i--);
}
int ledBright()
{
int i = 0;
volatile unsigned long *gpmcon = (volatile unsigned long *)0x7F008820;
volatile unsigned long *gpmdat = (volatile unsigned long *)0x7F008824;
/* gpm0,1,2,3设为输出引脚 */
*gpmcon = 0x1111;
while (1)
{
*gpmdat = i;
i++;
if (i == 16) i = 0;
delay();
}
return 0;
}
pc:r15 lr:r14 ip: r12 fp:r 112)汇编与C语言之间怎么传递参数
它们之间有一个规则,称为ATPCS规则。
第1个参数存在r0,第2、3、4个参数分别存在r1 r2 r3中。如果还有更多参数的话,就存在栈里面。如:
int ledBright(int start, int end, int a, int b, int c, int d) start存在r0,end a b 分别存在r1 r2 r3中,c d存在栈中。