Kernel 如何修复分段故障?

Kernel 如何修复分段故障?,kernel,arm,embedded-linux,vala,mmu,Kernel,Arm,Embedded Linux,Vala,Mmu,我需要在自定义硬件上的嵌入式linux环境中使用读取异步外部内存接口()。 我实际上还没有硬件,所以我正在Leopardboard 368上测试vala代码(如下)。 引导加载程序使用第一个AEMIF读取nand闪存。 我的代码试图使用第二个AEMIF读取不在Leopardboard上但将在自定义硬件上的SRAM。 我怀疑分段错误是由于我试图访问受保护的内存。 实际的自定义硬件将有几个M的SRAM需要读取,但我正试图让这个测试代码读取256字节。 如何修复由以下测试代码引起的分段错误? 我需要向

我需要在自定义硬件上的嵌入式linux环境中使用读取异步外部内存接口()。 我实际上还没有硬件,所以我正在Leopardboard 368上测试vala代码(如下)。 引导加载程序使用第一个AEMIF读取nand闪存。 我的代码试图使用第二个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);
uint8*源=(uint8*)0x04000000;//AEMIF数据(CE1)
uint32*pA2CR=(uint32*)0x01D10014;//AEMIF 2配置注册表(CS3空间)
const uint32 READ_SETUP=1;//读取设置:EMIF时钟周期-1

*pA2CR=(READ_SETUP我不熟悉DM386,但我曾经在DM6446上工作。在DM6446中,但我希望在DM368上也一样,物理地址被重新映射

我不知道您的情况,但我认为您可以使用miscdevice编写驱动程序,并为您的用户空间程序提供读写操作支持

在我的内核模块中,我使用
IO\u ADDRESS
宏进行重新映射并访问寄存器。举个例子:

#define REG_PINMUX1     (*((volatile unsigned long *) (IO_ADDRESS(PINMUX1))))
然后在代码中我有如下命令

REG_PINMUX0 &= ~(0x01000000);

因此,我认为您得到SEGFULT是因为您有一个错误的指针。尝试在没有内核模块的情况下从用户空间程序访问hw寄存器不是一个好策略。

SEGFULT可能不是违反保护,只是访问未映射到物理内存的用户内存。短期解决方案是
mmap()
替代SRAM的文件。请注意,
mmap()
可以提供一个要使用的虚拟地址或返回一个虚拟地址。顺便说一句,如果您有“自定义硬件”,那么您将不得不“弄乱内核”。另请参见@sawdust定制硬件与Leopoardboard几乎相同,此SRAM IF可能是唯一的例外。如果我必须更改内核,我会的。请注意Vala方面的几点:您不需要memset(Vala将为您将新缓冲区初始化为0)。此外,只需执行诸如
unowned uint8[]source=(uint8[])0x04000000;
之类的操作可能会更容易,然后您就可以使用数组切片来获取所需的数据(例如,
var dest=source[0:256];
)。您实际上几乎不需要在Vala中使用原始指针,尽管有些绑定(特别是libxml2和posix)这会吸引你这么做。那么这个地址存在于设备上吗?在基于Linux的系统上,每当我需要访问物理地址时,我都会使用devmem2。这可以帮助你检查是否可以访问该地址并编写类似的代码。(你可以在此处找到它的副本:)Linux内核不允许用户进程只是去更改您想要的任何物理内存位置。您需要为设备编写一个设备驱动程序,或者在设备的I/O范围内编写内存映射(如果您的内核支持的话)。但是执行后一种操作是有问题的,因为没有好的方法来控制对I/O区域的访问。因此,您可能会与正在进行的其他操作发生冲突,并导致各种问题。您确实应该从内核执行此操作。