ViKo 1 31 июля, 2019 Опубликовано 31 июля, 2019 · Жалоба Задумал сделать класс типа Port, состоящий из объектов типа Pin. Чтобы манипулировать не по одной ножке, а целым портом. Правильно ли я думаю, что мне нужны шаблонные классы Pin, вложенные в шаблон Port? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 31 июля, 2019 Опубликовано 31 июля, 2019 · Жалоба 13 minutes ago, ViKo said: Задумал сделать класс типа Port, состоящий из объектов типа Pin. Чтобы манипулировать не по одной ножке, а целым портом. Правильно ли я думаю, что мне нужны шаблонные классы Pin, вложенные в шаблон Port? Думаю, что лучше сделать свой отдельный шаблон под порт. Параметром шаблона будет базовый адрес порта (uint32_t), не указатель. Скорее всего это будет единственный параметр. Да и нужен ли тут шаблон? Однако, до сих пор ни в одном проекте мне так ни разу и не понадобилось обращение к целому порту. Через отдельные пины выходит намного нагляднее и поэтому такой код значительно проще отлаживать и сопровождать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 31 июля, 2019 Опубликовано 31 июля, 2019 (изменено) · Жалоба Я так понимаю, если использовать только ссылку на объект шаблонного класса, сам объект не создается. А целый порт нужен для установки режимов всех битов порта одной командой. Я так давно делаю. А заодно и биты устанавливать - сбрасывать одновременно. Не хочу иметь никаких накладных расходов при работе с GPIO (как не имею и сейчас, пользуясь #define). Изменено 31 июля, 2019 пользователем ViKo Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 31 июля, 2019 Опубликовано 31 июля, 2019 · Жалоба С портом так: Спойлер template<char port_name, Mode_td m00, Type_td t00, Speed_td s00, Pull_td p00, Altf_td a00, Mode_td m01, Type_td t01, Speed_td s01, Pull_td p01, Altf_td a01, Mode_td m02, Type_td t02, Speed_td s02, Pull_td p02, Altf_td a02, Mode_td m03, Type_td t03, Speed_td s03, Pull_td p03, Altf_td a03, Mode_td m04, Type_td t04, Speed_td s04, Pull_td p04, Altf_td a04, Mode_td m05, Type_td t05, Speed_td s05, Pull_td p05, Altf_td a05, Mode_td m06, Type_td t06, Speed_td s06, Pull_td p06, Altf_td a06, Mode_td m07, Type_td t07, Speed_td s07, Pull_td p07, Altf_td a07, Mode_td m08, Type_td t08, Speed_td s08, Pull_td p08, Altf_td a08, Mode_td m09, Type_td t09, Speed_td s09, Pull_td p09, Altf_td a09, Mode_td m10, Type_td t10, Speed_td s10, Pull_td p10, Altf_td a10, Mode_td m11, Type_td t11, Speed_td s11, Pull_td p11, Altf_td a11, Mode_td m12, Type_td t12, Speed_td s12, Pull_td p12, Altf_td a12, Mode_td m13, Type_td t13, Speed_td s13, Pull_td p13, Altf_td a13, Mode_td m14, Type_td t14, Speed_td s14, Pull_td p14, Altf_td a14, Mode_td m15, Type_td t15, Speed_td s15, Pull_td p15, Altf_td a15> class Port_c { static constexpr GPIO_TypeDef *Port = port_name == 'A' ? GPIOA : port_name == 'B' ? GPIOB : port_name == 'C' ? GPIOC : port_name == 'D' ? GPIOD : port_name == 'E' ? GPIOE : port_name == 'G' ? GPIOG : GPIOH; public: static void config() { Port->PUPDR = p15 << 30 | p14 << 28 | p13 << 26 | p12 << 24 | p11 << 22 | p10 << 20 | p09 << 18 | p08 << 16 | p07 << 14 | p06 << 12 | p05 << 10 | p04 << 8 | p03 << 6 | p02 << 4 | p01 << 2 | p00 << 0 ; Port->OTYPER = t15 << 15 | t14 << 14 | t13 << 13 | t12 << 12 | t11 << 11 | t10 << 10 | t09 << 9 | t08 << 8 | t07 << 7 | t06 << 6 | t05 << 5 | t04 << 4 | t03 << 3 | t02 << 2 | t01 << 1 | t00 << 0 ; Port->AFR[0] = a07 << 28 | a06 << 24 | a05 << 20 | a04 << 16 | a03 << 12 | a02 << 8 | a01 << 4 | a00 << 0 ; Port->AFR[1] = a15 << 28 | a14 << 24 | a13 << 20 | a12 << 16 | a11 << 12 | a10 << 8 | a09 << 4 | a08 << 0 ; Port->MODER = m15 << 30 | m14 << 28 | m13 << 26 | m12 << 24 | m11 << 22 | m10 << 20 | m09 << 18 | m08 << 16 | m07 << 14 | m06 << 12 | m05 << 10 | m04 << 8 | m03 << 6 | m02 << 4 | m01 << 2 | m00 << 0 ; } }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 31 июля, 2019 Опубликовано 31 июля, 2019 · Жалоба 8 minutes ago, ViKo said: С портом так: Hide contents Когда вижу три параметра в шаблоне или функции, уже начинаю нервничать. А тут аж 81 параметр! Это серьезная заявка на рекорд Гиннеса ;) Кроме шуток, покажите пример применения в реальном коде. Интересно, как это выглядит "вживую". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 31 июля, 2019 Опубликовано 31 июля, 2019 · Жалоба __nop(); GPIO_ns::PortA::config(); /*-----------------------------------------------------------------------------*/ while (1) { __nop(); __nop(); } Спойлер 000048 bf00 NOP ;71 00004a 490c LDR r1,|L1.124| 00004c 480c LDR r0,|L1.128| 00004e 60c1 STR r1,[r0,#0xc] ;71 000050 2100 MOVS r1,#0 ;71 000052 6041 STR r1,[r0,#4] ;71 000054 490b LDR r1,|L1.132| 000056 6201 STR r1,[r0,#0x20] ;71 000058 490b LDR r1,|L1.136| 00005a 6241 STR r1,[r0,#0x24] ;71 00005c 490b LDR r1,|L1.140| 00005e 6001 STR r1,[r0,#0] ;71 |L1.96| 000060 bf00 NOP ;77 000062 bf00 NOP ;77 000064 e7fc B |L1.96| ;;;80 ENDP 000066 0000 DCW 0x0000 |L1.104| DCD 0xb2d05e00 |L1.108| DCD 0x01c9c380 |L1.112| DCD 0x20004000 |L1.116| DCD 0x40020400 |L1.120| DCD 0x40020418 |L1.124| DCD 0x00285544 |L1.128| DCD 0x40020000 |L1.132| DCD 0x505510a0 |L1.136| DCD 0x000aa17a |L1.140| DCD 0xaaaa8abb То было с оптимизацией default. А это -O0: Спойлер ;;;71 __nop(); 00005e bf00 NOP ;;;72 GPIO_ns::PortA::config(); 000060 bf00 NOP 000062 480c LDR r0,|L1.148| 000064 490c LDR r1,|L1.152| 000066 60c8 STR r0,[r1,#0xc] 000068 2000 MOVS r0,#0 00006a 6048 STR r0,[r1,#4] 00006c 480b LDR r0,|L1.156| 00006e 6208 STR r0,[r1,#0x20] 000070 490b LDR r1,|L1.160| 000072 4809 LDR r0,|L1.152| 000074 6241 STR r1,[r0,#0x24] 000076 480b LDR r0,|L1.164| 000078 4907 LDR r1,|L1.152| 00007a 6008 STR r0,[r1,#0] 00007c bf00 NOP ;;;73 ;;;74 /*-----------------------------------------------------------------------------*/ ;;;75 ;;;76 while (1) { 00007e e001 B |L1.132| |L1.128| ;;;77 __nop(); __nop(); 000080 bf00 NOP 000082 bf00 NOP |L1.132| 000084 e7fc B |L1.128| Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 августа, 2019 Опубликовано 7 августа, 2019 · Жалоба В 23.07.2019 в 18:38, AHTOXA сказал: В моём примере точно не создаются - используются типы и их статические функции. В вашем примере при хорошем уровне оптимизации - тоже не создаются, что вы и видите в листинге. А при -O0 создадутся. Ну или если возьмёте адрес созданного объекта ( call_some_func(&Adc1s_n) ) - тоже создадутся. Вот на засаду напоролся. Создал массив PinA[] из 16 Pin_st структур, описывающих биты порта (режим, тип, скорость и т.д - 5 параметров). Сделал шаблонную функцию, задающую режимы GPIO->MODER, и т.д. template <char port_name> static void Port_init(Pin_st Pin[]) И пытаюсь передать в шаблонную функцию адрес этого массива. static inline void PortA_init(void) { Port_init<'A'>(&PinA[0]); } И получаю свой PinA[] массив в map размером на все 320 байтов (по слову на параметр). Видимо, никак от него не избавиться? В класс этот массив не могу включить, потому что не смогу задавать установку и сброс нескольких битов порта извне. Он же будет скрыт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 августа, 2019 Опубликовано 7 августа, 2019 · Жалоба И все манипуляции с установкой режимов порта, какие показаны выше, идут в программе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 7 августа, 2019 Опубликовано 7 августа, 2019 · Жалоба 4 часа назад, ViKo сказал: И пытаюсь передать в шаблонную функцию адрес этого массива. Если берёте адрес, то компилятор обязан создать объект. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 августа, 2019 Опубликовано 7 августа, 2019 (изменено) · Жалоба 53 минуты назад, AHTOXA сказал: Если берёте адрес, то компилятор обязан создать объект. Я это уже процитировал. И иначе в функцию не передать массив. Почему нельзя ссылку передавать? Хотя, видимо, и тогда должен создаваться массив. То есть, этот массив должен быть членом класса. В общем, всё пропало. О, я же могу не массивом задавать выводы, а поотдельности! Изменено 7 августа, 2019 пользователем ViKo Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 декабря, 2021 Опубликовано 7 декабря, 2021 · Жалоба Решил я в реальном проекте продолжить когда-то начатое. И столкнулся со следующей проблемой. Возможно, решение простое, но я его не нахожу. В одном заголовочном файле x.hpp описал выводы МК в виде структур. Все типы описаны как перечисления. Там же описан и шаблон класса порта со всеми статическими функциями - config, lock, read, write... /*! GPIO Pin structure */ struct Pin { GpioName name; // port name GpioBitn bitn; // bit number GpioMode mode; // mode GpioType type; // output type GpioSpeed speed; // output speed GpioPull pull; // pull-up/pull-down GpioInit init; // initial output data GpioLock lock; // configuration lock GpioAltf altf; // alternate function }; ... template <const Pin & ... PN> class Gpio { ... } В исходном файле x.cpp определяю выводы. И далее описываю порт целиком. static constexpr Pin SNSFLT { GpioName::na, GpioBitn::bn00, GpioMode::in, GpioType::pp, GpioSpeed::lo, GpioPull::np, GpioInit::hi, GpioLock::lk, GpioAltf::af00 }; ... using GpioA = Gpio <SNSFLT, SNSFIR, TXL1, RXL, TXL2, LPL, ALERT_N, TAMP, INSL, DBGTX, DBGRX, LEDR, LEDG, SWDIO, SWCLK, SNSEN_N>; Но когда из main функции в файле y.cpp пытаюсь вызвать функцию для конфигурации, получаю ошибку, что SNSFLT не описан. GpioA::config(); error: use of undeclared identifier 'SNSFLT' Попробовал заменить на extern constexpr Pin SNSFLT { GpioName::na, GpioBitn::bn00, GpioMode::in, GpioType::pp, GpioSpeed::lo, GpioPull::np, GpioInit::hi, GpioLock::lk, GpioAltf::af00 }; Ничего не меняется. В чем дело? Когда же выводы определяются в том же файле y.cpp, компилируется без ошибок. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 декабря, 2021 Опубликовано 7 декабря, 2021 · Жалоба static constexpr Pin SNSFLT { GpioName::na, GpioBitn::bn00, GpioMode::in, GpioType::pp, GpioSpeed::lo, GpioPull::np, GpioInit::hi, GpioLock::lk, GpioAltf::af00 }; ... using GpioA = Gpio <SNSFLT, SNSFIR, TXL1, RXL, TXL2, LPL, ALERT_N, TAMP, INSL, DBGTX, DBGRX, LEDR, LEDG, SWDIO, SWCLK, SNSEN_N>; Перенёс в x.hpp, всё компилируется. Не нравится, что определение класса и его использование сделано в одном файле. Но можно и на два разделить. Хотя, оставлю так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 7 декабря, 2021 Опубликовано 7 декабря, 2021 · Жалоба Переносить using в hpp почти всегда плохая идея. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 декабря, 2021 Опубликовано 7 декабря, 2021 · Жалоба Критикуешь - предлагай! (с) 56 минут назад, Arlleex сказал: Переносить using в hpp почти всегда плохая идея. Вообще не вижу проблем. Это же аналог typedef. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 7 декабря, 2021 Опубликовано 7 декабря, 2021 · Жалоба 24 минуты назад, ViKo сказал: Вообще не вижу проблем. Ну и зря. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться