当前位置:   article > 正文

arm裸机开发

arm裸机开发

裸机开发特点:

  • 1、 没有操作系统OS(Linux)
  • 2、 不可以使用系统调用
  • 3、 不能使用标准C/C++库(可以使用没有调系统调用的标准库函数接口)
  • 4、 可以直接访 问物理内存,如果开启MMU也可以访问虚拟内存
  • 5、 编译结果不能直接./运行,即不支持elf
  • 6、 执行之前必须要将可执行程序拷贝到指定物理内存
  • 7、 链接时需要用户手动指定物理内存将来执行的地址
  • 8、 手动将CPU的PC指向物理内存的入口地址处,从而开始执行自己的裸机程序(go 0x…)
    嵌入式:以计算机技术为基础,对软件硬件可裁剪,对功耗、体积、成本、可靠性都有严格要求的专用计算机系。

GNU常用工具

GNU组织不仅给我们带来了许多开源软件 工程,还带来了强大的GNU编译工具

  • 预处理器 cpp
  • C编译器 gcc
  • C++编译器 g++
  • 汇编器 as
  • 链接器 ld
  • 二进制工具集 objcopy、objdump、……

1、nm:符号显示器

$nm -n main_elf
  • 1
  • 第一列为符号地址
  • 第二列为符号所在段
  • 第三列为符号名称
    在这里插入图片描述
描述
b/B.bss(b静态/B非静态)未初始化变量
d/D.data(d静态/D非静态)已初始化变量
r/R.rodata(r静态/R非静态)只读数据段
t/T.text(t静态/T非静态)函数
A不可改变的绝对值
C.o中未初始化非静态变量
N调试用的符号
U表示符号只有声明没有定义

1.1、nm符号显示器总结:

  • 静态变量和非静态的全局变量,所分配的段只与其是否 初始化有关,如果初始化了则被分配 在.data段中,否 则在.bss段中
  • 函数无论是静态还是非静态的,总是被分配在.text中, 小写t表示静态,大写T表示非静态
  • 函数内的局部变量由于是分配在栈上的,所以在nm中是 看不到他们的

2、objdump:信息查看器

  • 查看所有段信息 $objdump -h main_elf
  • 查看文件头信息 $objdump -f main_elf
  • 查看反汇编 $objdump -d main_elf
  • 查看内嵌反汇编 $objdump -S -d main_elf
  • 可以查看有哪些段和段里面的信息 $objdump -s main_elf
    在这里插入图片描述

3、objcopy:段剪辑器

剪除elf格式信息,这样才能在裸机状态下执行

  • 去除elf格式信息 $objcopy -O binary -S main_elf main.bin

程序的编译链接过程

最后一步是将目标文件交给链接器链接生成 可执行文件

  • gcc -E -o main.i main.c
  • gcc -S -o main.S main.i
  • gcc -c -o main.o main.S
  • gcc -o main_elf main.o

1、什么是链接

将所用到的文件, 吧相应的代码放到相应的段里面,并给每个段安排一个起始地址;
在这里插入图片描述
在这里插入图片描述

  • 用户通常并不直接参与链接过程
  • 一个标准应用程序通常都由链接器采用默 认链接脚本(arm-linux-ld --verbose)将“用户 程序”和“库”共同链接生成可执行程序
  • 假如不采用系统给定的默认链接脚本,我 们应该怎样进行链接?
ld -o main main.o
  • 1

结论:

  • 链接过程中需要一个标号(_start)作为程序入口
  • 标号(_start)的作用是:将用户程序从汇编带到了C语 言程序入口,即main()函数,从此开始我们的应用程序 之旅
  • start标号所在的汇编文件在编译工具链下面: 4.3.2/arm-none-linux-gnueabi/libc/usr/lib/crt1.o
  • 如果没有crt1.o等标准库文件,我们可以自己实现_start入口,或者重新指定 一个新的入口
手动链接并生成可执行文件过程如下:
  • 直接通过参数指定程序入口和段地址: arm-linux-ld -Ttext=0x30000 -Tdata=0x40000 -e main -o app head.o main.o
  • 通过链接脚本来指定程序入口和段地址: arm-linux-ld -Tapp.lds -o app head.o main.o
//连接文件app.lds为: 
ENTRY(main) 
SECTIONS 
{
	//“*”号指所有目标,可以指定.o目标文件,多个用空格隔开 
	.=0x30000;//“.”指的是当前位置 
	.text:{*(.text)} 
	.=0x40000; 
	.data:{*(.data)} 
	.bss:{*(.bss)} 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

为什么需要我们自己完成链接过程?

裸机工程构建及调试

1、裸机程序完整编译过程:

案例,打印 hello IoT

int main()
{
	char *str = "\nhello IoT";
	char *p = 0xc00a1020;
	int i = 11;
	while(i--)
	{
		*p = *str++;
	}
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

裸机程序完整编译过程:

arm-linux-gcc -c -o t.o t.c	//只编译不连接
arm-linux-ld -o t t.o -e main -Ttext=0x47000000		//手动连接
arm-linux-objcopy -O binary -S t t.bin
  • 1
  • 2
  • 3

使用超级终端:
设置串口默认下载地址:
setenv loadaddr 0x47000000
查看设置的环境变量:printenv
上传.bin文件:loadb
运行:go 0x47000000
加粗样式

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/755400
推荐阅读
相关标签
  

闽ICP备14008679号