LINUX-裸板程序的开发

昨天和大家分享了一些裸板程序开发的流程,今天小伙伴可以根据我写的内容简单的写一下,你人生的第一个裸板程序(其中有一些具体的源代码以个人爱好进行写,有小伙伴需要的可以私信)

1.上位机linux系统编辑LED裸板程序代码,具体实施步骤如下:
sudo chown tarena /opt  -R //将/opt目录的root用户权限修改为tarena用户
sudo chgrp tarena /opt -R  //将/opt目录的root组权限修改为tarena组
结果是tarena普通用户也可以访问/opt目录了,后面嵌入式的代码都放在/opt目录中

mkdir -p /opt/arm/day01/1.0 
cd /opt/arm/day01/1.0
vim led.h  //各种声明
vim led.c  //各种定义
vim main.c //负责调用
        
2.上位机安装交叉编译器(针对于ARM架构的gcc)
获取交叉编译器:porting_resource.rar/交叉编译器/arm-cortex_a9-eabi-4.7-eglibc-2.18.tar.gz
cp arm-cortex_a9-eabi-4.7-eglibc-2.18.tar.gz /opt/
cd /opt/
tar -xvf arm-cortex_a9-eabi-4.7-eglibc-2.18.tar.gz
mv arm-cortex_a9-eabi-4.7-eglibc-2.18  toolchains //对生成的目录重命名为toolchains
sudo vim /etc/environment 
打开此文件在PATH环境变量中添加:/opt/toolchains/bin
结果如下:PATH="/opt/toolchains/bin:........" //注意:.......是省略了,你们千万别省略----设置PATH环境变量是为了让系统知道在哪里可以找到可执行文件,从而在命令行中可以直接使用命令名来执行这些文件,而不需要指定完整路径。不用写  ------./
保存退出
重启上位机linux系统
验证交叉编译器是否生效,执行以下命令:
arm-cortex_a9-linux-gnueabi-gcc -v //查看交叉编译器的版本,如果能够看到说明安装成功

3.上位机交叉编译LED裸板程序,具体实施步骤如下:
cd /opt/arm/day01/1.0
arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o led.o led.c 
arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o main.o main.c 
说明:
arm...gcc:C语言程序的交叉编译器
-nostdlib:告诉编译器一律不允许使用标准C库,此程序乃裸板程序
-c:只编译不链接

arm-cortex_a9-linux-gnueabi-ld -nostartfiles -nostdlib -Ttext=0x48000000 -emain -o led.elf  main.o led.o
说明:
arm...ld:链接器,将所有的.o文件组合在一起
-nostartfiles:告诉链接器,由于是裸板程序,无需添加相关的启动代码(就是程序的真正入口_start->main)
-Ttext=0x48000000:指定程序代码段的起始地址为0x48000000
-emain:指定程序的入口函数为main
-o led.elf:生成elf格式的可执行文件
    注意:elf格式的可执行文件只能运行在操作系统下,此文件的格式:文件信息头+纯正的二进制代码+文件信息尾
    在操作系统下,操作系统会帮你提取纯正的二进制代码最终运行

arm-cortex_a9-linux-gnueabi-objcopy -O binary led.elf led.bin
说明:
arm...objcopy:二进制文件处理功能,提取纯正的二进制代码
           类似去皮的工具,led.elf:类似带皮的核桃,led.bin:类似核桃里面的果肉,不带皮
led.elf:带皮的核桃,操作系统会去皮,也可以手动利用arm...objcopy去皮
led.bin:果肉,不带皮,是真正要运行的代码文件

cp /opt/arm/day01/1.0/led.bin /tftpboot  //拷贝led.bin到tftp网络下载服务的共享目录中

4.下位机测试
重启下位机,进入uboot命令行模式执行:
print  //查看serverip和ipaddr环境变量对应的地址是否正确
ping 192.168.1.8
tftp 0x48000000 led.bin 
go 0x48000000 


