c++20 中是否不推荐使用 volatile 限定符?

JHe*_*eni 4 c++ embedded gcc c++20

我刚刚在我的嵌入式项目中下载了带有 c++20 的 GCC 10。

然而,在嵌入式应用程序中,寄存器结构映射器使用 volatile 是很常见的。

由于编译器不知道寄存器值是否被 DMA 从外部更改,因此“强制”重新加载该寄存器是有意义的。

为了提高性能,其中一些 volatiles 被放置在 C 头文件中。当我在 cpp 文件中包含这些头文件时,我会收到很多不稳定的弃用错误。

有什么办法可以禁用这些错误吗?

@Edit 根据要求提供一些示例代码。

/*!
 * @brief Enable the clock for specific IP.
 *
 * @param name  Which clock to enable, see \ref clock_ip_name_t.
 */
static inline void CLOCK_EnableClock(clock_ip_name_t name)
{
    uint32_t regAddr = SIM_BASE + CLK_GATE_ABSTRACT_REG_OFFSET((uint32_t)name);
    (*(volatile uint32_t *)regAddr) |= (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
}
Run Code Online (Sandbox Code Playgroud)
C:/xxx/kinetisSDK/2.7.0/devices/MK64F12/drivers/fsl_clock.h:671:37: error: compound assignment with 'volatile'-qualified left operand is deprecated [- Werror=volatile] 
671 |     (*(volatile uint32_t *)regAddr) |= (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));      |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

由于这些定义遍布 NXP SDK,因此我尝试仅提取必要的部分。

https://godbolt.org/z/WKzj5j

不过Godbolt好像没问题。也许是因为我将 gcc 10 用于 arm eabi。

Joh*_*nck 7

你不能再使用|=了,但你可以使用=,所以改变这个:

(*(volatile uint32_t *)regAddr) |= (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
Run Code Online (Sandbox Code Playgroud)

对此:

*(volatile uint32_t *)regAddr = *(volatile uint32_t *)regAddr | (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
Run Code Online (Sandbox Code Playgroud)

  • `(*(易失性 uint32_t *)regAddr) |= ` 不等价于 `*(易失性 uint32_t *)regAddr = *(易失性 uint32_t *)regAddr`,因为后者对 易失性表达式求值两次。那么,出色的 C++ 委员会这次大量参与嵌入式系统程序员的理由是什么? (2认同)
  • @Lundin 如果“x”的值以编译器在操作执行期间不知道的方式发生变化,则标准不会定义“x |= y”的行为。你绝对不能以可移植的方式编写这样的代码——不存在“可移植的 UART 标志寄存器”这样的东西,它是一个需要特定于平台的代码的硬件怪癖。您的平台可能保证 `|=` 做正确的事情,但这将是特定于平台的保证,而不是 C++20 的保证。 (2认同)