Коллеги, приветствую, обзорная статья работы с Corgi SoM v1 на базе AMD (Xilinx) Zynq-7000. Статья охватывает работу модуля с Vivado IDE, Vitis IDE, подготовку базового образа, работу с Embedded Linux (u-boot, device tree, linux kernel, rootfs). Подготовку образа для SPI NOR памяти, SPI NAND памяти и сопутствующие моменты необходимые для старта работы с данным модулем. Дополнительно статья будет полезно для linux embedded разработчиков, которые делать будут bring-up плат на базе AMD(Xilinx) zynq платформ.

1. Описание Corgi SoM

Процессорный модуль Corgi SoM v1 на базе AMD Zynq-7000 (xc7z010, xc7z020) разработан белорусской компанией ШураКор (ShuraCore), модуль подходит для задач: робототехники, создание электроприводов/сервоприводов для управления электродвигателями/серводвигателями, создания силовой электроники DC/DC, AC/DC, DC/AC, разработки ПЛК (программируемых логических контроллеров), активных фильтров, систем сбора данных, I/O систем, системы машинного зрения, аудиосистем, а также находит применение в анализаторах качества сети и других промышленных решениях и не только. 

Процессорный модуль представлен в одном температурном варианте: для промышленного использования. На модуле расположен один из вариантов AMD Zynq 7010/7020 в корпусе clg400, DDR3 память 512 МБайт, SPI NOR память, SPI NAND память, 4 физики Ethernet 10/100/1000 Мбит. Установлены 2 физики на PL части и 2 физики на PS части. На PL физиках возможно использование и реализация EtherCAT slave, а также реализации и поддержка других промышленных протоколов: PROFINET, EtherNet/IP, CC-Link, POWERLINK. 

Несущая плата для Corgi SoM v1
Несущая плата для Corgi SoM v1
Corgi SoM v1
Corgi SoM v1

Модуль спроектирован с учетом использования либо полностью западных компонентов, либо полностью китайских компонентов.

Западный вариант SoM модуля и основная компонентная база:

  • Xilinx SoC Zynq-7010 (XC7Z010-2clg400i)/Xilinx SoC Zynq-7020 (XC7Z020-2clg400i)

  • Texas Instruments TPS51200DRCR Sink and Source DDR Termination Regulator

  • Texas Instruments TPS62085RLTR 3-A Step-Down Converter With Hiccup Short-Circuit Protection

  • Winbond Electronics W25M02GWZEIG Flash

  • Macronix International MX66L51235FZ2I-10G Flash

  • Alliance Memory AS4C256M16D3LC-12BCN DDR3

  • Realtek RTL8211FI-CG 10/100/1000 Ethernet

Восточный вариант SoM модуля и основная компонентная база:

  • Fudan Microelectronics fmql10s400/Fudan Microelectronics fmql20s400

  • SG Micro SGM2054XTD10G Sink and Source DDR Termination Regulator

  • SG Micro SGM61030BXTEP7G 3-A Step-Down Converter With Hiccup Short-Circuit Protection

  • GigaDevice GD5F2GQ5REYJG Flash

  • GigaDevice GD25B512MEYIG Flash

  • UniIC Semiconductors SCB13H4G160AF-13KI DDR3

  • Motorcomm YT8531H 10/100/1000 Ethernet

2. Vivado IDE

Базовый проект подготовлен для модуля Corgi SoM v1 в Vivado 2023.1. Проект Vivado можно скачать с github. Для запуска проекта, необходимо выполнить tcl команду, предварительно перейдя в директорию проекта, source ./base_corgi_som.tcl.

Рисунок 2.1. Базовый проект corgi som board v1.
Рисунок 2.1. Базовый проект corgi som board v1.

После выполнения команды source у вас должен появиться следующий блок дизайна, как на картинке 2.1. 

Рисунок 2.2. Адресное пространство проекта.
Рисунок 2.2. Адресное пространство проекта.

На рисунке 2.2. показано базовое адресное пространство, которое используется по умолчанию для SoM. 

Чтобы проект был полноценным необходимо в него добавить файл constraints.xdc. В файле constraints.xdc располагается распиновка для XC7Z020-2CLG400I привязка конкретного ввода/вывода модуля.  Добавление файла показана на рисунке 2.3, рисунке 2.4. 

Рисунок 2.3. Окно добавления ограничений (constraints).
Рисунок 2.3. Окно добавления ограничений (constraints).
Рисунок 2.4. Добавляем файл constraints из скачанного репозитория.
Рисунок 2.4. Добавляем файл constraints из скачанного репозитория.

Чтобы проект был готовым для синтеза и имплементации нужно добавить HDL wrapper, как на рисунке 2.5.

Рисунок 2.5. Создаем HDL wrapper для проекта.
Рисунок 2.5. Создаем HDL wrapper для проекта.

После подготовки проекта запустите процесс Synthesis → Implementation → Generate Bitstream. Это финальный шаг для получения прошивки (bitstream) FPGA (PL части SoC).

Рисунок 2.6. Экспорт аппаратной платформы.
Рисунок 2.6. Экспорт аппаратной платформы.

Для дальнейшей разработки в Vitis IDE необходимо: 

  • выполнить экспорт аппаратной платформы;

  • включить в экспорт сгенерированный bitstream.

После этого можно переходить к разработке и отладке в Vitis IDE.

3. Vitis IDE

Для подготовки образа c Embedded Linux для платформы Xilinx Zynq 7020 от Vitis IDE нам нужно сформировать FSBL и сгенерировать Device Tree. Так как по умолчанию у нас нет Device Tree, поэтому первоначальным шагом работы с Vitis IDE будет добавление каталога работы с генератором Device Tree. Репозиторий для генератора можно скачать с github. Перейдите в Preferences → Vitis → Software Repositories → Global Repositories и добавьте свой путь к скаченному каталогу генератора Device Tree, как на рисунке 3.1 (показан путь к установленному на дополнительный внешний SSD диск IDE от Xilinx, для более комфортной работы с версионностью и значительным размером занимаемого места на диске данной IDE).       

Рисунок 3.1. Добавление генератора device tree для Xilinx платформ.
Рисунок 3.1. Добавление генератора device tree для Xilinx платформ.

После добавления пути дерева устройств, переходим к созданию FSBL проекта. Вам необходимо выбрать создать новый проект, как показано на рисунке 3.2-3.6.

Рисунок 3.2. Окно создания нового приложения, выбор .xsa файла
Рисунок 3.2. Окно создания нового приложения, выбор .xsa файла
Рисунок 3.3. Окно названия проекта и деталей приложения. 
Рисунок 3.3. Окно названия проекта и деталей приложения. 
Рисунок 3.4. Окно выбора ОС, в нашем случае для FSBL нужен standalone.
Рисунок 3.4. Окно выбора ОС, в нашем случае для FSBL нужен standalone.
Рисунок 3.5. Окно создания проекта с помощью шаблонов, наш выбор FSBL.
Рисунок 3.5. Окно создания проекта с помощью шаблонов, наш выбор FSBL.
Рисунок 3.6. Собранный через шаблон Zynq FSBL проект по умолчанию.
Рисунок 3.6. Собранный через шаблон Zynq FSBL проект по умолчанию.

После успешной генерации проекта из шаблона, осталось только построить бинарный файл для FSBL. На текущем этапе работа с FSBL завершается и следующим шагом работы с Vitis IDE будет создание Device Tree для Corgi SoM. Для этого нужно выбрать создать новый платформенный проект и выбрать Device Tree в качестве ОС как это показано рисунках 3.7.-3.8.

Рисунок 3.7. Окно создания платформенного проекта, для генерации дерева устройств.
Рисунок 3.7. Окно создания платформенного проекта, для генерации дерева устройств.
Рисунок 3.8. Выбор в качестве ОС генерацию Device Tree.
Рисунок 3.8. Выбор в качестве ОС генерацию Device Tree.

Редактированием сгенерированного дерева устройства для целевой платформы мы займемся в отдельном разделе про Device Tree.  

4. Описание структуры разделов QSPI Flash

В данном разделе опишем структуру разделов QSPI Flash памяти. Конфигурация определяет разметку памяти QSPI Flash для встраиваемой системы Corgi SoM на базе Xilinx Zynq 7020. Разделы содержат ключевые компоненты для загрузки ОС Linux и работы системы.

1. Раздел qspi-fsbl-uboot

  • Адрес: 0x00000000

  • Размер: 8 МБ (0x800000)

  • Назначение:

    • FSBL (First Stage Boot Loader) – первичный загрузчик, инициализирующий аппаратную часть.

    • Bitstream – прошивка (конфигурация) PL(FPGA) части SoC Zynq 7020.

    • U-Boot – основной загрузчик, обеспечивающий запуск ядра Linux.

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

2. Раздел qspi-linux

  • Адрес: 0x00800000

  • Размер: 10 МБ (0xA00000)

  • Назначение:

    • Ядро Linux (Image / uImage) – исполняемый образ операционной системы.

Размер раздела позволяет хранить ядро с дополнительными драйверами и модулями.

3. Раздел qspi-device-tree

  • Адрес: 0x01200000

  • Размер: 256 КБ (0x40000)

  • Назначение:

    • Device Tree Blob (DTB) – описание аппаратной конфигурации системы.

DTB определяет, какие устройства доступны в Linux.

4. Раздел qspi-rootfs

  • Адрес: 0x01240000

  • Размер: 13 МБ 768 КБ (0xDC0000)

  • Назначение:

    • Корневая файловая система (rootfs.cpio.uboot) – сжатый архив, содержащий /bin, /lib, /etc и другие системные каталоги.

Формат cpio.uboot оптимизирован для загрузки через U-Boot.

Сводная таблица по разделам

Раздел

Адрес начала

Размер

Содержимое

qspi-fsbl-uboot

0x00000000

8 МБ

FSBL, Bitstream, U-Boot

qspi-linux

0x00800000

10 МБ

Ядро Linux

qspi-device-tree

0x01200000

256 КБ

Device Tree (DTB)

qspi-rootfs

0x01240000

13 МБ 768 КБ

Корневая ФС (cpio.uboot)

Примечание

  • Общий объем памяти: ~32 МБ (сумма всех разделов).

5. Настройка минимального FSBL для целей программирования флеш-памяти

В рамках проектов на базе Zynq 7000 часто возникает необходимость использования FSBL (First Stage Boot Loader) исключительно для инициализации подсистемы PS (Processing System - процессорная часть SoC), например, при программировании внешней флеш-памяти через Vitis IDE (наш случай). 

В стандартной реализации FSBL, при использовании режима загрузки с QSPI, загрузчик пытается автоматически считать и загрузить все разделы, определенные в образе. 

Чтобы сформировать необходимую последовательность загрузки необходимо создать специализированную версию FSBL, задача которой — исключительно выполнить процедуру аппаратной инициализации, в частности, вызвать функцию ps7_init(), не выполняя при этом загрузку других разделов из памяти.

Для этого следует:

  1. Создать новый проект FSBL в среде разработки Vitis IDE.

  2. Внести изменения в исходный файл main.c, удалив или закомментировав всю логику, связанную с обработкой и загрузкой разделов.

  3. Оставить только базовую инициализацию, включая вызов ps7_init() и, при необходимости, базовую отладочную информацию.

Такой минималистичный FSBL можно использовать как вспомогательный загрузчик при программировании QSPI флеш, исключая любые попытки загрузки лишнего содержимого, что обеспечивает стабильность и предсказуемость процесса.

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

Для этого модифицируемый вариант загрузки, выбрав загрузку через JTAG и предварительно нужно инициализировать QSPI. 

/*
 * Read bootmode register
 */
BootModeRegister = Xil_In32(BOOT_MODE_REG);
BootModeRegister &= BOOT_MODES_MASK;

//add this line to trick boot mode to JTAG
BootModeRegister = JTAG_MODE;
fsbl_printf(DEBUG_GENERAL,"Set JTAG mode to manual\n\r");

InitQspi();
fsbl_printf(DEBUG_INFO,"QSPI Init Done \r\n");
Рисунок 5.1. Vitis IDE подготовка custom FSBL с возможностью загрузки bin файла во FLASH.
Рисунок 5.1. Vitis IDE подготовка custom FSBL с возможностью загрузки bin файла во FLASH.

Только эти изменения нам нужны для Corgi SoM.

Рисунок 5.2. Vitis IDE включение отладочной информации.
Рисунок 5.2. Vitis IDE включение отладочной информации.

Для вывода отладочной информации необходимо использовать FSBL_DEBUG, FSBL_DEBUG_INFO.

FSBL_DEBUG
Установите этот флаг для включения базового режима отладки в FSBL. При активации этого флага FSBL начнёт выводить диагностические сообщения и события выполнения, такие как запуск и завершение этапов инициализации, статусы загрузки и ошибки. Это позволяет отслеживать общий процесс загрузки и помогает в базовой диагностике.

FSBL_DEBUG_INFO
Этот флаг активирует расширенный режим отладки. При его установке FSBL дополнительно выводит подробную отладочную информацию: дампы регистров, содержимое заголовков разделов, параметры загрузки и другие внутренние данные. 

Загрузка файла во FLASH

Загрузка осуществляется с помощью подготовленных bin файлов с u-boot  zynq_qspi_x4_single.bin/zynq_qspi_x1_single.bin расположенные (путь)/xilinx/2023.1/Vitis/2023.1/data/xicom/cfgmem/uboot.

Загрузить bin файл можно также с инструмента program_flash. Пример команды выполнения. 

program_flash -f /home/mcuby/corgi_bin/eth/BOOT.bin -offset 0 -flash_type qspi-x4-single -fsbl /home/mcuby/corgi_bin/fsbl_info_debug.elf -url TCP:127.0.0.1:3121 -target_id 3

Момент запуска, custom FSBL для загрузки образа через JTAG показан ниже.

Xilinx First Stage Boot Loader 
Release 2023.1  Sep  9 2025-14:11:37
Devcfg driver initialized 
Silicon Version 3.1
Set JTAG mode to manual
Single Flash Information
FlashID=0xC2 0x20 0x1A
MACRONIX 512M Bits
QSPI is in single flash connection
QSPI is in 4-bit mode
QSPI Init Done 
Boot mode is JTAG
U-Boot 2023.01-g8624651 (Mar 14 2023 - 23:15:54 -0600)

Model: Zynq CSE QSPI SINGLE Board
DRAM:  256 KiB
WARNING: Caches not enabled
Core:  8 devices, 7 uclasses, devicetree: embed
Loading Environment from <NULL>... OK
In:    dcc
Out:   dcc
Err:   dcc
Zynq> sf probe 0 0 0

SF: Detected mx66l51235l with page size 256 Bytes, erase size 64 KiB, total 64 MiB
Zynq> Sector size = 65536.
f probe 0 0 0

Performing Erase Operation...
sf erase 0 7D0000

….

device 0 offset 0x7b0000, size 0x10000
SF: 65536 bytes @ 0x7b0000 Written: OK
Zynq> 100%
sf write FFFC0000 7C0000 57C

device 0 offset 0x7c0000, size 0x57c
SF: 1404 bytes @ 0x7c0000 Written: OK
Zynq> Program Operation successful.
INFO: [Xicom 50-44] Elapsed time = 288 sec.

6. Buildroot

Buildroot - это инструмент для сборки Embedded Linux систем. Buildroot автоматизирует процесс построения пользовательского дистрибутива на основе кросс-компиляции. Ключевые преимущества для быстрого старта работы с этим инструментом - это простота и минимальная конфигурация, единый инструмент для настройки всего (целевой архитектуры, инструментов компиляции, ядра, базовой системы и пакетов). Автоматизация сборки: скачивает все исходные коды, применяет патчи, собирает тулчейн, корневую файловую систему и образ ядра Linux. Высокая скорость первой сборки, генерирует рабочую систему за небольшое количество времени. Интеграция с популярными библиотеками: поддерживает множество готовых пакетов (библиотек и утилит), которые можно легко добавить в систему. Создание готовых образов, которые можно сразу записать на носитель и загрузить целевое устройство. 

Базовая конфигурация которая используется в проекте - corgi_som_v1_defconfig, данную конфигурацию можно скачать с github проекта. Скачайте данный конфиг и помещаем в ваш buildroot проект (/buildroot/configs/). Для сборки проекта необходимо выполнить команду make corgi_som_v1_defconfig. Внимание, рекомендуется дочитать до конца статью и применить изменения с добавлением необходимого Device Tree.  Далее перейдем к непосредственной настройки Device Tree (dts, настройка интерфейсов целевой платформы), U-Boot (загрузчик), Linux Kernel (ядро) и rootfs (корневая файловая система). Рекомендуется использовать команду make source, команда позволяет скачать исходники без непосредственного сбора файлов, до момента полной конфигурации системы, а также релизные версии Buildroot.

7. Device Tree

В разделе Vitis IDE мы создали файлы необходимые для Device Tree. В этом разделе опишем, какие узлы мы настраиваем, какие значения задаем для устройств. 

Узел SPI1 используется для работы NAND SPI памяти, сформированное описание задает разделы работы для нашей UBIFS. Память разделена на 4 области, 16/80/80/80 MB соответственно. Предполагается использовать раздел "nand-reserved” в качестве резервной области под пользовательские задачи, раздел “ubia” как основной раздел, раздел “ubib” как дополнительный раздел. Раздел “nand-recovery” может использоваться, как раздел восстановления образа с Linux. 

Узел QSPI был описан ранее в разделе “описание структуры разделов QSPI Flash”. 

Узел gpio0, can0, can1, i2c0, i2c1, uart0, uart1, sdhci0 является базовыми узлами процессорной периферии и реализует конфигурацию работы с GPIO, CAN, I2C, UART соответственно. 

Работа с 4-мя физиками (приемопередатчиками) Ethernet и конфигурация MAC-ов описаны в узлах gem0, gem1, axi_ethernet_0, axi_ethernet_1. Gigabit Ethernet MAC (GEM) узлы определяют работу PS (CPU) подключенных физик, а AXI Ethernet подсистема определяют работу PL (FPGA) части Zynq. Для них мы задаем MAC адрес отличный на единицу в номере.

Данный Device Tree является одинаковым как для U-Boot, так и для Linux. Далее показано полное описание файл dts для Cori SoM v1.

/dts-v1/;
#include "zynq-7000.dtsi"
#include <dt-bindings/gpio/gpio.h>

/ {
	model = "Xilinx ZC702 board";
	compatible = "xlnx,zynq-zc702", "xlnx,zynq-7000";

	aliases {
		ethernet0 = &gem0;
		ethernet1 = &gem1;
		ethernet2 = &axi_ethernet_0;
		ethernet3 = &axi_ethernet_1;
		i2c0 = &i2c0;
		i2c1 = &i2c1;
		serial0 = &uart0;
		serial1 = &uart1;
		spi0 = &qspi;
		spi1 = &spi1;
	};

	memory@0 {
		device_type = "memory";
		reg = <0x0 0x20000000>;
	};

	chosen {
		bootargs = "console=ttyPS0,115200 root=/dev/ram rw earlyprintk";
		stdout-path = "serial0:115200n8";
	};

	amba_pl: amba_pl {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "simple-bus";
		ranges ;
		axi_ethernet_0: ethernet@41000000 {
			axistream-connected = <&axi_ethernet_0_dma>;
			axistream-control-connected = <&axi_ethernet_0_dma>;
			clock-frequency = <100000000>;
			clock-names = "s_axi_lite_clk", "axis_clk", "gtx_clk", "ref_clk";
			clocks = <&clkc 15>, <&clkc 15>, <&clkc 16>, <&clkc 17>;
			compatible = "xlnx,axi-ethernet-7.2", "xlnx,axi-ethernet-1.00.a";
			device_type = "network";
			interrupt-names = "mac_irq", "interrupt", "mm2s_introut", "s2mm_introut";
			interrupt-parent = <&intc>;
			interrupts = <0 33 1 0 34 4 0 35 4 0 36 4>;
			local-mac-address = [00 0a 35 00 00 02];
			phy-mode = "rgmii";
			reg = <0x41000000 0x40000>;
			xlnx = <0x0>;
			xlnx,axiliteclkrate = <0x0>;
			xlnx,axisclkrate = <0x0>;
			xlnx,channel-ids = "1";
			xlnx,clockselection = <0x0>;
			xlnx,enableasyncsgmii = <0x0>;
			xlnx,gt-type = <0x0>;
			xlnx,gtinex = <0x0>;
			xlnx,gtlocation = <0x0>;
			xlnx,gtrefclksrc = <0x0>;
			xlnx,include-dre ;
			xlnx,instantiatebitslice0 = <0x0>;
			xlnx,num-queues = /bits/ 16 <0x1>;
			xlnx,phyaddr = <0x1>;
			xlnx,phyrst-board-interface-dummy-port = <0x0>;
			xlnx,rable = <0x0>;
			xlnx,rxcsum = <0x0>;
			xlnx,rxlane0-placement = <0x0>;
			xlnx,rxlane1-placement = <0x0>;
			xlnx,rxmem = <0x1000>;
			xlnx,rxnibblebitslice0used = <0x0>;
			xlnx,tx-in-upper-nibble = <0x1>;
			xlnx,txcsum = <0x0>;
			xlnx,txlane0-placement = <0x0>;
			xlnx,txlane1-placement = <0x0>;
			xlnx,versal-gt-board-flow = <0x0>;
			zclock-names = "NULL";
			zclocks = "NULL";
			phy-handle = <&phy2>;
			axi_ethernet_0_mdio: mdio {
				#address-cells = <1>;
				#size-cells = <0>;
				phy2: phy@3 {
					device_type = "ethernet-phy";
					reg = <3>;
				};
			};
		};

		axi_ethernet_0_dma: dma@40400000 {
			#dma-cells = <1>;
			axistream-connected = <&axi_ethernet_0>;
			axistream-control-connected = <&axi_ethernet_0>;
			clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
			clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
			compatible = "xlnx,eth-dma";
			interrupt-names = "mm2s_introut", "s2mm_introut";
			interrupt-parent = <&intc>;
			interrupts = <0 35 4 0 36 4>;
			reg = <0x40400000 0x10000>;
			xlnx,addrwidth = /bits/ 8 <0x20>;
			xlnx,include-dre ;
			xlnx,num-queues = /bits/ 16 <0x1>;
		};

		axi_ethernet_1: ethernet@41040000 {
			axistream-connected = <&axi_ethernet_1_dma>;
			axistream-control-connected = <&axi_ethernet_1_dma>;
			clock-frequency = <100000000>;
			clock-names = "s_axi_lite_clk", "axis_clk", "gtx_clk", "gtx_clk90";
			clocks = <&clkc 15>, <&clkc 15>, <&misc_clk_0>, <&misc_clk_0>;
			compatible = "xlnx,axi-ethernet-7.2", "xlnx,axi-ethernet-1.00.a";
			device_type = "network";
			interrupt-names = "mac_irq", "interrupt", "mm2s_introut", "s2mm_introut";
			interrupt-parent = <&intc>;
			interrupts = <0 52 1 0 53 4 0 54 4 0 55 4>;
			local-mac-address = [00 0a 35 00 00 03];
			phy-mode = "rgmii";
			reg = <0x41040000 0x40000>;
			xlnx = <0x0>;
			xlnx,axiliteclkrate = <0x0>;
			xlnx,axisclkrate = <0x0>;
			xlnx,channel-ids = "1";
			xlnx,clockselection = <0x0>;
			xlnx,enableasyncsgmii = <0x0>;
			xlnx,gt-type = <0x0>;
			xlnx,gtinex = <0x0>;
			xlnx,gtlocation = <0x0>;
			xlnx,gtrefclksrc = <0x0>;
			xlnx,include-dre ;
			xlnx,instantiatebitslice0 = <0x0>;
			xlnx,num-queues = /bits/ 16 <0x1>;
			xlnx,phyaddr = <0x1>;
			xlnx,phyrst-board-interface-dummy-port = <0x0>;
			xlnx,rable = <0x0>;
			xlnx,rxcsum = <0x0>;
			xlnx,rxlane0-placement = <0x0>;
			xlnx,rxlane1-placement = <0x0>;
			xlnx,rxmem = <0x1000>;
			xlnx,rxnibblebitslice0used = <0x0>;
			xlnx,tx-in-upper-nibble = <0x1>;
			xlnx,txcsum = <0x0>;
			xlnx,txlane0-placement = <0x0>;
			xlnx,txlane1-placement = <0x0>;
			xlnx,versal-gt-board-flow = <0x0>;
			zclock-names = "NULL";
			zclocks = "NULL";
			phy-handle = <&phy3>;
			axi_ethernet_1_mdio: mdio {
				#address-cells = <1>;
				#size-cells = <0>;
				phy3: phy@1 {
					device_type = "ethernet-phy";
					reg = <1>;
				};
			};
		};

		misc_clk_0: misc_clk_0 {
			#clock-cells = <0>;
			clock-frequency = <125000000>;
			compatible = "fixed-clock";
		};

		axi_ethernet_1_dma: dma@40410000 {
			#dma-cells = <1>;
			axistream-connected = <&axi_ethernet_1>;
			axistream-control-connected = <&axi_ethernet_1>;
			clock-names = "s_axi_lite_aclk", "m_axi_sg_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
			clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
			compatible = "xlnx,eth-dma";
			interrupt-names = "mm2s_introut", "s2mm_introut";
			interrupt-parent = <&intc>;
			interrupts = <0 54 4 0 55 4>;
			reg = <0x40410000 0x10000>;
			xlnx,addrwidth = /bits/ 8 <0x20>;
			xlnx,include-dre ;
			xlnx,num-queues = /bits/ 16 <0x1>;
		};

		axi_gpio_0: gpio@41200000 {
			#gpio-cells = <2>;
			#interrupt-cells = <2>;
			clock-names = "s_axi_aclk";
			clocks = <&clkc 15>;
			compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
			gpio-controller ;
			interrupt-controller ;
			interrupt-names = "ip2intc_irpt";
			interrupt-parent = <&intc>;
			interrupts = <0 56 4>;
			reg = <0x41200000 0x10000>;
			xlnx,all-inputs = <0x1>;
			xlnx,all-inputs-2 = <0x0>;
			xlnx,all-outputs = <0x0>;
			xlnx,all-outputs-2 = <0x1>;
			xlnx,dout-default = <0x00000000>;
			xlnx,dout-default-2 = <0xFFFFFFFF>;
			xlnx,gpio-width = <0x2>;
			xlnx,gpio2-width = <0x4>;
			xlnx,interrupt-present = <0x1>;
			xlnx,is-dual = <0x1>;
			xlnx,tri-default = <0xFFFFFFFF>;
			xlnx,tri-default-2 = <0xFFFFFFFF>;
		};
	};
};

&gem0 {
	phy-mode = "rgmii-id";
	status = "okay";
	phy-handle = <&phy0>;

	local-mac-address = [00 0a 35 00 00 00];

	phy0: phy@1 {
		reg = <1>;
		device_type = "ethernet-phy";
	};
};

&gem1 {
	phy-mode = "rgmii-id";
	phy-handle = <&phy1>;
	status = "okay";

	local-mac-address = [00 0a 35 00 00 01];

	phy1: phy@1 {
		reg = <1>;
		device_type = "ethernet-phy";
	};
};

&gpio0 {
	emio-gpio-width = <64>;
	gpio-mask-high = <0x0>;
	gpio-mask-low = <0x5600>;
};

&can0 {
	status = "okay";
};

&can1 {
	status = "okay";
};

&i2c0 {
	clock-frequency = <400000>;
	status = "okay";
};

&i2c1 {
	clock-frequency = <400000>;
	status = "okay";
};

&uart0 {
	cts-override ;
	device_type = "serial";
	port-number = <0>;
	status = "okay";
};

&uart1 {
	cts-override ;
	device_type = "serial";
	port-number = <1>;
	status = "okay";
};

&intc {
	num_cpus = <2>;
	num_interrupts = <96>;
};

&qspi {
	u-boot,dm-pre-reloc;
	is-dual = <0>;
	num-cs = <1>;
	status = "okay";

	nor: flash@0 {

		spi-tx-bus-width = <4>;
		spi-rx-bus-width = <4>;

		spi-max-frequency = <50000000>;

		/* MX66L51235F, 512M-bit = 32M-Byte */

		compatible = "jedec,spi-nor";
		reg = <0>;

		#address-cells = <1>;
		#size-cells = <1>;

		/* 8MB, fsbl, bitstream, u-boot*/
		partition@0 {
			label = "qspi-fsbl-uboot";
			reg = <0x0 0x800000>;
		};

		/* 10MB, linux*/
		partition@800000 {
			label = "qspi-linux";
			reg = <0x800000 0xA00000>;
		};

		/* 256KB, device-tree */
		partition@1200000 {
			label = "qspi-device-tree";
			reg = <0x1200000 0x40000>;
		};

		/* 13MB 768KB, rootfs.cpio.uboot */
		partition@1240000 {
			label = "qspi-rootfs";
			reg = <0x1240000 0xDC0000>;
		};
	};
};

&spi1 {
	is-decoded-cs = <0>;
	num-cs = <1>;
	status = "okay";

	nand: flash@0 {
		status = "okay";

		compatible = "spi-nand";
		reg = <0>;
		spi-max-frequency = <50000000>;

		/* W25M02GW, 2x1G-bit = 2x128M-Byte */

		#address-cells = <1>;
		#size-cells = <1>;

		/* 16MB */
		partition@0 {
			label = "nand-reserved";
			reg = <0 0x1000000>;
		};

		/* recovery / install environment, 80MB */
		partition@1000000 {
			label = "nand-recovery";
			reg = <0x1000000 0x5000000>;
		};

		/* ubia (first image) - a/b names to prevent confusion with ubi0/1/etc, 80MB */
		partition@6000000 {
			label = "ubia";
			reg = <0x6000000 0x5000000>;
		};

		/* ubib (second image), 80MB */
		partition@B000000 {
			label = "ubib";
			reg = <0xB000000 0x5000000>;
		};

	};
};

&sdhci0 {
	status = "okay";
	xlnx,has-cd = <0x0>;
	xlnx,has-power = <0x0>;
	xlnx,has-wp = <0x0>;
};

&clkc {
	fclk-enable = <0x7>;
	ps-clk-frequency = <33333333>;
};

8. U-Boot

Изменения в U-Boot коснуться поддержки RGMII, AXI Ethernet, для поддержки AXI Ethernet и RGMII необходимо перейти в Device Drivers > Network device support и включить поддержку драйверов Enable RGMII, Xilinx AXI Ethernet. 

Для работы именно с U-Boot, в инфраструктуре Buildroot существует команда:

make uboot-menuconfig

Рисунок 8.1. Добавление поддержки RGMII, Xilinx AXI Ethernet в U-Boot.
Рисунок 8.1. Добавление поддержки RGMII, Xilinx AXI Ethernet в U-Boot.
Рисунок 8.2. Адреса смещения dtb и boot.src.
Рисунок 8.2. Адреса смещения dtb и boot.src.

Важным моментом корректности, в будущем старта образа, будут адреса смещения dtb и скрипта загрузки (boot.src). Задайте адреса смещения, как на рисунке 8.2. Boot.src используется для автоматизации загрузки.

CONFIG_XILINX_OF_BOARD_DTB_ADDR=0x1200000 CONFIG_BOOT_SCRIPT_OFFSET=0x7c0000

Для сборки пакета U-Boot в Buildroot можно использовать команды make uboot-build и make uboot-rebuild. Первая команда выполняет сборку только тех частей, которые считаются «устаревшими», тогда как вторая игнорирует эту проверку и всегда запускает полный процесс пересборки компонента U-Boot.

9. Linux Kernel

Изменения в Linux коснуться поддержки UBIFS и поддержки драйвера NAND SPI (W25M02GWZEIG). Далее по тексту раскрывается подробности того, какие изменения были сделаны относительно отладочной платы zc702, которая была выбрана за базу настроек Linux Kernel для Corgi SoM v1. Для работы именно с Linux Kernel, в инфраструктуре buildroot существует отдельная команда:

make linux-menuconfig

Выполнив эту команду, мы перейдем в окружение Linux Kernel.

Рисунок 9.1. Программные уровни VFS.
Рисунок 9.1. Программные уровни VFS.

VFS (Virtual File System) в Linux является абстрактным слоем (рисунок 9.1, A), который унифицирует работу с различными файловыми системами, включая UBIFS. На нижнем уровне NAND/NOR флеш (D) управляется через драйвер MTD (Memory Technology Device) (C), предоставляющий операции чтения/записи и стирания блоков. Над MTD располагается слой UBI (Unsorted Block Images) (B), который реализует управление износом, исправление ошибок и динамическое распределение логических томов поверх физических блоков. На базе UBI работает UBIFS (UBI File System) — журнальная файловая система, оптимизированная под NAND, обеспечивающая поддержку каталогов, индексов и метаданных. UBIFS напрямую интегрируется с VFS, предоставляя стандартные файловые интерфейсы и скрывая особенности управления флеш-памятью. Таким образом, взаимодействие строится по цепочке: VFS → UBIFS → UBI → MTD → физическая NAND/NOR.

Первым шагом добавления UBIFS, является добавление уровня UBI. Для этого перейдем в Device Drivers > Memory Technology Device (MTD) support и включим поддержку уровня UBI, как на рисунке 9.2. Также используемая NAND память работает по SPI интерфейсу. Необходимо добавить поддержку NAND SPI перейдя в Device Drivers > Memory Technology Device (MTD) support > NAND и включить соответствующий драйвер устройства, как на рисунке 9.3.

Рисунок 9.2. Включение уровня UBI в  Memory Technology Device (MTD) support.
Рисунок 9.2. Включение уровня UBI в  Memory Technology Device (MTD) support.
Рисунок 9.3. Включение поддержки NAND SPI для MTD.
Рисунок 9.3. Включение поддержки NAND SPI для MTD.
Рисунок 9.4. Включение поддержки UBIFS.
Рисунок 9.4. Включение поддержки UBIFS.

После включения драйверов описанных выше, нам доступен уровень UBIFS. Перейдите в File systems > Miscellaneous filesystems в включите поддержку UBIFS как на рисунке 9.4.

Заключительным этапом работы с разделом Linux Kernel будет коррекция драйвера NAND от вендора Winbond. По умолчанию поддержки 1.8V SPI NAND памяти W25M02GW нет в drivers/mtd/nand/spi/winbond.c, поэтому необходимо добавить SPINAND_INFO в winbond.c:

(ваш путь)/buildroot/output/build/linux-custom/drivers/mtd/nand/spi/winbond.c и внесите ниже представленный код в драйвер.

	SPINAND_INFO("W25M02GW",
		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbb, 0x21),
		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
		     NAND_ECCREQ(1, 512),
		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
					      &write_cache_variants,
					      &update_cache_variants),
		     0,
		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
		     SPINAND_SELECT_TARGET(w25m02gv_select_target)),

Для сборки пакета Linux Kernel в buildroot вы можете воспользоваться  командами make linux-build или make linux-rebuild. make linux-build соберет только то, что считается «устаревшим», make linux-rebuild явно отменяет эту проверку, гарантируя полный процесс пересборки компонента Linux Kernel в Buildroot.

10. rootfs

Ключевые пакеты корневой файловой системы сосредоточим вокруг работы с UBIFS (NAND) и базового тестирования Ethernet (GEM, AXI Ethernet). 

Для работы с утилитами командной строки мы используем BusyBox. BusyBox — это компактный набор утилит, объединяющий более 300 стандартных UNIX-команд в одном исполняемом файле. Он работает в POSIX-совместимых средах, включая Linux, Android и FreeBSD, и особенно востребован во встраиваемых системах с крайне ограниченными ресурсами. Благодаря своей универсальности и минимализму BusyBox часто называют «швейцарским ножом» для Embedded Linux, поскольку он заменяет целый арсенал отдельных программ, обеспечивая базовую функциональность операционной системы в условиях нехватки памяти и места на диске.

Добавим поддержку работы с некоторыми сетевыми утилитами: phytool, tcpdump, ifupdown scripts. Перейдите Target packages → Networking applications и включить их поддержку, как на рисунке 10.1.

Рисунок 10.1. Меню включения сетевых пакетов для rootfs.
Рисунок 10.1. Меню включения сетевых пакетов для rootfs.

Для тестирования SPI и PS части SoC можно воспользоваться утилитами (coremark, coremark-pro - не рекомендуется для сборки rootfs.cpio.uboot требует Perl в rootfs, spidev_test, stress, stress-ng), опция необязательная может использоваться по желанию. Для добавление данных пакетов перейдите в Target packages → Debugging, profiling and benchmark (рисунок 10.2) и включите указанные опции.

Рисунок 10.2. Меню Debugging, profiling and benchmark.
Рисунок 10.2. Меню Debugging, profiling and benchmark.

Для максимального тестирования и проверки работы NAND предлагаем воспользоваться всеми утилитами, которые представлены в меню для mtd (Target packages → Filesystem and flash utilities). Выберите все пакеты вложенные в mtd, jffs2 and ubi/ubifs tools, как это показано на рисунке 10.3.

Рисунок 10.3. Меню Filesystem and flash utilities, включение пакетов для работы с mtd.
Рисунок 10.3. Меню Filesystem and flash utilities, включение пакетов для работы с mtd.

Завершение работы с rootfs будет создание образов файловой системы UBIFS, initramfs/cpio и настройка Kernel. 

Cpio — это утилита-архиватор и формат файлов, который используется для работы с файловыми системами. В контексте Embedded Linux, cpio используется для создания initramfs начальной файловой системы в оперативной памяти, которая представляет собой архив в формате cpio, содержащий модули ядра и другие файлы, необходимые для загрузки операционной системы, и монтируемый в оперативную память. Такой способ один из самых простых способов для быстрого bring-up систем с Embedded Linux.

Настроить образы файловой системы и включить опции для них необходимо, как на рисунке 10.4 перейдя в раздел Filesystem images.

Рисунок 10.4. Настройка Filesystem images для UBIFS и initramfs/cpio.
Рисунок 10.4. Настройка Filesystem images для UBIFS и initramfs/cpio.

Для Kernel нужно внести изменение в путь расположения конфигурационного файла (рисунок 10.5) и выбрать Using a custom (def)config file. Данные изменения в файле содержат описание из раздела Linux Kernel. Custom конфигурационный файл находится в том же github репозитории, что и предыдущие файлы проекта (файл xilinx_zynq_defconfig можно скачать с github и поместите его в /buildroot/output/build/linux-custom/arch/arm/configs/). 

Рисунок 10.5. Окно конфигурации Linux Kernel в Buildroot.
Рисунок 10.5. Окно конфигурации Linux Kernel в Buildroot.

11. Запуск образа с Embedded Linux

Пришло время создать bin файл с fsbl, bitstream, u-boot, boot.src для старта загрузчика. Файл boot.src используется для автоматизации загрузки системы целиком. Файл автоматизации qspiboot.cmd находится в (ваш путь)/buildroot/output/build/uboot-custom/board/xilinx/bootscripts/, с помощью этого файла необходимо сгенерировать boot.src используя инструмент mkimage выполнив команду ./tools/mkimage -c none -A arm -T script -в qspi boot.cmt boot.scr (укажите пути относительно вашей системы). Примечание: 1) размеры fdt, kernel, rootfs корректируйте относительно того, какого размера вы собрали файлы; 2) адреса для bootm можно задать свои. 

# This example only target for qspi boot, sameway it can be created for boot
# devices like nand.
# Generate boot.scr:
# ./tools/mkimage -c none -A arm -T script -d qspiboot.cmd boot.scr
#
# It requires a list of environment variables to be defined before load:
# fdt_addr, fdt_offset, fdt_size, kernel_addr, kernel_offset, kernel_size
#
#sf probe 0 0 0 && sf read $fdt_addr $fdt_offset $fdt_size && sf read $kernel_addr $kernel_offset $kernel_size && booti #$kernel_addr - $fdt_addr

setenv fdt_addr 0x15000000
setenv fdt_offset 0x1200000
setenv fdt_size 0x4304

setenv kernel_addr 0x10000000
setenv kernel_offset 0x800000
setenv kernel_size 0x513358

setenv rootfs_addr 0x18000000
setenv rootfs_offset 0x1240000
setenv rootfs_size 0x596662

setenv bootargs console=ttyPS0,115200 ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs rw rootwait earlyprintk

#sf probe 0 0 0 && sf read $fdt_addr $fdt_offset $fdt_size && sf read $kernel_addr $kernel_offset $kernel_size && sf read $rootfs_addr $rootfs_offset $rootfs_size && bootm $kernel_addr $rootfs_addr $fdt_addr

sf probe 0 0 0 && sf read $fdt_addr $fdt_offset $fdt_size && sf read $kernel_addr $kernel_offset $kernel_size && sf read $rootfs_addr $rootfs_offset $rootfs_size && bootm $kernel_addr - $fdt_addr
Рисунок 11.1 Создание загрузочного образа в Vitis IDE.
Рисунок 11.1 Создание загрузочного образа в Vitis IDE.

В Vitis IDE необходимо создать BOOT.bin файл, который будет зашиваться в SPI NOR. Создайте порядок файлов, как на рисунке 11.1. Для файлов fsbl, bitstream, uboot смещение не указывается. Для файла boot.src укажите смещение 0x7c0000 (datafile - partition type). Далее выбираем прошить флеш память, как на рисунке 11.2. В качестве init файла выберите созданный custom FSBL, как в разделе “настройка минимального FSBL для целей программирования флеш-памяти”. 

Рисунок 11.2. Окно загрузки BIN файла в SPI NOR память.
Рисунок 11.2. Окно загрузки BIN файла в SPI NOR память.
Рисунок 11.3. Запуск U-Boot.
Рисунок 11.3. Запуск U-Boot.

После старта U-Boot (рисунок 11.3) необходимо выполнить следующие команды, для настройки сети и запуска через TFTP (протокол передачи файлов, который позволяет быстро передавать небольшие файлы, такие как файлы конфигурации и прошивки, без аутентификации и шифрования):

setenv ethact ethernet@e000b000

setenv ipaddr 192.168.100.2

setenv serverip 192.168.100.7

Команды setenv в U-Boot используются для настройки сетевого окружения перед загрузкой образов. Первая команда setenv ethact ethernet@e000b000 задаёт активный Ethernet-контроллер, который будет использоваться для сетевых операций — в данном случае это встроенный GEM MAC. Команда setenv ipaddr 192.168.100.2 назначает IP-адрес самой платы в локальной сети, чтобы обеспечить её доступность для сетевого обмена. Команда setenv serverip 192.168.100.7 указывает IP-адрес TFTP сервера, с которого плата будет загружать необходимые файлы, ядро Linux, device tree или rootfs. 

tftpboot 0x10000000 uImage

tftpboot 0x15000000 zynq-corgi-som-v1.dtb

tftpboot 0x18000000 rootfs.cpio.uboot

bootm 0x10000000 0x18000000 0x15000000

Последовательность команд загружает образы системы по сети с помощью TFTP и запускает ядро Linux. Команда tftpboot 0x10000000 uImage загружает образ ядра Linux (uImage) в оперативную память по адресу 0x10000000. Затем tftpboot 0x15000000 zynq-corgi-som-v1.dtb загружает device tree файл (.dtb), описывающий аппаратную конфигурацию платы, в адрес 0x15000000. Следующей командой tftpboot 0x18000000 rootfs.cpio.uboot загружается корневая файловая система в формате initramfs по адресу 0x18000000. После этого команда bootm 0x10000000 0x18000000 0x15000000 передаёт управление загруженному ядру, указывая адреса ядра, initramfs и device tree, в результате чего система Linux стартует с указанными параметрами (рисунок 11.4).

Далее сделаем запись недостающих данных в SPI NOR (linux kernel, dtb, rootfs):

Для Linux

sf probe 0 0 0

sf erase 0x800000 0xA00000

tftpboot 0x10000000 uImage

sf write 0x10000000 0x800000 0x513358

Для Device Tree

sf probe 0 0 0

sf erase 0x1200000 0x40000

tftpboot 0x15000000 zynq-corgi-som-v1.dtb

sf write 0x15000000 0x1200000 0x4304

Для rootfs

sf probe 0 0 0

sf erase 0x1240000 0xDC0000

tftpboot 0x18000000 rootfs.cpio.uboot

sf write 0x18000000 0x1240000 0x596662

Эта последовательность команд используется для прошивки образа в SPI-flash через U-Boot. Сначала выполняется команда sf probe 0 0 0, которая инициализирует SPI-контроллер и подключенную флеш-память. Затем с помощью sf erase стирается участок флеша размером n байт, начиная с адреса 0x#######, чтобы освободить место под запись. Команда tftpboot 0x####### #имя загружает файл #имя по сети с TFTP-сервера в оперативную память по адресу 0x#######. В завершение выполняется sf write, которая записывает загруженный образ из RAM во флеш-память, начиная с адреса 0x#######, на участок размером m байт. Разметка памяти описана в разделе “описание структуры разделов QSPI Flash”.

Рисунок 11.4. Запуск Linux с rootfs.cpio.uboot (bootargs = "console=ttyPS0,115200 root=/dev/ram rw earlyprintk").
Рисунок 11.4. Запуск Linux с rootfs.cpio.uboot (bootargs = "console=ttyPS0,115200 root=/dev/ram rw earlyprintk").

Строка в переменной bootargs = "console=ttyPS0,115200 root=/dev/ram rw earlyprintk" определяет параметры запуска ядра Linux. Она задаёт использование UART-порта ttyPS0 со скоростью 115200 бод в качестве системной консоли для ввода и вывода, указывает на размещение корневой файловой системы в оперативной памяти (/dev/ram) и её монтирование в режиме чтения и записи, а также включает режим earlyprintk, позволяющий ядру вывод��ть отладочные сообщения ещё на ранних стадиях загрузки до инициализации основных драйверов.

Для тестирования сетевой части, настроем IP-адреса сетевых интерфейсов:

ip addr add 192.168.100.20/24 dev eth0

ip addr add 192.168.100.30/24 dev eth1

ip addr add 192.168.100.40/24 dev eth2

ip addr add 192.168.100.50/24 dev eth3

Каждая команда присваивает статический IP-адрес соответствующему сетевому интерфейсу в подсети 192.168.100.0/24. 192.168.100.X/24 — IP-адрес с маской 255.255.255.0, dev ethX — интерфейс, которому назначается IP-адрес.

Для активации сетевых интерфейсов выполним следующие команды:

ip link set eth0 up

ip link set eth1 up

ip link set eth2 up

ip link set eth3 up

Данные команды включают (активируют) указанные сетевые интерфейсы, переводя их в состояние UP.

Для деактивация сетевых интерфейсов, необходимо выполнить ниже перечисленные команды:

ip link set eth0 down

ip link set eth1 down

ip link set eth2 down

ip link set eth3 down

Данные команды выключают (деактивируют) указанные сетевые интерфейсы, переводя их в состояние DOWN.

Проверим работу сетевых интерфейсов, для этого отправим ICMP-эхо (ping) с конкретного интерфейса:

ping -I eth0 -i 0.1 192.168.100.7

ping -I eth1 -i 0.1 192.168.100.7

ping -I eth2 -i 0.1 192.168.100.7

ping -I eth3 -i 0.1 192.168.100.7

Описание команды: ping — отправка ICMP-запросов к хосту 192.168.100.7, -I ethX — использование указанного интерфейса для отправки пакетов, -i 0.1 — интервал между отправками пакетов: 0.1 секунды. Команда позволяет проверить доступность хоста 192.168.100.7 с каждого интерфейса по отдельности.

Следующим этапом после работы с NOR SPI памятью будет конфигурация NAND SPI памяти. Для SPI NAND памяти сделаем возможность старта системы с UBIFS.

Creating 4 MTD partitions on "spi1.0":
0x000000000000-0x000001000000 : "nand-reserved"
0x000001000000-0x000006000000 : "nand-recovery"
0x000006000000-0x00000b000000 : "ubia"
0x00000b000000-0x000010000000 : "ubib"

4 fixed-partitions partitions found on MTD device spi0.0
Creating 4 MTD partitions on "spi0.0":
0x000000000000-0x000000800000 : "qspi-fsbl-uboot"
0x000000800000-0x000001200000 : "qspi-linux"
0x000001200000-0x000001240000 : "qspi-device-tree"
0x000001240000-0x000002000000 : "qspi-rootfs"

Получить информацию о mtd можно с помощью команды mtdinfo, пример далее.

# mtdinfo /dev/mtd2 -u
mtd2
Name:                           ubia
Type:                           nand
Eraseblock size:                131072 bytes, 128.0 KiB
Amount of eraseblocks:          640 (83886080 bytes, 80.0 MiB)
Minimum input/output unit size: 2048 bytes
Sub-page size:                  2048 bytes
OOB size:                       64 bytes
Character device major/minor:   90:4
Bad blocks are allowed:         true
Device is writable:             true
Default UBI VID header offset:  2048
Default UBI data offset:        4096
Default UBI LEB size:           126976 bytes, 124.0 KiB
Maximum UBI volumes count:      128

Для загрузки rootfs.ubi необходимо использовать команду ubiformat /dev/mtd2 -f rootfs.ubi. Скачать rootfs.ubi можно командой tftp -gr rootfs.ubi 192.168.100.7. После загрузки rootfs перезагружаем систему, boot.src загружает rootfs с NAND SPI (рисунок 11.5)

Рисунок 11.5. Запуск Linux с UBIFS (bootargs console=ttyPS0,115200 ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs rw rootwait earlyprintk - указано в boot.src).
Рисунок 11.5. Запуск Linux с UBIFS (bootargs console=ttyPS0,115200 ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs rw rootwait earlyprintk - указано в boot.src).

Строка (bootargs console=ttyPS0,115200 ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs rw rootwait earlyprintk) задаёт параметры ядру Linux через переменную bootargs. Параметр ubi.mtd=2 сообщает ядру, что UBI должен быть подключён к разделу номер 2 в памяти MTD. Далее root=ubi0:rootfs задаёт корневую файловую систему, расположенную в томе rootfs на UBI-устройстве с номером 0. Опция rootfstype=ubifs указывает тип файловой системы — UBIFS. Ключ rw разрешает монтировать rootfs в режиме чтения-записи, а rootwait заставляет ядро ждать появления устройства с корневой файловой системой перед монтированием. 

В итоге подготовлен образ с поддержкой NAND SPI и NOR SPI с Embedded Linux (u-boot, device tree, linux kernel, rootfs), собран FSBL для полноценного функционирования системы.

Комментарии (0)