Портирование U-Boot

Статус U-Boot

  • текущая миграция из файла заголовка платы определяется параметрами Kconfig
  • постоянная миграция с manual драйверов (выполняется вручную) относительно модели драйвера

Каталоги U-Boot

  • arch/
— Все, что связано с архитектурой или платформой: DTS, CPU init, pinmux контроллер, DRAM, тактирование, …
  • board/
— Спецификация для платы (init, настройка pinmuxing и т. д.), настройка файла Kconfig
заголовочные файлы платы (*.h), файлы платы, пути, Makefile для плат
  • configs/
— Все файлы defconfigs
  • drivers/
  • include/
— Все заголовочные файлы
  • include/configs/
— Все заголовочные файлы плат

Рабочий процесс подкрепления (добавления) новой платы в U-Boot

1. создайте файл платы
2. создайте Kconfig файл платы
3. создайте Makefile файл платы
4. создайте defconfig файл платы
5. создайте заголовочный файл платы
6. исходники платы для Вашего Kconfig в разрядности архитектуры для Kconfig
7. определите TARGET Kconfig в Kconfig своего процессора для платформы (например, sunxi (Allwinner) обмениваться общими файлами, как только defconfig сформирует запрос на необходимый файл)

Создайте файл платы

board/my_vendor/my_board/my_board.c

Глобальные данные 

  • DECLARE_GLOBAL_DATA_PTR
  • использование в коде с глобальной переменной gd
  • на ARM архитектуре, равно аппаратному регистру r9 для ARM32 и x18 для ARM64,
  • используется для хранения информации в «некоторой области памяти, которая доступна очень рано (внутренняя память), сразу после загрузки. Разрешен минимальный набор глобальных переменных во время инициализации системы (пока мы настраиваем контроллер памяти, для использования внешнего ОЗУ)
  • include/asm-generic/global_data.h необходим для поиска информации на хранение

Создайте для платы файл Kconfig

board/my_vendor/my_board/Kconfig

Параметры Kconfig

  • SYS_VENDOR и SYS_BOARD используются для идентификации каталога, в котором make ищет файлы необходимые для компиляции
    • если оба присутствуют
      • board/SYS_VENDOR/SYS_BOARD/
    • если SYS_VENDOR опущен
      • board/SYS_BOARD/
    • если SYS_BOARD опущен
      • board/SYS_VENDOR/common/
    • SYS_CONFIG_NAME используется для идентификации файла заголовка платы
      • include/configs/SYS_CONFIG_NAME.h

Создание Makefile платы

board/my_vendor/my_board/Makefile
obj-y := my_board.o

Создание defconfig платы

configs/my_board_defconfig
CONFIG_ARM=y
CONFIG_ARCH_MX6=y
CONFIG_TARGET_MY_BOARD=y
CONFIG_MXC_UART=y
  • поместите здесь все, что является выбираемым элементом для Kconfig (menuconfig)
  • драйверы, функции, поведение U-Boot, libs, и т.д

Создайте заголовочный файл платы (минимальный пример для i.MX6 Solo)

include/configs/my_board.h

Файл Kconfig исходной платы

arch/arm/Kconfig или
arch/arm/mach-imx/mx6/Kconfig

source «board/imx31_phycore/Kconfig»
source «board/isee/igep003x/Kconfig»
source «board/my_vendor/my_board/Kconfig»
source «board/olimex/mx23_olinuxino/Kconfig»
source «board/phytec/pcm051/Kconfig»

Определите параметр TARGET Kconfig платы

arch/arm/mach-imx/mx6/Kconfig
choice

config TARGET_MY_BOARD
bool «My awesome board»
select MX6S

endchoice

Последовательная инициализация U-Boot

  • в U-Boot работает два списка функций, цель которых заключается в инициализации или настройки конкретных IP блоков до того, как пользователь получит доступ к консоли
  • первый список определяется в common/board_f.c в массиве static init_fnc_t init_sequence_f[]
  • первый список берет на себя инициализацию памяти DRAM, отображение его и перемещение кода загрузчика, когда тот работает
  • второй список определяется в common/board_r.c в массиве static init_fnc_t init_sequence_r[]
  • некоторые функции выполняются только тогда, когда константа определена (например, CONFIG_BOARD_EARLY_INIT_F определена чтобы запустить board_early_init_f ())
  • любые функции возвращаемые ненулевое значение остановят последовательность инициализации и U-Boot не будет дальше загружаться
    • определите DEBUG, когда возникают проблемы с последовательностью инициализации
  • не все «особенности» доступны во всех функциях (т.е. нет udelay в board_early_init_f ())

Выбор драйвера

  • черпайте вдохновение (анализируйте текущие исходники) из boards с тем же IP
  • проверяйте драйверы для соответствующей подсистемы
    • сконцентрированное свое внимание на поведение драйвера
    • затем проверите регистры, битовые смещения, маски и т.д.
    • сделайте проверку для неопределенных макросов или констант
    • проверка для участков кода в окружении #ifdef блоков
  • ищите объектный файл этого драйвера в Makefile подсистемы
  • OBJ — $ (CONFIG_MY_DRIVER) + = my_driver.o
  • grep для CONFIG_MY_DRIVER,
  • видимый символ в файле Kconfig => добавить для платы (board) defconfig
  • невидимый символ в файле Kconfig или символ который не определен =>для файла заголовка платы
  • убедитесь, что ваш драйвер скомпилирован (ищите my_driver.o)

Выбор драйвера — пример NAND

  • drivers/mtd/nand/nand_mxs.c
  • CONFIG_NAND_MXS для компиляции драйвера
  • CONFIG_SYS_MAX_NAND_DEVICE и CONFIG_SYS_NAND_BASE константы для конфигурирования устройства
configs/my_board_defconfig
CONFIG_ARM = у
CONFIG_ARCH_MX6 = у
CONFIG_TARGET_MY_BOARD = у
CONFIG_MXC_UART = у
CONFIG_NAND_MXS = у
include/configs/my_board.h

 board/my_vendor/my_board.c

Примечание о деревьях устройств (device tree)

  • переход на деревья устройств началось еще в 2012 году, код медленно переносится («мигрирует»), драйвер за драйвером, подсистема за подсистемой
  • нужно для модели драйвера использовать дерево устройств
  • большинство драйверов имеют большие количество #ifdef блоков для CONFIG_DM (Driver Model — DM)
  • вы не можете выбрать на основе каждого драйвера включение поддержки DM
  • упомянутое ранее для основного кода подсистем
  • полная поддержка дерева устройств и фреймворк NAND не переносятся в DM

Усилия, необходимые для поддержки U-Boot (из опыта)

  • Ethernet, EEPROM, NAND, EMMC, считыватель SD карт, USB устройства, GPIO, UART, аудио (I2S), PMIC и т.д.
$ wc -l board/my_vendor/my_board/* configs/my_board_defconfig include/configs/my_board.h
15 board/my_vendor/my_board/Kconfig
8 board/my_vendor/my_board/Makefile
159 board/my_vendor/my_board/my_board.cfg #DCD conf for DDR controller and memory
218 board/my_vendor/my_board/my_board.c
39 configs/my_board_defconfig
110 include/configs/my_board.h
510 total
+ 1 строка в arch/ ARM/ Kconfig
+4 строки в arch/arm/ CPU/ ARMv7/ mx6/ Kconfig
  • собственно ~ 100 строк «реального» кода (PHY и платы инициализации, настройки ММС)
  • запрещается модификация исходного кода U-Boot
  • получил некоторые странные ошибки с Lib RSA при проверке подписей fitImage в U-Boot
  • обновление от 2017.03 до 2017.07 было очень легко:
    • портретирование платы: заголовочные файлы, файлы платы, Makefile, Kconfig и обновление
  • Kconfig архитектуры
  • убедитесь, что все параметры определенные в заголовочных файлах платы

Проблемы

  • последовательность инициализации платы трудоемкий процесс
  • все сигналы (даже UART) проходят через FPGA (в том случае, если у Вас FPGA)
  • отсутствии платы последовательность инициализации, нет FPGA, нет UART
  • запрещаются udelay в board_early_init_f
  • обходной путь заключается в использовании forloop с cpurelax ()

Оригинал статьи на английском языке по ссылке.

Отправить ответ

Оставьте первый комментарий!

Уведомлять о
avatar