系统移植篇之uboot-2:编译微观实验
编译分为宏观编译(下面5条合一起)和微观编译(就是下面的编译步骤)
预编译(宏展开等)
编译main.c->main.S
汇编(assembly):main.S文件变成main.O文件
链接(link):一系列.O拼接起来,连接成一个不带.O的文件main, elf文件,linux中直接可以运行了,但是烧写到sd卡或者flash中是不能直接运行的,因为这个文件里面还包含了很多乱七八糟的信息(段信息等),不是存粹的二进制文件,放裸板上面是不能运行的
生成二进制文件:objdump命令来输出, 会将elf文件里面的无用信息剥离,变成main.bin(比main文件小很多)文件,这个main.bin文件就可以直接烧写到自己的SD卡中, 裸机可以运行了
gcc是一系列工具的集合
arm提供了一个开发工具链(上面完整几个过程)
实验
大致过程
我们创建一个myboot文件夹,然后在这个文件夹下面,创建两个文件mystart.S(初始化GPIO)和mylowlevel_init.S(点亮LED灯),本来这两个子过程都是放在start.S里面的,我们拆开为了看这5个过程, 我们详细可以看实现过程的是汇编,链接,生成二进制文件
汇编: mystart.S->mystart.O, mylowlevel_init.S->mylowlevel_init.O
链接: mystart.O+mylowlevel_init.O ->myboot(elf格式的可执行性文件,不是二进制文件)
生成二进制文件: myboot -> myboot.bin
制作镜像(mkv210工具)myboot.bin -> myboot.16k
详细过程
mkdir myboot
cd myboot
vi mystart.S
# mystart.S
b reset
b reset #因为实验比较简单就不搞异常处理的代码了,所以发生异常就让其继续回到reset处处理
b reset
b reset
b reset
b reset
b reset
b resetreset:bl gpio_outbl led2_on #放在mylowlevel_init里面去实现#主要是上面两句代码,接下来为了跳开流水线+8那个指令等,就需要下面一段打酱油代码mov r0, r1mov r1, r2mov r2, r3mov r3, r4mov r4, r5
#接下来需要进入一个死循环,不让其跑飞,也不要让其卡住
# loop:# b loop
#linux和arm内核为了让代码更加优雅,他们写法如下所示
1:b 1b #跳到上一个1去执行# b 1f #跳到下一个1去执行
# 1:gpio_out: #配置打开GPIO口ldr r11,=0xE0200280ldr r12,=0x00001111 #展开成二进制就是0001000100010001str r12,[r11] #r12的内容放回r11的地址中去,GPIO配置成输出状态配置完成了#现在这个GPIO管脚是输出高电平还是低电平呢? 我们不知道ldr r11,=0xE0200284 #GPIO DATA的地址ldr r12,=0xFstr r12,[r11] #确保这个几个位都是高电平,让LED灯不亮mov pc,lr #lr中的内容返回到pc里面
小知识点:linux里面的vi跨文件复制
- 打开A文件输入一个双引号"紧挨着一个变量名(单个字符)紧挨着一个行数紧挨着yy 这就把A里面指定行数的内容都复制到剪切板里面了
"a3yy
三行被复制了 - 打开B文件
"ap
# mylowlevel_init.S
.globl led2_on #确保在其他文件中也可以调用led2_on
led2_on:ldr r11,=0xE0200284ldr r12,[r11]bic r12,r12,#(1<<1) #1左移一位,10,把r12的第二个位给清0,再回写进r12,led2点亮了str r12,[r11] #将r12的内容写回到GPIO的DATA寄存器中mov pc,lr #再去160行附近调用这个子过程