2

我正在使用 XC32 编译器为 PIC32MX795F512L 编写一些代码。我需要从作为 void* 传递给函数的缓冲区中读取数据。我需要将数据读取为无符号 32 位整数数组。问题是当我将 void* 转换为 uint32* 并尝试读取该数组的索引 0 处的值时,处理器会调用一般错误处理程序,而如果我将 void* 转换为 uint8* 并执行一些操作位操作以获得相同的数据,它可以正常工作。

代码如下所示:

void foo(void* data, uint32 length)
{
    uint32 i,j;
    uint32 block;
    for(i = 0, j = 0; i < length; i+= sizeof(uint32),j++)
    {
        printfUART(DEBUG_UART,"Debug 0\r\n");
#if 0//working code
        block = ((uint8*)data)[i + 3];
        block <<= 8;
        block |= ((uint8*)data)[i + 2];
        block <<= 8;
        block |= ((uint8*)data)[i + 1];
        block <<= 8;
        block |= ((uint8*)data)[i + 0];
#else//not working code
        block = ((uint32*)data)[j];
#endif
        printfUART(DEBUG_UART,"Debug 1\r\n");
    }
}

如果您将代码更改为#if 0按预期工作,我在循环中#if 1看到"Debug 0"并打印了很多次。"Debug 1"

但是如果你保持原样,“Debug 0”只会打印一次,然后代码会跳出循环进入编译器设置的cpu通用错误处理程序。这是 XC32 编译器中的错误,还是我缺少什么?

4

4 回答 4

5

我认为这是一个对齐问题。

如果data不在偶数地址(例如,因为它实际上是一个字节数组),则在您的平台上可能无法以 32 位方式访问它。

C 标准 (ISO/IEC 9899:1999, 6.3.2.3) 说:

指向对象或不完整类型的指针可以转换为指向不同对象或不完整类型的指针。如果结果指针未正确对齐指向的类型,则行为未定义。

于 2014-07-02T14:46:40.747 回答
2

您可以通过以下方式实现预期效果,而不是block = ((uint32*)data)[j];可能存在对齐问题:

memcpy( &block, data + j, sizeof block );

请注意,这在概念上与从单个字节构建它的版本不同。这取决于您的 CPU 如何表示整数(通常称为“字节序”)。

于 2014-07-04T00:21:06.443 回答
0

下面是您的代码,添加了调试输出。在主循环中,它在其占用的内存上运行了一些数组(故意),并且到目前为止它工作正常(尽管它可能仍然是平台不兼容的)。我很确定你没foo()问题,编译器也是,但你可能错误地称呼它。使用调试输出检查所有地址和值并检查范围。

void foo(void* data, unsigned int length)
{
    unsigned int  i,j;
    unsigned int  block;
    for(i = 0, j = 0; i < length; i+= sizeof(unsigned int ),j++)
    {
        printf("Debug 0\r\n");
        printf("i: 0x%d\r\n", i);
        printf("j: 0x%d\r\n", j );
#if 0//working code
        block = ((unsigned char*)data)[i + 3];
        block <<= 8;
        block |= ((unsigned char*)data)[i + 2];
        block <<= 8;
        block |= ((unsigned char*)data)[i + 1];
        block <<= 8;
        block |= ((unsigned char*)data)[i + 0];
#else//not working code
        block = ((unsigned int *)data)[j];
#endif
        printf("data: 0x%x\r\n", data );
        printf( " ((unsigned int )data +j) = 0x%x\r\n", ((unsigned int )data +j) );
        printf( " ((unsigned int *)data)[j] = 0x%x\r\n", ((unsigned int *)data)[j]);
        printf("block: 0x%x\r\n", block );
        printf("Debug 1\r\n");
        printf("\r\n");
        printf("\r\n");
    }
}

int main(void)
{
 unsigned int array[10] = {0xFE,0xED,0xBA,0xBE,0xDE,0xAD,0xBE,0xEF,0xCA,0xFE};
 printf ("array: 0x%x\r\n",array);
 printf ("array[1]:%x\r\n",array[1]);
 foo((void*) array, 50);

}

它的输出:

数组:0x1d0fdde0 数组[1]:ed 调试 0 i:0x0 j:0x0 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fdde0 ((unsigned int *)data)[j] = 0xfe 块:0xfe 调试 1

调试 0 i:0x4 j:0x1 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fdde1 ((unsigned int *)data)[j] = 0xed 块:0xed 调试 1

调试 0 i:0x8 j:0x2 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fdde2 ((unsigned int *)data)[j] = 0xba 块:0xba 调试 1

调试 0 i:0x12 j:0x3 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fdde3 ((unsigned int *)data)[j] = 0xbe 块:0xbe 调试 1

调试 0 i:0x16 j:0x4 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fdde4 ((unsigned int *)data)[j] = 0xde 块:0xde 调试 1

调试 0 i:0x20 j:0x5 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fdde5 ((unsigned int *)data)[j] = 0xad 块:0xad 调试 1

调试 0 i:0x24 j:0x6 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fdde6 ((unsigned int *)data)[j] = 0xbe 块:0xbe 调试 1

调试 0 i:0x28 j:0x7 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fdde7 ((unsigned int *)data)[j] = 0xef 块:0xef 调试 1

调试 0 i:0x32 j:0x8 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fdde8 ((unsigned int *)data)[j] = 0xca 块:0xca 调试 1

调试 0 i:0x36 j:0x9 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fdde9 ((unsigned int *)data)[j] = 0xfe 块:0xfe 调试 1

调试 0 i:0x40 j:0x10 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fddea ((unsigned int *)data)[j] = 0x0 块:0x0 调试 1

调试 0 i:0x44 j:0x11 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fddeb ((unsigned int *)data)[j] = 0x0 块:0x0 调试 1

调试 0 i:0x48 j:0x12 数据:0x1d0fdde0 ((unsigned int )data +j) = 0x1d0fddec ((unsigned int *)data)[j] = 0x0 块:0x0 调试 1

如果您更新更多详细信息和/或新结果,任何人都会获得更多理解并做出更好的答案,您将获得更可靠的答案。

于 2014-07-03T02:58:39.280 回答
0

undur_gongor 是正确的,这是一个对齐问题。考虑以下结构:

struct demo {
   uint8_t char_var;
   uint16_t short_var;
   uint32_t int_var;
};

如果打包结构放置在对齐的地址 0 处,那么您有一个从奇数地址 1 开始的 16 位变量和一个从地址 3 开始的 32 位变量。PIC32 只能从偶数地址(0、2、 4...) 和一个来自类似对齐地址 (0, 4, 8) 的 32 位变量。

访问打包结构或类似结构时,编译器会采取额外的步骤。解决方法一般是写入不受对齐影响的单个字节。正如 MM 提到的,最简单的解决方案是使用 memcpy。

于 2017-06-16T14:50:32.620 回答