Практическое применение RISC-V при программировании микроконтроллеров
Удаленное подключение из Windows + IDE
Мало кто из желающих “потыкать длинной палочкой” в контроллер захочет устанавливать для этого незнакомую операционную систему и изучать работу с ней. Поэтому попробую расписать как подключиться к стенду из Windows, открыть проект в среде разработки, залить результат на стенд и проверить работоспособность.
Важно: ни самой этой операционной системой, ни средами разработки я не пользовался уже лет десять, поэтому какие-то вещи наверняка устарели, какие-то можно сделать лучше, быстрее и удобнее. Но, по крайней мере, мой вариант хоть как-то работает.
Допустим, все, связанное с контроллером, будет хранится в каталоге C:\riscv\
: среда разработки, документация, проекты.
SSH
Основной способ доступа к стенду - разумеется, ssh. В windows его клиент из коробки не установлен, поэтому придется выкачивать со сторонних ресурсов. Я нашел, например, на гитхабе. Скачиваем, распаковываем в какое-нибудь место (желательно чтобы в пути не было спецсимволов вроде пробелов). Простой запуск установочного скрипта не срабатывает из-за политик безопасности, поэтому сначала их надо отключить. Для этого запускаем консоль (лучше современную, а не cmd.exe) от имени администратора (ждем полминуты, пока запустится, но мы ведь никуда не спешим, верно?) и вводим туда set-executionpolicy remotesigned
. Эту подсказку нам выдаст и сама консоль, если запустить скрипт из нее. Теперь можно запустить установочный скрипт install-sshd.ps1
. В конце он предложит перезагрузиться.
Далее надо запустить агента ssh: ssh-agent
. К счастью, при установке скрипт правильно прописывает все пути, и обращаться к ssh можно без указания полного пути.
Авторизация на сервере организована при помощи ssh-ключей: при помощи утилиты ssh-keygen
надо сгенерировать пару ключей. Просто запускаем ее из консоли без параметров и отвечаем на вопросы как ключи будут называться и каким паролем зашифрованы. Допустим, в качестве имени ключа мы выбрали C:\riscv\ssh\karakatitsa
, тогда это имя соответствует приватному ключу, его никому показывать нельзя, и в пару к нему будет создан C:\riscv\ssh\karakatitsa.pub
- публичный ключ. Его нужно тем или иным способом передать админу стенда. В ответ вы получите настройки соединения: адрес сервера, логин и все остальное например так:
address: 012.345.678.90
port: 42
login: user
camera port: 100500
Их можно, конечно, и руками вбивать при каждом подключении, например, так:
ssh user@012.345.678.90 -p 42 -L100500:localhost:8008
Но проще будет задать этому подключению человеко-читаемый псевдоним. Для этого в домашнем каталоге пользователя создаем каталог .ssh
- да, обязательно с точкой. Правда, у меня его создать средствами Проводника не получилось, впрочем консоль спасает: mkdir C:\users\user\.ssh
(логин моего тестового пользователя так и называется user). И уже в нем файл настройки config
, без расширения, то есть не config.txt
например. Если сомневаетесь, можно опять же из консоли: echo "" > C:\users\user\.ssh\config
. Теперь можно открыть этот файл любым текстовым редактором и вписать в него что-то вроде
Host karakatitsa
Hostname 012.345.678.90
Port 42
User user
LocalForward 100500 localhost:8008
IdentityFile C:\riscv\ssh\karakatitsa
Важно: в левой части должны быть именно Host, Hostname, а не что попало: утилиты ssh читают этот файл и ищут именно такие строки. Отдельно стоит рассказать о IdentityFile: эта опция необязательная, если уж вы указали ssh использовать данный приватный ключ, он его так и так найдет. Но не все серверы адекватно воспринимают когда к ним ломятся с десятком ключей подряд “а вдруг хоть этот подойдет”. Про LocalForward я расскажу чуть позже. Ну а Host это всего лишь псевдоним, под которым нам будет удобно подключаться, его в принципе можно выбрать любым.
Теперь, когда настройки внесены, осталось проверить возможно ли подключение. Но прежде надо зарегистрировать свой приватный ключ: ssh-add C:\riscv\ssh\karakatitsa
. И только теперь подключаемся: ssh karakatitsa
.
Но вот беда, консоль винды почему-то не отображает половину букв, да даже строку приветствия. Чтобы это исправить, можно запустить на сервере оболочку screen. Ах да, и во избежание очередных косяков с отображением, сразу же поменять в настройках консоли шрифт с растрового на векторный. Иначе не-латиница может вообще не отображаться. Впрочем, даже после этого какие-то баги с отображением останутся. Тут только искать нормальную консоль… Впрочем, мы ведь рассматриваем вариант с IDE, так что много нам в консоли делать не придется.
Теперь, когда мы подключились к серверу, можно проверить идет ли трансляция с камеры. Для этого на сервере запущена специальная программа, которая кодирует данные с нее и пересылает в некоторый порт (в нашем примере - в 100500-й). Далее ssh благодаря настройке LocalForward перенаправляет их в порт 8008 на нашей локальной машине. Соответственно, можно просто открыть браузер и вписать в адресную строку localhost:8008
, должен появиться интерфейс трансляции. Там нажимаем stream и наслаждаемся низкокачественной картинкой платы.
IDE
В качестве среды разработки GigaDevice, производитель нашего контроллера, предлагает NucleiStudio, среду на основе Eclipse. Не знаю насколько она хороша, но, по крайней мере, с ней идет компилятор risc-v. Соответственно, скачиваем ее и распаковываем куда-нибудь в C:\riscv\NucleiStudio
. Важно чтобы путь был как можно проще, без пробелов и прочих спецсимволов. Как заставить ее корректно работать из Program Files
я так и не понял.
Чтобы не писать проект с нуля, возьмем какой-нибудь blink из примеров к этому циклу лекций, и попробуем адаптировать его.
При запуске, IDE предлагает нам среди прочего импорт существующего проекта с существующим makefile’ом (только внимательно перепроверьте как какой проект вы импортируете, нас интересует RISC-V).
Project -> properties -> C/C++ build -> Builder, снимаем галочку и прописываем в Build command полный путь к утилите make: C:\riscv\NucleiStudio\toolchain\gcc\bin\make
Еще стоит исправить кодировку и конец строки по умолчанию: Project -> properties -> Resource, исправляем Text file encoding на UTF-8 и New text file delimiter на Unix. Иначе при копировании с/на сервер могут быть проблемы.
Теперь, когда наш makefile подхватился, можно решать проблемы отсутствующих программ. Например, там в качестве компилятора указан riscv64-unknown-elf-
, но в нашей системе он называется иначе. Идем в недра каталога с NucleiStudio и ищем C:\riscv\NucleiStudio\toolchain\gcc\bin
, там будут riscv-nuclei-elf-gcc
и прочие. Вот вместо riscv64-unknown-elf-
и пропишем полный путь, причем обязательно с кавычками "C:\riscv\NucleiStudio\toolchain\gcc\bin\riscv-nuclei-elf-"
Компиляция прошла успешно, надо попробовать прошить полученный файл в контроллер. Для этого его надо скопировать на сервер и запустить скрипт прошивки. Собственно прошивку я предлагаю повесить на кнопочку Run среды. Правда, по умолчанию при нажатии на эту кнопочку она порывается нашу прошивку выполнить - угу, RISC-V файл на x86-железе - и закономерно терпит неудачу. Чтобы IDE чувствовала себя получше, вместо реального файла подсунем ей скрипт для прошивки, а чтобы случайно его не потерять, впишем его создание в тот же makefile под специальным таргетом:
REMOTEPATH := "/home/user/prog/test"
...
burn.bat:
echo "scp $(frmname).bin karakatitsa:$(REMOTEPATH)/test.bin" > $@
echo "ssh karakatitsa \"cd $(REMOTEPATH) ; ./prog.sh\"" >> $@
Для тех, кто не знаком с makefile’ом, здесь создается burn.bat со следующим содержимым:
scp res/firmware.bin karakatitsa:/home/user/prog/test/test.bin
ssh karakatitsa "cd /home/user/prog/test ; ./prog.sh"
При его запуске файл прошивки копируется с локальной машины в /home/user/prog/test/test.bin
на сервере, потом там же, на сервере выполняется две команды подряд: cd /home/user/prog/test
и ./prog.sh
, то есть перейти в рабочий каталог, куда мы только что скопировали файл, и запустить его прошивку. Сам скрипт prog.sh
я выдрал из того же makefile:
#!/bin/bash
uart_port="/dev/tty_GD32_PROG_0"
stty -F $uart_port 300
stty -F $uart_port 50
echo 'RBU' > $uart_port
echo 'rBU' > $uart_port
sleep 1
stm32flash $uart_port -w test.bin
stty -F $uart_port 50
echo 'Rbu' > $uart_port
sleep 1
echo 'rbuz' > $uart_port
Поскольку в windows с консолью все плохо, лучше этот файл создать на своей машине, а потом скопировать на сервер и поменять ему права:
scp prog.sh karakatitsa:/home/user/prog/test
ssh karakatitsa "chmod +x /home/user/prog/test/prog.sh"
При очередной сборке проекта у нас появляется burn.bat, который надо прописать в настройках проекта Run -> Run configuration -> C/C++ Application. И можно проверять что все работает.
Еще одна вещь, которую стоит проверить - работа с клавиатурой. В ssh-консоли переходим в prog/kbd_driver
и запускаем ./res/prog64
. Должен появиться интерфейс виртуальной клавиатуры. Нажимая на кнопки 1-4, q-r, a-f и z-v можно “нажимать” виртуальные кнопки. Это будет отображаться зеленым свечением соответствующих квадратов, что можно видеть на камере. Еще раз: если рамки клавиш в терминале не видны, включите векторные шрифты в настройках терминала. Исходники этого драйвера хранятся тут же (и здесь, на гитхабе, разумеется), а конфиг-файл COKP_kbd.cfg
, можно поменять хоткеи, подписи кнопок и битовые маски, которые им соответствуют. И, естественно, этот код можно всячески изучать и допиливать.
Большая часть отладки завязана на UART, соответственно надо иметь под рукой хотя бы два терминала: для отладки и для клавиатуры / команд / прочего, Хорошо с этим справляется утилиты tmux
, запускаемая на сервере. При помощи команды tmux split-window -h
она позволяет разделить окно на две части, в по ctrl+B, влево/вправо переключаться между ними. Например, в одной части можно запустить screen /dev/tty_DBG_0 9600
, а в другой тот самый драйвер клавиатуры. Кстати, screen и сам умеет делить окно на части. Чтобы закрыть окно, достаточно ввести exit или просто ctrl+D. Чтобы закрыть screen, надо ctrl+A, k, y. Впрочем, возможности что tmux, что screen этим не ограничиваются, рекомендую изучить их подробнее.
Как в первый раз
Предположим, мы все эти настройки провели, поигрались с контроллером и выключили машину. Как будет выглядеть очередной запуск рабочего окружения с нуля?
-
Запускаем консоль
-
ssh-agent
-
ssh-add C:\risvc\ssh\karakatitsa
-
ssh karakatitsa
-
Открываем браузер с адресом
localhost:8008
чтобы смотреть на платку в прямом эфире -
Запускаем NucleiStudio
-
Пишем код
-
Компилируем (кнопка build / ctrl + B)
-
Запускаем (кнопка Run / ctrl + F11)
-
Повторять до достижения цели
Заключение
Как ни странно, работать со стендом из-под windows все же можно, хотя мне и не понравилось. Слишком медленно все запускается, кривущий терминал, в котором нет даже истории, много места отъедается самой IDE, а ведь надо еще на трансляцию с камеры смотреть, и кнопки в эмуляторе нажимать.
Впрочем, личные предпочтения это личные предпочтения, возможно, для кого-то это удобно. А может быть, пары дней освоения незнакомой системы все же недостаточно для подобных оценок.
Что могло пойти не так
- Утилиты ssh (ssh, scp и др.) невразумительно ругаются в консоль.
Возможно, не выполнена установка (запуск install-sshd.ps1), не запущен ssh-agent или неправильно настроен конфигурационный файл ~\.ssh\config. Мало ли, расширение внезапно образовалось, или просто опечатка.
- Не отображается строка приветствия при подключении по ssh
Как полноценно починить не знаю, но можно попробовать запустить screen. Впрочем, все баги это не исправит. Возможно, получится найти более вменяемый терминал, чем встроенные в винду.
- Не отображаются русские буквы, псевдографика, рамочки в драйвере виртуальной клавиатуры
Возможно, забыли переключить шрифты консоли на векторные