无DMA支持时,CPU从NIC读取数据的处理方式及指令序列问询
外设无法使用DMA时的数据传输方案
核心处理逻辑
当NIC这类外设无法通过DMA直接将板载缓冲区数据传输到系统内存时,只能依赖CPU作为中介完成数据搬运——本质是CPU从外设的板载缓冲区(属于内存映射IO,即MMIO区域)读取数据,再写入到系统内存的目标地址。
通用指令序列(x86/ARM通用逻辑)
不管是x86还是ARM,核心流程一致,分为以下步骤:
- 确认地址范围:获取外设板载缓冲区的MMIO基址(比如x86的BAR地址、ARM的外设映射基址),以及系统内存的目标缓冲区地址,同时确定待传输的数据长度。
- 循环逐单元搬运:
- 从外设MMIO地址读取一个数据单元(字节/半字/字,取决于外设位宽和传输需求)
- 将读取到的数据写入系统内存的目标地址
- 偏移外设源地址和系统内存目标地址,重复操作直到所有数据传输完成
- 同步收尾:根据外设规范,可能需要写入特定MMIO寄存器,确认传输完成或清除外设的中断/就绪标记。
x86架构汇编示例
; 假设:外设MMIO地址存于EBX,系统内存目标地址存于ESI,数据长度存于ECX mov ecx, [data_len] ; 加载待传输的字节总数 transfer_loop: mov al, [ebx] ; 从外设MMIO读取1字节到AL寄存器 mov [esi], al ; 将AL中的字节写入系统内存目标地址 inc ebx ; 外设地址偏移+1 inc esi ; 系统内存地址偏移+1 dec ecx ; 剩余传输长度-1 jnz transfer_loop ; 未传输完成则继续循环 ; 可选:写入外设控制寄存器,标记传输完成 mov dword [periph_ctrl_reg], 0x1
ARM架构汇编示例(AArch32)
; 假设:外设MMIO地址存于r0,系统内存目标地址存于r1,数据长度存于r2 transfer_loop: ldrb r3, [r0] ; 从外设MMIO读取1字节到r3寄存器 strb r3, [r1] ; 将r3中的字节写入系统内存目标地址 add r0, r0, #1 ; 外设地址偏移+1 add r1, r1, #1 ; 系统内存地址偏移+1 subs r2, r2, #1 ; 剩余长度-1并设置标志位 bne transfer_loop ; 长度未清零则继续循环 ; 可选:写入外设状态寄存器完成同步 mov r3, #0x1 str r3, [periph_status_reg]
操作数类型说明
这个过程仅涉及内存地址引用,不会将数据本身作为立即操作数。因为外设的板载数据是动态存储在MMIO区域的,CPU只能通过内存地址去读取这些数据,再写入到系统内存的对应地址;而立即操作数是指令中编码的固定值,无法适配动态变化的外设数据。
额外注意点
- CPU介入的传输效率远低于DMA,因为每一次数据读写都会占用CPU周期,还会增加缓存一致性的额外开销。
- 部分架构支持批量传输指令(比如x86的
rep movsb、ARM的LDM/STM),可以减少循环的指令开销,但本质仍是CPU逐单元完成数据搬运。
内容的提问来源于stack exchange,提问作者19216811
相关产品推荐
相关产品推荐

