Pull to refresh

Comments 63

Ехали антипаттерны через антипаттерны:
memset(app_pointer->key, 0, 8);
app_pointer->key[2] = KEY_W;
app_pointer->key[3] = KEY_O;
app_pointer->key[4] = KEY_N;
app_pointer->key[5] = KEY_D;
app_pointer->key[6] = KEY_E;
app_pointer->key[7] = KEY_R;
app_pointer->usb_composite->usb_send_packet(app_pointer->key, 8);

app_pointer->key[2] = 0;
app_pointer->key[3] = 0;
app_pointer->key[4] = 0;
app_pointer->key[5] = 0;
app_pointer->key[6] = 0;
app_pointer->key[7] = 0;

1. Магическая константа 8. Стоит поменять размер массива — имеем жуткий головняк с отловом константы.
2. Как следствие первого — первый и второй аргументы memset между собой не связаны. Компилятор никак не сможет предупредить нас, если что-то пошло не так. Напоминаю, что у вас C++, а значит есть шаблоны. Можно сделать все проверки очень красиво и в compile time.
3. Обнуление — классный кусок «китайского кода». Вам работу построчно оплачивают? Это раздутый кирпич кода, весь семантический смысл которого — memset. Если вы думаете, что цикл будет работать дольше — заставьте компилятор его раскрутить.
На этом месте в дальнейшем будет меню, здесь нужно было просто вывести что-нибудь, что бы понять, работает USB HID или нет.
Для начала, предлагаю вам воспользоваться простейшим шаблонным трюком-оберткой для memset:

template<typename T> void ZeroIt(T& value)
{
	memset(&value,0,sizeof(value));
}

Тест на IDEONE
Мой pull-request
Спасибо, я услышала вас. Давно собиралась почитать книжку Real-Time C++ Efficient Object-Oriented and Template Microcontroller Programming, — Kormanyos C.M, а вы напомнили мне о ней)
Мммм… пример я посмотрел, но не совсем понимаю в ZeroIt передается массив целиком или же указатель на него? Если последнее — то при размере массива более 4 (на 32 битной архитектуре) вы получите ой… А если массив целиком — вы можете получить срыв стека… может все же определить размер массива константой и передавать её?
Массив передается по ссылке. Раз по ссылке, то sizeof(value) = sizeof(массива). В моем примере, это будет 12 байт.
В большинстве случаев, компилятор и вовсе выбросит отдельный вызов функции и впишет на это место memset с правильными параметрами.
Про константу 8 — вы правы. Про обнуление — не совсем. Для ВАС — memset читабельней, для Анны — читабельней присвоение нулями. Embeded проекты — трудно отлаживать, их проще сразу писать в максимально простом и надежном варианте.

И ещё. Вы не сумели разобраться, что делает этот код. А это — ОДНОРАЗОВЫЙ тест, он посылает сообщение «WONDER WOMEN». Живет такой тест — полчаса. И чем тупее в нем код — тем лучше. Тест должен тестировать остальные части программы, а не быть источником ошибок.
Данный тест наверняка сделан при помощи copy-paste, а не набран полностью вручную. Статистика говорит о том, что copy-paste — это очень продуктивный источник ошибок. Даже Кармак в Quake III учудил.

Этот код не помещается на один экран стандартного монитора. Следовательно, нарушает эргономику — для его обозрения нужно дергать свою кратковременную память и скроллить туда-сюда.

Этот код у неподготовленного читателя вызывает необходимость сверки индексов — а вдруг, там не все и не подряд? И там ведь действительно — не все, а с двойки.

И про «тестовость» и «временность». Такие чудесные времянки потом, в условиях цейтнота, перерастают в Главное Техническое Решение Продукта и живут потом годами.
Нет, это именно ТЕСТ. Проверка, что мы можем что-то передать, притворившись клавиатурой. И он реально одноразовый.Он не предназначен для ВАШЕГО монитора. А, например, на мой — он влезает целиком.

Да, согласен, иногда времянки живут долго. Но это именно ИНОГДА. А в данном случае — ЗАВЕДОМО одноразовый тест.

У вас мышление преподавателя. а не ИНЖЕНЕРА. У инженера к разным частям кода — разные требования. К одним — скорость, к другим — читаемость, к третьим — быстрота написания, к четвертым — отсутствие ошибок. А преподаватель считает, что есть две точки зрения — одна ЕГО, а другая неправильная.

Я уже видел, как отличный ученик таких вот преподавателей стал УЖАСНЫМ инженером. его код был красив, параметризован, обвешан кучей темплейтов и классов. Он даже работал — но только с данными от сферической лошади в вакууме. Чуть что реальное — и все, случайно залетевший дятел рушил всю цивилизацию.

В инженерных понятиях — код должен эффективно выполнять СВОЮ задачу. Причем для каждой задачи — понятие эффективности разное. Но практически никогда таким критерием не является КРАСОТА кода. Да, да для некоторого кода ПОЛЕЗНА сопровождаемость. Но не тогда, когда она идет в ущерб главной задаче.

А когда второстепенные критерии становятся на первое место — это не инженер. Это вечный студентик, работающий ради отметки.

Что поражает в «экосистеме» разработки под микроконтроллеры — жуткий зоопарк не совместимых друг с другом и с немного отличающися железом, нет, не библиотек, а огрызков исходного кода. Каких-либо вменяемых абстракций просто нет, народ из своей бизнес-логики пишет напрямую в регистры и занимается прочим непотребством. В ChibiOS хотя бы более-менее работающий HAL сделали и понятия блочных устройств и потоков ввели, но это не сильно спасает, когда в руки попадает какой-нибудь экранчик, пример к которому написан ещё до появления STMCube и использует старый и вручную поправленый cmsis, а иной документации просто нет.
Отмечу, что «пишет напрямую в регистры» в большинстве попросту необходимо. Довольно часто невозможно спроектировать программную абстракцию. Или такая абстракция будет неоправданно «тяжелой».
Можно обернуть всю параметризацию, которая известна compile time (а такой 99%) в шаблоны, тем самым без потери производительности мы получим гибкую абстракцию
Если код пишется для любительских поделок, то такой вариант подойдет. Как говориться на вкус и цвет. Но, в более ответственных применениях, такой «сахар» приведет к увеличению сложности верификации проекта и стоимости его поддержки.
Если следовать вашей логике, то вся параметризация и гибкость есть синтаксический сахар, который увеличивает сложность при верификации. Но как показывает профессиональный опыт моей разработки встраиваемых систем, поддерживать шаблонный код в разы лучше чем прибитый гвоздями.
Мне кажется — сильно зависит от назначения, если нужен жесткий реалтайм — привет asm регистры и пр… Если не очень жесткий — разного рода rtos, если время реакции некритично (в пределах 1/10 — 1/20 сек) и вычислительных и иных мощностей чипа хватает — можно городить все что угодно и во главу поставить, например, как вы верно указали удобство поддержки и независимость от платформы…
Всегда на утверждения о корреляции асма и производительности скидываю эту статью.
http://easyelectronics.ru/rabota-s-portami-vvoda-vyvoda-mikrokontrollerov-na-si.html

Если вы используете раннее связывание, то оверхеда перед прибиванием гвоздями нет совершенно никакого. При этом код типа
typedef Led<PortA,4> led1;
typedef Led<PortA,5> led2;
led1::init();
led2::init();
led1::toggle();
led2::toggle();

приятнее читать и удобнее сопровождать

Ртос это уже другого поля ягоды, при этом в текущем проекте никто не запрещал мне критичный к времени выполнения код обрабатывать в прерываниях с более высоким приоритетом прямо поверх шедулера.
Хотелось бы узнать побольше о вашем опыте. О том, как вы переносите ваши шаблоны на GCC 2.95 (привет МСВС), как он работают на компиляторах, отличных от GCC (привет разным российскими процессорам), как вы переносите ваш код на системы, где С++ просто нету, а есть только Си?

Или вы ради вашей красоты просто отказываетесь от проектов, где заказчиком жестко задан процессор?

Что касается сложности верификации — ну вы же профи, вы алгоритмы работы своих устройств выучили на зубок. А для обычного человека намного проще, когда код работы с устройством идет в тех же понятиях, что и в описании устройства. А любая абстракция — мешает верифицировать код по документации, Потому что сегодня одно устройство, завтра другое, послезавтра третье. И на каждое — 50-100 страниц доки.

я не профи во встраиваемых системах. Полдюжины embeded проектов, где работает мой код — это мало. Потому часть, связанную с железом мне проще писать ровно по доке. Без выкрутасов крутых ембедчиков, которые эти доки помнят наизусть.

Зато мой код — РАБОТАЕТ. А коллеге, любившему темплейты — оказалось проще уволиться, чем отладить свой код. У него вся энергия ушла в многоуровневые навороты. В итоге навороты красивые, но функции своей не выполняют. Хотя если бы обошелся без красивостей и код был бы меньше раза в 3-4 и работал бы намного правильней. УВЫ, темплейты и классы — отличный способ спустить пар в свисток.
Вы не поверите, но GCC 2.95 поддерживает шаблоны.

На компиляторах от Keil и Iar все работает прекрасно.

Миландр (привет разным российскими процессорам) тоже поддерживает C++ и шаблоны. Любые армы поддерживают C++ и шаблоны, микроконтроллеры авр поддерживают C++ и шаблоны. Пики и 8051 только остались за бортом, но их никто не использует.

Так что похоже вы сами себе придумали проблему и сами поставили ее мне в укор.
Раз пошло время придуманых ситуаций, я тоже задам вам вопрос.
Что вы будете делать если микроконтроллер не поддерживает ни C++ ни С а только ADA? Или вы ради вашей красоты просто отказываетесь от проектов, где заказчиком жестко задан процессор?

Вы опять же не поверите, но параметризацию устройства можно тоже вынести в отдельный класс и получить великолепную абстракцию, причем человеку который пишет не надо знать что и как там инкапсулированно, настроил phy микросхему на 10 Мбит, ок, на 100 надо? Не будем перелапачивать весь код, а просто добавим реализацию конфигурирования на 100мБит.

Зато мой код — РАБОТАЕТ. А коллеге, любившему темплейты — оказалось проще уволиться, чем отладить свой код.
Вот это характеристика только ваша и коллеги. МОЙ КОД ТОЖЕ РАБОТАЕТ!!!!!!!!!!!..

Это сродни истории
«К нам в бригаду строителей пришел странный какой то, все молотками забивают гвозди, а он пневматический принес, поковырялся там, гвоздей не забил ни одного на компрессор пожаловался и уволился.»

Это же не пневматического молотка проблема, это человека. А вы экстраполировали своего коллегу на все сообщество C++ программистов.
ЖАЛЬ, что вы проблему не понимаете. Ещё больше ЖАЛЬ, что вы свое непонимание проблемы передаете студентам.

Первичное — код должен РАБОТАТЬ. ПРАВИЛЬНО работать. Выполнять нужные функции. Вторичное — это НАДЕЖНОСТЬ кода. Работоспособность кода при ошибках в данных, при изменении условий, На третьем месте — СКОРОСТЬ и затраты памяти. И только на четвертом — СОПРОВОЖДАЕМОСТЬ. Потому что в большинстве случаев сопровождение надежно работающего кода — не нужно.

Бывают ситуации, когда сопровождаемость вылезает на второе место. это когда известно, что проект будет развиваться годами.

А вот на ПЕРВОМ месте сопровождаемость лишь тогда, когда код НЕ РАБОТАЕТ Не выполняет своих функций. Вот тогда 99% сил будут потрачены на сопровождение и поиск ошибок.

Ну и сдача экзаменов — на экзаменах, конечно СТИЛЬ написания намного важнее, работает программа или нет.

В итоге после ВУЗа мы получаем специалистов с отличным стилем и неработоспобными программами. И это ОБЩАЯ ситуация.

Поймите, вы ставите телегу впереди лошади. То есть стиль впереди работоспособности. Мне ЖАЛЬ, что вы не понимаете, насколько это вредно.

Из более 30 лет своей программистом карьеры я лет 20 занимался именно сопровождением чужого кода.И код, в котором на первом месте сопровождаемость — исправить невозможно. Его можно только написать заново. А если код рабоспособен и надежен — проблем с ним немного. Если он плохо написан — его несложно отрефакторить.

Теперь ответы на ваши вопросы.
1) Код без темплейтов и С++сных наворотов я перепишу на что угодно. Не только на АДА, но даже на РАЯ (он же Ершол). Даром что ли я на полусотне языков читаю. А вот ваши красивости на АДА просто так не перенесешь.
2) имелся ввиду 1879ВЯ1Я от модуля. Для DSP там российский компилятор.
3) GCC 2.95 — да, шаблоны поддерживает. Но далеко не все, что умеет GCC 5.0
4) Кого выносить в отдельный модуль — решение архитектурное, а не стилевое. Давайте не путать предмет спора. Хорошая архитектура — действительно полезна для проекта. Но если вы не понимаете отличие архитектуры от стиля — значит вы не готовы к серьезному обсуждению.

ИТОГ. О ваших проектах вы не рассказали ничего. Есть чего рассказывать или все под NDA как незабвенная Bolgeos?
Я разрабатывал измерительное оборудование для железнодорожных систем.
В данный момент разрабатываю измерительные системы для антенных комплексов.
Видео
На данном видео можно увидеть комплекс, в разработке которого я принимал участие.

Дальнейшую дискуссию с вами продолжать не могу, в силу отстуствия конструктивной составляющей. Похоже шаблоны и С++ для вас есть вселенское зло, которое надо искоренять всеми силами
Вселенское зло — это ошибка ПРИОРИТЕТОВ. Перфекционизм во второстепенном.Замена цели средством.

Я правильно понимаю, что вы разрабатываете измеритель для одного спутника, потом немного дописываете — и получаете измеритель для второго, потом — для третьего? То есть в ВАШЕЙ задаче сопровождаемость действительно может стоять даже на первом месте. То есть вам может быть важнее выдать 10 похожих приборов, чем работоспособность отдельного прибора. И уж точнее важнее время разработки всей серии, чем время разработки отдельного прибора.

Осталось понять, что это ВАШ частный случай. Который не имеет отношения к той же пастильде.

Шаблоны и разные С++ные хитрости — это СРЕДСТВА. На своем месте — они хороши. А когда их написание идет в ущерб работоспособности кода — они плохи.

Прошу прощения, спойлеры мне недоступны.

http://bash.im/quote/420672
Вася и Петя одновременно начали писать один и тот же продукт.
Вася был «ориентирован на результат» и начал сразу писать говнокод не продумав толком архитектуру.
А Петя месяц разрабатывал архитектуру, месяц делал удобный интуитивный интерфейс, которому позавидывал бы Джони Айв, потом месяц писал тесты, потом два месяца писал сам код и получил идеальное стабильное приложение.
Но Вася выпустил уже через месяц первую версию программы, пусть и не идеальную, пусть с багами, но рабочую, и начал её продавать. Ещё через месяц выпустил вторую версию исправляющие баги первой и добавляющие новые баги. Ещё через месяц на доходы от продаж нанял двух толковых программеров, которые за два месяца перелопатили весь код, согласно пожеланиям пользователей допилили интерфейс и выпустили третью версию программы.
Итого, через пять месяцев у Васи было два работника, куча клиентов и сносно работающее приложение отвечающее желаниям клиентов.
У Пети было вылизанное никому не известное приложение, минус на банковском счёте и ни одного клиента.
В завершение этого выдуманного примера можно сказать, что через полгода Вася купил все наработки Пети, Петю взял в штат тестировщиком, а сам по пьяни разбился на своём новеньком Туареге
Да, чтобы вы понимали. Мои требования к компиляции на любом компилятор, начиная с borland C++ 3.1 для MS-DOS 1990ого года выпуска — они точно так же специфичны, как и ваши.

