- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我也在 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++14
将 volatile
表达式的语义转换为 (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/
我正在对 JVM 上的 STM 技术进行一些研究。阅读了一些文档后,我对 Multiverse 的实现有些困惑。 根据 the Multiverse FAQ , Multiverse 不支持检测。然而
我想知道 Clojure 怎么可能已经实现了软件事务内存并且没有发现任何问题,而微软没有完成它的 C# 工作并注意到一些问题使得实现这里描述的 STM 不切实际: http://www.bluebyt
最后,我有以下设置 C:>哪里玩 C:\apps\play-2.2.0\play C:\apps\play-2.2.0\play.bat C:> 哪里 scala C:\apps\scala\bin\
我试图找出 Clojure 所称的 STM 与 Haskell 中实现的 STM 之间的区别。撇开实际的语言语义差异不谈,正如 Rich Hickey 在他的演讲中所说,Clojure 的 STM 实
阅读 Bartosz Milewski 的精彩作品 blog post在 STM 上,我很兴奋地阅读了以下内容: But take into account an important fact: ST
大家好, 在某些时候,我认为这些 stm 实现(我使用过一点点的多元宇宙......),被过度宣传了。因为在某些时候他们使用 CAS 来为他们提供操作的原子性。如果我直接使用 CAS 而不是使用这些实
haskell 的 stm 库中有一个函数,其类型签名如下: alwaysSucceeds :: STM a -> STM () 根据我对 Haskell 中 STM 的了解,在执行 STM 计算时,
在 Clojure 中,我们使用 STM 来实现并发。 我的问题是STM使用数据的时间点值,这是否会带来歧义? 我们如何知道访问了什么值? 最佳答案 Clojure 中的 STM 提供了(通过 ref
我需要有关用作原子更改日志的数据结构的建议。 我正在尝试实现以下算法。有流量传入更改更新内存中的映射。在类似 Haskell 的伪代码中它是 update :: DataSet -> Some
我正在尝试对这两个(软件事务内存和原子操作,我想两者不一样)进行一些基准测试,尽管我没有使用STM做太多事情(它似乎很难使用),但我成功地尝试了对基准测试进行计数,即所有线程将共享计数器递增 5000
我能够使用 STM 初始化状态并将其打印出来: module Main where import Control.Concurrent.STM data State = State {name ::
我读过两个关于 STM 如何实现的完全不同的描述。也许两者都是正确的,或者一个是错误的,我希望有人能阐明这一点。 Take 1(维基百科):允许所有线程修改共享内存,但事务中的每次读写都会被记录下来。
我知道将具有副作用的函数放在 STM 事务中通常是不好的做法,因为它们可能会被重试和调用多次。 然而,在我看来,您可以使用代理来确保只有在事务成功完成后才会执行副作用。 例如 (dosync //
我正在编写一个程序,其中大量代理监听事件并对其使用react。由于Control.Concurrent.Chan.dupChan已弃用我决定使用 TChan 的广告。 TChan 的表现比我预想的差很
我正在研究 Clojure 中的并发编程。 http://clojure.org/concurrent_programming 我了解到atom、ref和agent形式是用来维护程序状态的。 仅ref
你好,我正在阅读《clojure 的乐趣》这本书,在关于 STM 的部分中,他们有一个 2 个事务的图像,其中 A 最初从引用中检索与 B 相同的值,然后事务 A 和 B 都进行计算但 A 首先完成并
我熟悉Database transactions ,并花费了大量的时间调整isolation levels 。我从未在代码中实现过自己的事务模型。 我已通读 the source code对于 Clo
我有一个事务由于某种原因无限期失败,我想在内部使用跟踪指令。例如,要在执行此片段中的事务之前打印 MVar 的状态: data_out do putTMVar
当我们运行 STM 表达式时,它命中了 retry,线程被阻塞,如果条目被修改,事务将再次运行。 但我想知道: 如果我们读取一个 STM 变量,但在导致重试的特定分支中实际未使用该变量,更新它是否会尝
我正在研究 Clojure 中的并发编程。 http://clojure.org/concurrent_programming 我了解到atom、ref 和agent 表单用于维护程序状态。 只有 r
我是一名优秀的程序员,十分优秀!