LINUX.ORG.RU

Написал эмулятор своего мобильника

 , ,


2

1

Более чем два месяца назад заказал отладочные платы для своего хоббийного проекта, но они так и не пришли и хз, придут ли вообще. Разработка прошивки для него из-за этого застопорилась: писать «на воздух» я не особо люблю, а текущая клавиатура уже не отвечает моим требованиям - банально не хватает кнопок.

И тогда в голову начала приходить мысль - а не организовать ли мне эмулятор по типу того, который используется в Android Studio? Идея показалась мне классной, но останавливало отсутствие внятной документации по qemu, поэтому для реализации задумки предлагалось соснуть сурца. В какой-то момент я понял, что без полноценной клавиатуры я не смогу продолжить проект - банально нет всех нужных кнопок - было принято решение засучить рукава и попробовать.

В штатной поставке esp-idf есть qemu, но в ней особо не развернёшься, поэтому начал с простого - используя простое i2c устройство в качестве шаблона, создал заглушки для клавиатуры, контроллера модема и контроллера питания. Подключить их тоже не составило труда - код как раз на скриншоте. Обмен данными по шине i2c оказался очень простым: на эмулируемом устройстве есть всего 2 функции обратного вызова - для чтения и для записи. Таким образом, когда мастер пишет и читает, то просто подсовываем ему то, что он просит. Таким образом реализовать эмуляцию i2c устройств оказалось легче лёгкого.

Далее прерывания. Для эмуляции линий gpio в qemu используются линии прерываний. Тут вроде всё просто: на эмулируемом устройстве создаются выходные линии qemu_irq и далее они подключаются… куда? Вот тут меня ждала первая, пусть и лёгкая, задача. В самом начале я подключил линию irq клавиатуры на матрицу прерываний. Обработчик прерываний вызывался, но понять, на каком gpio оно произошло он не мог. Немного пораскинув мозгами и пососав сурца покопав исходники, я нашёл правильное место для подключения - матрица gpio. Как видите, в функциях read и write ничего нет, поэтому реализовать матрицу предлагается самостоятельно. Ожидаемо :) Реализовывается она очень просто. Сначала в матрице gpio создаются 40 входных и 40 выходных лини qemu_irq, которые будут отвечать за все gpio, которые есть у esp32. Далее создаются ещё 2 выходные линии qemu_irq, которые отвечают за обычные и non-maskable прерывания. Их я подключил к матрице прерываний на специально предусмотренные для этого каналы.

Теперь возвращаемся к функцуиям read и write. Вы когда-нибудь работали с расширителями портов, которые подключаются по шинам spi и i2c? Вся суть сводится к тому, что вы просто пишете и читаете нужные регистры по шинам, верно? Вот тут всё тоже самое, только с одним маленьким отличием - сами регистры нахадятся в самом микроконтроллере и процессор имеет к ним прямой доступ. То есть матрица gpio - это просто расширитель портов, который встроен в процессор и подключен напрямую к нему. Таким образом, вы теперь выступаете в качестве микросхемы :) В ваши регистры будут что-то писать и читать, а вы будете управлять линиями gpio. Когда процессор хочет выставить нужный gpio в нужный уровень - он просто пишет нужный бит в нужный регистр. Вы это видите и переключаете нужную линию qemu_irq в нужный уровень. Если же входная линия изменяет свой уровень, то вы просто отмечаете это у себя в структуре и при чтении сможете вернуть процессору текущие уровни gpio. Если процессор настроил прерывание на каком-либо gpio, то его можно уведомить об этом с помощью линий irq и nmi-irq. Далее процессор прочитает регистр прерываний и попросит вас сбросить их и вы это сделаете :) (иначе он будет постоянно опрашивать регистры прерываний, думая, что они всё ещё активны). Таким образом, реализовать матрицу gpio не составило особого труда. После этого я подключил свои устройства к нужным линиям матрицы gpio и смог эмулировать работу gpio без проблем.

Итак, я уже потирал руки и думал: «Сейчас я кабанчиком организую эмуляцию дисплея на шине spi и можно будет браться за гуй.». Ок, по аналогии с устройством i2c, беру в качестве шаблона какое-нибудь spi-устройство и начинаю реализовывать дисплей. Общение происходит как по i2c, только вместо обратных вызовов read и write, у вас есть обратный вызов transfer, в котором одновременно происходит и приём и передача данных. Сделал я дисплей, запускаю и… тишина! То есть по шине мне передаются сплошные нули! Всмысле? 0_0 В этот раз пососать сурца покопаться в исходниках пришлось гораздо более основательно. В итоге, понатыкав везде и всюду спасительный printf(), я нашёл чёрную дыру, в которой терялись данные по дороге от гостя до эмулируемого дисплея. На первый взгляд кажется, что тут всё ок, но когда я расставил printf() для распечатки адресов регистров, которые пишет и читает процессор, то всё встало на свои места - этот код никаким образом не обрабатывает регистры DMA! То есть вообще. Получается, что гость пытается слать данные через DMA буфер, а ванильный эмулятор spi туда даже не смотрит. В итоге, я сделал его копию и написал свою реализацию, которая позволяет отправлять данные по spi с использованием dma (полную реализацию пилить не стал, ибо влом). И для этого пришлось решить задачу со звёздочкой - доступ к памяти гостя.

Пару слов о том, как работает DMA на esp32. Прошивка организовывает где-нибудь в памяти специальные структуры с указателями на сами данные и входной буфер. Далее в специальнные DMA-регистры записываются адреса (указатели) этих структур. Далее подаётся команда на запуск передачи и данные передаются/принимаются без участия процессора. Теперь передо мной встала задача - как получить доступ по указателям, которые мне передаёт гость? Ведь гость даёт адрес внутри адресного пространства виртуальной машины. Сначала я нашёл решение с помощью функций cpu_physical_memory_read() и cpu_physical_memory_write(), которые работают с указателями из адресного пространства гостя. Но лишнее копирование не давало мне покоя и я нашёл решение получше.

При создании виртуальной машины qemu создаются различные области памяти. Одна из них - оперативка. Создаётся с помощью memory_region_init_ram(). В esp32 создаётся несколько различных областей такого типа. Фишка в том, что все эти области выделены как обычная память на хосте. Идея заключается в том, чтоб использовать memory_region_get_ram_ptr(), чтоб получить указатель на каждую область. Затем, зная начальный и конечный адрес каждого региона, можно вычислить расположение данных в оперативке хоста и работать с ними напрямую.

Последняя задача - как передать эти указатели, которые возвращают вызовы memory_region_get_ram_ptr(), в сам эмулятор spi? Он выполнен как отдельное устройство. В этот раз сосание сурца ковыряние в исходниках и чтение крох документации ничего не дали, поэтому решил действовать в лоб - передавать через свойства устройства. В эмуляторе spi я сделал несколько свойств с помощью object_property_add(), при создании машины при инициализации spi просто передал указатели как uint64_t с помощью qdev_prop_set_uint64(). Не уверен, что поступал правильно, но других решений не нашёл. Возможно, в таких случаях следует создавать отдельное устройство - эмулятор DMA, не знаю. Тем не менее, это сработало - я смог получить доступ к памяти гостя, высчитав смещение и прибавив его к одному из указателей на область памяти.

Гуй сделал на Tcl/Tk. Общение в машиной идёт через fifo. Просто и понятно. Уверен, что у qemu есть свой api для построения гуя, но я, честно говоря, к этому моменту уже окончательно устал искать информацию раз, и хотелось немного попрактиковаться в тикле два. До этого в тикле не работал с цветными изображениями и это был неплохой повод попробовать. Оказалось, что всё делается элементарно через image. Благо по тиклю информация есть, в отличие от.

К чему я вообще пишу обо всё об этом? Похвастаться? Да, не без этого, но ещё больше хочется поделиться вот чем. До того, как я полез писать эмулятор, я многое знал, но не понимал как именно работают те или иные вещи в микроконтроллерах. После того, как я написал эмулятор, я многое понял. Например, как именно процессор управляет своей перефирией. Как работают прерывания. Как работает DMA. Да и вообще, получил опыт в работе с «сырыми» регистрами. Я это к тому, что если у вас есть какая-нибудь идея и вам хочется её осуществить, то всегда пробуйте! Даже если задача изначально кажется сложной и неподъёмной. Запросто может оказаться так, что вы, как и я, не просто реализуете задуманное, но ещё получите ценные знания и/или опыт в процессе.

Такие дела \ё/

★★★

Проверено: hobbit ()
Последнее исправление: hobbit (всего исправлений: 28)
Ответ на: комментарий от Jullyfish

Этого производителя сразу в лес. У них ни даташиттов ни документации нихрена. https://www.waveshare.com/wiki/43H-800480-IPS Тупо готовые модули есть под линукс и всё.

Кстати, забыл уточнить важную вещь - наличие GRAM. Я таких всего парочку находил, но они были с большой диагональю.

u5er ★★★
() автор топика
Ответ на: комментарий от Morin

прямо на шлейфе

Вариант «на троечку». Но я такие довольно редко видел. В основном ставят плату на обороте дисплея.

cog

В таком случае это уже сам драйвер матрицы. Например, есть контроллеры ILI, которые умеют в MIPI DSI.

u5er ★★★
() автор топика

Вижу каких-то барышень и мелкое нечто. На что смотреть-то?

alt-tab-let ★★
()
Ответ на: комментарий от ann_lortemp2

ToxID 125009B917E9C2046A3FFC05C151D48BE8F5291FBCCA21DF479E86E44D7DBC22A421AA892F96

u5er ★★★
() автор топика

...пососать сурца...

Навеяло:

лососни тунца!!!11

Не, чо, молодчик! Аж захотелось и мне что-нибудь пореверсить!

sparkie ★★★★★
()
Ответ на: комментарий от temak

красноглазия

Скорее велосипедостроения ;)

u5er ★★★
() автор топика

Про аниме-тян на обоях комментарии были? Это моветон, если что. А так хорошим делом занимаешься.

peregrine ★★★★★
()
Ответ на: комментарий от u5er

Мы на ЛОР-е, а тут как-то так. 27997 результатов. Я чёт не понял, у нас что совсем ЛОР выродился, что на второй странице ещё никто не отписал очевидные нормы сообщества. )))

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от peregrine

Прикольно. Только там все повторяют одну и ту же фразу, но только нет пояснений, почему это стало моветоном. Что в этом плохого? Или может было какое-то событие, после которого это стало считаться моветоном?

u5er ★★★
() автор топика
Ответ на: комментарий от u5er

Или может было какое-то событие

нашествие анимешников в пубертате, ещё фрактал был, который годами балансировал на грани педобира

почему это стало моветоном

Это очевидно же, мы на ЛОР-е, а тут ты с тянками по больному

)))

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

нашествие анимешников в пубертате

Как будто что-то плохое :)

ещё фрактал был

Фрактал, если это тот самый, был толстый троль и стрелочник. Я не думаю, что есть смысл приводить его как аргумент.

Это очевидно же, мы на ЛОР-е

Не вижу никакой связи.

а тут ты с тянками по больному

Ты намекаешь на недавние события?

Ладно, это уже седьмой пост оффтопа в этой теме пошёл из-за обоев. Пожалуй подумаю над тем, чтоб в другой раз использовать стандартный непрозрачный xterm.

u5er ★★★
() автор топика
Ответ на: комментарий от u5er

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

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

CrX ★★★★★
()
Ответ на: комментарий от CrX

обои были упомянуты

Обои только ты упомянул ;)

но в итоге получится польза.

Давай я тебе расскажу кратко о своём пути линуксоида. Самый первый дистр, который я накатил по-серьёзному, был деб с LXDE. В ней использовался «обычный» непрозрачный эмулятор терминала с чёрным фоном. Через буквально 3 дня ковыряния и осваивания системы (половина из которых проходили в этом терминале с чёрным фоном) деб мне надоел: в нём всё работало и мне стало скучно. Тогда я полез на лор и начал читать про «линуксы»: что в них и как. В какой-то момент я наткнулся на упоминание LFS.

Угадай, что было дальше. Правильно - у меня загорелись глаза и я пошёл его собирать! Разумеется, я это делал всё в том же «чёрном» терминале. Компилял я его примерно месяц, потому что на ноуте процессор атом n450 да и дела ещё какие-то попутно были. В процессе сборки LFS до меня дошло, что такое юзы в дженту и как они работают, поэтому после того, как я собрал LFS, я его тут же снёс вместе с дебом и уже начал накатывать дженту. Дженту я накатывал несолько раз: сначала на ноуте с атомом n450, потом на десктопе. На десктопе дела шли на порядки быстрее, потому что там i7 5820k. Дальше я довольно долго разбирался в системе и затачивал её под себя. Многое приходилось делать в «чёрном» терминале.

И вот, в какой-то момент, когда я разобрался с «кишкками» системы, я занялся гуем. Когда дело дошло до эмулятора терминала, я полез искать легковескный и нашёл вариант urxvt, который умеет в прозрачность. Ты даже не представляешь, как я кайфанул, когда я настроил в нём прозрачность - глазам наоборот стало в разы комфортнее. Наверное, из-за того, что контрастность стала ниже: одно дело читать белый буквы на чёрном фоне, другое - белые буквы на «светлом» фоне.

Я всю эту телегу расписал к тому, что я достаточно посидел в «обычном» терминале и возвращаться к нему не хочу. Такие дела.

Кстати, имей в виду, что по скриншоту ты не сможешь оценить то, как эта прозрачность моём мониторе: мне на каждой машине приходится подкручивать прозрачность под кокретный монитор.

u5er ★★★
() автор топика
Ответ на: комментарий от u5er

Обои только ты упомянул ;)

Эээм… А как же твоё:

Ладно, это уже седьмой пост оффтопа в этой теме пошёл из-за обоев. Пожалуй подумаю над тем, чтоб в другой раз использовать стандартный непрозрачный xterm.

из-за обоев

?


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

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

Наверное, из-за того, что контрастность стала ниже: одно дело читать белый буквы на чёрном фоне, другое - белые буквы на «светлом» фоне.

Тоже, видимо, индивидуально. Я сколько пробовал низкий контраст, включая всякие модные zenburn’ы и подобное, серыми буквами на сером фоне, или с тем или иным оттенком — всегда это некомфортно для глаз в итоге было. Для меня идеал — это чёрный фон и светлые (не обязательно прям #ffffff, конечно, буквы), то есть реально высокий контраст.

Я всю эту телегу расписал к тому, что я достаточно посидел в «обычном» терминале и возвращаться к нему не хочу. Такие дела.

Это правильно. Главное, чтоб тебе нравилось. Но ты сам написал, что будешь «в другой раз использовать стандартный непрозрачный xterm». Я и подумал, что может оно в итоге и на пользу. Но если для тебя всё наоборот, то дело только твоё, конечно же.

CrX ★★★★★
()
Ответ на: комментарий от CrX

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

Я сколько пробовал низкий контраст, включая всякие модные zenburn’ы и подобное

Главное, чтоб тебе нравилось

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

Но ты сам написал, что будешь «в другой раз использовать стандартный непрозрачный xterm»

Я имел в виду при создании скриншотов. Чтоб некоторые особо впечатлительные особо не впечатлялись xD

Хотя я уверен, что даже если я так сделаю, то в следующий раз моветоном окажется что-нибудь ещё.

u5er ★★★
() автор топика
Ответ на: комментарий от u5er

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

Absolutely!

Я имел в виду при создании скриншотов. Чтоб некоторые особо впечатлительные особо не впечатлялись xD

А зачем тогда вообще публиковать? Нет уж, пусть впечатляются! :)

Хотя я уверен, что даже если я так сделаю, то в следующий раз моветоном окажется что-нибудь ещё.

Не, моветон на ЛОРе именно «тян на обоях», таков уж лор ЛОРа, как и то, что любые шрифты — ШГ (хоть для кого-то)

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 1)
Ответ на: комментарий от CrX

А зачем тогда вообще публиковать? Нет уж, пусть впечатляются! :)

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

любые шрифты — ШГ

Самое удивительное то, что пока я таких заявлений не видел под своими скринами. Возможно потому, что у меня исходное разрешение 4к и формат .png, который без потерь. Может про шг чаще пишут под теми скриншотами, которые в более низком разрешении да ещё в каком-нибудь .jpg, который с потерями и шакалит. А может ещё и потому, что всех основных флудерастов и ненужнистов забанили и начало выясняться, что и нынешняя трава вполне себе зелёная ;)

u5er ★★★
() автор топика
Ответ на: комментарий от u5er

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

Ну да, пожалуй, ты прав. Когда цель показать конкретную поделку, наверное лучше всего, когда остальное максимально нейтрально — не будет почём зря людей отвлекать.

Возможно потому, что у меня исходное разрешение 4к

Да, поэтому. Шрифты — такая штука, что чем больше размер шрифта, тем меньше всяких компромисов требуется при рендеринге. Там, где на мелком шрифте приходится делать выбор между радугой, мылом или лесенкой, в крупном шрифте при большом DPI можно вообще без сглаживания обойтись (то есть, с «лесенкой», которую не видно), и разницы не будет — настоящих пикселей хватит, без изврата. Ну а 4к, соответственно, позволяет сделать более крупные (в пикселях) шрифты.

и формат .png, который без потерь

Да у всех .png. Когда с потерями, про ШГ не пишут, пишут про шакалов. Потому что понятно, что по скриншоту в jpg понять, говно шрифты, или нет, невозможно.

CrX ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.