Перейти к содержанию
    

тонкости constexpr

Здравствуйте.

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

 

Есть у меня класс - драйвер таймера, в котором используемый таймер описан как

static constexpr TIM_TypeDef * const SYSTIMER = TIM6;

где TIM6 - стандартный дефайн ((TIM_TypeDef *) TIM6_BASE).

 

Раньше всё было хорошо, компилировалось-работало, а теперь поломалось:

начиная с какой-то версии gcc подкрутили, и в полном соответствии со стандартом reinterpret_cast стал неконстантным выражением.

 

Народ на стековерфлоу предлагает удалить constexpr.

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Может, так:

    static constexpr TIM_TypeDef* TIM() { return TIM2; }

?

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

 

А если не привязываться к constexpr, то можно сделать вот так:

struct SomeClass
{
    struct TIMx
    {
        TIM_TypeDef* operator->() { return TIM2; }
    };
};

 

Тогда можно писать

SomeClass::TIMx->CR = 0;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может, так:

    static constexpr TIM_TypeDef* TIM() { return TIM2; }

?

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

Спасибо большое!!

Проверил на 5-м gcc (5.4 2016q3 от ARM.com).

Он ест оба варианта, содержимое бинарника идентичное.

6-му gcc этот вариант тоже подходит.

 

А если не привязываться к constexpr, то можно сделать вот так:

struct SomeClass
{
    struct TIMx
    {
        TIM_TypeDef* operator->() { return TIM2; }
    };
};

 

Тогда можно писать

SomeClass::TIMx->CR = 0;

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

 

 

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

 

Ещё у меня есть конструкция

static PeriphBit<(uintptr_t)&EXTI->IMR, EXTI_IMR_MR1> ExtiUnmaskIRQ;

 

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

 

// возвращает номер старшего бита
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]; }
};

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проверил на 5-м gcc (5.4 2016q3 от ARM.com).

Он ест оба варианта, содержимое бинарника идентичное.

6-му gcc этот вариант тоже подходит.

Попробуйте ещё без constexpr. Скорее всего будет то же самое. Зато без скобочек:)

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

Вы наверное с -O0 компилируете? Тогда ругается, да. С другими уровнями не должно.

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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;

работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не ясно в чем проблема?

char x = 0;

auto p = reinterpret_cast<uintptr_t>(&x);

Без ругани сохранили указатель в p, явным приведением типа.

 

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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. Надо этим пользоваться:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

ах тыж эво оно как!!!

#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)

век живи учись дураком помрешь....

спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...