繁体   English   中英

将 uint16_t 数组作为 uint32_t 指针访问

[英]Accessing a uint16_t array as a uint32_t pointer

我正在使用一个 ARM 处理器,它有 2 个 16 位 ADC 作为一个 32 位值(认为是读取立体声信号的两个通道)。 我想获取 uint16_t[1024][2] 的值,但系统模块需要使用 uint32_t 指针调用的 DMA。 如果我将它设为 uint32_t 数组,那么我必须执行 AND 和逻辑移位以将其转换回 2 个 uint16_t 值。 如果我可以让 DMA 将其视为 32 位 memory 但将数据作为 16 位 2 元素数组进行操作,则可以释放大部分 CPU 时间。 有什么建议么?

我正在使用 STM32CubeIDE,它是带有 GCC 编译器的 Eclipse 编辑器的插件。

我无法让 DMA 使用任何 16 位值,因此我设置了 32 位缓冲区,并正在寻找一种方法来将数学运算作为 2 个单独的 16 位值。 我的尝试是为缓冲区定义一个 32 位值,然后使用 16 位 int 2 元素数组取消引用它以进行数学运算:

...
static uint32_t ADC_Buff[SAMPLES*2];
static uint16_t *vasamples[][2];
*vasamples= &ADC_Buff;
...
// setup DMA
if (HAL_ADCEx_MultiModeStart_DMA(&hadc1, *(ADC_Buff), (uint32_t)(SAMPLES)) != HAL_OK)
{
    errnum = 4;
    Error_Handler();
}

备选 0

将数组定义为联合:

static union {
    uint32_t u32[SAMPLES*2];
    uint16_t u16[SAMPLES*2][2];
} ADC_Buff;

将所需的uint32_t传递给 DMA 例程:

HAL_ADCEx_MultiModeStart_DMA(&hadc1, ADC_Buff.u32, (uint32_t) SAMPLES)

使用uint16_t数据:

for (size_t i = 0; i < SAMPLES*2; ++i)
    printf("Sample[%zu] = %" PRIu16 ", %" PRIu16 ".\n",
        i, ADC_Buff.u16[i][0], ADC_Buff.u16[i][1]);

C 标准定义了以这种方式在联合中重新解释数据的行为。 (C++ 没有。)

备选方案 1

ADC_Buff定义为uint32_t的数组(如题中当前代码所示),传递给DMA例程,然后使用memcpy重新解释:

for (size_t i = 0; i < SAMPLES*2; ++i)
{
    uint16_t t[2];
    memcpy(t, &ADC_Buff[i], sizeof t);
    printf("Sample[%zu] = %" PRIu16 ", %" PRIu16 ".\n",
        i, t[0], t[1]);
}

编译器可能会对此进行优化以消除memcpy ,您可以通过检查生成的汇编语言来检查它。

备选方案 2

根据uint32_t的需要将缓冲区定义为uint16_t [2]和 alignment 的数组,并在将其传递给 DMA 例程时强制地址:

static uint16_t _Alignas (uint32_t) ADC_Buff[SAMPLES*2][2];

…
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t *) ADC_Buff, (uint32_t) SAMPLES)

虽然 C 标准不会定义如果HAL_ADCEx_MultiModeStart_DMA写在 C 代码中的行为,但显然不是,完全,因为 DMA 不可能严格符合 C 代码。 作为系统例程,它做自己的事情,编译器在编译这段源代码时对它不可见。 关于别名的规则是为了给编译器提供优化的机会,在这种情况下它们没有任何作用。

备选方案 3

使用备选方案 2 并使用-fno-strict-aliasing编译,它要求 GCC 和 Clang 支持超出 C 标准提供的别名。 如果源文件中的其他地方编译器会利用严格的别名规则,则此开关会阻止这些优化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM