Forger 26 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба ViKo, не слушайте АНТОХА, его аргументация всегда через одно место сделана. Иначе не умеет. Класс AbstractPin создан не просто так. Он необходим для возможности передавать экземпляры пинов в другие модули (по ссылке, разумеется). Например, для автоматически привязки на нужную Alternative функцию. Вот пример: Hardware::SerialPortUSART6 serialPort; Hardware::Pin<PC6> pinTX; Hardware::Pin<PC7> pinRX; .... serialPort.initialize(); ... serialPort.setPinTx(pinTX); serialPort.setPinRx(pinRX); ... serialPort.run(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба Ладно, с "местами" - ничья. Ваши взаимные отношения не остались без внимания общественности. Поговорили. Мне бы по моим мелким вопросикам просветиться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба 11 minutes ago, ViKo said: И не создаются функции в main.c, когда там использую. По паре nop вижу. Я очень плохо понимаю весь этот синтаксис. В чем ошибки? Потому что нельзя просто так умножать на true/false. В данном случае для компилятора просто нет никакой разницы между HsAdc_tm<true, true> и HsAdc_tm<false, false>; Перепишите HsAdc_tm так, чтобы исключить такие вещи. Например, явно внутри проверяя s1 и s2 через свои if. Не страшно что будет чуть-больше текста, зато подобные ошибки будут сразу видны. Компилятор умеет все нормально оптимизировать, не пытайтесь делать это за него ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба На unsigned s1 и s2 (0, 1) тоже не может умножать inline, что ли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба 6 minutes ago, ViKo said: На unsigned s1 и s2 (0, 1) тоже не может умножать inline, что ли? Так у вас template <bool s1, bool s2> зы. Кстати, понять по этому шаблону, что именно делают s1 и s2 без поллитра не получится Если у вас всего четыре ADC и явно прописаны названия функций, то не вижу смысла городить огород из в целом не читаемого шаблона, когда внутри HsAdc1_select и остальных можно сразу явно вызывать GpioLowHigh_set с нужными параметрами. Выходной код будет такой же по объему. Но читать это будет гораздо проще. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба 21 минуту назад, ViKo сказал: Это все в main.h. На последние 4 выдается: Source\main.h(146): warning: #174-D: expression has no effect HsAdc_tm<true, false>; И не создаются функции в main.c, когда там использую. По паре nop вижу. Я очень плохо понимаю весь этот синтаксис. В чем ошибки? Скобочки надо, это же функция, её нужно вызывать: HsAdc_tm<false, false>(); И я не вижу, где вы используете класс Pin_st. Он как-то сам по себе, а остальные функции - сами по себе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба Эх, скобочки, скобочки. В этих "шифровках" сходу и не увидишь ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба Pin_st <'B', 13> Adc1s_n; Pin_st <'B', 14> Adc2s_n; Получилось. Для HsAdc1_select(); HsAdc2_select(); HsAdc_select(); HsAdc_deselect(); С оптимизацией O3 имею: 00001a 480a LDR r0,|L1.68| 00001c 4908 LDR r1,|L1.64| 00001e 6181 STR r1,[r0,#0x18] 000020 ea4f4131 ROR r1,r1,#16 000024 6181 STR r1,[r0,#0x18] 000026 f04f41c0 MOV r1,#0x60000000 00002a 6181 STR r1,[r0,#0x18] 00002c 1409 ASRS r1,r1,#16 00002e 6181 STR r1,[r0,#0x18] 2 минуты назад, Forger сказал: и я почему-то уверен, что без глубокого анализа соотв. h-файла не сможете разобраться. Оно в h-файле и есть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба А для -O0, однако, функцию хочет вызвать. Где, возьмет, не понимаю. Нашлось в конце. ;;;56 HsAdc1_select(); 00001e bf00 NOP 000020 f7fffffe BL _ZN28_INTERNAL_8_Main_cpp_TimCapt8HsAdc_tmILb1ELb0EEEvv ; void [local to Main_cpp]::HsAdc_tm<(bool)1, (bool)0>() 000024 bf00 NOP 13 минут назад, Forger сказал: умение долго удерживать в голове эти магические аббревиатуры Зачем? Главное знать интерфейс функций, которыми пользуешься. В данном случае, 4 простейших функции: HsAdc1_select(); HsAdc2_select(); HsAdc_select(); HsAdc_deselect(); Два АЦП. Выбираются по одному, оба, или не выбираются. Это на их CS идет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба 17 minutes ago, ViKo said: HsAdc1_select(); HsAdc2_select(); HsAdc_select(); HsAdc_deselect(); Два АЦП. Выбираются по одному, оба, или не выбираются. Это на их CS идет. Имхо, ни разу не очевидно Впрочем, это - ваш код, хозяин-барин :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба 23 минуты назад, ViKo сказал: Pin_st <'B', 13> Adc1s_n; Pin_st <'B', 14> Adc2s_n; Получилось. Для HsAdc1_select(); HsAdc2_select(); HsAdc_select(); HsAdc_deselect(); Отлично. Теперь сделайте следующий шаг: вместо шаблонной функции HsAdc_tm(), которая умеет работать только с двумя ножками, добавьте в структуру Pin_st функции on() и off(). После этого ваш код будет выглядеть примерно так: using Adc1Cs = Pin_st <'B', 13>; using Adc2Cs = Pin_st <'B', 14>; Adc1Cs::off(); Adc2Cs::off(); Adc1Cs::on(); Adc2Cs::on(); Потом вам захочется инициализировать ножки. И вы добавите функцию init(mode). Потом вам покажется удобным добавить третий параметр - активный уровень ('L' для низкого, 'H' - для высокого). И у вас получится мой pin.h :))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба Ну, когда-нибудь... Зато я могу сразу две ножки изменить. Для того и страдал. А до этого дефайнами влегкую махал ногами без накладных расходов. Кстати, эти Pin_st в памяти МК создаются или нет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 23 июля, 2019 Опубликовано 23 июля, 2019 · Жалоба Ну так и в моём примере сразу две ножки :) 1 час назад, ViKo сказал: Кстати, эти Pin_st в памяти МК создаются или нет? В моём примере точно не создаются - используются типы и их статические функции. В вашем примере при хорошем уровне оптимизации - тоже не создаются, что вы и видите в листинге. А при -O0 создадутся. Ну или если возьмёте адрес созданного объекта ( call_some_func(&Adc1s_n) ) - тоже создадутся. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 24 июля, 2019 Опубликовано 24 июля, 2019 · Жалоба 17 часов назад, AHTOXA сказал: Ну так и в моём примере сразу две ножки :) Хочу вернуться к этому вопросу. У меня одной командой включаются или выключаются CS для двух устройств, по двум битам порта, в любой из 4-х комбинаций вкл/выкл. Могу ли я, пользуясь using для каждого из битов, создать 4 функции? Ведь структура, описывающая бит порта, ничего не знает о соседнем бите. Это надо уже для двух битов структуру сочинять. Почему так работает: Спойлер 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(GPIOB, 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>(); } А так - нет: using Adc1s_n = Pin_st <'B', 13>; using Adc2s_n = Pin_st <'B', 14>; Source\main.h(140): error: #254: type name is not allowed Adc1s_n.Mask * s1 | Adc2s_n.Mask * s2, Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 24 июля, 2019 Опубликовано 24 июля, 2019 · Жалоба Когда вы обращаетесь к статическому члену класса/структуры, то это надо делать через двоеточие: Adc1s_n::Mask То же и для вызова функций: Adc1s_n::off(); А вот если вы объявите экземпляр этого класса, то через точку: Adc1s_n Adc1s; Adc1s.Mask; Adc1s.off(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться