Это будет в некотором роде продолжение статьи IAR RISC-V GD32V Evaluation Board, только теперь с примером проекта на бесплатном ПО, исправлением косяков отладочной платы IAR и просто бомблением на тему, как же так плохо можно было сделать отладочную плату.

Фиксим отладочную плату от IAR
В качестве примера проекта я захотел сделать что-то посерьезнее мигания светодиодом, задействовав сразу АЦП, SPI, GPIO, таймер и немного математики.
В процессе изучения SDK и примеров производителя я столкнулся с тем, что с канала АЦП, на который заведён микрофон, читается постоянно значение «4095» (для 12 бит это аккурат напряжение питания). Странно. Смотрю осциллографом, что на выходе первого ОУ после микрофона (точка 1):

Всё в норме, половина питания (Vref задаётся резисторами R31, R32) и усиленный переменный сигнал с микрофона. Смотрю выход второго ОУ (точка 2) и там… напряжение питания. Гхм. Может быть, я ошибся, настроил пин как выход — перепроверяю всё, в прошивке всё отлично. Смотрю на схему ещё раз, и меня осенило — R52. Вот это реально могёт в схемотехнику тот, кто проектировал эту плату…

Не, ну правда, чётко. Задать усиление ОУ как по переменному, так и по постоянному напряжению и потом подать полное напряжение Vref на положительный вход (и ОУ попытается усилить Vref по постоянному напряжение в Ку раз, войдя в насыщение). С этим связан ещё один прикол, заходим в официальный репозиторий примеров этой отладочной платы:

Видите тут примеры с АЦП? Нет. Правильно, ведь без доработки платы поиграться с микрофоном не получится (хотя есть ещё другие каналы, с подстроечным резистором и датчиком освещения, там проблем нет, вроде). :) Благо с ЦАП особо не накосячили, просто повесили буферный ОУ.
Я даже набросал эту схему в симуляторе (почти аналог по номиналам и типу ОУ):

И всё ожидаемо (не) работает:

Исправляем схему:

И всё работает в симуляции корректно теперь:

Итак, вносим правки в схему отладочной платы теперь, чтобы она работала корректно и микрофон имел хорошую чувствительность:

- Выпаять R52 — это основная проблема;
- Последовательно с C18 необходимо впаять резистор R? номиналом 1 кОм;
- Поменять номиналы резисторов R33, R51 на 100 кОм — эта и предыдущая доработки увеличат усиление и чувствительность микрофона соответственно;
- Поменять номинал C20 на 100 пФ — чуть лучше фильтровать ВЧ будет, но особой роли НЕ сыграет, можно не менять или даже выпаять (а игрался я с этим номиналом и R?, а также параллельно самому микрофону ставил конденсатор по другой причине, о которой ниже).
Примечание: абсолютно аналогичные доработки требуются в схеме, отвечающей за внешний микрофон! Просто я не буду уже приводить аналогичную схему с другими позиционными номерами компонентов.
И это я уже забил на то, что после R60 и других аналогичных резисторов на входах ОУ требуется буферный конденсатор на общий, чтобы минимизировать результаты процессов переключения входов АПЦ, а точнее взаимного влияния их друг на друга и ошибки квантования входного сигнала. Очень хорошая статья на эту тему — Демоны в АЦП STM32.
Проверяю я работу схемы после доработок и замечаю такое дело:
Периодические иголки в сигнале, они зависят от режима работы внешнего SPI дисплея. Не, ну я, конечно, соглашусь, дома у меня осциллограф старый Owon ещё тот, но не настолько… Проверяю опять всю схему аналоговую, может, чего подвозбуждается или ещё что-то, и нахожу, что, как минимум, если взять GND с J4 и посмотреть, что происходит на GND J1, то можно увидеть следующую картину (на самом деле там пачками помехи идут, как раз на обновление ЖКИ, но осциллограф сохраняет сигнал как ему больше нравится):

Окей, аналогичная картина и на пинах питания ОУ, а это значит, что у нас КРИВАЯ разводка питания платы. Стоило ожидать… после перлов, найденных при первом знакомстве с отладочным комплектом. Ну что ж, максимум, что я могу сделать, это:

Да, просто накинул поверх провода от LDO и конденсатора рядом, стало лучше, но полностью наводки не ушли:
Примечание: также закоротил J6, который, по задумке разработчика, давал возможность запитать +3.3 В от USB или от внешнего разъёма J6, а вот +3.3 В при таком раскладе на внешнюю плату было брать неоткуда, что довольно бредово, если хочется подключить внешние модули с питанием +3.3 В, но это не последнее такое решение в отношении внешних разъёмов, есть ещё приколы…
В процессе изучения схемы отладочной платы, помимо того что я постоянно плевался на её «стиль» (сами взгляните в pdf), я для удобства расписал все разъёмы IO (странно, что производитель такого не сделал, файл Board IO.xlsx на гите):

Практически НИ ОДИН GPIO не выведен просто так на разъёмы, он так или иначе подключен к периферии, что установлена на плате, тогда как у МК есть свободные пины, и их просто не задействовали… также зачем-то профукали кучу интерфейсов МК (таких как USB, SPI, I2S, I2C), не подключив или только частично выведя IO этих интерфейсов на внешние разъёмы. Это фиаско. Настолько откровенно ужасно спроектированной платы я давно не видел, да многие noname платы с Али продуманы и разведены лучше, чем эта. И да, это уже 3-я ревизия (!!!), страшно представить, что было в первой:

И после увиденного я уже вообще не удивляюсь подобному (и теперь понимаю, откуда появились перемычки на светодиодах и горка mosfet-ов):

Нормальный человек как считает? 1, 2, 3, 4, 5… а разработчик данной отладки считает более изощрённо.
Ну да ладно, подгорели и теперь готовы к дальнейшему созданию проекта.
Подготовка Visual Studio Code
Всё аналогично, как и в предыдущей статье для ARM МК, поэтому повторяться я не буду. Если вы уже работаете с ARM-ми, то вам и настраивать ничего не потребуется, а если вы впервые работаете с Visual Studio Code, то тогда стоит прочесть первую статью — Visual Studio Code — написание и отладка прошивок для ARM Cortex-M.
Установка тулчейна, драйверов отладчика
Всё аналогично. Кроме момента с тулчейном, для сборки прошивок под архитектуру RISC-V потребуется GCC версия для RISC-V архитектуры — xPack GNU RISC-V Embedded GCC, пути прописываются в Path аналогичным образом. В качестве инструментов для сборки можно использовать как GNU MCU Eclipse Windows Build Tools, так и xPack Windows Build Tools.
Тестовый проект и компиляция
Базовая структура, описывающая проект:

Да, это суперпростой осциллограф\анализатор спектра, переключаемый кнопками. По сути, у нас есть таймер, который пинает АЦП, с которого замеры читаются по DMA в память (массив), а после заполнения массива вызывается обработка накопленных данных (получая на выходе спектр Фурье или просто масштабированный сигнал), после обработки данные пишутся уже в большой массив, отображающий один кадр ЖКИ (с упрощённым форматом R2G3B3, чтобы минимизировать потребление памяти), а после чего, на лету переводя из R2G3B3 в R5G6B5, кадр пишется в ЖКИ по SPI. ЖКИ я использовал на контроллере ST7735S с разрешением 80*160 точек. Вот такой:

Итак, сам проект можно скачать с гитхаба, и открывается он аналогично в Visual Studio Code как Folder:

Основные моменты, когда будете менять его под свои нужды:
- файл .vscode\c_cpp_properties.json — все локальные пути в проекте, дефайны и путь к тулчейну в «RISCV_GCC_TOOLCHAIN«, чтобы среда могла корректно проверять на лету на ошибки, подсвечивать их и работали переходы по коду;
- файл .vscode\launch.json — настройки отладки, тут, в целом, ничего особо нового не появилось, основное отличие от ARM версии — интерфейс подключения JTAG;
- файл .vscode\settings.json — дополнительные настройки отладки, и тут есть одно важное отличие — параметр «cortex-debug.armToolchainPrefix«, благодаря которому расширение Cortex-Debug стартует отладку RISC-V :) ;
- файл .vscode\tasks.json — немного поменялся формат команд, как и сами скрипты для J-Link, но, в целом, ничего примечательного.
Далее файл сборки проекта — Makefile, он очень похож на STM32 версию, добавились только отдельные секции для пользовательских исходников, include папок, поменялись настройки компилятора и линковщика, но всё в целом наглядно и понятно расположено.
Папка Drivers — сюда я положил исходный код SDK (папка Firmware) из файла GD32VF103_Firmware_Library_V1.0.2.rar (уже доступна GD32VF103_Firmware_Library_V1.1.0.rar версия, но я не стал обновлять).
Папка DriversExt — различные драйверы внешней периферии, добавляемые пользователем.
Файлы startup, lds (start.S, entry.S, GD32VF103xB.lds) также взяты из GD32VF103_Firmware_Library_V1.0.2.rar, лежат в папке примера под Eclipse Firmware\Drivers\RISCV\env_Eclipse.
Папка Drivers\NMSIS — сюда я положил порт CMSIS DSP из гитхаба NMSIS (вложения папки NMSIS без документации и примеров).
Файл Inc\window_table.h сгенерирован самописной утилитой на C#, тут хранятся коэффициенты окна для сигнала, который будет обработан быстрым преобразованием Фурье.
На этом, собственно, и всё, основной код можно посмотреть в main.c, хоть и без комментариев, но всё довольно наглядно и адекватно проименовано.
После стиля именования HAL или LL на STM32 функции с именами типа gpio_init или spi_i2s_data_transmit прям дико навевают забытый уже SPL, но потом быстро привыкаешь и уже не обращаешь внимания.
Прошивка и тестирование работы
Основное, с чего стоит начать — это версия J-Link, согласно официальному обзору различий версий Software and Hardware Features Overview, минимальная версия J-Link для работы с RISC-V – v10.1, а лучше v11. Подойдёт даже EDU версия, с демократичным ценником и минимальным функционалом, но не ограниченным числом точек останова в отладке (правда, отладчик Ozone будет работать неполноценно). Единственный косяк для меня заключается в большом размере самого отладчика и неудобном, огромном разъёме IDC-20, поэтому я сваял на скорую руку такой переходник для удобства использования:

В остальном же прошивка ничем не отличается от прошивки STM32, различия только в интерфейсе — JTAG и прописывании адреса флешки в скрипте JLink\FlashMCU.jlink.
Итак, прошиваем скомпилированную прошивку, и можно играться:

Отладка
Всё абсолютно аналогично примеру на ARM, запускаем отладку так же и можем ставить точки останова когда захотим (не как в IAR EB, только в паузе) и смотреть переменные налету:

Примечание: единственное, что неадекватно работает — это автоопределение Global, Local, Static переменных, что и можно наблюдать на гифке выше. Возможно, я накосячил с флагами компилятора… или таки не получилось Cortex-Debug натянуть на RISC-V без проблем. :)
Если же добавить переменные вручную в Watch, то они прекрасно читаются (тут видно, как они меняются, когда я нажимаю на кнопки на плате):

Ну и последнее, добавив SVD файл, можно смотреть регистры МК (аналогично смотрю на PA10, который меняется в зависимости от нажатия на кнопку):

На этом всё. :) Спасибо, что прочитали!
Ссылки
- IAR RISC-V GD32V Evaluation Board — первая часть с обзором отладочного комплекта GD32VF103RBT6 от IAR;
- GD32VF103_VSC_Example — репозиторий проекта;
- Evaluation kit for RISC-V — официальная страница с описанием платы и формой для заказа отладочного комплекта;
- IAR RISC-V GD32V Evaluation kit — Project examples — официальный репозиторий с примерами;
- GD32VF103RBT6 — официальная страница МК с документацией, примерами и SDK;
- GD32VF103 Firmware Library — официальный репозиторий с SDK;
- NMSIS — порт CMSIS DSP;
- Visual Studio Code — написание и отладка прошивок для ARM Cortex-M — аналогичная статья для ARM;
- GNU MCU Eclipse Windows Build Tools — инструменты для сборки, Windows порт;
- xPack Windows Build Tools — инструменты для сборки, Windows порт (релиз от xpack-dev-tools);
- xPack GNU RISC-V Embedded GCC — тулчейн RISC-V;
- J-Link Software and Documentation Pack — драйвера, документация для J-Link.