3. ARM寄存器组织

这是32位ARM架构(ARMv7及更早版本)的寄存器组织图,核心展示了ARM状态下不同处理器模式的通用寄存器、程序计数器和程序状态寄存器的映射关系,以及关键的**寄存器分组(banked register)**机制。

一、核心机制:寄存器分组

图中带阴影的单元格表示分组寄存器------它们在不同处理器模式下拥有独立的物理副本。当处理器切换模式时,会自动切换到对应模式的寄存器副本,无需软件保存/恢复,大幅提升异常处理和上下文切换的速度。

二、通用寄存器与程序计数器(r0-r15)

任意时刻,处理器只能看到16个通用寄存器(r0-r15),但整个系统实际包含37个物理通用寄存器。

寄存器范围 共享/分组特性 功能说明
r0-r7 所有7种模式完全共享 通用数据寄存器,用于临时存储数据、函数参数和返回值
r8-r12 仅FIQ模式有独立副本(r8_fiq-r12_fiq),其余模式共享 通用数据寄存器;FIQ模式独占这5个寄存器,无需保存即可直接使用,实现最快中断响应
r13(SP) 所有特权模式都有独立副本(r13_svc/r13_abt等) 栈指针寄存器,每个特权模式拥有独立栈空间,避免不同模式栈互相干扰
r14(LR) 所有特权模式都有独立副本(r14_svc/r14_abt等) 链接寄存器,保存子程序调用或异常返回的地址
r15(PC) 所有模式完全共享 程序计数器,指向当前正在取指的指令地址。注意:ARM状态下PC值=当前执行指令地址+8(源于经典三级流水线)

三、程序状态寄存器

1. CPSR(当前程序状态寄存器)

所有模式共享,32位寄存器,保存处理器当前的核心状态:

  • 条件标志位(N/Z/C/V):控制条件指令的执行
  • 中断屏蔽位(I/F):分别屏蔽IRQ和FIQ中断
  • 模式位(M4:0):决定处理器当前运行的模式
  • T位:控制处理器处于ARM状态(32位指令)还是Thumb状态(16位指令)

2. SPSR(备份程序状态寄存器)

每个特权模式都有独立的SPSR副本(SPSR_fiq/SPSR_svc等):

  • 当发生异常进入特权模式时,CPSR的当前值会自动保存到对应模式的SPSR
  • 异常返回时,将SPSR的值恢复到CPSR,还原异常前的处理器状态
  • 用户模式没有SPSR,因为它不是异常入口模式

四、7种处理器模式说明

模式名称 特权级别 主要用途
User(用户) 非特权 应用程序运行的默认模式,不能直接访问系统资源
System(系统) 特权 与用户模式共享所有寄存器,用于运行操作系统内核任务
FIQ(快速中断) 特权 处理高优先级、需要快速响应的中断
IRQ(普通中断) 特权 处理一般的外部硬件中断
Supervisor(管理) 特权 操作系统内核运行的核心模式,复位和软中断(SWI)会进入此模式
Abort(中止) 特权 处理内存访问异常(如预取指中止、数据中止)
Undefined(未定义) 特权 执行未定义指令时进入,用于模拟协处理器指令等
Secure monitor(安全监控) 特权 支持ARM TrustZone技术,负责安全世界与非安全世界的切换

五、关键设计亮点

  1. FIQ模式的极致优化:独占r8-r14共7个分组寄存器,中断服务程序无需压栈保存寄存器,可直接执行,是ARM架构满足嵌入式实时性要求的核心设计。
  2. 模式隔离与安全:不同特权模式拥有独立的栈指针和程序状态备份,防止用户模式程序破坏系统内核状态。
  3. 低开销上下文切换:通过硬件自动切换分组寄存器,减少了异常处理时的软件开销。

仅 FIQ 模式有独立副本(r8_fiq-r12_fiq) 什么意思

这句话是ARM架构为了实现极致快速中断响应的核心设计,我用大白话和类比给你讲清楚:

一、先理解"寄存器副本"是什么

你可以把每个寄存器想象成一个临时储物柜,CPU干活时所有数据都要先放到这里。

"有独立副本"的意思是:这个储物柜不是大家共用的,而是专门给某个人(某一种处理器模式)单独准备的物理柜子。别人用他们的,你用你的,互不干扰。

二、"仅FIQ模式有"的具体含义

看你提供的表格中r8-r12这五行:

  • 所有其他6种模式 (用户、系统、管理、中止、IRQ、未定义、安全监控):共用同一个物理的r8、r9、r10、r11、r12寄存器。也就是说,当处理器从IRQ模式切换到管理模式时,它们看到的r8-r12是完全相同的一组柜子。
  • 只有FIQ模式 :它有自己单独的5个物理寄存器,分别叫r8_fiq、r9_fiq、r10_fiq、r11_fiq、r12_fiq。这5个柜子只有FIQ模式能访问,其他任何模式都看不到也用不了。

三、这个设计的巨大好处:让FIQ中断"快到极致"

这是ARM架构最经典的实时性优化,核心是省去了"保存/恢复寄存器"的耗时操作

对比普通中断(IRQ)的处理流程

  1. 中断来了,CPU要立刻停下手里的活去处理中断
  2. 必须先把r8-r12里正在用的数据,全部保存到内存里(压栈)
  3. 才能使用r8-r12来执行中断服务程序
  4. 中断处理完,还要把刚才保存的数据从内存里恢复回r8-r12(出栈)
  5. 才能继续干之前的活

问题:访问内存的速度比访问寄存器慢几百倍,这两步"压栈/出栈"会产生很大的延迟。

FIQ中断的处理流程

  1. 中断来了,CPU立刻切换到FIQ模式
  2. 直接使用自己专属的r8_fiq-r12_fiq寄存器,里面是空的(或者保存的是上一次FIQ中断的数据)
  3. 中断处理完,直接切换回原来的模式即可

优势:完全省去了压栈和出栈的时间,中断响应速度比IRQ快得多。

四、补充说明

  • FIQ模式不仅有r8-r12的独立副本,还有自己独立的r13(栈指针)、r14(链接寄存器)和SPSR(状态备份寄存器)。
  • 也就是说,FIQ模式总共拥有7个专属寄存器,这意味着一个简单的FIQ中断服务程序可以完全不访问内存,只在寄存器里完成所有操作,达到纳秒级的响应速度。
  • 这种设计专门用于处理对实时性要求极高的场景,比如工业控制中的电机调速、高速数据采集、汽车安全气囊的触发等。

r8_fiq与r8不是物理上同一个寄存器吗,别的模式为什么看不到

它们绝对不是同一个物理寄存器,是CPU内部完全独立的两个硬件存储单元 。你看不到的原因不是软件做了"隐藏",而是CPU硬件层面的"地址路由"机制决定的------这是ARM寄存器分组(Banked Register)最核心的硬件实现原理。

一、硬件实现:一个编号对应多个物理寄存器,靠"开关"切换

我用一个最贴近硬件的类比来说明:

  • 你可以把CPU内部想象成一个有很多房间的大楼,每个物理寄存器就是一个独立的房间,里面放着数据。
  • 寄存器编号(r0-r15)不是房间号,而是大楼门口的快递收件地址
  • 每个收件地址后面,连接着一个硬件多路选择器(MUX),它就像一个智能快递分拣开关。
  • 这个开关的控制权,完全由CPSR寄存器里的**模式位(M4:0)**决定。

以r8为例的具体路由规则

当CPU执行指令访问"r8"这个地址时:

  • 如果当前模式位是FIQ模式 (0b10001),硬件开关会自动把"r8"这个地址,连接到物理寄存器A(r8_fiq)
  • 如果当前模式位是任何其他模式 (用户/系统/IRQ等),硬件开关会自动把"r8"这个地址,连接到物理寄存器B(通用r8)

关键结论

  • 物理寄存器A和B是两个完全独立的硬件单元,各自有自己的存储电路,互不影响。
  • 任何时刻,一个地址只能连接到一个物理寄存器。
  • 软件永远只能通过"r8"这个统一的名字访问,根本不知道也不需要知道背后具体是哪个物理寄存器

二、为什么别的模式"看不到"r8_fiq?

因为硬件开关根本不会把r8_fiq连接到CPU的内部数据总线上,除非当前处于FIQ模式。

这就像:

  • 你家有两个冰箱,一个放在客厅(通用r8),一个放在你的卧室(r8_fiq)。
  • 家里的"取冰箱"指令,默认是去客厅拿东西。
  • 只有当你切换到"卧室模式"时,"取冰箱"指令才会自动去卧室的冰箱拿东西。
  • 你在客厅的时候,永远看不到也拿不到卧室冰箱里的东西,不是因为它被锁起来了,而是因为指令根本不会指向那里。

三、一个直观的代码实验验证

假设我们写一段汇编代码,在不同模式下读写r8:

asm 复制代码
; 1. 先切换到用户模式,给r8赋值100
mov r8, #100        ; 此时写入的是 物理寄存器B(通用r8)

; 2. 触发一个FIQ中断,CPU自动切换到FIQ模式
; (以下是FIQ中断服务程序)
fiq_handler:
    mov r0, r8      ; 此时读取的是 物理寄存器A(r8_fiq),值不是100!
    mov r8, #200    ; 写入的是物理寄存器A,不会影响通用r8的值
    subs pc, lr, #4 ; 退出FIQ,自动切回用户模式

; 3. 回到用户模式
mov r1, r8          ; 此时r1的值还是100,完全不受FIQ模式里r8操作的影响

实验结果:用户模式下r8的值始终是100,FIQ模式里对r8的读写完全独立。

四、为什么要这么设计?而不是用同一个寄存器+内存保存?

核心原因是速度差了几百倍

  • 访问寄存器:1个CPU时钟周期
  • 访问内存:几百个CPU时钟周期

如果r8_fiq和r8是同一个物理寄存器,那么FIQ中断来了就必须:

  1. 把r8里的用户数据保存到内存(几百个周期)
  2. 使用r8处理中断
  3. 把数据从内存恢复回r8(又几百个周期)

而现在的硬件分组设计,这两步耗时操作完全被硬件省略了。CPU切换模式时,只是拨动了一下硬件开关,耗时0个额外周期。

这就是为什么FIQ能做到"纳秒级响应",成为ARM架构在嵌入式实时领域称霸的核心原因。

五、补充:为什么不所有模式都做独立副本?

因为成本和功耗

  • 每个32位物理寄存器,都需要占用芯片上的晶体管资源。
  • 如果7种模式每个都有16个独立寄存器,总共需要112个物理寄存器,芯片面积会大很多,功耗也会飙升。

ARM的设计是精准的取舍

  • 只给对实时性要求最高的FIQ模式,多分配了5个寄存器(r8-r12)
  • 其他特权模式,只分配了最必要的2个寄存器(r13栈指针和r14链接寄存器)
  • 这样既保证了关键场景的实时性,又控制了芯片的成本和功耗。

FIQ 模式只能访问r8_fiq吗 不能访问r8吗

是的,在FIQ模式下,你 只能访问r8_fiq,绝对不能直接访问那个所有其他模式共用的通用r8**。这不是软件做的权限限制,而是CPU硬件电路的物理连接决定的,没有任何指令可以绕过这个规则。

一、最核心的硬件事实

当CPU的CPSR模式位被设置为FIQ模式(0b10001)时:

  • 所有汇编指令中出现的r8这个名字,100%被硬件路由到物理寄存器r8_fiq
  • 那个通用r8的物理存储单元,此时完全与CPU的内部数据总线断开连接
  • 软件没有任何办法,能让r8这个编号指向通用r8的物理地址

用一个绝对准确的电路类比

你可以把每个寄存器编号想象成一个单刀双掷开关

  • 开关的公共端连接到CPU的指令执行单元(你写代码能控制的部分)
  • 开关的两个触点分别连接到两个独立的物理寄存器:通用r8 和 r8_fiq
  • 开关的拨杆 ,直接由CPSR寄存器的模式位硬件控制

当模式位是FIQ时,开关自动拨到r8_fiq;当模式位是其他任何值时,开关自动拨到通用r8。软件只能控制模式位,不能直接控制开关的位置

二、一个彻底打消疑问的实验

假设在进入FIQ中断前,用户模式下的通用r8的值是0x12345678。现在进入FIQ模式,执行以下代码:

asm 复制代码
; 此时处于FIQ模式
mov r0, r8          ; r0的值不是0x12345678,而是r8_fiq里原来的值
mov r8, #0xAAAAAAAA ; 写入的是r8_fiq,通用r8的值仍然是0x12345678

; 退出FIQ,自动切回用户模式
subs pc, lr, #4

; 回到用户模式
mov r1, r8          ; r1的值还是0x12345678,完全不受FIQ里操作的影响

结论 :FIQ模式下对r8的所有读写,都与通用r8毫无关系。

三、那有没有办法在FIQ模式下"看到"通用r8?

有,但只能间接访问 ,而且会完全破坏FIQ的实时性优势,所以实际工程中绝对不会有人这么做

两种间接访问方法

  1. 切换模式访问

    你可以在FIQ模式下,临时把CPSR的模式位改成用户模式,此时r8就会指向通用r8。但这样做:

    • 会破坏FIQ的中断屏蔽状态,可能导致其他中断嵌套
    • 需要额外保存和恢复CPSR,增加了几十倍的延迟
    • 完全违背了使用FIQ的初衷
  2. 内存中转

    在进入FIQ之前,把通用r8的值提前保存到内存的某个固定地址。在FIQ模式下,通过读取这个内存地址来间接获取通用r8的值。但这样做:

    • 访问内存的速度比访问寄存器慢几百倍
    • 需要提前安排好内存空间,增加了系统复杂度

四、为什么要设计成"完全不能直接访问"?

这正是FIQ能做到"零延迟响应"的关键。

如果FIQ模式既能访问r8_fiq,又能访问通用r8,那么:

  • 当FIQ中断到来时,你仍然需要先把通用r8里的数据保存到内存
  • 否则,如果你在FIQ里不小心修改了通用r8,就会破坏被中断程序的状态
  • 这样一来,FIQ和普通的IRQ就没有任何区别了

现在的设计是:FIQ模式拥有一个完全独立的寄存器环境。你在FIQ里可以放心大胆地使用r8-r14,完全不用担心会影响到其他模式的程序,也完全不需要做任何保存和恢复操作。

五、补充:r0-r7是个例外

注意,r0-r7在所有模式下都是共用同一个物理寄存器的。也就是说,在FIQ模式下,你访问r0,操作的就是那个所有模式都共用的通用r0。

这就是为什么一个标准的FIQ中断服务程序,通常只会使用r8-r13这几个专属寄存器。如果必须使用r0-r7,那么你还是需要把它们压栈保存,用完后再恢复。

生活类比+逐行代码拆解讲透。这是ARM汇编最核心的基础,所有函数调用和异常处理都建立在这个机制上。

一、一句话先懂核心逻辑

BL 函数名 就相当于:

  1. 先在笔记本上记下"我现在看到第几行了,看完函数要从下一行继续"(这个"笔记本"就是LR寄存器)
  2. 然后跳转到函数的第一行去执行
  3. 函数执行完,照着笔记本上记的页码,翻回去继续看(这个"翻页"的动作就是把LR的值复制给PC)

二、最通俗的生活类比

想象你正在看一本说明书:

  • 你手里的页码牌 就是PC(程序计数器),它永远指向你正在看的那一页
  • 你口袋里的便签纸 就是LR(链接寄存器),专门用来记"一会儿要回到哪一页"

现在发生了这件事:

  1. 你正看到第100页(PC=100),这一页写着:"请先去看附录A的第200页,再回来继续"
  2. 你先在便签纸上写下101(LR=101)------因为看完附录A,你要从第101页继续看,而不是再看一遍第100页
  3. 然后你把页码牌翻到200页(PC=200),开始看附录A
  4. 附录A看完了,你看一眼便签纸上的101,把页码牌直接翻到101页(PC=LR)
  5. 你就从第101页开始,继续看原来的说明书了

这就是BL指令和LR寄存器工作的完整过程。

三、逐行代码拆解(绝对清晰)

我们写一段最简单的ARM汇编代码,把每一步PC和LR的值都标出来,你一看就懂。

asm 复制代码
; 地址  指令
0x0000  mov r0, #1        ; 第1行:r0=1
0x0004  mov r1, #2        ; 第2行:r1=2
0x0008  BL  add_func      ; 第3行:调用add_func函数 【关键行】
0x000C  mov r2, r0        ; 第4行:把函数返回值存到r2
0x0010  b   .             ; 第5行:程序结束,原地循环

; 这是add_func函数,地址从0x0020开始
0x0020  add r0, r0, r1    ; 函数第1行:r0=r0+r1=1+2=3
0x0024  mov pc, lr        ; 函数第2行:返回 【关键行】

我们一步一步看CPU是怎么执行的:

  1. 执行第1行(地址0x0000):PC=0x0000,执行完后PC自动变成0x0004
  2. 执行第2行(地址0x0004):PC=0x0004,执行完后PC自动变成0x0008
  3. 执行第3行(BL add_func,地址0x0008)
    • 第一步(自动) :CPU先把下一条指令的地址0x000C ,保存到LR寄存器里 → LR=0x000C
    • 第二步(自动) :CPU把PC的值改成函数的地址0x0020 → PC=0x0020
    • 现在CPU就跳转到函数里去执行了
  4. 执行函数第1行(地址0x0020):PC=0x0020,计算r0=3,执行完后PC变成0x0024
  5. 执行函数第2行(mov pc, lr,地址0x0024)
    • 这就是"把LR的值复制到PC" → PC=LR=0x000C
    • 现在CPU的PC指向了0x000C,也就是原来的第4行
  6. 执行第4行(地址0x000C):PC=0x000C,把r0的值3存到r2里,执行完后PC变成0x0010
  7. 执行第5行:程序结束

四、解答你最可能有的两个疑问

疑问1:为什么LR保存的是"下一条指令的地址",而不是BL指令本身的地址?

因为BL指令已经执行完了

如果LR保存的是BL指令的地址0x0008,那么函数返回后,CPU又会执行一遍BL指令,再次调用add_func,就会陷入无限循环。

所以正确的做法是,保存BL指令的下一条指令地址0x000C,这样返回后就能从被打断的地方继续往下执行。

疑问2:为什么"把LR的值复制到PC"就能实现返回?

因为PC是CPU的"指挥棒"

PC寄存器的值,永远是CPU下一条要执行的指令的地址。你把PC改成什么值,CPU就会立刻跳转到那个地址去执行指令。

所以当你执行mov pc, lr时,就相当于告诉CPU:"别按顺序往下走了,直接去执行LR里存的那个地址的指令吧"。

五、两个非常重要的补充细节

1. BL和普通跳转指令B的区别

  • B 地址:只跳转,不保存LR。跳过去就再也回不来了,适合用在if/elsewhile这种不需要返回的跳转
  • BL 地址:跳转+自动保存LR。专门用在函数调用,跳过去执行完还能回来

2. 异常返回和函数返回的微小区别

你图片里还提到了"产生异常时"的LR,这里有一个容易踩的坑:

  • 函数调用返回 :直接用mov pc, lr即可
  • 异常返回 :必须用subs pc, lr, #4(也就是把LR的值减4再复制给PC)

原因:异常发生时,CPU的流水线已经预取了异常指令的下两条指令,所以LR里自动保存的是"被打断指令的下下条地址"。减4之后,才能准确回到被异常打断的那条指令继续执行。

六、最后总结

  • BL 函数 = 自动保存返回地址到LR + 跳转到函数
  • mov pc, lr = 跳转到LR里保存的返回地址
  • 整个过程完全由CPU硬件自动完成,不需要你手动计算地址
  • 这就是所有高级语言里"函数调用"功能在CPU层面的本质实现

这是32位ARM架构(ARMv7及更早)的CPSR(当前程序状态寄存器)详解图 ,它是ARM CPU最核心的寄存器,相当于CPU的"状态总控制台",所有运算结果、中断开关、指令集类型和运行模式都由它控制。

一、CPSR总览

CPSR是一个32位的寄存器,所有7种处理器模式共享同一个物理CPSR。它的每一位都有明确的硬件含义,任何一位的变化都会直接改变CPU的行为。

二、核心位域详解(从高位到低位)

1. 条件代码标志位(31-28位):运算结果的"成绩单"

这4位是CPU执行算术/逻辑指令后自动设置的,所有ARM指令都可以根据这4位的值决定是否执行(这就是ARM著名的"条件执行"特性)。

名称 含义 置1条件
31 N(负标志) 负或小于 运算结果的最高位为1(即结果为负数)
30 Z(零标志) 运算结果为0
29 C(进位/借位标志) 进位或借位扩展 加法:结果产生进位时置1 减法:结果产生借位时置0 移位/循环指令:保存移出的最后一位
28 V(溢出标志) 溢出 有符号数运算结果超出32位有符号数的表示范围时置1

关键区分

  • C位用于无符号数运算的溢出判断
  • V位用于有符号数运算的溢出判断
  • 这两个标志是独立的,互不影响

示例

asm 复制代码
mov r0, #0x7FFFFFFF  ; r0 = 最大的32位有符号正数
add r1, r0, #1       ; r1 = 0x80000000
; 执行后:N=1(结果为负),Z=0,C=0(无进位),V=1(有符号溢出)

2. 保留位(27-8位)

这20位是ARM公司预留的,用于未来架构扩展。软件绝对不能修改这些位,否则可能导致CPU进入不可预测的状态。

3. 控制位(7-0位):CPU的"控制面板"

这8位直接控制CPU的核心行为,只有在特权模式下才能修改。

名称 含义 置1效果
7 I(IRQ禁止位) IRQ中断禁止 置1时,CPU屏蔽所有普通外部中断
6 F(FIQ禁止位) FIQ中断禁止 置1时,CPU屏蔽所有快速中断
5 T(状态位) 指令集状态 T=0:CPU处于ARM状态(执行32位指令) T=1:CPU处于Thumb状态(执行16位指令)
4-0 M4:0(模式位) 处理器运行模式 5位二进制值决定CPU当前的7种运行模式

模式位M4:0对应表(与你之前看到的7种模式一一对应):

M4:0 模式名称
0b10000 User(用户)
0b11111 System(系统)
0b10001 FIQ(快速中断)
0b10010 IRQ(普通中断)
0b10011 Supervisor(管理)
0b10111 Abort(中止)
0b11011 Undefined(未定义)
0b10110 Secure monitor(安全监控)

三、四个域的划分(图中底部说明)

ARM将32位的CPSR划分为4个独立的域,主要是为了在异常处理时能够选择性地保存和恢复状态,提高效率。

位范围 名称 包含内容
F域 31:24 条件域 包含N、Z、C、V四个条件标志位
S域 23:16 状态域 部分保留位和扩展状态位
X域 15:8 预留域 全部为保留位
C域 7:0 控制域 包含I、F、T和M4:0所有控制位

实际用途:在进入异常时,操作系统可以只保存C域(控制域),而不需要保存整个CPSR,减少上下文切换的开销。

四、重要补充知识点

  1. CPSR与SPSR的关系

    • 当发生异常时,CPU会自动将当前CPSR的值,保存到对应异常模式的SPSR(备份程序状态寄存器)中
    • 异常返回时,再将SPSR的值恢复到CPSR,还原异常前的CPU状态
    • 用户模式没有SPSR,因为它不是异常入口模式
  2. CPSR的读写方式

    • 不能直接用mov指令修改整个CPSR
    • 必须使用专用指令:
      • mrs r0, cpsr:将CPSR的值读取到通用寄存器r0
      • msr cpsr_c, r0:将r0的值写入CPSR的控制域(C域)
      • msr cpsr_f, r0:将r0的值写入CPSR的条件域(F域)
  3. 条件执行的威力

    因为有了这4个条件标志位,ARM指令可以在不跳转的情况下实现条件执行。例如:

    asm 复制代码
    add r0, r1, r2
    addeq r0, r0, #1  ; 只有当上面的加法结果为0(Z=1)时,这条指令才会执行

    这可以大幅减少分支跳转,提高代码执行效率。

相关推荐
xiangw@GZ1 天前
ARM TCM 紧耦合内存与 Cache 架构区别
arm开发·架构
XINVRY-FPGA1 天前
XCKU035-2FBVA676I AMD Xilinx Kintex UltraScale FPGA
arm开发·嵌入式硬件·网络安全·fpga开发·硬件工程·信号处理·fpga
少年、潜行1 天前
IAR FOR ARM 历史版本安装包、安装、注册流程【百度网盘资源】
arm开发·iar·iar历史版本·iar安装
Aaron15882 天前
无人机反制中AOA+TDOA联合定位技术与雷达探测定位技术的应用对比分析
arm开发·嵌入式硬件·fpga开发·硬件工程·无人机·信息与通信·信号处理
m0_747124532 天前
ARM架构基础知识扫盲
arm开发·架构
海绵宝宝de派小星2 天前
MCP与A2A协议深度解析:Agent时代的“TCP/IP“如何诞生
arm开发·网络协议·tcp/ip·ai
Zephyrus_20232 天前
LSM6DSV16X驱动移植+调试
c语言·arm开发
瑞禧生物tech2 天前
四臂聚乙二醇-磷脂 4-Arm PEG-DSPE 反应原理解析
arm开发
振南的单片机世界2 天前
地址总线定“找谁”,数据总线定“搬多少”
arm开发·stm32·单片机