ZX Murmulator - одноплатный ультрадешевый микрокомпьютер на основе платы Raspberry Pi Pico (далее "пика"), которая, в свою очередь, основана на микроконтроллере - RP2040.

RP2040 - одна из наиболее известных двухъядерных реализаций ARM Cortex-M0+ с 264 КБ встроенной SRAM памяти и от 2-ух до 16-ти МБ flash-памяти подключаемых по QSPI интерфейсу, распаянной на плате пики. Данный микроконтроллер легко гонится до 400 МГц без какого либо радиатора, не смотря на свои штатные 133. Что позволяет запускать на нём достаточно прожорливые задачи.

Это скорость чипа RP2040 378 MHz с эмуляцией FPU, тест запущен под Murmulator OS.
Это скорость чипа RP2040 378 MHz с эмуляцией FPU, тест запущен под Murmulator OS.

В предыдущей статье (https://habr.com/ru/articles/839960/) я упомянул, что для Мурмулятора в настоящее время разрабатывается собственная операционная система. Возникает вопрос - зачем микрокомпьютеру с 264 КБ памяти вообще понадобилась ОС?

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

На самом деле, почти все прикладные задачи Мурмулятора можно решать без всякой ОС - достаточно установить бут-лоадер (см. https://github.com/xrip/pico-launcher), который позволит управлять прошивками, загружая их с SD-карточки. Основной недостаток бут-лоадера - невозможность редактирования конфиг-файлов эмуляторов легко решается путём его дописывания. Но если понадобится что-то ещё? Можно на каждый чих писать отдельную прошивку, или модифицировать существующую. Т.е. Murmulator OS (далее - просто МОС) должна решить эту проблему - дать более гибкий способ расширения функциональности.

Что ещё полезного может предоставить операционная система? - Унификация доступа к оборудованию. В настоящее время, каждая отдельная прошивка содержит все необходимые для функционирования приложения драйвера устройств, т.е. на лицо явная избыточность. Если ОС будет содержать все нужные драйвера, то приложение сможет сконцентрироваться только на своей функциональности, а остальное запрашивать у ОС.

Ещё одним дополнительным профитом наличия для устройства какой-то ОС является возможность использования данного устройства для обучения детей основным концепциям информатики. А учитывая, что изначально Мурмулятор - платформа игровая, для которой существует множество эмуляторов ретро-компьютеров, то можно познакомить детвору и с историей развития вычислительной техники, показать игры 80-ых и начала 90-ых годов прошлого века различных платформ, стран и концепций.

Не стоит также забывать, что Мурмулятор - ультрабюджетное решение, т.е. позволить себе такое устройство может практически кто угодно. Добыть PS/2 клавиатуру и VGA-монитор - в наше время тоже задача крайне бюджетная. Т.е. в этаком "offline-режиме", ребёнку необходимо будет только где-то заполучить файлы прошивок (эмуляторы) и ретро-игры к ним. Думаю, что наши бизнесмены, что продают готовые мурмуляторы, вполне могут предоставлять их с SD-карточкой, на которой уже будет записана вся коллекция. Ну, это уже не относится к самой ОС.

Когда я только задумался о написании ОС к Мурмулятору, была мысль, что можно создавать целые компьютерные классы мурмуляторов, но просмотрев (по-диагонали) программу обучения информатике в школе, понял - поздно, т.к. оно уже никому не нужно, там учат окошки по десктопу таскать и в экселе таблички править. Ну, может, программа ещё изменится, и основы таки начнут преподавать. Или оно пригодится в ретро-компьютерных клубах. А есть такие? Если нет - дарю бизнес-идею ))

Вернёмся к самой ОС. Выбирая ядро для будущей ОС, я перелопатил кучу уже готового кода, в котором меня что-то да не устраивало. Ближе всего к требуемым параметрам оказалась FreeRTOS (https://github.com/FreeRTOS/FreeRTOS-Community-Supported-Demos/tree/3d475bddf7ac8af425da67cdaa2485e90a57a881/CORTEX_M0%2B_RP2040), единственным недостатком которой является её достоинство - она очень простая и при этом крайне несамодостаточная. Т.е. нельзя скачать где-то дистрибутив данной ОС под RP2040 и поставить на какое-то оборудование, пусть даже несовместимое с Мурмулятором. FreeRTOS, в данном случае - встраиваемое решение, т.е. если вам понадобилась многозадачность, то она вам её обеспечит, но вот с файловыми операциями, драйверами клавиатуры, видео-подсистемы, звука и любого чиха - это всё на вас.

Зачем вообще мне понадобилась многозадачность? Вон, древние MS DOS или Windows 3.1 вполне без неё обходились, и ничего. Тут очень сложно пояснить человеку, который никогда не писал программы под ОС с добровольной многозадачностью. Скажу кратко - это крайне утомительно и крайне ненадёжно. Нет никакой гарантии, что твоя программа получит доступ к ресурсу вовремя. Т.е. тебе бы в буфер саундкарты что-то записать надо, но нет - программа форматирования дискеты в это время заняла все ресурсы и не отдаёт, а саундкарта в это время выводит одну ноту, т.к. новой нотой её никто не снабдил. В общем, я выбрал себе ядро будущей ОС, и принялся активно обшивать его драйверами доступных устройств.

Ещё пару слов надо сказать про ARM Cortex M0+ - это ядро не имеет полноценного MMU - только примитивный MPU и малополезный для нас, в данном случае, XIP. Т.е. о виртуальной памяти можно сразу забыть. Попытка её построить на одном MPU приведёт к таким тормозам, что можно просто установить эмулятор IBM PC XT и получить аналогичную производительность.

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

Переписывать линковщик - задача явно не моего уровня (или потребует несоразмерного времени), поэтому было принято решение от него избавиться. Совсем. Возможно, в будущем, я напишу линковщик под МОС, как и компилятор под неё, и всё остальное... но пока-то его нет (подходящего). Соответственно, результатом компиляции программы в объектный файл на данном этапе мы и удовлетворимся. Теперь задача ОС - расположить где-то в свободной памяти код из объектника, разрезолвить адреса и передать управление функции main.

Возникает вопрос - а как программа будет обращаться к API самой ОС? Ну, поскольку ОС - обычная .uf2 прошивка, в которой адреса функций таки можно прибить гвоздями к определённым адресам, задав их в .ld файле, проблемы как-бы и нет, но это крайне громоздкое и неудобное решение - прописывать для каждой функции АПИ её адрес. Лучше сделать таблицу адресов функций (указателей на них), её начало прибить к определённому адресу, а наполнение пусть сам линкер резолвит.

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

#define M_OS_API_SYS_TABLE_BASE ((void*)(0x10000000ul + (16 << 20) - (4 << 10)))
static const unsigned long * const _sys_table_ptrs = (const unsigned long * const)M_OS_API_SYS_TABLE_BASE;

inline static int kill(uint32_t task_n) {
typedef int (*fn_ptr_t)(uint32_t);
return ((fn_ptr_t)_sys_table_ptrs[244])(task_n);
}

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

Надо заметить, что из-за особенностей Cortex-M0+ все приложения МОС будут разделять общую память, а это обозначает снижение надёжности всей системы. К сожалению, я так и не придумал хорошего решения данной проблемы. Может быть, позже я к этому вернусь и попробую задействовать существующий в процессоре MPU для недопущения обращения к "чужой" памяти, но пока этой функциональности просто нет, и при разработке программ это необходимо учитывать.

Также необходимо учитывать, что если какая-то программа совершит нечто "запрещённое", что приведёт к HardFault ядра процессора, то никакая FreeRTOS тут уже не поможет - ядро остановится - т.е. повиснет. У меня имеются ряд идей по перехвату HardFault и дальнейшему удалению контекста задачи, но это также пока не реализовано.

Аналог SIGKILL для задач тоже пока не реализован, вместо этого имеется аналог SIGTERM, что предполагает обработку данного сигнала самой программой (для этого имеется предопределённый хэндлер "signal", на который и надо вешать логику выхода из задачи).

Есть вероятность, что с выходом Raspberry Pi Pico 2, на чипе RP2350 (2 x ARM Cortex-M33) все проблемы можно будет решить штатной виртуализацией, и этот кусок реализации ОС придётся выкинуть. Но это уже будет другой Мурмулятор (2.0?)...

Исходники МОС можно изучать тут: https://github.com/DnCraptor/murmulator-os

Чуть позже выложу ещё статью про МОС с точки зрения пользователя.

MOS воспроизводит .wav-файл
MOS воспроизводит .wav-файл
Murmulator Commander под MOS
Murmulator Commander под MOS

Комментарии (20)


  1. lumag
    31.08.2024 07:13
    +3

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

    Есть подход под названием ELF FDPIC. Это стандартный ELF, просто слинкованный не совсем стандартным образом. Весь код остается не зависящим от адреса загqрузки, вся зависимость от адреса загрузки уходит в PLT. В итоге сегмент кода так и остается read only и может шариться между задачами на MMU-less системах.


    1. mikeveng73 Автор
      31.08.2024 07:13

      Сборка с флагом -fPIC у меня не прошла. Не смог я подобрать правильные ключики...


      1. lumag
        31.08.2024 07:13
        +3

        -mfdpic, а не просто -fPIC.


        1. mikeveng73 Автор
          31.08.2024 07:13

          спасибо, попробую. интересно даже, что получится )


  1. lumag
    31.08.2024 07:13
    +1

    Еще, было бы интересно узнать, чем ZephyrOS не понравилась


    1. mikeveng73 Автор
      31.08.2024 07:13

      А к ней есть порт под RP2040?


      1. lumag
        31.08.2024 07:13

        1. mikeveng73 Автор
          31.08.2024 07:13

          спасибо, почитаю, поизучаю. эту штуку я в своё время пропустил.


        1. mikeveng73 Автор
          31.08.2024 07:13

          просмотрел доку по-быстрому. пока принципиальных отличий от FreeRTOS не нашёл.


  1. mafia8
    31.08.2024 07:13

    Добыть PS/2 клавиатуру...

    В одном сетевом магазине:

    Bluetooth (193), PS/2 (4) USB (539)


    1. mikeveng73 Автор
      31.08.2024 07:13

      пока хватает в продаже (даже новых), не смотря на то, что предложение по USB доминирует
      пока хватает в продаже (даже новых), не смотря на то, что предложение по USB доминирует


  1. Indemsys
    31.08.2024 07:13

    Плату с микронтроллером сделать гораздо легче чем фреймворк с осью, middleware и драйверами. Поэтому по уму выбирают сначала ось с фреймворком, а потом берут то железо под которое она портировна. Так проще и быстрее.
    Под Raspberry Pi Pico пока не видно нигде полноценных фреймворков.


    1. mikeveng73 Автор
      31.08.2024 07:13

      Ну, тут задача была обратная - аппаратура уже есть, а ОСи - нет )


      1. Indemsys
        31.08.2024 07:13

        Не, ошибся.
        Там оказывается все есть в виде Raspberry Pi Pico SDK. Там же и RTOS, WiFi, BLE, USB.
        Единственно нет графического движка.
        Но сам чип слабый, даже RP2350 будет все еще сильно слабее лидеров от ST, Renesas, NXP.


        1. mikeveng73 Автор
          31.08.2024 07:13

          Ну, он сильно бюджетный. А RP2350/54 - ждём. Пока в доступных точках их нет. Не из Британии же заказывать ))


        1. mikeveng73 Автор
          31.08.2024 07:13

          Кстати, под винду есть удобный инсталлер: https://github.com/raspberrypi/pico-setup-windows/releases (но требует Win10 или выше).


  1. ABy
    31.08.2024 07:13

    "Ничего не понял, но очень интересно"

    Вот, допустим, пилю я портативку на rp2040 с spi экранчиком 128х128. Смогу я этот мурмулятор использовать в своем проекте?


    1. mikeveng73 Автор
      31.08.2024 07:13

      Мурмулятор ОС пока не поддерживает экраны-матрицы, а вот в pico-launcher можно подсмотреть управление матрицей 240*320 ST7789 по i2c. Исходники тут: https://github.com/xrip/pico-launcher/tree/main/drivers/st7789, там рядом есть ещё поддержка ws2812.


  1. EvilTeacher
    31.08.2024 07:13

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


    1. mikeveng73 Автор
      31.08.2024 07:13

      Это не другая идеология, а общая база для всех ОС. Командной строке надо учить всех, а не одних задротов, иначе мы никогда не выберемся из "поколения-ЕГ".