esaulenka 7 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Здравствуйте. Возникла проблема после апгрейда gcc 4.8 на последнюю (6-ю) версию. Есть у меня класс - драйвер таймера, в котором используемый таймер описан как static constexpr TIM_TypeDef * const SYSTIMER = TIM6; где TIM6 - стандартный дефайн ((TIM_TypeDef *) TIM6_BASE). Раньше всё было хорошо, компилировалось-работало, а теперь поломалось: начиная с какой-то версии gcc подкрутили, и в полном соответствии со стандартом reinterpret_cast стал неконстантным выражением. Народ на стековерфлоу предлагает удалить constexpr. Что-то мне эта идея не нравится - мне в основном надо просто прочитать значение этого таймера, и код этот раздувается вдвое. Что б тут сделать?.. Обратно #define не хочу... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Что б тут сделать?.. Обратно #define не хочу... Может, так: static constexpr TIM_TypeDef* TIM() { return TIM2; } ? Надо, конечно, глянуть потом, сработал ли constexpr. Но по крайней мере не ругается:) А если не привязываться к constexpr, то можно сделать вот так: struct SomeClass { struct TIMx { TIM_TypeDef* operator->() { return TIM2; } }; }; Тогда можно писать SomeClass::TIMx->CR = 0; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Может, так: 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]; } }; Может, тоже подскажете, как доработать?.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 21 апреля, 2017 Опубликовано 21 апреля, 2017 · Жалоба Проверил на 5-м gcc (5.4 2016q3 от ARM.com). Он ест оба варианта, содержимое бинарника идентичное. 6-му gcc этот вариант тоже подходит. Попробуйте ещё без constexpr. Скорее всего будет то же самое. Зато без скобочек:) У меня не получилось, ругается невнятными словами. Ну да ладно. Вы наверное с -O0 компилируете? Тогда ругается, да. С другими уровнями не должно. Может, тоже подскажете, как доработать?.. А что с ней не так? У меня скомпилировалась. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 24 апреля, 2017 Опубликовано 24 апреля, 2017 · Жалоба Прошу прощения за пятничный сумбур, очень уж домой хотелось :-) 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; работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Major 0 24 апреля, 2017 Опубликовано 24 апреля, 2017 · Жалоба Не ясно в чем проблема? char x = 0; auto p = reinterpret_cast<uintptr_t>(&x); Без ругани сохранили указатель в p, явным приведением типа. Покажите шаблон, возможно в нем проблема. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 24 апреля, 2017 Опубликовано 24 апреля, 2017 · Жалоба 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. Надо этим пользоваться:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
klen 1 17 мая, 2017 Опубликовано 17 мая, 2017 · Жалоба EXTI_BASE + offsetof(EXTI_TypeDef, IMR). Насколько я понял, они оставили себе какую-то лазейку и исхитрились сделать offsetof() constexpr. Надо этим пользоваться:) ах тыж эво оно как!!! #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) век живи учись дураком помрешь.... спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться