You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过/dev/mem访问超4000字节报Bus Error及Python BRAM读写问题

问题根因

你遇到的超过4000字节触发Bus Error的问题,主要来自三个核心原因:

  • mmap映射长度未做页对齐:Linux 下mmap映射的第二个参数必须是页大小(通常为4KB)的整数倍,你当前直接传入length + virt_offset,当这个值不是页对齐时,访问映射边界外的地址就会触发SIGBUS。4000字节接近4KB页大小,超出后刚好跨页触发边界访问错误。
  • 内核CONFIG_STRICT_DEVMEM限制:多数默认发行版内核开启了该配置,禁止用户空间访问1MB以上的物理内存地址,你使用的0xa0000000地址远高于该阈值,未关闭该配置会直接触发访问异常。
  • numpy数组赋值范围不匹配:写操作时你直接用array[0:length] = data,如果data的长度和length>>2(32位单位的数量)不匹配,会触发越界访问。
修复方案

前置准备

首先确认内核关闭了CONFIG_STRICT_DEVMEM:在内核编译配置中关掉该选项,或者启动内核时添加strict-devmem=0参数,重启后生效。

修正后的读代码

import os
import mmap
import numpy as np

def read_bram(raddr, size):
    page_size = mmap.PAGESIZE
    base_addr = raddr
    virt_base = base_addr & ~(page_size - 1)
    virt_offset = base_addr - virt_base
    # 映射长度向上做页对齐
    map_len = (virt_offset + size + page_size - 1) & ~(page_size - 1)
    mmap_file = os.open('/dev/mem', os.O_RDWR | os.O_SYNC)
    try:
        mem = mmap.mmap(mmap_file, map_len,
                        mmap.MAP_SHARED, mmap.PROT_READ | mmap.PROT_WRITE,
                        offset=virt_base)
        # 按实际需要的长度读取,copy后数据脱离mmap生命周期,关闭映射后仍可正常访问
        rdbuf = np.frombuffer(mem, dtype=np.uint32, count=size >> 2, offset=virt_offset).copy()
    finally:
        os.close(mmap_file)
        mem.close()
    return rdbuf

修正后的写代码

import os
import mmap
import numpy as np

def write_bram(waddr, data):
    page_size = mmap.PAGESIZE
    # data为uint32类型的numpy数组,计算总字节大小
    size = data.size * 4
    base_addr = waddr
    virt_base = base_addr & ~(page_size - 1)
    virt_offset = base_addr - virt_base
    # 映射长度向上做页对齐
    map_len = (virt_offset + size + page_size - 1) & ~(page_size - 1)
    mmap_file = os.open('/dev/mem', os.O_RDWR | os.O_SYNC)
    try:
        mem = mmap.mmap(mmap_file, map_len,
                        mmap.MAP_SHARED, mmap.PROT_READ | mmap.PROT_WRITE,
                        offset=virt_base)
        array = np.frombuffer(mem, dtype=np.uint32, count=size >> 2, offset=virt_offset)
        array[:] = data
        # 强制刷入物理内存,保证数据写入BRAM硬件
        mem.flush()
    finally:
        os.close(mmap_file)
        mem.close()
注意事项
  • 所有操作/dev/mem的程序必须以root权限运行,否则会没有访问权限。
  • 确认BRAM的物理地址范围是连续的,且大小匹配你要读写的长度,不要访问BRAM地址范围之外的空间。
  • 如果需要更高的读写性能,可以去掉os.O_SYNC标志,操作完成后手动调用mem.flush()保证数据写入硬件。

内容的提问来源于stack exchange,提问作者ram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 09:06:03