ViKo 1 18 июля, 2019 Опубликовано 18 июля, 2019 · Жалоба Подходит. Эта функция нужна чисто для проверки диапазона. Вызывается много раз, но всегда с константой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 18 июля, 2019 Опубликовано 18 июля, 2019 · Жалоба Однако, для не целых аргументов такой способ не подходит. К примеру: #define HMCAD_FSCALE(CNT) \ (((CNT >= 0 ? CNT : CNT - 0.3) * 100 + 15) / 30 + 32) // Fine Gain (1.0077...0.0.9923) #define HMCAD_FGAIN_XX(XX) \ ((XX >= 1) ? (XX - 1 + 2E-14) / 2E-13 : 0x7F - (1 - XX + 2E-14) / 2E-13) Здесь я не могу сделать inline функцию не только с вычислением результата, но и со static_assert проверкой диапазона аргумента. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 18 июля, 2019 Опубликовано 18 июля, 2019 · Жалоба Выброшу static_assert, буду использовать inline функции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 18 июля, 2019 Опубликовано 18 июля, 2019 · Жалоба 3 часа назад, ViKo сказал: Подходит. Эта функция нужна чисто для проверки диапазона. Вызывается много раз, но всегда с константой. Зачем тогда функция? Если аргумент всегда - константа, то логично написать макрос. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 18 июля, 2019 Опубликовано 18 июля, 2019 · Жалоба 25 минут назад, jcxz сказал: Зачем тогда функция? Если аргумент всегда - константа, то логично написать макрос. С #error? Это не современно. И функций у меня много разных. Надо в одном стиле всё делать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 19 июля, 2019 Опубликовано 19 июля, 2019 · Жалоба Сделал иначе. Недопустимые диапазоны аргументов преобразовываю в граничные допустимые, операторами ? : И функции инлайнятся, и непотребного не выдают. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба Погружаюсь в шаблоны. Косячу. template <GPIO_TypeDef *port, unsigned bit> struct Pin_st { static constexpr GPIO_TypeDef *Port = port; static constexpr unsigned Bit = bit; static constexpr uint16_t Mask = 1 << bit; }; using Adc1s_n = Pin_st <GPIOB, 13>; using Adc2s_n = Pin_st <GPIOB, 14>; Получаю. Source\main.h(108): error: #873: non-integral operation not allowed in nontype template argument Указатели же допускаются. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба 5 minutes ago, ViKo said: Source\main.h(108): error: #873: non-integral operation not allowed in nontype template argument У меня на этот пример ничего не ругается (ARM compiler v6, включен C++11). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба 3 минуты назад, Forger сказал: У меня на этот пример ничего не ругается (ARM compiler v6, включен C++11). Проверил, не ругается. Но ругается на многое другое. Так что пока остаюсь на v5. Чего же там не хватает. Кажется, смогу заменить на static constexpr GPIO_TypeDef *Port = port == 'A' ? GPIOA : port == 'B' ? GPIOB : port == 'C' ? GPIOC : Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба Заменил, как написал. Скомпилировалось. Не всё умеет v5. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба 42 minutes ago, ViKo said: Заменил, как написал. Скомпилировалось. Не всё умеет v5. Когда делал свой шаблон Pin, тогда сидел на v5 и тоже столкнулся с этой "руганью" компилятора. Решил в лоб: всего один параметр в шаблоне, разбор идет в конструкторе абстрактного класса, например: Hardware::Pin<PD1> pinCAN1_TX; ... Hardware::DigitalOutputPin<PA9> pinON; Но каждый такой pin требует доп. ОЗУ для хранения указателей на порт и маску. Учитывая, что чем больше число пинов у камня, тем больше у него ОЗУ, забил на этот "минус" )) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба А как вы их распознаёте, PD1, PA9? Ну, как компилятор их интерпретирует? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба 40 minutes ago, ViKo said: А как вы их распознаёте, PD1, PA9? Ну, как компилятор их интерпретирует? Абстрактный класс, который в конструкторе разбирает соотв. параметр: Spoiler ... using PinName = enum { PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PA8, PA9, PA10, PA11, PA12, PA13, PA14, PA15, // 0 PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13, PB14, PB15, // 1 .... NONE }; ..... namespace stm32f4 { class AbstractPin { using Port = GPIO_TypeDef; using PortIndex = uint8_t; public: AbstractPin(PinName); void setAsDigitalInput(); void setAsDigitalOutput(); .... template <PinName pin = NONE> class Pin : public AbstractPin { public: Pin() : AbstractPin(pin) { } }; .... template <PinName pin = NONE> class DigitalOutputPin : public AbstractPin { public: DigitalOutputPin() : AbstractPin(pin) { setAsDigitalOutputPin(); setAsPushPull(); setOutputSpeedNormal(); } }; Spoiler stm32f4::AbstractPin::AbstractPin(PinName pin) { // Undefined pin if (pin == NONE) { port = reinterpret_cast<Port*>(GPIOA_BASE); setMask = 0; resetMask = 0; return; } pinIndex = (pin % 16); setMask = (1 << pinIndex); resetMask = (1 << (pinIndex + 16)); switch (pin / 16) { case (0): port = reinterpret_cast<Port*>(GPIOA_BASE); SET_BIT(RCC->AHB1LPENR, RCC_AHB1LPENR_GPIOALPEN); SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN); break; case (1): port = reinterpret_cast<Port*>(GPIOB_BASE); SET_BIT(RCC->AHB1LPENR, RCC_AHB1LPENR_GPIOBLPEN); SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOBEN); break; .... setAsDigitalInput(); } Хотя можно изголиться и все это сделать на шаблонах, но тогда скорее всего вырастет уже объем прошивки, хотя ОЗУ уже так тратиться не будет. В целом - экономии мизерные. Не вижу смысла особо заморачиваться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба ViKo, не слушайте Forger-а, у него всегда всё через одно место сделано. Вот правильные Pin-ы: тынц. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба Спасибо всем! Меня сейчас устраивает описание, как ниже сделано. template <char port, unsigned bit> struct Pin_st { static constexpr GPIO_TypeDef *Port = port == 'A' ? GPIOA : port == 'B' ? GPIOB : port == 'C' ? GPIOC : port == 'D' ? GPIOD : port == 'E' ? GPIOE : port == 'G' ? GPIOG : GPIOH; static constexpr unsigned Bit = bit; static constexpr uint16_t Mask = 1 << bit; }; // using Adc1s_n = Pin_st <'B', 13>; // using Adc2s_n = Pin_st <'B', 14>; Pin_st <'B', 13> Adc1s_n; Pin_st <'B', 14> Adc2s_n; inline void GpioLowHigh_set(GPIO_TypeDef *port, uint16_t mask_low, uint16_t mask_high) { port->BSRR = mask_low << 16 | mask_high; } template <bool s1, bool s2> static void HsAdc_tm() { GpioLowHigh_set(Adc1s.Port, Adc1s_n.Mask * s1 | Adc2s_n.Mask * s2, Adc1s_n.Mask * !s1 | Adc2s_n.Mask * !s2); } inline void HsAdc1_select(void) { HsAdc_tm<true, false>; } inline void HsAdc2_select(void) { HsAdc_tm<false, true>; } inline void HsAdc_select(void) { HsAdc_tm<true, true>; } inline void HsAdc_deselect(void) { HsAdc_tm<false, false>; } Это все в main.h. На последние 4 выдается: Source\main.h(146): warning: #174-D: expression has no effect HsAdc_tm<true, false>; И не создаются функции в main.c, когда там использую. По паре nop вижу. Я очень плохо понимаю весь этот синтаксис. В чем ошибки? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться