Forger 22 17 декабря, 2021 Опубликовано 17 декабря, 2021 · Жалоба 22 minutes ago, Arlleex said: Хорошо, когда вектор прерывания периферии выделен только для нее. Но бывают вектора, которые делят между собой несколько периферийных блоков. Например, TIM6_DAC_IRQHandler. Как здесь поможет делегат? Бывают мульти-делегаты, тогда на один "вектор" можно повесить сколько угодно делегатов. Такое у меня предусмотрено, но пока что никогда не пользовался. Не было нужды. 22 minutes ago, Arlleex said: А еще, бывает, одна и та же периферия оккупирует несколько векторов, например, TIM8_CC_IRQHandler, TIM8_TRG_COM_TIM14_IRQHandler, TIM8_UP_TIM13_IRQHandler, TIM8_BRK_TIM12_IRQHandler... Тут еще проще - просто расширяется список методов для подключения всех этих векторов. Достаточно лишь дать осмысленные имена этим методам. 22 minutes ago, Arlleex said: А еще, бывает, например, один таймер может использоваться для обслуживания драйверов нескольких вообще не связанных друг с другом механизмов. Это осуществляется на уровне проектирования структуры проекта. Никто не запрещает выделить такой таймер в отдельную структуру и уже подключать к ней нужное число любых делегатов на что угодно. Т.е. таймер является собственностью некого логического блока проекта и уже к этому блоку стучаться другие. Но я стараюсь всегда каждый аппаратный блок сделать собственностью (private) другого блока/модуля. Как правило у меня в проектах запас по аппаратным ресурсах крайне избыточный, т.к. стоимость камня в общей стоимости проектов - капля в море. Даже с учетом последних цен ) 22 minutes ago, Arlleex said: Грубо говоря, есть вектор TIM2_IRQHandler. И есть N объектов класса nsFIFO::cUARTDMARx, которым нужен аппаратный таймер для отсчитывания 1мс интервалов ("стандартный" механизм DMA + TIM в STM32 для приема неизвестного количества байтов в непрерывном режиме по UART-у). Для 1мс интервалов есть OS, для микросекундных - таймеры. Как-то делал некий диспетчер для управления аппаратными таймерами для формирования точных временных отрезков. Так вот этот блок содержал внутри себя все таймеры, доступные для этой цели. И этот блок/модуль распределял какой таймер кому достанется. А уже снаружи другие модули стучались и просили на время по-пользоваться таким таймером. Т.к. время владения таймера крохотное, то всем просящим хватало доступных 4х таймеров (какой-то древний проц. типа ELAN). Суть такая - напрямую таймеры были недоступны, а только через диспетчер таймеров. Он решал кому можно, а кому надо подождать. 22 minutes ago, Arlleex said: Разве делегатом можно "привязаться" к одному аппаратному вектору в нескольких инстанциях? Мультиделегат. Но я избегаю таких толстых решений. В МК это избыточно, хотя в жирных и мощных вполне реализуемо. На самом деле если столкнусь, наверняка найду еще более красивое и простое решение ) Остальная часть кода этого даже и не заметит. 22 minutes ago, Arlleex said: Т.е. какое здесь решение наиболее изящно? У меня, пока что, кроме как создать публичные методы svcOnDMAIrq() и svcOnTmrIrq(), дергать их из обработчика соответствующего вектора прерывания DMA и таймера, идей нет. Но здесь нужно всегда руками "добавлять" обработку конкретного экземпляра класса в соответствующих векторах. Может, я чего-то не знаю? Не совсем понял, скорее вообще не понял (( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 165 17 декабря, 2021 Опубликовано 17 декабря, 2021 · Жалоба 2 минуты назад, Forger сказал: Не совсем понял, скорее вообще не понял (( class A { ... public: void svcOnDMAIrq(); void svcOnTmrIrq(); }; ... A obj1; ... // явно вызываем "обработчики" в объекте extern "C" void DMA1_Stream0_IRQHandler() { obj1.svcOnDMAIrq(); } extern "C" void TIM2_IRQHandler() { obj1.svcOnTmrIrq(); } Если создать еще obj2, obj3... то для них нужно будет в TIM2_IRQHandler() "добавлять" вызовы svcOnTmrIrq(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 22 17 декабря, 2021 Опубликовано 17 декабря, 2021 · Жалоба 7 minutes ago, Arlleex said: Если создать еще obj2, obj3... то для них нужно будет в TIM2_IRQHandler() "добавлять" вызовы svcOnTmrIrq(). Мульти-делегаты или отдельный диспетчер для управления сторонними подключениями к одному обработчику. Стучаться к диспетчеру, он подключит новый делегат в список. Список тогда может быть жесткий, на конкретное число подключения или на край "резиновый" список (мульти-делегат). В данном случае скорее первое - жесткой список. Не обязательно полностью забивать весь список - пустые делегаты почти не жрут ресурса при вызове. Признаюсь, пока не сталкивался с этой нуждой. Но стало вдруг интересно попробовать (пока с академической точки зрения) )) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 165 17 декабря, 2021 Опубликовано 17 декабря, 2021 · Жалоба Кошмар, я ничего не понял Ладно, пока что реализую как понимаю, а дальше будь что будет). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 22 17 декабря, 2021 Опубликовано 17 декабря, 2021 · Жалоба 2 minutes ago, Arlleex said: Кошмар, я ничего не понял Ладно, пока что реализую как понимаю, а дальше будь что будет). Мульти-делегат - это по сути односвязный список других делегатов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 165 17 декабря, 2021 Опубликовано 17 декабря, 2021 · Жалоба В общем, это очень жирно по ресурсам вызова, я думаю. Сотня тактов на вход в прерывание и на выход из него наберется... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 22 17 декабря, 2021 Опубликовано 17 декабря, 2021 · Жалоба 12 minutes ago, Arlleex said: В общем, это очень жирно по ресурсам вызова, я думаю. Сотня тактов на вход в прерывание и на выход из него наберется... Ничего подобного )) Вот вызов делегата с момента входа в обработчик, BX - это уже вызов конкретно user-обработчика, который повешен на делегат (метод-класса): В r0 записывается соотв. this владельца этого user-метода. В r1 - адрес этого user-метода. Это по сути вызов c++ метода класса. Оптимизация конечно включена. Компилятор конечно v6. Справляется на ура ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 224 17 декабря, 2021 Опубликовано 17 декабря, 2021 · Жалоба 35 минут назад, Forger сказал: И это называется "ничего жирного"??? Почти десяток тактов там, где по уму вообще ни одного такта не требуется! А может и больше десятка тактов, может даже все 20 тактов (как с кешем и латентностью флеши повезёт повезёт). Да ещё ОЗУ требуется (указатели читаются из ОЗУ). Это просто пустое транжиренье ресурсов. Ради шашечек.... PS: Да и кроме этих 3-х команд мы видим сверху и снизу ещё некие команды. Про которые вы умолчали. Подозреваю что в реале там ещё больше ресурсов нужно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 22 17 декабря, 2021 Опубликовано 17 декабря, 2021 · Жалоба 1 hour ago, jcxz said: Это просто пустое транжиренье ресурсов. Ради шашечек.... Для вас "шашечки", а для меня - необходимость. Не все способны держать в голове чудовищную кашу и запутанной структуры проекта и горы мудреных макросов ради макросов. Я так не умею. Не расстроен ни разу. И мне глубоко плевать на немного бОльший расход озу - камни у меня в проектах всегда имеют многократный запас по ресурсам. Впроголодь не живем, как некоторые :) Читаемость кода на первом месте для меня. К тому же вызов через делегат позволяет избежать вложенного вызова цепочки методов, как этого приходилось делать раньше. Более структурирование построение кода позволяет упростить код там, где это было невозможно сделать нормально. Количество багов и детских граблей заметно сократилось. Код по сути становится быстрее, что некоторым покажется парадоксально. Опять-таки, нравится вам сидеть на голых сях и макросах - дело ваше. Но для меня это - пройденный этап, обратно не вернусь, хватит, намучался. 1 hour ago, jcxz said: Да и кроме этих 3-х команд мы видим сверху и снизу ещё некие команды. При особо богатой фантазии можно и не такое увидеть :) Желтым цветом выделена команда, адрес которой вписан в таблицу векторов в соотв. месте. Т.е. это - первая команда, которая вызывается при входе в конкретно взятый обработчик. Последняя 4я - это безусловный переход на сам метод, адрес которого забит в этот делегат. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 165 17 декабря, 2021 Опубликовано 17 декабря, 2021 · Жалоба Читаю про ссылки. В целом, все понятно, как использовать тоже понятно. Не понятно одно: зачем они нужны, когда есть указатели? Ну т.е. их же ведь не спроста придумали и ввели в синтаксис языка. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 17 декабря, 2021 Опубликовано 17 декабря, 2021 · Жалоба 1 час назад, Arlleex сказал: зачем они нужны, когда есть указатели? Они нужны для реализации механизма перегрузки операторов. Для него важно, чтобы семантика использования ссылок на объекты была идентична семантике работы с самими объектами. Вот ещё интересная статья про указатели и ссылки: чем они похожи, а чем различаются. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 18 декабря, 2021 Опубликовано 18 декабря, 2021 · Жалоба 20 часов назад, Arlleex сказал: Не понятно одно: зачем они нужны, когда есть указатели? Ну т.е. их же ведь не спроста придумали и ввели в синтаксис языка. Их ввели, когда захотели сделать перегрузку операторов. Upd. Пардон, не рассмотрел предыдущий пост. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexRayne 7 18 декабря, 2021 Опубликовано 18 декабря, 2021 · Жалоба 12.05.2021 в 13:40, Arlleex сказал: Т.е. именование становится контекстно-зависимым, а не как в Си - прямым по имени и только лишь. Линус Товальдс в свое время это свойство поставил в беду с++ - для патч-менеджмента такой код катастрофа. контекст-зависимость легко оборачивается возможностью попутать код, нетривиальными ошибками. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 165 18 декабря, 2021 Опубликовано 18 декабря, 2021 · Жалоба Попутать код можно только написав его задней пяткой. ИМХО. А если оно уже написано и отлажено сто раз, то и лазить в реализацию не имеет смысла. Линус Торвальдс для меня не авторитет, я вообще в авторитеты себе никого не ставлю, особенно в программировании. Слишком много в нем религиозных предубеждений, которые мешают адекватной индивидуальной оценке всяких "за" и "против" каких-то подходов, которые, вообще-то, нужно "прочувствовать" на собственной шкуре. Но и изолироваться от внешнего мира нельзя, т.к. это путь в никуда, поэтому я и задаю здесь свои тупые вопросы, получаю ответы и пропускаю их через свои субъективные фильтры "это правильно, а это не правильно нифига, т.к. не ложится на мое видение удобства пользования инструмента (языка C++)". Я считаю, что катастрофа - это когда физический объем кода настолько большой, что время на его освоение другим разработчиком просто не вписывается ни в какие рамки. А на плюсах писать основную логику программы куда лаконичнее и понятнее, ИМХО (в этом удалось убедиться на нескольких чужих проектах), чем на Си. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 224 18 декабря, 2021 Опубликовано 18 декабря, 2021 · Жалоба 58 минут назад, Arlleex сказал: Я считаю, что катастрофа - это когда физический объем кода настолько большой, что время на его освоение другим разработчиком просто не вписывается ни в какие рамки. Если речь про работу в команде, то работа там должна быть организована так, чтобы не было необходимости освоения другим разработчиком кода соседа. Это достигается построением API взаимодействия разных модулей программы (ведомых разными разработчиками). А если речь про какой-то чужой код, который вы берёте и встраиваете в свой проект (или изучаете), то тут, имхо, играет роль не си/си++, а стиль написания того чужого кода. Чем он ближе к вашему - тем понятнее. Плюсовость тут по-моему не играет ни какой роли. Может даже наоборот - осложнять освоение (вам например удобнее для какой-то операции перегрузить оператор '+=' для своего класса, а другой человек будет всё время на этом спотыкаться; ему удобнее и понятнее - через член-функции). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться