Потому как не различает символьное имя Hsync, Vsync, или spi_cl. Зато знает что такое A0, A2, A2, и умеет с ними обращаться.
Ещё как различает. Это же ТИП, который содержит информацию какой пин на каком порту, какой режим работы и даже начальное состояние при включении питания.
Если бы функция не различала Hsync и Vsync, то как бы она могла требовать передачи только подходящих пинов?
Вооот!!! Функция реально не может различать Hsync и Vsync, она работает с интерфейсом - а там список допустимых параметров в виде реальных контактов портов мк: A0, A1, A2, и так далее. А0 совпадает? ну так в чём проблема - используем. Тот-же Hsync можно назвать десятком дополнительных имён - без какого-либо конфликта. Грубо говоря - это будет много имён одного длинного макроопределения. Я спотыкался об такую бяку когда слишком много умничал, а сейчас как рукой сняло.
Вооот!!! Функция реально не может различать Hsync и Vsync, она работает с интерфейсом - а там список допустимых параметров в виде реальных контактов портов мк: A0, A1, A2, и так далее. А0 совпадает? ну так в чём проблема - используем. Тот-же Hsync можно назвать десятком дополнительных имён - без какого-либо конфликта. Грубо говоря - это будет много имён одного длинного макроопределения.
Я уже запутался Ранее тут была твоя инициализация FMC, 43 вызова gpio_one_pin(), что помешает использовать повторно любой из этих 43 пинов в другом месте для другой периферии?
Тот-же Hsync можно назвать десятком дополнительных имён - без какого-либо конфликта. Грубо говоря - это будет много имён одного длинного макроопределения.
Это у тебя. А у меня, например, можно сделать так
Код:
using Hsync1 = PA1; using Hsync2 = PA1; using Hsync3 = PA3;
Но нельзя сделать так
Код:
PinList<Hsync1,Hsync2,Hsync3>::mode();
Будет ошибка компиляции с сообщем "Двойное использование пина". А именно так у меня конфигурируются ноги. Не по одной, а все разом!
что помешает использовать повторно любой из этих 43 пинов
Да абсолютно ничего не помешает, ни у меня, ни у VladislavS. Для защиты от повторного использования есть методы, но они таки требуют предварительной подготовки кода. Просто так оно не будет работать. Самый простой способ - залочить сам пин. Эта возможность предусмотрена самой ST, но все либы что я видел - просто не использовали это. В случае лока пина, отваливается или сбоит свеже_написанный код, тут хотя-бы понятно где копать. А вот когда оно всё в одной куче, да ещё и максимальными полномочиями - концов проблемы можно и не найти.
И ещё одна вещь, которая упорно игнорируется: После отладки кода наступает процесс глобальной оптимизации. Удаляется лишнее, скрывается неиспользуемое, лишние проверки да и сама отладка - что нужна была только в процессе развития. Словом - проект заметно худеет. Дык вот, на этом этапе всё актуальное содержимое регистров периферии - копируется в массивы. Да, там получаются магические числа, но это уже никого не волнует. Да и сам процесс инициализации превращается простейший цикл записи содержимого массива в регистры. На этом этапе отключить отдельную функцию установки одного контакта - гораздо проще чем функцию установки множества пинов разных портов по имени периферии. Потому как эта хрень тянет за собой слишком много, и код ниже будет материться.
VladislavS - имелось в виду двойное использование в двух отдельных вызовах. Контроль самих параметров функции даже на Си нормально работает.
После отладки кода наступает процесс глобальной оптимизации. Удаляется лишнее, скрывается неиспользуемое, лишние проверки да и сама отладка - что нужна была только в процессе развития. Словом - проект заметно худеет.
Аааааа!!! Нет!!! Только не это!!! Во-первых, это лишняя работа. Во-вторых, источник ошибок.
У меня хоть каждую ногу отдельно, хоть группами можно описать. Но! Всё это собирается в одном месте и одним махом инициализируется. Компилятор сам делает то что вы называете "процесс глобальной оптимизации". И делает это с самого начала разработки, с одной единственной ноги и до всего чипа.
Да абсолютно ничего не помешает, ни у меня, ни у VladislavS. Для защиты от повторного использования есть методы, но они таки требуют предварительной подготовки кода. Просто так оно не будет работать.
Ясно, но отличия все равно существенные... Сейчас я могу сделать так:
Для обоих интерфейсов можно передать только подходящие пины, но PA11 есть в обоих и работать ничего не будет, однако какова вероятность допустить такую ошибку? У мк 82 доступных пина, из них в качестве NSS2 можно использовать 4, один из них точно правильный, соответственно вероятность нарваться на нерабочий пин в случае ошибки равна 3/82. В типичном сишном коде проверок пинов нет вообще, там вероятность будет 81/82 и ничего, программят как-то
При желании можно объединить все пины в рамках одного списка создав временный объект, если есть дубликаты, код не скомпилируется:
Ну вот берёт и сразу делает. Смотри. Для начала срисовываем со схемы назначение пинов. Можно этого и не делать, но так нагляднее.Спойлер
Код:
// SWD using SWCLK = PA14; using SWDIO = PA13;
// Ethernet using RMII_MDIO = PA2; using RMII_MDC = PC1; using TX_EN = PB11; using TXD0 = PB12; using TXD1 = PB13; using REF_CLK = PA1; using CRS_DV = PA7; using RXD0 = PC4; using RXD1 = PC5;
// USB using USBDM = PA11; using USBDP = PA12; using VBUS = PA9;
// Концевики оптопереключателей using S1_2 = PD5; using S1_3 = PD4; using S2_2 = PB8; using S2_3 = PB7; using S3_2 = PB4; using S3_3 = PD6; using S4_2 = PD1; using S4_3 = PD0; using S5_2 = PE6; using S5_3 = PE0; using S6_2 = PE2; using S6_3 = PE1; // Ключи управления оптопереключателями using C1_1 = PD2; using C1_2 = PD3; using C2_1 = PB6; using C2_2 = PB9; using C3_1 = PB3; using C3_2 = PB5; using C4_1 = PC11; using C4_2 = PC12; using C5_1 = PE5; using C5_2 = PD7; using C6_1 = PE3; using C6_2 = PE4;
using LED_HDD = PA15; using U3_RW = PD12; using RF_ON = PC7; using RWR_ON = PD15; using USART3_TX = PB10; using USART3_RX = PD9;
Затем, если хочется, группируем их по функциональным модулям. Так потом их скопом даже в другой проект тягать удобнее.Спойлер
Код:
using CSWD_PINS = ConfigList<PinMode::AF_PushPull_LowSpeed_PullDown<0x0>, SWCLK, PinMode::AF_PushPull_VeryHighSpeed_PullUp<0x0>, SWDIO>;
На этом этапе создаются только ТИПЫ, ни одной строчки кода ещё нет. И теперь в одном месте хлоп, и всё махом инициализировали. Проверив на корректность и повторы.Спойлер
И по мере разработки я просто в этот список пины добавляю и всё. Не надо потом ничего "глобально оптимизировать". Оно всю жизнь проекта остаётся оптимизированным.
Reflector - вероятность ошибки можно значительно снизить, если использовать пул накопления входных параметров. Либо структура, либо динамическая смена имён, или иные варианты. Можно просто лочить контакты в два этапа - накопление и закрепление. Если в момент накопления будет исключение - то выдавать ошибку.
VladislavS писал(а):
Смотри. Для начала срисовываем со схемы назначение пинов.
Секундочку, это что - руками делается????? То-есть вот так ручками вводить всё что требуется??? Аминь. Кубик выдаёт рапорт в пдф и тхт, там безумно простой формат данных, буквально на два часа перекуров. Я могу согласиться, когда мк всего на 20 ног - там трудно ошибиться, и огромная лень так загоняться. Но если это бга корпус на 400 ног - это-ж рехнуться можно. А там ещё и схему рисовать, в лайте наверное, на 400 ног... Увольте.
Схема устройства и даташиты на комплектующие - это первично. Кубик в эту пищевую цепочку не встроен, особенно если чип не от st. Прямо сейчас у меня fpga на 484 ноги в работе. И ничего, схема, файл с назначением и параметрами пинов - всё в наличии. Внутри, как нетрудно догадаться, далеко не stm32, а подход тот же. Никто не уволен, всё работает.
Написать USBDM = PA11; глядя на схему раз в десять быстрее, чем ввести вашу структуру десятерной вложенности.
Reflector - вероятность ошибки можно значительно снизить, если использовать пул накопления входных параметров. Либо структура, либо динамическая смена имён, или иные варианты. Можно просто лочить контакты в два этапа - накопление и закрепление.
Написал сегодня функцию которая в небольшом массиве накапливает маски пинов, а массив ей передается тот же самый, что и функции инициализации, причем формат я переработал и он стал компактнее, если раньше 14 пинов LTDC паковались в 39 байт, то теперь их 29. Возможно так пока и оставлю, но ходят слухи что в стандарт C++ проталкивают даже работу с файлами на этапе компиляции, т.е. вместо массива с масками пинов в RAM каждый вызов функции сможет при компиляции читать данные из "файла" и сохранять изменения обратно
1 байт кол-во пинов N, N x ( 4 бита порт, 4 бита пин, 8 бит режим)?
AF пропустил, 2 байта на пин уже не получится. На самом деле передается маска пинов, режим, порт/AF, итого 4 байта, в конце FF. На примере FMC это выглядит так:
Код:
constexpr auto pins = AltFuncMap<>::fmc<BusWidth, Bank, NE, A, RD>(); pins.template init<PinMode::AF_PushPull>();
9 байт - это автоматически сгенерированный массив для инициализации и проверки 20-ти пинов FMC, в R0 для обоих вызовов грузится одинаковый адрес, проверка дубликатов естественно в релизной сборке отсутствует.
Цитата:
Сколько занимает функция раскручивающая его?
Отключаем оптимизацию, вызов для нашего FMC по прежнему суммарно занимает 10 байт(без проверки дубликатов), 9-ти байтовый массив округлится до 10-ти байт, а сама функция заняла 224 байта. AVI-crak писал, что у него функция 212 байт, каждый вызов - 8 байт, для 20-ти пинов получается 160 байт и это все с включенной оптимизацией.
Написал сегодня функцию которая в небольшом массиве накапливает маски пинов,
Там есть регистр лока пинов, он еже есть физически, и его нужно использовать. Логичнее создать массив структур всех используемых ног, вносить в него изменения и проверки "за кадром", а в результате иметь прямую запись в регистры из того самого массива, как собственно предлагал VladislavS. Ну это в случае продолжения полировки яиц.
Лично мне и так нормально. Сначала в кубике поверяю возможность задействовать необходимую мне периферию, есно с выбором корпуса (хотя вариантов с нашими магазинами - не шибко много). Потом по списку рапотра самого кубика создаю назначения ног мк для схемы, её тоже почти из готовых кубиков собираю. И тестовая быстрая трассировка: получилось - можно программировать, не получилось - опять ныряем в кубик. Описать состояние ног можно и руками, однако если оно уже есть из кубика- то проще скриптом получить готовый код. Рапорт кубика выглядит примерно так:
Даже если не хочется заморачиваться со скриптами - то копировать эту часть рапорта в код, и постепенно, сверху вниз - заменять строки на свой код вызова функции. Оно-ж удобнее отдельного листочка бумаги.
Понятно. Не, я не люблю тащить пины в классы, которые их аппаратно используют, только за ради инициализации.
Они там не только ради инициализации, у того же FMC на основании пина Ax, который может использовать как RS пин дисплея, рассчитывается маска которая потом накладывается на адрес. Также от банка FMC зависит какие будут допустимые пины NE т.e. эту информацию если что пришлось бы дублировать. У SPI дисплея может быть софтовый NSS и снова будут RS/RST. Если дисплей подключен через ногодрыг, то нужны все пины как в месте их инициализации, так и в самом классе дисплея. Любой светодиод - это инициализация и дергание пина. Любая кнопка - это инициализация и чтение пина... Кроме того классы знают какие пинам нужно задавать режимы и как подмешивать AF, остается лишь вызвать init(). С точки зрения использования подобных библиотек - это упрощение, а размер всегда будет меньше при инициализации всех пинов в одном месте без RMW.
Там есть регистр лока пинов, он еже есть физически, и его нужно использовать.
Регистр LCKR для проверки дубликатов не подходит, часть ног могут переконфигурироваться не лету, в таком случае их лочить нельзя.
Цитата:
Логичнее создать массив структур всех используемых ног, вносить в него изменения и проверки "за кадром", а в результате иметь прямую запись в регистры из того самого массива, как собственно предлагал VladislavS.
Не уверен, что понял... Я ориентируюсь на демонстрируемые примеры, а в них было 40+ gpio_one_pin() для FMC, что уже для меня явный перебор. Это уже все, или какие-то таблицы вытянутые из кубика добавляются дополнительно?
? Это там https://github.com/AVI-crak/gpio_one Материалы для создания таблиц не включены в проект, не хватало чтобы меня ещё и за них пинали. Рапорт кубика - это просто для удобства. Регистор LCKR использует всего 16 бит по назначению, будет физически присутствовать в массиве структур для дальнейшей перезаписи - в 32b виде. Можно и поэксперементировать со второй половиной.
AVI-crak писал(а):
Я ориентируюсь на демонстрируемые примеры, а в них было 40+ gpio_one_pin() для FMC, что уже для меня явный перебор.
Ну дык от этого количество ног для этого интерфейса - меньше не станет. FMC конечно уникальный по гибкости интерфейс, там всего несколько ножек можно куда-то сместить. Но это не повод заморачиваться написанием функции именно для инсталла ног этого интерфейса.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 22
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения