一、简答题(共20分,每题4分)

  1. 名词解释:PWM、DMA、AMBA、EMPU
    PWM脉宽调制(Pulse Width Modulation)(第5章Timer)
    DMA直接存储器访问(Direct Memory Access)(第5章)
    AMBA先进微控制器总线架构(Advanced Microcontroller Bus Architecture)(第5章S3C2440体系架构)
    EMPU嵌入式微处理器(Embedded Microprocessor Unit)(第1章嵌入式处理器)

  1. 根据嵌入式系统的特点,写出嵌入式系统的定义
    嵌入式系统是以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统功能、可靠性、成本、体积、功耗严格要求的专用计算机系统
    在这里插入图片描述

  1. 简述 ARM 处理器的 7 种运行模式及各自的用途。

    模式 说明
    用户(usr) 正常程序执行
    快速中断(fiq) 高速中断处理
    外部中断(irq) 通用中断处理
    管理(svc) 操作系统保护模式
    中止(abt) 内存访问异常处理
    未定义(und) 未定义指令异常
    系统(sys) 特权任务运行

    在这里插入图片描述
    在这里插入图片描述


  1. 什么是嵌入式处理器?嵌入式处理器分为哪几类?请举例说明。
    嵌入式处理器是嵌入式系统的硬件核心,是一种专用、高度定制化的计算机处理器。具有体积小、高稳定性、低功耗和环境适应性强等特点。
    在这里插入图片描述

分类:

类别 核心特征 举例
嵌入式微处理器(EMPU) CPU内核。需要外部扩展内存、总线和外设才能构成完整系统。是嵌入式系统中的“性能担当”,可运行复杂操作系统。 ARM架构:Cortex-A系列
嵌入式微控制器(EMCU) 单片机,将整个计算机系统集成到一块芯片中。 STM32系列
嵌入式数字信号处理器(EDSP) 专为数字信号处理算法优化。 德州仪器(TI):TMS320系列
嵌入式片上系统(ESoC) 在单一芯片上集成多个处理器核心 苹果A系列芯片

  1. ARM 体系结构相对于一般 RISC 指令集的特别之处表现在哪里?
    在这里插入图片描述

二、简单应用题(共20分,每题4分)

  1. 初始值 R1=23H,R2=0FH,执行指令
    BIC R0, R1, R2, LSL #1
    后,寄存器 R0 和 R1 的值分别是多少?

    R0:0x21
    R1:0x23(不变)
    在这里插入图片描述

在这里插入图片描述


  1. 小端模式下,[0x40003000]=0x11223344,请图示说明数据在存储器中是如何存储的。
    小端模式
    0x40003000 0X44
    0x40003001 0X33
    0x40003002 0X22
    0x40003003 0X11
    在这里插入图片描述
    在这里插入图片描述

  1. CMP 指令的操作是什么?写一个程序,判断 R1 的值是否大于 0x30,是则将 R1 减去0x30。
    CMP指令的格式是:CMP{<cond>} <Rn>, <op1>
    CMP指令执行 Rn - op1 的减法操作,并根据结果更新CPSR中的条件标志位(N、Z、C、V),但不保存减法结果。
CMP R1, #0x30 	;判断R1的值是否大于0x30
SUBHI R1, R1, #0X30	;	若大于(HI),则R1减去(SUB)0x30

条件码

cond 含义 英文助记
EQ 相等 Equal
NE 不等 Not Equal
CS/HS 无符号数大于等于 Carry Set/Unsigned High or Same
HI 无符号数大于 Unsigned High
CC/LO 无符号数小于 Carry Clear/Unisgned Lower
LS 无符号数小于等于 Unsigned Lower or Same

在这里插入图片描述


  1. 进行基于 ARM 核的嵌入式系统软件开发时,调用如下函数:
int Func1(int arg1, void *arg2, char arg3, int *arg4)

请说明这四个参数通过什么方式从调用程序传入被调函数?

前4个参数使用寄存器传递
根据 AAPCS(ARM Architecture Procedure Call Standard),前4个整型或指针参数依次通过 R0、R1、R2、R3 传递。这4个参数恰好全部使用寄存器,无需使用堆栈。
在这里插入图片描述


  1. 请指出 LDR 伪指令的用法。指令格式与 LDR 加载指令的区别是什么?

LDR伪指令格式为:
LDR <Rd>, =expr (加载立即数
LDR <Rd>, =label (加载标号地址
加载32位的立即数或一个地址值到目标寄存器Rd。

特性 LDR伪指令 LDR加载指令
本质 伪指令,在汇编期间由汇编器处理 机器指令,CPU直接执行
格式 LDR Rd, =expr/label(带等号 LDR{cond}{size} Rd, <addr>各种寻址模式
操作数 右操作数为立即数或标号 右操作数为内存地址表达式(如[Rn]、[Rn,#offset])
功能 将常数或地址加载到寄存器 内存地址加载数据到寄存器
汇编结果 可能被转换为一条或多条实际指令(如MOV或LDR从文字池读取) 直接对应一条二进制机器指令
用途 初始化寄存器值,获取变量/函数地址 内存数据访问,是加载/存储架构的核心

LDR伪指令是汇编器提供的便捷工具,用于加载常数和地址,其本质是汇编时的替换机制;而LDR加载指令是机器指令,是CPU执行的真实内存访问指令。
在这里插入图片描述


三、硬件应用题(共20分,每题4分)

  1. 说明 S3C2440 中断优先级管理模块的工作原理。
    S3C2440中断控制器采用两级仲裁机制来管理中断优先级:
    每个一级仲裁器(ARBITER0 ~ ARBITER5)从它管理的中断源中选择优先级最高的一个,输出到二级仲裁器。
    二级仲裁器(ARBITER6)从6个一级仲裁器的输出中再次选择优先级最高的一个,向ARM核发出中断请求。
    每一个仲裁器有两个控制信号:ARB_MODEARB_SEL
    ARB_MODE仲裁模式,0=固定优先级,1=循环优先级。
    ARB_SEL仲裁选择,指出最低优先级。01=REQ1,10=REQ2,11=REQ3,00=REQ4
    在这里插入图片描述
    在这里插入图片描述

  1. 阅读下列与看门狗有关的寄存器描述,解释每一行代码的功能
 #define rWTCON (*(volatile unsigned *)0x53000000)
 #define rWTDAT (*(volatile unsigned *)0x53000004)
 #define rWTCNT (*(volatile unsigned *)0x53000008)
 void watchdog_test(void)
 {
 rWTCON = ((PCLK/1000000-1)<<8)|(3<<3)|(1<<2); 	// 第1行
 rWTDAT = 7812;		// 第2行
 rWTCNT = 7812;		// 第3行
 rWTCON|=(1<<5);	 // 第4行
 }

(白话理解看门狗定时器功能,不严谨,帮助理解)
看门狗听着很高级,其实还是个定时器,基础功能用于定时。
首先要理解看门狗的三个寄存器:
WTCON:看门狗控制寄存器,Config,配置功能、数值、控制信息等。
WTDAT:看门狗数值寄存器,Data,决定定时多长时间,保存计数初值。
WTCNT:看门狗计数寄存器,Count,决定变化的节拍,保存当前的计数值。
大致理解定时过程:通过config配置,我们知道计数的最小单位(根据时钟频率等等),Data告诉我们总共要计数多少次,Count首先记为Data中的初值,开始工作后根据节拍持续的-1,-1,…,直至为0,产生中断,这一次规定的定时就完成了。

rWTCON = ((PCLK/1000000-1)<<8)|(3<<3)|(1<<2); 	// 第1行

配置看门狗控制寄存器 WTCON,设置预分频值时钟分频因子,并使能中断
预分频值和分频因子共同决定看门狗时钟频率。
中断使能,但看门狗定时器本身尚未使能(WTCON[5]仍为0),复位功能也未使能(WTCON[0]为0)。
在这里插入图片描述

rWTDAT = 7812;		// 第2行

设置看门狗数据寄存器 WTDAT 的值为 7812。
WTDAT 保存计数初值
当 WTCNT 递减到0时,自动将 WTDAT 中的值(7812)重新加载到 WTCNT。
在这里插入图片描述

rWTCNT = 7812;		// 第3行

设置看门狗计数寄存器 WTCNT 的当前值为 7812。
看门狗使能时,WTDAT 的值不会自动加载到 WTCNT。
必须在使能看门狗前手动给 WTCNT 赋初始值,否则可能因初值不确定而导致立即触发中断或复位。
在这里插入图片描述

 rWTCON|=(1<<5);	 // 第4行

使能看门狗定时器
看门狗定时器开始工作,WTCNT 从7812开始递减计数。在这里插入图片描述


  1. 当 PCLK 为 40MHz 时,串口 0 的波特率为 2400bps,串口 1 的波特率为 115200bps,相应的控制寄存器如何设置?
    UBRDIVn值的计算公式:
    UBRDIVn=round(源时钟波特率×16)−1UBRDIVn=round(\frac{源时钟}{波特率\times16})-1UBRDIVn=round(波特率×16源时钟)1
    串口0:UBRDIV0=round(40,000,0002400×16)−1=round(1041.6667)−1=1041UBRDIV0=round(\frac{40, 000, 000}{2400\times16})-1=round(1041.6667)−1=1041UBRDIV0=round(2400×1640,000,000)1=round(1041.6667)1=1041
    即UBRDIV0=0X411
    串口1:UBRDIV1=round(40,000,000115200×16)−1=round(21.7014)−1=21UBRDIV1=round(\frac{40, 000, 000}{115200\times16})-1=round(21.7014)−1=21UBRDIV1=round(115200×1640,000,000)1=round(21.7014)1=21
    即UBRDIV1=0X15
    在这里插入图片描述

  1. S3C2440 外部最大寻址空间是多少?分几个存储模块?使用哪些引脚作为片选信号
    S3C2440外部最大寻址空间是1GB,分8个存储模块,使用引脚nGCS7~0作为通用片选信号。
    在这里插入图片描述

  1. 说明 S3C2440 如何通过中断检测触摸屏的按压事件,并简述中断触发的条件和处理流程。

中断触发的条件:
等待中断模式下,触摸屏控制器监控XP、XM、YP、YM引脚的状态。
当触摸屏未被按下时,由于上拉电阻Y_ADC为高电平
当触摸屏被按下时,X和Y方向的导电层接触,导致Y_ADC的电压被拉低,从而产生一个低电平信号。产生INT_TC中断

处理流程简述:

  • 初始化:配置ADC和触摸屏接口的寄存器,ADCTSC设置为等待中断模式,并设置中断使能
  • 等待中断:系统进入等待状态,当触摸屏被按下时,硬件产生INT_TC中断
  • 中断服务程序
    在中断服务程序中,首先清除中断标志。
    然后,改变触摸屏工作模式(例如设置为自动XY坐标转换模式)。
    启动A/D转换,读取X和Y坐标值。
    处理坐标数据(例如通过串口输出)。
    重新配置为等待中断模式,以便检测下一次按压。
    清除中断并返回。
    在这里插入图片描述

四、程序设计题(共20分,每题10分)

  1. 编写完整的ARM汇编程序,实现读取 ARM 指令中 SWI 指令的立即数。

首先我们要明白我们在做什么?
step1:SWI指令是干什么的?
SWI指令是软件中断指令,是因为ARM指令在用户模式中受到很大的局限,有一些资源不能够访问,所以,我们使用软件控制-软件中断指令的方式访问这些资源。
那我们也就明白了,SWI软件中断指令是用于产生软件中断,调用系统历程。
~
step2:我们为什么想要读取SWI指令的立即数?
SWI指令的格式:SWI {<cond>} 24位立即数
其中24位立即数就是用于指定调用历程的类型。
我们根据这24位立即数就可以判断我们应该调用哪个系统历程。
~
setp3:如何读取SWI指令的立即数?
所以,当我们已经进入了SWI中断处理程序后,我们如何读取原先SWI指令中的这24位立即数呢?
这就是我们本题考查的内容:编写ARM汇编程序,读取ARM指令中SWI指令的立即数。

	T_bit EQU 0x20	;常量定义
SWI_Hander
	STMFD SP!, {R0-R3, R12, LR}	;现场保护
	MRS R0, SPSR	;读取SPSR到R0
	TST R0. #T_bit	;测试T位
	LDRNEH R0, [LR, #-2]	;读取16位Thumb指令码
	BICNE R0, R0, #0xFF00	;提取8位立即数
	LDREQ R0,[LR, #-4]	;读取32位ARM指令码
	BICEQ R0, R0, #0xFF000000	;提取24位立即数
	...
	LDMFD SP!, {R0-R3, R12, PC}^	;恢复现场并返回

迷了😵??别着急,主包现在就跟你一起研读代码😋!)
T_bit EQU 0x20 ;常量定义
EQU 是ARM汇编语言中的伪指令,用于定义符号常量
0x20的二进制为0010 0000,对应第5位为1
也就是:定义了一个T_bit符号常量,其数值为0x20,后续把它T_bit作为一个掩码,我们就可以知道一个数的第5位是0还是1。
在这里插入图片描述

STMFD SP!, {R0-R3, R12, LR} ;现场保护
LDMFD SP!, {R0-R3, R12, PC}^ ;恢复现场并返回
这两条指令我们合在一起看,STMFDLDMFD是堆栈寻址指令,用于数据栈与寄存器组之间批量数据传输。
我们经常会说,中断程序,保护现场,恢复现场等等,就是使用堆栈指令实现的。所以我们经常会在中断程序中看到他们。我们记住他们就可以!
STMFD满递减堆栈存储指令,其中R0-R3,R12是可能被中断处理程序修改的通用寄存器,LR(R14)包含返回地址,是我们需要保护的数据。
LDMFD恢复寄存器,从堆栈弹出到R0-R3,R12,PC。欸!有同学要问了,怎么冒出来个PC?
PC:将返回地址直接加载到程序计数器,即实现了跳转。
^后缀:将SPSR(特权异常模式)恢复到CPSR(全局)。
在这里插入图片描述

MRS R0, SPSR ;读取SPSR到R0
MRS:将程序状态寄存器CPSR的数据保存至通用寄存器R0中。(其实还是为了保存现场数据!)
还有跟他一对的MSR是将通用寄存器的数据写到程序状态寄存器中。
在这里插入图片描述
TST R0, #T_bit ;测试T位
TST指令:按位与操作并设置标志位Z,不保存结果。
我们刚刚得到了SPSR的数据在R0中,同时使用最开始定义的常量T_bit(0010 0000)作为掩码,二者,就可以巧妙地得到SPSR的第5位数是为0还是1。
Q1:为什么是第5位?程序状态寄存器CPSR/SPSR的第五位为T位,决定是ARM指令(32位)还是Thumb指令(16位)
T=0:ARM模式;T=1:Thumb模式。
在这里插入图片描述
结果若标志位Z:
Z=1:T位=0(ARM状态)
Z=0:T位=1(Thumb状态)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
Thumb状态处理(Z=0)
LDRNEH R0, [LR, #-2] ;读取16位Thumb指令码
BICNE R0, R0, #0xFF00 ;提取8位立即数
LDRH:半字数据加载指令(16位)
NE条件码:Z清零
在这里插入图片描述

Q:为什么是LR -2
三级流水线下,执行Thumb指令时PC值为:指令地址 + 4
发生异常时,LR = 异常返回地址 = SWI指令地址 + 4
因此:SWI指令地址 = LR - 4
但:Thumb指令长度为2字节,所以:
下一条指令地址 = SWI指令地址 + 2
实际LR保存的是:SWI指令地址 + 4(流水线原因)
因此:SWI指令地址 = LR - 2

BIC:位清除指令,将第二操作数为1的位,对应R0的位清0
Thumb SWI指令格式:11011111 imm8
高8位:0xDF(固定)
低8位:立即数
BICNE R0, R0, #0xFF00:清除高8位,保留低八位,把立即数存储到R0中。

在这里插入图片描述
ARM状态处理(Z=1)
LDREQ R0,[LR, #-4] ;读取32位ARM指令码
BICEQ R0, R0, #0xFF000000 ;提取24位立即数
同理✨
EQ条件码:Z=1满足条件
在这里插入图片描述

Q:为什么是 LR-4
ARM指令长度为4字节
流水线中PC值 = 指令地址 + 8
发生异常时,LR = SWI指令地址 + 8
因此:SWI指令地址 = LR - 8
但:ARM处理异常时,硬件会自动调整LR:
对于SWI异常,硬件将LR设置为:SWI指令地址 + 4
所以:SWI指令地址 = LR - 4
((这方面要详细讲起来其实还能讲好多,主包干不动了🥲)

ARM SWI指令格式:[cond:4][1111:4][imm24:24]
高8位:条件码(4位)+ 操作码(4位)
低24位:立即数
BICEQ R0, R0, #0xFF000000:清除高8位,保留低24位,把立即数存储到R0中。

(呕吼!搞定!多看几遍就能理解了!对照着知识点PPT看,遇到不明白的知识点就去翻一翻,实在不想花时间,直接背😖总能拿下的!😎)


  1. 使用 ARM 汇编语言实现给定符号函数:
    假定 x 是-5,编写程序实现符号函数的功能:
int sign(int x) {
	if (x > 0) return 1;
 	else if (x < 0) return-1;
 	else return 0;
}
; 代码段
    AREA    SignFunction, CODE, READONLY
    ENTRY

; 主程序入口
start
    LDR     R0, =x_value  ; 加载 x 的值 (-5) 到 R0
    BL      sign_function ; 调用符号函数
    LDR     R1, =result   ; 将结果存储到 result 变量
    STR     R0, [R1]

    ; 程序结束
    MOV     R0, #0x18
    LDR     R1, =0x20026
    SWI     0x123456

; 符号函数:sign(int x)
; 输入:R0 = x
; 输出:R0 = sign(x)
sign_function
    CMP     R0, #0  ; 比较 x 与 0
    MOVGT   R0, #1  ; 如果 x > 0,返回 1
    BGT     sign_exit
    MOVLT   R0, #-1 ; 如果 x < 0,返回 -1
    BLT     sign_exit
    MOVEQ   R0, #0  ; 否则 x == 0,返回 0

sign_exit
    BX      LR

; 数据段
    AREA    SignData, DATA, READWRITE
    
x_value DCD   -5        ; 假设 x = -5
result  DCD   0         ; 存储结果

    END

ARM汇编模板:


; 代码段
    AREA    Function, CODE, READONLY
    ENTRY

; 主程序入口
start
    ...

; 程序结束
stop
    MOV     R0, #0x18
    LDR     R1, =0x20026
    SWI     0x123456

; 数据段
    AREA    Data, DATA, READWRITE
...
    END

MOV, BL涉及的条件码:
在这里插入图片描述

在这里插入图片描述

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