На хабре время от времени появляются и, что печально, пропадают темы, посвященные созданию своих ОС. На самом деле написать ОС с нуля и описать весь процесс – далеко не самая легкая задача, особено если начать со своего загрузчика.
Но что если мы возьмем архитектуру, где не нужен загрузчик, и при некотором умении вообще не придется ни одной строчки писать на ассемблере?
Зачем? Для ARM существует несколько вполне успешных ОС от очень маленьких до современных версий Linux, и Windows RT (и Darwin конечно же, в лице iOS). Чтобы упростить себе задачу, мы ограничимся архитектурой ARMv6-M в лице ядра Cortex-M0 внутри процессора LPC1114.
Я думал было начать с AVR, но 8 бит – это как-то скучно, да и с ARM я несколько более сдружился за последние годы. В вопросе выбора профиля ARM (их есть три: Application, Real-time и Microcontroller) тоже вопросов не было – application слишком тяжеловесен, real-time – специфичен. Так что работаем с профилем микроконтроллеров. Тут тоже были варианты, но в конце концов я решил остановиться на минимальном – Cortex-M0, при необходимости потом можно будет нарастить мощности для этого эксперимента. Ну и выбрать конкретный процессор было уже просто – LPC1114 поставляется в варианте DIP-28 (жук с ножками), так что его можно легко купить и начать с ним работать без глубоких познаний в микроэлектронике.
Кстати, о железе. Было бы неплохо иметь под рукой следующие вещи: компьютер с GNU-шным ARM-тулчейном (llvm тоже подойдет), собственно сам процессор LPC1114, протоборду, несколько проводов, резисторов и светодиодов, а также самое главное – FTDI кабель (USB в UART) на 3.3V.
Что именно мы будем делать? Для начала помигаем светодиодами и подумаем, а зачем нам вообще какая-то ОС, если светодиоды и так прекрасно работают? Потом попробуем прочитать данные с какого-то датчика по I2C или SPI и убедимся, что ОС нам все еще не нужна. А дальше мы попробуем построить свой собственный маленький IPv6-стек поверх беспроводных сетей для устройств с низким энергопотреблением (я говорю о 6LoWPAN поверх 802.15.4) и поймем, что тут-то и пригодится механизм для регулирования процессов и независимого взаимодействия с устройствами, пока мы мигаем светодиодами.
Итак, посмотрим с чем нам предстоит работать
Cortex-M0 – это самая упрощенная реализация ARM-архитектуры, и, как результат, одна из самых экономных в плане энергопотребления, что позволяет использовать ARM вместо скучных AVR-ов и PIC-ов. При этом, у ARM куча отличных средств разработки, всяческие Web-IDE и пара высококачественных опенсорсных тулчейнов.
Cortex-M0 поддерживает немного урезанный набор инструкций Thumb и несколько инструкций из Thumb-2, или всего 56 инструкций в целом, так что необходимые знания ассемблера можно подтянуть за вечер.
Механизма управления памятью (MMU или более упрощенный вариант – MPU) в ядре нет, так что у нас будет такой себе process party, когда каждый процесс может рулить системой. Ну да и ладно, зато кода меньше!
Что же есть? Достаточно гибкий механизм прерываний, поддержка разной перифирии, возможность собрать тестовую плату на коленке.
Но как же без ассемблера?
Поскольку непосредственный участник событий (LPC1114) приедет ко мне на почту только завтра, сегодня я расскажу о том, как современные ARM-ы загружаются. Раньше этот процесс был несколько прямолинейнее, процессор просто считывал инструкцию по адресу 0x00000000, где должна была бы оказаться флеш-память, и первой же инструкцией перепрыгивал бы куда-то глубже в тело загрузчика, так как дальше по адресам были переходы от разных прерываний. Загрузчику приходилось инициализировать такую базовую вещь как оперативную память (тогда она была преимущественно внешней), и только потом, настроив память и указатель на стек, можно было отправляться в мир C.
Сейчас все стало как-то существенно проще. Значение по адресу 0x00000000 считывется и записывается непосредственно в SP (Stack Pointer – регистр, указывающий на верхушку стека). Потом процессор считывает адрес из 0x00000004, где находится Reset Vector (в котором записано, куда переходить в случае сброса), и начинает выполнять команды по этому адресу. Учитывая что стек настроен, можно отправляться прямиком в main(). Чтобы еще больше упростить жизнь разработчикам, ARM разработали стандарт CMSIS – Cortex Microcontroller Software Interface Standard. В него входит набор функций и макросов, с помощью которых писать ассемблерные вставки не прийдется, да и инициализацию системы проводить не надо будет.
На сегодня все, в следующий раз я покажу как собрать минимально рабочую схему, помигать светодиодом и задуматься о задачах «системного» уровня.
Автор: farcaller