#c #gcc #embedded #c 20
#c #gcc #встроенный #c 20
Вопрос:
Я только что загрузил GCC 10 с c 20 в свой встроенный проект.
Однако во встроенных приложениях довольно часто используется volatile для сопоставления структур регистров.
Поскольку компилятор не знает, было ли значение регистра изменено извне DMA, имеет смысл «принудительно» перезагрузить этот регистр.
Для повышения производительности некоторые из этих летучих компонентов помещаются в заголовочные файлы C. Когда я включаю эти заголовки в cpp-файл, я получаю множество ошибок устаревания volatile.
Есть ли какой-либо способ отключить эти ошибки?
@Редактировать в соответствии с запросом некоторый пример кода.
/*!
* @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));
}
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)); |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Поскольку эти определения распространяются по всему NXP SDK, я попытался извлечь только необходимые части.
Однако Godbolt, похоже, в порядке. Может быть, это потому, что я использую gcc 10 для arm eabi.
Комментарии:
1. Пожалуйста, покажите код и предупреждение, которое вы получаете. Только некоторые виды использования
volatile
являются устаревшими. Лучший способ — изменить ваш заголовочный файл, чтобы не использовать устаревшие материалы.2. Если вы хотите отключить предупреждения, не решив проблему,
-Wno-deprecated
полностью подавите предупреждения и-Wno-error=deprecated
должны удалить ошибки из-Werror
флага, сохранив предупреждения.3.
compound assignment with 'volatile'-qualified left operand is deprecated
это не то же самое, что'volatile' is deprecated
4. @BasileStarynkevitch За исключением того, что заголовки, предоставляемые поставщиком, обычно предназначены для API-интерфейсов C с условной
extern 'C'
оболочкой для взаимодействия с C . Это может усложниться, а изменение сторонних заголовков затрудняет применение обновлений. Еще одна возможность — не использовать C 20. Я не уверен, что это необходимо для небольших встроенных целей. Стандарт распространяется на места, которые мало интересны большинству разработчиков встраиваемых систем.5. @BasileStarynkevitch Этот код, скорее всего, является настройкой синхронизации какого-либо аппаратного периферийного устройства в микроконтроллере Kinetis, поэтому он очень близок к аппаратному обеспечению и, следовательно, очень непригоден для C . Особенно это касается всех версий C для lalala-im-a-PC, выпущенных после 2011 года.
Ответ №1:
Вы больше не можете использовать |=
, но вы можете использовать =
, поэтому измените это:
(*(volatile uint32_t *)regAddr) |= (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
К этому:
*(volatile uint32_t *)regAddr = *(volatile uint32_t *)regAddr | (1UL << CLK_GATE_ABSTRACT_BITS_SHIFT((uint32_t)name));
Комментарии:
1. уххх, это не мой код. Это SDK от NXP. Подобные инструкции распространяются на весь SDK. Я боялся, что вы можете так сказать: O Поэтому мне придется «скрыть» эти летучие вещества из кода c путем создания оболочек C: O
2.
(*(volatile uint32_t *)regAddr) |=
не эквивалентно*(volatile uint32_t *)regAddr = *(volatile uint32_t *)regAddr
, потому что последний дважды вычисляет выражение volatile. Итак, каково обоснование от блестящего комитета C с их большим количеством программистов для встроенных систем на этот раз?3. @Lundin Стандарт не определяет поведение
x |= y
, если значениеx
изменяется способами, о которых компилятор не знает во время выполнения операции в любом случае. Вы определенно не можете писать такой код переносимым — не существует такого понятия, как «переносимый регистр флага UART», это аппаратная особенность, которая требует кода, зависящего от платформы. Ваша платформа может гарантировать, что|=
это правильно, но это будет гарантия, зависящая от платформы, а не от C 20.4. @Lundin Это просто означает, что любые побочные эффекты, которые он имеет, не могут повторяться дважды. Например, если вы это сделаете
*i |= j
, это означает, что может произойти только одно приращение. Это не означает, что реализация не может читатьi
дважды, еслиi
находится в памяти. Несмотря на то, что аппаратная периферия одна и та же, семейства и ядра разные, поэтому способ доступа к оборудованию в коде отличается.5. @Lundin Ты этого не делаешь. Здесь нет объекта, обозначаемого volatile glvalue . Если вы думаете, что есть, скажите мне, что это за объект.