Zynq 7000. Загрузка Embedded Linux на SoC через JTAG с помощью XSCT

от автора

Учитывая, что я очень давно занимаюсь отладкой и запуском самых разнообразных проектов связанных с Zynq 7000 — со временем количество итераций перезапуска при проведении отладки увеличивалось пропорционально сложности проекта. Когда я только начинал осваивать разработку под Zynq, то каждый раз закидывал новый образ на microSD карту. Это было очень медленным процессом и требовало от меня постоянно подключать/отключать карту. После этого я освоил сетевую загрузку через Ethernet и TFTP, заменяя файлы по сети и проверяя результат после перезагрузки.

Впоследствии, изучив вопрос связанный с типами загрузки, я обнаружил, что есть альтернативный способ загрузки платы через интерфейс JTAG, который впрочем может оказаться единственным доступным, если на плате нет microSD и Ethernet.  

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

❯ Дисклеймер

Перед началом повествования хотелось бы заранее оговориться, что основная цель, которую я преследую при написании этой статьи — рассказать о своем опыте, с чего можно начать, при изучении отладочных плат на базе Zynq. Я не являюсь профессиональным разработчиком под ПЛИС и SoC Zynq, не являюсь системным программистом под Linux и могу допускать какие-либо ошибки в использовании терминологии, использовать не самые оптимальные пути решения задач, etc. Но отмечу, что любая конструктивная и аргументированная критика только приветствуется.

❯ Что такое сервер XSCT?

В составе набора инструментов для работы Zynq 700 имеется утилита XSCT т. е. Xilinx Software Command-line Tool. По сути — это командная строка, которая поддерживает выполнение скриптов в режиме интерактивного терминала. Данная тулза предоставляет огромное количество самых разных возможностей, большую часть которых мы не будем рассматривать в рамках данной статьи. Всем интересующимся — в документ UG-1400. 

Мы лишь ограничимся рассмотрением опций загрузки устройства через JTAG.

❯ Что необходимо из аппаратного обеспечения?

Так как в этой статье я буду рассматривать выполнения загрузки на Zynq Mini — на нем уже имеется встроенный отладчик JTAG и никаких внешних устройств не потребуется. В случае, если вы выполняете действия на какой-то другой железке — вам обязательно понадобится стандартный отладчик JTAG от Xilinx и плата должна иметь выводы JTAG. Выглядит он следующим образом:

Либо есть альтернативный вариант для отладки, который дает возможность проводить отладку в т. ч. по сети Ethernet. Называется эта железка Xilinx SmartLynq JTAG Cable: 

Но стоит данная железка не мало, в районе 130К рублей и рассматривать мы ее не будем. Большая часть доступных отладчиков для Zynq отличается между собой используемым чипом и есть медленные варианты, но есть отладчики на чипах FTDI, которые обеспечивают высокую скорость загрузки образов. 

❯ Загрузка с помощью JTAG по шагам

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

❯ Запуск сервера XSCT

В первую очередь необходимо запустить сервер XSCT из директории, в которой установлен Xilinx Vivado/Vitis. Обычно он находится в директории Xilinx/Vitis/2021.1/bin/xsct. После запуска утилиты появляется командная строка. С этой утилитой можно взаимодействовать в т. ч. с помощью специальных TCL-скриптов.

megalloid@megalloid-xubuntu:~$ cd Xilinx/Vitis/2023.2/bin/ megalloid@megalloid-xubuntu:~/Xilinx/Vitis/2023.2/bin$ ./xsct  Display is :185 rlwrap: warning: your $TERM is 'xterm-256color' but rlwrap couldn't find it in the terminfo database. Expect some problems.                                                                              7 ****** Software Commandline Tool (XSCT) v2023.2.2   **** SW Build 0 on 2024-02-08-22:35:25     ** Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.     ** Copyright 2022-2024 Advanced Micro Devices, Inc. All Rights Reserved.   Note:  XSCT has been deprecated. It will still be available for several releases.It's recommended to start new projects with new python command line tool.         Use "vitis -s <script>" (script mode) and "vitis -i" (interactive mode) to load new Python CLI for Vitis.   xsct% help Available Help Categories  breakpoints   - Target Breakpoints/Watchpoints. connections   - Target Connection Management. device        - Device Configuration System. download      - Target Download FPGA/BINARY. hsi           - HSI commands. ipi           - IPI commands to Versal PMC. jtag          - JTAG Access. memory        - Target Memory. miscellaneous - Miscellaneous. petalinux     - Petalinux commands. projects      - Vitis Projects. registers     - Target Registers. reset         - Target Reset. running       - Program Execution. sdtgen        - System Device Tree. stapl         - STAPL Operations. streams       - Jtag UART. svf           - SVF Operations. tfile         - Target File System.  Type "help" followed by above "category" for more details or help" followed by the keyword "commands" to list all the commands  xsct%

❯ Установка драйверов и решение проблемы отсутствия устройства в списке

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

xsct% connect attempting to launch hw_server  ****** Xilinx hw_server v2023.2.2   **** Build date : Jan  5 2024 at 11:23:30     ** Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.     ** Copyright 2022-2024 Advanced Micro Devices, Inc. All Rights Reserved.  INFO: hw_server application started INFO: Use Ctrl-C to exit hw_server application  INFO: To connect to this hw_server instance use url: TCP:127.0.0.1:3121  tcfchan#0 xsct% targets xsct%

В списке ничего нет. Вытыкаем устройство из ПК и подключаем обратно, смотрим dmesg:

[ 1901.337966] usb 1-5: new high-speed USB device number 6 using xhci_hcd [ 1901.491022] usb 1-5: New USB device found, idVendor=0403, idProduct=6014, bcdDevice= 9.00 [ 1901.491038] usb 1-5: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 1901.491046] usb 1-5: Product: Digilent USB Device [ 1901.491052] usb 1-5: Manufacturer: Digilent [ 1901.491058] usb 1-5: SerialNumber: 210251A08870 [ 1901.495113] ftdi_sio 1-5:1.0: FTDI USB Serial Device converter detected [ 1901.495205] usb 1-5: Detected FT232H [ 1901.496522] usb 1-5: FTDI USB Serial Device converter now attached to ttyUSB0

Скорее всего устройство просто не имеет udev-правила, которое определяет конфигурацию для вновь подключенного устройства. Добавим его. 

Для этого нужно сделать следующее:

megalloid@megalloid-xubuntu:~$ sudo adduser $USER dialout megalloid@megalloid-xubuntu:~$ cd ~/Xilinx/Vivado/2023.2/data/xicom/cable_drivers/lin64/install_script/install_drivers megalloid@megalloid-xubuntu:~/Xilinx/Vivado/2023.2/data/xicom/cable_drivers/lin64/install_script/install_drivers$ sudo ./install_drivers INFO: Installing cable drivers. INFO: Script name = ./install_drivers INFO: HostName = megalloid-xubuntu INFO: RDI_BINROOT= . INFO: Current working dir = /home/megalloid/Xilinx/Vivado/2023.2/data/xicom/cable_drivers/lin64/install_script/install_drivers INFO: Kernel version = 6.5.0-41-generic. INFO: Arch = x86_64. Successfully installed Digilent Cable Drivers --File /etc/udev/rules.d/52-xilinx-ftdi-usb.rules exists. --File /etc/udev/rules.d/52-xilinx-ftdi-usb.rules version = 0001 --File 52-xilinx-ftdi-usb.rules exists. --File 52-xilinx-ftdi-usb.rules version = 0001 --File 52-xilinx-ftdi-usb.rules is already updated. --File /etc/udev/rules.d/52-xilinx-pcusb.rules does not exist. --File version of /etc/udev/rules.d/52-xilinx-pcusb.rules = 0000. --Updating rules file.  INFO: Digilent Return code = 0 INFO: Xilinx Return code = 0 INFO: Xilinx FTDI Return code = 0 INFO: Return code = 0 INFO: Driver installation successful. CRITICAL WARNING: Cable(s) on the system must be unplugged then plugged back in order for the driver scripts to update the cables.

❯ Вывод списка устройств в JTAG

После того как выполнили все действия из предыдущего этапа необходимо отключить устройство от ПК и подключить обратно, а в терминале XSCT выполнить следующее:

xsct% targets xsct% disconnect xsct% Info: tcfchan#2 closed xsct% connect tcfchan#3 xsct% targets   1  APU      2  ARM Cortex-A9 MPCore #0 (Running)      3  ARM Cortex-A9 MPCore #1 (Running)   4  xc7z020 xsct%

Команда targets выводит список устройств, подключенных к JTAG. Всё, устройство детектируется. Идём к следующему шагу. 

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

xsct% targets   1  whole scan chain (Unknown device configuration)  xsct% targets   1  whole scan chain (Unknown IR length)  xsct% targets   1  whole scan chain (too many devices)

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

xsct% jtag target 1  xsct% jtag frequency -list 125000 250000 500000 1000000 2000000 3000000 3750000 5000000 6000000 7500000 10000000 15000000 30000000  xsct% jtag frequency 15000000

При работе с ZynqMini я смело выставляю частоту 30000000 и все работает очень быстро:

xsct% jtag frequency 30000000 30000000

Идем дальше. 

❯ Загрузка bitstream в Zynq через JTAG

Чтобы начать проверку частей полученного проекта на плате в первую очередь необходимо загрузить bitstream-файл в PL-часть. Для этого необходимо сделать следующее:

xsct% targets   1* APU      2  ARM Cortex-A9 MPCore #0 (Running)      3  ARM Cortex-A9 MPCore #1 (Running)   4  xc7z020 xsct% targets 4  xsct% fpga /home/megalloid/Xilinx/Projects/ZynqMini/1.Linux/top_design_wrapper.bit 100%    3MB   3.3MB/s  00:01 

Сразу же происходит загрузка образа FPGA и загорается светодиод DONE.

❯ Загрузка FSBL

Следующим этапом можно загрузить First Stage Bootloader. Это второй загрузчик, который вступает в работу после BootROM. Загрузка выполняется не менее просто:

xsct% targets -set -nocase -filter {name =~ "arm*#0"} xsct% dow /home/megalloid/Xilinx/Projects/ZynqMini/1.Linux/Vitis/zynq_fsbl/build/zynq_fsbl.elf Downloading Program -- /home/megalloid/Xilinx/Projects/ZynqMini/1.Linux/Vitis/zynq_fsbl/build/zynq_fsbl.elf section, .text: 0x00000000 - 0x0001045f section, .handoff: 0x00010460 - 0x000104ab section, .note.gnu.build-id: 0x000104ac - 0x000104cf section, .init: 0x000104d0 - 0x000104db section, .fini: 0x000104dc - 0x000104e7 section, .rodata: 0x000104e8 - 0x000110d0 section, .data: 0x000110d8 - 0x00013c0f section, .mmu_tbl: 0x00014000 - 0x00017fff section, .ARM.exidx: 0x00018000 - 0x00018007 section, .init_array: 0x00018008 - 0x0001800f section, .fini_array: 0x00018010 - 0x00018013 section, .rsa_ac: 0x00018014 - 0x0001903f section, .bss: 0x00019040 - 0x0001a3f3 section, .drvcfg_sec: 0x0001a3f4 - 0x0001a4b7 section, .heap: 0x0001a4b8 - 0x0001c4bf section, .stack: 0xffff0000 - 0xffffd3ff  Setting PC to Program Start Address 0x00000000 Successfully downloaded /home/megalloid/Xilinx/Projects/ZynqMini/1.Linux/Vitis/zynq_fsbl/build/zynq_fsbl.elf xsct% Info: ARM Cortex-A9 MPCore #0 (target 2) Stopped at 0xffffff28 (Suspended)

Запуск осуществляется на 1-м ядре ARM PS-части. Запускаем FSBL:

xsct% con

Если при компиляции FSBL вы включили отладочный вывод, при запуске — то UART-терминале мы увидим следующее:

Xilinx First Stage Boot Loader  Release 2023.2  Aug  9 2024-15:21:41 Silicon Version 3.1 Boot mode is SD SD: Unable to open file BOOT.BIN: 3                                    SD_INIT_FAIL FSBL Status = 0xA009

Теперь разберем полученный вывод. Команда dow выполняет загрузку заданного исполняемого файла на указанный target и устанавливает соответствующий указатель команд ядра ARM в entry point. После установки счетчика процессор останавливает работу. После необходимо остановить выполнение вручную для выполнения последующей загрузки:

xsct% stop Info: ARM Cortex-A9 MPCore #0 (target 2) Stopped at 0x11ac (Suspended)

Остановка необходима для того, чтобы остановить работу Memory Management Unit (MMU), т. к. он выполняет трансляцию физических адресов в логические и по сути мешает прямому чтению/записи в память. 

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

❯ Инициализация PS-части

В состав генерируемого содержимого при создании проект в Vivado входит не только bitstream-файл. Помимо этого в XSA-архиве присутствует скрипт инициализации PS-части. И после запуска FSBL для инициализации периферии необходимо предварительно извлечь XSA-архив и выполнить на отлаживаемой плате скрипт ps7_init.tcl:

xsct% targets   1  APU      2* ARM Cortex-A9 MPCore #0 (Suspended)      3  ARM Cortex-A9 MPCore #1 (Running)   4  xc7z020  xsct% targets 1    xsct% source /home/megalloid/Xilinx/Projects/ZynqMini/1.Linux/top_design_wrapper.xsa_FILES/ps7_init.tcl  xsct% ps7_init 

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

❯ Загрузка Device Tree Blob для U-Boot

Для работы U-Boot необходим бинарный файл Device Tree. Без этого файла U-Boot не сможет проинициализировать периферию, которая необходима для дальнейшей работы. Для загрузки Device Tree Blob в RAM необходимо выполнить следующее:

xsct% targets -set -nocase -filter {name =~ "arm*#0"}  xsct% set device_tree_offset 0x10000 0x10000  xsct% dow -data /home/megalloid/Xilinx/Tools/u-boot-xlnx/arch/arm/dts/zynqmini.dtb ${device_tree_offset} 100%    0MB   0.6MB/s  00:00     Successfully downloaded /home/megalloid/Xilinx/Tools/u-boot-xlnx/arch/arm/dts/zynqmini.dtb

Опция -data необходима для того, чтобы указать, что этот файл не является исполняемым. Смещение, которое использовано в качестве переменной задается при компиляции U-Boot в параметре Default DTB pickup address. 

❯ Загрузка U-Boot

Для того, чтобы осуществить загрузку Linux необходимо запустить скомпилированный файл U-Boot на плате. Сделать этого можно следующим образом:

xsct% dow /home/megalloid/Xilinx/Tools/u-boot-xlnx/u-boot.elf  Downloading Program -- /home/megalloid/Xilinx/Tools/u-boot-xlnx/u-boot.elf section, .data: 0x04000000 - 0x040fb453 100%    0MB   0.5MB/s  00:01 Setting PC to Program Start Address 0x04000000 Successfully downloaded /home/megalloid/Xilinx/Tools/u-boot-xlnx/u-boot.elf  xsct% con Info: ARM Cortex-A9 MPCore #0 (target 2) Running

Обратим внимание в UART-терминал:

U-Boot 2023.01 (Aug 09 2024 - 19:31:07 +0300)  CPU:   Zynq 7z020 Silicon: v3.1 DRAM:  ECC disabled 512 MiB Core:  19 devices, 13 uclasses, devicetree: board Flash: 0 Bytes NAND:  0 MiB MMC:   mmc@e0100000: 0 Loading Environment from FAT... *** Error - No Valid Environment Area found *** Warning - bad env area, using default environment  In:serial@e0001000 Out:   serial@e0001000 Err:   serial@e0001000 Net:    ZYNQ GEM: e000b000, mdio bus e000b000, phyaddr 0, interface rgmii-id  Warning: ethernet@e000b000 (eth0) using random MAC address - b2:ba:f7:7d:a1:49 eth0: ethernet@e000b000 Hit any key to stop autoboot:  0  Zynq>

