Загрузчик U-Boot

Данный документ описывает особенности работы загрузчика U-Boot для модулей на базе СнК 1892ВМ14Я (далее MCom-02):

  • Салют-ЭЛ24Д1 r1.3;

  • Салют-ЭЛ24Д1 r1.4;

  • Салют-ЭЛ24Д1 r1.5;

  • Салют-ЭЛ24Д1 r1.5 с установленным навигационным радиомодулем RF2Chan v2;

  • Салют-ЭЛ24Д2 r1.1;

  • Салют-ЭЛ24ОМ1 r1.1 с установленным Салют-ЭЛ24ПМ1 r1.1, r1.2;

  • Салют-ЭЛ24ОМ1 r1.2 с установленным Салют-ЭЛ24ПМ1 r1.2, Салют-ЭЛ24ПМ2 r1.0, r1.1, r1.2.

Особенности загрузчика:

  • начальная инициализация аппаратуры;

  • загрузка Device Tree Blob (DTB) и образа Linux с SD/MMC/USB/NAND-носителя [1], по TFTP;

  • загрузка baremetal приложений из SPI флеш-памяти или с SD/MMC/USB/NAND-носителя;

  • поддержка схемы загрузки Linux Distro (extlinux.conf);

  • инициализация контроллеров памяти DDR;

  • поддержка переменных окружения;

  • поддержка монитора U-Boot по терминалу UART;

  • поддержка сторожевого таймера;

  • поддержка программной перезагрузки;

  • поддержка GPIO;

  • поддержка I2C;

  • поддержка USB на встроенном контроллере USBIC в режиме Host/Device [2];

  • поддержка MMC;

  • поддержка SPI флеш-памяти;

  • поддержка NAND флеш-памяти [3];

  • поддержка Ethernet;

  • поддержка файловых систем FAT, ext2, ext4 (только чтение), UBIFS;

  • поддержка заводских настроек;

  • вывод статуса последнего сброса микросхемы.

Загрузчик реализует обходы для следующих ограничений согласно документу «Микросхема интегральная 1892ВМ14Я. Перечень выявленных ограничений»:

  • #867;

  • #971;

  • #972;

  • #1160;

  • #1969;

  • #3346.

Сборка загрузчика

Исходные коды

Имена файлов и директорий указаны относительно корневой директории исходных кодов загрузчика.

Описание общей структуры исходных кодов доступно в файле README.

Список файлов для поддержки модулей на базе MCom-02:

  • Файлы начальной инициализации:

    • arch/arm/cpu/armv7/mcom/*.c

    • arch/arm/cpu/armv7/mcom/*.S

    • arch/arm/include/asm/arch-mcom/*.h

    • board/elvees/common/*.c

    • board/elvees/salute*/*.c

  • Файлы Device Tree Source (DTS):

    • arch/arm/dts/mcom02*.dts

    • arch/arm/dts/mcom02*.dtsi

  • Файлы конфигурации Kconfig:

    • arch/arm/cpu/armv7/mcom/Kconfig

    • board/elvees/**/Kconfig

    • configs/salute*_defconfig

  • Файлы конфигурации для поддерживаемых модулей:

    • include/configs/mcom.h

Конфигурация

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

Дополнительные параметры конфигурации для модулей на базе MCom-02:

  • DDR_CALIBRATION

    Включение режима калибровки памяти DDR.

    Значение по умолчанию: не задано.

  • DDR_CALIBRATION_DDRMC_ID

    Номер контроллера DDR для режима калибровки.

    Значение по умолчанию: 0.

  • HW_WATCHDOG

    Включение аппаратного сторожевого таймера.

    Значение по умолчанию: не задано.

  • BOOT_ELF_FROM_SPI

    Включение загрузки ELF-файла из SPI флеш-памяти.

    Значение по умолчанию: не задано.

Сборка

Результатом сборки исходных кодов загрузчика является образ u-boot.mcom, предназначенный для прошивки SPI флеш-памяти модуля или записи на SD/MMC-карту. Образ доступен в корневой директории загрузчика после завершения сборки.

Для сборки загрузчика на ПК должно быть установлено следующее программное обеспечение:

  • arm-linux-gnueabi toolchain для кросс-компиляции;

Переменные окружения, влияющие на сборку загрузчика:

  • ARCH — целевая архитектура;

  • CROSS_COMPILE — префикс кросс-компилятора;

  • DEVICE_TREE — имя файла DTS (без расширения) для целевого модуля;

  • PATH — пути для поиска используемых приложений.

Соответствие модулей, конфигураций и имён DTS файлов приведено в таблице Таблица 6.

Таблица 6 Конфигурации и DTS файлы для модулей Салют-ЭЛ24

Модуль

Конфигурация

DTS

Салют-ЭЛ24Д1 r1.3

saluted1_defconfig

mcom02-saluteel24d1-r1.3

Салют-ЭЛ24Д1 r1.4

saluted1_defconfig

mcom02-saluteel24d1-r1.4

Салют-ЭЛ24Д1 r1.5

saluted1_defconfig

mcom02-saluteel24d1-r1.5

Салют-ЭЛ24Д2 r1.1

saluted2_defconfig

mcom02-saluteel24d2-r1.1

Салют-ЭЛ24ПМ1 с ОМ1

salutepm_defconfig

mcom02-saluteel24pm1-r1.1-1.2-om1-r1.1-1.2

Салют-ЭЛ24ПМ2 с ОМ1

salutepm_defconfig

mcom02-saluteel24pm2-r1.0-1.1-om1-r1.2

Пример сборки загрузчика для модулей Салют-ЭЛ24ПМ2 r1.0, r1.1, r1.2:

export PATH=$PATH:<path-to-toolchain-from-buildroot-output-host-bin-dir>
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
export DEVICE_TREE=mcom02-saluteel24pm2-r1.0-1.1-om1-r1.2
make salutepm_defconfig
make

Примечание

Глава Сборка в «родной» ОС (native) содержит опциональные команды для сборки образов U-Boot всех поддерживаемых модулей.

Состав образа

Образ загрузчика u-boot.mcom состоит из образа U-Boot, прикрепленного к образу U-Boot SPL. Образ U-Boot включает DTB для настройки устройств и передачи в Linux.

Образы U-Boot SPL и U-Boot имеют формат uImage и создаются приложением tools/mkimage, входящим в состав загрузчика.

Для обхода ограничения #867 в заголовке образа U-Boot SPL значению поля Target Operating System присваивается значение U-Boot.

Для обхода ограничения #3346 размер образа U-Boot SPL выравнивается до ближайшего четного значения.

Схема разбиения образа u-boot.mcom представлена в таблице Таблица 7.

Таблица 7 Схема разбиения образа загрузчика

Область

Смещение (КБ)

Максимальный размер (КБ)

Образ U-Boot SPL

0

56

Переменные окружения [4]

64

64

Образ U-Boot

128

Запуск загрузчика

Обзор загрузки

При включении питания модуля выполняется:

  1. Первичный загрузчик BootROM копирует U-Boot Secondary Program Loader (U-Boot SPL) из SPI флеш-памяти или с SD/MMC-карты во внутреннюю память RAM и передает ему управление. Источник копирования определяется значением регистра BOOT контроллера SMCTR СнК 1892ВМ14Я.

  2. U-Boot SPL копирует основной загрузчик (U-Boot) из SPI флеш-памяти или с SD/MMC-карты в память DDR и передает ему управление. Источник копирования определяется значением регистра BOOT контроллера SMCTR СнК 1892ВМ14Я. Подробнее см Инициализация U-Boot SPL.

  3. U-Boot выполняет:

    1. Чтение заводских настроек в соответствии с документом Заводские настройки. Подробнее см. описание переменных окружения factory_eth_mac и factory_serial.

    2. Выключение контроллера DDR, заданного переменной ddrctl_cid, если значение переменной ddrctl_cmd установлено в disable. По умолчанию выключается контроллер DDR1 для модулей Салют-ЭЛ24Д1 и Салют-ЭЛ24Д2.

    3. Исполнение сценария, заданного переменной окружения bootcmd. Выполнение сценария может быть прервано отсылкой любого символа в терминал UART модуля. В этом случае запускается монитор U-Boot для выполнения команд загрузчика (подробнее см. Команды).

Инициализация U-Boot SPL

