概论

  • 事件与中断
  • 发生硬件事件==>发生中断(广义)
  • 寄存器组
  • R0-R7为低组通用寄存器,R8-R12为高组通用寄存器
  • R13为Banked堆栈指针(称为SP)
    • CM3有两个堆栈,对应两个SP(不会同时使用),内核态堆栈使用MSP,用户态堆栈使用PSP
    • 这两个堆栈又可以被N个进程瓜分(每个进程都有自己的小堆栈)(实际上其他段也是一样)
  • R14为连接寄存器(称为LR)
    • 存放嵌套函数中的最后一级返回地址
  • R15为程序计数器(称为PC)
  • 特殊寄存器
  • PSRs:状态字寄存器(ALU标志、中断状态)
  • MASKs:中断屏蔽寄存器
  • CONTROL:控制寄存器(特权状态)
  • 只能被MSR/MRS指令访问
  • 只有ASPR可以在用户态/内核态访问,其他只能在内核态访问
  • 总线与内存空间映像(见STM32架构笔记)
  • 内存保护单元MPU
  • 在内存的某些region上,给特权加访问限制,若犯规(violated),会产生fault异常
  • Cortex-M3使用纯Thumb指令集:甚至乘法也是单周期的

指令系统

  • 基础
  • 标号、立即数(#)、注释(;)
  • 常量(DCB、DCW、DCD)
  • 编译器指示字(DCI)、宏定义(EQU)
  • 比较与测试(CMP和TST)、加载与拷贝(MOV和CPY)、快速加载(=addr)
  • 访存与访存偏移([R0],[R1, 常量偏移])
  • 计算:数运算、布尔运算、REV、SXT和UXT
  • 分支转移:CMP+B系列(等价于CB系列)、IT、TB系列(查switch表)
  • 访存:LD系列、ST系列、POP、PUSH
  • 注意LDR/ADR和STR、LDMIA和STMDB
  • 高级技巧
  • 指令的.W后缀:不加.W=可能16b或32b指令,加.W强制为32b指令
  • 连续寄存器表示:R0-R7
  • 寄存器列表:{R1-R3,R12,...}
  • 预索引与后索引
  • 指令Barrier
  • 编译器屏障:阻止编译器重排指令(不会生成新指令)
    • 重排原理:在单线程的语义不变的情况下,通过将耗时指令前移等方法,增加指令并行性等。但可能导致多线程时错误重排。
  • 内存屏障:阻止cpu乱序访问内存(会生成新指令)
    • 原理:访存完毕后才能通过barrier,实现内存访问的同步问题
    • 用于实现锁的原子性、设备寄存器操作顺序、上下文切换时的寄存器操作顺序

中断与异常

  • 1-15为内异常,16以后为外中断
  • 异常包括Trap(即SVC)、Fault
  • 中断包括Exception
  • 中断服务程序也叫ISR

  • Fault强制提升(Escalation)

  • 如果同级/高级的ISR触发了同级/低级的Fault,会强制提升为HardFault
  • 因为同级及以下的ISR无法处理了,所以必须提升到最高级
  • 强制锁定:在NMI/HardFault/复位中出现了任意Fault会立即锁定内核

总线Fault

  • 取指(PrefetchAbort)、数据读写(DataAbort)、PUSH和POP错误
  • 强制提升:读中断向量时出现总线Fault,会被立即强制提升为HardFault

  • 调试方法

  • 查看总线Fault状态寄存器BFSR:
    • 确定是取指/数据读写/栈读写
    • 确定该Fault地址是否精确,BFAR是否有效
  • 查看总线Fault地址寄存器BFAR(BFARVALID=1时):确定错误地址

存储器Fault

  • 读:访问MPU不允许的地址、访问不存在的地址、用户态访问了内核态区域
  • 写:向只读存储器写、用户态访问了内核态区域
  • 强制提升

  • 调试方法:同理,看MFSR和MMAR

用法Fault

  • 使用了未定义的指令(如协处理器指令)
  • 可以利用这个中断来进行软件模拟,来实现指令行为
  • 切入ARM状态(纯Thumb指令集不支持)
  • 加载PC时使用了LSB为0的数(表示PC所指的指令为ARM指令,为1表示Thumb指令)
  • 自定义用法Fault
  • 可以在NVIC中设置除数为0/未对齐访问的中断标志,使它们也产生用法Fault
  • 强制提升

  • 调试方法:同理,看UFSR和MMAR

HardFault

  • 调试方法:看HFSR
  • 确定是否是强制提升得到的HardFault
  • 确定是否由取向量时总线Fault
  • 若为提升得到,但不是取向量导致的,则必须检查其他Fault,确定是由谁提升的

应对Fault(重要)

  • 恢复:使用软件来解决问题(如协处理器导致的UsageFault)
  • 中止任务:终止任务,若可能,就重新执行
  • 复位内核:设置NVIC的VECT_RESET位,只复位内核,而不复位片上外设

SVC和PendSV

  • SVC:不可挂起的系统调用,必须立即进行用户态->内核态
  • 被嵌套:产生用法Fault
  • 在NMI中调用:产生HardFault
  • 若被挂起:产生强制提升的HardFault
  • PendSV:可挂起的系统调用,一般用于进程的上下文切换

调试系统架构CoreSight

  • 侵入式调试
  • 单步执行、watchpoint
  • 硬件断点、软件断点
  • 调试监视器异常(DebugMon_Handler)
  • 基于ROM的调试
    • ST-LINK调试器
    • 闪存地址重载(flash patching):使用FPB寄存器
    • COMP:用于比较指令是否符合停止条件,并在停止时将原指令更换为断点指令
    • REMAP:用于停止时将原指令写入指定的SRAM地址
    • CTRL:控制FPB过程