Pull to refresh
-22
0
Андрей Батищев @DX168B

Программист

Send message

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

Я разбирал перо от 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. Не, так не пойдет.

На первом фото я узнал одного человека. Конкретнее, руководителя отдела R&D :)

Вам могу пожелать только успеха. Электронная промышленность - сложная и затратная (как экономически, так и по времени) отрасль. Особенно, если разрабатывать технологии с нуля.

Извиняюсь за ответ на очень старый коммент, но я соглашусь.

У меня STM32F407 очень тяжело справляется с преобразованием потока данных 24 бит 48k smp/s сначала в 24 бит 384k smp/s, потом в 9 бит 384k посредством дельта-сигма модуляции. А на МК возложена еще и куча других задач. Потому эту задачу я отвел для FPGA. Даже дешевый вариант Cyclone II (EP2C5T144C8N) справляется с преобразованием и дальнейшей обработкой этого потока просто на ура. По барабану даже на то, что там КИХ фильтр высокого порядка для апсемплинга.

Собственно, с этой задачи и началось мое освоение ПЛИС. Освоил быстро, благо с логической схемотехникой был знаком даже до освоения микроконтроллеров. В качестве языка выбрал Verilog. Писанины на нем меньше, чем на VHDL. Тот же КИХ писал сам. В железе заработал сразу, так как при разработке следовал стандарту: Строгая синхронщина, управляемая конечным автоматом. И так во всех функциональных модулях. Проект сложный, в нем я сразу столкнулся со всем многообразием методов отстрелить себе ногу. Столкнулся даже с синхронизацией между разными тактовыми доменами. Но все построил так, что Таймквесту достаточно было только сказать, какие и откуда у меня тактовые частоты и больше ничего ему не потребовалось.

Сделал Ваш вариант. Играет в принципе нормально, но чем больше каскадов ставлю последовательно (увеличиваю порядок модулятора), тем громче становится фоновый шум. По идее, он должен был смещаться за пределы слышимого диапазона, но пока что-то идет не так. Может где-то напортачил. Привожу главный кусок реализации модулятора 3 порядка на Verilog

Hidden text
	// Data lines
	wire[23:0] leftQuantizer;
	wire[23:0] rightQuantizer;
	
	// Delta 0
	wire[23:0] left_delta_0 = leftNsIn - leftQuantizer;
	wire[23:0] right_delta_0 = rightNsIn - rightQuantizer;
	
	// Sigma 0
	reg[23:0] left_sigma_0 = 0;
	reg[23:0] right_sigma_0 = 0;
	
	always @(posedge clock or posedge reset) begin
		if(reset == 1'b1) begin
			left_sigma_0 <= 0;
			right_sigma_0 <= 0;
		end else begin
			if(integr_enable == 1'b1) begin
				left_sigma_0 <= left_sigma_0 + left_delta_0;
				right_sigma_0 <= right_sigma_0 + right_delta_0;
			end
		end
	end
	
	// Delta 1
	wire[23:0] left_delta_1 = left_sigma_0 - leftQuantizer;
	wire[23:0] right_delta_1 = right_sigma_0 - rightQuantizer;
	
	// Sigma 1
	reg[23:0] left_sigma_1 = 0;
	reg[23:0] right_sigma_1 = 0;
	
	always @(posedge clock or posedge reset) begin
		if(reset == 1'b1) begin
			left_sigma_1 <= 0;
			right_sigma_1 <= 0;
		end else begin
			if(integr1_enable == 1'b1) begin
				left_sigma_1 <= left_sigma_1 + left_delta_1;
				right_sigma_1 <= right_sigma_1 + right_delta_1;
			end
		end
	end
	
	// Delta 2
	wire[23:0] left_delta_2 = left_sigma_1 - leftQuantizer;
	wire[23:0] right_delta_2 = right_sigma_1 - rightQuantizer;
	
	// Sigma 2
	reg[23:0] left_sigma_2 = 0;
	reg[23:0] right_sigma_2 = 0;
	
	always @(posedge clock or posedge reset) begin
		if(reset == 1'b1) begin
			left_sigma_2 <= 0;
			right_sigma_2 <= 0;
		end else begin
			if(integr2_enable == 1'b1) begin
				left_sigma_2 <= left_sigma_2 + left_delta_2;
				right_sigma_2 <= right_sigma_2 + right_delta_2;
			end
		end
	end
	
	assign leftQuantizer = {left_sigma_2[23:15], 15'd0};
	assign rightQuantizer = {right_sigma_2[23:15], 15'd0};

Управляется просто:

По приходу фронта на вход "data_valid", пришедшая выборка из апсемплера фиксируется во входных регистрах (в коде не приведены) leftNsIn и rightNsIn. Далее простая машина состояний по очереди раздает импульсы разрешения интеграторам, начиная с нулевого интегратора и заканчивая последним. После фиксирует результат в выходных регистрах.

Реализую похожее на FPGA. Только у меня это будет сразу усилитель D класса. Сильный упор на качество не делаю, но постараюсь сделать как можно качественнее, на сколько хватит ресурсов.

Несущую выбрал 384кГц, на эту частоту больше выбора силовых ключей. При этой частоте, разрядность ШИМ получается равной 9 битам (модулятор при этом просит около 200мГц). Больше сделать проблематично, так как от FPGA EP2C5T144C8N можно получить стабильную работу на частотах не более 260мГц. Другой ПЛИСины у меня пока нет, обкатываюсь на этой. Модулятор работает хорошо как в тестбенчах, так и в железе.

Исходный сигнал - 24 бит, 48кГц. АЦП - PCM1802. Просто потому что нашел ее в виде модуля на Али. До 384кГц довожу оверсемплингом, построенном на самопальном КИХ фильтре на 128 коэффициентов. КИХ тоже работает хорошо. Может работать на тактовой до 60МГц, но его можно еще ускорить, если конвейеризовать некоторые узкие места (в самом умножителе и между его выходом и сумматором. Мне лень было всовывать регистры между ними). Но текущей его производительности хватает и так с головой на 50 МГц. Однако, вместо Дельта-Сигмы я решил попробовать нойзшейпинг. Он точно так же должен сместить шум квантования вправо по спектру.

Из текущих проблем, чтобы впервые запустить это дело и проверить:

  1. Переделать I2S интерфейс. Я его делал первым, попутно осваивая Verilog и технологии FPGA. Потому там сплошная асинхронщина. На выходных реализую синхронный дизайн этого модуля.

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

Ваш вариант с "многобитной" дельта-сигмой тоже попробую.

Information

Rating
4,328-th
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity