结合AliOS Things谈嵌入式系统通用问题定位方法(1):CPU相关基础

简介: 本文着重从问题定位的角度来介绍如何定位嵌入式软件系统中的问题,并结合AliOS Things提供的部分维测手段来介绍。

1、背景介绍

本文着重从问题定位的角度来介绍如何定位嵌入式软件系统中的问题,并结合AliOS Things提供的部分维测手段来介绍。

AliOS Things目前已经提供了丰富的Debug维测功能、离线的脚本解析,以及可视化的IDE工具来让用户快速上手使用我们的维测功能;相关的维测功能和工具也在实际开发项目中不断完善。

完善的维测工具一直是AliOS Things的主要发展的方向;但是从另一个方面来说,工具本身的作用也是有限的,嵌入式系统出现的问题可以说是千变万化;不同的开发者,对于工具提供的信息理解也不尽相同。我们在熟悉使用基本的维测工具的同时,还需要了解底层问题定位的基础知识,基本的定位手段和思路。解Bug的技术思路和维测工具的完善应该是相辅相成,相互促进的。

本文介绍了部分常用的嵌入式问题定位的基础知识和基本的手段。其中涉及到的AliOS Things内核一些已有的工具,以及一些内容的拓展和深入,读者可以自行了解和学习。

结合AliOS Things谈嵌入式系统通用问题定位方法(2):内核相关基础

结合AliOS Things谈嵌入式系统通用问题定位方法(3):问题定位思路

1.1、对象

嵌入式内核和驱动开发测试人员

协议栈、中间件开发测试人员

上层APP组件开发测试人员

1.2、目的

如何从底层软件源头上开始解bug

如何快速确认分流大量bug

从问题本身理解规范性代码如何编写

1.3、内容

结合AliOS Things内核来介绍:

解bug的必要知识点

解bug的通用方法、步骤、关键点

AliOS Things提供定位问题的手段、工具

本文介绍的内容主要以ARMv7架构为例,编译器为gcc。

2、CPU相关基础点

(以ARMv7a为例)

2.1、基础架构

!

Monitor:安全非安全

Hypervisor: 虚拟化

PL1:特权模式

PL0:用户模式

内核的内核态对应CPU的特权模式;

内核的用户态对应CPU的用户模式。

对于PL1,有7种子模式,我们主要关注:

SVC:内核正常运行模式

IRQ:中断进入模式

UND: 指令异常

ABT:数据异常

CPU当前状态可通过CPSR尾部的Mode状态寄存器来获取:


  1. .equ CPSR_Mode_USR, 0x10
  2. .equ CPSR_Mode_FIQ, 0x11
  3. .equ CPSR_Mode_IRQ, 0x12
  4. .equ CPSR_Mode_SVC, 0x13
  5. .equ CPSR_Mode_ABT, 0x17
  6. .equ CPSR_Mode_UND, 0x1B
  7. .equ CPSR_Mode_SYS, 0x1F

2.2、基础寄存器

32bit ARM汇编有16个32位寄存器:

- r0-r3 主要用来传递函数调用第1到第4个参数(a0-a3),更多的参数须通过栈来传递。

- r0-r1也作为结果寄存器,保存函数返回结果;被调用的子程序在返回前无须恢复这些寄存器的内容。

- r4-r9 为被调保存(callee-save)寄存器,一般保存内部局部变量(local variables)。

- r7 大部分情况用来保存系统调用号(syscall number)。

- r9 某些变体可能当作特殊寄存器。

- r10(SL)被调保存寄存器,Stack Limit。

- r11(FP)被调保存寄存器, 帧指针(Flame Pointer)。

- r12(IP)特殊寄存器,栈寄存器(Intra Procedure)。

- r13(SP)特殊寄存器,栈指针,类似x86_64中的RSP。

- r14(LR)特殊寄存器。Link Register.

- r15(PC)特殊寄存器。Program Counter (like RIP in x86_64 & EIP in x86)

其中注意几点:每个模式下SP(R13)独立,PC只有一个,LR独立,SPSR自动保存着进入该模式前的CPSR。Fiq比较特殊,R8~R14都是独立的。

2.3、协处理器

ARM体系架构支持协处理器,用于扩展ARM处理器功能。协处理器指令用于访问协处理器。协处理器支持16个协处理器,编号0-15,使用CP0-CP15描述。

  • CP15:提供系统控制功能。包括架构和特性ID,以及控制,状态信息和配置支持。
  • CP14:提供硬件Debug功能。
  • CP10,CP11:共同支持浮点运算和向量操作。控制和配置浮点和高级SIMD扩展架构。
  • CP8,9,12,13:为ARM架构保留协处理器。
  • CP0-7:由厂家定义协处理功能

2.4、基础指令

ARM提供两种指令编码格式:Thumb(2)、ARM指令集

ARM指令集每条指令固定为4 字节大小;

Thumb(2)指令集每条指令为2或者4字节大小;

具体细节不在此赘述。

2.5、压栈出栈相关

压栈出栈指令可以用下面表格来概括:

!

其中LDM的后缀对应关系:

FA: full + add 满增

FD:full + decrease 满减

EA:empty + add 空增

ED:empty + decrease 空减

IA: increment after 先取值,SP后增加

IB: increment before SP先增加,后取值

DA: decrement after 先取值,SP后减小

DB: decrement before SP先减小,后取值

目前一般使用的是:

LDMIA :弹栈时,先取SP内数据,后SP地址增大

STMDB :压栈时,SP地址先减小,后开始存放数据

2.6、异常

异常寄存器:

主要关注四个寄存器,来判断访问哪个地址出现了何种异常:

DFSR:数据异常状态寄存器

DFAR:导致数据异常的地址

IFSR:指令异常状态寄存器

IFAR:导致指令异常的地址

2.7、MMU/MPU相关

对于MPU和MMU的细节,用户可不需要关注。但是需要了解基本概念。

MPU针对ARM-M系列,可以设定特殊内存段的属性是特权还是非特权访问,没有虚拟和物理的映射;

MMU针对ARM-A系列,包含虚拟和物理的映射,以及各种权限的控制。

M系列的用户态有特权和非特权之分;

A系列的用户态即对应最小用户权限模式。

对于访问地址的权限问题,有时需要查看MMU页表,去核对属性。

容易遇到的问题:

  • 访问权限问题,如代码段数据段的权限问题
  • 页表覆盖导致内存空间冲突问题

2.8、函数/数据断点

函数和数据断点是CPU提供的基本调式Debug功能。

对应gdb的对函数打断点,watch监控某一块内存的修改访问,以及进一步的单步调试功能。

2.9、编译汇编链接相关

2.9.1、需关注编译选项

Cpu相关:

-mcpu=cortex-a7 :指定cpu架构

-mfpu=neon-vfpv4 :浮点数、neno指令

-mfloat-abi=hard :软硬浮点

emu相关:

-fshort-enums

sizeof(enum1)不增加这个-fshort-enums选项的时候为4,增加后为该enum实际可以存放的最小字节数据类型,如1字节。

默认不设定,一旦设置就选用节省内存的enum长度

编译告警相关:

-Wall : 编译显示所有告警

-Werror: 所有的警告当成错误进行处理

-Wfatal-errors:出现错误停止编译

-w : 关闭告警

需要使用gdb查看详细的数据结构信息:

加入-g选项

2.9.2、汇编注意点

函数跳转指令(B、BL、BLX):

BL 和 BLX 指令可将下一个指令的地址复制到 LR(r14,链接寄存器)中。

BX 和 BLX 指令可将处理器的状态从 ARM 更改为 Thumb,或从 Thumb 更改为 ARM。

BLX label 无论何种情况,始终会更改处理器的状态。

BX Rm 和 BLX Rm 可从 Rm 的位 [0] 推算出目标状态:

如果 Rm 的位 [0] 为 0,则处理器的状态会更改为(或保持在)ARM 状态

如果 Rm 的位 [0] 为 1,则处理器的状态会更改为(或保持在)Thumb 状态。

反汇编别名:

在查看汇编时,通用寄存器会有特殊的别名,常用对应如下:

R10 sl 栈限制

R11 fp 桢指针

R12 ip

R13 sp 栈指针

R14 lr 连接寄存器

R15 pc 程序计数器

函数入参传递:

对于ARM-32位处理器,R0、R1、R2、R3寄存器分别作为函数的第0个至第3个入参,超出入参使用栈空间;

32位函数出参统一使用R0。

调用者报错和被调用者保存的寄存器:

被调用函数只会保存被自己上下文修改的R4开始的寄存器,R0~R3由调用栈按需保存。

指令编码:

每条指令都有固定的编码格式,否则就是非法指令。动态加载/调用栈解析等会有对指令修改的操作,一般对定位问题有两个小用途:

  • 看开栈大小:主要有没有定义过大的数组,通过sub sp的指令来搜索立即数的大小;

e24dd014 sub sp, sp, #20

  • 强制修改指令

在代码段可修改的情况下,强制修改指令,达到某种如进入死循环,强制跳转的目的

2.9.3、ELF结构相关

ELF内是比较复杂的数据结构,其中分可重定位文件(.o)、共享目标文件(.so)、以及可执行文件(elf)。二进制bin文件不属于elf格式,而是没有elf的头部和相关符号等信息,纯碎装载的可执行段的二进制文件。内部结构比较复杂,只介绍基本定位问题使用的。

Elf中的section:一般在ld中可见定义的描述,如下面即是一个section


 
  1. . data : {
  2. __data_start = .;
  3. *(. data)
  4. *(. data.*)
  5. __data_end = .;
  6. } > DRAM_ADDR

Elf中的段:在最后链接时,链接器会将各个section组合成最终的几个段,当然可以在ld中显示地关联段。

Section一般存在于尚未链接的可重定位文件,最终生成可执行的elf中都是组合的段信息

!

基本查看ELF信息的编译器工具:

  • 查看ELF头部信息、段组成

  
arm-none-eabi-readelf -lS ./helloworld@developerkit.elf

结果示例:

  • Elf转汇编

   
localhost: arm-none-eabi-objdump -d ./helloworld @developerkit.elf

  • 查找符号

    
  1. localhost: arm-none-eabi-nm ./helloworld @developerkit.elf | grep aos_init
  2. 080021f8 T aos_init

相关信息也可通过map文件,其同样也是通过elf生成。

  • addr2line

     
  1. localhost: arm-none-eabi-addr2line -e ./helloworld @developerkit.elf 0x80021f8
  2. /workspace/aos_gerrit_new/core/osal/aos/rhino. c: 815

通过指令地址,导出对应C的文件名和行数

对于C++一般使用 –pfiCe选项

  • C++函数名

汇编中C++的函数名非常复杂,可通过下面命令输入正常的函数名:


      
  1. localhost: arm-none-eabi-c++filt smartbox @mt8153a-mk.app.elf _ZN17GwMeshControlInfoD1Ev smartbox @mt8153a-mk.app.elf
  2. GwMeshControlInfo::~GwMeshControlInfo()

开发者技术支持

如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号

更多技术与解决方案介绍,请访问阿里云AIoT首页https://iot.aliyun.com/

目录
打赏
0
0
0
0
12433
分享
相关文章
软考软件评测师——计算机组成与体系结构(CPU指令系统)
本内容详细解析了计算机中央处理器(CPU)的核心架构及其关键组件的工作原理。首先介绍了CPU的四大核心模块:运算单元、控制单元、寄存器阵列和内部总线,并阐述其在数据处理中的核心职责。接着深入探讨了算术逻辑部件(ALU)的功能与专用寄存器的作用,以及通用寄存器对性能提升的意义。随后分析了控制单元的指令处理流程及特殊寄存器的功能。此外,还解析了寄存器系统的分类与设计特点,并对比了不同内存访问模式的特点与应用场景。最后,通过历年真题巩固相关知识点,帮助理解CPU各组件的协同工作及优化策略。
快速定位并优化CPU 与 JVM 内存性能瓶颈
本文介绍了 Java 应用常见的 CPU & JVM 内存热点原因及优化思路。
821 166
|
3月前
|
【Function App】如果一个拥有多个Function App的Plan遇见了High CPU问题? 如何方便定位是哪一个Function App引发的呢?
在Azure Function App测试中,若多个Function App共用同一App Service Plan资源,当出现High CPU问题时,由于Function App公开指标无法直接观测CPU状态,可通过启用Application Insights解决。其Live Metrics功能可过滤并查看每个Function App的CPU使用情况。具体步骤为:将所有Function App连接至同一Application Insights资源,进入Live Metrics页面按Role筛选监控数据。附有三段C#代码示例,分别展示占用CPU、Memory及普通功能的实现方法。
132 36
|
4月前
|
Linux系统中如何查看CPU信息
本文介绍了查看CPU核心信息的方法,包括使用`lscpu`命令和读取`/proc/cpuinfo`文件。`lscpu`能快速提供逻辑CPU数量、物理核心数、插槽数等基本信息;而`/proc/cpuinfo`则包含更详细的配置数据,如核心ID和处理器编号。此外,还介绍了如何通过`lscpu`和`dmidecode`命令获取CPU型号、制造商及序列号,并解释了CPU频率与缓存大小的相关信息。最后,详细解析了`lscpu`命令输出的各项参数含义,帮助用户更好地理解CPU的具体配置。
507 8
详解Hyper-V虚拟机CPU分配方法
在Hyper-V环境中,合理分配虚拟机的CPU资源至关重要。vCPU是物理CPU的虚拟化表示,管理员可通过指定处理器数量、核心数、设置兼容性和亲和性、启用动态分配等方法优化性能。使用性能监视工具监控并调整CPU资源,避免过度分配,确保虚拟机稳定运行。定期评估和优化资源分配策略,以适应业务变化,保持最佳性能。
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
111 0
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
|
6月前
|
【Azure App Service】对App Service中CPU指标数据中系统占用部分(System CPU)的解释
在Azure App Service中,CPU占比可在App Service Plan级别查看整个实例的资源使用情况。具体应用中仅能查看CPU时间,需通过公式【CPU Time / (CPU核数 * 60)】估算占比。CPU百分比适用于可横向扩展的计划(Basic、Standard、Premium),而CPU时间适用于Free或Shared计划。然而,CPU Percentage包含所有应用及系统占用的CPU,高CPU指标可能由系统而非应用请求引起。详细分析每个进程的CPU占用需抓取Windows Performance Trace数据。
161 40
Linux系统查看操作系统版本信息、CPU信息、模块信息
在Linux系统中,常用命令可帮助用户查看操作系统版本、CPU信息和模块信息
891 23
转载:【AI系统】CPU 基础
CPU,即中央处理器,是计算机的核心部件,负责执行指令和控制所有组件。本文从CPU的发展史入手,介绍了从ENIAC到现代CPU的演变,重点讲述了冯·诺依曼架构的形成及其对CPU设计的影响。文章还详细解析了CPU的基本构成,包括算术逻辑单元(ALU)、存储单元(MU)和控制单元(CU),以及它们如何协同工作完成指令的取指、解码、执行和写回过程。此外,文章探讨了CPU的局限性及并行处理架构的引入。
转载:【AI系统】CPU 基础
转载:【AI系统】CPU 计算本质
本文深入探讨了CPU计算性能,分析了算力敏感度及技术趋势对CPU性能的影响。文章通过具体数据和实例,讲解了CPU算力的计算方法、算力与数据加载之间的平衡,以及如何通过算力敏感度分析优化计算系统性能。同时,文章还考察了服务器、GPU和超级计算机等平台的性能发展,揭示了这些变化如何塑造我们对CPU性能的理解和期待。
转载:【AI系统】CPU 计算本质

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问