Загрузчик🔗

Общие сведения и назначение🔗

Загрузчик предназначен для выполнения операций начальной инициализации аппаратуры SoC, конфигурирования памяти (таблица трансляции адресов MMU и размещение сегментов OCM) и загрузки образа прикладной программы из флешь памяти в OCM с последующей передачей ей управления.

На начальном этапе загрузчик производит низкоуровневую инициализацию (SCU, MMU, кэши L1 и L2 уровней), настройку режимов процессора (SPSR и SP) и выполняет код стартапа C/C++.

Затем управление передаётся функции main загрузчика, которая осуществляет ремап таблицы трансляции MMU, перемещение сегментов OCM и собственно загрузку образа прикладной программы из флешь памяти в OCM.

Начальный код загрузчика реализован на основе FSBL (First Stage Boot Loader) для Zynq-7000, который в свою очередь во многом базируется на референсном коде от ARM. Ниже приведено конспективное описание работы загрузчика.

Работа загрузчика состоит из нескольких этапов, которые подробнее описаны на соответствующих страницах:

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

Начальный старт и низкоуровневая инициализация🔗

Точка старта – адрес 0x00000000, на этот адрес управление передаёт BootROM после загрузки кода из внешней ПЗУ. На этом этапе производится низкоуровневая инициализация связанных с CPU устройств: кэшей данных и инструкций, MMU, предсказателя ветвлений, настройка указателей стека и т.п. Особенностью данной реализации является то, что кэши данных и инструкций не разрешаются перед передачей управления следующему этапу. Это сделано из-за того, что далее будет осуществляться загрузка (копирование) кода и данных основной части загрузчика DRAM, кэши для этого не нужны и даже мешают (более подробно описано на соответствующей странице).

Низкоуровневая инициализация подробно описана на странице Старт и низкоуровневая инициализация

Инициализация периферийных устройств и запуск основного загрузчика🔗

Эти действия выполняются в коде функции _start, управление которой передаёт код низкоуровневой инициализации. По сути это функция C/C++ стартапа, которая, как правило, осуществляет инициализацию указателя стека, статическую и динамическую инициализацию и передаёт управление функции main. В данном случае действия существенно отличаются от обычного сценария, т.к. эта функция помимо перечисленного выполняет копирование кода и данных основной части загрузчика в DRAM.

Описание стартапа приведено на странице С/C++ Startup.

Работа основной части загрузчика🔗

Код основной части загрузчика выполняет следующие действия:

  • перемещает таблицу трансляции MMU в старшие адреса OCM;
  • перемещает сегменты OCM из младших адресов в старшие;
  • конфигурирует PL;
  • загружает образ целевой программы в OCM;
  • передаёт управление целевой программе.

Подробно перечисленные действия описаны на странице Основной код загрузчика.

Заключение🔗

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