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)

Чрезвычайно интересный текст. Но мимокрокодил в моём лице не очень понял границу между эмулятором и эмулируемым.

Про сам хоббийный проект можно написать, что это вообще такое будет?

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

Да, было бы намного лучше ту фотку тоже запостить в галерею в качестве рабочего места. :) С рассказом, естественно.

hobbit ★★★★★
()
Последнее исправление: hobbit (всего исправлений: 2)
Ответ на: комментарий от LINUX-ORG-RU

Не, думаю, оно заслуживает отдельного рассказа.

Подтверждаю как есть.

hobbit ★★★★★
()

Вот это да, какой отличный проект. Все это крайне крайне интересно, касательно всех аспектов.

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

James_Holden ★★★★★
()

Интересно, не знал что есть qemu для esp32. А он полностью совместим с реальным устройством, не считая всякую периферию? Имею в виду эмулирует ли он ROM как на реальном устройстве и можно ли запускать реальную прошивку без изменений, или нужно специальную версию собирать

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

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

Имею в виду эмулирует ли он ROM как на реальном устройстве

Не уверен. Можешь начать копать отсюда.

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

можно ли запускать реальную прошивку без изменений

Я свою реальную прошивку запустил без изменений - она на скриншоте. Но правда для этого пришлось изменить исходники qemu :)

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

Обычный модем, обычная сотовая связь.

Эх, я уже думал что ты на аналог osmocom замахнулся. А зачем тогда нужен ESP? На встраиваемых модемах есть процессор, на котором можно запускать пользовательские задачи уровня опроса клавиатуры, индикации и работы с жиденькой переферией типа SPI флешки.

https://simcom.ee/documents/SIM800x/SIM800%20Series%20Embedded%20AT_Application%20Note_1.02.pdf

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

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

Про osmocom в курсе. Одно время даже интересовался им, но не смог разобраться, как его можно использовать.

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

Про osmocom в курсе. Одно время даже интересовался им, но не смог разобраться, как его можно использовать.

Когда-то давным-давно я показывал на osmocom студентам, как происходит соединение и отправка SMS в GSM сетях, там очень подробные логи. Кому-то даже было интересно. Еще лет 10 назад на его базе (а может быть и нет) разные организации разрабатывали всякие пико- и нано-BTS.

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

я показывал на osmocom студентам

Жалко, что я не был твоим студентом - с удовольствием бы посмотрел.

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

В каждом esp32 чипе есть большой ром с кодом который запечен в сам кристал, не на SPI флешке. Например WiFi стек находится там и большая часть sdk тоже вызывает функции из rom, это позволяет сильно сэкономить размер прошивки. Содержимое выкладывают как бинари тут. Эта версия qemu скорее всего тоже их содержит раз обычные прошивки работают без модификаций.

pftBest ★★★★
()
Ответ на: комментарий от s-warus

Можно, но пользоваться будет неудобно. Во-первых, из-за ширины экрана(на текущем экране длина строки - 22 символа), во-вторых - из-за клавиатуры. Не думаю, что с такой клавиатуры будет удобно вводить полноценные консольные команды или сидеть в консольном редакторе. Но чисто технически можно, да. Если не админить, а использовать для выполнения заранее определённых команд - самое то.

На самом деле, я думал про ssh как про средство для проброса портов и шифрования трафика, но сходу не осилил - там несколько RFC и в них надо вникать так основательно. А телнет запилить можно кабанчиком.

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

складная блютуз клава, я fdless модифицировал для чтения - просмотра книжек с андроид ssh клиента. 22 маловато.

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

22 маловато

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

Если для админить, то нужен форм-фактор нокия n900 или umpc по типу sony vgn-ux. Там и дисплей достаточно большой и клавиатуру можно организовать полноценную.

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

то нужен форм-фактор нокия n900 или umpc по типу sony vgn-ux

да ты прав, думаю тексто читалку проще на самом телефоне, можно ключь к десктопу внедрить (ушёл в туалет, телефон исчез комп залочился)

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

А задача-то какая?

Вот я пилю устройство, у которого должен быть конкретный функционал:

  1. Он должен работать с сотовой сетью - звонки, смс, ussd, телефонная книга (сделал на скорую руку, работает).
  2. В нём должен быть музыкальный проигрыватель (сделал на скорую руку, работает).
  3. В нём должна быть спутниковая навигация и карты (не реализовано).
  4. Возможность установить его на руль велосипеда и использовать в качестве велокомпьютера (начну заниматься после изготовления корпуса).

Как видишь, у меня есть чёткий список хотелок, которые я для себя задумал, оценив при этом свои силы. 1, 2 и 4 я смогу сделать 100%. 3 под вопросом. Такие дела.

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

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

Только «юзерспейс». Я использую esp-idf. Она использует очень много всего готового, но я в будущем возможно некоторые вещи реализую сам. Некоторые из любопытства, а некоторые из-за того, что штатный API мне не очень нравится.

Из того, что запилил я сам - это все драйвера для всей периферии, которая подключается к esp32, графическую библиотеку, «оконный» менеджер. Написал свой AT-клиент для общения с модемом. Запилил дисплейную подсистему, которая позволяет динамически добавлять графические дисплеи и полностью отвязать общение с железом от графического тулкита. Пока плат нет, то занимаюсь гуем и эмулятор мне в этом здорово помогает.

Дальнейшая разработка зависит от того, получится ли у меня подобрать такую матрицу, которая подключается по MIPI DSI или нет. Если нет, то в bare metal пока не полезу. Если да, то система переедет на esp32-p4 и тогда рискну написать свою реализацию RTOS. Чисто в качестве изучения того, как всё работает - потоки, семафоры, мьютексы, управление памятью и вот это вот всё.

На счёт «с чем-то частично совместима». Возможно, я буду пилить реализацию клиентов для различных прикладных протоколов. Например, VNC, irc и т.д.. Это считается за совместимость?

VNC, кстати, уже начерно реализовал - работает. Правда картинку 480x320 грузит секунды полторы xD Но оптимизацией пока заниматься не буду - есть более важные вещи.

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

я думал про ssh как про средство для проброса портов и шифрования трафика, но сходу не осилил

Я иногда чуть-чуть с esp32 играюсь по просьбе знакомых. Под неё есть ssh библиотека. Она, в общем, рабочая, хотя на тот момент когда я с ней игрался, там был баг, что там какой-то из буферов сделали слишком большой. Но с моей подачи это исправили.

Прикольный pet-проект у вас! Я лично esp32 для себя забраковал, т.к.:

  • ISA публично не доступно;
  • Без тяжелого огроменного SDK для esp32 ничего сделать нельзя;
  • А документация…

Для какого-то прототипирования или какую-нибудь поделку вполне нормально, но что-то серьёзное делать – крайне сомнительно.

тогда рискну написать свою реализацию RTOS

Успехов!

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

ssh библиотека

Неспортивное поведение. Одна из причин, почему я пишу всё сам - потому что хобби. Многие вещи, которые я написал сам, есть уже в готовом варианте, но какой в этом смысл? Если бы я делал устройство на заказ, то тогда можно было бы взять готовые библиотеки для «сокращения времени выхода на рынок», но это не мой случай (и не мой метод).

Для какого-то прототипирования или какую-нибудь поделку вполне нормально, но что-то серьёзное делать – крайне сомнительно.

Возможно, в будущем переползу на esp32-p4. Это микроконтроллер общего назначения с ядрами RISC-V. В документацию я пока не заглядывал, но он должен быть полностью открытым. Или я ошибаюсь?

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

Одна из причин, почему я пишу всё сам - потому что хобби.

Это замечательно, я не настаиваю. :^)

Или я ошибаюсь?

Надеюсь, что нет. Но наверняка сказать не могу.

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

esp32 - soc

на ядра думаю документы будут, а вот все остальное может быть тайной ;) Где-то с годик не смотрел, но примерно в то время проекты барметалл были ну в очень зачаточном состоянии. Если они все еще живы конечно

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

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

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

на ядра думаю документы будут, а вот все остальное может быть тайной

Ну вот на «обычный» esp32 (который не S*, не C* и т.д.) в референс мануале есть описание всей периферии за исключением блютуз и вафли. Может на них тоже есть, но в другом документе, хз. В P4 нет ни блютуза ни вафли + ядро более свободное, насколько я знаю, поэтому предположу, что в референс мануале на P4 будет всё.

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

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

зайди на эспрессифф, вполне честное описание

И правда! У меня просто есть ряд знакомых, которые в своих станках используют esp32 и утверждают, что это MCU.

И вот прям сейчас поискал «esp32 bare metal», многие на форумах уверены, что это MCU.

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

В P4 нет ни блютуза ни вафли + ядро более свободное, насколько я знаю, поэтому предположу, что в референс мануале на P4 будет всё.

Если будет успех (или не успех), делитесь!

Себе тоже заказал парочку ESP32-P4-POE-ETH поиграться.

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

Если будет успех (или не успех), делитесь!

Смотря в чём успех :) В успехе использования P4 как такового я не сомневаюсь вообще. А вот в успехе нахождения матрицы под MIPI DSI есть сомнения. Те, которые есть в продаже на самом деле не MIPI DSI - у них на обороте есть плата с конверторами интерфейсов. Вся суть от этого теряется. А те, у которых MIPI DSI заходит прям в саму матрицу, либо имеют слишком большую диагональ (более 5 дюймов), либо слишком большое разрешение(значительно больше 800x400). Плюс их хрен закажешь. Так что пока периодически сажусь искать, но ничего подходящего пока не нашёл. Радует то, что их популярность растёт, а значит появляются новые варианты.

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

https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4-function-ev-board/user_guide.html#user-guide-esp32-p4-function-ev-board-front

там и пример готовой матрицы на 7 дюймов с тачем

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

/me разводит руками

У меня слов нет. Одни эмоции.

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

MIPI DSI заходит прям в саму матрицу

5 дюймов

800x400

без(!) тача.

Если встретится что-нибудь такое, пингану.

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

у них на обороте есть плата с конверторами интерфейсов

Это как раз с таким конвертором? (Да, я понимаю, что нужно без него. Хочу понять как он выглядит.)

https://www.chipdip.ru/product/4.3inch-dsi-lcd-ips-displey-800x480-px-s-waveshare-9000791757

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

5и дюймовок 800х480 довольно много

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

У меня у самого на плате запаян преобразователь SPI->RGB16 в виде счётчика и пары сдвиговых регистров и я ищу способы от него избавиться. Менять шило на мыло такая себе идея.

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

Да, это с конвертором. Тот, который я ищу, у них шлейф идёт сразу в матрицу и никаких плат сзади матрицы нет. Выглядит это примерно вот так https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRHqoVCmFbGj6OwGH_0wgWAUtHVKywAItcqBg&s

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