Дебажим U-boot на реальном железе

МЕНЮ


Главная страница
Поиск
Регистрация на сайте
Помощь проекту
Архив новостей

ТЕМЫ


Новости ИИРазработка ИИВнедрение ИИРабота разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика

Авторизация



RSS


RSS новости


Продолжение предыдущей статьи, в которой мы ускорили разработку под embedded linux. Рабочая станция + sftp сервер + nfs сервер ускорили на порядок (10х) доставку изменений кода на целевое железо. Теперь не нужно часами компилировать код. В этой статье продолжаем очеловечивать разработку. На этот раз прикручиваем полноценную графическую IDE и пошаговую отладку кода на целевом железе с помощью программатора J-Link. Но пока только загрузчика U-boot. И автоматизируем развертывание рабочей среды разработчика с помощью Docker.

Микропроцессор, используемый в статье - imx6ull (ArmV7), программатор - j-link. В случае, если ваш процессор есть в списке поддерживаемых архитектур, - то у вас есть все шансы повторить все шаги, описанные в статье и получить возможность полноценной отладки программного кода на удаленном железе. По крайней мере, с ARM-ами затруднений возникнуть не должно. В данной статье рассматривается только отладка загрузчика (u-boot). Надеюсь, что и до ядра доберемся в одной из следующих статей.

Подготовка железа

  • Подключаем программатор по JTAG к целевой железке.

  • подключаем программатор по USB к хосту (рабочему ПК).

  • подключаем железку к хосту с помощью COM-порта.

  • подаем питание на железку.

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

Установка драйверов

Устанавливаем gdb-multiarch:

  $ sudo apt-get install gdb-multiarch

Скачиваем драйвера j-link и устанавливаем их:

  $ dpkg -i /drivers/JLink_Linux_V754b_x86_64.deb

Сборка toolchain

В вашем случае он может быть уже предустановлен/предскомпилирован. В нашем случае компилируем:

  $ mkdir /opt/eclipse/ $ cd /opt/elcipse/ $ git clone https://github.com/wireless-road/imx6ull-openwrt.git $ cd imx6ull-openwrt $ ./compile.sh flexcan_wifi

Установка IDE и создание проекта

Скачиваем Eclipse IDE for Embedded C/C++ Developers и распаковываем архив в /opt/eclipse.

Нажимаем File --> New Project и выбираем Makefile Project with Existing Code:

Задаем каталог с исходниками U-boot. В нашем случае, их можно найти в build_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/u-boot-wirelessroad_ecspi3/u-boot-2017.07:

Далее, необходимо задать переменные окружения для корректной работы eclipse с вашим toolchain. Для этого кликаете правой кнопкой мыши на проект в окне Eclipse, нажимаете Properties, а далее - C/C++ Build --> Environment исоздаете несколько переменных:

  ARCH=arm CROSS_COMPILE=arm-openwrt-linux-muslgnueabi- STAGING_DIR=/opt/eclipse/imx6ull/imx6ull-openwrt/staging_dir/

Переменная STAGING_DIR специфична для OpenWrt, - вам она, возможно, и не нужна.
Далее редактируем уже имеющуюся переменную PATH, добавив в ее начало следующее:

  /opt/eclipse/imx6ull-openwrt/build_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/linux-imx6ull_cortexa7/linux-4.14.199/scripts/dtc/:/opt/eclipse/imx6ull-openwrt/staging_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/host/bin:/opt/eclipse/imx6ull-openwrt/staging_dir/hostpkg/bin:/opt/eclipse/imx6ull-openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-7.5.0_musl_eabi/bin:/opt/eclipse/imx6ull-openwrt/staging_dir/host/bin:/bin:

Здесь, несколько каталогов тулчейна, разделенных двоеточием. В итоге, должно получиться следующее:

Следующим шагом отключаем дефолтный компилятор:

и задаем пути к заголовочным файлам нашего тулчейна:

  /opt/eclipse/imx6ull-openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-7.5.0_musl_eabi/arm-openwrt-linux-muslgnueabi/include/ /opt/eclipse/imx6ull-openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-7.5.0_musl_eabi/include/ /opt/eclipse/imx6ull-openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-7.5.0_musl_eabi/lib/gcc/arm-openwrt-linux-muslgnueabi/7.5.0/include/

Не забываем включить параллельную сборку:

Готово. Теперь можно попробовать собрать u-boot. Нажмите правой кнопкой мыши на проект и затем Clean Project для очистки проекта, Build Project для сборки:

Далее, необходимо, либо включить в концигурации u-boot опцию CONFIG_TOOLS_DEBUG, либо с помощью утилиты make menuconfig, либо в ручную задав в .config файле следующее:

  CONFIG_TOOLS_DEBUG=y

Возможно, в ide вы не найдете этого файла, поскольку он скрыт. Включить отображение скрытых файлов можно следующим образом:

После этого пересоберите проект, чтобы отладочные символы попали в итоговый бинарник.

Осталось совсем чуть-чуть, а именно настроить конфигурацию программатора. Нажмите Run --> Debug Configurations и задайте настройки:

Автоматизируй это.

Довольно длительная последовательность действий и практически каждый клиент, использующий наше BSP, каждый новый разработчик на каком-нибудь этапе да и споткнется, проверено на практике. Поэтому, логично будет автоматизировать развертнывание всей среды разработки, включая скачивание исходных кодов, сборку тулчейна и установку(например с Driverpaksolution) IDE. При этом, упаковка в docker контейнер дает надежку, что вся процедура развертывания будет более-менее стабильно разработать на максимально большом количестве компьютеров. Таким образом, вся выше-описанная инструкция заменяется четырьмя консольными командами:

  $ git clone https://github.com/wireless-road/openwrt-ide.git $ docker-compose run --name openwrt openwrt

И уже из консоли контейнера:

  $ ./setup_ide.sh $ /opt/eclipse/eclipse/eclipse

Исходники среды и более подробную инструкцию с некоторыми пояснениями можно найти тут. Eclipse, к сожалению, имеет ограниченные возможности для работы из консоли, но, к счастью, он portable. Таким образом, один раз настроив проект в eclipse, и упаковав его обратно в архив, можно переносить пред-настроенную IDE с машины на машину. Использование docker, в добавок к изоляции среды позволяет также решить возможные ошибки при распаковке архива по другому пути. В теории должно работать, практика покажет как оно на самом деле.

И последнее, - грязный хак, без которого, в нашем случае, u-boot не хотел работать под отладчиком. Вначале, в консоли u-boot вводим:

  => printenv fdtcontroladdr fdtcontroladdr=8ef216d8

и данное значение хард-кодим в u-boot/lib/fdtdec.c в функции fdtdec_setup():

Как этот костыль заменить корректными методами мы пока, к сожалению, не разобрались. Надеюсь, осилим в ближайшее время, но пока так. В вашем случае, если eclipse не сможет стартануть отладку кода, может оказаться полезным запустить отладку в консольном режиме. Для этого запускаете GDBServer:

  $ JLinkGDBServer -device MCIMX6Y2 -if JTAG -speed 1000

а следом запускаете консольный дебаггер, где u-boot - скомпилированный ранее образ загрузчика:

  $ gdb-multiarch u-boot --nx (gdb) target remote localhost:2331 (gdb) monitor reset (gdb) monitor halt (gdb) monitor sleep 200 (gdb) load

а далее шагаете до участка кода, на котором все рушится:

  (gdb) s reset () at arch/arm/cpu/armv7/start.S:40 40		b	save_boot_params (gdb) s save_boot_params () at arch/arm/cpu/armv7/start.S:116 116		b	save_boot_params_ret		@ back to my caller (gdb) s save_boot_params_ret () at arch/arm/cpu/armv7/start.S:56 56		mrs	r0, cpsr (gdb) s 57		and	r1, r0, #0x1f		@ mask mode bits (gdb) s 58		teq	r1, #0x1a		@ test for HYP mode 

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

Собственно, отладка

Задаем точку остановки, например функцию initcall_run_list, которая в цикле запускает функции инициализации перферии:

И нажимаем на кнопку Debug, а следом на кнопку Resume:

В итоге, должны попасть в выбранную нами функцию. Попробуйте нажать на кнопку Step Over несколько раз - курсор текущего положения должен начать перемещаться по коду:

Давайте попробуем начать знакомство с u-boot. Дойдя до строчки подсвеченной зеленым цветом на предыдущем скриншоте поставьте на ней точку остановки (двойной щелчок левой кнопкой мыши по синему полю слева напротив нужной строки), а далее нажимайте на кнопку Resume. После каждого нажатия на Resume, наводите курсор init_fnc_ptr, - в появляющемся всплывающем окне будет появляться название очередной функции, которая будет вызвана. В итоге, можно получить предстваление о том, какими функциями собтсвенно, и происходит инициализация периферии:

  setup_mon_len fdtdec_setup initf_malloc initf_bootstage init_console_record arch_cpu_init march_cpu_init initf_dm arch_cpu_init_dm board_early_init_f get_clocks timer_init board_post_clk_init env_init init_baud_rate serial_init console_init_f display_options									U-Boot 2017.07 (Sep 19 2021 - 11:24:07 +0300) display_text_info print_cpuinfo										CPU:   Freescale i.MX6ULL rev1.1 528 MHz (running at 396 MHz) 																CPU:   Industrial temperature grade (-40C to 105C) at 70C 																Reset cause: unknown reset show_board_info									Model: WirelessRoad ecspi3 																Board: MX6ULL WirelessRoad ECSPI3 module init_func_i2c										I2C:   ready announce_dram_init							DRAM: dram_init			 setup_dest_addr reserve_round_4k reserve_mmu reserve_video reserve_trace reserve_uboot reserve_malloc reserve_board setup_machine reserve_global_data reserve_fdt reserve_bootstage reserve_arch reserve_stacks dram_init_banksize show_dram_config								256MiB display_new_sp reloc_fdt reloc_bootstage setup_reloc											Setup fec 0                                 NAND:  0 MiB                                 MMC:   FSL_SDHC: 0                                 board_spi_cs_gpio bus 2 cs 0                                 SF: Detected w25q256 with page size 256 Bytes, erase size 4 KiB, total 32 MiB                                 In:    serial                                 Out:   serial                                 Err:   serial                                 Net:   FEC [PRIME]                                 Hit any key to stop autoboot:  0  

Здесь, левая колонка - вызывающиеся функции, правая - логи в консоли, выдаваемые функцией.

Продолжение

Тут и тут можно ознакомиться с удаленной отладкой приложений пользовательского уровня. В следующей же статье надеюсь добраться до пошаговой отладки ядра.


Источник: habr.com

Комментарии: