Поиск по сайту:

Перенос операционных систем на новые архитектуры чипов


Чему научились сопровождающие RT-Thread при переносе операционной системы встраиваемых систем на различные архитектуры чипов.

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

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

Чтобы заставить процессор отправлять сигналы на жесткий диск для записи данных или на монитор для отображения изображения, он должен получить инструкции. Эти инструкции представлены в форме «кода», который представляет собой краткий способ сказать, что кто-то должен написать программу, которая «говорит» на том же языке, что и процессор. ЦП понимает машинный язык — практически непонятный массив битов, который большинство людей не удосуживаются записать вручную. Вместо этого мы используем такие языки программирования, как C, C++, Java, Python и т. д. Эти языки анализируются и компилируются в машинный язык, который передается в ЦП.

Если вы попытаетесь дать инструкции процессору на языке, который он не понимает, процессор не будет знать, что делать. Вы можете испытать довольно не впечатляющие результаты такой попытки недопонимания, попытавшись загрузить Raspberry Pi из образа RHEL x86_64. Было бы здорово, если бы это сработало, но это не так.

Портирование ОС на новую архитектуру

Проект RT-Thread предлагает операционную систему (ОС) с открытым исходным кодом для программистов встраиваемых систем. Встроенное пространство чрезвычайно разнообразно: здесь имеется множество устройств Интернета вещей (IoT), специализированных промышленных устройств и устройств для любителей. Цель RT-Thread — сделать программирование встраиваемых систем простым для всех, независимо от того, какое устройство вы используете. Иногда это означает перенос ОС на новую архитектуру, будь то чип той же архитектуры, но с немного другим набором команд, или вообще новую архитектуру.

Поначалу подход к этой проблеме может показаться немного пугающим — вы можете не знать, с чего и как начать. В этой статье собраны уроки, которые извлекли сопровождающие RT-Thread, когда мы портировали RTOS на новые архитектуры чипов.

Что нужно знать перед началом

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

  1. Подготовьте среду выполнения на языке C.
  2. Убедитесь, что символы можно отправлять и получать через последовательный порт.
  3. Убедитесь, что код переключения контекста работает.
  4. Получите поддержку аппаратных таймеров
  5. Убедитесь, что программа обработки прерываний может получать и анализировать данные через последовательный порт.

Модель исполнения

В большинстве продвинутых архитектур ОС и пользовательские приложения работают с разными уровнями привилегий. Это предотвращает влияние неисправного кода на интеграцию и безопасность ОС. Например, в архитектуре ARMv7-A ОС обычно работает в системном режиме, а в ARMv8-A ОС может работать на уровне привилегий EL2 или EL3.

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

1. Выполнить код C

Ключевым действием на этом этапе является установка нуля в разделе начального символа блока (.bss) и настройка указателей стека.

В реализациях на языке C неинициализированные глобальные переменные и статические переменные обычно хранятся в разделе .bss, который не занимает места на устройстве хранения. Когда программа загружается, соответствующее пространство выделяется в памяти и инициализируется нулем. Когда ОС загружается, она должна выполнить эту работу сама.

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

2. Используйте хотя бы один последовательный диск.

RT-Thread выводит информацию и регистрирует ее через последовательный порт, что также помогает отлаживать код в процессе трансплантации. На этом этапе получение данных через последовательные порты не требуется. Мы поняли, что находимся на правильном пути, когда впервые увидели наш дружелюбный, знакомый логотип RT-Thread над последовательным портом!

3. Подтвердите логику переключения контекста.

Контекст задачи — это вся среда ее выполнения, которая содержит общие регистры, программный счетчик, расположение кадра стека и т. д. Когда создается новый поток, RT-Thread должен вручную выделить и настроить его контекст, чтобы планировщик мог переключиться на новый поток, как и в случае с другими.

Есть три вещи, на которые следует обратить внимание:

  • Во-первых, при запуске RT-Thread прерывания по умолчанию отключены. Они включаются при первом включении планировщика задач; этот процесс реализуется на языке ассемблера в период переключения контекста.
  • Во-вторых, следующее планирование начнется при выходе потока, то есть когда принадлежащие ему ресурсы будут возвращены простаивающему потоку.
  • В-третьих, порядок помещения данных в стек должен соответствовать порядку извлечения данных из стека.

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

4. Установите таймер

RT-Thread требует таймера для периодической генерации прерываний; это используется для подсчета тиков, прошедших с момента запуска системы. Номер тика используется для обеспечения функций программного прерывания и указания ядру, когда начинать планирование задачи.

Установка значения интервала времени может оказаться непростой задачей. Обычно это от 10 мс до 1 мс. Если вы выберете небольшой интервал времени на медленном процессоре, большая часть времени будет потрачена на переключение задач — в ущерб выполнению чего-либо еще.

5. Убедитесь, что последовательный порт работает правильно.

На этом этапе мы взаимодействовали с RT-Thread msh через последовательный порт. Мы отправляли команды, нажимали Enter и наблюдали, как msh выполняет команду и отображает результаты.

Этот процесс обычно нетрудно осуществить. Однако небольшое предупреждение: не забудьте очистить флаг прерывания на некоторых платформах после обработки прерывания последовательного порта.

Как только последовательный порт заработает правильно, процесс портирования практически завершен!

Быть занятым

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

Если у вас нет проекта, который нужно перенести на новый чип, присоединяйтесь к нам; проекту RT-Thread всегда может понадобиться помощь в портировании ОСРВ на новые чипы! Будучи проектом с открытым исходным кодом, RT-Thread меняет ландшафт встраиваемого программирования с открытым исходным кодом. Пожалуйста, представьтесь и обратитесь за помощью в Клуб RT-Thread!

Эта статья основана на статье «Как перенести операционную систему на другую архитектуру чипа?» сообщества разработчиков и переиздается с разрешения.