Как стать автором
Обновить
-22
0
Андрей Батищев @DX168B

Программист

Отправить сообщение

Я забыл об одном важном нюансе. В пункте два, у кого были нули в запрошенных битах и при этом на шине проскакивал ответ на запрос мастера, прекращали отвечать на запросы следующих битов до следующего пакета из 1 пункта. Таким образом, опрашивая со старших битов, из процесса извлечения очередного серийника устройства выбывают крупные группы устройств.

То есть, имеем три устройства со следующими серийниками (пусть серийники будут 4-битными для упрощения)

А - 0110

В - 1001

С - 1111

На запрос 3 бита ответят устройства В и С, а устройство А, услышав этот ответ, замолкает до следующего пакета "есть ли кто неадресованный?"

На запрос второго бита ответит устройство С, а устройство В замолкнет.

На запрос первого и нулевого битов ответит только устройство С.

Таким образом у мастера получится серийник устройства С. Он назначит ему адрес и оно перестанет участвовать в сканировании.

При очередном запросе неадресованных устройств, устройства А и В выйдут из режима молчания.

На запрос 3 бита ответит устройство В, а устройство А, услышав ответ В, замолкнет.

При запросе 2 бита, оба устройства не ответят, но при этом устройство В, не услышав ответа продолжит отвечать на последующие запросы. То же самое будет и при запросе 1 бита и мастер запишет у себя два нуля. И уже на запрос нулевого бита, устройство В ответит. Так у мастера сформируется серийник устройства В.

При последующих итерациях отвечать будет только устройство А.

Идея эта была не нова и честно была украдена у протокола 1-Wire

Верно. Ибо ко многим этим знаниям человечество шло тысячи лет.

Реализовывали похожий принцип. Только в нашем случае серийники были длинными, а в целях сокращения длины рабочих пакетов, адреса были короткими. И короткие адреса назначал мастер. Только у нас было чуть по другому. Протокол разбивался на две части: Протокол сканирования и протокол рабочего обмена (который, кстати, может быть любым. Даже модбасом) Отвечали устройства так же - затяжкой линии в ноль. Работало это так:

  1. Запрос неадресованных устройств на шине. Если таковые были, отвечали нулём на шине. Мастер, обнаружив ноль, приступал к следующему этапу. А иначе, просто повторял запрос и обслуживал уже адресованные устройства.

  2. Запрос в стиле "есть у кого в серийнике 31й бит, равный единице?". Если у кого-то есть, тот отвечает нулём. Мастер, поймав ответ, записывает у себя единицу в 31й бит. А если ответ так и не поступил, пишет ноль в 31й бит. После этого он посылает следующий запрос, но спрашивает уже за 30й бит и так далее, до нулевого. В итоге, у него получается серийник одного из устройств.

  3. Мастер отправляет этому устройству пакет с коротким адресом, используя его серийник. Устройство получив короткий адрес, прекращает отвечать на запросы битов серийника и на запрос недресованных устройств и переходит в рабочий режим. После чего, мастер начинает обслуживание этого устройства и переходит в пункт 1. Такой цикл повторяется всякий раз, когда имеется ответ на пакет из первого пункта.

    Периодически, мастер интересуется на предмет появления новых устройств на шине, посылая запрос на наличие неадресованных устройств.

    Чтобы пересканировать шину заново, используется пакет начала сканирования. Услышав его, все устройства сбрасывают свои адреса и переходят в режим сканирования. Обычно он отправляется мастером, если его база найденных устройств пуста.

    Таким образом мы решили вопрос горячей замены устройств без каких либо манипуляций с прописыванием адресов. Воткнул устройство в шину и оно тут же обнаружилось мастером.

Я собирал U-Boot два раза. Первый раз под микроконтроллер, второй раз под свою плату с целью исправления бага с управлением питания. Патч отдал сообществу Armbian и они внесли его в официальный конфиг, так как с этой проблемой сталкивались многие. Вроде ни с чем сложным не столкнулся. Оба раза собралось без каких-либо танцев с бубном.

Я вот тоже не сторонник воровства, но однажды мне пришлось взломать МК, достать прошивку, отреверсить её, найти баг, исправить, собрать, прошить и пользоваться изделием дальше. Потому что от вендора добиться исправлений было нереально. Такой вот ремонт софта.

Я разбирал перо от Samsung Galaxy Note (1). Там изменение частоты резонанса было реализовано посредством изменения индуктивности с помощью дополнительного кусочка феррита. Между ним и основным сердечником стояла мягкая силиконовая прокладка. При давлении на перо, дополнительный кусок феррита приближался к основному, сдавливая прокладку. Таким образом увеличивается индуктивность и падает резонансная частота. На мой взгляд, это более простая и надёжная конструкция, в отличии от переменной ёмкости.

