Как реализовать базовую функциональность ввода-вывода, как в x86, при написании ОС на ARM?

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

Я нашел отличный учебник по написанию ОС ARM: написание простого ядра ОС. Я прочитал большую его часть и знал, как использовать последовательный порт для вывода на терминал QEMU и изменения режима ЦП. Однако, по сравнению с обычным пониманием "Операционной системы" и других материалов о написании ОС на платформе x86, я обнаружил, что мало текста о том, как реализовать эти вещи в ARM.

Как вывести на настоящий "экран"?

Написание графического интерфейса - это действительно тяжелая работа, связанная со многими темами. Но в x86 у нас есть вызовы прерывания BIOS для вывода символов на экран. Я использую QEMU универсальный для моделирования устройства ARM. Теперь единственное, что я могу сделать, - это вывод или ввод в последовательный порт (UART) или через него и взаимодействие с ним через терминал моего собственного компьютера. Есть какой-либо способ сделать это?

Как принять ввод с устройств?

Обычная плата ARM имеет порты USB, которые можно подключить к клавиатуре. Я знаю, что клавиатурное событие вызовет прерывание. Как мне сделать это через USB на платформе ARM?

Как сделать файловую систему?

Поскольку практически никто не использует настоящий "жесткий диск" на устройствах ARM, поэтому я хотел бы выбрать SD-карту (MMC) в качестве элемента хранения в ОС. Я написал простой симулятор файловой системы, используя файл как диск. Итак, я знаю понятия в файловой системе. Но есть ли разница между файловой системой SD-карт и файловой системой обычных дисков?

Как загрузиться?

Я использую QEMU, который просто запускается с использованием определенного исполняемого имени файла. Кажется, он просто "загружает" весь исполняемый файл в память и начинает выполнять инструкции. Но в реальности загрузка - сложный процесс. Я искал в интернете и знаю загрузчик с именем uBoot. Но где я смущен, так это тем, что загрузчику также необходимо найти образ ядра из файлов, поэтому он должен иметь возможность доступа к файловым системам?

Как сделать программу?

Если бы я закончил все вещи выше. Теперь мою ОС можно использовать как игрушку. Но могу ли я написать код и скомпилировать их? Я использую кросс-компилятор на моем компьютере. Но нет компилятора, доступного для новой системы. Даже если я поместил в него больше программ, как я могу "загрузить" их в память так же, как в Unix exec делает?

Эти вопросы действительно смущают меня сейчас, и я не могу найти хорошего ответа или материала по этим темам. Так что мое нынешнее направление мышления неверно? Или написание на базе x86 лучше, если только для обучения?

Благодарю.

1 ответ

Решение

Как вывести на настоящий "экран"?

Зависит от того, какой тип экрана вы подключили, если у вас есть какая-то графическая карта, то вам нужна документация для этой карты (для чего-либо конкурентного на рынке, который обычно доступен у производителя карты под подписанным NDA), и напишите свой собственный драйвер в соответствии с ним, Чтобы создать полноценный графический драйвер, поддерживающий также некоторые сложные API, такие как OpenGL и подобные, ожидайте, что усилия по написанию собственного драйвера будут в течение нескольких лет.

Если у вас есть простой светодиодный дисплей или какой-либо чип, способный работать так же, как VGA, то вы, вероятно, можете обойтись без нескольких настроек управляющих регистров, отображая видеопамять устройства в адресное пространство памяти ЦП, а затем записывая биты /ASCII в это сопоставленная память.

BIOS x86 является наследием старых графических карт PC XT/AT, когда существует немного стандартов, таких как CGA -> EGA -> VGA, и производители довольно разумно соблюдают стандарты, чтобы использовать универсальные драйверы. Начиная с эпохи Windows, производителям проще предоставлять свои собственные драйверы с закрытым исходным кодом и создавать свои собственные HW любым удобным для них способом (но при этом поддерживая базовую функциональность, подобную VGA, доступной по устаревшим причинам / при загрузке - сегодня это не большая проблема с транзисторами. дешевы, поэтому добавление нескольких тысяч для эмуляции VGA возможно).

Как принять ввод с устройств?

Опять же, вам нужно написать первый USB-драйвер, который будет обрабатывать шину USB на стороне устройства ARM, а затем конкретному USB-устройству нужен собственный драйвер, а общее семейство устройств, таких как клавиатуры, универсально до такой степени, что один драйвер может обрабатывать ~ все они.

Как сделать файловую систему?

Опять же, есть какой-то картридер, вам нужны документы для этого ридера и посмотрите, как с ним работать, очень вероятно, что для доступа к карте у него будет какой-то блочный API-интерфейс, оттуда он должен быть в достаточной степени похож на любую другую работу блочного устройства. (если вы *NIX знакомы с тем, что я имею в виду под "блочным устройством", блоки данных похожи на сектора).

Но есть ли разница между файловой системой SD-карт и файловой системой обычных дисков?

Как создатель ОС вы сами можете решить, насколько вы будете отклоняться от общих схем вещей, но карты, как правило, имеют логические сектора (блоки), как старые жесткие диски, поэтому при хорошем дизайне драйверов, скрывающем любые детали за API "блоков", это будет то же самое для кода FS. Основное различие в драйверах флэш-дисков заключается в том, что они совместно с некоторыми файловыми системами обычно предоставляют дополнительные возможности, такие как обрезка свободного пространства для экономии при записи при удалении блоков.

Как загрузиться?

В реальном мире это зависит от платы и ее чипсета, от того, как она инициализирует процессор ARM, а также от того, запущена ли какая-либо прошивка и откуда. Вероятно, каждая плата будет иметь своего рода "BIOS" в некоторой памяти ПЗУ, которая будет что-то делать для поиска дополнительного пользовательского кода (загрузчика) в определенных местах (обычно на некоторых дисковых устройствах или с функцией сетевой загрузки).

Как сделать программу?

Даже если я поместил в нее больше программ, как я могу "загрузить" их в память так же, как это делает exix call exec?

Ну, это ответственность вашей ОС, чтобы обеспечить управление всеми этими процессами и предоставить определенный API для приложений. Если вы не хотите писать свой собственный компилятор, вы можете использовать некоторый открытый исходный код, такой как gcc/clang, но это означает, что вам придется реализовать большинство служб API *NIX OS. Не волнуйтесь, это не так сложно, например, ядро ​​GNU "Hurd" работает только 27 лет, и оно прекрасно складывается...


Серьезно, как показ одного человека, вы можете создать именно эту "игрушечную ОС" (если только вы не хотите тратить десятилетия на свой проект). Если вы хотите просто узнать что-то новое об архитектуре ОС и компьютерах, мне кажется, что вы находитесь в той точке, когда изучение источников linux и чтение нескольких книг по этой теме может дать вам гораздо больше за гораздо более короткое время.

Другие вопросы по тегам