Видим, что периферия проинициализирована и U-Boot запустился. Переходим к загрузке образа Linux.

❯ Загрузка Linux

Последний шаг, который необходимо выполнить для загрузки — загрузить в RAM оставшиеся компоненты: Linux Kernel, Device Tree Blob, RootFS. При этом очень важно правильно рассчитать адреса для загрузки этих компонентов так, чтобы один случайно не перезаписал другой. В идеале лучше всего грузить единый, скомпонованный в один файл, образ FIT Image, но я покажу как загрузить отдельные компоненты через XSCT через консоль:

xsct% targets -set -nocase -filter {name =~ "arm*#0"}      xsct% set device_tree_offset 0x1f00000 0x1f00000  xsct% set linux_kernel_offset 0x3000000 0x3000000  xsct% set rootfs_offset 0x2000000 0x2000000  xsct% stop  xsct% dow -data /home/megalloid/Xilinx/Tools/u-boot-xlnx/arch/arm/dts/zynqmini.dtb ${device_tree_offset} 100%    0MB   0.3MB/s  00:00     Successfully downloaded /home/megalloid/Xilinx/Tools/u-boot-xlnx/arch/arm/dts/zynqmini.dtb  xsct% dow -data /home/megalloid/Xilinx/Tools/linux-xlnx/arch/arm/boot/uImage ${linux_kernel_offset} 100%    4MB   0.4MB/s  00:10 Successfully downloaded /home/megalloid/Xilinx/Tools/linux-xlnx/arch/arm/boot/uImage  xsct% dow -data /home/megalloid/Xilinx/Tools/buildroot/images/rootfs.cpio.uboot ${rootfs_offset} 100%    4MB   0.5MB/s  00:09 Successfully downloaded /home/megalloid/Xilinx/Tools/buildroot/images/rootfs.cpio.uboot  xsct% con

После загрузки образов в оперативную память необходимо передать их на исполнение уже используя встроенные средства U-Boot через команду bootm в UART-терминале:

Zynq> bootm 0x3000000 0x2000000 0x1f00000

И наблюдаем как запускается ядро Linux:

## Booting kernel from Legacy Image at 03000000 ...    Image Name:   Linux-6.1.0-xilinx    Image Type:   ARM Linux Kernel Image (uncompressed)    Data Size:    4624016 Bytes = 4.4 MiB    Load Address: 00008000    Entry Point:  00008000    Verifying Checksum ... OK ## Loading init Ramdisk from Legacy Image at 02000000 ...    Image Name:       Image Type:   ARM Linux RAMDisk Image (uncompressed)    Data Size:    4940379 Bytes = 4.7 MiB    Load Address: 00000000    Entry Point:  00000000    Verifying Checksum ... OK ## Flattened Device Tree blob at 01f00000    Booting using the fdt blob at 0x1f00000 Working FDT set to 1f00000    Loading Kernel Image    Loading Ramdisk to 1e61c000, end 1ead225b ... OK    Loading Device Tree to 1e616000, end 1e61bd8b ... OK Working FDT set to 1e616000  Starting kernel ...  Booting Linux on physical CPU 0x0 Linux version 6.1.0-xilinx (megalloid@megalloid-xubuntu) (arm-linux-gnueabihf-gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #1 SMP PREEMPT Fri Aug  9 21:45:24 MSK 2024  ...  root@zynq:~ > uname -r Linux-6.1.0-xilinx

Если все образы были собраны корректно то произойдет загрузка Linux и всего необходимого для работы. 

❯ Заключение

Когда я освоил этот инструмент, время на отладку сократилось значительно, потому что раньше приходилось постоянно мучаться с пересборкой комплексного файла BOOT.bin и перекидывать это на microSD, возиться с кард-ридерами и прочим. Теперь процесс проверки ускорился, прямо скажем, значительно. И в качестве бонуса — для XSCT можно подготовить TCL-скрипт, который будет выполнять все эти действия автоматически.

Пользуйтесь на здоровье. Благодарю за внимание.

📚 Читайте также:


Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud в нашем Telegram-канале 

Перейти ↩


ссылка на оригинал статьи https://habr.com/ru/articles/835912/