Кто подскажет, есть ли патченный под винду openocd с поддержкой китайских микроконтроллеров конторы HDSC? Просто ставить виртуалку с линуксом только из-за этого не очень хотелось бы.

Интересно, а можно было бы сделать по другому? В провайдерской сети поднять технический VLAN , на котором поднять сервис обновления прошивки. Но клиентские роутеры не настраивать на него. Монтажникам вручить специально настроенный роутер, настроенный на этот VLAN. Монтажник приходит на объект, втыкает спецроутер, подключает его к роутеру, который нужно прошить, подаёт питание, прошивает, снимает спецроутер и ставит свежепрошитый роутер на объект. Это позволило бы избавиться от этой проблемы хоть и не сразу, а постепенно.

Я перекинул функцию UART1 RTS на ногу BOOT1 и освободил PA15 для использования в качестве выхода синтезатора частоты. Сигнал появился. Кстати, адаптер уже служит верой и правдой и прекрасно справляется с поставленной ему задачей. Ваш проект помог мне сэкономить время.

Было такое у меня тоже когда-то. Закрыл 53-й порт для входящего трафика с интерфейса, который у меня определен как WAN. Открытый DNS используется злоумышленниками для атак на другие ресурсы. Для этого они отправляют запрос на DNS микротика с подмененным IP (IP жертвы). Микротик отправляет ответ в сторону жертвы. Такая вот флуд-атака.

Мы на шине, типа открытого коллектора, использовали свой протокол поиска, взяв за основу алгоритм поиска 1-Wire. Всё устройства изначально не имеют короткого адреса. Неадресованные устройства отвечают на специальную команду проверки наличия неадресованных устройств зажимом линии к земле на некоторое время. Главный контроллер ожидает спада линии в течении некоторого времени. Если зажим линии произошёл, значит начинается процесс опроса битов серийного номера. Главный шлёт запрос с номером бита серийника. Если ответ зажимом линии произошёл, значит у кого-то на шине он равен нулю. Если ответа нет, значит единица. В зависимости от ответов, формируется серийник, которому посылается команда назначения адреса. Получив адрес, такое устройство становится адресованным и больше не отвечает на запрос наличия неадресованных устройств на шине. Поиск заканчивается после того, как прекратятся ответы на запрос наличия неадресованных устройств. Так как шина поддерживала горячую замену устройств, главный контроллер периодически посылал запросы в шину о наличии новых устройств.

Стоит литиевая с преобразователем в мультиметре. Цвет чёрный с зелёным. Ставил её и в радиомикрофон. Помех небыло.

Два минуса имеются:

  1. Не работает индикатор разряда батареи на мультиметре.

  2. Разряжается за 3-4 месяца, даже если не пользоваться.

    В остальном только плюсы.

Благодарю за ответ.

Я использую ногу PA15 для вывода сигнала таймера. Используется первый канал (CH1) таймера TIM2. И столкнулся с проблемой. Дело в том, что где-то в коде, обслуживающем USB, портится конфигурация ноги PA15. Она вроде как не используется нигде, но проблема есть. Если закомментировать строку usb_init() в main.c, то проблем нет и сигнал выводится. Таймер инициализируется самым последним. Значит портится не в функции usb_init(), а где-то в обработчиках прерываний. Пока разбираюсь, где проблема.

Мне нужно сделать на скорую руку один адаптер. В нем нужен источник импульсов, потому решил сделать USB-UART адаптер на плате BluePill, так как у МК есть таймеры, которые могут послужить настраиваемым источником импульсов. За основу взял Ваш проект. Собрал без проблем, прошил, все работает и всё устраивает. Даже свободная нога имеется, на которую выходит первый канал второго таймера. В коде разобрался быстро. Добавил ряд команд в консоль для настройки таймера и свою структуру настроек в конфигурацию (всего два 16-битных поля). Всё читается и сохраняется без проблем, целостность конфигурации во флеш не нарушается.

Остался один вопрос. Как настроено тактирование микроконтроллера? Какие частоты заданы на системных шинах? Просто все максимально допустимые?

Можно так:

Непосредственно перед запуском передачи включаем линию DE.

Включаем прерывание DMA по завершению передачи.

В прерывании DMA по завершению включаем прерывание UART, которое сигнализирует о пустом регитре данных (TX reg. empty).

В прерывании TXE включаем прерывание TX complete (TXC) и выключаем TXE.

В прерывание TXC деактивируем линию DE и выключаем это прерывание.

Как это работает.

Регистр данных UART буферизован посредством FIFO буфера. Не помню точно, какова глубина буфера, (2 байта скорее всего), но прерывание TXE сигнализирует о том, что можно записать следующий байт, пока идёт отправка предыдущего. Прерывание TXC сигнализирует о том, что отправка текущего байта завершена. Оно будет вызываться всегда, когда завершается отправка очередного байта.

Идея состоит в том, что как только DMA просигнализирует о завершении последней транзакции, мы начнём ждать, когда регистр данных UART освободится. Так мы будем знать, что отправляется последний байт.

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

Как только он отправится, можно отключить линию DE

Имею такой. Оригинальный, исправный, с руссифицированной оригинальной клавиатурой. Иногда использую в некоторых целях. Например, компилирую прямо на нем некоторый свой код. Да и лежит, как запасной, на всякий случай. Много раз выручал в этой роли.

У меня есть pet проект, где тоже планируется создание сущностей C++ в Lua. (Это большой высокопроизводительный дашборд для мониторинга огромного количества датчиков и имеющий возможность расширения функционала посредством Lua и в будущем ещё и Python). Для объектов, которые создаются и уничтожаются в Lua все просто. Создаём в C++ класс, который планируем экспортировать в Lua. Пишем фабрику объектов этого класса в Lua - по сути создаём таблицу с именем класса и помещаем в неё метод new, который создаёт объект класса, создаёт в Lua таблицу, в которой в поле с именем класса и типом lightuserdata помещает указатель на созданный объект. Далее в неё помещаются методы класса (обёртки над методами, которые извлекают сначала указатель с вышеупомянутого поля, проверяют аргументы и вызывают соответствующие методы класса с передачей аргументов и возвращают значение в Lua, если нужно). После этого, за метаметодом _gc закрепляется функция удаления объекта. В этом случае жизнь объекта полностью контролируется скриптом. Причем, даже если потерять ссылку на объект в Lua, то сборщик мусора корректно удаляет объект из памяти, дёрнув метаметод _gc() И это прекрасно работает.

В статье предлагается назначать объектам идентификаторы и хранить их в каком-нибудь "реестре". В принципе, в моем проекте такой реестр есть, но вот как организовать обращение к объектам, которые могут создаваться и удаляться не только скриптом, но и по иным событиям, идей не приходило. В принципе, статья меня уже натолкнула на идею, за что автору спасибо.

Бизнесу необходимо зарабатывание денег, потому что без них он существовать не будет. Другое дело - цель создания бизнеса. Кто-то создает только ради сколачивания бабла (чем больше, тем лучше, высасывая все соки с бизнеса), а у кого-то есть идея и бизнес служит не только целью заработка денег, но и заработку репутации, желанию сделать уникальный качественный продукт или услугу и т.п.

volatile - это в первую очередь сообщение компилятору, что содержимое переменной в любой момент может измениться по внешним причинам. Например, если это регистр, связанный с оборудованием, или элемент буфера DMA, или её может изменить другой процесс (если программа работает в среде операционной системы). Соответственно, оптимизация по отношению к ней будет иной.

Особенно это хорошо проявляется на процессорах RISC с гарвардской архитектурой (ARM, RISC-V и т.п.).

Допустим, мы объявили регистр ввода-вывода обычной переменной и каким-то образом назначили ей корректный адрес размещения в памяти, отраженный на физический регистр. А теперь нам нужно дрыгнуть один раз выходом операцией "чтение-модификация-запись". То есть, прочитать регистр, изменить один бит, записать, потом снова изменить, потом снова записать.

int reg_0;
reg_0 |= 0x01;
reg_0 &= 0xFE;

Что произойдет? Процессор загрузит содержимое регистра в регистр общего назначения. Потом изменит бит, потом снова изменит и запишет обратно. На выходе импульса не будет.

LDR R0, REG_0 ;Чтение регистра
ORI R0, 0x01	;Изменение содержимого
ANDI R0, 0xFE	;Изменение содержимого
STR REG_0, R0	;Запись изменений

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

Если мы объявим переменную-регистр как volatile, то компилятор будет производить "чтение-модификация-запись" в физический регистр при каждом обращении к нему и операции эти не выбросит. Тогда на выходе мы получим желанный импульс.

LDR R0, REG_0 ;Чтение регистра
ORI R0, 0x01	;Изменение содержимого
STR REG_0, R0	;Запись изменений

LDR R0, REG_0 ;Чтение регистра
ANDI R0, 0xFE	;Изменение содержимого
STR REG_0, R0	;Запись изменений

Это же касается и операций чтения. При каждом обращении в Сишной программе к этому регистру, будут всегда производиться чтения с физического регистра.

Короче, выбросить всё, что активно используется в embedded. Не, так не пойдет.

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность