在一个嵌入式系统,我们已经安装,使我们能够读取任意数据命令行接口,用于诊断目的。对于大多数数据,这一工作,我们使用 memcpy() 数据复制在要求的地址和发送过一串连接。

但是,16位硬件寄存器, memcpy() 引起一些问题。如果我想要进入一个16位硬件注册使用的两个8位访问,在高阶字节不正确。

有人遇到这个问题?我是一个'高级别'(C#/Java/Python/红宝石)的家伙就是靠拢的硬件,这是外星人的领土。

什么是最好的方式来处理这个吗?我看到一些信息,具体而言,一个有些令人困惑[我的]后 在这里,.提交人的这个职位已 到底 同样的问题,我做的但我讨厌实现一个解决方案没有完全理解我在做什么。

任何灯光,你可以摆脱在此问题上是非常赞赏。谢谢!

有帮助吗?

解决方案

除了什么 埃迪说, 你通常需要使用挥发性指阅读登记册硬件(假设存储器的映射的登记册,这是没有的情况下用于所有系统,但它听起来像是真正的为你的).是这样的:

// using types from stdint.h to ensure particular size values
// most systems that access hardware registers will have typedefs
// for something similar (for 16-bit values might be uint16_t, INT16U,
// or something)

uint16_t volatile* pReg = (int16_t volatile*) 0x1234abcd;  // whatever the reg address is

uint16_t val = *pReg;  // read the 16-bit wide register

这是一系列文章由丹全,应该给你几乎所有你需要知道能够有效地使用存储器的映射在寄存器C/C++:

其他提示

在此硬件每个寄存器被公开为一个两字节的阵列,所述第一元件是在一个两字节边界对齐(其地址为偶数)。的memcpy()运行一个字节在每次迭代循环,并复制,所以从这些寄存器这种方式(所有循环展开,char是一个字节)副本:

*((char*)target) = *((char*)register);// evenly aligned - address is always even
*((char*)target + 1) = *((char*)register + 1);//oddly aligned - address is always odd

然而第二行不正确地工作对于某些硬件具体原因。如果您一次一次复制,而不是一个两个字节,它是不是做这样(短整型是两个字节):

*((short int*)target) = *((short*)register;// evenly aligned

下面复制在一个操作中两个字节,第一字节被均匀地排列。因为有从一个奇怪对齐地址没有单独的复制,它的工作原理。

的修饰的memcpy检查地址是否venely对齐并且如果他们是在拖拷贝字节的块。

如果你需要访问的硬件寄存器的一个具体的大小,那么就有两种选择:

  • 了解你的C编译器产生的代码,所以可以使用适当的整型访问的存储器,或者
  • 嵌入了一些会做的访问正确的字或字的大小。

阅读的硬件寄存器可能有的副作用影响,这取决于登记册及其功能,当然,所以重要的是要访问的硬件寄存器的适当大小的访问,所以你可以阅读整个登记册。

一般它足以为使用整数型,其大小作为寄存器相同。上的的编译器,一短为16位。

void wordcpy(short *dest, const short *src, size_t bytecount)
{
    int i;
    for (i = 0;  i < bytecount/2;  ++i)
        *dest++ = *src++;
}

我觉得所有的细节被包含在该线程您张贴,所以我会尝试打破它一点;

具体而言;

If you access a 16-bit hardware register using two 8-bit
accesses, the high-order byte doesn't read correctly (it
always read as 0xFF for me). This is fair enough since
TI's docs state that 16-bit hardware registers must be
read and written using 16-bit-wide instructions, and
normally would be, unless you're using memcpy() to
read them.

所以这里的问题是,如果它们的值都在一个16位读读取硬件寄存器只报告正确的值。这将等同于做;

uint16 value = *(regAddress);

此读取来自使用单个的16字节的读地址到值寄存器。在另一方面你的memcpy这是一次复制数据的单字节。像;

while (n--)
{
  *(uint8*)pDest++ = *(uint8*)pSource++;
}

因此,这使得寄存器以一次要读取的8位(1个字节),从而导致值为所述无效。

贴在该线程中的解决方案是使用16位读徘徊无论源和目的地是A6位对齐到使用memcpy的一个版本,将复制数据。

你有什么需要知道什么?你已经找到了一个单独的文章,解释它。显然,CPU的文档的需要的16位硬件寄存器进行访问,与16位读取和写入,但您的memcpy的实现使用8位的读/写。因此,他们不在一起工作。

的解决方案是简单地不使用memcpy访问此寄存器。 相反,编写自己的例程拷贝16位值。

不知道问题是什么 - 我认为,后有合适的解决方案。 正如你所说,这个问题是标准的memcpy()程序读取的时间,不用于内存映射的硬件寄存器正常工作的一个字节。这是处理器的限制 - 有根本没有办法得到一个有效的值在时刻读取字节

所建议的解决方案是将写自己的memcpy(),它仅适用于字对齐的地址,并在同一时间读取的16位字。这是相当简单 - 链路不仅提供了C和汇编版本。唯一的疑难杂症是确保你总是这样,从有效对齐地址的16个副本。你可以这样做在两个方面:要么使用连接命令或编译指示,以确保一切都对齐,或为额外的字节在未对齐的缓冲区的前面加上一个特殊情况

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top