Судя по минусам — тут много народу, кто путает средства с целями. Ну что же, мне жаль. :-(
UFO just landed and posted this here
Абстракция, в общем-то, может и не выходить за пределы текста кода, хороший (или ужасный) пример такого кода — Метод Даффа
Да, согласна с вами. О применении ChibiOS в проектах думаю уже довольно давно. Слышала, что HAL там действительно самый хороший из всего того, что на данный момент представлено. Но на внедрение использования OS (на корпоративном уровне) нужно время, которого к сожалению всегда не хватает. Однако, полагаю, что скоро жизнь заставит и переход на ChibiOS все-таки будет осуществлен.
а что ещё остается делать при размере ОЗУ 2кбайта.
На описываемом в статье USB-брелке используется чип STM32F405 ($4.39 за штуку на digikey), у которого на борту полмегабайта флэша и 192 килобайт ОЗУ.
В этом плане с вашим проектом хорошо пересекается ещё одна интересная и потенциально нужная как открытый проект задача — индивидуальная раскладка клавиатуры, носимая с собой, не зависящая от ОС. От такой «раскладки» требуется не только перекодировка комбинаций с обычной клавиатуры через USB-переходник, но и кодирование произвольных длинных слов (тех же паролей, но и не только) из других слов или сочетаний клавиш. И там тоже стоит вопрос об аппаратной реализации хаба USB. Так что можно брать вашу реализацию за основу и тащить туда.

(Куда? Не задавался давно этим вопросом; может, кто-то подскажет? Нашёл только похожую функцию в одном гаджете для планшетов — клавиатура через USB)
Интересно. Эдакий аппаратный Karabiner для мака. И наоборот.
После долгой работы на маке, переходя на PC, начинаешь на автомате использовать command+c вместо ctr+c и т.п. А переопределить такие штуки глобальным хуком (на Win32) не всегда можно. Аппаратный транслятор в этом смысле имел бы преимущество.
Было бы интересно посмотреть на отчет из PVS-Studio по этому проекту.
Уверен много интересного напишет.
Разве PVS-Studio не заточен под VS? Может быть вы можете порекомендовать еще какие-нибудь анализаторы?
У PVS есть бинарник, который можно вызывать для каждого файла проекта по аналогии с компилятором. FAQ. То есть, к IDE он жестко не привязан.

Рекомендовать могу анализатор из состава Clang. Он интересен тем, что бесплатен и открыт. Опенсорс к опенсорсу.

Девушка — программист микроконтроллеров!
А такого удивительного? Что девушки — не программисты?
А у тебя не будет минусов, потому что никто не догадается. Удивительно, правда?
Извините покорно, но Вы не подскажете, когда конкретно я с Вами на брудершафт пил?
вам стоило вспомнить о вежливости двумя комментариями выше. предлагаю на этом закончить нашу беседу
А что невежливого в сообщении, что чего-то где-то не будет?

(А что Вы, прочитав это сообщение, подумали — это уже претензия не ко мне: «каждый воспринимает увиденное в меру своей распущенности» ©.)
UFO just landed and posted this here
Реализация 0.1 является тестовой, типо proof of concept и все такое. В рамках данной реализации, мы пока не используем media клавиатуры, клавиатуры с USB хабами и т. д. Мы обязательно займемся этим на следующем этапе развития проекта, но на данной стадии это избыточно. Тут перед нами стоит другая задача: проверить жизнеспособность идеи. Например, на внешней памяти предполагается организация файловой системы и нужно оценить скорость записи файлов на диск через USB, скорость работы самого контроллера с этой памятью как с файловой системой. Еще нам нужно портировать keepass и тут тоже много вопросов: сколько времени будет занимать шифрование / дешифрование базы данных, а подумали ли мы о том, где хранить расшифрованную базу данных и др. Таким образом, пока что нам нужно сделать прототип устройства, чтобы понять:
  • подходящий ли контроллер мы выбрали?
  • а память?
  • нам нужно где-то хранить расшифрованную БД, так может рядом с флешом поставить еще и энергозависимую память?
  • а что со скоростью работы устройства? не пора ли нам использовать RTOS?

и многое другое.
У вас на MCU есть ноги для SDIO. Подключите к ним microSD флешку и не мучайтесь c внешним контроллером памяти. Для ChibiOS есть готовая реализация USB Mass Storage поверх SD-карты, кстати.
К бд имеет смысл стучаться, используя шифрование/дешифрование «на лету».
Так да) Мы уже задались вопросом почему мы SD-то не поставили, это действительно было бы проще. С контроллером тоже косяк вышел, мы поставили STM32F40x, а нужно было STM32F41x, ибо в там есть крипто процессор. «На лету» вы имеете ввиду расшифровывать только необходимые в данный момент записи?
Вам весь файл в памяти не нужен, его вполне можно читать в поточном режиме при поиске нужного пароля.
Да, РТОС вскоре может пригодится, чтобы велосипед не изобретать, вроде неплохая РТОС — RIOT
http://www.riot-os.org/#features
Хе… а в устройстве не предусмотрен недокументированный режим аппаратного кейлогера? Реализация прям напрашивается…
Я думаю, если будет возможность перепрошивать контроллер собранной у себя из исходников прошивкой, то кейлоггер маловероятен.

Интересно, можно ли в принципе на stm32f4 одновременно завести hid и uvc? Использую stm32 usb device library. М.б. есть какие-либо примеры?

Вы имеете ввиду USB video device? Почему нет? Для того, чтобы устройство распознавалось как video device, необходимо лишь правильно описать дескрипторы, тут найти примеры не составит труда. Для работы устройства нужно понимать протокол взаимодействия хоста с данным видом устройств. Существует документ Universal Serial Bus Device Class Definition for Video Devices там все подробно описано (глава 3 поможет с дескрипторами, а глава 4 с протоколом взаимодействия). Изучите его, поймите, что требуется, и это, я полагаю, значительно облегчит ваши поиски! Удачи!
Будет ли реализована возможность заливать собранную самому прошивку и загрузчик?

Какую комбинацию клавиш надо нажать чтобы Пастильда вставила только пароль, а не логин и пароль?

Есть ли техподдержка у товара Пастильда?

Пастильда это open source, проект больше не поддерживается.

Существует ли способ микроконтроллером со стороны прошивки прочитать состояние зелёных LED светодиодов CapsLock/NumLock/ScrollLock?

Вот библиотека STM32_USB_Host_Library похоже, что не позволяет такое делать.

STM32_USB_Host_Library How to read CapsLock LED status
https://community.st.com/t5/stm32cubemx-mcus/read-state-of-caps-lock-from-keyboard/td-p/273899

По-моему только комп их отсылает

Тогда как STM32 USB Device HID устройство может прочитать у PC состояние зелёных светодиодов для USB клавиатуры?

Архитектурно за состояние диодов отвечает хост, он сообщает клавиатуре что включить/выключить. В общем случае у него может не быть способа прочитать что там думает по этому поводу клавиатура. Но вроде всё же можно: https://community.st.com/t5/stm32cubeide-mcus/usb-host-keyboard-output-report-how-to-control-the-3-leds/m-p/308465/highlight/true#M16633

Я пробовал функцию USBH_HID_GetReport. И она всегда возвращает нули.

И потом, не понятно откуда взялись эти магические чиселки: 2 и 0 на месте 2го и 3го аргумента?

Даже если принудительно включить все LED функцией

uint8_t led_byte = 7;

status = USBH_HID_SetReport(phost, 2, 0, &led_byte, 1);
то функция
status = USBH_HID_GetReport(phost, 2, 0, &led_byte, 1);
всё равно возвращает нули

Вот тут человек @LitLageR
https://habr.com/ru/articles/788844/
написал, что ему якобы удалось с клавиатуры прочитать состояние xxxxLock LEDы.

Однако подробности реализации отсутствуют.

Вот там человек пришет, что он приделал к своей клавиатуре получение команд от хоста "включи лампочку хххЛок", которые ST в своей типовой библиотеке не сделал.
Полистайте первоисточник: https://usb.org/sites/default/files/hid1_11.pdf
Там в конце есть AppendixB, в котором протокол типовой клавиатуры приведён. И в нём нет возможности достать из клавиатуры статус этих лампочек. Это только хост может скомандовать. Когда захочет.

Sign up to leave a comment.

Articles