предупреждение библиотеки stm32 HAL с C++14 и выше
я опубликовал то же самое вопрос на форуме сообщества STM32, но не получил ответа.
Я использую библиотеку stm32 HAL в проекте с включенным C++14. Он выдает мне следующее предупреждение, от которого я не могу избавиться.
../ платформа / stm32/l4/STM32L4xx_HAL_Driver/Inc / stm32l4xx_hal_rcc.h: 735: 57:
предупреждение: преобразование в void не будет иметь доступа к объекту типа ' volatile uint32_t {aka volatile long unsigned int} ' неиспользуемый(tmpreg);
это происходит, когда вызов __GPIOX_ЦЛК_включить() или __Хэла_РКЦ_GPIOX_ЦЛК_включить называется.
кто-нибудь смог избавиться от вышеуказанного предупреждения, оставив исходный код HAL нетронутым.
или любые идеи о том, что можно сделать.
текущий уровень предупреждения -стены.
я испытал вышеуказанную проблему с кодом серии 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 неповрежденным. Одним из возможных решений было бы использовать прямой доступ к регистру, не проходя через библиотеку, предоставляемую удобным макросом.
спасибо заранее.
2 ответов
проблема -std=c++14
изменение семантики a 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 говоря
задержка между периферийными часами RCC enable и эффективным периферийным включением должна учитываться для управления периферийным чтением/записью в регистры.
[...]
вставьте фиктивную операцию чтения из соответствующего регистра сразу после включение периферийных часов.
поскольку все периферийные регистры, конечно, объявлены as volatile
, простое выражение, содержащее только рассматриваемый регистр, заставит обратный отсчет с необходимыми состояниями ожидания через ту же периферийную шину, поэтому этого будет достаточно:
do {
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;
/* Delay after an RCC peripheral clock enabling */
RCC->AHB2ENR;
} while(0)
остальное, по-видимому, является чрезмерно продуманным обходным путем для некоторых багги-компиляторов, но я еще не видел одного настолько сломанного, что выражение с изменчивым типом было бы оптимизировано.
существует этот крайний случай, однако, с изменчивой переменной, приведенной к (void)
, где семантика, по-видимому, изменилась в C++14.
давайте возьмем простой пример
void x() {
volatile int t;
t=1;
((void)(t));
}
Arm gcc 7.2.1 вызывается с помощью -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
и тот же код, скомпилированный с -std=c++14
is
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.
мой первоначальный вопрос предназначен для поиска решения, оставляя основной драйвер ST неповрежденным. Одним из возможных решений было бы использовать прямой доступ к регистру, не проходя через библиотеку, предоставляемую удобным макросом.
Я бы предложил идти вперед и избегать библиотеки, IMHO HAL лучше рассматривать как коллекцию примеров или предложений по реализации.
*я не мог найти способ, чтобы отключить его. Что не значит, нет.
есть код, который вы можете зафиксировать в своем собственном репозитории, чтобы обойти проблему и скомпилировать код с помощью c++14.
/* Workaround for the broken UNUSED macro */
#include "stm32f3xx_hal_def.h"
#undef UNUSED
#define UNUSED(x) ((void)((uint32_t)(x)))
Это должно быть добавлено перед включением любого из заголовков HAL. Для меня было удобно разместить в stm32f3xx_hal_conf.h
файл сразу после включения модуля макросов (т. е. #define HAL_WWDG_MODULE_ENABLED
line), но перед фактическими заголовками HAL включены.
Я обновил все свои источники до #include "stm32f3xx_hal_conf.h"
вместо отдельных заголовков HAL.
это работает, потому что основан на прекрасные научные @берендъи предупреждение происходит в форме volatile
назначение. При приведении значения к чему-то, что не является изменчивым, новое предложение в стандарте C++14 ускользает.