【发布时间】:2012-09-04 20:05:07
【问题描述】:
我需要在自定义硬件上的嵌入式 Linux 环境中使用 TMS320DM368 读取异步外部存储器接口 (AEMIF)。 我实际上还没有硬件,所以我正在 Leopardboard 368 上测试 vala 代码(如下)。 引导加载程序使用第一个 AEMIF 来读取 nand flash。 我的代码正在尝试使用第二个 AEMIF 来读取不在 Leopardboard 上但将在自定义硬件上的 SRAM。 我怀疑分段错误是由于我试图访问受保护的内存而引起的。 实际的自定义硬件将有几 M 需要读取的 SRAM,但我试图让这个测试代码读取读取 256 个字节。 如何修复由下面的测试代码引起的分段错误? 我需要向内核添加驱动程序吗? 如果可能的话,我宁愿不要弄乱内核。 是否有嵌入式 Linux 方法来配置或声明某些地址范围不受保护?
uint8 * source = (uint8 *)0x04000000; // AEMIF Data (CE1)
uint32 * pA2CR = (uint32 *)0x01D10014; // AEMIF 2 Config Reg (CS3 space)
const uint32 READ_SETUP = 1; // Read setup: EMIF clock cycles - 1
*pA2CR = (READ_SETUP << 13);
const size_t size = 256;
var dest = new uint8[size];
memset(dest, 0, size);
memcpy(dest, source, size);
【问题讨论】:
-
段错误可能不是保护违规,而只是访问未映射到物理内存的用户内存。一个短期的解决方案是
mmap()一个文件来代替 SRAM。请注意,mmap()可以提供一个虚拟地址以供使用或将返回一个虚拟地址。顺便说一句,如果您有“自定义硬件”,那么您将不得不“弄乱内核”。另见stackoverflow.com/questions/11500291/… -
@sawdust 定制硬件几乎与 Leopoardboard 相同,这款 SRAM IF 可能是唯一的出发点。如果我必须更改内核,我会的。
-
Vala 方面的一些小注释:您不需要 memset(Vala 将为您将新缓冲区初始化为 0)。此外,像
unowned uint8[] source = (uint8[]) 0x04000000;这样的操作可能更容易,然后您可以使用数组切片来获取您想要的数据(例如,var dest = source[0:256];)。你真的几乎不需要在 Vala 中使用原始指针,尽管一些绑定(特别是 libxml2 和 posix)会诱使你这样做。 -
那么这个地址存在于设备上吗?在基于 Linux 的系统上,每当我需要访问物理地址时,我都会使用 devmem2。这可以帮助您检查您是否可以访问该地址并编写类似的代码。 (你可以在这里找到它的副本:elinux.org/images/a/aa/Devmem2.c)
-
Linux 内核不允许用户进程随意更改您想要的任何物理内存位置。您要么需要编写设备驱动程序,要么需要在设备的 I/O 范围内编写内存映射(如果您的内核支持)。但后者是有问题的,因为没有好的方法来控制对 I/O 区域的访问。因此,您可能会与正在发生的其他事情发生冲突并导致各种问题。您真的应该从内核中执行此操作。
标签: kernel arm embedded-linux vala mmu