ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

第九周工作实录

第九周工作实录

本周制作YMC25564-02BADYDGL 的OTP1x3测板的AD画图订板,学习的是嵌入式刷题,包括嵌入式基础对于嵌入式和裸机开发的区别。

单片机做系统要用到RTOS,RTOS有三大性质(实时性、可裁剪性、可靠性)。

  • 实时性:实时操作系统中,首要任务是调度一切可利用的资源来完成实时控制任务。
  • 可裁剪性:RTOS所有机制(内存管理、中断处理、任务调度)确保最关键的任务能按时执行。
  • 可靠性:实时操作系统就是系统启动后运行一个后台程序。

RTOS本身通常没有像Windows界面那样图形界面为用户直接操作。实时操作系统可以根据应用环境要求内核进行裁剪和重配,单片机RAM有限,如果项目不需要网络可以把网络协议栈剪掉。

RTOS(Real Time Operating System)实时操作系统

在单片机(如STM32)裸机开发时,通常用全局变量和中断标志位解决问题。但一旦引入RTOS(如FreeRTOS、uC/OS、RT-Thread),系统变成多任务并发环境,多个任务可能会同时争夺同一个硬件资源(如串口、SPI总线、显示屏),这时就必须用到信号量机制。

PV(信号量机制)操作实现进程同步和互斥。

1、确定信号量的初始值(最大值)

举个例子两个进程属于互斥资源(同一时刻只能被一个进程使用)

信号量初始值属于系统中该类资源数量,信号量S的初始值为2.当没有进程使用的时候S达到最大值2.

2、确定信号量的最小值

P操作(申请资源)执行S-1,如果S<0进程阻塞,进入等待队列。

V操作(释放资源)执行S+1,如果S<=0唤醒一个进程。

极端情况 n个进程想使用这两条线或者说是打印机,第一个进程是S=2-1=1.....到S=0-1=-1,S=-1-1=-2 简单说是从2到0前面只是占了3位所以S在最后=-(n-2) P=-(N-2) V=2 PV=-(N-2)~2 现实中可能就是I2C总线。

信号量(Semaphore)分类(二值信号量、计数信号量、互斥量)
  1. 二值信号量:取0或1,实现互斥锁加任务同步。
  2. 计数信号量:取0~N,用来管理多个同类资源。
  3. 互斥量:带有优先级继承机制的特殊二值信号量,防止优先级翻转。

常见RTOS的API对应,书本考试上称PV操作来源于荷兰语Proberen和Verhogen 实际封装成了各种函数。

  • uC/os:OSSemPend()=>P,OSSemPost()=>V
  • Free RTOS:xSemaphore Take()=>P,xSemaphore Give()=>V
  • RT-Thread:rt_sem_take()=>P,rt_sem_release()=>V

加入一个问题——在中断服务函数(ISR)中应该是用什么操作释放信号量?

在Free RTOS中必须带From ISR后缀API 如xSemaphoreGiveFrom ISR,且不能带阻塞。

中断处理流程

硬件自动完成:关中断->保存断点->软件处理:识别中断源->保存现场和屏蔽字->开中断->执行中断服务程序主体->关中断->恢复现场和屏蔽字->开中断->中断返回,恢复断点

设置屏蔽字,关中断经常出现在开中断前后,用来控制中断嵌套和保护现场。

中断服务程序(ISR)ARM V8 ERET异常返回,IRET X86中断返回。ERET (Exception Return) 是 ARMv8 (AArch64) 架构中用于从异常处理程序返回的核心指令。它的作用远不止是简单的“跳转”,而是一次对处理器状态的原子性恢复,会同时恢复程序计数器(PC)和整个处理器状态(PSTATE)。

ERET是一条特殊的系统指令,它执行时主要完成两个关键动作:

  1. 恢复 PSTATE(处理器状态):从当前异常级别的SPSR_ELn(Saved Program Status Register) 寄存器中读取值,并恢复到 PSTATE 中。这包括条件标志位、中断屏蔽位、处理器模式等关键信息。

  2. 跳转到返回地址:从当前异常级别的ELR_ELn(Exception Link Register) 寄存器中读取值,并将其设置为新的程序计数器(PC),从而让CPU回到异常发生时的地址(或处理程序指定的其他地址)继续执行。

这两个动作必须是原子的。如果分两步执行,无论是先设置 PC 还是先恢复 PSTATE,都可能导致 CPU 在错误的状态下执行代码,引发混乱。

完整的异常返回流程:从硬件保存到软件恢复

要理解ERET,需要将它放在完整的异常处理闭环中来看:

  1. 异常发生(硬件自动保存):当异常发生时,CPU 硬件会自动将当前的 PSTATE 保存到SPSR_ELn,并将异常返回地址(通常是导致异常的指令或它的下一条)保存到ELR_ELn。

  2. 异常处理(软件执行):软件(如操作系统内核)在异常处理程序中执行,进行必要的处理。如果处理程序修改了SPSR_ELn或ELR_ELn(例如,需要返回到不同的地址),它会用MSR指令写入新值。

  3. 异常返回(执行ERET):异常处理程序结束时,执行ERET指令。此时,硬件会原子性地从SPSR_ELn和ELR_ELn中读取值,并分别恢复 PSTATE 和 PC,从而无缝地返回到被中断的上下文。

🔗 关键寄存器:ELR_ELx 与 SPSR_ELx

ERET的运作依赖于这对“孪生”系统寄存器:

  • ELR_ELx(Exception Link Register):“返回地址保险箱”。它保存了异常返回后要执行的下一条指令的地址。

  • SPSR_ELx(Saved Program Status Register):“处理器状态快照”。它完整保存了异常发生瞬间的 PSTATE,包括条件标志位、中断屏蔽位(DAIF)、处理器模式(EL)和堆栈指针选择(SP)等。ERET通过恢复SPSR_ELx,也就恢复了处理器的“身份”和“权限”,例如从内核态(EL1)返回到用户态(EL0)。

⚠️ 编程关键点与限制

在实际编程中,使用ERET需要注意以下几点:

  • 特权指令:ERET是特权指令,不能在 EL0(用户态)执行,否则会触发未定义指令异常。

  • 非法返回:ERET执行时,硬件会检查SPSR_ELn中的值是否合法。例如,试图返回到一个非法的异常级别或非法的执行状态(如 AArch32 与 AArch64 之间的非法切换)会触发非法返回事件 (Illegal return event),导致异常。

  • 推测执行屏障 (Speculation Barrier):在某些 ARMv8.5+ 的 CPU 上,ERET之后的指令可能会被推测执行。如果这带来了安全风险(如侧信道攻击),需要在ERET后插入一个推测执行屏障(如SB指令)来阻止 CPU “偷看”并执行ERET之后的指令。

  • 上下文同步:ERET本身会带来一次上下文同步,确保之前对系统寄存器的修改(如通过MSR指令)对后续的指令可见。

缓存Cache:分为直接映射(硬件极简单,成本最低,冲突率极高),全相联映射(冲突率极低,硬件成本极高,速度慢),组相联映射(完美平衡了直接映射的“低成本”和全相联的“低冲突”)。平衡速度与硬件成本。

替换算法:Cache满了腾位置,用LRU(最近最少使用)FIF0(先进先出)

MESI协议(缓存一致性协议)

MESI 代表一个缓存行的四种状态:

  1. M (Modified - 已修改):数据在我这被改了,跟主存(内存)不一样了。此时我是独占的,别人都没这数据。

  2. E (Exclusive - 独占):数据只有我这儿有,主存里也有一样的。别人没这数据。

  3. S (Shared - 共享):这数据好几个核都有,大家都没改它,和主存一致。

  4. I (Invalid - 无效):被别人改过了,我这块缓存作废了,不能用了。

映射方式决定了 CPU去哪找数据。

替换算法决定了 CPU扔掉谁来腾位置。

MESI 协议决定了多核之间怎么同步数据,防止读到脏数据。

LCD背光驱动电路

一个led外加一个背光灯,使能端接PWM,PWM占空比=(开的时间)/(开+关的时间),PWM=50%灯半亮。通过数据手册来使电阻分压,公式Vout=Vin[R2/(R1+R2)],来看MCU ADC的量程。

BUCK降压:利用二极管单向导电性 串一个MOS管和一个电感并电感和负载,公式Vout=Vinx占空比

Boost升压:电源电感LED并电感和负载 开关正常放,公式Vout=Vin(1-占空比)。

对光耦参数选型问题:看单片机引脚驱动,选IF=>正向电流。接收信号类型:选线性/非线性 CTR输出与输入电流成比例接耐压:选VISO隔离电压对于恒流驱动,PWM调光 :主用功率驱动。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进