Поднимаем Linux на MIPSfpga и ПЛИС Altera

в 21:56, , рубрики: C, fpga, mips, MIPS microAptiv UP, MIPSfpga, SoC, Verilog, Анализ и проектирование систем, программирование микроконтроллеров, системное программирование

КДПВ

Предоставленная Imagination Technologies документация на MIPSfpga очень хорошо и подробно описывает развертывание Linux. Но используемая при этом система на кристалле построена с помощью Xilinx-специфических периферийных модулей. Потому ее повторение на отладочной плате с ПЛИС Altera в исходном виде представляется невозможным. Решением является система на кристалле MIPSfpga-plus с ее платформонезависимой периферией. О том, как запустить на ней Linux, читайте в этой статье.

Введение

Сразу отметим, что получаемой в результате описанных ниже действий конфигурации пока что далеко от идеала. На данный момент не поддерживается загрузка с внешнего носителя, а в числе поддерживаемых устройств можно упомянуть только UART и GPIO. Поэтому фронт дальнейшей работы по развитию системы MIPSfpga-plus представляется очень широким.
Далее предполагается, что читатель:

  • знаком с предметной областью в объеме учебника Харрис-энд-Харрис [L1];
  • имеет доступ к исходным кодам MIPSfpga [L2] и mipsfpga-plus [L3];
  • настроил и проверил работу MIPSfpga-plus с SDRAM [L5] и UART [L6], а также в режиме удаленной отладки [L4];
  • имеет некоторые навыки использования средств разработки ОС Linux, опыт работы с git;

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

  • отладочная плата Terasic DE10-Lite с ПЛИС Altera MAX10 и SDRAM 64Mб на борту;
  • плата Pinboard II в качестве отладчика и UART-конвертера. Вы можете использовать любую плату с FTDI USB-чипом, поддерживающим MPSSE, пример такой конфигурации описан в [L4];
  • компьютер Windows 7 (x64) и Quartus Prime 16.1 для синтеза и программирования ПЛИС;
  • виртуальная машина с Ubuntu 17.04 (x64) для сборки ядра и RAM-образа файловой системы;
  • доступ в Интернет;

В случае, если вы планируете серьезно и глубоко погрузиться в магию ядра Linux, настойчиво рекомендуется ознакомится с материалами [L7], в частности, с презентациями [L8] и [L9].
Если все перечисленные требования выполнены, начнем!

Синтез конфигурации и программирование ПЛИС

  • в настройках MIPSfpga-plus (файл mfp_ahb_lite_matrix_config.vh) должны быть включены периферийные модули работы с SDRAM и UART, а также отладка через MPSSE — если используется механизм отладки, описанный в [L4]:

    `define MFP_USE_SDRAM_MEMORY
    `define MFP_USE_DUPLEX_UART
    `define MFP_USE_MPSSE_DEBUGGER

  • с помощью Quartus выполнить сборку MIPSfpga-plus и программирование ПЛИС;

Сборка ядра и RAM-диска

Предполагается, что дальнейшие действия выполняются на машине под управлением Linux.

  • обновить список доступных для системы пакетов:

    sudo apt-get update

  • установить утилиты и библиотеки, необходимые для конфигурирования и сборки:

    sudo apt-get install -y build-essential git libncurses5-dev bc unzip

  • создать каталог, в котором будет идти вся дальнейшая работа и перейти в него:

    mkdir ~/mipsfpga
    cd ~/mipsfpga

  • выполнить загрузку toolchain с сайта Imagination Technologies:

    wget http://codescape-mips-sdk.imgtec.com/components/toolchain/2016.05-06/Codescape.GNU.Tools.Package.2016.05-06.for.MIPS.MTI.Linux.CentOS-5.x86_64.tar.gz

  • создать каталог и развернуть в нем скачанный пакет:

    mkdir ~/mipsfpga/toolchain
    tar -xvf Codescape.GNU.Tools.Package.2016.05-06.for.MIPS.MTI.Linux.CentOS-5.x86_64.tar.gz -C ~/mipsfpga/toolchain

  • желательно (но не обязательно) прописать путь к развернутым исполняемым файлам в переменную $PATH, это упростит работу с ними. Например, в ~/.profile

    pathadd() {
    if [ -d "$1" ] && [[ ":$PATH:" != *":$1:"* ]]; then
        PATH="$1${PATH:+":$PATH"}"
    fi
    }
    pathadd "$HOME/bin"
    pathadd "$HOME/.local/bin"
    pathadd "$HOME/mipsfpga/toolchain/mips-mti-linux-gnu/2016.05-06/bin"

  • получаем ядро Linux:

    git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git kernel

  • получаем buildroot, с помощью которого будет сформирован RAM-образа файловой системы:

    git clone git://git.buildroot.net/buildroot

  • создаем каталог для патчей buildroot и Linux, необходимых для развертывания на MIPSfpga-plus:

    mkdir patches

  • скачиваем патчи [L10], сохраняем их в только что созданном каталоге;

  • переходим в каталог с buildroot и откатываемся на версию 2017.05.1 (коммит f3d8beeb3694):

    cd buildroot
    git checkout 2017.05.1

  • применяем патч к buildroot:

    git apply ../patches/MIPSfpga_buildroot.patch

  • выполняем конфигурирование buildroot:

    make xilfpga_static_defconfig

  • при необходимости вносим изменения в конфигурацию:

    make menuconfig

  • запускаем сборку RAM-образа файловой системы и идем пить вкусный кофе (чай, пиво или кто что любит), т.к. процесс это весьма продолжительный:
    make

  • переходим в каталог с ядром Linux и проверяем, что RAM-образа файловой системы находится по ожидаемому нами пути (в дальнейшем нам необходимо будет указать его в конфигурации ядра):

    cd ../kernel/
    ls -l ../buildroot/output/images/rootfs.cpio

  • откатываемся на версию v4.12.1 (коммит cb6621858813), т.к. именно от нее сформирован патч:

    git checkout v4.12.1

  • применяем патч:

    git apply ../patches/MIPSfpga_linux.patch

  • применяем базовую конфигурацию ядра MIPSfpga:

    make ARCH=mips xilfpga_de10lite_defconfig

  • запускаем редактор конфигурации:

    make ARCH=mips menuconfig

  • включаем поддержку RAM-диска и прописываем к нему путь (ранее мы проверяли существование этого файла):

RAM disk settings

  • сохраняем изменения, выходим из графического конфигуратора и запускаем сборку ядра:
    make ARCH=mips CROSS_COMPILE=~/mipsfpga/toolchain/mips-mti-linux-gnu/2016.05-06/bin/mips-mti-linux-gnu-

Загрузка ядра в память и запуск

  • на машине, к которой подключен аппаратный отладчик, запускаем OpenOCD, например так, как это описано в [L4];
  • на этой же машине запускаем терминал (например, PuTTY) и подключаемся к COM-порту (скорость 115200);
  • на Linux-компьютере, где мы выполняли сборку, запускаем gdb из состава MIPS toolchain. Предполагается, что мы находимся в каталоге с собранным ядром:

    mips-mti-linux-gnu-gdb ./vmlinux

    Дальнейшие действия выполняются в консоли gdb.

  • подключаемся к OpenOCD, который запущен на машине с аппаратным отладчиком:

    (gdb) target remote 192.168.Х.Х:3333

  • выполняем сброс системы MIPSfpga:

    (gdb) mo reset halt

  • сообщаем отладчику, что наша система Little Endian:

    (gdb) set endian little

  • запускаем ядро на выполнение:

    (gdb) continue

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

Лог загрузки

Linux version 4.12.1+ (stas@ubuntu) (gcc version 4.9.2 (Codescape GNU Tools 2016.05-06 for MIPS MTI Linux) ) #1 Sat Jul 22 14:35:05 MSK 2017
CPU0 revision is: 00019e60 (MIPS M14KEc)
MIPS: machine is terasic,de10lite
Determined physical RAM map:
 memory: 04000000 @ 00000000 (usable)
Initrd not found or empty - disabling initrd
Primary instruction cache 4kB, VIPT, 2-way, linesize 16 bytes.
Primary data cache 4kB, 2-way, VIPT, no aliases, linesize 16 bytes
Zone ranges:
  Normal   [mem 0x0000000000000000-0x0000000003ffffff]
Movable zone start for each node
Early memory node ranges
  node   0: [mem 0x0000000000000000-0x0000000003ffffff]
Initmem setup node 0 [mem 0x0000000000000000-0x0000000003ffffff]
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
Kernel command line: console=ttyS0,115200
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 60512K/65536K available (1830K kernel code, 99K rwdata, 320K rodata, 944K init, 185K bss, 5024K reserved, 0K cma-reserved)
NR_IRQS:8
clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 38225208935 ns
sched_clock: 32 bits at 50MHz, resolution 20ns, wraps every 42949672950ns
Console: colour dummy device 80x25
Calibrating delay loop... 10.81 BogoMIPS (lpj=21632)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
devtmpfs: initialized
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
futex hash table entries: 256 (order: -1, 3072 bytes)
clocksource: Switched to clocksource MIPS
random: fast init done
workingset: timestamp_bits=30 max_order=14 bucket_order=0
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
console [ttyS0] disabled
b0400000.serial: ttyS0 at MMIO 0xb0401000 (irq = 0, base_baud = 3125000) is a 16550A
console [ttyS0] enabled
Freeing unused kernel memory: 944K
This architecture does not have kernel memory protection.
mount: mounting devpts on /dev/pts failed: No such device
mount: mounting tmpfs on /dev/shm failed: Invalid argument
mount: mounting tmpfs on /tmp failed: Invalid argument
mount: mounting tmpfs on /run failed: Invalid argument
Starting logging: OK
Initializing random number generator... done.
Starting network: ip: socket: Function not implemented
ip: socket: Function not implemented
FAIL

Welcome to MIPSfpga
mipsfpga login:

Работа с GPIO

Воспользуемся возможностями Linux для того, чтобы поуправлять той периферией, которая нам доступна (на момент написания статьи это GPIO, правда не в полном объеме):

  • проверяем, что драйвер GPIO загружен и устройство доступно:

    ls /sys/class/gpio/
    export       gpiochip480  unexport

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

    mount -t debugfs none /sys/kernel/debug
    cat /sys/kernel/debug/gpio
    gpiochip0: GPIOs 480-511, parent: platform/bf800000.gpio, bf800000.gpio:

  • активируем LED0 (в текущем случае это gpio480):

    echo 480 > /sys/class/gpio/export

  • переводим его в режим вывода:

    echo out > /sys/class/gpio/gpio480/direction

  • переводим его в высокий уровень:

    echo 1 > /sys/class/gpio/gpio480/value

  • если все сделано правильно, то светодиод LED0 должен светиться.

Что дальше

Описанная конфигурация — это, по сути, только начало портирования Linux на систему MIPSfpga-plus. К числу работ, которые необходимо выполнить, чтобы система могла нормально использоваться для практических задач, можно отнести:

  • поддержка существующих периферийных устройств: контроллер прерываний, более полная поддержка GPIO, Altera ADC;
  • поддержка периферийных устройств MIPSfpga-plus, включая отсутствующие на данный момент PWM, интерфейсы SPI (присутствует ограниченно), I2C, DDR и Ethernet;
  • поддержка внешних носителей (mmc/sdram) и возможности загрузки с них;
    По этой причине, если в текущей конфигурации вы столкнетесь с какими-то ошибками (багами), то не удивляйтесь — работы еще много.

Благодарности

Автор выражает благодарность коллективу переводчиков учебника Дэвида Харриса и Сары Харрис «Цифровая схемотехника и архитектура компьютера» [L1], компании Imagination Technologies за академическую лицензию на современное процессорное ядро и образовательные материалы, а также персонально Юрию Панчулу YuriPanchul за его работу по популяризации MIPSfpga.

Ссылки

[L1] — Цифровая схемотехника и архитектура компьютера
[L2] — Как начать работать с MIPSfpga;
[L3] — Проект MIPSfpga-plus на github;
[L4] — MIPSfpga и внутрисхемная отладка;
[L5] — MIPSfpga и SDRAM. Часть 1;
[L6] — MIPSfpga и UART;
[L7] — Free Electrons. Free training materials and conference presentations;
[L8] — Free Electrons. Embedded Linux system development course;
[L9] — Free Electrons. Linux kernel and driver development course;
[L10] — Патчи для buildroot и Linux, необходимые для развертывания на MIPSfpga-plus.

Автор: Stanislav Zhelnio

Источник

Поделиться

* - обязательные к заполнению поля