-
Постов
5 803 -
Зарегистрирован
-
Посещение
-
Победитель дней
14
Arlleex стал победителем дня 6 апреля
Arlleex имел наиболее популярный контент!
Репутация
131 Очень хорошийИнформация о Arlleex
- Сейчас Просмотр форумов
-
Звание
Гуру
Контакты
-
ICQ
Array
Посетители профиля
-
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Обычно в этом корень всех бед. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Да. Так делают, например, топовые гиганты типа интел/амд/нвидиа. И да, я не видел ни одной фирмы, где прям по серьезке садились бы считать байты ОЗУ, которые потребуются для задачи, ибо хотя бы найти челвоека, который это умеет и потом будет в случае чего отвечать - та еще задача. Обычно смотрят по верхушкам - устраивает ли МК/проц по интерфейсам и их скоростям, режимам и т.д. Можно ли его купить в обозримом будущем в тех же объемах, что он продается сейчас. У инженера обычно в комплекте где-то в районе пятой точки есть чуйка, которая подсказывает ему, хватит ли ему ресурсов или будет маловато. Чуйка обучается опытом а потом подтверждается расчетами. -
STM32F103 переход в default_handler
Arlleex ответил addi II тема в Программирование
... или стартап-файл не под свой контроллер налутал)) -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Есть, конечно)) Но эта ошибка из разряда "вернуть адрес локальной переменной из функции" - т.е. бывалым разработчиком не допустится🙂 Операции с DMA либо блокирующие (костыль, не делаю так никогда), либо функция отправки пишет в буфер, из которого DMA спокойно будет отправлять, а из той функции можно смело выходить. Я стремлюсь всегда разделять уровни кода, поэтому все очень просто становится читать и поддерживать. Вот так выглядит интерфейс чтения/записи в UART #ifndef _UART_HPP_ #define _UART_HPP_ #include "macros.h" namespace nsUART { void init(); u32 readRxFIFO (u8 dst[], u32 len); s32 writeTxFIFO(u8 src[], u32 len); } #endif И совершенно не важно, что передача и прием реализованы как кольцевой буфер с задействованным DMA как на прием, так и на передачу. Задача (или цикл) парсера вызывает readRxFIFO() и разгребает входящий поток байтов: если нащупала что-то осмысленное - вызывает функцию разбора пакетов. Если хотим отправить данные - вызываем соотв. функцию и передаем ей эти данные, она их кодирует, обрамляет как надо и вызывает writeTxFIFO(). -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Отключать то зачем? Скорее, просто следить за когерентностью данных и вовремя их флушить/инвалидировать. Я тоже могу представить контекст, в котором эти сентенции уместны. Но они точно не уместны при тезисном описании в википедиях и тем более не применимы в технических дискуссиях за свод нерушимых правил, преклоняясь перед авторитетом дяди в очках с задней обложки книжки. На всякий случай, повторюсь🙂 Я цифру 1024 написал от балды, это лишь для примера было. На самом деле у меня отправляемые пакеты создаются по мере необходимости к отправке, т.е. на стеке. А вот под принимаемые пакеты как раз статически выделяется буфер-агрегатор (в виде Си-шного union) под самый длинный возможный пакет. Т.е. если максимально возможный принимаемый пакет будет, например, 1000 байт - будет создан буфер на 1000 байт или чуть больше для локальных требований к выравниванию и т.д. В особых случаях, когда памяти почти нет (ОЗУ), а линия связи позволяет отправлять данные порционно - то можно так и делать. Например, тот же SLIP по UART-у можно не кодировать предварительно, а кодировать по мере отправки очередного символа. С тем же езернетом так не получится - внутри одного езернет-кадра будь добр подготовить все нужные данные сразу. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Именно. Профессоры обычно только и печатали книжки, не имея ни малейшего представления о реальном коде. Туда же книжки Макконела и Мартина - т.е. в жопито😉 Посмотрел цитаты великого цитируемого (с моими скромными комментами): За любым столом после 3-й рюмки уже обычно начинаются пространные рассуждения о смысле жизни и трехэтажная философия. Здесь из этого же разряда - просто потому, что "классики" больше никакой нет. За неимением цитируют вот таких вот деятелей. P.S. И кстати, а причем тут щас вообще оптимизация? Я вроде о ней даже не говорил. Нет, ну я конечно стараюсь сразу более менее вменяемо подходить к написанию кода - т.е. там, где можно сразу сделать хорошо - делаю. Другой подход мне уже не приживется, ибо это, как и любовь к говнокодингу - либо навсегда, либо никогда. Сегодня вот на моем смартфоне при открытии камеры вываливалось сообщение "Невозможно подключиться к камере". Б%ять! И никакая перезагрузка не помогает. Калькулятор весит 100 мегов - скоро, видимо, и считать правильно перестанет. И так со всем программным, что меня окружает в нынешнем мире. Вот такая философия с преждевременной оптимизацией и породила покрасчиков кнопок, которым похрен на юзеров, которым для моргания лымпочкой нужна ардуина на распбери пай, не меньше. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Прошу прощения, не обратил внимания, что указатель. Вы правы. Однако да, мой компайлер обозвал меня представителем европейского модного движения за VLA внутри структуры А так - это почти то, что я хотел🙂 А разница? В одном проекте - по прерываниям делал, в текущем - DMA принимает. Как это влияет на разбор байтового потока? Зачем его знать? DMA настраивается в кольцевой режим. Задача, обслуживающая канал приема, читает эти байты и отдает его фреймеру SLIP-а, а тот уже на выходе выдает пакеты данных. Потому что структуру в ее самом девственном виде проще читать и давать ее другим разработчикам, дабы понимали ее формат при поддержке протоколов общения. Когда передается 100500 разных классов, начиненных еще каким-то функционалом - становится вообще-то затруднительно сходу въехать в порядок разложения этой порнографии на байтики в реальном проводе. Структура весьма самодокументируема - сразу понятно, что за чем идет. В классе, в котором помимо данных набито еще 100 строк всяких методов и перегрузок, разобраться тяжелее сходу. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Это будет подтягивать динамическое выделение памяти, такое меня уже не устроит. Ух тут сколько всего написали (это хорошо, дискуссия жива🙂) - однако я внесу немножко понятностей. Не важно, что за протокол, важно то, что он пакетный: длина пакета выкорчевывается внеполосной сигнализацией на уровне проводов или (для примитивных байтовых интерфейсов) промежуточный канальный фреймер разбирает поток байтов на кадры/пакеты. Короче говоря, я всегда знаю, сколько данных мне прилетело в пакете. Пакет, как обычно, уже содержит заголовок со всякими типами содержимого для идентификации этого пакета и т.д. Шмалять в сеть пакеты фиксированной длины здесь очень избыточно - это точно красный флаг. Так вот. У меня девайс состоит из множества плат, каскадно соединенных друг с другом порой сильно разными интерфейсами. Пакет данных со входа до самой дальней платы может пройти пару-тройку интерфейсных мостов со своими протокольно-зависимыми особенностями. Каждая "промежуточная" плата имеет механизм проброса "не своих" пакетов данных туда дальше в "паровозик". Чтобы облегчить ПО каждой платы, она детально даже не разбирает "не свои" пакеты, а как есть его пересылает дальше. Где-то закладывать CRC не имело бы смысла, а где-то, из-за этого "прозрачного режима", CRC пакету нужен. Например: девайс состоит из двух плат (1) и (2), между ними прокинут UART. С платы (1) наружу девайса торчит Ethernet, воткнутый в комп. С компа шлю данные плате (2) - и, казалось бы, езернет уже гарантирует целостность своего фрейма, т.е. можно не вносить контрольную сумму для данных, но данные ведь предназначены плате (2), а чтобы туда попасть, данные должны преобразоваться в UART платой (1) и транслироваться на плату (2). Этот UART - байтовый, поэтому поверх него работает SLIP. Но для контроля целостности данных на приеме платой (2) пакет нужно долполнить контрольной суммой. Что и делает сразу отправляющая сторона перед засовыванием в езернет. Насчет положения CRC в структуре: да, можно в хедер ее пихнуть. Однако это маааленький такой костыль с тасованием расположения, который конкретно в данном случае вполне поможет (за счет наличия в Си и (с позволения компиляторов) C++ FAM в структурах). Да, удобно, если КС в конце - сверил - и результат будет 0. Оданко по затратам на вычисление это будет почти один-в-один с пробегом по хедеру и по данным и последующим сравнением полученной КС с той, что в хедере лежит (в случае размещения КС в хедере). Исторически у меня так завелось, что хедеры могут быть разных размеров, и поэтому КС размещалась строго в конце, несмотря на то, что размер кадра плавающий. Меня полностью устраивает этот вариант и поныне. И я хотел, чтобы несколько "костыльно" выглядящее определение структуры с гибким массивом в конце наконец обрело лаконичный вид в C++. Мне не нужна динамическая память - мне нужно как-то сказать компайлеру, чтобы на статически выделенном куске создавал структуру, в которой после гибкого массива расположен еще какой-то элемент. Условно, чтобы это выглядело примерно так (как я это вижу): struct FlexFrame { Header hdr; u8 data[]; // <- гибкий массив, а значит дальше можно ставить только элементы с атрибутом "гибкого положения" u32 crc __attribute__((flexible)); // положение этого члена "гибкое", в зависимости от объема поля data при создании структуры }; ... static u8 RxPacketMemory[1024]; // статически выделенная память для создания "гибких" структур // вызвали с len == 10 void sendPacket(u32 len) { // тут нужен был бы синтаксис объявления структуры, например FlexFrame frame __attribute__((RxPacketMemory, len)); // компилятор думает, что frame имеет data[10], размещая frame в памяти RxPacketMemory frame.crc = ...; // компилятор для доступа к полю crc использует соответствующее смещение, полученное на основе аргумента функции } -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Работает все прекрасно и у меня. И 15 лет назад тоже все работало. Меня интересовало, додумалось ли C++ сообщество до чего-то более удобоваримого в этом плане. P.S. Какие указатели в протоколе передачи данных??? Вы о чем? Вроде понятно, что данные снабжаются КС и уже улетают в провод. В дизасм смотреть или даже не пытаться?🙂 P.S. Я с МК тоже отправляю, так что способ ищу легковесный. Если нет - мне проще (как всегда, собственно) написать свой небольшой класс. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Я от того и спрашиваю, что задача тривиальная, а решалась всегда "криво"🙂 Но, видимо, нужно создать класс-оболочку над неким массивом известной длины (достаточной, чтобы вместить нужное количество данных) и с ним уже работать. Длину не нужно передавать, т.к. сам протокол умеет детектировать ее по механизму кадрирования нижних уровней. ИМХО, ужасное решение🙂 Потому что у меня десятки разных управляющих структур бегают, с разным содержимым и длиной. Контрольную сумму логично располагать где-то в одном конкретном месте для всех структур: и это либо начало кадра, либо самый его хвост. Иначе, чтобы определить положение КС, нам надо "узнать", что это за структура, а лезть в ее поля, не проверив КС - нельзя. У меня "узаконен" формат с CRC в хвосте. Алгоритм приема и отбраковки битых кадров становится универсальным. -
Плавный переход C -> C++ под МК
Arlleex ответил Arlleex тема в Программирование
Можно ли в C++ как-то красиво описать структуру с гибким положением последнего элемента? Допустим, есть структура struct TxRS485 { Header hdr; u8 byte[N]; u32 crc; } N должно будет стать известно в рантайме, поэтому шаблоны тут вряд ли помогут. Задача простая (и применяемая ну совсем повсюду): из поля ввода юзер-данных считать строчку, запихнуть ее в структуру с определенным паттерном (снабдив заголовками и т.д.), последним элементом должен "приклеиться" CRC-чек. Вроде все просто, однако как будто нет решения, кроме как по старинке "клеить" вручную хедер с данными, а потом к этому всему дописывать контрольную сумму. -
У китайцев чуть более прогнозируемая ситуация: если купить становится затруднительно у основного поставщика, то по инерции можно еще полгода точно ехать с помощью других продаванов, в это время подготавливая почву для внедрения новой аппаратной платформы. Другое дело - например, евреи - i.MX6 (по крайней мере, нужные нам SoM) пропали за месяц от слова "навсегда".
-
При мне уже несколько пытались - ни у кого не вышло.
-
У манагеров всегда все просто. Это вечно недовольным инженерам вечно то конденсаторов не хватает, то дорожки не лезут.
-
К этому и сводится большая часть программирования, несмотря на рядом стоящую помойку под названием стандартная библиотека.