gpt4 book ai didi

c++ - C++14及以上的stm32 hal库警告

转载 作者:可可西里 更新时间:2023-11-01 16:36:07 30 4
gpt4 key购买 nike

我也在 STM32 社区论坛中发布了相同的 question,但没有收到回复。

我在启用了 C++14 的项目中使用 stm32 HAL 库。它向我发出以下警告,我无法摆脱。

../platform/stm32/l4/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h:735:57:

warning: conversion to void will not access object of type 'volatile uint32_t {aka volatile long unsigned int}' UNUSED(tmpreg); \

当调用 __GPIOX_CLK_ENABLE() 或 __HAL_RCC_GPIOX_CLK_ENABLE 时会发生这种情况。

有没有人能够摆脱上述警告而使 HAL 源代码完好无损。

或者任何可以做的事情的想法。

当前警告级别为-Wall。

我在 l4 和 f4 系列代码中都遇到过上述问题。

示例代码:

int main(void)
{
HAL_Init();

__GPIOB_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.Pin = GPIO_PIN_7;

GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

for (;;)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
HAL_Delay(500);
}
}

罪魁祸首是 __GPIOB_CLK_ENABLE(),它被扩展为以下内容(在 ST 驱动程序中)。

#define __HAL_RCC_GPIOB_CLK_ENABLE()           do { \
__IO uint32_t tmpreg; \
SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN); \
/* Delay after an RCC peripheral clock enabling */ \
tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN); \
UNUSED(tmpreg); \
} while(0)

我最初的问题是想找到一个解决方案,让底层的 ST 驱动程序完好无损。一种可能的解决方案是使用直接寄存器访问,而无需通过提供方便的宏的库。

提前谢谢你。

最佳答案

问题是 -std=c++14volatile 表达式的语义转换为 (void),并引入了一个显然*无条件警告它,并且 ST 的一名编码员试图“三重确定”寄存器读取将发生。

UNUSED()宏的定义是

#define UNUSED(x) ((void)(x))

__IO定义为

#define     __IO    volatile

那么 __HAL_RCC_GPIOB_CLK_ENABLE() 的扩展就是

do {
volatile uint32_t tmpreg;
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;
/* Delay after an RCC peripheral clock enabling */
tmpreg = RCC->AHB2ENR & RCC_AHB2ENR_GPIOBEN;
((void)(tmpreg));
} while(0)

寄存器的延时和回读是各种STM32 errata saying推荐的

A delay between an RCC peripheral clock enable and the effective peripheral enabling should be taken into account in order to manage the peripheral read/write to registers.

[...]

insert a dummy read operation from the corresponding register just after enabling the peripheral clock.

由于所有外设寄存器当然都被声明为 volatile,一个仅包含相关寄存器的简单表达式将强制通过相同的外设总线进行具有必要等待状态的回读,因此这就足够了:

do {
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;
/* Delay after an RCC peripheral clock enabling */
RCC->AHB2ENR;
} while(0)

其余的可能是针对一些有缺陷的编译器的过度设计的解决方法,但我还没有看到一个如此糟糕以至于可以优化 volatile 类型的表达式。

然而,存在边缘情况,将 volatile 变量强制转换为 (void),其中语义在 C++14 中明显发生了变化。

让我们举个简单的例子

void x() {
volatile int t;
t=1;
((void)(t));
}

Arm gcc 7.2.1 invoked with -O3 -mcpu=cortex-m4 -mthumb -Wall -x c++ -std=c++11将其编译为

x():
sub sp, sp, #8
movs r3, #1
str r3, [sp, #4]
ldr r3, [sp, #4]
add sp, sp, #8
bx lr

the same code compiled with -std=c++14

x():
sub sp, sp, #8
movs r3, #1
str r3, [sp, #4]
add sp, sp, #8
bx lr

...和一个警告:

<source>: In function 'void x()':
<source>:5:13: warning: conversion to void will not access object of type 'volatile int'
((void)(t));
~^~

另请注意第二种情况中缺少的 ldr 指令。使用 C++14 写入后不会访问该变量。

My original question is intended to find out a solution, leaving the underlying ST driver intact. One possible solution would be to use the direct register access without going through the library provided convenient macro.

我建议继续前进并避免使用库,恕我直言,HAL 最好被视为示例或实现建议的集合。

*我找不到禁用它的方法。这并不意味着没有。

关于c++ - C++14及以上的stm32 hal库警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49061212/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com