При инициализации U-Boot SPL выполняется:

  • включение L1-кэша инструкций для CPU0, CPU1 (L1-кэш данных включается для CPU0 в основном загрузчике);

  • минимальная начальная настройка аппаратуры (см. функцию board_init_f() в файле arch/arm/cpu/armv7/mcom/board.c):

    • выключение ядра CPU1 (подробнее см. Передача управления из U-Boot в baremetal-приложение);

    • выключение DDR retention (ограничение #1160);

    • запись адреса функции холодного сброса BootROM в регистр ALWAYS_MISC0;

    • включение сторожевого таймера, если задано конфигурацией;

    • включение отображения загрузочных областей по умолчанию (ограничение #971);

    • включение конфигурации по умолчанию для коммутатора Accelerator Coherency Port (ограничение #972);

    • настройка APLL, CPLL и SPLL;

    • настройка терминала UART0;

    • включение питания модулей памяти DDR0 и DDR1 (для модулей Салют-ЭЛ24ПМ);

    • настройка контроллеров памяти DDR0 и DDR1;

    • настройка контроллеров SDMMC0 и SDMMC1 (включение резистивных подтяжек и т.д.);

  • загрузка U-Boot (см. функцию board_init_r() в файле common/spl/spl.c):

    • загрузка драйвера GPIO;

    • загрузка драйвера SPI для контроллера SPI0;

    • загрузка драйвера SPI флеш-памяти;

    • загрузка драйвера контроллерa SDMMC;

    • загрузка драйвера контроллера USBIC;

    • копирование из SPI флеш-памяти или с SD/MMC-карты в память DDR основного загрузчика;

    • передача управления основному загрузчику.

Карта распределения ОЗУ

После запуска загрузчик располагается в верхней области памяти, подключенной к контроллеру DDR0. Свободные области DDR0/DDR1 могут использоваться для загрузки Linux и автономных приложений.

Расположение загрузчика в памяти для поддерживаемых модулей на базе MCom-02 показано в таблице Таблица 8.

Таблица 8 Карта распределения ОЗУ

Область

Начальный адрес

Конечный адрес

Свободная память

0x40000000

0x7EFFFFFF

U-Boot [5]

0x7F000000

0x7FFFFFFF

Свободная память

0xA0000000

0xDFFFFFFF

Подробную информацию об использовании памяти загрузчиком можно получить с помощью команды монитора bdinfo.

Переменные окружения

Загрузчик поддерживает возможность настройки через переменные окружения.

Во время запуска загрузчик выполняет поиск переменных окружения, сохраненных в SPI флеш-памяти:

  • при успешном обнаружении устанавливаются переменные окружения, сохраненные в SPI флеш-памяти;

  • в случае ошибки устанавливаются переменные окружения, заданные по умолчанию.

Переменные окружения загрузчика, заданные по умолчанию (см. файл include/configs/mcom.h):

ddrctl_cmd

Команда управления контроллерами DDR.

Значение по умолчанию: disable.

ddrctl_cid

Номер контроллера DDR для команды ddrctl_cmd.

Значение по умолчанию: 1.

bootcmd

Последовательность действий, выполняемых при команде boot.

Значение по умолчанию соответствует последовательности действий, описанной ниже.

Если загрузчик собран с включенной опцией BOOT_ELF_FROM_SPI, то выполняется:

  1. Копирование ELF-файла приложения из SPI флеш-памяти в ОЗУ. Источник размещения в SPI флеш-памяти определяется переменными окружения bootelf_elfsize, bootelf_spibus, bootelf_spioffset. Адрес в ОЗУ определяется переменной bootelf_addr.

  2. Передача управления в скопированный ELF-файл.

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

Если команда завершилась неуспешно, загрузчик переходит к выполнению следующей команды из списка boot_targets.

Последовательность действий, выполняемая при загрузке Linux c использованием схемы Distro:

  1. Поиск файла /boot/extlinux/extlinux.conf на разделе носителя.

  2. Чтение и обработка опций, заданных в extlinux.conf.

  3. Копирование образа Linux, файла DTB в ОЗУ, параметров ядра.

  4. Обновление свойств DTB (например, запись ethaddr и serial# в соответствующие поля DTB).

  5. Запуск образа Linux с помощью команды sysboot.

boot_targets

Последовательность команд загрузки Linux (подробнее см. bootcmd).

Значение по умолчанию: mmc1 mmc0 usb0 ubifs0.

bootelf_addr

Адрес памяти ОЗУ для загрузки ELF-файла.

Значение по умолчанию: 0x50000000.

bootelf_elfsize

Размер ELF-файла в байтах.

Значение по умолчанию: 0x200000.

bootelf_spibus

Номер шины SPI к которой подключен чип SPI флеш-памяти.

Значение по умолчанию: 0.

bootelf_spioffset

Смещение ELF-файла в SPI флеш-памяти в байтах.

Значение по умолчанию: 0x100000.

ethaddr

MAC-адрес контроллера Ethernet. При наличии переменной, U-Boot использует указанный адрес для инициализации контроллерa Ethernet и добавляет свойство local-mac-address в узел контроллерa внутри Device Tree. Поиск узла осуществляется посредством псевдонима ethernet узла aliases. Таким образом, U-Boot и Linux используют один MAC-адрес во время работы. При отсутствии переменной U-Boot и Linux генерируют произвольные MAC-адреса независимо.

При загрузке модуля выполняется чтение заводских настроек и анализ наличия переменной factory_eth_mac. Если переменная factory_eth_mac существует, а ethaddr не существует, то ethaddr создаётся и заполняется значением factory_eth_mac. В противном случае ethaddr не изменяется.

factoryoffset

Смещение в байтах последнего сектора SPI флеш-памяти, где хранятся заводские настройки. Переменная создаётся динамически и не должна изменяться пользователем.

factorysize

Размер в байтах сектора SPI флеш-памяти, где хранятся заводские настройки. Переменная создаётся динамически и не должна изменяться пользователем.

factory_eth_mac

MAC-адрес Ethernet из заводских настроек. Переменная создаётся динамически и не должна изменяться пользователем. Переменная не создаётся в случае отсутствия заводских настроек. См. также ethaddr.

factory_serial

Серийный номер модуля из заводских настроек. Переменная создаётся динамически и не должна изменяться пользователем. Переменная не создаётся в случае отсутствия заводских настроек. См. также serial#.

serial#

Серийный номер модуля.

Значение переменной записывается в свойство serial-number в DTB (свойство доступно в Linux по пути /sys/firmware/devicetree/base/serial-number). При загрузке модуля выполняется чтение заводских настроек и анализ наличия переменной factory_serial. Если factory_serial существует, а serial# не существует, то serial# создаётся и заполняется значением factory_serial. В противном случае serial# не изменяется.

В мониторе U-Boot доступны функции управления переменными окружения.

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

env default <var_name>
saveenv

Команды

Фактический набор команд доступен по команде терминала help.

Полный список команд U-Boot — https://docs.u-boot.org/en/stable/usage/index.html#shell-commands. Для включения некоторых команд может требоваться изменение файла конфигурации U-Boot.

Реализованы дополнительные команды:

  • ddrctl disable <0|1>

    Выключение контроллеров памяти DDR. Команда отключает тактовую частоту для указанного контроллера.

Загрузка Linux

U-Boot настроен на загрузку с использованием схемы Distro и extlinux.conf. Последовательность действий при загрузке Linux описана в bootcmd, список команд загрузки — в boot_targets. Инструкции по загрузке с SD-карты, eMMC, NAND, Ethernet TFTP/NFS см. Дистрибутив Buildroot.

Загрузка ELF-файла из SPI флеш-памяти

Для загрузки ELF-файла из SPI флеш-памяти необходимо собрать загрузчик с опцией BOOT_ELF_FROM_SPI (подробнее см. bootcmd).

Передача управления из U-Boot в baremetal-приложение

Варианты передачи управления в baremetal-приложение:

  • с возвратом в U-Boot,

  • без возврата в U-Boot.

Для передачи управления без возврата в U-Boot необходимо:

  1. разработать исходный код приложения. Требования к исходному коду:

    • секции кода, стека и данных не должны использовать используемые загрузчиком U-Boot адреса (подробнее см. Карта распределения ОЗУ);

    • для включения CPU1 необходимо:

      • переключить отображение нулевых адресов CPU1 в BootROM (записать значение 0x3 по физическому адресу 0x38096004);

      • записать адрес начала кода, исполняемого CPU1, в регистр ALWAYS_MISC0;

      • включить домен питания CPU1 (записать значение 4 по физическому адресу 0x38095000).

  2. скомпилировать ELF-файл приложения;

  3. загрузить ELF-файл приложения с ПК в память ОЗУ модуля, например:

    • через интерфейс Ethernet:

      • загрузить ELF-файл на сервер TFTP на ПК;

      • загрузить ELF-файл приложения в память ОЗУ модуля командой tftpboot.

    • через интерфейс SD/eMMC/USB:

      • cкопировать ELF-файл приложения в раздел Boot на SD/eMMC/USB-носитель;

      • загрузить ELF-файл приложения в память ОЗУ модуля. Например для модуля Салют-ЭЛ24ОМ1 с установленным модулем Салют-ЭЛ24ПМ1 и установленной SD-картой необходимо выполнить команду fatload mmc 1 <addr> <file.elf>, где <addr> — адрес ОЗУ для загрузки ELF-файла, <file.elf> — имя ELF-файла на SD-карте.

    • через интерфейс NAND:

      • cкопировать ELF-файл приложения в раздел Boot NAND флеш-памяти;

      • загрузить ELF-файл приложения в память ОЗУ модуля, выполнив команду ubifsload <addr> <file.elf>, где <addr> — адрес ОЗУ для загрузки ELF-файла, <file.elf> — имя ELF-файла в разделе Boot NAND флеш-памяти.

    • через интерфейс SPI:

      • загрузить ELF-файл приложения в SPI флеш-память:

        • загрузить ELF-файл приложения в память ОЗУ модуля через интерфейсы UART, SD/eMMC, Ethernet;

        • выполнить запись командой sf write.

      • загрузить ELF-файл приложения в память ОЗУ модуля командой sf read.

    • через интерфейс UART:

      • выполнить команду loady на модуле;

      • передать ELF-файл приложения с помощью программы minicom с использованием протокола YMODEM на ПК.

  4. передать управление из U-Boot в приложение командой bootelf <addr>, где <addr> — адрес загруженного в памяти ELF-файла.