Репозиторий содержит baremetal-приложения для запуска на процессорах ARM CPU0 и MIPS32 RISC0.
Содержание
Для сборки используются тулчейны ARM и RISC. Для RISC должен использоваться тулчейн производства ЭЛВИС (тулчейн реализует обходы аппаратных ошибок ядра).
Оба тулчейна входят в состав MCom-03 Linux SDK. Описание тулчейнов — Средства сборки
Подготовка среды:
wget https://dist.elvees.com/mcom03/buildroot/2023.03/rockpi/images/aarch64-buildroot-linux-gnu_sdk-buildroot.tar.gz tar -xf aarch64-buildroot-linux-gnu_sdk-buildroot.tar.gz source aarch64-buildroot-linux-gnu_sdk-buildroot/environment-setup export MIPS32_CMAKE_TOOLCHAIN_FILE=$PWD/aarch64-buildroot-linux-gnu_sdk-buildroot/opt/toolchain-mipsel-elvees-elf32/share/cmake/toolchain.cmake export ARM_CMAKE_TOOLCHAIN_FILE=$PWD/aarch64-buildroot-linux-gnu_sdk-buildroot/share/buildroot/toolchainfile.cmake
Note
Ссылка на релиз MCom-03 Buidroot приведена справочно. Последняя версия данного репозитория может требовать более свежих версий компиляторов.
Сборка проекта для MIPS32 (RISC0):
cmake -S . -B build-mips -DCMAKE_TOOLCHAIN_FILE=$MIPS32_CMAKE_TOOLCHAIN_FILE make -j -C build-mips
Сборка проекта ARM64 (CPU0):
cmake -S . -B build-arm -DCMAKE_TOOLCHAIN_FILE=$ARM_CMAKE_TOOLCHAIN_FILE make -j -C build-arm
Для проверки форматирования используется pre-commit (см. pre-commit.com):
pre-commit run --all-files
Приложение настраивает ARM MMU, включает кэш данных и инструкций, выполняет бесконечный цикл чтения 4 непересекающихся областей памяти DDR общим размером N KиБ. Каждый раз после прочтения N КиБ * 1024 данных увеличивает на 1 счетчик в памяти SRAM. Приложение может запускаться на нескольких ядрах CPU, в этом случае каждое ядро читает отдельную область DDR и обновляет свой счетчик.
Приложение собирается только для архитектуры ARM64.
Приложение собирается в вариантах XIP и JTAG для запуска из QSPI0 XIP и через JTAG.
При запуске из QSPI0 XIP приложение настраивает частоты системного коммутатора, частоты CPU, загружает из QSPI0 по смещению 0x10000 байт ddrinit и запускает его, загружает из QSPI0 по смещению 0x20000 байт arm-hang-test в DDR по адресу 0x8_9040_0000 и запускает 4 ядра ARM с адреса 0x8_9040_0000. Далее в бесконечном цикле проверяет статус выполнения arm-hang-test. Если обнаружено зависание arm-hang-test (ARM CPU перестал обновлять счетчики в SRAM), приложение обновляет счетчик зависаний и выполняет перезагрузку с использованием WDT. При каждом запуске приложение печатает в UART суммарные счетчики количества выполненных загрузок и зависаний теста arm-hang-test, а также зажигает зеленый светодиод, если не было ни одного зависания или красный в обратном случае.
При запуске через JTAG алгоритм работы приложения аналогичен работе в режиме QSPI0 XIP за исключением того, что образы arm-hang-test и ddrinit загружаются через JTAG. В данном режиме есть возможность задавать длительность одной итерации теста. Для этого перед запуском MDB-скрипта необходимо установить переменную окружения TEST_MAX_ITERS.
Приложение собирается только для архитектуры MIPS32.
Приложение в бесконечном цикле выводит сообщение "Hello, world!" в UART0 и переключает состояние GPIO1_PORTD_0 (на плате MCom-03 BuB к этому GPIO подключен светодиод HL11).
Приложение собирается в двух (для MIPS) или трёх (для ARM64) вариантах:
- XIP для запуска с QSPI-памяти;
- RAM для запуска через JTAG или при загрузке через консоль UART;
- U-Boot для запуска из U-Boot (доступно только для ARM64).
- Собрать приложение для MIPS32.
- Прошить файл hello-world-mips-xip0.bin на SPI-флеш.
- Подключить SPI-флеш в разъём QSPI0.
- Выставить переключатели BOOT в состояние "000".
- Подать питание на MCom-03.
- Собрать приложение для ARM64.
- Прошить файл hello-world-aarch64-xip1.bin на SPI-флеш.
- Подключить SPI-флеш в разъём QSPI1.
- Выставить переключатели BOOT в состояние "101".
- Подать питание на MCom-03.
Собрать приложение для MIPS32.
Выставить переключатели BOOT в состояние "000" или "011".
Подать питание на MCom-03.
Запустить MDB и выполнить команды:
loadelf <путь_к_файлу>/hello-world-mips-ram.elf set risc.pc 0xa0000000 run
Собрать приложение для ARM64.
Выставить переключатели BOOT в состояние "000" или "011".
Подать питание на MCom-03.
Запустить MDB и выполнить команды:
set 0xbf000020 0x10 loadbin <путь_к_файлу>/hello-world-aarch64-ram.bin 0xa0000000 set 0xbf000000 0x10 set 0xbf001008 0x115 set 0xa1080000 0x2 set 0xa1080004 0x2 set 0xa1080008 0x2 set 0xa1000040 0x10 set 0xa100011C 0x0 set 0xa1000000 0x10
Собрать приложение для MIPS32.
Выставить переключатели BOOT в состояние "011".
Подать питание на MCom-03.
Передать содержимое приложения в накристальное ОЗУ:
cat hello-world-mips-ram.hex > /dev/ttyUSB0
Открыть UART-консоль:
minicom -D /dev/ttyUSB0
В UART-консоли ввести команду:
run
Собрать приложение для ARM64.
Запустить U-Boot. При появлении соощения Hit any key to stop autoboot нажать любую клавишу, что бы перейти в режим командной строки.
Загрузить elf-файл в память любым способом. Например:
через UART0 по протоколу XMODEM:
loadx $loadaddr
с SD-карты:
load mmc 1:1 $loadaddr /spi-flasher-aarch64-uboot.elf
Запустить исполнение elf-файла:
setenv autostart 1 bootelf $loadaddr
Note
В U-Boot доступно только 256 МиБ DDR-памяти в диапазоне от 0x8_9040_0000 до 0x8_A03F_FFFF поэтому загружать elf-файл необходимо в пределах этого диапазона. Следует учитывать, что в верхней части этого диапазона располагается код U-Boot, который нельзя перекрывать. Адрес начала U-Boot можно посмотреть в поле relocaddr, выполнив команду bdaddr. Для избежания повреждения кода U-Boot при загрузке файла рекомендуется использовать адрес из переменной loadaddr. При выполнении команды bootelf elf-файл будет распакован по адресу 0x8_9100_0000.
Приложение настраивает все частоты на близкие к максимальным значения, выводит из ресета все блоки и запускает непрерывные обновления 32-битных значений в памяти SPRAM на ARM CPU и MIPS1 CPU с целью создать высокое потребление MCom-03.
Во время запуска приложение выводит в UART0 на скорости 9600 бод настраиваемые частоты, а во время работы раз в 500 мс проверяет активность всех ядер ARM CPU и MIPS1 CPU. В случае если какое-то ядро зависло (перестало обновлять переменную в памяти SPRAM), выводится сообщение в UART0.
Приложение собирается только для архитектуры MIPS. Собирается несколько вариантов теста: для двух плат (отличаются используемыми GPIO) и с разным набором инициализируемых подсистем.
Приложение предназначено для загрузки в режиме UART0 (BOOT=3) и предоставляет функционал для работы с памятью SPI NOR, подключенной к QSPI0 или QSPI1. Приложение используется скриптом mcom03-flash-tools для прошивки SPI Flash.
Приложение spi-flasher предоставляет консоль через UART0 и может использоваться вручную без mcom03-flash-tools (кроме записи данных, которые передаются в бинарном виде). Для ручного запуска spi-flasher необходимо выполнить следующие действия:
Собрать spi-flasher для архитектуры MIPS (нужен файл spi-flasher-mips-ram.hex).
Выставить переключатели BOOT в состояние "011" и подать питание на MCom-03 (или нажать Reset, если питание уже было подано).
Выполнить:
cat spi-flasher-mips-ram.hex > /dev/ttyUSB0
Открыть UART в любом текстовом терминале (например,
minicom -D /dev/ttyUSB0).Выполнить команду
run. После этого начинает исполняться spi-flasher.
Основные команды:
baudrate <new_baudrate>- изменить скорость работы UART-порта. Поддерживаются любые значения скоростей от 50 по 115200, а так же 230400, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, 4000000. При вызове команды будет либо выведено сообщение о том, что скорость не поддерживается, либо выведено на старой скорости приглашение командной строки (символ "#"), после чего будет изменена скорость и на новой скорости выведено сообщениеBaudrate changed to <new_baudrate>"с новым приглашением командной строки.qspi <id> [v18]<id>- выбор QSPI0 или QSPI1;[v18]- выбор напряжения КП QSPI1. Для QSPI0 значение[v18]игнорируется.[v18]= 0 - режим 3.3В,[v18]= 1 - режим 1.8В (например,qspi 1 0).read <offset> <size> [text|bin]- чтение содержимого SPI Flash.<offset>- смещение, начиная с которого читать данные,<size>- размер данных. Если третий аргумент не указан или указан какtext, то данные выводятся в текстовом виде. Бинарный вид (bin) используется только для mcom03-flash-tools. Например,read 0 0x200.write <offset> <page_size>- запись данных в SPI Flash, начиная со смещения<offset>.<page_size>- размер страницы (можно узнать из описания на микросхему SPI Flash). Для записи используется собственный протокол: Запись данных.erase <offset>- очистка сектора, начинающегося со смещения<offset>. Размер сектора зависит от конкретной флеш-памяти (для S25FL128S сектор имеет размер 64 КиБ).readcrc <offset> <size>- посчитать и вывести в консоль CRC16 для<size>байт данных, начиная со смещения<offset>.custom <tx_data> <rx_size>- отправка на SPI Flash данных<tx_data>и вывод<rx_size>байт ответа.<tx_data>- это набор байт, записанных слитно в 16-ричном представлении. Перед<tx_data>можно не указывать0x. Например, командаcustom 0b00020000 64илиcustom 0x0b00020000 64отправит на SPI 5 байт[0b, 00, 02, 00, 00](команда FAST_READ, адрес 0x200 и один dummy-байт) и прочитает 64 байта ответа.<rx_size>может быть любым неотрицательным целым числом.bootrom- прыжок в код BootROM. Это действие выглядит как перезагрузка. Доступно только для сборки под процессор MIPS. Для тестирвоания команды можно использовать следующий код:# загрузить SPI Flasher в память и запустить cat spi-flasher-mips-ram.hex > /dev/ttyUSB0 sleep 1 echo "run" > /dev/ttyUSB0 # проверить, что запускается именно SPI Flasher и он знает команду "bootrom" echo -e "help\r" > /dev/ttyUSB0 & grep "bootrom" /dev/ttyUSB0 sleep 1 # выполнить команду "bootrom" и проверить, что запущена именно консоль BootROM echo -e "bootrom\r" > /dev/ttyUSB0 sleep 1 echo -e "help\r" > /dev/ttyUSB0 & grep "devcommit" /dev/ttyUSB0
exit- выход в родительскую программу, из которой был вызван spi-flasher. Доступно только для сборки под U-Boot.
Команда write указывает смещение и размер страницы. Команда возвращает строку:
Ready for data #
После чего ожидает блоки данных. Структура блока:
+--------------------------------------------------+ | len_lo | len_hi | crc_lo | crc_hi | payload .... | +--------------------------------------------------+
len_loиlen_hi- младший и старший байты размера данныхpayloadв байтах (размер блока не должен превышать размер страницы, указанный командойwrite);crc_loиcrc_hi- младший и старший байты CRC16 от данныхpayload;payload- данные для записи.
Если размер указан нулевой размер payload, то происходит возврат в консоль.
После передачи последнего байта payload spi-flasher выдаёт один из ответов:
- символ 'R' - означает, что блок записан и spi-flasher ожидаёт следующий блок;
- символ 'C' - означает, что CRC16 от
payloadне соответствует укзанному (данные повредились при передаче через UART). В этом случае запись не производилась и можно либо повторить передачу этого блока, либо прервать запись и вернуться в консоль, указав нулевой размер данных; - строка 'En<сообщение>n' - означает, что произошла ошибка.