Скамейки и программное обеспечение Baremetal

Я ищу некоторую информацию о программировании на голом железе. Я работаю на разных платформах PowerPC и в настоящее время пытаюсь доказать, что ядро ​​Linux не влияет на некоторые тесты. Эти тесты довольно простые, загружаются и сохраняются в asm volatile, а также некоторые тесты (Coremark, Dhrystone и т. д.). Эти тесты отлично работают в Linux, но теперь мне нужно протестировать их на голом металле, в среде, в которой у меня нет опыта. На всех моих платформах установлен u-boot, и мне интересно, есть ли такие приложения, которые позволили бы мне запускать кросс-компилированные тесты powerpc-eabi? например, сможет ли gdbserver, запущенный u-boot, обмениваться данными через последовательный порт или Ethernet? Возможно ли, чтобы U-boot вызывал busybox?


person d34db33f    schedule 24.01.2014    source источник


Ответы (3)


Uboot - это загрузчик... используйте его. Вероятно, у вас есть загрузчик xmodem или ymodem с uboot, если дело дойдет до драки, вы можете превратить свою программу в длинную серию операций записи слов в память, а затем перейти к ней.

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

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

В зависимости от того, как вы написали свою программу на языке высокого уровня (я предполагаю, что C), вам, возможно, придется обнулить область .bss и настроить область .data, хорошая вещь в использовании загрузчика для копирования программы в оперативную память и просто запустите его, обычно вам не нужно ничего этого делать, бинарный файл, который вы загружаете и запускаете, уже имеет обнуленный bss и .data в нужном месте. Таким образом, нужно вернуться к настройке стека и ветвления или просто ветвления, поскольку вам может даже не понадобиться устанавливать стек.

Построение программы на «голом железе» — настоящая проблема, потому что у вас нет системы для выполнения системных вызовов, а отказаться от этого и/или смоделировать сложно. newlib, например, немного упрощает жизнь, поскольку в ней очень легко заменить системный бэкэнд, так что вы можете, например, оставить printfs в dhrystone (вместо того, чтобы удалить их и найти другой способ вывода строк по мере необходимости или вывода результатов.

скомпилировать в объект файлы C легко, собрать сборку легко, и вы должны быть в состоянии сделать это с помощью вашего кросс-компилятора powerpc-eabi gcc. поскольку это, вероятно, плоский кусок оперативной памяти, вы, вероятно, можете сделать что-то вроде -Ttext 0x123450000, где число — это любой базовый адрес оперативной памяти, которую вы хотите использовать. если у вас есть какие-либо умножения или деления, или любые числа с плавающей запятой, или любые другие функции библиотеки gcc (которые заменяют вещи, которые ваш процессор может или не может делать, или требуют оболочки для их правильного выполнения) или любые вызовы libc, тогда он попытается связать их в , В идеале библиотеки gcc просты, но в зависимости от кросс-компилятора они могут быть проблемой, в худшем случае возьмите исходники gcc и создайте эти функции самостоятельно, или получите или создайте другой кросс-компилятор gcc с другими целевыми параметрами (как правило, простая вещь сделать).

Я настоятельно рекомендую вам разобрать двоичный файл и убедиться, что точка входа вашего бутстрапа не находится в начале двоичного файла. используйте objcopy для создания бинарного файла powerpc-...-objcopy myprog.elf -O binary myprog.bin. затем используйте xmodem или ymodem в приглашении uboot, чтобы скопировать эту программу и запустить ее.

резервное копирование. из таблиц данных для части, когда вы ищете uart и выясняете базовый адрес, вы должны сначала использовать приглашение uboot для записи по адресу регистра передачи uart, например, напишите 0x30 на этот адрес, и если у вас есть правильный адрес затем, прежде чем он снова напечатает приглашение uboot после вашей команды, в выводе должен быть дополнительный ноль «0». Если вы не можете заставить его сделать это с помощью одной записи из командной строки uboot, вы не заставите его работать в любой программе, у вас неправильный адрес или вы делаете что-то еще неправильно.

Затем напишите очень маленькую программу на ассемблере, которая выводит символ в UART, записывая по этому адресу, а затем подсчитывает его до некоторого большого числа в зависимости от скорости вашего процессора. Если вы работаете на частоте 100 МГц, сосчитайте до 100 миллионов или более (или сосчитайте до нуля от нескольких сотен миллионов), затем перейдите к началу и повторите, вывод, ожидание вывода, ожидание. создайте и свяжите эту крошечную программу, а затем загрузите ее с помощью xmodem или чего-либо еще и перейдите к ней. Если вы не можете заставить его выводить символ каждые несколько секунд, вы не сможете перейти к чему-то более сложному.

Следующая небольшая программа опрашивает регистр состояния, ждет, пока буфер tx опустеет, затем записывает 0x30 в регистр tx. увеличьте регистр, содержащий 0x30, до 0x31 и этот регистр с 0x37. перейти к ожиданию пустого tx и вывести новое значение 0x31, сделать это бесконечным циклом. Если после того, как вы начнете бегать, вы не увидите 01234567012345670... повторяющееся бесконечно без искажения чисел, они должны быть 0-7 и повторяться, тогда вы не сможете перейти к чему-то более сложному.

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

Начните с малого с любых библиотечных вызовов, без которых, по вашему мнению, вы не сможете обойтись (например, printf), и если вы не можете сделать простой printf("Hello World\n"); работать со всеми связями и системным бэкэндом и т. д., тогда вы не сможете запустить Dhrystone и оставить его системные вызовы.

Компилятор, скорее всего, превратит некоторые вызовы Dhrystone в вызовы memcpy или memset, которые вам придется реализовывать, скорее всего, существуют настроенные вручную версии этих сборок, и ваши показатели производительности Dhrystone могут и будут сильно зависеть от реализации подобных функций, поэтому вы не можете просто сделать это

void memset ( unsigned char *d unsigned char c, unsigned int len)
{
    while(len--) *(d++)=c;
}

и ожидать любой производительности. Вероятно, вы можете взять их версии gcc lib или gnu libc или просто украсть их из сборки Linux одного из этих тестов (разобрать и взять asm), таким образом, у вас будут яблоки к яблокам...

Бенчмаркинг часто более фальшивый, чем реальный, очень легко взять один и тот же исходный код теста с одним и тем же компилятором в той же среде (в Linux или на «голом железе» и т. д.) и показать совершенно разные результаты, выполняя различные простые действия, используя разные параметры компилятора. , перестановка функций, добавление нескольких nops в загрузчик и т. д. Все, что нужно либо для создания другого кода, либо для использования преимущества кэша, либо для того, чтобы пострадать от него, и т. д. Если вы хотите показать, что голое железо работает быстрее, чем в операционной системе, это скорее всего НЕ произойдет без небольшой работы. Вам нужно будет получить кэши i и d, кеш d, вероятно, потребует, чтобы вы подняли mmu и так далее. Все это может быть исследовательским проектом. Затем вам нужно знать, как управлять сборкой вашего компилятора, убедитесь, что оптимизация включена, как уже упоминалось, добавьте или удалите nops в вашем бутстрапе, чтобы изменить выравнивание узких циклов в коде по отношению к строкам кеша. В операционной системе есть прерывания и другие вещи, возможно, вы работаете в многозадачном режиме, поэтому с голым железом вы должны иметь возможность запускать тесты, такие как dhrystone, с той же скоростью или быстрее, чем Linux, если вы не можете, это не потому, что Linux быстрее это потому, что вы не делаете что-то правильно в своей реализации на голом железе.

Да, вы, вероятно, можете использовать gdb для общения с uboot и загрузки программ, не уверен, что я никогда не использую gdb, я предпочитаю использовать тупой терминал и модем x или y или использовать jtag с терминалом openocd (telnet в openocd, а не gdb).

person old_timer    schedule 25.01.2014
comment
вы можете выяснить, где находится оперативная память, из которой вы хотите загрузить и запустить свою программу, изучив сценарии uboot, используемые для копирования linux в оперативную память, затем перейти к ссылке на оперативную память (printenv?) и загрузить и запустить вашу программу по тому же адресу... - person old_timer; 25.01.2014
comment
Спасибо за этот потрясающий ответ. Я попробую все эти маленькие программы. - person d34db33f; 25.01.2014

Вы можете попробовать скомпилировать тесты вместе с u-boot. Так что после завершения загрузки u-boot загружает вашу программу. Я знаю, что это было возможно для платформ ARM. Я не знаю, существуют ли наборы инструментов для разработки «голого железа» PowerPC.

person akarapatis    schedule 24.01.2014
comment
u-boot уже на моей машине, я не уверен, что буду перекомпилировать его снова. И у меня много тестов, поэтому я не думаю, что это самый простой вариант. Спасибо, в любом случае! - person d34db33f; 26.01.2014

На https://cirosantilli.com/linux-kernel-module-cheat/#dhrystone в этой фиксации я предоставил минимальный работающий пример Dhrystone baremetal с Newlib на ARM, который работает на QEMU и gem5. С этой отправной точкой не должно быть сложно перенести его на PowerPC или другие ISA и реальные платформы.

В этой настройке Newlib реализует все, кроме самих системных вызовов, как описано по адресу: https://electronics.stackexchange.com/questions/223929/c-standard-libraries-on-bare-metal/400077#400077, что значительно упрощает использование больших подмножеств стандартной библиотеки C.

И я использую newlib через цепочку инструментов, созданную с помощью crosstool-NG.

Некоторые ключевые файлы в этой настройке:

  • скрипт компоновщика
  • реализации системных вызовов
  • полная команда make, показывающая некоторые используемые флаги:

    make \
      -j 8 \
      -C /home/ciro/bak/git/linux-kernel-module-cheat/submodules/dhrystone \
      CC=/home/ciro/bak/git/linux-kernel-module-cheat/out/crosstool-ng/build/default/install/aarch64/bin/aarch64-unknown-elf-gcc \
      'CFLAGS_EXTRA=-nostartfiles -O0' \
      'LDFLAGS_EXTRA=-Wl,--section-start=.text=0x40000000 -T /home/ciro/bak/git/linux-kernel-module-cheat/baremetal/link.ld' \
      'EXTRA_OBJS=/home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/lib/bootloader.o /home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/lib/lkmc.o /home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/lib/syscalls_asm.o /home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/lib/syscalls.o' \
      OUT_DIR=/home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/submodules/dhrystone \
      -B \
    ;
    

Связано: Как скомпилировать тест dhrystone для RV32I

person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 02.04.2020