5.掌握反汇编工具(objdump),具体实验步骤如下:
a)上位机执行:
    cd /opt/arm/day01/1.0
    arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o led.o led.c //只编译不链接,不允许用标准C库的代码
    arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o main.o main.c 
    arm-cortex_a9-linux-gnueabi-ld -nostartfiles -nostdlib -Ttext=0x48000000 -emain -o led.elf main.o led.o //链接
    arm-cortex_a9-linux-gnueabi-objcopy -O binary led.elf led.bin //提取纯正的二进制代码
    arm-cortex_a9-linux-gnueabi-objdump -D led.elf > led.dis 
    说明:
    arm...objdump:反汇编工具,将二进制可执行文件翻译生成汇编文件
        gcc正向编译:.c->.i->.s->.o->可执行程序
        反汇编/逆向编译:可执行文件或者.o->.s
    led.dis:就是生成的反汇编文件,里面就是汇编代码
    vim led.dis //打开反汇编文件,得到:
     led.elf:     文件格式 elf32-littlearm //ELF格式,32位,小端模式,arm模式    ,后续详解
     Disassembly of section .text: //以下就是代码段的内容
    48000000 <main>: //说明main函数的内存起始地址就是0x48000000
                //也就是说内存的0x48000000这个地址存放的是main函数
               将来在下位机执行go 0x48000000时,实际是让cpu直接运行main函数
               至于其他的信息后续课程详解!
               
b)下位机测试:
重启下位机,进入uboot命令行模式执行:
print  //查看serverip和ipaddr环境变量对应的地址是否正确
ping 192.168.1.8 //先验证网络是否联通
tftp 0x48000000  led.bin //下载内容到下位机内存0x48000000
go 0x48000000   ->运行0x48000000地址上的程序(led.bin)

6.案例:继续玩转反汇编工具
a)上位机实施步骤:
cp /opt/arm/day01/1.0 /opt/arm/day01/2.0 -fr
cd /opt/arm/day01/2.0
vim led.c 
将delay函数或者led_init,除了入口函数main其余的任意函数定义的代码放到入口函数main的前面
保存退出
arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o led.o led.c //只编译不链接,不允许用标准C库的代码
arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o main.o main.c 
arm-cortex_a9-linux-gnueabi-ld -nostartfiles -nostdlib -Ttext=0x48000000 -emain -o led.elf main.o led.o//链接
arm-cortex_a9-linux-gnueabi-objcopy -O binary led.elf led.bin //提取纯正的二进制代码
拷贝到windows的fastboot目录中
arm-cortex_a9-linux-gnueabi-objdump -D led.elf > led.dis 
vim led.dis 得到:
48000000 <led_init>: //此时下位机内存的0x48000000地址放的不再是入口函数main,而出第一个函数led_init
            将来在下位机执行go 0x48000000肯定无法再循环开关灯了,因为cpu执行led_init
            并不会执行main函数
b)下位机测试:
重启下位机,进入uboot命令行模式执行:
print  //查看serverip和ipaddr环境变量对应的地址是否正确
ping 192.168.1.8 //先验证网络是否联通
tftp 0x48000000  led.bin //下载内容到下位机内存0x48000000
go 0x48000000   ->运行0x48000000地址上的程序(led.bin)//实际是让cpu直接去执行led_init函数,无法再开关灯了    

c)上位机实施步骤:
cp /opt/arm/day01/1.0 /opt/arm/day01/3.0 -fr
arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o led.o led.c //只编译不链接,不允许用标准C库的代码
arm-cortex_a9-linux-gnueabi-gcc -nostdlib -c -o main.o main.c 
arm-cortex_a9-linux-gnueabi-ld -nostartfiles -nostdlib -Ttext=0x48000000 -emain -o led.elf led.o main.o //链接
arm-cortex_a9-linux-gnueabi-objcopy -O binary led.elf led.bin //提取纯正的二进制代码
拷贝到windows的fastboot目录中
arm-cortex_a9-linux-gnueabi-objdump -D led.elf > led.dis 
vim led.dis 得到:
go 0x48000000 <led_init>: //此时下位机内存的0x48000000地址放的不再是入口函数main,而出第一个函数led_init
            将来在下位机执行go 0x48000000肯定无法再循环开关灯了,因为cpu执行led_init
            并不会执行main函数
b)下位机测试:
重启下位机,进入uboot命令行模式执行:
print  //查看serverip和ipaddr环境变量对应的地址是否正确
ping 192.168.1.8 //先验证网络是否联通
tftp 0x48000000  led.bin //下载内容到下位机内存0x48000000
go 0x48000000   ->运行0x48000000地址上的程序(led.bin)//实际是让cpu直接去执行led_init函数,无法再开关灯了
    
c)切记:裸板程序在链接时(arm...ld)是从文件的开头依次向下开始一个函数一个函数的链接
    所以就需要将入口函数放到文件的最开头,如果是多个文件(.o)
    则将入口函数所在的.o文件放到第一个去连接:
    例如:arm...ld .... -o xxx.elf  A.o B.o C.o ... //A.o文件中的第一个函数就是入口函数,所以A.o放到最开头

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值