- Cortex-M是32位RISC处理器,这意味着其数据总线、内部寄存器和指令长度都固定为32位。
- 答案:× (错误)
- 解析: 虽然数据总线和寄存器是32位的,但Cortex-M支持的Thumb-2指令集是变长指令集,包含了16位和32位两种长度的指令,并非固定的32位。
- Cortex-M4处理器采用小端模式,这意味着一个32位数据
0x12345678
存放在地址0x20000000
时,地址0x20000003
处存放的是数据0x12
。 - 答案:√ (正确)
- 解析: 小端模式(Little-Endian)指数据的低位字节存放在内存的低地址处,高位字节存放在高地址处。对于
0x12345678
,78
是最低位字节,12
是最高位字节。因此,存放地址从低到高依次为0x78
(0x20000000)、0x56
(0x20000001)、0x34
(0x20000002)、0x12
(0x20000003)。
- 为了访问效率,Cortex-M处理器要求所有类型的数据(字节、半字、字)都必须进行地址对齐。
- 答案:× (错误)
- 解析: 字节(8位)访问没有对齐要求,可以在任意地址进行。只有半字(16位)和字(32位)访问才建议进行地址对齐(地址分别是2和4的倍数)以获得最佳性能。部分Cortex-M核支持非对齐访问,但会牺牲性能。
- Cortex-M的三级流水线在遇到跳转指令时,需要清空流水线,这会导致性能损失。
- 答案:√ (正确)
- 解析: 跳转指令(如B, BL, BX)会改变程序的正常执行顺序,导致流水线中已经取指和译码的指令变为无效,必须被清空(Flush),然后从新的目标地址重新开始取指,这会引入几个时钟周期的延迟。
- Cortex-M的GPIO引脚在上电复位后,其状态与8051单片机一样,都为高电平输出状态。
- 答案:× (错误)
- 解析: 根据笔记,Cortex-M的GPIO在复位后通常被配置为高阻态输入模式,以防止对外部电路产生不确定的驱动。而8051的I/O口(P1-P3)复位后是高电平状态。
- Cortex-M采用改进型哈佛结构,其程序总线和数据总线在硬件上是分离的,但地址空间是统一的。
- 答案:√ (正确)
- 解析: 这是改进型哈佛结构的典型特征。分离的总线允许处理器同时进行取指和数据访问,提高了性能。而统一的4GB地址空间意味着程序代码、数据和外设都在同一个地址映射中,可以通过地址方便地访问。
- 所有16位和32位的Thumb-2指令都可以无差别地访问R0-R12所有通用寄存器。
- 答案:× (错误)
- 解析: 这是一个重要的区别。许多紧凑的16位Thumb指令只能访问低寄存器组(R0-R7),而32位指令则可以访问所有通用寄存器(R0-R12)。
- 在Cortex-M中,主栈指针MSP和进程栈指针PSP在物理上是两个完全独立的寄存器。
- 答案:√ (正确)
- 解析: 处理器内部确实存在两个物理的栈指针寄存器。在任何时刻,只有一个是当前活动的SP,具体是哪个由CONTROL寄存器控制。这种设计是为了在操作系统环境中安全地隔离内核和用户任务的堆栈。
- 执行
BL Label
指令后,返回地址被存入R14(LR),此时LR中存放的是Label
的地址。 - 答案:× (错误)
- 解析:
BL
是带链接的跳转指令。LR中存放的是下一条指令的地址,即BL
指令执行完毕后应该返回的地方,而不是跳转目标Label
的地址。
MOV PC, LR
这条指令可以实现从子程序返回,其效果与BX LR
完全相同。- 答案:× (错误)
- 解析:
MOV PC, LR
可以实现跳转,但它不等同于BX LR
。BX
指令会检查LR最低位来判断目标代码是ARM还是Thumb状态,而MOV
指令不会,它仅仅是把地址值传给PC。在Cortex-M中,必须保持Thumb状态,因此标准的返回指令是BX LR
或POP {PC}
。
- 读取PC寄存器的值,得到的是当前正在执行指令的地址。
- 答案:× (错误)
- 解析: 由于三级流水线的存在,当一条指令正在“执行”阶段时,PC已经指向了“取指”阶段的指令。因此,读取PC得到的值是“当前执行指令的地址 + 4”。
- xPSR寄存器由APSR、IPSR和EPSR三部分组成,程序员可以通过
MSR
指令一次性修改xPSR中的所有位。 - 答案:× (错误)
- 解析: 程序员只能访问和修改APSR中的标志位,以及通过特定指令影响IPSR和EPSR。例如,EPSR中的T位是只读的,且必须为1,不能被修改。
- IPSR寄存器中的数值为0时,表示当前处理器不处于任何异常或中断服务模式下。
- 答案:√ (正确)
- 解析: IPSR(中断程序状态寄存器)用于记录当前激活的异常编号。当没有异常或中断在服务时,其值为0,这被称为线程模式(Thread Mode)。
- APSR中的S标志位(饱和标志)与N、Z、C、V标志位一样,可以作为条件转移指令的判断依据。
- 答案:× (错误)
- 解析: 根据笔记,S(Saturation)标志位用于指示饱和运算的状态,但它不作为条件转移的依据。条件转移只依赖于N, Z, C, V四个标志位。
- 对字变量
LDR R0, [R1]
和半字变量LDRH R0, [R1]
进行非对齐访问时,处理器会产生一个硬件错误(HardFault)。 - 答案:× (错误)
- 解析: 不一定。这取决于处理器的配置。如果使能了非对齐访问,处理器会通过多次总线访问来完成操作,只是会降低性能。如果禁止了非对齐访问,才会产生用法错误(UsageFault),如果用法错误也被禁止,它可能会升级为硬件错误。
- Cortex-M的堆栈是向上生长的满栈模型,即SP指针指向栈顶最后一个有效数据,并且每次压栈时SP地址会增加。
- 答案:× (错误)
- 解析: Cortex-M的堆栈是向下生长的满栈模型。向下生长意味着每次压栈,SP的地址会减小。
- 执行指令
PUSH {R0, R1}
后,SP的值会减8,并且R0被存放在比R1更高的地址上。 - 答案:√ (正确)
- 解析:
PUSH
两个32位寄存器,SP会减2 * 4 = 8
。在ARM架构中,无论寄存器编号大小,总是将编号较小的寄存器存放在较低的地址。因此,R0存放在新的SP
地址处,R1存放在SP+4
地址处。所以R0的地址低于R1的地址。
- Cortex-M处理器复位后,会首先从地址0x00000004处读取复位向量,然后才从0x00000000处加载MSP的初始值。
- 答案:× (错误)
- 解析: 顺序反了。根据复位流程图,处理器复位后,首先从地址
0x00000000
处读取MSP的初始值,然后才从0x00000004
处读取复位向量(即程序的入口地址)。
- 向量表中的所有地址的最低位(LSB)必须为0,以表示处理器处于ARM状态。
- 答案:× (错误)
- 解析: 正好相反。Cortex-M只在Thumb状态下运行,因此向量地址的最低位必须为1,用来指示处理器跳转后应保持在Thumb状态。
- 中断服务程序的入口地址就是向量表中对应中断号位置存放的32位数值。
- 答案:× (错误)
- 解析: 这是一个细微但重要的点。向量表中存放的32位数值,其最低位(bit 0)是Thumb状态指示位(必须为1),真正的入口地址是这个数值将bit 0清零后的结果。
- NVIC中,优先级编号为3的中断可以抢占正在执行的优先级编号为5的中断。
- 答案:√ (正确)
- 解析: 在Cortex-M的NVIC中,优先级的数值越小,代表其优先级越高。因此,优先级3高于优先级5,可以抢占(打断)正在执行的优先级5的中断服务程序。
- 如果两个中断的抢占优先级和响应优先级都完全相同,当它们同时请求中断时,中断号较小的那个会得到响应。
- 答案:√ (正确)
- 解析: 当所有可配置的优先级都相同时,最终的仲裁依据是它们在向量表中的位置,即固定的中断号。中断号较小的中断具有天然的较高优先级。
- Cortex-M响应中断时,硬件会自动压栈8个寄存器,这个过程不会被更高优先级的中断打断。
- 答案:√ (正确)
- 解析: 硬件压栈过程是原子性的,一旦开始,就必须完成,以保证堆栈的完整性。即使在压栈过程中有更高优先级的中断请求,也必须等待压栈完成后才能响应。
- 指令
MOVS R0, R1
在传送数据的同时,会根据R1的值更新APSR中的N和Z标志位。 - 答案:√ (正确)
- 解析: 指令后缀
S
的作用就是要求指令在执行后更新APSR中的条件标志位。MOVS
会根据传送的数据(即R1的值)来设置N(是否为负)和Z(是否为零)标志。
- 执行
MOVW R0, #0x1234
后,R0的值为0x00001234
;紧接着执行MOVT R0, #0x5678
后,R0的值将变为0x56781234
。 - 答案:√ (正确)
- 解析:
MOVW
(Move Wide)用于加载一个16位的立即数到寄存器的低16位,同时将高16位清零。MOVT
(Move Top)用于加载一个16位的立即数到寄存器的高16位,且不影响低16位。两者配合可以加载任意32位立即数。
LDRSB R0, [R1]
指令会从R1指向的地址加载一个字节,并将其进行零扩展到32位后存入R0。- 答案:× (错误)
- 解析: 后缀
SB
代表Signed Byte
(有符号字节)。该指令加载一个字节后,会进行符号位扩展到32位。即如果加载的字节最高位是1(负数),则R0的高24位会被填充为1;如果最高位是0,则填充为0。零扩展对应的指令是LDRB
。
- 指令
STR R0, [R1], #4
是一个后序变址的存储指令,它会先将R0的值存入R1指向的地址,然后将R1的值加4。 - 答案:√ (正确)
- 解析: 这是后序变址寻址。操作
[R1]
先执行,即在存储时使用R1当前的值作为地址。操作完成后,地址指针R1再更新(R1 = R1 + 4
)。
- 多重存储指令
STMDB R0!, {R1-R4}
中,DB
表示在存储之前先将地址递减(Decrease Before)。 - 答案:√ (正确)
- 解析:
DB
是Decrease Before
的缩写。这意味着在存储每个寄存器之前,基址寄存器R0的值会先减4。!
表示操作完成后,R0的最终值会写回到R0寄存器中。
B.LT Label
指令的跳转条件是APSR中的N标志位和V标志位不相等。- 答案:√ (正确)
- 解析:
LT
(Less Than) 条件码用于有符号数比较。跳转的条件是N != V
(负数标志不等于溢出标志)。
ITTEE EQ
指令块允许在条件相等时,顺序执行两条Then指令,在条件不等时,顺序执行两条Else指令。- 答案:√ (正确)
- 解析:
IT
指令块用于条件执行。T
代表Then,E
代表Else。ITTEE
表示第一条指令是Then,第二、三条是Else,第四条是Else。如果条件EQ
(相等)满足,则执行第一条指令,跳过后面三条;如果不满足,则跳过第一条,顺序执行后面三条。
- Cortex-M的位段操作(Bit-banding)本质上是通过软件查表和计算来实现对单个位的原子访问。
- 答案:× (错误)
- 解析: 位段操作是由处理器硬件自动完成的。当CPU访问位段别名区的特定字地址时,总线硬件会自动将其转换为对位段区中对应位的读-修改-写操作,这个过程对软件是透明的。
- 在STM32中,要将一个GPIO引脚配置为复用功能模式,需要设置
GPIOx_MODER
寄存器中对应的两位为10
。 - 答案:√ (正确)
- 解析: 根据笔记,
GPIOx_MODER
寄存器中,每个引脚由两位控制。00
=输入,01
=通用输出,10
=复用功能,11
=模拟模式。
- 向
GPIOx_BSRR
寄存器的BR1
位写1,可以使GPIOx_ODR
寄存器的第1位清零。 - 答案:√ (正确)
- 解析:
BSRR
的高16位(BR15-BR0
)用于复位(清零)对应的端口位。这是一个原子操作,比读-修改-写ODR
寄存器更高效、更安全。
- STM32中的基本定时器(如TIM6, TIM7)也具备PWM输出和输入捕获功能。
- 答案:× (错误)
- 解析: 基本定时器功能最简单,主要用于提供基本的定时和触发DAC等。它们没有捕获/比较通道,因此不具备PWM输出或输入捕获功能。这些功能由通用定时器和高级定时器提供。
- 在配置PWM模式时,定时器的周期由预分频寄存器(PSC)的值决定,占空比由自动重装载寄存器(ARR)的值决定。
- 答案:× (错误)
- 解析: 关系说反了。定时器的周期由自动重装载寄存器(ARR)的值决定(CNT计数到ARR的值为一个周期)。占空比由捕获/比较寄存器(CCR)与ARR值的比例决定。预分频寄存器(PSC)决定了CNT计数一次的时钟周期。
- DMA控制器在进行一次数据传输前,必须由CPU设置源地址、目标地址和传输数量,一旦启动后,整个数据块的传输过程无需CPU干预。
- 答案:√ (正确)
- 解析: 这正是DMA的工作原理。CPU进行初始化配置后,DMA控制器就可以“接管”总线,在内存和外设之间搬运数据,直到传输完成产生中断,从而将CPU解放出来。
- 在C语言中,定义一个指向外设基地址的结构体指针,可以直接通过
>
操作符来读写该外设的所有寄存器。 - 答案:√ (正确)
- 解析: 这是STM32固件库和HAL库中广泛使用的编程技巧。通过将寄存器映射到结构体成员,可以用
peripheral_ptr->REGISTER_NAME
的形式访问寄存器,代码可读性强且结构清晰。
- Cortex-M处理器从异常返回时,必须执行
RETI
指令。 - 答案:× (错误)
- 解析:
RETI
是8051单片机从中断返回的指令。Cortex-M从异常(包括中断)返回是通过向LR(链接寄存器)加载特殊的EXC_RETURN值,然后通过BX LR
或POP {PC}
等指令实现的。
- 1MB的位段区可以映射到32MB的位段别名区,这意味着对别名区的一个字节地址的访问,会映射到对位段区中一个特定位的操作。
- 答案:× (错误)
- 解析: 概念有误。是对别名区的一个字(Word)地址的访问,会映射到位段区中一个特定位的操作。因为对位的操作(置1或清0)是通过读写一个完整的字来实现的。
BX R0
指令执行时,如果R0的最低位是0,处理器将尝试切换到ARM状态并引发一个用法错误异常。- 答案:√ (正确)
- 解析: Cortex-M处理器只支持Thumb状态,因此跳转的目标地址最低位必须为1。如果尝试跳转到一个最低位为0的地址,硬件会认为这是一个非法的状态切换尝试,从而触发UsageFault异常。
CMP R0, #0
指令执行后,如果R0的值为0,则APSR中的Z标志位会被置1。- 答案:√ (正确)
- 解析:
CMP
指令通过执行减法来比较(但不保存结果),并根据减法结果更新标志位。如果R0 - 0
的结果为0,则Z(零)标志位被置1。
- 链接寄存器LR (R14) 除了用于保存函数返回地址,在异常发生时,它会被硬件赋予一个特殊的EXC_RETURN值,用于指示异常返回时的处理器状态。
- 答案:√ (正确)
- 解析: 这是一个高级知识点。进入异常时,硬件会将LR设置为一个特殊的值(如
0xFFFFFFF9
),这个值的高位是F
,低4位则包含了异常返回后应该恢复的处理器状态信息(例如返回到哪个堆栈,返回到特权模式还是用户模式等)。
- 进程栈指针PSP只能在特权模式下被修改。
- 答案:√ (正确)
- 解析: 对CONTROL寄存器(用于切换MSP/PSP)和PSP寄存器本身的直接写操作都属于系统级控制,必须在特权模式下才能执行,以保证操作系统的安全和稳定。
- 指令
LDR R0, =0x12345678
是一条伪指令,汇编器会将其转换为一条MOV
指令或一条LDR
指令从文字池中加载数据。 - 答案:√ (正确)
- 解析:
LDR Rd, =const
是汇编器提供的伪指令,用于方便地加载一个32位常量。汇编器会根据常量的大小智能地选择最优的实现方式:如果常量可以用MOV
/MOVW
指令表示,就用它们;如果不行,汇编器会在代码段附近生成一个“文字池(Literal Pool)”存放这个常量,然后用一条PC相对的LDR
指令去加载它。
STRH R0, [R1, R2]
指令表示将R0的低16位存储到地址(R1+R2)处。- 答案:√ (正确)
- 解析:
STRH
是存储半字(Half-word, 16位)的指令。寻址方式是基址(R1)加寄存器偏移(R2)。该指令会将R0的低16位内容,存储到由R1和R2内容相加得到的内存地址处。
- SysTick定时器是一个24位的递减计数器,当它从1减到0时,可以产生一个SysTick异常。
- 答案:√ (正确)
- 解析: SysTick是Cortex-M内核标配的系统定时器,它是一个24位的递减计数器,非常适合用作操作系统的时钟节拍。当计数到0时,会触发一个SysTick异常(中断),并自动重装载初值。
- MPU(内存保护单元)可以把内存划分为多个区域,并为每个区域独立设置访问权限,但它不能防止DMA控制器对受保护区域的非法访问。
- 答案:× (错误)
- 解析: MPU的保护是针对总线上的所有主设备(Bus Master)的,包括CPU核心和DMA控制器。因此,如果DMA试图向一个被MPU配置为只读的区域写入数据,同样会触发内存管理错误(MemManage Fault)。
- 在一个抢占优先级高于当前执行代码的中断发生时,硬件压栈后,会立即从向量表取址并跳转,这个过程不存在流水线停顿。
- 答案:× (错误)
- 解析: 任何改变程序控制流的操作,包括中断引发的强制跳转,都会导致流水线被清空和重新填充,从而产生延迟。虽然中断响应很快,但流水线停顿是不可避免的。
- 即使一个GPIO端口被配置为输出模式,程序依然可以读取其
IDR
寄存器来获取该引脚的实际电平状态。 - 答案:√ (正确)
- 解析:
ODR
(Output Data Register)是输出数据锁存器,决定了你要输出的电平。而IDR
(Input Data Register)则总是反映该I/O引脚物理上的实际电平状态。这在检测短路或总线冲突等场景下非常有用。
- 使用
__attribute__((packed))
关键字定义的C语言结构体,可以确保其成员变量在内存中是连续存放的,没有为了对齐而产生的填充字节,但这可能会导致非对齐访问,从而降低Cortex-M的访问性能。 - 答案:√ (正确)
- 解析:
packed
属性强制编译器取消为了对齐而添加的填充字节,使得结构体紧凑。但如果结构体内的半字或字成员因此落在了非对齐的地址上,CPU在访问它们时就需要执行非对齐访问,这会比对齐访问花费更多的时钟周期,降低性能,甚至在禁止非对齐访问时引发异常。