将 uint16_t 数组作为 uint32_t 指针访问
我正在使用一种 ARM 处理器,该处理器具有 2 个 16 位 ADC 作为一个 32 位值(可以将其视为读取立体声信号的两个通道)。我想获取 uint16_t[1024][2] 形式的值,但系统模块需要使用 uint32_t 指针调用 DMA。如果我将其设为 uint32_t 数组,那么我必须执行 AND 和逻辑移位将其转换回 2 个 uint16_t 值。如果我可以让 DMA 将其视为 32 位内存,但将数据作为 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();
}
I am working with an ARM processor that has 2 16-bit ADC's as one 32-bit value (think of as reading both channels of a stereo signal). I want to get the values as uint16_t[1024][2], but the system modules require the DMA called with a uint32_t pointer. IF I make it a uint32_t array, then I have to do AND and Logical Shifts to convert it back into 2 uint16_t values. Most of the CPU time would be freed up if I could have the DMA see it as 32-bit memory but manipulate the data as a 16-bit 2 element array. Any suggestions?
I am using the STM32CubeIDE which is a plugin to the Eclipse editor with the GCC compiler.
I could not get the DMA to work with any 16-bit values so I set up 32-bit buffer and am looking for a way to do the math as 2 separate 16-bit values.
My attempt was to define a 32-bit value for the buffer and then dereference it for math operations with a 16-bit int 2 element array:
...
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();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
替代方案 0
将数组定义为联合:
将所需的
uint32_t
传递到 DMA 例程:使用
uint16_t
数据:C 标准以这种方式定义了重新解释联合中数据的行为。 (C++ 没有。)
替代方案 1
将
ADC_Buff
定义为uint32_t
数组(如问题中当前的代码所示),将其传递给 DMA 例程,然后使用memcpy重新解释它:编译器可能会对此进行优化以消除memcpy,您可以通过检查生成的汇编语言来检查它。
替代方案 2
将缓冲区定义为
uint16_t [2]
数组,并根据uint32_t
需要进行对齐,并在将其传递到 DMA 例程时强制地址:而 C 标准将如果
HAL_ADCEx_MultiModeStart_DMA
是用 C 代码编写的,则不定义行为,显然完全不是这样,因为 DMA 在严格符合 C 代码的情况下是不可能的。作为一个系统例程,它做自己的事情,编译器在编译此源代码时无法看到它。关于别名的规则是为了给编译器提供优化的机会,在这种情况下它们没有任何作用。替代方案 3
使用替代方案 2 并使用
-fno-strict-aliasing
进行编译,这要求 GCC 和 Clang 支持超出 C 标准提供的别名。如果源文件中的其他位置编译器会利用严格的别名规则,则此开关会阻止这些优化。Alternative 0
Define the array as a union:
Pass the desired
uint32_t
to the DMA routine:Use the
uint16_t
data:The C standard defines the behavior of reinterpreting data in unions this way. (C++ does not.)
Alternative 1
Define
ADC_Buff
as an array ofuint32_t
(as shown in the code currently in the question), pass it to the DMA routine, and then usememcpy
to reinterpret it:The compiler may optimize this to eliminate the
memcpy
, which you can check by examining the generated assembly language.Alternative 2
Define the buffer as an array of
uint16_t [2]
with alignment as needed foruint32_t
and coerce the address when passing it to the DMA routine:While the C standard would not define the behavior if
HAL_ADCEx_MultiModeStart_DMA
were written in C code, it is clearly not, completely, as DMA is impossible in strictly conforming C code. As a system routine, it does its own thing, and the compiler has no visibility into it when compiling this source code. The rules about aliasing are to give the compiler opportunities to optimize, and they have no effect in this case.Alternative 3
Use alternative 2 and compile with
-fno-strict-aliasing
, which asks GCC and Clang to support aliasing beyond what the C standard provides. If there are other places in the source file where the compiler would take advantage of the strict aliasing rules, this switch prevents those optimizations.