百问网智能家居ARM架构的一些知识点

Posted pupuhetu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了百问网智能家居ARM架构的一些知识点相关的知识,希望对你有一定的参考价值。

从入门单片机以来,我所用来学习的板子都是ST公司的。他们公司有写好的标准库,HAL库,LL库供学习者使用。但是我觉得这不利于理解单片机工作原理,因为在以后的学习或是工作里,总有遇到其他公司芯片的时候。这就涉及到了寄存器操作等知识。因为ARM架构在嵌入式领域使用较为广泛,所以我在韦东山老师的课程下学习了相关知识。以下内容大部分源于韦老师的课件。

官网就有很多免费的课程,很适合新手入门,韦老师在B站也有课程,我就是B站搜索发现的。下面是韦东山老师团队的官网及B站地址:
新版官网:http://100ask.org/
旧版官网:https://www.100ask.net/
B站链接:https://space.bilibili.com/275908810/channel/detail?cid=135681

一、ARM与x86的区别

首先是操作地址空间的区别,ARM根据cpu发出的不同地址选择不同的设备,包括内存,串口等设备,不区分IO和内存,直接把IO空间映射到内存空间,访问方法都是用内存空间的方式操作。x86是根据cpu发出的不同指令选择不同设备,并且在cpu眼里内存和IO是隔离开的,IO空间使用完全不同的指令来访问。

其次就是指令集,ARM芯片属于精简指令集计算机(RISC:Reduced Instruction Set Computing)。它所用的指令比较简单,有如下特点: 对内存只有读、写指令;对于数据的运算是在CPU内部(即寄存器)实现,所以RISC设定多组寄存器来加速程序的运算;使用RISC指令的CPU复杂度小一点,易于设计。

x86属于复杂指令集计算机(CISC:Complex Instruction Set Computing),它所用的指令比较复杂,比如某些复杂的指令,它是通过“微程序”来实现的。比如执行乘法指令时,实际上会去执行一个“微程序”。CISC架构的很多复杂指令都通过CPU内的微码来完成,会影响效率。但是CISC的指令集丰富,编译器设计可以更简单。CISC允许数据处理指令对内存进行直接操作,需要的寄存器数量减少。

二、ARM内部寄存器及汇编知识

ARM架构中CPU内部都有R0-R15寄存器,分别用来暂存不同的数据。

ARM体系结构提供了十六个32位通用寄存器(R0-R15)供软件使用。其中的15个(R0-R14)可用于通用数据存储,而R15是程序计数器,其值随处理器执行指令而改变。显式地写入R15可以更改程序流程。软件还可以访问CPSR和SPSR。SPSR中保存的上一个运行模式的CPSR的副本。
同一个寄存器可能在不同模式下对应物理上不同的位置。只有特定模式下才能访问到这些位置的寄存器。
有些寄存器,不同的工作模式下有自己的副本,当切换到另一个工作模式时,那个工作模式的寄存器副本将被使用,这些寄存器被称为备份寄存器。备份寄存器在物理上使用不同的存储,通常仅在特定模式下才可以访问它们。下图中带阴影标记的寄存器都是备份寄存器。

在所有模式下,“低位寄存器”和R15共享相同的物理存储位置。图3-5显示了某些模式下的某些“高位寄存器”被备份。例如,FIQ模式下使用R8-R12备份寄存器,也就是说,FIQ模式下对其的访问将转到另一个物理存储位置。对于除用户和系统模式以外的所有模式,R13和SPSR都是备份寄存器。
对于备份寄存器,软件通常不会指定要访问哪个模式下的寄存器,这是由当前运行的模式隐含的。例如,在用户模式下使用R13时实际上将访问R13_usr,而在SVC模式下将访问R13_svc。
R13(在所有模式下)是堆栈指针,但是当堆栈操作不需要时,它可以用作通用寄存器。
R14(链接寄存器)保存BL分支指令的下一条指令的地址。当它不支持子程序的返回时,它也可以用作通用寄存器。R14_svc,R14_irq,R14_fiq,R14_abt和R14_und同样用于在发生中断和异常时,或者执行转移和链接指令时,备份R15的返回值。
R15是程序计数器并保存当前程序地址(实际上,在ARM状态下,它始终指向当前指令之后的八个字节,而在Thumb状态下,它始终指向当前指令之后的四个字节,这是原始ARM1的三级流水线的遗留特性)。在ARM状态下读取R15时,位[1:0]为零,位[31:2]包含PC值。在Thumb状态下,位[0]始终读为零。
R0-R14的复位值是不定的。在使用堆栈之前,必须通过引导代码初始化SP(堆栈指针)。因为每种模式下的R13即SP寄存器都有自己的实体,所以你用到哪种模式,就需要单独为该模式设置SP。ARM体系结构过程调用标准(AAPCS)或ARM嵌入式ABI(AEABI)指定了软件应如何使用通用寄存器,以便在不同的工具链或编程语言之间进行互操作。

M系和A系稍有不同。M系的程序状态保存在xPSR里,A系保存在CPSR里。

xPSR在其内部又被分为三个子状态寄存器:
应用程序 PSR(APSR);中断号 PSR(IPSR);执行 PSR(EPSR)
通过 MRS/MSR 指令,这 3 个 PSRs 即可以单独访问,也可以组合访问(2 个组合,3 个组合都可以)。当使用三合一的方式访问时,应使用名字“xPSR”或者“PSR”。

汇编指令可以分为几大类:数据处理、内存访问、跳转、饱和运算、其他指令
数据处理指令的UAL汇编格式为:

Operation表示各类汇编指令,比如ADD、MOV;
cond表示conditon,即该指令执行的条件;
S表示该指令执行后,会去修改程序状态寄存器;
Rd为目的寄存器,用来存储运算的结果;
Rn、Operand2是两个源操作数

内存访问指令:读内存指令LDR/LDM,写内存指令STR/STM,
LDM:Load Multiple Register;
STM:Store Multiple Register。

LDR使用伪指令将任意数值赋给寄存器,LDR作为“伪指令”时,指令中有一个“=”,否则它就是真实的LDR(load regisgter)指令了。由编译器将伪指令替换成真实指令。

ADR的意思是:address,用来读某个标号的地址,它是伪指令,ADR伪指令会被编译器替换成一条合适的指令,通常,编译器会用一条ADD指令或SUB指令来实现该ADR伪指令的功能,如果不能用一条指令来实现ADR伪指令的功能,编译器将会报错。

LDR 和 ADR 都有能力产生一个地址,但是语法和行为不同。对于 LDR,如果汇编器发现要产生立即数是一个程序地址,它会自动地把 LSB 置位,ADR则不会修改LSB。LDR 通常是把要加载的数值预先定义,再使用一条 PC 相对加载指令来取出。而 ADR 则尝试对 PC 作算术加法或减法来取得立即数。因此 ADR 未必总能求出需要的立即数。其实顾名思义,ADR 是为了取出附近某条指令或者变量的地址,而 LDR 则是取出一个通用的 32 位整数。因为 ADR 更专一,所以得到了优化,故而它的代码效率常常比 LDR的要高。

常用的”满减“:入栈(STMFD/STMDB)出栈(LDMFD/LDMIA)
sp的顺序原则是低标号的寄存器对应低地址,高标号的寄存器对应高地址。
根据栈指针指向,可分为满(Full)/空(Empty):
满SP指向最后一个入栈的数据,需要先修改SP再入栈
空SP指向下一个空位置,先入栈再修改SP

跳转指令的核心指令是
B:Branch,跳转
BL:Branch with Link,跳转前先把返回地址保持在LR寄存器中
BX:Branch and eXchange,根据跳转地址的BIT0切换为ARM或Thumb状态(0:ARM状态,1:Thumb状态)
BLX:Branch with Link and eXchange 根据跳转地址的BIT0切换为ARM或Thumb状态(0:ARM状态,1:Thumb状态)

了解完这些之后,还是要自己手撸一遍点灯的汇编过程,才会记得更加深刻。

Buildroot系统构建学习笔记(以百问网imx6ull开发板为例)

点击上方「嵌入式云IOT技术圈」,选择「置顶公众号」第一时间查看嵌入式笔记!

最近在学习音视频开发相关的内容,故硬件选型是非常重要的,加上芯片缺货,为了保证未来芯片供应链正常,结合预测趋势以及对芯片行业相关的定量分析 ,最终我选择了瑞芯微刚推出不久的芯片:RV1126_RV1109系列,为了高效学习,我将瑞芯微平台SDK里提供的docs目录下的文档做了分类整理和汇总,以便后期在工作中用到相应的知识可以很快的查阅到相关的资料高效完成调试和开发:

这个平台构建系统的方式采用的是buildroot构建,所以系统学习buildroot将有利于开展接下来的工作,这也是目前嵌入式开发的发展方向!

开发板之类的,原理都是相通的,通一个则一通百通,所以我就用百问网提供的imx6ull开发板和文档教程来学习和总结吧

以上是关于百问网智能家居ARM架构的一些知识点的主要内容,如果未能解决你的问题,请参考以下文章

关于ARM架构的一些知识

ARM Cortex-A7 MPCore架构基础知识

ARM PWN基础教程

安卓智能手机的基于ARM架构的处理器,为啥能够支持基于Linux内核的操作系统?

ARMv8架构的沿革

ARM处理器架构理论知识