目录
前言
主要介绍基于linux开发环境下,如何开发ARM A7
ARM启动及开发基础
1.Cortex-A架构
1)Cortex-A7运行模式
模式 | 说明 |
---|---|
User(USR) | 用户模式,非特权模式,大部分程序运行的时候就处于此模式。 |
FIQ | 快速中断模式,进入FIQ中断异常 |
IRQ | 一般中断模式。 |
Supervisor(SVC) | 超级管理员模式,特权模式,供操作系统使用。 |
Monitor(MON) | 监视模式?这个模式用于安全扩展模式。 |
Abort(ABT) | 数据访问终止模式,用于虚拟存储以及存储保护。 |
Hyp(HYP) | 超级监视模式?用于虚拟化扩展。 |
Undef(UND) | 未定义指令终止模式。 |
System(SYS) | 系统模式,用于运行特权级的操作系统任务 |
2)寄存器组
①包含低寄存器组(R0-R7)、高寄存器组(R8-R5)、堆栈指针SP、链接寄存器LR、程序计数器PC、当前程序状态寄存器CPRS、备份程序状态寄存器SPSR
②除了FIQ模式,其他工作模式共用通用寄存器。SPSR 的作用是当发生异常时备份 CPSR 的状态,也就是说 SPSR 保存的是执行异常处理函数前的 CPSR 的值。CPRS寄存器的M[4:0]为处理器模式控制位。
2.启动方式
1)启动方式选择
当mode选择10即内部boot模式时,CFG引脚设置
2)镜像组成
①Image Vector Table简称IVT,IVT里面包含了一系列的地址信息,这些地址信息在ROM 中按照固定的地址存放着。
②Boot data,启动数据,包含了镜像要拷贝到哪个地址,拷贝的大小是多少等等
③Device configuration data,简称 DCD,设备配置信息,重点是 DDR3 的初始化配置
④用户代码可执行文件,比如 led.bin
imxdownload 所生成的 load.imx 就是在 led.bin 前面加上 IVT+Boot data+DCD。内部 BootROM 会将 load.imx 拷贝到 DDR 中,用户代码是要一定要从 0X87800000 这个地方开始的,因为链接地址为 0X87800000,load.imx 在用户代码前面又有 (4-1)3KByte 的 IVT+Boot Data+DCD 数据,因此 load.imx 在 DDR 中的起始地址就是 0X87800000-3072=0X877FF400。
3.汇编基础
1)label:instruction @ comment
2)函数名:
函数体
返回语句
3)伪操作
指令 | 功能 |
---|---|
.byte | 定义单字节数据,比如.byte 0x12。 |
.short | 定义双字节数据,比如.short 0x1234。 |
.long | 定义一个 4 字节数据,比如.long 0x12345678。 |
.equ | 赋值语句,格式为:.equ 变量名,表达式,比如.equ num, 0x12,表示 num=0x12。 |
.align | 数据字节对齐,比如:.align 4 表示 4 字节对齐。 |
.end | 表示源文件结束。 |
.global | 定义一个全局符号,格式为:.global symbol,比如:.global _start。 |
4)存储区访问指令
5)跳转指令
6)数据传输指令
7)逻辑运算指令
8)压栈和出栈指令
9)算术运算指令
4.Makefile语法基础
1)目标与依赖
[目标]:[依赖]
[命令]
2)伪目标(不期待生成目标文件)
.PHONY:[依赖]
3)使用变量
①"=":延迟赋值,该变量只有在调用的时候,才会被赋值
②":=":直接赋值,延迟赋值相反,使用直接赋值的话,变量的值定义时就已经确定了。
③"?=":若变量值为空,则进行赋值,通常用于设置默认值
④"+=":追加赋值,可以往变量后面增加新的内容
⑤ $(变量名):调用变量
4)改造规则
①%是通配符功能类似于*
② $@代表目标
③ $<代表第一个依赖文件
④ $^表示所有的依赖文件
5)使用分支
ifeq(arg1, arg2) #若arg1与arg2值相同则为真
分支1
else
分支2
endif
6)使用函数
格式: ( 函数名参数 ) 或者 (函数名 参数)或者 (函数名参数)或者{函数名 参数}
① $ (notdir 文件名):去除文件路径中的目录部分
② $(wildcard 匹配规则):用于获取文件列表,并使用空格分隔开
③ $(patsubst 匹配规则, 替换规则, 输入的字符串):当输入的字符串符合匹配规则,那么使 用替换规则来替换字符串
④ $(foreach < var>, < list >,< text>):是把参数< list>中的单词逐一取出来放到参数< var>中,然后再执行< text >所包含的表达式。< text>所返回的每个字符串所组成的整个字符串将会是函数 foreach 函数的返回值
5.Makefile补充
1)调用数学库用"-L"指定库所在的目录
c
LIBPATH := -lgcc -L /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.4
2)-Wall选项意思是编译后显示所有警告
3)-nostdlib 不连接系统标准启动文件和标准库文件.只把指定的文件传递给连接器
4)加入选项"-fno-builtin"表示不使用内建函数
5)添加了选项"-Wa,-mimplicit-it=thumb",避免报错thumb(拇指?) 条件指令应该在IT(?)块中
c
$(CC) -Wall -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin -c -O2 $(INCLUDE) -o $@ $<
4)加入了"-march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard"指令,这些指令用于
指定编译浮点运算的时候使用硬件 FPU
c
$(CC) -Wall -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin -c -O2 $(INCLUDE) -o $@ $<
6.编译下载
1)arm-linux-gnueabihf-gcc编译文件
powershell
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
其中"-g"选项是产生调试信息,GDB 能够使用这些调试信息进行代码调试。"-c"选项是编译源文件,但是不链接。"-o"选项是指定编译产生的文件名字
2)arm-linux-gnueabihf-ld 链接文件
powershell
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
-Ttext 就是指定链接地址,"-o"选项指定链接生成的 elf 文件名
3)arm-linux-gnueabihf-objcopy 格式转换
powershell
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
"-O"选项指定以什么格式输出,后面的"binary"表示以二进制格式输出,选项"-S"表示不要复制源文件中的重定位信息和符号信息,"-g"表示不复制源文件中的调试信息,最终生成led.bin文件
4)arm-linux-gnueabihf-objdump 反汇编
powershell
arm-linux-gnueabihf-objdump -D led.elf > led.dis
"-D"选项表示反汇编所有的段
5)给予烧写软件imxdownload 可执行权限:chmod 777 imxdownload
6)确定要烧写的 SD 卡:ls /dev/sd* (或者lsblk)-> 看分区找到对应卡
7)向SD卡烧写bin文件:./imxdownload led.bin /dev/sdb
结语
有关linux系统移植,见以下文章
https://blog.csdn.net/weixin_44567668/article/details/128507480