реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> тонкости constexpr
esaulenka
сообщение Apr 21 2017, 12:01
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Здравствуйте.
Возникла проблема после апгрейда gcc 4.8 на последнюю (6-ю) версию.

Есть у меня класс - драйвер таймера, в котором используемый таймер описан как
static constexpr TIM_TypeDef * const SYSTIMER = TIM6;
где TIM6 - стандартный дефайн ((TIM_TypeDef *) TIM6_BASE).

Раньше всё было хорошо, компилировалось-работало, а теперь поломалось:
начиная с какой-то версии gcc подкрутили, и в полном соответствии со стандартом reinterpret_cast стал неконстантным выражением.

Народ на стековерфлоу предлагает удалить constexpr.
Что-то мне эта идея не нравится - мне в основном надо просто прочитать значение этого таймера, и код этот раздувается вдвое.

Что б тут сделать?.. Обратно #define не хочу...


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Apr 21 2017, 16:16
Сообщение #2


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(esaulenka @ Apr 21 2017, 17:01) *
Что б тут сделать?.. Обратно #define не хочу...

Может, так:
Код
    static constexpr TIM_TypeDef* TIM() { return TIM2; }

?
Надо, конечно, глянуть потом, сработал ли constexpr. Но по крайней мере не ругаетсяsm.gif

А если не привязываться к constexpr, то можно сделать вот так:
Код
struct SomeClass
{
    struct TIMx
    {
        TIM_TypeDef* operator->() { return TIM2; }
    };
};


Тогда можно писать
Код
SomeClass::TIMx->CR = 0;


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Apr 21 2017, 17:24
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Цитата(AHTOXA @ Apr 21 2017, 19:16) *
Может, так:
Код
    static constexpr TIM_TypeDef* TIM() { return TIM2; }

?
Надо, конечно, глянуть потом, сработал ли constexpr. Но по крайней мере не ругаетсяsm.gif

Спасибо большое!!
Проверил на 5-м gcc (5.4 2016q3 от ARM.com).
Он ест оба варианта, содержимое бинарника идентичное.
6-му gcc этот вариант тоже подходит.

Цитата(AHTOXA @ Apr 21 2017, 19:16) *
А если не привязываться к constexpr, то можно сделать вот так:
Код
struct SomeClass
{
    struct TIMx
    {
        TIM_TypeDef* operator->() { return TIM2; }
    };
};


Тогда можно писать
Код
SomeClass::TIMx->CR = 0;

У меня не получилось, ругается невнятными словами. Ну да ладно.


Следующий вопрос, если Вы не против.

Ещё у меня есть конструкция
static PeriphBit<(uintptr_t)&EXTI->IMR, EXTI_IMR_MR1> ExtiUnmaskIRQ;

Откуда я её взял (слегка доработав), думаю, Вы узнаете sm.gif

Код
// возвращает номер старшего бита
constexpr int8_t mask2bit (uint32_t val)
{
    return (val > 1) ? ( mask2bit (val/2) + 1 ) : 0;
}

enum
{
    pPERIPH_BASE      = 0x40000000UL,     // Peripheral base address
    pPERIPH_BB_BASE   = 0x42000000UL,     // Peripheral base address in the bit-band region
    pSRAM1_BB_BASE    = 0x22000000UL,     // SRAM1(112 KB) base address in the bit-band region
    pSRAM2_BB_BASE    = 0x2201C000UL      // SRAM2(16 KB) base address in the bit-band region
};

/**
* Peripheral bit - bit-band accessed bit.
* @param addr        peripheral address
* @param bit_mask    mask of requested bit. Важно! в маске должен быть только ОДИН бит!
*/
template <uintptr_t addr, uint32_t bit_mask> struct PeriphBit
{
    enum { BIT = mask2bit(bit_mask)    };
    enum { BB_ADDR  = pPERIPH_BB_BASE + (addr - pPERIPH_BASE) * 32 };
    uint32_t operator=(uint32_t value)
        { ((volatile uint32_t*)BB_ADDR)[BIT] = (bool)value; return value; }
    operator uint32_t()
        { return ((volatile uint32_t*)BB_ADDR)[BIT]; }
};

Может, тоже подскажете, как доработать?..


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Apr 21 2017, 18:17
Сообщение #4


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(esaulenka @ Apr 21 2017, 22:24) *
Проверил на 5-м gcc (5.4 2016q3 от ARM.com).
Он ест оба варианта, содержимое бинарника идентичное.
6-му gcc этот вариант тоже подходит.

Попробуйте ещё без constexpr. Скорее всего будет то же самое. Зато без скобочекsm.gif
Цитата(esaulenka @ Apr 21 2017, 22:24) *
У меня не получилось, ругается невнятными словами. Ну да ладно.

Вы наверное с -O0 компилируете? Тогда ругается, да. С другими уровнями не должно.
Цитата(esaulenka @ Apr 21 2017, 22:24) *
Может, тоже подскажете, как доработать?..

А что с ней не так? У меня скомпилировалась.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Apr 24 2017, 08:26
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Прошу прощения за пятничный сумбур, очень уж домой хотелось :-)

Код
Building file: ../Drivers/AccelDrv.cpp
Invoking: Cross ARM C++ Compiler
arm-none-eabi-g++ -mcpu=cortex-m3 -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -flto
-Wuninitialized  -g -DSTM32F105xC -DSTM32F10X_CL -I /skipped/ -std=gnu++11 -fabi-version=0 -fno-exceptions -fno-rtti
-MMD -MP -MF"Drivers/AccelDrv.d" -MT"Drivers/AccelDrv.o" -c -o "Drivers/AccelDrv.o" "../Drivers/AccelDrv.cpp"

In file included from ../Drivers/AccelDrv.cpp:8:0:
../Drivers/AccelDrv.h:39:30: error: reinterpret_cast from integer to pointer
  static PeriphBit<(uintptr_t)&EXTI->IMR, EXTI_IMR_MR1> ExtiUnmaskIRQ;
                              ^~~~~~~~~~
../Drivers/AccelDrv.h:39:54: note: in template argument for type 'unsigned int'
  static PeriphBit<(uintptr_t)&EXTI->IMR, EXTI_IMR_MR1> ExtiUnmaskIRQ;


Версия стандарта не влияет. Уровень оптимизации (проверял -Os и -Og) не влияет.

Ещё более корявое решение
static PeriphBit<EXTI_BASE + offsetof(EXTI_TypeDef, IMR), EXTI_IMR_MR1> ExtiUnmaskIRQ;
работает.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
Major
сообщение Apr 24 2017, 10:08
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 618
Регистрация: 7-12-04
Из: Новосибирск
Пользователь №: 1 375



Не ясно в чем проблема?
char x = 0;
auto p = reinterpret_cast<uintptr_t>(&x);
Без ругани сохранили указатель в p, явным приведением типа.

Покажите шаблон, возможно в нем проблема.

Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Apr 24 2017, 11:19
Сообщение #7


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(esaulenka @ Apr 24 2017, 13:26) *
static PeriphBit<(uintptr_t)&EXTI->IMR, EXTI_IMR_MR1> ExtiUnmaskIRQ;

Ну, тоже можно выкрутиться как-то так:
Код
static constexpr uintptr_t IMRAddr() { return (uintptr_t)&EXTI->IMR; }
static PeriphBit2<IMRAddr(), EXTI_IMR_MR1> ExtiUnmaskIRQ;

Но мне больше нравится
EXTI_BASE + offsetof(EXTI_TypeDef, IMR). Насколько я понял, они оставили себе какую-то лазейку и исхитрились сделать offsetof() constexpr. Надо этим пользоватьсяsm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
klen
сообщение May 17 2017, 12:53
Сообщение #8


бессмертным стать можно тремя способами
*****

Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912



Цитата(AHTOXA @ Apr 24 2017, 14:19) *
EXTI_BASE + offsetof(EXTI_TypeDef, IMR). Насколько я понял, они оставили себе какую-то лазейку и исхитрились сделать offsetof() constexpr. Надо этим пользоватьсяsm.gif

ах тыж эво оно как!!!
#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
век живи учись дураком помрешь....
спасибо.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th April 2024 - 23:44
Рейтинг@Mail.ru


Страница сгенерированна за 0.01427 секунд с 7
ELECTRONIX ©2004-2016