предупреждение библиотеки 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 ускользает.